int dm200encode()

in Sharing/Src/External/zint-2.4.3/src/backend/dmatrix.c [341:757]


int dm200encode(struct zint_symbol *symbol, unsigned char source[], unsigned char target[], int *last_mode, int length)
{
	/* Encodes data using ASCII, C40, Text, X12, EDIFACT or Base 256 modes as appropriate */
	/* Supports encoding FNC1 in supporting systems */

	int sp, tp, i, gs1;
	int current_mode, next_mode;
	int inputlen = length;
	int c40_buffer[6], c40_p;
	int text_buffer[6], text_p;
	int x12_buffer[6], x12_p;
	int edifact_buffer[8], edifact_p;
	int debug = 0;
#ifndef _MSC_VER
        char binary[2 * inputlen];
#else
        char* binary = (char*)_alloca(2 * inputlen);
#endif

	sp = 0;
	tp = 0;
	memset(c40_buffer, 0, 6);
	c40_p = 0;
	memset(text_buffer, 0, 6);
	text_p = 0;
	memset(x12_buffer, 0, 6);
	x12_p = 0;
	memset(edifact_buffer, 0, 8);
	edifact_p = 0;
	strcpy(binary, "");

	/* step (a) */
	current_mode = DM_ASCII;
	next_mode = DM_ASCII;

	if(symbol->input_mode == GS1_MODE) { gs1 = 1; } else { gs1 = 0; }

	if(gs1) {
		target[tp] = 232; tp++;
		concat(binary, " ");
		if(debug) printf("FN1 ");
	} /* FNC1 */

	if(symbol->output_options & READER_INIT) {
		if(gs1) {
			strcpy(symbol->errtxt, "Cannot encode in GS1 mode and Reader Initialisation at the same time");
			return ZINT_ERROR_INVALID_OPTION;
		} else {
			target[tp] = 234; tp++; /* Reader Programming */
			concat(binary, " ");
			if(debug) printf("RP ");
		}
	}

	while (sp < inputlen) {

		current_mode = next_mode;

		/* step (b) - ASCII encodation */
		if(current_mode == DM_ASCII) {
			next_mode = DM_ASCII;

			if(istwodigits(source, sp) && ((sp + 1) != inputlen)) {
				target[tp] = (10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130;
				if(debug) printf("N%d ", target[tp] - 130);
				tp++; concat(binary, " ");
				sp += 2;
			} else {
				next_mode = look_ahead_test(source, inputlen, sp, current_mode, gs1);

				if(next_mode != DM_ASCII) {
					switch(next_mode) {
						case DM_C40: target[tp] = 230; tp++; concat(binary, " ");
							if(debug) printf("C40 "); break;
						case DM_TEXT: target[tp] = 239; tp++; concat(binary, " ");
							if(debug) printf("TEX "); break;
						case DM_X12: target[tp] = 238; tp++; concat(binary, " ");
							if(debug) printf("X12 "); break;
						case DM_EDIFACT: target[tp] = 240; tp++; concat(binary, " ");
							if(debug) printf("EDI "); break;
						case DM_BASE256: target[tp] = 231; tp++; concat(binary, " ");
							if(debug) printf("BAS "); break;
					}
				} else {
					if(source[sp] > 127) {
						target[tp] = 235; /* FNC4 */
						if(debug) printf("FN4 ");
						tp++;
						target[tp] = (source[sp] - 128) + 1;
						if(debug) printf("A%02X ", target[tp] - 1);
						tp++; concat(binary, "  ");
					} else {
						if(gs1 && (source[sp] == '[')) {
							target[tp] = 232; /* FNC1 */
							if(debug) printf("FN1 ");
						} else {
							target[tp] = source[sp] + 1;
							if(debug) printf("A%02X ", target[tp] - 1);
						}
						tp++; 
						concat(binary, " ");
					}
					sp++;
				}
			}

		}

		/* step (c) C40 encodation */
		if(current_mode == DM_C40) {
			int shift_set, value;

			next_mode = DM_C40;
			if(c40_p == 0) {
				next_mode = look_ahead_test(source, inputlen, sp, current_mode, gs1);
			}

			if(next_mode != DM_C40) {
				target[tp] = 254; tp++; concat(binary, " ");/* Unlatch */
				next_mode = DM_ASCII;
				if (debug) printf("ASC ");
			} else {
				if(source[sp] > 127) {
					c40_buffer[c40_p] = 1; c40_p++;
					c40_buffer[c40_p] = 30; c40_p++; /* Upper Shift */
					shift_set = c40_shift[source[sp] - 128];
					value = c40_value[source[sp] - 128];
				} else {
					shift_set = c40_shift[source[sp]];
					value = c40_value[source[sp]];
				}

				if(gs1 && (source[sp] == '[')) {
					shift_set = 2;
					value = 27; /* FNC1 */
				}

				if(shift_set != 0) {
					c40_buffer[c40_p] = shift_set - 1; c40_p++;
				}
				c40_buffer[c40_p] = value; c40_p++;

				if(c40_p >= 3) {
					int iv;

					iv = (1600 * c40_buffer[0]) + (40 * c40_buffer[1]) + (c40_buffer[2]) + 1;
					target[tp] = iv / 256; tp++;
					target[tp] = iv % 256; tp++;
					concat(binary, "  ");
					if (debug) printf("[%d %d %d] ", c40_buffer[0], c40_buffer[1], c40_buffer[2]);

					c40_buffer[0] = c40_buffer[3];
					c40_buffer[1] = c40_buffer[4];
					c40_buffer[2] = c40_buffer[5];
					c40_buffer[3] = 0;
					c40_buffer[4] = 0;
					c40_buffer[5] = 0;
					c40_p -= 3;
				}
				sp++;
			}
		}

		/* step (d) Text encodation */
		if(current_mode == DM_TEXT) {
			int shift_set, value;

			next_mode = DM_TEXT;
			if(text_p == 0) {
				next_mode = look_ahead_test(source, inputlen, sp, current_mode, gs1);
			}

			if(next_mode != DM_TEXT) {
				target[tp] = 254; tp++; concat(binary, " ");/* Unlatch */
				next_mode = DM_ASCII;
				if (debug) printf("ASC ");
			} else {
				if(source[sp] > 127) {
					text_buffer[text_p] = 1; text_p++;
					text_buffer[text_p] = 30; text_p++; /* Upper Shift */
					shift_set = text_shift[source[sp] - 128];
					value = text_value[source[sp] - 128];
				} else {
					shift_set = text_shift[source[sp]];
					value = text_value[source[sp]];
				}

				if(gs1 && (source[sp] == '[')) {
					shift_set = 2;
					value = 27; /* FNC1 */
				}

				if(shift_set != 0) {
					text_buffer[text_p] = shift_set - 1; text_p++;
				}
				text_buffer[text_p] = value; text_p++;

				if(text_p >= 3) {
					int iv;

					iv = (1600 * text_buffer[0]) + (40 * text_buffer[1]) + (text_buffer[2]) + 1;
					target[tp] = iv / 256; tp++;
					target[tp] = iv % 256; tp++;
					concat(binary, "  ");
					if (debug) printf("[%d %d %d] ", text_buffer[0], text_buffer[1], text_buffer[2]);

					text_buffer[0] = text_buffer[3];
					text_buffer[1] = text_buffer[4];
					text_buffer[2] = text_buffer[5];
					text_buffer[3] = 0;
					text_buffer[4] = 0;
					text_buffer[5] = 0;
					text_p -= 3;
				}
				sp++;
			}
		}

		/* step (e) X12 encodation */
		if(current_mode == DM_X12) {
			int value = 0;

			next_mode = DM_X12;
			if(text_p == 0) {
				next_mode = look_ahead_test(source, inputlen, sp, current_mode, gs1);
			}

			if(next_mode != DM_X12) {
				target[tp] = 254; tp++; concat(binary, " ");/* Unlatch */
				next_mode = DM_ASCII;
				if (debug) printf("ASC ");
			} else {
				if(source[sp] == 13) { value = 0; }
				if(source[sp] == '*') { value = 1; }
				if(source[sp] == '>') { value = 2; }
				if(source[sp] == ' ') { value = 3; }
				if((source[sp] >= '0') && (source[sp] <= '9')) { value = (source[sp] - '0') + 4; }
				if((source[sp] >= 'A') && (source[sp] <= 'Z')) { value = (source[sp] - 'A') + 14; }

				x12_buffer[x12_p] = value; x12_p++;

				if(x12_p >= 3) {
					int iv;

					iv = (1600 * x12_buffer[0]) + (40 * x12_buffer[1]) + (x12_buffer[2]) + 1;
					target[tp] = iv / 256; tp++;
					target[tp] = iv % 256; tp++;
					concat(binary, "  ");
					if (debug) printf("[%d %d %d] ", x12_buffer[0], x12_buffer[1], x12_buffer[2]);

					x12_buffer[0] = x12_buffer[3];
					x12_buffer[1] = x12_buffer[4];
					x12_buffer[2] = x12_buffer[5];
					x12_buffer[3] = 0;
					x12_buffer[4] = 0;
					x12_buffer[5] = 0;
					x12_p -= 3;
				}
				sp++;
			}
		}

		/* step (f) EDIFACT encodation */
		if(current_mode == DM_EDIFACT) {
			int value = 0;

			next_mode = DM_EDIFACT;
			if(edifact_p == 3) {
				next_mode = look_ahead_test(source, inputlen, sp, current_mode, gs1);
			}

			if(next_mode != DM_EDIFACT) {
				edifact_buffer[edifact_p] = 31; edifact_p++;
				next_mode = DM_ASCII;
			} else {
				if((source[sp] >= '@') && (source[sp] <= '^')) { value = source[sp] - '@'; }
				if((source[sp] >= ' ') && (source[sp] <= '?')) { value = source[sp]; }

				edifact_buffer[edifact_p] = value; edifact_p++;
				sp++;
			}

			if(edifact_p >= 4) {
				target[tp] = (edifact_buffer[0] << 2) + ((edifact_buffer[1] & 0x30) >> 4); tp++;
				target[tp] = ((edifact_buffer[1] & 0x0f) << 4) + ((edifact_buffer[2] & 0x3c) >> 2); tp++;
				target[tp] = ((edifact_buffer[2] & 0x03) << 6) + edifact_buffer[3]; tp++;
				concat(binary, "   ");
				if (debug) printf("[%d %d %d %d] ", edifact_buffer[0], edifact_buffer[1], edifact_buffer[2], edifact_buffer[3]);

				edifact_buffer[0] = edifact_buffer[4];
				edifact_buffer[1] = edifact_buffer[5];
				edifact_buffer[2] = edifact_buffer[6];
				edifact_buffer[3] = edifact_buffer[7];
				edifact_buffer[4] = 0;
				edifact_buffer[5] = 0;
				edifact_buffer[6] = 0;
				edifact_buffer[7] = 0;
				edifact_p -= 4;
			}
		}

		/* step (g) Base 256 encodation */
		if(current_mode == DM_BASE256) {
			next_mode = look_ahead_test(source, inputlen, sp, current_mode, gs1);

			if(next_mode == DM_BASE256) {
				target[tp] = source[sp];
				if(debug) printf("B%02X ", target[tp]);
				tp++;
				sp++;
				concat(binary, "b");
			} else {
				next_mode = DM_ASCII;
				if(debug) printf("ASC ");
			}
		}

		if(tp > 1558) {
			return 0;
		}

	} /* while */

	/* Empty buffers */
	if(c40_p == 2) {
		target[tp] = 254; tp++; /* unlatch */
		target[tp] = source[inputlen - 2] + 1; tp++;
		target[tp] = source[inputlen - 1] + 1; tp++;
		concat(binary, "   ");
		if(debug) printf("ASC A%02X A%02X ", target[tp - 2] - 1, target[tp - 1] - 1);
		current_mode = DM_ASCII;
	}
	if(c40_p == 1) {
		// don't unlatch before sending a single remaining ASCII character.
		target[tp] = source[inputlen - 1] + 1; tp++;
		concat(binary, "  ");
		if(debug) printf("ASC A%02X ", target[tp - 1] - 1);
		current_mode = DM_ASCII;
	}

	if(text_p == 2) {
		target[tp] = 254; tp++; /* unlatch */
		target[tp] = source[inputlen - 2] + 1; tp++;
		target[tp] = source[inputlen - 1] + 1; tp++;
		concat(binary, "   ");
		if(debug) printf("ASC A%02X A%02X ", target[tp - 2] - 1, target[tp - 1] - 1);
		current_mode = DM_ASCII;
	}
	if(text_p == 1) {
		target[tp] = 254; tp++; /* text encodation requires unlatch */
		target[tp] = source[inputlen - 1] + 1; tp++;
		concat(binary, "  ");
		if(debug) printf("ASC A%02X ", target[tp - 1] - 1);
		current_mode = DM_ASCII;
	}

	if(x12_p == 2) {
		target[tp] = 254; tp++; /* unlatch */
		target[tp] = source[inputlen - 2] + 1; tp++;
		target[tp] = source[inputlen - 1] + 1; tp++;
		concat(binary, "   ");
		if(debug) printf("ASC A%02X A%02X ", target[tp - 2] - 1, target[tp - 1] - 1);
		current_mode = DM_ASCII;
	}
	if(x12_p == 1) {
		// don't unlatch before sending a single remaining ASCII character.
		target[tp] = source[inputlen - 1] + 1; tp++;
		concat(binary, "  ");
		if(debug) printf("ASC A%02X ", target[tp - 1] - 1);
		current_mode = DM_ASCII;
	}

	/* Add length and randomising algorithm to b256 */
	i = 0;
	while (i < tp) {
		if(binary[i] == 'b') {
			if((i == 0) || ((i != 0) && (binary[i - 1] != 'b'))) {
				/* start of binary data */
				int binary_count; /* length of b256 data */

				for(binary_count = 0; binary[binary_count + i] == 'b'; binary_count++);

				if(binary_count <= 249) {
					dminsert(binary, i, 'b');
					insert_value(target, i, tp, binary_count); tp++;
				} else {
					dminsert(binary, i, 'b');
					dminsert(binary, i + 1, 'b');
					insert_value(target, i, tp, (binary_count / 250) + 249); tp++;
					insert_value(target, i + 1, tp, binary_count % 250); tp++;
				}
			}
		}
		i++;
	}

	for(i = 0; i < tp; i++) {
		if(binary[i] == 'b') {
			int prn, temp;

			prn = ((149 * (i + 1)) % 255) + 1;
			temp = target[i] + prn;
			if (temp <= 255) { target[i] = temp; } else { target[i] = temp - 256; }
		}
	}

	if(debug) {
		printf("\n\n");
		for(i = 0; i < tp; i++){
			printf("%02X ", target[i]);
		}
		printf("\n");
	}

	*(last_mode) = current_mode;
	return tp;
}