diff options
author | B. Watson <urchlay@slackware.uk> | 2024-06-29 04:49:12 -0400 |
---|---|---|
committer | B. Watson <urchlay@slackware.uk> | 2024-06-29 04:49:12 -0400 |
commit | 017a503f34a0f8ce2245f1b5dd78894f65326a90 (patch) | |
tree | 62ac02471db0a6e9b97b619b7b63f05110fad61b /a8cat.c | |
parent | d1563c6d7db5e2c8484b80b870e7fb753400f6db (diff) | |
download | bw-atari8-tools-017a503f34a0f8ce2245f1b5dd78894f65326a90.tar.gz |
a8cat: added (will eventually replace both a8utf8 and a8eol).
Diffstat (limited to 'a8cat.c')
-rw-r--r-- | a8cat.c | 187 |
1 files changed, 187 insertions, 0 deletions
@@ -0,0 +1,187 @@ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <locale.h> +#include <wchar.h> +#include <errno.h> + +#include "atables.h" +#include "wtable.h" + +const char **table = ata2utf; + +const char *inverse_on = "\x1b[7m"; +const char *inverse_off = "\x1b[0m"; + +int underline = 0, reverse = 0, textmode = 0, ics = 0; + +void print_help(void) { + printf("Usage: a8cat [-i] [-u] [file ...]\n"); +} + +FILE *open_input(const char *file) { + FILE *input; + + if(file[0] == '-' && file[1] == 0) { + if(freopen(NULL, "rb", stdin)) { + input = stdin; + } else { + perror("(standard input)"); + return NULL; + } + } else if(!(input = fopen(file, "rb"))) { + perror(file); + return NULL; + } + + return input; +} + +int handle_escape_seq(int inv, FILE *input) { + int count, c; + char buf[5] = { 0x1b, 0, 0, 0, 0 }; + + for(count = 1; count < 4; count++) { + c = fgetwc(input); + if(c == WEOF) break; + buf[count] = c; /* FIXME: might be a wide char! */ + } + + if(strcmp(inverse_on, buf) == 0) { + return 0x80; + } else if(strcmp(inverse_off, buf) == 0) { + return 0; + } else { + fputs(buf, stdout); + return inv; + } +} + +int a8revcat(const char *file) { + FILE *input; + int c, d, inv = 0; + + if( !(input = open_input(file)) ) + return 1; + + setlocale(LC_CTYPE, "en_US.UTF-8"); + while( (c = fgetwc(input)) != WEOF ) { + if(c == 0x1b) { + inv = handle_escape_seq(inv, input); + } else if(c == '\n') { + putchar(0x9b); + } else if(c < 0x80) { + putchar(c | inv); + } else { + d = wchar2atascii(c, ics); + if(d == -1) { + fprintf(stderr, "warning: unrecognized Unicode character %04x\n", c); + } else { + putchar(d | inv); + } + } + } + + return 0; +} + +/* XXX: hard-coded ANSI/vt100 escape sequences. would be + better but more complex to use terminfo to support any ol' + terminal... */ +void inverse(int onoff) { + fputs((onoff ? inverse_on : inverse_off ), stdout); +} + +int a8cat(const char *file) { + FILE *input; + int c, inv = 0; + + if( !(input = open_input(file)) ) + return 1; + + while( (c = fgetc(input)) != EOF ) { + if(c == 0x9b) { + putchar('\n'); + continue; + } + + if(textmode) { + switch(c) { + case 0x09: /* Atari TAB is same as ASCII */ + putchar('\t'); + continue; + case 0xfd: /* bell */ + putchar('\a'); + continue; + case 0x7e: /* backspace */ + putchar('\b'); + continue; + default: break; + } + } + + if(!underline) { + /* strings of inverse chars only get one "inverse on" ANSI + sequence, and one "inverse off" afterwards. */ + if(c & 0x80) { + if(!inv) { + inv = 1; + inverse(1); + } + } else { + if(inv) { + inv = 0; + inverse(0); + } + } + } + + fputs(table[c & 0x7f], stdout); + + if(underline && (c & 0x80)) { + putchar('\b'); + putchar('_'); + } + } + + /* gotta turn off inverse, so if there's another file after this one, + it doesn't start out being printed in inverse. */ + if(inv && !underline) inverse(0); + + fclose(input); + return 0; +} + +int main(int argc, char **argv) { + int opt, result = 0; + + while( (opt = getopt(argc, argv, "ihurt")) != -1) { + switch(opt) { + case 'i': table = ics2utf; ics = 1; break; + case 'h': print_help(); exit(0); break; + case 'u': underline = 1; break; + case 'r': reverse = 1; break; + case 't': textmode = 1; break; + default: print_help(); exit(1); break; + } + } + + if(reverse) { + if(underline || textmode) { + fprintf(stderr, "-t and -u options don't make sense with -r.\n"); + exit(1); + } + } + + if(optind >= argc) { + result = (reverse ? a8revcat("-") : a8cat("-")); + } else { + while(optind < argc) { + result += (reverse ? a8revcat(argv[optind]) : a8cat(argv[optind])); + optind++; + } + } + + exit(result); +} |