|
|
@ -39,9 +39,126 @@ static void doSegmentDemo(void);
|
|
|
|
static void doMaskDemo(void);
|
|
|
|
static void doMaskDemo(void);
|
|
|
|
static void printQr(const uint8_t qrcode[]);
|
|
|
|
static void printQr(const uint8_t qrcode[]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int border = 4;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct output_formatting {
|
|
|
|
|
|
|
|
char const *begin_code;
|
|
|
|
|
|
|
|
char const *begin_line;
|
|
|
|
|
|
|
|
char const *light;
|
|
|
|
|
|
|
|
char const *dark;
|
|
|
|
|
|
|
|
char const *same;
|
|
|
|
|
|
|
|
char const *end_line;
|
|
|
|
|
|
|
|
char const *end_code;
|
|
|
|
|
|
|
|
bool braille_map;
|
|
|
|
|
|
|
|
uint32_t *charMap;
|
|
|
|
|
|
|
|
int num_across;
|
|
|
|
|
|
|
|
int num_down;
|
|
|
|
|
|
|
|
} OFM;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
|
|
|
|
blackOnWhite,
|
|
|
|
|
|
|
|
whiteOnBlack,
|
|
|
|
|
|
|
|
ansiColour,
|
|
|
|
|
|
|
|
unicodeHalfBlock,
|
|
|
|
|
|
|
|
unicodeBraille,
|
|
|
|
|
|
|
|
} TermMode;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static TermMode outputMode = blackOnWhite;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static OFM ofmt[] = {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[blackOnWhite] = (OFM){
|
|
|
|
|
|
|
|
/* this assumes dark text on light background */
|
|
|
|
|
|
|
|
.light = " ",
|
|
|
|
|
|
|
|
.dark = "##",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[whiteOnBlack] = (OFM){
|
|
|
|
|
|
|
|
/* this assumes light text on dark background */
|
|
|
|
|
|
|
|
.light = "##",
|
|
|
|
|
|
|
|
.dark = " ",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[ansiColour] = (OFM){
|
|
|
|
|
|
|
|
.begin_line = "",
|
|
|
|
|
|
|
|
.light = "\033[47m ",
|
|
|
|
|
|
|
|
.dark = "\033[40m ",
|
|
|
|
|
|
|
|
.same = " ",
|
|
|
|
|
|
|
|
.end_line = "\033[m\n",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[unicodeHalfBlock] = (OFM){
|
|
|
|
|
|
|
|
.begin_line = "\033[30;47m",
|
|
|
|
|
|
|
|
.end_line = "\033[39;49m\n",
|
|
|
|
|
|
|
|
.num_across = 1,
|
|
|
|
|
|
|
|
.num_down = 2,
|
|
|
|
|
|
|
|
.charMap = (uint32_t[4]){
|
|
|
|
|
|
|
|
' ', /* clear bottom & top */
|
|
|
|
|
|
|
|
0x2580, /* ▀ clear bottom, marked top */
|
|
|
|
|
|
|
|
0x2584, /* ▄ marked bottom, clear top */
|
|
|
|
|
|
|
|
0x2588, /* █ marked bottom & top */
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[unicodeBraille] = (OFM){
|
|
|
|
|
|
|
|
.begin_line = "\033[30;47m",
|
|
|
|
|
|
|
|
.end_line = "\033[39;49m\n",
|
|
|
|
|
|
|
|
.braille_map = true,
|
|
|
|
|
|
|
|
.num_across = 2,
|
|
|
|
|
|
|
|
.num_down = 4,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// The main application program.
|
|
|
|
// The main application program.
|
|
|
|
int main(void) {
|
|
|
|
int main(int argc/*unused*/, char const*const*argv) {
|
|
|
|
|
|
|
|
char const*argv0 = *argv++;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
|
|
|
|
char const*arg = *argv++;
|
|
|
|
|
|
|
|
if (!arg || *arg++ != '-') break; /* "-" as a non-option arg */
|
|
|
|
|
|
|
|
char opt = *arg++;
|
|
|
|
|
|
|
|
if (!opt) { --argv; break; }
|
|
|
|
|
|
|
|
if (opt == '-') {
|
|
|
|
|
|
|
|
if (!*arg) break; /* "--" marks end of options */
|
|
|
|
|
|
|
|
if (!strcmp(arg, "border" )) opt = 'b';
|
|
|
|
|
|
|
|
else if (!strcmp(arg, "plain" )) opt = 'p';
|
|
|
|
|
|
|
|
else if (!strcmp(arg, "plain=bow")) opt = 'p';
|
|
|
|
|
|
|
|
else if (!strcmp(arg, "plain=wob")) opt = 'P';
|
|
|
|
|
|
|
|
else if (!strcmp(arg, "unicode=braille")) opt = 'Q';
|
|
|
|
|
|
|
|
else if (!strcmp(arg, "unicode=halfblock")) opt = 'R';
|
|
|
|
|
|
|
|
else if (!strcmp(arg, "ansi" )) opt = 'S';
|
|
|
|
|
|
|
|
else goto bad_opt;
|
|
|
|
|
|
|
|
arg = NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (opt) {
|
|
|
|
|
|
|
|
case 'P': outputMode = blackOnWhite; break;
|
|
|
|
|
|
|
|
case 'Q': outputMode = unicodeBraille; break;
|
|
|
|
|
|
|
|
case 'R': outputMode = unicodeHalfBlock; break;
|
|
|
|
|
|
|
|
case 'S': outputMode = ansiColour; break;
|
|
|
|
|
|
|
|
case 'p': outputMode = whiteOnBlack; break;
|
|
|
|
|
|
|
|
case 'b': arg = arg && *arg ? arg : *argv++;
|
|
|
|
|
|
|
|
if (!arg) goto missing_value;
|
|
|
|
|
|
|
|
border = strtol(arg, (char**)&arg, 10);
|
|
|
|
|
|
|
|
if (*arg) goto bad_value;
|
|
|
|
|
|
|
|
arg = NULL;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: goto bad_opt;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (arg && *arg) {
|
|
|
|
|
|
|
|
fprintf(stderr, "Bundled options not supported at '%s'\n", arg);
|
|
|
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
bad_opt:
|
|
|
|
|
|
|
|
fprintf(stderr, "Invalid option '%s'\n", argv[-1]);
|
|
|
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
|
|
|
missing_value:
|
|
|
|
|
|
|
|
fprintf(stderr, "Missing value for option '%s'\n", argv[-1]);
|
|
|
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
|
|
|
bad_value:
|
|
|
|
|
|
|
|
fprintf(stderr, "Improper numeric value '%s'\n", argv[-1]);
|
|
|
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
|
|
|
}
|
|
|
|
doBasicDemo();
|
|
|
|
doBasicDemo();
|
|
|
|
doVarietyDemo();
|
|
|
|
doVarietyDemo();
|
|
|
|
doSegmentDemo();
|
|
|
|
doSegmentDemo();
|
|
|
@ -321,15 +438,79 @@ static void doMaskDemo(void) {
|
|
|
|
|
|
|
|
|
|
|
|
/*---- Utilities ----*/
|
|
|
|
/*---- Utilities ----*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static inline void wputchar(uint32_t ch) {
|
|
|
|
|
|
|
|
if (ch < 0x80)
|
|
|
|
|
|
|
|
putchar(ch);
|
|
|
|
|
|
|
|
else if (ch < 0x800)
|
|
|
|
|
|
|
|
putchar(0xc0 | ch >> 6 & 0x1f),
|
|
|
|
|
|
|
|
putchar(0x80 | ch & 0x3f);
|
|
|
|
|
|
|
|
else if (ch < 0x10000)
|
|
|
|
|
|
|
|
putchar(0xe0 | ch >> 12 & 0x0f),
|
|
|
|
|
|
|
|
putchar(0x80 | ch >> 6 & 0x3f),
|
|
|
|
|
|
|
|
putchar(0x80 | ch & 0x3f);
|
|
|
|
|
|
|
|
else if (ch < 0x200000)
|
|
|
|
|
|
|
|
putchar(0xf0 | ch >> 18 & 0x07),
|
|
|
|
|
|
|
|
putchar(0x80 | ch >> 12 & 0x3f),
|
|
|
|
|
|
|
|
putchar(0x80 | ch >> 6 & 0x3f),
|
|
|
|
|
|
|
|
putchar(0x80 | ch & 0x3f);
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
putchar('?');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Prints the given QR Code to the console.
|
|
|
|
// Prints the given QR Code to the console.
|
|
|
|
static void printQr(const uint8_t qrcode[]) {
|
|
|
|
static void printQr(const uint8_t qrcode[]) {
|
|
|
|
int size = qrcodegen_getSize(qrcode);
|
|
|
|
int size = qrcodegen_getSize(qrcode);
|
|
|
|
int border = 4;
|
|
|
|
struct output_formatting *of = &ofmt[outputMode];
|
|
|
|
|
|
|
|
if (of->begin_code)
|
|
|
|
|
|
|
|
fputs(of->begin_code, stdout);
|
|
|
|
|
|
|
|
int const num_across = of->num_across;
|
|
|
|
|
|
|
|
int const num_down = of->num_down;
|
|
|
|
|
|
|
|
if (num_across && num_down)
|
|
|
|
|
|
|
|
for (int y = -border; y < size + border; y += num_down) {
|
|
|
|
|
|
|
|
if (of->begin_line)
|
|
|
|
|
|
|
|
fputs(of->begin_line, stdout);
|
|
|
|
|
|
|
|
for (int x = -border; x < size + border; x += num_across) {
|
|
|
|
|
|
|
|
uint32_t cellBits = 0;
|
|
|
|
|
|
|
|
for (int dx = num_across; dx-- > 0;) {
|
|
|
|
|
|
|
|
for (int dy = num_down; dy-- > 0;) {
|
|
|
|
|
|
|
|
cellBits <<= 1;
|
|
|
|
|
|
|
|
bool bit = qrcodegen_getModule(qrcode, x+dx, y+dy);
|
|
|
|
|
|
|
|
cellBits |= bit;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
wchar_t cellChar = '?';
|
|
|
|
|
|
|
|
if (of->braille_map) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* cellChar Braille
|
|
|
|
|
|
|
|
* 0 4 ⇒ must be ⇒ 0 3
|
|
|
|
|
|
|
|
* 1 5 ⇒ rearranged to ⇒ 1 4
|
|
|
|
|
|
|
|
* 2 6 ⇒ this order ⇒ 2 5
|
|
|
|
|
|
|
|
* 3 7 ⇒ ⇒ 6 7
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
cellChar = cellBits & 0x87
|
|
|
|
|
|
|
|
| cellBits << 3 & 0x40
|
|
|
|
|
|
|
|
| cellBits >> 1 & 0x38
|
|
|
|
|
|
|
|
| 0x2800; /* start of Braille range in Unicode */
|
|
|
|
|
|
|
|
} else if (of->charMap)
|
|
|
|
|
|
|
|
cellChar = of->charMap[cellBits];
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
cellChar = cellBits;
|
|
|
|
|
|
|
|
wputchar(cellChar);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
fputs(of->end_line ?: "\n", stdout);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
for (int y = -border; y < size + border; y++) {
|
|
|
|
for (int y = -border; y < size + border; y++) {
|
|
|
|
|
|
|
|
int prevBit = -1; /* neither true nor false */
|
|
|
|
|
|
|
|
if (of->begin_line)
|
|
|
|
|
|
|
|
fputs(of->begin_line, stdout);
|
|
|
|
for (int x = -border; x < size + border; x++) {
|
|
|
|
for (int x = -border; x < size + border; x++) {
|
|
|
|
fputs((qrcodegen_getModule(qrcode, x, y) ? "##" : " "), stdout);
|
|
|
|
bool thisBit = qrcodegen_getModule(qrcode, x, y);
|
|
|
|
|
|
|
|
fputs( ! of->same || prevBit != thisBit ? thisBit ? of->dark : of->light : of->same,
|
|
|
|
|
|
|
|
stdout );
|
|
|
|
|
|
|
|
prevBit = thisBit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fputs("\n", stdout);
|
|
|
|
fputs(of->end_line ?: "\n", stdout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fputs("\n", stdout);
|
|
|
|
fputs(of->end_code ?: "\n", stdout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|