📄 window.c
字号:
/* * window.c Very portable window routines. * Currently this code is used in _both_ the BBS * system and minicom. * * Author: Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org> * */#include <sys/types.h>#if defined(_MINIX) || defined(linux)# include <termcap.h>#elsechar *tgetstr(), *tgoto();int tgetent(), tputs(), tgetnum(), tgetflag();#endif#include <string.h>#if defined (_POSIX_SOURCE) || defined(_BSD43)# include <stdlib.h># include <unistd.h>#else char *getenv();#endif#include "charmap.h"/* Don't want to include all header stuff for three prototypes from sysdep.c */#if __STDC__ int setcbreak(int); int getch(void); void getrowcols(int *rows, int *cols);#else int setcbreak(); int getch(); void getrowcols();#endif#if 0 /* Should use it in wprintf */#ifdef _MINIX# include <stdarg.h>#else# include <varargs.h>#endif#endif#include <stdio.h>#include <signal.h>#include "window.h"#ifndef BBS#include "config.h"#endif#define BUFFERSIZE 2048#define swap(x, y) { int d = (x); (x) = (y); (y) = d; }/* Terminal capabilities */static char *CM, *IS, *RS;static char *ME, *SE, *UE, *AE;static char *AS, *MB, *MD, *MR, *SO, *US;static char *CE, *Al, *Dl, *AL, *DL;static char *CS, *SF, *SR, *VB;static char *VE, *VI, *KS, *KE;static char *CD, *CL, *IC, *DC;static char *BC, *CR, *NL;/* Special characters */static char D_UL;static char D_HOR;static char D_UR;static char D_LL;static char D_VER;static char D_LR;static char S_UL;static char S_HOR;static char S_UR;static char S_LL;static char S_VER;static char S_LR;static char _bufstart[BUFFERSIZE];static char *_bufpos = _bufstart;static char *_buffend;static ELM *gmap;static char curattr = -1;static char curcolor = -1;static int curx = -1;static int cury = -1;static int _intern = 0;static int _curstype = CNORMAL;static int _has_am = 0;static int _mv_standout = 0;static ELM oldc;static int sflag = 0;/* * Smooth is only defined for slow machines running Minicom. * With this defined, Minicom will buffer only per-line * and the output will look much less 'jerky'. (I hope :-) */#ifdef SMOOTHstatic WIN *curwin = NIL_WIN;extern WIN *us;#endifint useattr = 1;int dirflush = 1;int LINES, COLS;int usecolor = 0;WIN *stdwin;char *_tptr = CNULL;int literal = 0;int w_init = 0;#if DEBUG/* * Debug to stdout */int debug(s, a1, a2, a3, a4)char *s;int a1, a2, a3, a4;{ char lala[80]; sprintf(lala, s, a1, a2, a3, a4); write(2, lala, strlen(lala)); return(0);}#endif/* ===== Low level routines ===== *//* * Flush the screen buffer */void wflush(){ register int todo, done; todo = _bufpos - _bufstart; _bufpos = _bufstart; while(todo > 0) { done = write(1, _bufpos, todo); if (done > 0) { todo -= done; _bufpos += done; } } _bufpos = _bufstart;}/* * Output a raw character to the screen */static int outchar(c)int c;{ *_bufpos++ = c; if (_bufpos >= _buffend) wflush();#if defined(SMOOTH) if (curwin == us && (c == '\n' || c == '\r')) wflush();#endif return(0);}/* * Output a raw string to the screen. */static void outstr(s)char *s;{#ifdef _MINIX while(*s) (void) outchar (*s++);#else tputs(s, 1, outchar);#endif}/* * Turn off all attributes */static void _attroff(){ if (ME != CNULL) outstr(ME); else { if (SE != CNULL) outstr(SE); if (UE != CNULL) outstr(UE); } if (AE != CNULL) outstr(AE);}/* * Turn some attributes on */static void _attron(attr)char attr;{ if (!usecolor || (attr & A_REVERSE) == 0) { /* Reverse standout does not look too good.. */ if (attr & A_BOLD && MD != CNULL) outstr(MD); if (attr & A_STANDOUT && SO != CNULL) outstr(SO); if (attr & A_UNDERLINE && US != CNULL) outstr(US); } if (attr & A_REVERSE && MR != CNULL) outstr(MR); if (attr & A_ALTCHARSET && AS != CNULL) outstr(AS); if (attr & A_BLINK && MB != CNULL) outstr(MB);}/* * Set the colors */static void _colson(color)char color;{ char buf[12]; sprintf(buf, "\033[%d;%dm", COLFG(color) + 30, COLBG(color) + 40); outstr(buf);} /* * Set global attributes, if different. */static void _setattr(attr, color)char attr, color;{ if (!useattr) return; if (!usecolor) { curcolor = color; if (attr == curattr) return; curattr = attr; _attroff(); _attron(attr); return; } if (attr == curattr && color == curcolor) return; _attroff(); _colson(color); _attron(attr); curattr = attr; curcolor = color;}/* * Goto (x, y) in stdwin */static void _gotoxy(x, y)int x, y;{ register oldattr = -1; if (x < COLS && y < LINES && (x != curx || y != cury)) { if (!_mv_standout && curattr != A_NORMAL) { oldattr = curattr; _setattr(A_NORMAL, curcolor); } if (CR != CNULL && y == cury && x == 0) outstr(CR);#if 0 /* Hmm, sometimes NL only works in the first column */ else if (NL != CNULL && x == curx && y == cury + 1) outstr(NL);#else else if (NL != CNULL && x == 0 && x == curx && y == cury + 1) outstr(NL);#endif else if (BC != CNULL && y == cury && x == curx - 1) outstr(BC); else outstr(tgoto(CM, x, y)); curx = x; cury = y; if (oldattr != -1) _setattr(oldattr, curcolor); } }/* * Write a character in stdwin at x, y with attr & color * 'doit' can be -1: only write to screen, not to memory * 0: only write to memory, not to screen * 1: write to both screen and memory */static void _write(c, doit, x, y,attr, color)int c, doit;int x, y;char attr, color;{ register ELM *e; /* If the terminal has automatic margins, we can't write to the * last line, last character. After scrolling, this "invisible" * character is automatically restored. */ if (_has_am && y >= LINES - 1 && x >= COLS - 1) { doit = 0; sflag = 1; oldc.value = c; oldc.attr = attr; oldc.color = color; } if (x < COLS && y < LINES) { if (doit != 0) { _gotoxy(x, y); _setattr(attr, color);#ifdef _ACK c &= 0xFF;#endif (void) outchar(literal ? c : wcharmap[(unsigned char)c]); curx++; } if (doit >= 0) { e = &gmap[x + y * COLS]; e->value = c; e->attr = attr; e->color = color; } }}/* * Set cursor type. */static void _cursor(type)int type;{ _curstype = type; if (type == CNORMAL && VE != CNULL) outstr(VE); if (type == CNONE && VE != CNULL && VI != CNULL) outstr(VI);}/* ==== High level routines ==== */#if 0/* This code is functional, but not yet used. * It might be one day.... *//* * Resize a window */void wresize(win, lines, cols)WIN *win;int lines, cols;{ int x, y; ELM *oldmap, *newmap, *e, *n; if ((newmap = (ELM *)malloc(lines * cols * sizeof(ELM))) == (ELM *)NULL) return; if (win == stdwin) oldmap = gmap; else oldmap = win->map; for(y = 0; y < lines; y++) for(x = 0; x < cols; x++) { n = &newmap[y + x * cols]; if (x < win->xs && y < win->ys) { e = &oldmap[y + x * COLS]; n->value = e->value; n->color = e->color; n->attr = e->attr; } else { n->value = ' '; n->color = win->color; n->attr = win->attr; } } if (win->sy2 == win->y2) win->sy2 = win->y1 + lines - 1; win->y2 = win->y1 + lines - 1; win->ys = lines; win->xs = cols; free(oldmap); if (win == stdwin) { gmap = newmap; LINES = lines; COLS = cols; } else win->map = newmap;}#endif/* * Create a new window. *//*ARGSUSED*/WIN *wopen(x1, y1, x2, y2, border, attr, fg, bg, direct, histlines, rel)int x1, y1, x2, y2;int border;int attr, fg, bg, direct;int histlines;int rel;{ WIN *w; ELM *e; int bytes; int x, y; int color; int offs; int doclr = 1; /* Could later be added as argument to func */#ifdef SMOOTH curwin = NIL_WIN;#endif if ((w = (WIN *)malloc(sizeof(WIN))) == (WIN *)0) return(w); offs = (border != BNONE); if (x1 < offs) x1 = offs; if (y1 < offs) y1 = offs;#if 0 if (x2 >= COLS - offs) x2 = COLS - offs - 1; if (y2 >= LINES - offs) y2 = LINES - offs - 1;#endif if (x1 > x2) swap(x1, x2); if (y1 > y2) swap(y1, y2); w->xs = x2 - x1 + 1; w->ys = y2 - y1 + 1; w->x1 = x1; w->x2 = x2; w->y1 = w->sy1 = y1; w->y2 = w->sy2 = y2; w->doscroll = 1; w->border = border; w->cursor = CNORMAL; w->attr = attr; w->autocr = 1; w->wrap = 1; color = w->color = COLATTR(fg, bg); w->curx = 0; w->cury = 0; w->o_curx = curx; w->o_cury = cury; w->o_attr = curattr; w->o_color = curcolor; w->o_cursor = _curstype; w->direct = direct; if (border != BNONE) { x1--; x2++; y1--; y2++; } /* Store whatever we are overlapping */ bytes = (y2 - y1 + 1) * (x2 - x1 + 1) * sizeof(ELM) + 100; if ((e = (ELM *)malloc(bytes)) == (ELM *)0) { free(w); return((WIN *)0); } w->map = e; /* How many bytes is one line */ bytes = (x2 - x1 + 1) * sizeof(ELM); /* Loop */ for(y = y1; y <= y2; y++) { memcpy(e, gmap + COLS * y + x1, bytes); e += (x2 - x1 + 1); } #if HISTORY /* Do we want history? */ w->histline = w->histlines = 0; w->histbuf = (ELM *)0; if (histlines) { /* Reserve some memory. */ bytes = w->xs * histlines * sizeof(ELM); if ((w->histbuf = (ELM *)malloc(bytes)) == NULL) { free(w->map); free(w); return((WIN *)0); } w->histlines = histlines; /* Clear the history buf. */ e = w->histbuf; for(y = 0; y < w->xs * histlines; y++) { e->value = ' '; e->attr = attr; e->color = color; e++; } }#endif /* And draw the window */ if (border) { _write(border == BSINGLE ? S_UL : D_UL, w->direct, x1, y1, attr, color); for(x = x1 + 1; x < x2; x++) _write(border == BSINGLE ? S_HOR : D_HOR, w->direct, x, y1, attr, color); _write(border == BSINGLE ? S_UR : D_UR, w->direct, x2, y1, attr, color); for(y = y1 + 1; y < y2; y++) { _write(border == BSINGLE ? S_VER : D_VER, w->direct, x1, y, attr, color); for(x = x1 + 1; x < x2; x++) _write(' ', w->direct, x, y, attr, color); _write(border == BSINGLE ? S_VER : D_VER, w->direct, x2, y, attr, color); } _write(border == BSINGLE ? S_LL : D_LL, w->direct, x1, y2, attr, color); for(x = x1 + 1; x < x2; x++) _write(border == BSINGLE ? S_HOR : D_HOR, w->direct, x, y2, attr, color); _write(border == BSINGLE ? S_LR : D_LR, w->direct, x2, y2, attr, color); if (w->direct) _gotoxy(x1 + 1, y1 + 1); } else if (doclr) winclr(w); wcursor(w, CNORMAL); if (w->direct) wflush(); return(w);}/* * Close a window. */void wclose(win, replace)WIN *win;int replace;{ register ELM *e; register int x, y;#ifdef SMOOTH curwin = NIL_WIN;#endif if (win == stdwin) { win_end(); return; } e = win->map; if (win->border) { win->x1--; win->x2++; win->y1--; win->y2++; } wcursor(win, win->o_cursor); if (replace) { for(y = win->y1; y <= win->y2; y++) { for(x = win->x1; x <= win->x2; x++) { _write(e->value, 1, x, y, e->attr, e->color); e++; } } _gotoxy(win->o_curx, win->o_cury); _setattr(win->o_attr, win->o_color); } free(win->map); free(win);#if HISTORY if (win->histbuf) free(win->histbuf);#endif wflush();}static int oldx, oldy;static int ocursor;/* * Clear screen & restore keyboard modes */void wleave(){ oldx = curx; oldy = cury; ocursor = _curstype; (void) setcbreak(0); /* Normal */ _gotoxy(0, LINES - 1); _setattr(A_NORMAL, COLATTR(WHITE, BLACK)); _cursor(CNORMAL); if (CL != CNULL) outstr(CL); else outstr("\n"); if (KE != CNULL) outstr(KE); if (RS != CNULL) outstr(RS); wflush();}void wreturn(){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -