精華區beta SetupBBS 關於我們 聯絡資訊
/*-------------------------------------------------------*/ /* screen.c ( NTHU CS MapleBBS Ver 2.36 ) */ /*-------------------------------------------------------*/ /* target : ANSI/Chinese screen display routines */ /* create : 95/03/29 */ /* update : 95/12/15 */ /*-------------------------------------------------------*/ #include <varargs.h> #include "bbs.h" extern char clearbuf[]; extern char cleolbuf[]; extern char scrollrev[]; extern char strtstandout[]; extern char endstandout[]; extern int clearbuflen; extern int cleolbuflen; extern int scrollrevlen; extern int strtstandoutlen; extern int endstandoutlen; extern int automargins; extern int dumb_term; extern void ochar(); extern void output(); #define o_clear() output(clearbuf,clearbuflen) #define o_cleol() output(cleolbuf,cleolbuflen) #define o_scrollrev() output(scrollrev,scrollrevlen) #define o_standup() output(strtstandout,strtstandoutlen) #define o_standdown() output(endstandout,endstandoutlen) uschar scr_lns, scr_cols; uschar cur_ln = 0, cur_col = 0; uschar docls, downfrom = 0; uschar standing = NA; char roll = 0; int scrollcnt, tc_col, tc_line; screenline *big_picture = NULL; void initscr() { if (!dumb_term && !big_picture) { extern char *calloc(); scr_lns = t_lines; scr_cols = t_columns = ANSILINELEN; /* scr_cols = MIN(t_columns, ANSILINELEN); */ big_picture = (screenline *) calloc(scr_lns, sizeof(screenline)); docls = YEA; } } void move(y, x) { cur_col = x; cur_ln = y; } void getyx(y, x) int *y, *x; { *y = cur_ln; *x = cur_col; } static void rel_move(was_col, was_ln, new_col, new_ln) { extern char *BC; if (new_ln >= t_lines || new_col >= t_columns) return; tc_col = new_col; tc_line = new_ln; if (new_col == 0) { if (new_ln == was_ln) { if (was_col) ochar('\r'); return; } else if (new_ln == was_ln + 1) { ochar('\n'); if (was_col) ochar('\r'); return; } } if (new_ln == was_ln) { if (was_col == new_col) return; if (new_col == was_col - 1) { if (BC) tputs(BC, 1, ochar); else ochar(Ctrl('H')); return; } } do_move(new_col, new_ln); } static void standoutput(buf, ds, de, sso, eso) char *buf; int ds, de, sso, eso; { if (eso <= ds || sso >= de) { output(buf + ds, de - ds); } else { int st_start, st_end; st_start = MAX(sso, ds); st_end = MIN(eso, de); if (sso > ds) output(buf + ds, sso - ds); o_standup(); output(buf + st_start, st_end - st_start); o_standdown(); if (de > eso) output(buf + eso, de - eso); } } void redoscr() { register screenline *bp; register int i, j, len; if (dumb_term) return; o_clear(); for (tc_col = tc_line = i = 0, j = roll; i < scr_lns; i++, j++) { if (j >= scr_lns) j = 0; bp = &big_picture[j]; if (len = bp->len) { rel_move(tc_col, tc_line, 0, i); if (bp->mode & STANDOUT) standoutput(bp->data, 0, len, bp->sso, bp->eso); else output(bp->data, len); tc_col += len; if (tc_col >= t_columns) { if (automargins) tc_col = t_columns - 1; else { tc_col -= t_columns; tc_line++; if (tc_line >= t_lines) tc_line = b_lines; } } bp->mode &= ~(MODIFIED); bp->oldlen = len; } } rel_move(tc_col, tc_line, cur_col, cur_ln); docls = scrollcnt = 0; oflush(); } void refresh() { register screenline *bp = big_picture; register int i, j, len; extern int automargins; extern int scrollrevlen; if (dumb_term) return; if (num_in_buf()) return; if ((docls) || (abs(scrollcnt) >= (scr_lns - 3))) { redoscr(); return; } if (scrollcnt < 0) { if (!scrollrevlen) { redoscr(); return; } rel_move(tc_col, tc_line, 0, 0); do { o_scrollrev(); } while (++scrollcnt); } else if (scrollcnt > 0) { rel_move(tc_col, tc_line, 0, b_lines); do { ochar('\n'); } while (--scrollcnt); } for (i = 0, j = roll; i < scr_lns; i++, j++) { if (j >= scr_lns) j = 0; bp = &big_picture[j]; len = bp->len; if (bp->mode & MODIFIED && bp->smod < len) { bp->mode &= ~(MODIFIED); if (bp->emod >= len) bp->emod = len - 1; rel_move(tc_col, tc_line, bp->smod, i); if (bp->mode & STANDOUT) standoutput(bp->data, bp->smod, bp->emod + 1, bp->sso, bp->eso); else output(&bp->data[bp->smod], bp->emod - bp->smod + 1); tc_col = bp->emod + 1; if (tc_col >= t_columns) { if (automargins) { tc_col -= t_columns; if (++tc_line >= t_lines) tc_line = b_lines; } else tc_col = t_columns - 1; } } if (bp->oldlen > len) { rel_move(tc_col, tc_line, len, i); o_cleol(); } bp->oldlen = len; } rel_move(tc_col, tc_line, cur_col, cur_ln); oflush(); } void clear() { if (!dumb_term) { register int i; docls = YEA; cur_col = cur_ln = roll = downfrom = i = 0; do { #if 0 memset(&big_picture[i], 0, 3); #else register screenline *slp; slp = &big_picture[i]; slp->mode = slp->len = slp->oldlen = 0; #endif } while (++i < scr_lns); } } void clrtoeol() { if (!dumb_term) { register screenline *slp; register int ln; standing = NA; if ((ln = cur_ln + roll) >= scr_lns) ln -= scr_lns; slp = &big_picture[ln]; if (cur_col <= slp->sso) slp->mode &= ~STANDOUT; if (cur_col > slp->oldlen) { for (ln = slp->len; ln <= cur_col; ln++) slp->data[ln] = ' '; } if (cur_col < slp->oldlen) { for (ln = slp->len; ln >= cur_col; ln--) slp->data[ln] = ' '; } slp->len = cur_col; } } #if 0 void clrline() { if (!dumb_term) { register screenline *slp; int i; if ((i = cur_ln + roll) >= scr_lns) i -= scr_lns; slp = &big_picture[i]; cur_col = slp->mode = slp->len = 0; if (slp->oldlen) slp->oldlen = 255; } } #endif void clrtobot() { if (!dumb_term) { register screenline *slp; register int i, j; for (i = cur_ln, j = i + roll; i < scr_lns; i++, j++) { if (j >= scr_lns) j -= scr_lns; slp = &big_picture[j]; slp->mode = slp->len = 0; if (slp->oldlen) slp->oldlen = 255; } } } #if 0 void clrstandout() { if (!dumb_term) { register int i; for (i = 0; i < scr_lns; i++) big_picture[i].mode &= ~(STANDOUT); } } #endif void outch(c) register uschar c; { register screenline *slp; register int i; #ifndef BIT8 c &= 0x7f; #endif if (dumb_term) { #ifdef BIT8 if ((c != '') && !isprint2(c)) #else if (!isprint(c)) #endif { if (c == '\n') ochar('\r'); else c = '*'; } ochar(c); return; } if ((i = cur_ln + roll) >= scr_lns) i -= scr_lns; slp = &big_picture[i]; #ifdef BIT8 if ((c != '') && !isprint2(c)) #else if (!isprint(c)) #endif { if (c == '\n' || c == '\r') { if (standing) { slp->eso = MAX(slp->eso, cur_col); standing = NA; } #if 1 if ((i = cur_col - slp->len) > 0) memset(&slp->data[slp->len], ' ', i + 1); #else if (cur_col > slp->len) { for (i = slp->len; i <= cur_col; i++) slp->data[i] = ' '; } #endif slp->len = cur_col; cur_col = 0; if (cur_ln < scr_lns) cur_ln++; return; } c = '*'; /* substitute a '*' for non-printable */ } if (cur_col >= slp->len) { for (i = slp->len; i < cur_col; i++) slp->data[i] = ' '; slp->data[cur_col] = '\0'; slp->len = cur_col + 1; } if (slp->data[cur_col] != c) { slp->data[cur_col] = c; if ((slp->mode & MODIFIED) != MODIFIED) slp->smod = slp->emod = cur_col; slp->mode |= MODIFIED; if (cur_col > slp->emod) slp->emod = cur_col; if (cur_col < slp->smod) slp->smod = cur_col; } if (++cur_col >= scr_cols) { if (standing && (slp->mode & STANDOUT)) { standing = 0; slp->eso = MAX(slp->eso, cur_col); } cur_col = 0; if (cur_ln < scr_lns) cur_ln++; } } static void parsecolor(buf) char *buf; { char *val; char data[24]; data[0] = '\0'; val = (char *) strtok(buf, ";"); while (val) { if (atoi(val) < 30) { if (data[0]) strcat(data, ";"); strcat(data, val); } val = (char *) strtok(NULL, ";"); } strcpy(buf, data); } #define NORMAL (00) #define ESCAPE (01) #define VTKEYS (02) void outc(ch) register unsigned char ch; { if (showansi) outch(ch); else { static char buf[24]; static int p = 0; static int mode = NORMAL; int i; switch (mode) { case NORMAL: if (ch == '\033') mode = ESCAPE; else outch(ch); return; case ESCAPE: if (ch == '[') mode = VTKEYS; else { mode = NORMAL; outch(''); outch(ch); } return; case VTKEYS: if (ch == 'm') { buf[p++] = '\0'; parsecolor(buf); } else if ((p < 24) && (not_alpha(ch))) { buf[p++] = ch; return; } if (buf[0]) { outch(''); outch('['); for (i = 0; p = buf[i]; i++) outch(p); outch(ch); } p = 0; mode = NORMAL; } } } void outs(str) register char *str; { while (*str) outc(*str++); } void outmsg(msg) register char *msg; { move(b_lines, 0); clrtoeol(); while (*msg) outc(*msg++); } void prints(va_alist) va_dcl { va_list args; char buff[512], *fmt; va_start(args); fmt = va_arg(args, char *); vsprintf(buff, fmt, args); va_end(args); outs(buff); } void scroll() { if (dumb_term) { outc('\n'); } else { scrollcnt++; if (++roll >= scr_lns) roll = 0; move(b_lines, 0); clrtoeol(); } } void rscroll() { if (dumb_term) { outs("\n\n"); } else { scrollcnt--; if (--roll < 0) roll = b_lines; move(0, 0); clrtoeol(); } } region_scroll_up(int top, int bottom) { int i; if (top > bottom) { i = top; top = bottom; bottom = i; } if (top < 0 || bottom >= scr_lns) return; for (i = top; i < bottom; i++) big_picture[i] = big_picture[i + 1]; memset(big_picture + i, 0, sizeof(*big_picture)); memset(big_picture[i].data, ' ', scr_cols); save_cursor(); change_scroll_range(top, bottom); do_move(0, bottom); scroll_forward(); change_scroll_range(0, scr_lns - 1); restore_cursor(); refresh(); } region_scroll_down(int top, int bottom) { } void standout() { if (!standing && !dumb_term && strtstandoutlen) { register screenline *slp; slp = &big_picture[((cur_ln + roll) % scr_lns)]; standing = YEA; slp->sso = slp->eso = cur_col; slp->mode |= STANDOUT; } } void standend() { if (standing && !dumb_term && strtstandoutlen) { register screenline *slp; slp = &big_picture[((cur_ln + roll) % scr_lns)]; standing = NA; slp->eso = MAX(slp->eso, cur_col); } } #if 0 void outns(str, n) register char *str; register int n; { while (n--) outc(*str++); } void chcxy(type) int type; { static backup_x; static backup_y; if (type == 0) { /* backup */ backup_x = cur_col; backup_y = cur_ln; } else { /* restore */ cur_col = backup_x; cur_ln = backup_y; } } #endif