/* vi: set sw=4 ts=4: */ /* * KON2 - Kanji ON Console - * Copyright (C) 1992, 1993 MAEDA Atusi (mad@math.keio.ac.jp) * Copyright (C) 1992-1996 Takashi MANABE (manabe@papilio.tutics.tut.ac.jp) * * CCE - Console Chinese Environment - * Copyright (C) 1998-2003 Rui He (rhe@3eti.com) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include #include #include #include #include #include #include "defs.h" #include "errors.h" #include "getcap.h" #include "font.h" #include "mouse.h" #include "vtcon.h" #include "vc.h" #include "term.h" #include "key.h" #include "hzinput.h" #include "vga.h" #include "fb.h" #include "encfilter.h" #ifdef HAVE_SYS_IOCTL_H #include #endif DispInfo dispInfo; CursorInfo cursorInfo; VideoInfo *pVideoInfo = NULL; CursorInfo mouseCursor; static char DisplayName[10]; /* VGA or S3 or... buffer overflow? */ #define CCE_HANDLE_VTSWITCH (StartFromConsole && dispInfo.type != TYPE_SDL) int text_mode = FALSE; int curActive = FALSE; static volatile bool busy; /* TRUE iff updating screen */ static volatile bool release; /* delayed VC switch flag */ static void ShowCursor(CursorInfo *, bool); static void LeaveVC(int); static void EnterVC(int); static void TextClearBand(ConInfo *con, int top, int btm); #define CCE_MOUSE_TMPFILE "/.cCeMsEtMp" /* should we use file or memory to do it? */ static char tmpFileName[CCE_PATHNAME_MAX]; /* Fix deprecated cast-as-lvalue, which will cause warnings in GCC >= 3.3.4 */ static inline void blatch(void *head, int n) { while (n-- > 0) { /* (*(unsigned char *)head) &= (unsigned char)0x7F; ((unsigned char *)head)++; */ unsigned char *temp = (unsigned char *)head; *temp &= (unsigned char)0x7F; head = temp; head = (unsigned char *)head + 1; } } static inline void llatch(void *head, int n) { n >>= 2; /* convert into 32 bits */ while (n-- > 0) { /* (*(unsigned int *)head) &= (unsigned long)0x7F7F7F7F; ((unsigned int *)head)++; */ unsigned int *temp = (unsigned int *)head; *temp &= (unsigned long)0x7F7F7F7F; head = temp; head = (unsigned int *)head + 1; } } static inline bool IsKanji(ConInfo *con,u_int x, u_int y) { return(*(con->flagBuff + TextAddress(con,x, y)) & CODEIS_1); } static inline bool IsKanji2(ConInfo *con,u_int x, u_int y) { return(*(con->flagBuff + TextAddress(con,x, y)) & CODEIS_2); } void TextDeleteChar(ConInfo *con, int n) { u_int addr, dx; addr = TextAddress(con, con->x, con->y); dx = dispInfo.txmax - con->x - n; #ifdef DEBUG #endif bmove(con->textBuff + addr, con->textBuff + addr + n, dx); bmove(con->attrBuff + addr, con->attrBuff + addr + n, dx); blatch(con->flagBuff + addr, dx); addr = TextAddress(con, dispInfo.txmax - n, con->y); memset(con->textBuff + addr, 0x20, n); memset(con->attrBuff + addr, (con->bcol << 4) | con->fcol, n); bzero2(con->flagBuff + addr, n); } void TextInsertChar(ConInfo *con,int n) { u_int addr, dx; addr = TextAddress(con, dispInfo.txmax, con->y); /* txmax for example, 128 */ dx = dispInfo.txmax - con->x - n; #ifdef DEBUG #endif brmove(con->textBuff + addr, con->textBuff + addr - n, dx); brmove(con->attrBuff + addr, con->attrBuff + addr - n, dx); addr = TextAddress(con,con->x, con->y); blatch(con->flagBuff + addr + n, dx); memset(con->textBuff + addr, 0x20, n); memset(con->attrBuff + addr, (con->bcol << 4) | con->fcol, n); bzero2(con->flagBuff + addr, n); } void TextMoveUp(ConInfo *con,int top, int btm, int line) { int n, src, dst; if (btm - top - line + 1 <= 0) { TextClearBand(con,top, btm); return; } for (n = top; n <= btm - line; n ++) { dst = TextAddress(con,0, n); src = TextAddress(con,0, n + line); lmove(con->textBuff + dst, con->textBuff + src, dispInfo.txmax); lmove(con->attrBuff + dst, con->attrBuff + src, dispInfo.txmax); lmove(con->flagBuff + dst, con->flagBuff + src, dispInfo.txmax); llatch(con->flagBuff + dst, dispInfo.txmax); } TextClearBand(con,btm - line + 1, btm); } void TextMoveDown(ConInfo *con,int top, int btm, int line) { int n, src, dst; if (btm - top - line + 1 <= 0) { TextClearBand(con,top, btm); return; } for (n = btm; n >= top + line; n --) { dst = TextAddress(con,0, n); src = TextAddress(con,0, n - line); lmove(con->textBuff + dst, con->textBuff + src, dispInfo.txmax); lmove(con->attrBuff + dst, con->attrBuff + src, dispInfo.txmax); lmove(con->flagBuff + dst, con->flagBuff + src, dispInfo.txmax); llatch(con->flagBuff + dst, dispInfo.txmax); } TextClearBand(con,top, top + line - 1); } void ScrollUp(ConInfo *con,int line) { { TextMoveUp(con, con->ymin, con->ymax, line); } } void ScrollDown(ConInfo *con,int line) { { TextMoveDown(con,con->ymin, con->ymax, line); } } void TextClearAll(ConInfo *con) { memset(con->textBuff, 0x20, con->textSize); memset(con->attrBuff, ((con->bcol << 4) | con->fcol), con->textSize); lzero(con->flagBuff, con->textSize); mInfo.sw = 0; con->textClear = TRUE; } void TextClearEol(ConInfo *con,u_char mode) { u_int addr; u_char len, x=0; switch(mode) { case 1: /* erase from start of line to cursor(including cursor) */ len = con->x + 1; /* Rui He Sep 28 fixed, added 1 */ break; case 2: /* erase whole line */ len = dispInfo.txmax; /* 80/128 etc */ break; default: /* 0 erase from cursor to end of line */ x = con->x; len = dispInfo.txmax - con->x; break; } addr = TextAddress(con, x, con->y); memset(con->textBuff + addr, 0x20, len); memset(con->attrBuff + addr, (con->bcol << 4) | con->fcol, len); bzero2(con->flagBuff + addr, len);/* needless to latch */ } void TextClearEos(ConInfo *con,u_char mode) { int addr, len, y; if (mode == 2) { TextClearAll(con); return; } switch(mode) { case 1: for (y = 0; y < con->y; y ++) { addr = TextAddress(con,0, y); memset(con->textBuff + addr, 0x20, dispInfo.txmax); memset(con->attrBuff + addr, (con->bcol << 4) | con->fcol, dispInfo.txmax); lzero(con->flagBuff + addr, dispInfo.txmax); } addr = TextAddress(con,0, con->y); memset(con->textBuff + addr, 0x20, con->x); memset(con->attrBuff + addr, (con->bcol << 4) | con->fcol, con->x); bzero2(con->flagBuff + addr, con->x); /* needless to latch */ break; default: for (y = con->y + 1; y < dispInfo.tymax; y ++) { addr = TextAddress(con,0, y); memset(con->textBuff + addr, 0x20, dispInfo.txmax); memset(con->attrBuff + addr, (con->bcol << 4) | con->fcol, dispInfo.txmax); lzero(con->flagBuff + addr, dispInfo.txmax); } addr = TextAddress(con,con->x, con->y); len = dispInfo.txmax - con->x; memset(con->textBuff + addr, 0x20, len); memset(con->attrBuff + addr, (con->bcol << 4) | con->fcol, len); bzero2(con->flagBuff + addr, len); /* needless to latch */ break; } } static void TextClearBand(ConInfo *con, int top, int btm) { int y, addr; for (y = top; y <= btm; y ++) { addr = TextAddress(con,0, y); memset(con->textBuff + addr, 0x20, dispInfo.txmax); memset(con->attrBuff + addr, (con->bcol << 4) | con->fcol, dispInfo.txmax); lzero(con->flagBuff + addr, dispInfo.txmax);/* needless to latch */ } } void TextClearChars(ConInfo * con, int len) { int addr; if ( con->x + len > dispInfo.txmax ) len = dispInfo.txmax - con->x; addr = TextAddress(con, con->x, con->y); memset(con->textBuff + addr, 0x20, len); memset(con->attrBuff + addr, (con->bcol << 4) | con->fcol, len); bzero2(con->flagBuff + addr, len); /* needless to latch */ } static inline void KanjiAdjust(ConInfo *con,int *x, int *y) { if (IsKanji2(con,*x, *y)) { --*x; } } static u_char paste_buff[256]; void TextCopy(ConInfo *con,int fx, int fy, int tx, int ty) { int fd; int from, to, y, swp, xx, x; u_char ch, ch2; int buff_len = 0; unlink(tmpFileName); if ((fd = open(tmpFileName, O_WRONLY|O_CREAT, 0600)) < 0) { return; } KanjiAdjust(con,&fx, &fy); KanjiAdjust(con,&tx, &ty); if (fy > ty) { swp = fy; fy = ty; ty = swp; swp = fx; fx = tx; tx = swp; } else if (fy == ty && fx > tx) { swp = fx; fx = tx; tx = swp; } xx = dispInfo.txmax-1; for (y = fy; y <= ty; y ++) { if (y == ty) xx = tx; from = TextAddress(con,fx, y); if (con->flagBuff[from] & CODEIS_2) from--; to = TextAddress(con,xx, y); for (x = to; x >= from; x --) if (con->textBuff[x] > ' ') break; to = x; for (x = from; x <= to; x++) { ch = con->textBuff[x]; if (!ch) ch = ' '; if (con->flagBuff[x] & CODEIS_1) { x++; ch2 = con->textBuff[x]; switch(lInfo.sysCoding) { case CODE_EUC: ch2 |= 0x80; ch |= 0x80; break; case CODE_SJIS: jistosjis(ch, ch2); break; } paste_buff[buff_len++] = ch; paste_buff[buff_len++] = ch2; } else paste_buff[buff_len++] = ch; if (buff_len >= sizeof(paste_buff)-4) /* leave some room for '\n' below and next two bytes */ { #ifdef SUPPORT_ENCODING_FILTER if (UseEncodingFilter) { buff_len = DoEncodingFilter(CONVERT_TO_FILTER, paste_buff, buff_len); if (EncodingFilterLen > 0) write(fd, EncodingFilterBuff, EncodingFilterLen); } else #endif { write(fd, paste_buff, buff_len); buff_len = 0; } } } /* for x */ if (y < ty) { paste_buff[buff_len++] = '\n'; } fx = 0; } /* for xx */ if (buff_len > 0) { #ifdef SUPPORT_ENCODING_FILTER if (UseEncodingFilter) /* converted from native to target filter encoding */ { buff_len = DoEncodingFilter(CONVERT_TO_FILTER, paste_buff, buff_len); if (EncodingFilterLen > 0) write(fd, EncodingFilterBuff, EncodingFilterLen); } else #endif write(fd, paste_buff, buff_len); /* write the remaining */ } close(fd); } void TextPaste(ConInfo *con) { /* u_char ch; */ int fd, i; size_t nRead; if ((fd = open(tmpFileName, O_RDONLY)) < 0) return; while( (nRead = read(fd, paste_buff, sizeof(paste_buff))) > 0) { for(i = 0; i < nRead; i++) { if (paste_buff[i] == 0xa) /* necessary? */ paste_buff[i] = 0xd; /* Line bug.. */ } write(con->masterPty, paste_buff, nRead); } close(fd); } void TextReverse(ConInfo *con,int fx, int fy, int tx, int ty) { int from, to, y, swp, xx, x; u_char fc, bc, fc2, bc2; KanjiAdjust(con,&fx, &fy); KanjiAdjust(con,&tx, &ty); if (fy > ty) { swp = fy; fy = ty; ty = swp; swp = fx; fx = tx; tx = swp; } else if (fy == ty && fx > tx) { swp = fx; fx = tx; tx = swp; } for (xx = dispInfo.txmax-1, y = fy; y <= ty; y ++) { if (y == ty) xx = tx; from = TextAddress(con,fx, y); to = TextAddress(con,xx, y); if (con->flagBuff[from] & CODEIS_2) from--; for (x = from; x <= to; x ++) { if (!con->textBuff[x]) continue; fc = con->attrBuff[x]; bc = fc >> 4; bc2 = (bc & 8) | (fc & 7); fc2 = (fc & 8) | (bc & 7); con->attrBuff[x] = fc2 | (bc2 << 4); con->flagBuff[x] &= ~CLEAN_S; } fx = 0; } } void TextWput1(ConInfo *con,u_char ch) { u_int addr; addr = TextAddress(con,con->x, con->y); con->attrBuff[addr] = con->fcol | (con->bcol << 4); con->textBuff[addr] = ch; con->flagBuff[addr] = con->db; #ifdef DEBUG fprintf(stderr, "Now in TextWput1, con-X=%d con-y=%d, db=0x%x ch=0x%x\n", con->x, con->y, con->db, ch); #endif } void TextWput2(ConInfo *con,u_char ch) { u_int addr; addr = TextAddress(con,con->x, con->y); con->textBuff[addr] = ch; con->flagBuff[addr] = LATCH_2; } void TextWput(ConInfo *con,u_char ch1, u_char ch2) { u_int addr; #ifdef DEBUG fprintf(stderr, "Now in TextWput x=%d y=%d ch1=0x%x ch2=0x%x con->db=0x%x\n", con->x, con->y, ch1, ch2, con->db); #endif addr = TextAddress(con,con->x, con->y); con->attrBuff[addr] = con->fcol | (con->bcol << 4); con->textBuff[addr] = ch1; /* ch2; Rui He Jul 9 2003 changed */ con->flagBuff[addr] = con->db; /* LATCH_1 | xx */ con->textBuff[addr+1] = ch2; /* ch1; Rui He Jul 9 2003 changed */ con->flagBuff[addr+1] = LATCH_2; } void TextSput(ConInfo *con,u_char ch) { u_int addr; addr = TextAddress(con,con->x, con->y); con->flagBuff[addr] = LATCH_S|con->sb; con->attrBuff[addr] = con->fcol | (con->bcol << 4); con->textBuff[addr] = ch; } void TextRefresh(ConInfo *con) { int i,j; u_char ch, ch2, fc, bc; int color; color = (con->attr & ATTR_REVERSE ? con->fcol:con->bcol)&7; busy = TRUE; if (!curActive) { busy = FALSE; return; } ShowCursor(&cursorInfo, FALSE); ShowCursor(&mouseCursor, FALSE); if (con->textClear) pVideoInfo->clear(CLEAR_DISPLAY, color); con->textClear = FALSE; for (j = 0; j < con->textSize; j ++) { i = (con->textHead +j ) % con->textSize; if (con->flagBuff[i] & CLEAN_S) continue; fc = con->attrBuff[i] & 0x0F; bc = con->attrBuff[i] >> 4; ch = con->textBuff[i]; con->flagBuff[i] |= CLEAN_S; if ((con->flagBuff[i] & CODEIS_1)) { dbFReg = &fDRegs[ con->flagBuff[i] & LANG_CODE ]; i = (i+1) % con->textSize; con->flagBuff[i] |= CLEAN_S; ch2 = con->textBuff[i]; pVideoInfo->wput(lInfo.sysCoding, /*con->flagBuff[i] & LANG_CODE, */ j % dispInfo.txmax, j / dispInfo.txmax, ch, ch2, fc, bc); } else { sbFReg = &fSRegs[0]; /* Rui He Jul 9 2003 changed to handle half-Chinese problem forced to use English */ pVideoInfo->sput(j % dispInfo.txmax, j / dispInfo.txmax, ch, fc, bc); } } cursorInfo.kanji = IsKanji(con,con->x, con->y); cursorInfo.x = con->x; cursorInfo.y = con->y; ShowCursor(&cursorInfo, TRUE); busy = FALSE; if (CCE_HANDLE_VTSWITCH) { #ifdef SIGUSR1 if (release) LeaveVC(SIGUSR1); #endif } } void TextRepaintAll(ConInfo *con) { llatch(con->flagBuff, con->textSize); con->currentScroll = con->scrollLine = 0; TextRefresh(con); RefreshInputArea(TRUE); /* window-0/1/2.. */ } #ifdef HAVE_TIOCWINSZ static struct winsize text_win; /* for the old text window */ #endif static void SigAlarmHandler(int signum) { #ifdef SIGALRM signal(SIGALRM, SigAlarmHandler); alarm( 60 ); /* set it up again */ #endif if (curActive && text_mode == FALSE) RefreshInputArea(FALSE); } static void SetTextMode(void) { ShowCursor(&cursorInfo, FALSE); pVideoInfo->text_mode(); text_mode = TRUE; #if defined(HAVE_TIOCCONS) ioctl(0, TIOCCONS, NULL); #endif } static void GraphMode(void) { #if defined(HAVE_VT_PROCESS_SWITCH) struct vt_mode vtm; #endif text_mode = FALSE; #ifdef SIGALRM signal(SIGALRM, SigAlarmHandler); alarm( 60 ); /* 60 seconds, update once per minute */ #endif if (CCE_HANDLE_VTSWITCH) { #if defined(__OpenBSD__) || defined(__NetBSD__) int mode = WSDISPLAYIO_MODE_MAPPED; /* 1 */ ioctl(0, WSDISPLAYIO_SMODE, &mode); #endif #if defined(HAVE_KDSETMODE) #if defined(SUPPORT_MOUSE) && defined(SUPPORT_GPMMOUSE) if (mouseType != MOUSE_GPM) #endif { ioctl(0, KDSETMODE, KD_GRAPHICS); } #endif /* HAVE_KDSETMODE */ #if defined(HAVE_VT_PROCESS_SWITCH) #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__SCO__) ioctl(0, VT_RELDISP, VT_ACKACQ); /* VT_ACKACQ is 2 */ #endif signal(SIGUSR1, LeaveVC); signal(SIGUSR2, EnterVC); vtm.mode = VT_PROCESS; vtm.waitv = 0; vtm.relsig = SIGUSR1; vtm.acqsig = SIGUSR2; #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) vtm.frsig = SIGUSR1; #else vtm.frsig = 0; /* add by Rui He frsig is not used */ #endif ioctl(0, VT_SETMODE, &vtm); #endif /* HAVE_VT_PROCESS_SWITCH */ } pVideoInfo->graph_mode(); #if defined(HAVE_TIOCCONS) ioctl(curCon->masterPty, TIOCCONS, NULL); /* redirect system output to pseudo tty */ #endif llatch(curCon->flagBuff, curCon->textSize); TextRefresh(curCon); RefreshInputArea(TRUE); } void LeaveVC(int signum) { #if defined(HAVE_VT_PROCESS_SWITCH) if (CCE_HANDLE_VTSWITCH) { signal(SIGUSR1, LeaveVC); /* should use sigaction()? */ if (busy) { release = TRUE; /* delay */ return; } release = FALSE; curActive = FALSE; SetTextMode(); #if defined(SUPPORT_MOUSE) if (mInfo.has_mouse) { MouseResetRfd(mouseFd); MouseDetach(); } #endif #if defined(linux) ioctl(0, VT_RELDISP, 1); /* no VT_TRUE definition in Linux */ #elif defined(__FreeBSD__) ioctl(0, VT_RELDISP, VT_TRUE); /* VT_TRUE is 1, user release display */ #else ioctl(0, VT_RELDISP, 1); /* works for Lynx */ #endif RestoreKeymap(); } #endif /* HAVE_VT_PROCESS_SWITCH */ } static void EnterVC(int signum) { #if defined(HAVE_VT_PROCESS_SWITCH) if (CCE_HANDLE_VTSWITCH) { signal(SIGUSR2, EnterVC); if (!curActive) { curActive = TRUE; GraphMode(); #if defined(SUPPORT_MOUSE) if (mInfo.has_mouse) { MouseAttach(); MouseSetRfd(mouseFd); } #endif } /* !curActive */ SetupKeymap(); } #endif /* HAVE_VT_PROCESS_SWITCH */ } static int saveTime, saverCount; static bool saved; static void SaveScreen(bool save) { if (saved != save) { saved = save; pVideoInfo->screen_saver(save); } saverCount = 0; } static int ConfigSaver(const char *confstr) { saveTime = atoi(confstr) * 600; /* convert unit from minitue to 1/10 sec */ return SUCCESS; } static void ToggleCursor(CursorInfo *c) { c->count = 0; if (text_mode) return; c->shown = ! c->shown; pVideoInfo->cursor(c); /* draw the cursor using XOR operation */ } static void ShowCursor(CursorInfo *c, bool show) { if (!curActive || !c->sw) return; if (c->shown != show) ToggleCursor(c); } static void PollMouseCursor(void) { if (dispInfo.type == TYPE_SDL || (dispInfo.type == TYPE_GGI && !StartFromConsole)) return; ShowCursor(&mouseCursor, FALSE); if (mInfo.sw > 0) { --mInfo.sw; if (cursorInfo.shown) { int x = mInfo.x, y = mInfo.y; KanjiAdjust(curCon,&x, &y); mouseCursor.kanji = IsKanji(curCon,x, y); mouseCursor.x = x; mouseCursor.y = y; ShowCursor(&mouseCursor, TRUE); } } } void PollCursor(bool wakeup) { if (!curActive) return; if (wakeup) { SaveScreen(FALSE); ShowCursor(&cursorInfo, TRUE); if (mInfo.has_mouse) PollMouseCursor(); return; } if (saved) return; if ((saveTime > 0) && (++saverCount == saveTime)) { ShowCursor(&cursorInfo, FALSE); ShowCursor(&mouseCursor, FALSE); SaveScreen(TRUE); return; } if ((cursorInfo.interval > 0) && (++cursorInfo.count == cursorInfo.interval)) ToggleCursor(&cursorInfo); if (mInfo.has_mouse) PollMouseCursor(); } static int ConfigInterval(const char *confstr) { cursorInfo.interval = mouseCursor.interval = atoi(confstr); return SUCCESS; } #define COUNTER_ADDR 0x61 static int beepCount, okBeepIO; static int ConfigBeep(const char *confstr) { beepCount = atoi(confstr) * 10000; #if defined(linux) && defined(CCE_TARGETARCH_I386) if (beepCount > 0) { okBeepIO = (ioperm(COUNTER_ADDR, 1, TRUE) == 0); } #endif return SUCCESS; } void Beep(void) { if (!curActive || !okBeepIO || beepCount <= 0) return; #if defined(linux) && defined(CCE_TARGETARCH_I386) PortOutb(PortInb(COUNTER_ADDR)|3, COUNTER_ADDR); usleep(beepCount); PortOutb(PortInb(COUNTER_ADDR)&0xFC, COUNTER_ADDR); #endif } static int ConfigDisplay(const char *confstr) { /* int fd = -1; */ if (strlen(confstr) < 10) /* buffer overflow? */ { sscanf(confstr, "%9s", DisplayName); } return SUCCESS; } int ConfigKanjiCursor(const char *confstr) { kanjiCursor = BoolConf(confstr); return SUCCESS; } int ConfigCursorTop(const char *confstr) { cursorTop = atoi(confstr); return SUCCESS; } int ConfigCursorBottom(const char *confstr) { cursorBtm = atoi(confstr); return SUCCESS; } int ConfigScreen(const char *confstr) { sscanf(confstr, "%d %d %d", &dispInfo.tymax, &dispInfo.txmax, &dispInfo.linegap); if (dispInfo.tymax <= 0 || dispInfo.txmax <= 0 || dispInfo.linegap < 0) dispInfo.tymax = dispInfo.txmax = dispInfo.linegap = 0; if (fontwidth <= 0 || fontheight <= 0) { fatal("Can't find the required font for encoding!\n"); } pVideoInfo = InitVideoInfo(DisplayName); if (pVideoInfo == NULL) fatal("graphics mode initialization failed!\n"); return SUCCESS; } void ConsoleInit() { #ifdef HAVE_TIOCWINSZ ioctl(0, TIOCGWINSZ, &text_win); /* get text window size */ #endif DefineCap("Display", ConfigDisplay, "VGA"); DefineCap("BeepCounter", ConfigBeep, "5"); DefineCap("CursorInterval", ConfigInterval, "4"); DefineCap("SaveTime", ConfigSaver, "4"); DefineCap("Screen", ConfigScreen, "25 80 0"); /* "25 80 2"); */ DefineCap("KanjiCursor", ConfigKanjiCursor, "On"); DefineCap("CursorTop", ConfigCursorTop, "14"); DefineCap("CursorBottom", ConfigCursorBottom, "15"); #if defined(__FreeBSD__) && defined(SUPPORT_FRAMEBUF) DefineCap("FreeBSDFrameBuffer", ConfigFreeBSDFrameBuffer, "0 0 0"); #endif } void ConsoleStart(void) { curActive = TRUE; pVideoInfo->start(); cursorInfo.shown = mouseCursor.shown = FALSE; mouseCursor.sw = TRUE; saved = FALSE; if (getenv("HOME")) snprintf(tmpFileName, sizeof(tmpFileName)-1, "%s/%s", getenv("HOME"), CCE_MOUSE_TMPFILE); else snprintf(tmpFileName, sizeof(tmpFileName)-1, "/tmp/%s%3d", CCE_MOUSE_TMPFILE, getuid()); GraphMode(); } void ConsoleCleanup() { #ifdef SIGALRM signal(SIGALRM, SIG_DFL); /* for time */ #endif #if defined(linux) && defined(CCE_TARGETARCH_I386) ioperm(COUNTER_ADDR, 1, FALSE); #endif #if defined(HAVE_VT_PROCESS_SWITCH) if (CCE_HANDLE_VTSWITCH) { struct vt_mode vtm; #ifdef SIGUSR1 signal(SIGUSR1, SIG_DFL); #endif #ifdef SIGUSR2 signal(SIGUSR2, SIG_DFL); #endif vtm.mode = VT_AUTO; vtm.waitv = 0; vtm.relsig = 0; vtm.acqsig = 0; ioctl(0, VT_SETMODE, &vtm); #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__SCO__) ioctl(0, VT_RELDISP, 1); #endif } #endif /* HAVE_VT_PROCESS_SWITCH */ if (curActive) { pVideoInfo->clear(CLEAR_INPUT, DEF_BGCOLOR); /* 0 for black */ SetTextMode(); } if (CCE_HANDLE_VTSWITCH) { #if defined(__OpenBSD__) || defined(__NetBSD__) int mode = WSDISPLAYIO_MODE_EMUL; /* 0 */ ioctl(0, WSDISPLAYIO_SMODE, &mode); #endif #if defined(HAVE_KDSETMODE) ioctl(0, KDSETMODE, KD_TEXT); #endif } pVideoInfo->detach(); /* will mem_unmap */ #if defined(HAVE_TIOCWINSZ) ioctl(0, TIOCSWINSZ, &text_win); #endif }