#include "atascii.h" const char *atascii_inverse_on = "\x1b[7m"; const char *atascii_inverse_off = "\x1b[27m"; /* only called in magazine mode. cursor control characters like a bell in the middle of a non-inverse string should not cause it to print {inv}{bell}{norm}. The {bell} is "inherently" inverse (since its high bit is set) but doesn't need to be printed that way. */ static int affects_inv(int c) { switch(c) { case 0x1b: /* esc */ case 0x1c: /* up */ case 0x1d: /* down */ case 0x1e: /* left */ case 0x1f: /* right */ case 0x9b: /* EOL */ case 0x9c: /* del line */ case 0x9d: /* ins line */ case 0x9e: /* clear tab */ case 0x9f: /* set tab */ case 0x7d: /* cls */ case 0x7e: /* BS */ case 0x7f: /* tab */ case 0xfd: /* bell */ case 0xfe: /* del chr */ case 0xff: /* ins chr */ return 0; default: return 1; } } int atascii_context_init(atascii_ctx *ctx, int mode, int flags) { memset(ctx, 0, sizeof(atascii_ctx)); switch(mode) { case ATA_MODE_UTF8: if(flags & ATA_FLAG_ICS) ctx->table = ics2utf; else ctx->table = ata2utf; break; case ATA_MODE_MAGAZINE: ctx->flags &= ~ATA_FLAG_UNDERLINE; ctx->table = ata2mag; break; default: return 0; } ctx->mode = mode; ctx->flags = flags; return 1; } char *atascii_a2utf(atascii_ctx *ctx, int src, char *dest) { dest[0] = 0; if(src == ATA_CHR_FINISH) { if(ctx->inv) strcpy(dest, atascii_inverse_off); return dest; } if(src == 0x9b) { strcpy(dest, "\n"); ctx->lines++; return dest; } if(ctx->flags & ATA_FLAG_TEXTMODE) { switch(src) { case 0x7f: /* tab */ strcpy(dest, "\t"); return dest; case 0xfd: /* bell */ strcpy(dest, "\a"); return dest; case 0x7e: /* backspace */ strcpy(dest, "\b"); return dest; default: break; } } if(ctx->flags & ATA_FLAG_STRIP_INVERSE) src &= 0x7f; if(!(ctx->flags & ATA_FLAG_UNDERLINE)) { /* strings of inverse chars only get one "inverse on" ANSI sequence, and one "inverse off" afterwards. */ if(src & 0x80) { if(!ctx->inv) { if(ctx->mode == ATA_MODE_MAGAZINE) { if(affects_inv(src)) { strcpy(dest, "{inv}"); ctx->inv = 1; } } else { strcpy(dest, atascii_inverse_on); ctx->inv = 1; } } } else { if(ctx->inv) { if(ctx->mode == ATA_MODE_MAGAZINE) { if(affects_inv(src)) { strcpy(dest, "{norm}"); ctx->inv = 0; } } else { strcpy(dest, atascii_inverse_off); ctx->inv = 0; } } } } if(ctx->mode == ATA_MODE_MAGAZINE) { /* special cases: control codes with bit 7 set can't go in the table since it's only got 128 entries. */ switch(src) { case 0x9c: strcat(dest, "{del-line}"); return dest; case 0x9d: strcat(dest, "{ins-line}"); return dest; case 0x9e: strcat(dest, "{clr-tab}"); return dest; case 0x9f: strcat(dest, "{set-tab}"); return dest; case 0xfd: strcat(dest, "{bell}"); return dest; case 0xfe: strcat(dest, "{del-char}"); return dest; case 0xff: strcat(dest, "{ins-char}"); return dest; default: break; } } strcat(dest, ctx->table[src & 0x7f]); if((ctx->flags & ATA_FLAG_UNDERLINE) && (src & 0x80)) { strcat(dest, "\b_"); } return dest; }