diff options
Diffstat (limited to 'terms.c')
-rw-r--r-- | terms.c | 1839 |
1 files changed, 1839 insertions, 0 deletions
@@ -0,0 +1,1839 @@ +/* $Id: terms.c,v 1.1 2001/11/08 05:15:43 a-ito Exp $ */ +/* + * An original curses library for EUC-kanji by Akinori ITO, December 1989 + * revised by Akinori ITO, January 1995 + */ +#include <stdio.h> +#include <signal.h> +#include <sys/types.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/time.h> +#include <unistd.h> +#include "config.h" +#include <string.h> +#ifdef MOUSE +#ifdef USE_GPM +#include <gpm.h> +#endif /* USE_GPM */ +#ifdef USE_SYSMOUSE +#include <machine/console.h> +int (*sysm_handler) (int x, int y, int nbs, int obs); +static int cwidth = 8, cheight = 16; +static int xpix, ypix, nbs, obs = 0; +#endif /* use_SYSMOUSE */ + +static int is_xterm = 0; +void mouse_init(), mouse_end(); +int mouseActive = 0; +#endif /* MOUSE */ + +#ifdef AIX +#include <sys/select.h> +#endif /* AIX */ + +#include "terms.h" +#include "fm.h" +#include "myctype.h" + +#ifdef __EMX__ +#define INCL_DOSNLS +#include <os2.h> +#include <sys/select.h> + +#ifndef JP_CHARSET +extern int CodePage; +#endif /* !JP_CHARSET */ +#endif /* __EMX__ */ + +char *getenv(const char *); +MySignalHandler reset_exit(SIGNAL_ARG), error_dump(SIGNAL_ARG); +void setlinescols(void); +void flush_tty(); + +#ifndef SIGIOT +#define SIGIOT SIGABRT +#endif /* not SIGIOT */ + +#ifdef TERMIO +#include <sys/ioctl.h> +#include <termio.h> +typedef struct termio TerminalMode; +#define TerminalSet(fd,x) ioctl(fd,TCSETA,x) +#define TerminalGet(fd,x) ioctl(fd,TCGETA,x) +#define MODEFLAG(d) ((d).c_lflag) +#define IMODEFLAG(d) ((d).c_iflag) +#endif /* TERMIO */ + +#ifdef TERMIOS +#include <termios.h> +#include <unistd.h> +typedef struct termios TerminalMode; +#define TerminalSet(fd,x) tcsetattr(fd,TCSANOW,x) +#define TerminalGet(fd,x) tcgetattr(fd,x) +#define MODEFLAG(d) ((d).c_lflag) +#define IMODEFLAG(d) ((d).c_iflag) +#endif /* TERMIOS */ + +#ifdef SGTTY +#include <sys/ioctl.h> +#include <sgtty.h> +typedef struct sgttyb TerminalMode; +#define TerminalSet(fd,x) ioctl(fd,TIOCSETP,x) +#define TerminalGet(fd,x) ioctl(fd,TIOCGETP,x) +#define MODEFLAG(d) ((d).sg_flags) +#endif /* SGTTY */ + +#define MAX_LINE 200 +#define MAX_COLUMN 400 + +/* Screen properties */ +#define S_SCREENPROP 0x0f +#define S_NORMAL 0x00 +#define S_STANDOUT 0x01 +#define S_UNDERLINE 0x02 +#define S_BOLD 0x04 +#define S_EOL 0x08 + +/* Sort of Character */ +#define C_WHICHCHAR 0xc0 +#define C_ASCII 0x00 +#ifdef JP_CHARSET +#define C_WCHAR1 0x40 +#define C_WCHAR2 0x80 +#endif /* JP_CHARSET */ +#define C_CTRL 0xc0 + +#define CHMODE(c) ((c)&C_WHICHCHAR) +#define SETCHMODE(var,mode) var = (((var)&~C_WHICHCHAR) | mode) + +/* Charactor Color */ +#define COL_FCOLOR 0xf00 +#define COL_FBLACK 0x800 +#define COL_FRED 0x900 +#define COL_FGREEN 0xa00 +#define COL_FYELLOW 0xb00 +#define COL_FBLUE 0xc00 +#define COL_FMAGENTA 0xd00 +#define COL_FCYAN 0xe00 +#define COL_FWHITE 0xf00 +#define COL_FTERM 0x000 + +#define S_COLORED 0xf00 + +#ifdef BG_COLOR +/* Background Color */ +#define COL_BCOLOR 0xf000 +#define COL_BBLACK 0x8000 +#define COL_BRED 0x9000 +#define COL_BGREEN 0xa000 +#define COL_BYELLOW 0xb000 +#define COL_BBLUE 0xc000 +#define COL_BMAGENTA 0xd000 +#define COL_BCYAN 0xe000 +#define COL_BWHITE 0xf000 +#define COL_BTERM 0x0000 + +#define S_BCOLORED 0xf000 +#endif /* BG_COLOR */ + + +#define S_GRAPHICS 0x10 + +#define S_DIRTY 0x20 + +#define SETPROP(var,prop) (var = (((var)&S_DIRTY) | prop)) + +/* Line status */ +#define L_DIRTY 0x01 +#define L_UNUSED 0x02 +#define L_NEED_CE 0x04 +#define L_CLRTOEOL 0x08 + +#define ISDIRTY(d) ((d) & L_DIRTY) +#define ISUNUSED(d) ((d) & L_UNUSED) +#define NEED_CE(d) ((d) & L_NEED_CE) + +typedef unsigned short l_prop; + +typedef struct scline { + char *lineimage; + l_prop *lineprop; + short isdirty; + short eol; +} Screen; + +static +TerminalMode d_ioval; +static +int tty; +static +FILE *ttyf; + +static +char bp[1024], funcstr[256]; + +char *T_cd, *T_ce, *T_kr, *T_kl, *T_cr, *T_bt, *T_ta, *T_sc, *T_rc, +*T_so, *T_se, *T_us, *T_ue, *T_cl, *T_cm, *T_al, *T_sr, *T_md, *T_me, +*T_ti, *T_te, *T_nd, *T_as, *T_ae, *T_eA, *T_ac, *T_op; + +int LINES, COLS; +static int max_LINES = 0, max_COLS = 0; +static int tab_step = 8; +static int CurLine, CurColumn; +static Screen *ScreenElem = NULL, **ScreenImage = NULL; +static l_prop CurrentMode = 0; +static int graph_enabled = 0; + +char DisplayCode = DISPLAY_CODE; + +static char gcmap[96]; + +extern int tgetent(char *, char *); +extern int tgetnum(char *); +extern int tgetflag(char *); +extern char *tgetstr(char *, char **); +extern char *tgoto(char *, int, int); +extern int tputs(char *, int, int (*)(char)); +void putchars(unsigned char, unsigned char, FILE *); +void clear(), wrap(), touch_line(), touch_column(int); +#ifdef JP_CHARSET +void switch_wchar(FILE *); +void switch_ascii(FILE *); +#endif +void need_clrtoeol(void), clrtoeol(void); + +int write1(char); + +/* #define writestr(s) tputs(s,1,write1) */ + +static void +writestr(char *s) +{ + tputs(s, 1, write1); +} + +#define MOVE(line,column) writestr(tgoto(T_cm,column,line)); + +int +set_tty(void) +{ + char *ttyn; +#ifdef MOUSE + char *term; +#endif + + if (isatty(0)) /* stdin */ + ttyn = ttyname(0); + else +#ifndef __EMX__ + ttyn = "/dev/tty"; +#else /* __EMX__ */ + ttyn = "con"; +#endif /* __EMX__ */ + tty = open(ttyn, O_RDWR); + if (tty < 0) { + /* use stderr instead of stdin... is it OK???? */ + tty = 2; + } + ttyf = fdopen(tty, "w"); + TerminalGet(tty, &d_ioval); +#ifdef MOUSE + term = getenv("TERM"); + if (!strncmp(term, "kterm", 5) || !strncmp(term, "xterm", 5)) { + is_xterm = 1; + } +#endif + return 0; +} + +void +ttymode_set(int mode, int imode) +{ + int er; + TerminalMode ioval; + + TerminalGet(tty, &ioval); + MODEFLAG(ioval) |= mode; +#ifndef SGTTY + IMODEFLAG(ioval) |= imode; +#endif /* not SGTTY */ + + er = TerminalSet(tty, &ioval); + + if (er == -1) { + printf("Error occured while set %x: errno=%d\n", mode, errno); + reset_exit(SIGNAL_ARGLIST); + } +} + +void +ttymode_reset(int mode, int imode) +{ + int er; + TerminalMode ioval; + + TerminalGet(tty, &ioval); + MODEFLAG(ioval) &= ~mode; +#ifndef SGTTY + IMODEFLAG(ioval) &= ~imode; +#endif /* not SGTTY */ + + er = TerminalSet(tty, &ioval); + + if (er == -1) { + printf("Error occured while reset %x: errno=%d\n", mode, errno); + reset_exit(SIGNAL_ARGLIST); + } +} + +#ifndef SGTTY +void +set_cc(int spec, int val) +{ + int er; + TerminalMode ioval; + + TerminalGet(tty, &ioval); + ioval.c_cc[spec] = val; + er = TerminalSet(tty, &ioval); + if (er == -1) { + printf("Error occured: errno=%d\n", errno); + reset_exit(SIGNAL_ARGLIST); + } +} +#endif /* not SGTTY */ + +void +close_tty(void) +{ + close(tty); +} + +void +reset_tty(void) +{ + if (DisplayCode != CODE_EUC && DisplayCode != CODE_SJIS) +#if defined(__EMX__)&&!defined(JP_CHARSET) + if(!CodePage) +#endif + writestr("\033(B"); /* designate US_ASCII */ + writestr(T_op); /* turn off */ + writestr(T_me); + if (!Do_not_use_ti_te) { + if (T_te && *T_te) + writestr(T_te); + else + writestr(T_cl); + } + writestr(T_se); /* reset terminal */ + fflush(ttyf); + TerminalSet(tty, &d_ioval); + close(tty); +} + +MySignalHandler +reset_exit(SIGNAL_ARG) +{ + reset_tty(); +#ifdef MOUSE + if (mouseActive) + mouse_end(); +#endif /* MOUSE */ + exit(0); + SIGNAL_RETURN; +} + +MySignalHandler +error_dump(SIGNAL_ARG) +{ + signal(SIGIOT, SIG_DFL); + reset_tty(); + abort(); + SIGNAL_RETURN; +} + +void +set_int(void) +{ + signal(SIGHUP, reset_exit); + signal(SIGINT, reset_exit); + signal(SIGQUIT, reset_exit); + signal(SIGTERM, reset_exit); + signal(SIGILL, error_dump); + signal(SIGIOT, error_dump); + signal(SIGFPE, error_dump); +#ifdef SIGBUS + signal(SIGBUS, error_dump); +#endif /* SIGBUS */ +/* signal(SIGSEGV, error_dump); */ +} + + +static void +setgraphchar(void) +{ + int c, i, n; + + for (c = 0; c < 96; c++) + gcmap[c] = (char) (c + ' '); + + if (!T_ac) + return; + + n = strlen(T_ac); + for (i = 0; i < n - 1; i += 2) { + c = (unsigned) T_ac[i] - ' '; + if (c >= 0 && c < 96) + gcmap[c] = T_ac[i + 1]; + } +} + +#define graphchar(c) (((unsigned)(c)>=' ' && (unsigned)(c)<128)? gcmap[(c)-' '] : (c)) + +#define GETSTR(v,s) {v = pt; suc = tgetstr(s,&pt); if (!suc) v = ""; else v = allocStr(suc,0); } + +void +getTCstr(void) +{ + char *ent; + char *suc; + char *pt = funcstr; + int r; + +#ifdef __DJGPP__ + ent = getenv("TERM") ? getenv("TERM") : "dosansi"; +#else + ent = getenv("TERM"); +#endif /* __DJGPP__ */ + r = tgetent(bp, ent); + if (r != 1) { + /* Can't find termcap entry */ + fprintf(stderr, "Can't find termcap entry %s\n", ent); + reset_exit(SIGNAL_ARGLIST); + } + + GETSTR(T_ce, "ce"); /* clear to the end of line */ + GETSTR(T_cd, "cd"); /* clear to the end of display */ + GETSTR(T_kr, "nd"); /* cursor right */ + if (suc == NULL) + GETSTR(T_kr, "kr"); + if (tgetflag("bs")) + T_kl = "\b"; /* cursor left */ + else { + GETSTR(T_kl, "le"); + if (suc == NULL) + GETSTR(T_kl, "kb"); + if (suc == NULL) + GETSTR(T_kl, "kl"); + } + GETSTR(T_cr, "cr"); /* carrige return */ + GETSTR(T_ta, "ta"); /* tab */ + GETSTR(T_sc, "sc"); /* save cursor */ + GETSTR(T_rc, "rc"); /* restore cursor */ + GETSTR(T_so, "so"); /* standout mode */ + GETSTR(T_se, "se"); /* standout mode end */ + GETSTR(T_us, "us"); /* underline mode */ + GETSTR(T_ue, "ue"); /* underline mode end */ + GETSTR(T_md, "md"); /* bold mode */ + GETSTR(T_me, "me"); /* bold mode end */ + GETSTR(T_cl, "cl"); /* clear screen */ + GETSTR(T_cm, "cm"); /* cursor move */ + GETSTR(T_al, "al"); /* append line */ + GETSTR(T_sr, "sr"); /* scroll reverse */ + GETSTR(T_ti, "ti"); /* terminal init */ + GETSTR(T_te, "te"); /* terminal end */ + GETSTR(T_nd, "nd"); /* move right one space */ + GETSTR(T_eA, "eA"); /* enable alternative charset */ + GETSTR(T_as, "as"); /* alternative (graphic) charset start */ + GETSTR(T_ae, "ae"); /* alternative (graphic) charset end */ + GETSTR(T_ac, "ac"); /* graphics charset pairs */ + GETSTR(T_op, "op"); /* set default color pair to its original + * * * * * * * value */ +#ifdef CYGWIN +/* for TERM=pcansi on MS-DOS prompt. * T_as = "\033[12m"; * T_ae = + * "\033[10m"; * T_ac = + * "l\001k\002m\003j\004x\005q\006n\020a\024v\025w\026u\027t\031"; */ + T_as[0] = '\0'; + T_ae[0] = '\0'; + T_ac[0] = '\0'; +#endif /* CYGWIN */ + + LINES = COLS = 0; + setlinescols(); + setgraphchar(); +} + +#ifndef TIOCGWINSZ +#include <sys/ioctl.h> +#endif /* not TIOCGWINSZ */ + +void +setlinescols(void) +{ + char *p; + int i; +#ifdef __EMX__ + { + int s[2]; + _scrsize(s); + COLS = s[0]; + LINES = s[1]; + + if (getenv("WINDOWID")) { + FILE *fd = popen("scrsize", "rt"); + if (fd) { + fscanf(fd, "%i %i", &COLS, &LINES); + pclose(fd); + } + } +#ifndef JP_CHARSET + else{ + ULONG CpList[8],CpSize; + CodePage=-1; + if(!DosQueryCp(sizeof(CpList),CpList,&CpSize)) + CodePage=*CpList; + } +#endif + } +#elif defined(TERMIOS) && defined(TIOCGWINSZ) + struct winsize wins; + + i = ioctl(tty, TIOCGWINSZ, &wins); + if (i >= 0 && wins.ws_row != 0 && wins.ws_col != 0) { + LINES = wins.ws_row; + COLS = wins.ws_col; + } +#endif /* defined(TERMIOS) && defined(TIOCGWINSZ) + * + */ + if (LINES <= 0 && + (p = getenv("LINES")) != NULL && + (i = atoi(p)) >= 0) + LINES = i; + if (COLS <= 0 && + (p = getenv("COLUMNS")) != NULL && + (i = atoi(p)) >= 0) + COLS = i; + if (LINES <= 0) + LINES = tgetnum("li"); /* number of line */ + if (COLS <= 0) + COLS = tgetnum("co"); /* number of column */ + if (COLS > MAX_COLUMN) + COLS = MAX_COLUMN; + if (LINES > MAX_LINE) + LINES = MAX_LINE; +} + +void +setupscreen(void) +{ + int i; + + if (LINES + 1 > max_LINES) { + max_LINES = LINES + 1; + max_COLS = 0; + ScreenElem = New_N(Screen, max_LINES); + ScreenImage = New_N(Screen *, max_LINES); + } + if (COLS + 1 > max_COLS) { + max_COLS = COLS + 1; + for (i = 0; i < max_LINES; i++) { + ScreenElem[i].lineimage = New_N(char, max_COLS); + ScreenElem[i].lineprop = New_N(l_prop, max_COLS); + } + } + for (i = 0; i < LINES; i++) { + ScreenImage[i] = &ScreenElem[i]; + ScreenImage[i]->lineprop[0] = S_EOL; + ScreenImage[i]->isdirty = 0; + } + for (; i < max_LINES; i++) { + ScreenElem[i].isdirty = L_UNUSED; + } + + clear(); +} + +/* + * Screen initialize + */ +int +initscr(void) +{ + if (set_tty() < 0) + return -1; + set_int(); + getTCstr(); + if (T_ti && !Do_not_use_ti_te) + writestr(T_ti); + setupscreen(); + return 0; +} + +#ifdef JP_CHARSET +static int wmode = C_ASCII; +static char wbuf; +#endif + +int +write1(char c) +{ +#ifdef SCREEN_DEBUG + usleep(50); +#endif /* SCREEN_DEBUG */ +#ifdef JP_CHARSET + if (IS_KANJI(c)) { + switch (wmode) { + case C_ASCII: + switch_wchar(ttyf); + case C_WCHAR2: + wmode = C_WCHAR1; + wbuf = c; + break; + case C_WCHAR1: + wmode = C_WCHAR2; + putchars((unsigned char) wbuf, (unsigned char) c, ttyf); + break; + } + } + else { + switch (wmode) { + case C_ASCII: + break; + case C_WCHAR1: + /* ignore byte */ + wmode = C_ASCII; + switch_ascii(ttyf); + break; + case C_WCHAR2: + wmode = C_ASCII; + switch_ascii(ttyf); + break; + } + putc(c, ttyf); + } +#else /* not JP_CHARSET */ + putc(c, ttyf); +#endif /* not JP_CHARSET */ +#ifdef SCREEN_DEBUG + fflush(ttyf); +#endif /* SCREEN_DEBUG */ + return 0; +} + +#ifdef JP_CHARSET +void +endline(void) +{ /* End of line */ + if (wmode != C_ASCII) { + switch_ascii(ttyf); + wmode = C_ASCII; + } +} + +void +switch_ascii(FILE * f) +{ + extern char *GetSOCode(char); + if (CODE_JIS(DisplayCode)) { + fputs(GetSOCode(DisplayCode), f); + } +} + +void +switch_wchar(FILE * f) +{ + extern char *GetSICode(char); + if (CODE_JIS(DisplayCode)) { + fputs(GetSICode(DisplayCode), f); + } +} + +void +putchars(unsigned char c1, unsigned char c2, FILE * f) +{ + Str s; + char *p; + + switch (DisplayCode) { + case CODE_EUC: + putc(c1, f); + putc(c2, f); + return; + case CODE_JIS_n: + case CODE_JIS_m: + case CODE_JIS_N: + case CODE_JIS_j: + case CODE_JIS_J: + putc(c1 & 0x7f, f); + putc(c2 & 0x7f, f); + return; + case CODE_SJIS: + s = Strnew_size(3); + put_sjis(s, c1 & 0x7f, c2 & 0x7f); + break; + } + if (! s->length) { + putc('?', f); + putc('?', f); + return; + } + for (p = s->ptr; *p != '\0'; p++) + putc(*p, f); +} +#endif /* JP_CHARSET */ + +void +move(int line, int column) +{ + if (line >= 0 && line < LINES) + CurLine = line; + if (column >= 0 && column < COLS) + CurColumn = column; +} + +#ifdef BG_COLOR +#define M_SPACE (S_SCREENPROP|S_COLORED|S_BCOLORED|S_GRAPHICS) +#else /* not BG_COLOR */ +#define M_SPACE (S_SCREENPROP|S_COLORED|S_GRAPHICS) +#endif /* not BG_COLOR */ + +static int +need_redraw(char c1, l_prop pr1, char c2, l_prop pr2) +{ + if (c1 != c2) + return 1; + if (c1 == ' ') + return (pr1 ^ pr2) & M_SPACE & ~S_DIRTY; + + if ((pr1 ^ pr2) & ~S_DIRTY) + return 1; + + return 0; +} + +#define M_CEOL (~(M_SPACE|C_WHICHCHAR)) + +void +addch(char c) +{ + char *p; + l_prop *pr; + int dest, i; + short *dirty; +#ifdef __EMX__ + extern int CodePage; +#endif + + if (CurColumn == COLS) + wrap(); + if (CurColumn >= COLS) + return; + p = ScreenImage[CurLine]->lineimage; + pr = ScreenImage[CurLine]->lineprop; + dirty = &ScreenImage[CurLine]->isdirty; + + /* Eliminate unprintables according to * iso-8859-*. + * Particularly 0x96 messes up T.Dickey's * (xfree-)xterm */ + if (IS_INTERNAL(c)) + c = ' '; + + if (pr[CurColumn] & S_EOL) { + if (c == ' ' && +#ifdef JP_CHARSET + CHMODE(CurrentMode) != C_WCHAR1 && +#endif /* JP_CHARSET */ + !(CurrentMode & M_SPACE)) { + CurColumn++; + return; + } + for (i = CurColumn; i >= 0 && (pr[i] & S_EOL); i--) { + p[i] = ' '; + SETPROP(pr[i], (pr[i] & M_CEOL) | C_ASCII); + } + } + + if (c == '\t' || c == '\n' || c == '\r' || c == '\b') + SETCHMODE(CurrentMode, C_CTRL); +#ifdef JP_CHARSET + else if (CHMODE(CurrentMode) == C_WCHAR1) + SETCHMODE(CurrentMode, C_WCHAR2); + else if (IS_KANJI1(c)) + SETCHMODE(CurrentMode, C_WCHAR1); +#endif /* JP_CHARSET */ + else if (!IS_CNTRL(c)) + SETCHMODE(CurrentMode, C_ASCII); + else + return; + + /* Required to erase bold or underlined character for some * terminal + * emulators. */ + if (((pr[CurColumn] & S_BOLD) && + need_redraw(p[CurColumn], pr[CurColumn], c, CurrentMode)) || + ((pr[CurColumn] & S_UNDERLINE) && !(CurrentMode & S_UNDERLINE))) { + touch_line(); + if (CurColumn < COLS - 1) { + touch_column(CurColumn + 1); + if (pr[CurColumn + 1] & S_EOL) { + p[CurColumn + 1] = ' '; + SETPROP(pr[CurColumn + 1], (pr[CurColumn + 1] & M_CEOL) | C_ASCII); + } +#ifdef JP_CHARSET + else if (CHMODE(pr[CurColumn + 1]) == C_WCHAR1 && CurColumn < COLS - 2) + touch_column(CurColumn + 2); +#endif /* JP_CHARSET */ + } + } + +#ifdef JP_CHARSET + if (CurColumn >= 1 && CHMODE(pr[CurColumn - 1]) == C_WCHAR1 && + CHMODE(CurrentMode) != C_WCHAR2) { + p[CurColumn - 1] = ' '; + SETPROP(pr[CurColumn - 1], (pr[CurColumn - 1] & ~C_WHICHCHAR) | C_ASCII); + touch_line(); + touch_column(CurColumn - 1); + } + + if (CurColumn < COLS - 1 && CHMODE(pr[CurColumn + 1]) == C_WCHAR2 && + CHMODE(CurrentMode) != C_WCHAR1) { + p[CurColumn + 1] = ' '; + SETPROP(pr[CurColumn + 1], (pr[CurColumn + 1] & ~C_WHICHCHAR) | C_ASCII); + touch_line(); + touch_column(CurColumn + 1); + } + + if (CurColumn == COLS - 1 && CHMODE(CurrentMode) == C_WCHAR1) { + wrap(); + p = ScreenImage[CurLine]->lineimage; + pr = ScreenImage[CurLine]->lineprop; + } +#endif /* JP_CHARSET */ + if (CHMODE(CurrentMode) != C_CTRL) { + if (need_redraw(p[CurColumn], pr[CurColumn], c, CurrentMode)) { + p[CurColumn] = c; + SETPROP(pr[CurColumn], CurrentMode); + touch_line(); + touch_column(CurColumn); +#ifdef JP_CHARSET + if (CHMODE(CurrentMode) == C_WCHAR1) + touch_column(CurColumn + 1); + else if (CHMODE(CurrentMode) == C_WCHAR2) + touch_column(CurColumn - 1); +#endif /* JP_CHARSET */ + } + CurColumn++; + } + else if (c == '\t') { + dest = (CurColumn + tab_step) / tab_step * tab_step; + if (dest >= COLS) { + wrap(); + touch_line(); + dest = tab_step; + p = ScreenImage[CurLine]->lineimage; + pr = ScreenImage[CurLine]->lineprop; + } + for (i = CurColumn; i < dest; i++) { + if (need_redraw(p[i], pr[i], ' ', CurrentMode)) { + p[i] = ' '; + SETPROP(pr[i], CurrentMode); + touch_line(); + touch_column(i); + } + } + CurColumn = i; + } + else if (c == '\n') { + wrap(); + } + else if (c == '\r') { /* Carrige return */ + CurColumn = 0; + } + else if (c == '\b' && CurColumn > 0) { /* Backspace */ + CurColumn--; +#ifdef JP_CHARSET + if (CurColumn > 0 && + CHMODE(pr[CurColumn]) == C_WCHAR2) + CurColumn--; +#endif /* JP_CHARSET */ + } +} + +void +wrap(void) +{ + if (CurLine == LINES - 1) + return; + CurLine++; + CurColumn = 0; +} + +void +touch_column(int col) +{ + if (col >= 0 && col < COLS) + ScreenImage[CurLine]->lineprop[col] |= S_DIRTY; +} + +void +touch_line(void) +{ + if (!(ScreenImage[CurLine]->isdirty & L_DIRTY)) { + int i; + for (i = 0; i < COLS; i++) + ScreenImage[CurLine]->lineprop[i] &= ~S_DIRTY; + ScreenImage[CurLine]->isdirty |= L_DIRTY; + } + +} + +void +standout(void) +{ + CurrentMode |= S_STANDOUT; +} + +void +standend(void) +{ + CurrentMode &= ~S_STANDOUT; +} + +void +toggle_stand(void) +{ + l_prop *pr = ScreenImage[CurLine]->lineprop; + pr[CurColumn] ^= S_STANDOUT; +#ifdef JP_CHARSET + if (CHMODE(pr[CurColumn]) == C_WCHAR1) + pr[CurColumn + 1] ^= S_STANDOUT; +#endif /* JP_CHARSET */ +} + +void +bold(void) +{ + CurrentMode |= S_BOLD; +} + +void +boldend(void) +{ + CurrentMode &= ~S_BOLD; +} + +void +underline(void) +{ + CurrentMode |= S_UNDERLINE; +} + +void +underlineend(void) +{ + CurrentMode &= ~S_UNDERLINE; +} + +void +graphstart(void) +{ + CurrentMode |= S_GRAPHICS; +} + +void +graphend(void) +{ + CurrentMode &= ~S_GRAPHICS; +} + +int +graph_ok(void) +{ +#ifndef KANJI_SYMBOLS + if (no_graphic_char) + return 0; +#endif /* not KANJI_SYMBOLS */ + return T_as[0] != 0 && T_ae[0] != 0 && T_ac[0] != 0; +} + +void +setfcolor(int color) +{ + CurrentMode &= ~COL_FCOLOR; + if ((color & 0xf) <= 7) + CurrentMode |= (((color & 7) | 8) << 8); +} + +static char * +color_seq(int colmode) +{ + static char seqbuf[32]; + sprintf(seqbuf, "\033[%dm", ((colmode >> 8) & 7) + 30); + return seqbuf; +} + +#ifdef BG_COLOR +void +setbcolor(int color) +{ + CurrentMode &= ~COL_BCOLOR; + if ((color & 0xf) <= 7) + CurrentMode |= (((color & 7) | 8) << 12); +} + +static char * +bcolor_seq(int colmode) +{ + static char seqbuf[32]; + sprintf(seqbuf, "\033[%dm", ((colmode >> 12) & 7) + 40); + return seqbuf; +} +#endif /* BG_COLOR */ + +#define RF_NEED_TO_MOVE 0 +#define RF_CR_OK 1 +#define RF_NONEED_TO_MOVE 2 +#ifdef BG_COLOR +#define M_MEND (S_STANDOUT|S_UNDERLINE|S_BOLD|S_COLORED|S_BCOLORED|S_GRAPHICS) +#else /* not BG_COLOR */ +#define M_MEND (S_STANDOUT|S_UNDERLINE|S_BOLD|S_COLORED|S_GRAPHICS) +#endif /* not BG_COLOR */ +void +refresh(void) +{ + int line, col, pcol; + int pline = CurLine; + int moved = RF_NEED_TO_MOVE; + char *pc; + l_prop *pr, mode = 0; + l_prop color = COL_FTERM; +#ifdef BG_COLOR + l_prop bcolor = COL_BTERM; +#endif /* BG_COLOR */ + short *dirty; + + for (line = 0; line < LINES; line++) { + dirty = &ScreenImage[line]->isdirty; + if (*dirty & L_DIRTY) { + *dirty &= ~L_DIRTY; + pc = ScreenImage[line]->lineimage; + pr = ScreenImage[line]->lineprop; + for (col = 0; col < COLS && !(pr[col] & S_EOL); col++) { + if (*dirty & L_NEED_CE && col >= ScreenImage[line]->eol) { + if (need_redraw(pc[col], pr[col], ' ', 0)) + break; + } + else { + if (pr[col] & S_DIRTY) + break; + } + } + if (*dirty & (L_NEED_CE | L_CLRTOEOL)) { + pcol = ScreenImage[line]->eol; + if (pcol >= COLS) { + *dirty &= ~(L_NEED_CE | L_CLRTOEOL); + pcol = col; + } + } + else { + pcol = col; + } + if (line < LINES - 2 && pline == line - 1 && pcol == 0) { + switch (moved) { + case RF_NEED_TO_MOVE: + MOVE(line, 0); + moved = RF_CR_OK; + break; + case RF_CR_OK: + write1('\n'); + write1('\r'); + break; + case RF_NONEED_TO_MOVE: + moved = RF_CR_OK; + break; + } + } + else { + MOVE(line, pcol); + moved = RF_CR_OK; + } + if (*dirty & (L_NEED_CE | L_CLRTOEOL)) { + writestr(T_ce); + if (col != pcol) + MOVE(line, col); + } + pline = line; + pcol = col; + for (; col < COLS; col++) { + if (pr[col] & S_EOL) + break; + + /* + * some terminal emulators do linefeed when a + * character is put on COLS-th column. this behavior + * is different from one of vt100, but such terminal + * emulators are used as vt100-compatible + * emulators. This behaviour causes scroll when a + * character is drawn on (COLS-1,LINES-1) point. To + * avoid the scroll, I prohibit to draw character on + * (COLS-1,LINES-1). + */ +#ifndef BG_COLOR + if (line == LINES - 1 && col == COLS - 1) + break; +#endif /* not BG_COLOR */ + if ((!(pr[col] & S_STANDOUT) && (mode & S_STANDOUT)) || + (!(pr[col] & S_UNDERLINE) && (mode & S_UNDERLINE)) || + (!(pr[col] & S_BOLD) && (mode & S_BOLD)) || + (!(pr[col] & S_COLORED) && (mode & S_COLORED)) +#ifdef BG_COLOR + || (!(pr[col] & S_BCOLORED) && (mode & S_BCOLORED)) +#endif /* BG_COLOR */ + || (!(pr[col] & S_GRAPHICS) && (mode & S_GRAPHICS))) { + if ((!(pr[col] & S_COLORED) && (mode & S_COLORED)) +#ifdef BG_COLOR + || (!(pr[col] & S_BCOLORED) && (mode & S_BCOLORED)) +#endif /* BG_COLOR */ + ) + writestr(T_op); + if (!(pr[col] & S_GRAPHICS) && (mode & S_GRAPHICS)) + writestr(T_ae); + writestr(T_me); + mode &= ~M_MEND; + } + if ((*dirty & L_NEED_CE && col >= ScreenImage[line]->eol) ? + need_redraw(pc[col], pr[col], ' ', 0) : (pr[col] & S_DIRTY)) { + if (pcol == col - 1) + writestr(T_nd); + else if (pcol != col) + MOVE(line, col); + + if ((pr[col] & S_COLORED) && (pr[col] ^ mode) & COL_FCOLOR) { + color = (pr[col] & COL_FCOLOR); + mode = ((mode & ~COL_FCOLOR) | color); + writestr(color_seq(color)); + } +#ifdef BG_COLOR + if ((pr[col] & S_BCOLORED) && (pr[col] ^ mode) & COL_BCOLOR) { + bcolor = (pr[col] & COL_BCOLOR); + mode = ((mode & ~COL_BCOLOR) | bcolor); + writestr(bcolor_seq(bcolor)); + } +#endif /* BG_COLOR */ + if ((pr[col] & S_STANDOUT) && !(mode & S_STANDOUT)) { + writestr(T_so); + mode |= S_STANDOUT; + } + if ((pr[col] & S_UNDERLINE) && !(mode & S_UNDERLINE)) { + writestr(T_us); + mode |= S_UNDERLINE; + } + if ((pr[col] & S_BOLD) && !(mode & S_BOLD)) { + writestr(T_md); + mode |= S_BOLD; + } + if ((pr[col] & S_GRAPHICS) && !(mode & S_GRAPHICS)) { + if (!graph_enabled) { + graph_enabled = 1; + writestr(T_eA); + } + writestr(T_as); + mode |= S_GRAPHICS; + } + write1((pr[col] & S_GRAPHICS) ? graphchar(pc[col]) : pc[col]); + pcol = col + 1; + } + } + if (col == COLS) + moved = RF_NEED_TO_MOVE; + for (; col < COLS && !(pr[col] & S_EOL); col++) + pr[col] |= S_EOL; + } + *dirty &= ~(L_NEED_CE | L_CLRTOEOL); + if (mode & M_MEND) { + if (mode & (S_COLORED +#ifdef BG_COLOR + | S_BCOLORED +#endif /* BG_COLOR */ + )) + writestr(T_op); + if (mode & S_GRAPHICS) + writestr(T_ae); + writestr(T_me); + mode &= ~M_MEND; + } +#ifdef JP_CHARSET + endline(); +#endif /* JP_CHARSET */ + } + MOVE(CurLine, CurColumn); + fflush(ttyf); +} + +void +clear(void) +{ + int i, j; + l_prop *p; + writestr(T_cl); + move(0, 0); + for (i = 0; i < LINES; i++) { + ScreenImage[i]->isdirty = 0; + p = ScreenImage[i]->lineprop; + for (j = 0; j < COLS; j++) { + p[j] = S_EOL; + } + } + CurrentMode = C_ASCII; +} + +static void +scroll_raw(void) +{ /* raw scroll */ + MOVE(LINES - 1, 0); + write1('\n'); +} + +void +scroll(int n) +{ /* scroll up */ + int cli = CurLine, cco = CurColumn; + Screen *t; + int i, j, k; + + i = LINES; + j = n; + do { + k = j; + j = i % k; + i = k; + } while (j); + do { + k--; + i = k; + j = (i + n) % LINES; + t = ScreenImage[k]; + while (j != k) { + ScreenImage[i] = ScreenImage[j]; + i = j; + j = (i + n) % LINES; + } + ScreenImage[i] = t; + } while (k); + + for (i = 0; i < n; i++) { + t = ScreenImage[LINES - 1 - i]; + t->isdirty = 0; + for (j = 0; j < COLS; j++) + t->lineprop[j] = S_EOL; + scroll_raw(); + } + move(cli, cco); +} + +void +rscroll(int n) +{ /* scroll down */ + int cli = CurLine, cco = CurColumn; + Screen *t; + int i, j, k; + + i = LINES; + j = n; + do { + k = j; + j = i % k; + i = k; + } while (j); + do { + k--; + i = k; + j = (LINES + i - n) % LINES; + t = ScreenImage[k]; + while (j != k) { + ScreenImage[i] = ScreenImage[j]; + i = j; + j = (LINES + i - n) % LINES; + } + ScreenImage[i] = t; + } while (k); + if (T_sr && *T_sr) { + MOVE(0, 0); + for (i = 0; i < n; i++) { + t = ScreenImage[i]; + t->isdirty = 0; + for (j = 0; j < COLS; j++) + t->lineprop[j] = S_EOL; + writestr(T_sr); + } + move(cli, cco); + } + else { + for (i = 0; i < LINES; i++) { + t = ScreenImage[i]; + t->isdirty |= L_DIRTY | L_NEED_CE; + for (j = 0; j < COLS; j++) { + t->lineprop[j] |= S_DIRTY; + } + } + } +} + +#if 0 +void +need_clrtoeol(void) +{ + /* Clear to the end of line as the need arises */ + l_prop *lprop = ScreenImage[CurLine]->lineprop; + + if (lprop[CurColumn] & S_EOL) + return; + + if (!(ScreenImage[CurLine]->isdirty & (L_NEED_CE | L_CLRTOEOL)) || + ScreenImage[CurLine]->eol > CurColumn) + ScreenImage[CurLine]->eol = CurColumn; + + ScreenImage[CurLine]->isdirty |= L_NEED_CE; +} +#endif /* 0 */ + +void +clrtoeol(void) +{ /* Clear to the end of line */ + int i; + l_prop *lprop = ScreenImage[CurLine]->lineprop; + + if (lprop[CurColumn] & S_EOL) + return; + + if (!(ScreenImage[CurLine]->isdirty & (L_NEED_CE | L_CLRTOEOL)) || + ScreenImage[CurLine]->eol > CurColumn) + ScreenImage[CurLine]->eol = CurColumn; + + ScreenImage[CurLine]->isdirty |= L_CLRTOEOL; + touch_line(); + for (i = CurColumn; i < COLS && !(lprop[i] & S_EOL); i++) { + lprop[i] = S_EOL | S_DIRTY; + } +} + +#ifdef BG_COLOR +void +clrtoeol_with_bcolor(void) +{ + int i, cli, cco; + l_prop pr; + + if (!(CurrentMode & S_BCOLORED)) { + clrtoeol(); + return; + } + cli = CurLine; + cco = CurColumn; + pr = CurrentMode; + CurrentMode = (CurrentMode & (M_CEOL | S_BCOLORED)) | C_ASCII; + for (i = CurColumn; i < COLS; i++) + addch(' '); + move(cli, cco); + CurrentMode = pr; +} + +void +clrtoeolx(void) +{ + clrtoeol_with_bcolor(); +} +#else /* not BG_COLOR */ + +void +clrtoeolx(void) +{ + clrtoeol(); +} +#endif /* not BG_COLOR */ + +void +clrtobot_eol(void (*clrtoeol) ()) +{ + int l, c; + + l = CurLine; + c = CurColumn; + (*clrtoeol) (); + CurColumn = 0; + CurLine++; + for (; CurLine < LINES; CurLine++) + (*clrtoeol) (); + CurLine = l; + CurColumn = c; +} + +void +clrtobot(void) +{ + clrtobot_eol(clrtoeol); +} + +void +clrtobotx(void) +{ + clrtobot_eol(clrtoeolx); +} + +#if 0 +void +no_clrtoeol(void) +{ + int i; + l_prop *lprop = ScreenImage[CurLine]->lineprop; + + ScreenImage[CurLine]->isdirty &= ~L_CLRTOEOL; +} +#endif /* 0 */ + +void +addstr(char *s) +{ + while (*s != '\0') + addch(*(s++)); +} + +void +addnstr(char *s, int n) +{ + int i; + +#ifdef JP_CHARSET + for (i = 0; i < n - 1 && *s != '\0'; i++) + addch(*(s++)); + if (*s != '\0') { + if (IS_KANJI2(*s)) { + /* WCHAR */ + if (CHMODE(CurrentMode) == C_WCHAR1) { + /* WCHAR second byte */ + addch(*s); + } + } + else { + /* Ascii or WCHAR2 */ + addch(*s); + } + } +#else /* not JP_CHARSET */ + for (i = 0; i < n && *s != '\0'; i++) + addch(*(s++)); +#endif /* not JP_CHARSET */ +} + +void +addnstr_sup(char *s, int n) +{ + int i; + +#ifdef JP_CHARSET + for (i = 0; i < n - 1 && *s != '\0'; i++) + addch(*(s++)); + if (*s != '\0') { + if (IS_KANJI2(*s)) { + /* WCHAR */ + if (CHMODE(CurrentMode) == C_WCHAR1) { + /* WCHAR second byte */ + addch(*s); + i++; + } + } + else { + /* Ascii or WCHAR2 */ + addch(*s); + i++; + } + } +#else /* not JP_CHARSET */ + for (i = 0; i < n && *s != '\0'; i++) + addch(*(s++)); +#endif /* not JP_CHARSET */ + for (; i < n; i++) + addch(' '); +} + +void +crmode(void) +#ifndef SGTTY +{ + ttymode_reset(ICANON, IXON); + ttymode_set(ISIG, 0); +#ifdef TERMIOS + set_cc(VMIN, 1); +#else /* not TERMIOS */ + set_cc(VEOF, 1); +#endif /* not TERMIOS */ +} +#else /* SGTTY */ +{ + ttymode_set(CBREAK, 0); +} +#endif /* SGTTY */ + +void +nocrmode(void) +#ifndef SGTTY +{ + ttymode_set(ICANON, 0); +#ifdef TERMIOS + set_cc(VMIN, 4); +#else /* not TERMIOS */ + set_cc(VEOF, 4); +#endif /* not TERMIOS */ +} +#else /* SGTTY */ +{ + ttymode_reset(CBREAK, 0); +} +#endif /* SGTTY */ + +void +term_echo(void) +{ + ttymode_set(ECHO, 0); +} + +void +term_noecho(void) +{ + ttymode_reset(ECHO, 0); +} + +void +term_raw(void) +#ifndef SGTTY +#ifdef IEXTEN +#define TTY_MODE ISIG|ICANON|ECHO|IEXTEN +#else /* not IEXTEN */ +#define TTY_MODE ISIG|ICANON|ECHO +#endif /* not IEXTEN */ +{ + ttymode_reset(TTY_MODE, IXON | IXOFF); +#ifdef TERMIOS + set_cc(VMIN, 1); +#else /* not TERMIOS */ + set_cc(VEOF, 1); +#endif /* not TERMIOS */ +} +#else /* SGTTY */ +{ + ttymode_set(RAW, 0); +} +#endif /* SGTTY */ + +void +term_cooked(void) +#ifndef SGTTY +{ +#ifdef __EMX__ + /* On XFree86/OS2, some scrambled characters + * will appear when asserting IEXTEN flag. + */ + ttymode_set((TTY_MODE)&~IEXTEN,0); +#else + ttymode_set(TTY_MODE, 0); +#endif +#ifdef TERMIOS + set_cc(VMIN, 4); +#else /* not TERMIOS */ + set_cc(VEOF, 4); +#endif /* not TERMIOS */ +} +#else /* SGTTY */ +{ + ttymode_reset(RAW, 0); +} +#endif /* SGTTY */ + +void +term_cbreak(void) +{ + term_cooked(); + term_noecho(); +} + +char +getch(void) +{ + char c; + + read(tty, &c, 1); + return c; +} + +#ifdef MOUSE +#ifdef USE_GPM +char +wgetch(void) +{ + char c; + + read(tty, &c, 1); + return c; +} + +int +do_getch() +{ + if (is_xterm) + return getch(); + else + return Gpm_Getch(); +} +#endif /* USE_GPM */ + +#ifdef USE_SYSMOUSE +int +sysm_getch() +{ + fd_set rfd; + int key, x, y; + + FD_ZERO(&rfd); + FD_SET(tty, &rfd); + while (select(tty + 1, &rfd, NULL, NULL, NULL) <= 0) { + if (errno == EINTR) { + x = xpix / cwidth; + y = ypix / cheight; + key = (*sysm_handler) (x, y, nbs, obs); + if (key != 0) + return key; + } + } + return getch(); +} + +int +do_getch() +{ + if (is_xterm) + return getch(); + else + return sysm_getch(); +} + +MySignalHandler +sysmouse(SIGNAL_ARG) +{ + struct mouse_info mi; + + mi.operation = MOUSE_GETINFO; + if (ioctl(tty, CONS_MOUSECTL, &mi) == -1) + return; + xpix = mi.u.data.x; + ypix = mi.u.data.y; + obs = nbs; + nbs = mi.u.data.buttons & 0x7; + /* for cosmetic bug in syscons.c on FreeBSD 3.[34] */ + mi.operation = MOUSE_HIDE; + ioctl(tty, CONS_MOUSECTL, &mi); + mi.operation = MOUSE_SHOW; + ioctl(tty, CONS_MOUSECTL, &mi); +} +#endif /* USE_SYSMOUSE */ +#endif /* MOUSE */ + +void +bell(void) +{ + write1(7); +} + +void +skip_escseq(void) +{ + int c; + + c = getch(); + if (c == '[' || c == 'O') { + c = getch(); + while (IS_DIGIT(c)) + c = getch(); + } +} + +void +sleep_till_anykey(int sec, int purge) +{ + fd_set rfd; + struct timeval tim; + int er, c; + TerminalMode ioval; + + TerminalGet(tty, &ioval); + term_raw(); + + tim.tv_sec = sec; + tim.tv_usec = 0; + + FD_ZERO(&rfd); + FD_SET(tty, &rfd); + + if (select(tty + 1, &rfd, 0, 0, &tim) > 0 && purge) { + c = getch(); + if (c == ESC_CODE) + skip_escseq(); + } + er = TerminalSet(tty, &ioval); + if (er == -1) { + printf("Error occured: errno=%d\n", errno); + reset_exit(SIGNAL_ARGLIST); + } +} + +#ifdef MOUSE + +#define XTERM_ON {fputs("\033[?1001s\033[?1000h",ttyf); flush_tty();} +#define XTERM_OFF {fputs("\033[?1000l\033[?1001r",ttyf); flush_tty();} + +#ifdef USE_GPM +/* Linux console with GPM support */ + +void +mouse_init() +{ + Gpm_Connect conn; + extern int gpm_process_mouse(Gpm_Event *, void *); + + if (mouseActive) + return; + if (is_xterm) { + XTERM_ON; + } + else { + conn.eventMask = ~0; + conn.defaultMask = 0; + conn.maxMod = 0; + conn.minMod = 0; + Gpm_Open(&conn, 0); /* don't care even if it fails */ + gpm_handler = gpm_process_mouse; + } + mouseActive = 1; +} + +void +mouse_end() +{ + if (mouseActive == 0) + return; + if (is_xterm) { + XTERM_OFF; + } + else + Gpm_Close(); + mouseActive = 0; +} + +#elif defined(USE_SYSMOUSE) +/* *BSD console with sysmouse support */ +void +mouse_init() +{ + mouse_info_t mi; + extern int sysm_process_mouse(); + + if (mouseActive) + return; + if (is_xterm) { + XTERM_ON; + } + else { +#if defined(FBIO_MODEINFO) || defined(CONS_MODEINFO) /* FreeBSD > 2.x */ +#ifndef FBIO_GETMODE /* FreeBSD 3.x */ +#define FBIO_GETMODE CONS_GET +#define FBIO_MODEINFO CONS_MODEINFO +#endif /* FBIO_GETMODE */ + video_info_t vi; + + if (ioctl(tty, FBIO_GETMODE, &vi.vi_mode) != -1 && + ioctl(tty, FBIO_MODEINFO, &vi) != -1) { + cwidth = vi.vi_cwidth; + cheight = vi.vi_cheight; + } +#endif /* defined(FBIO_MODEINFO) || + * defined(CONS_MODEINFO) */ + signal(SIGUSR2, SIG_IGN); + mi.operation = MOUSE_MODE; + mi.u.mode.mode = 0; + mi.u.mode.signal = SIGUSR2; + if (ioctl(tty, CONS_MOUSECTL, &mi) != -1) { + signal(SIGUSR2, sysmouse); + mi.operation = MOUSE_SHOW; + ioctl(tty, CONS_MOUSECTL, &mi); + sysm_handler = sysm_process_mouse; + } + } + mouseActive = 1; +} + +void +mouse_end() +{ + if (mouseActive == 0) + return; + if (is_xterm) { + XTERM_OFF; + } + else { + mouse_info_t mi; + mi.operation = MOUSE_MODE; + mi.u.mode.mode = 0; + mi.u.mode.signal = 0; + ioctl(tty, CONS_MOUSECTL, &mi); + } + mouseActive = 0; +} + +#else +/* not GPM nor SYSMOUSE, but use mouse with xterm */ + +void +mouse_init() +{ + if (mouseActive) + return; + if (is_xterm) { + XTERM_ON; + } + mouseActive = 1; +} + +void +mouse_end() +{ + if (mouseActive == 0) + return; + if (is_xterm) { + XTERM_OFF; + } + mouseActive = 0; +} + +#endif /* not USE_GPM nor USE_SYSMOUSE */ + + +void +mouse_active() +{ + if (!mouseActive) + mouse_init(); +} + +void +mouse_inactive() +{ + if (mouseActive && is_xterm) + mouse_end(); +} + +#endif /* MOUSE */ + +void +flush_tty() +{ + fflush(ttyf); +} |