/* * Copyright (C) 1996 Ben Fowler * Copyright (C) 2003 Pekka Enberg * * Contents of this file originated from Linux sources sometime late * 1995. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * */ #include "ansi-esc.h" /* * Global variables used by the ANSI escape code translator. The list * is long; please feel free to send patches to Walt ;-). */ static int fore; static int back; static int need_wrap; static int def_color; static int par[8]; static int intensity; static int underline; static int blink; static int reverse; static int saved_x; static int saved_y; static int s_intensity; static int s_underline; static int s_blink; static int s_reverse; static int s_color; static int npar; static int y; static int x; static int color; static int pos; static int vc_state; static int ques; static int attr; static int tab_stop[5]; void default_attr () { intensity = 1; underline = 0; reverse = 0; blink = 0; color = 7; fore = 7; back = 0; } void update_attr () { attr = color; if (blink) attr ^= 0x80; if (intensity == 2) attr ^= 0x08; } void csi_m () { int i; for (i = 0; i <= npar; i++) switch (par[i]) { case 0: /* all attributes off */ default_attr (); break; case 1: intensity = 2; break; case 2: intensity = 0; break; case 4: underline = 1; break; case 5: blink = 1; break; case 7: reverse = 1; break; case 10: /* ANSI X3.64-1979 (SCO-ish?) * Select primary font, don't display * control chars if defined, don't set * bit 8 on output. */ break; case 11: /* ANSI X3.64-1979 (SCO-ish?) * Select first alternate font, let's * chars < 32 be displayed as ROM chars. */ break; case 12: /* ANSI X3.64-1979 (SCO-ish?) * Select second alternate font, toggle * high bit before displaying as ROM char. */ break; case 21: case 22: intensity = 1; break; case 24: underline = 0; break; case 25: blink = 0; break; case 27: reverse = 0; break; case 38: /* ANSI X3.64-1979 (SCO-ish?) * Enables underscore, white foreground * with white underscore (Linux - use * default foreground). */ color = (def_color & 0x0f) | back; underline = 1; break; case 39: /* ANSI X3.64-1979 (SCO-ish?) * Disable underline option. * Reset colour to default? It did this * before... */ color = (def_color & 0x0f) | back; underline = 0; break; case 49: color = (def_color & 0xf0) | fore; break; default: if (par[i] >= 30 && par[i] <= 37) { fore = (par[i] - 30) & 0x07; color = (back << 4) | fore; } else if (par[i] >= 40 && par[i] <= 47) { back = (par[i] - 40) & 0x07; color = (back << 4) | fore; } break; } update_attr (); } void gotoxy (int new_x, int new_y, unsigned long width, unsigned long height) { if (new_x < 0) x = 0; else if (new_x >= width) x = width - 1; else x = new_x; if (new_y < 0) y = 0; else if (new_y >= height) y = height - 1; else y = new_y; pos = (y * width) + x; need_wrap = 0; } void save_cur () { saved_x = x; saved_y = y; s_intensity = intensity; s_underline = underline; s_blink = blink; s_reverse = reverse; s_color = color; } void restore_cur (unsigned long width, unsigned long height) { gotoxy (saved_x, saved_y, width, height); intensity = s_intensity; underline = s_underline; blink = s_blink; reverse = s_reverse; color = s_color; update_attr (); need_wrap = 0; } static void lf (unsigned long width, unsigned long height) { if (y < height - 1) { y++; pos += width; } need_wrap = 0; } void cr () { pos -= x; need_wrap = 0; x = 0; } /* DOS end-of-file character. */ #define DOS_EOF 26 unsigned long ansi_esc_translate (FILE * fp, unsigned int * editbuffer, unsigned long width, unsigned long height) { int c, ok; /* * Some of these initial values might not be needed but right now * it's better to be safe than sorry. -Pekka, 2003-01-11 */ y = 0; x = 0; intensity = 1; underline = 0; blink = 0; reverse = 0; saved_x = 0; saved_y = 0; s_intensity = 0; s_underline = 0; s_blink = 0; s_reverse = 0; s_color = 0; color = 0; npar = 0; need_wrap = 0; def_color = 0x07; pos = 0; fore = 7; back = 0; vc_state = ESnormal; ques = 0; attr = 7; tab_stop[0] = 0x01010100; tab_stop[1] = 0x01010101; tab_stop[2] = 0x01010101; tab_stop[3] = 0x01010101; tab_stop[4] = 0x01010101; /* Read file, translate escape codes to color codes, and store them into an array. */ while (((c = getc (fp)) != -1) && (c != DOS_EOF) && (pos < width * height)) { ok = (c >= 32); /* less than ' ' ignored */ if ((vc_state == ESnormal) && ok) { if (need_wrap) { cr (); lf (width, height); } editbuffer[pos] = ((attr << 8) + c); if (x == width - 1) need_wrap = 1; /* decawm; */ else { x++; pos++; } continue; } switch (c) { case 7: continue; case 8: continue; case 9: pos -= x; while (x < width - 1) { x++; if (tab_stop[x >> 5] & (1 << (x & 31))) break; } pos += x; continue; case 10: case 11: case 12: cr (); lf (width, height); continue; case 13: continue; case 14: continue; case 15: continue; case 24: case 26: vc_state = ESnormal; continue; case 27: vc_state = ESesc; continue; case 127: continue; case 128 + 27: vc_state = ESsquare; continue; } switch (vc_state) { case ESesc: vc_state = ESnormal; switch (c) { case '[': vc_state = ESsquare; continue; case ']': vc_state = ESnonstd; continue; case '%': vc_state = ESpercent; continue; case 'E': cr (); lf (width, height); continue; case 'M': /* nothing */ continue; case 'D': lf (width, height); continue; case 'H': continue; case 'Z': continue; case '7': save_cur (); continue; case '8': restore_cur (width, height); continue; case '(': vc_state = ESsetG0; continue; case ')': vc_state = ESsetG1; continue; case '#': vc_state = EShash; continue; case 'c': continue; case '>': /* Numeric keypad */ continue; case '=': /* Appl. keypad */ continue; } continue; case ESnonstd: if (c == 'P') { /* palette escape sequence */ for (npar = 0; npar < 7; npar++) par[npar] = 0; npar = 0; vc_state = ESpalette; continue; } else if (c == 'R') { /* reset palette */ vc_state = ESnormal; } else vc_state = ESnormal; continue; case ESpalette: if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) { par[npar++] = (c > '9' ? (c & 0xDF) - 'A' + 10 : c - '0'); } else vc_state = ESnormal; continue; case ESsquare: for (npar = 0; npar < 7; npar++) par[npar] = 0; npar = 0; vc_state = ESgetpars; if (c == '[') { /* Function key */ vc_state = ESfunckey; continue; } ques = (c == '?'); if (ques) continue; case ESgetpars: if (c == ';' && npar < 6) { npar++; continue; } else if (c >= '0' && c <= '9') { par[npar] *= 10; par[npar] += c - '0'; continue; } else vc_state = ESgotpars; case ESgotpars: vc_state = ESnormal; switch (c) { case 'h': continue; case 'l': continue; case 'n': continue; } if (ques) { ques = 0; continue; } switch (c) { case 'G': case '`': if (par[0]) par[0]--; gotoxy (par[0], y, width, height); continue; case 'A': if (!par[0]) par[0]++; gotoxy (x, y - par[0], width, height); continue; case 'B': case 'e': if (!par[0]) par[0]++; gotoxy (x, y + par[0], width, height); continue; case 'C': case 'a': if (!par[0]) par[0]++; gotoxy (x + par[0], y, width, height); continue; case 'D': if (!par[0]) par[0]++; gotoxy (x - par[0], y, width, height); continue; case 'E': if (!par[0]) par[0]++; gotoxy (0, y + par[0], width, height); continue; case 'F': if (!par[0]) par[0]++; gotoxy (0, y - par[0], width, height); continue; case 'd': if (par[0]) par[0]--; gotoxy (x, par[0], width, height); continue; case 'H': case 'f': if (par[0]) par[0]--; if (par[1]) par[1]--; gotoxy (par[1], par[0], width, height); continue; case 'J': continue; case 'K': continue; case 'L': continue; case 'M': continue; case 'P': continue; case 'c': continue; case 'g': continue; case 'm': csi_m (); continue; case 'q': /* DECLL - but only 3 leds */ continue; case 'r': continue; case 's': save_cur (); continue; case 'u': restore_cur (width, height); continue; case 'X': continue; case '@': continue; case ']': /* setterm functions */ continue; } continue; case ESpercent: vc_state = ESnormal; continue; case ESfunckey: vc_state = ESnormal; continue; case EShash: vc_state = ESnormal; continue; case ESsetG0: vc_state = ESnormal; continue; case ESsetG1: vc_state = ESnormal; continue; default: vc_state = ESnormal; } } return pos; /* return number of bytes stored in buffer. */ }