/* vi: set sw=4 ts=4: */ /* * KON2 - Kanji ON Console - * 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 #include #include "getcap.h" #include "defs.h" #include "errors.h" #include "vc.h" #include "child.h" #include "mouse.h" #include "key.h" #include "vga.h" #include "hzinput.h" #include "term.h" #ifdef HAVE_PWD_H #include #endif #ifdef HAVE_SYS_IOCTL_H #include #endif #ifdef HAVE_SYS_WAIT_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif #ifdef HAVE_SYS_TIME_H #include /* for Linux 2.2.x, for struct timeval */ #endif #if defined(SUPPORT_GGILIB) #include "cceggi.h" #endif #if defined(SUPPORT_SDLLIB) #include "ccesdl.h" #endif #if defined(SUPPORT_ENCODING_FILTER) #include "encfilter.h" #endif #define NR_TERMS 10 int numTerms = 0; int termMask[NR_TERMS]; ConInfo *curCon = NULL; #ifdef SUPPORT_POSIX_TERMIOS static struct termios oldTio; #endif int VtNum; /* current virtual terminal */ int StartFromConsole = 1; /* 0 for X Windows */ int GGIAvail, SDLAvail; /* GGI or SDL library available? */ int UseGGIFirst, UseSDLFirst; /* Use GGI/SDL on console ? */ #ifdef __BEOS__ #undef HAVE_SELECT /* hack for BeOS R5, its select() can work on socket only!*/ #endif struct initInfo { bool display; /* display initialized */ bool termios; /* termios saved */ bool got_oldtio; }; static struct initInfo init; static void TermClose(ConInfo *con); static void SetSignalHandlers(void); static void CleanUp(void) { #ifdef SUPPORT_POSIX_TERMIOS if (init.termios) tcsetattr(0, TCSANOW, &oldTio); #endif #ifdef SIGCHLD signal(SIGCHLD, SIG_DFL); #endif #ifdef SIGHUP signal(SIGHUP, SIG_DFL); #endif #ifdef SIGTERM signal(SIGTERM, SIG_DFL); #endif #ifdef SIGSEGV signal(SIGSEGV, SIG_DFL); #endif #ifdef SIGUSR1 signal(SIGUSR1, SIG_DFL); #endif #ifdef SIGUSR2 signal(SIGUSR2, SIG_DFL); #endif ChildCleanup(); InputCleanup(); if (init.display) ConsoleCleanup(); if (dispInfo.type != TYPE_GGI && dispInfo.type != TYPE_SDL) { KeymapCleanup(); MouseCleanup(); } FontDetach(TRUE); /* remove loaded font */ #ifdef SUPPORT_ENCODING_FILTER if (UseEncodingFilter) CleanupEncodingFilter(); #endif if (/*(dispInfo.type != TYPE_GGI && dispInfo.type != TYPE_SDL) &&*/ StartFromConsole) { fprintf(stdout, "\x1B[2J\x1B[1;1;f"); fflush(stdout); } fprintf(stderr,"\r\nCCE> Finished without core dump :) \r\n"); if (dispInfo.gxdim >= 1280 && fontheight < 24) fprintf(stderr, "CCE> You can try 24x24 font by changing config file " CONFIG_NAME ".\r\n"); fprintf(stderr, "\r\n"); } static void ExitTerm(int signum) { #if defined(__SunOS__) || defined(__SCO__) fatal("%s\n", _sys_siglist[signum]); #elif defined(__Minix__) || defined(__WINDOWS__) fatal("SIG\n"); /* no siglist in Minix? */ #else fatal("%s\n",sys_siglist[signum]); /* Please change it to fatal("SIG\n") if sys_siglist is not defined! */ #endif } static fd_set origReadFds; static int maxFds = 0; void MouseSetRfd(int mfd) { if (dispInfo.type != TYPE_GGI && dispInfo.type != TYPE_SDL) { if (mfd > 0) FD_SET(mfd, &origReadFds); if (mfd >= maxFds) maxFds = mfd + 1; } } void MouseResetRfd(int mfd) { if (dispInfo.type != TYPE_GGI && dispInfo.type != TYPE_SDL) { if (mfd > 0) FD_CLR(mfd, &origReadFds); } } static void ConsoleHandler(void) { static u_char buff[BUFSIZ]; /* int remain_bytes; */ fd_set readFds; int j,k, nRead; #ifdef HAVE_SELECT struct timeval tv; #endif ConInfo *con; #ifdef SUPPORT_GGILIB gii_event_mask ggiEvMask; #endif if (dispInfo.type != TYPE_GGI && dispInfo.type != TYPE_SDL) { if (mInfo.has_mouse && mouseFd > 0) MouseSetRfd(mouseFd); else MouseResetRfd(mouseFd); #if !defined(HAVE_SELECT) && defined(O_NONBLOCK) fcntl(0, F_SETFL, O_NONBLOCK); /* make the stdin non-blocking */ #endif } while (curCon && numTerms > 0) /* forever looping */ { int tryagain = 0, v = 1; do /* wait until something happens */ { PollCursor(FALSE); readFds = origReadFds; #ifdef HAVE_SELECT tv.tv_sec = 0; tv.tv_usec = 100000; /* 0.1 sec */ #endif switch(dispInfo.type) { #ifdef SUPPORT_GGILIB case TYPE_GGI: ggiEvMask = emKey | emPointer; v = GGIEVENTSELECT(ggiVis, &ggiEvMask, maxFds, &readFds, NULL, NULL, &tv); tryagain = (ggiEvMask == 0 && (v == 0 || (v < 0 && errno == EINTR))); break; #endif /* SUPPORT_GGILIB */ #ifdef SUPPORT_SDLLIB case TYPE_SDL: #ifdef HAVE_SELECT tv.tv_usec = 50000; /* 0.05 second */ v = select(maxFds, &readFds, NULL, NULL, &tv); tryagain = (v == 0 || (v < 0 && errno == EINTR)); #endif HandleSDLEvents(curCon->masterPty); break; #endif /* SUPPORT_SDLLIB */ default: #ifdef HAVE_SELECT v = select(maxFds, &readFds, NULL, NULL, &tv); tryagain = (v == 0 || (v < 0 && (errno == EINTR || mouseFd < 0))); #endif break; } /* switch */ } while(tryagain); if (v < 0) PerrorExit("select"); /* necessary ? */ switch(dispInfo.type) { #ifdef SUPPORT_GGILIB case TYPE_GGI: if (ggiEvMask) { HandleGIIEvents(curCon->masterPty); PollCursor(TRUE); } break; #endif #ifdef SUPPORT_SDLLIB case TYPE_SDL: /* Already handled before */ break; #endif default: if (curCon && FD_ISSET(0, &readFds)) { nRead = read(0, buff, sizeof(buff)); for(j=0; j masterPty,buff[j]); PollCursor(TRUE); } if (mInfo.has_mouse && curCon && mouseFd > 0) { if (FD_ISSET(mouseFd, &readFds)) { MouseHandleEvent(mouseFd); PollCursor(TRUE); } } break; } /* switch */ nRead = 0; /* remaining bytes in buff */ for(k = numTerms, con = curCon; k > 0; k--) { if (FD_ISSET(con->masterPty, &readFds)) { nRead += read(con->masterPty, buff+nRead, sizeof(buff)-nRead); if (nRead > 0) { if (text_mode) { write(1, buff, nRead); /* output to stdout, before CCE start up? */ nRead = 0; /* force it to be 0, ignore the error condition */ } else { #ifdef SUPPORT_ENCODING_FILTER if (UseEncodingFilter) /* all the input go through filter */ { nRead = DoEncodingFilter(CONVERT_FROM_FILTER, buff, nRead); if (EncodingFilterLen > 0) VtWrite(con, EncodingFilterBuff, EncodingFilterLen); } else #endif { VtWrite(con, buff, nRead); nRead = 0; /* force it to be 0 */ } if (con == curCon) TextRefresh(curCon); } } } con = con->nextCon; if (con->prevCon->terminate) { FD_CLR(con->prevCon->masterPty, &origReadFds); TermClose(con->prevCon); } } } /* while */ } int OpenConsole(int flags) { int cfd; #if defined(linux) cfd = open("/dev/console", flags); /* crw--w--w root root /dev/console */ if (cfd < 0) cfd = open("/dev/tty0", flags); #elif defined(__FreeBSD__) cfd = open("/dev/ttyv0", flags); if (cfd < 0) cfd = open("/dev/console", flags); #elif defined(__NetBSD__) cfd = open("/dev/ttyE0", flags); if (cfd < 0) cfd = open("/dev/ttyE0", flags); #elif defined(__OpenBSD__) cfd = open("/dev/console", flags); if (cfd < 0) cfd = open("/dev/ttyC0", flags); #elif defined(__Lynx__) cfd = open("/dev/con", flags); if (cfd < 0) cfd = open("/dev/atc0", flags); #else /* using /dev/console ok? */ cfd = open("/dev/console", flags); #endif return cfd; } static void GetConsoleVtNum(void) { int cfd; #if defined(linux) || defined(__Lynx__) struct vt_stat vts; #endif VtNum = 0; /* default is 0 (like Solaris 9, only one console terminal) */ cfd = OpenConsole(O_RDONLY); if (cfd < 0) message("Failed to open console device.\n"); #if defined(linux) || defined(__Lynx__) ioctl(cfd, VT_GETSTATE, &vts); VtNum = vts.v_active; #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) ioctl(cfd, VT_GETACTIVE, &VtNum); #endif close(cfd); } #if defined(linux) #include /* for TTY_MAJOR */ #define CCE_TTY_MAJOR TTY_MAJOR #elif defined(__FreeBSD__) || defined(__OpenBSD__) #define CCE_TTY_MAJOR 12 /* ttyv? ttyC? */ #elif defined(__NetBSD__) #define CCE_TTY_MAJOR 47 /* ttyE? */ #elif defined(__Lynx__) #define CCE_TTY_MAJOR 4 /* atc? */ #elif defined(__SCOOpenServer__) #define CCE_TTY_MAJOR 0 /* SCO OpenServer 5.0.7 /dev/ttyNN (0,0)-(0,N) */ #elif defined(__QNX__) #define CCE_TTY_MAJOR 5 /* dev/con1 ~ con4 MAJOR is 4 or 5?! FIXME! */ #define CCE_MAJOR(dev) ((dev) >> 10) #define CCE_MINOR(dev) ((dev) & 0x3FF) #elif defined(__SunOS__) #define CCE_TTY_MAJOR 0 /* dev/console? (0,0) ? FIXME */ #else #define CCE_TTY_MAJOR 4 /* most Unix use 4 for console tty major? */ #endif #if !defined(CCE_MAJOR) #define CCE_MAJOR(dev) ((dev) >> 8) #endif #if !defined(CCE_MINOR) #define CCE_MINOR(dev) ((dev) & 0xFF) #endif int IsConsoleTTY(int fd) { struct stat ttystat; if (!isatty(fd)) return 0; #ifdef HAVE_TTYNAME if (!ttyname(fd) || stat(ttyname(fd), &ttystat) == -1) #endif return 0; /* if no ttyname(), probabaly always GUI OS, return 0 */ if (!strcmp(ttyname(fd), "/dev/console")) return 1; #if defined(__Mach__) || defined(__Hurd__) || defined(__Darwin__) if (strcmp(ttyname(fd), "/dev/console")) return 0; #elif defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__Lynx__) || defined(__SunOS__) || defined(__QNX__) || defined(__Minix) || defined(__SCOOpenServer__) if (CCE_MAJOR(ttystat.st_rdev) != CCE_TTY_MAJOR) { #if defined(__NetBSD__) if (!strncmp(ttyname(fd), "/dev/ttyE", 9)) return 1; /*FIXME,hack for changing TTY_MAJOR! */ #elif defined(__OpenBSD__) if (!strncmp(ttyname(fd), "/dev/ttyC", 9)) return 1; #endif return 0; } #elif defined(__WINDOWS__) || defined(__BEOS__) return 0; /* always full screen GUI */ #elif defined(__SCOUnixWare__) if (strncmp(ttyname(fd), "/dev/vt",7)) return 0; #else return 1; #endif #if defined(linux) if (CCE_MINOR(ttystat.st_rdev) > 63) return 0; #endif return 1; /* default is 1 ? */ } void TermInit() { init.display = init.termios = init.got_oldtio = FALSE; text_mode = TRUE; #ifdef SUPPORT_POSIX_TERMIOS if (isatty(0)) /* in X Windows, it's possible that 0 is not tty! */ { if (tcgetattr(0, &oldTio) == -1) { } else init.got_oldtio = TRUE; } #endif /* SUPPORT_POSIX_TERMIOS */ StartFromConsole = IsConsoleTTY(fileno(stdin)); #ifdef __Darwin__ UseGGIFirst = UseSDLFirst = 1; /* hack for Mac OS X */ #endif #ifdef SUPPORT_GGILIB if (UseGGIFirst) GGIAvail = IsGGIAvailable(); #endif #ifdef SUPPORT_SDLLIB if (!GGIAvail && UseSDLFirst) SDLAvail = IsSDLAvailable(); #endif #if !defined(__MSDOS__) #if defined(SUPPORT_VGA) || defined(SUPPORT_FRAMEBUF) if (!GGIAvail && !SDLAvail && !StartFromConsole) /* VGA and FrameBuf works in console only */ #endif { #if defined(SUPPORT_GGILIB) /* try GGI first */ if (!UseGGIFirst) GGIAvail = IsGGIAvailable();/* GGI supports X Windows */ #endif #if defined(SUPPORT_SDLLIB) /* try SDL second */ if (!GGIAvail && !UseSDLFirst) SDLAvail = IsSDLAvailable(); #endif if (!GGIAvail && !SDLAvail) { #if !defined(DEBUG) fatal("No GGI/SDL found, you can only run CCE in text console.\n"); #endif /* DEBUG */ } } #endif /* __MSDOS__ */ CapInit(); ChildInit(); if (dispInfo.type != TYPE_GGI && dispInfo.type != TYPE_SDL) { MouseInit(); KeymapInit(); } VtInit();/*jmt:2k0826:moved from (b4 ConsoleInit) to (b4 InputInit) // Big5 jmce */ FontInit(); ConsoleInit(); InputInit(); GetConsoleVtNum(); /* try to get the VtNum (for use in hzinput.c) */ } void ChangeTerm(int direction) { if (direction) curCon = curCon->nextCon; else curCon = curCon->prevCon; TextRepaintAll(curCon); } static void TermClose(ConInfo *con) { sigset_t mask; if (con == NULL) return; #ifdef SIGCHLD /* MinGW32 has no SIGCHLD */ sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigprocmask(SIG_BLOCK, &mask, NULL); #endif if (con != con->nextCon) /* all console is closed? */ { con->prevCon->nextCon = con->nextCon; con->nextCon->prevCon = con->prevCon; } else curCon = NULL; numTerms--; termMask[con->window] = 0; #ifdef SIGCHLD sigprocmask(SIG_UNBLOCK, &mask, NULL); #endif if (curCon == con) ChangeTerm(1); close(con->masterPty); VtCleanup(con); } void SetTermWinSize(int fd, int row, int col) { #ifdef HAVE_TIOCWINSZ struct winsize win; if (row <= 0) row = dispInfo.tymax; if (col <= 0) col = dispInfo.txmax; win.ws_row = row; win.ws_col = col; ioctl(fd, TIOCSWINSZ, &win); #endif } #if defined(__BEOS__) #define CCE_PTY_DEVICE "/dev/pt/" #elif defined(__SunOS__) || defined(__WINDOWS__) #define CCE_PTY_DEVICE "/dev/ptmx" /* System V style, cygwin also does this */ #else #define CCE_PTY_DEVICE "/dev/pty" /* BSD style pty & tty */ #endif #define PTY_ERRMSG "Failed to open new pseudo TTY.\r\n" #if defined(__MSDOS__) || defined(__MINGW32__) int TermFork(ConInfo *con) { return 1; } #else /* __MSDOS__ */ int TermFork(ConInfo *con) { char ls, ln; int slavePty; #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) int devtty; #elif defined(__SunOS__) || defined(__WINDOWS__) u_char *ttyName; #endif #if defined(__SunOS__) || defined(__WINDOWS__) strcpy(con->ptyName, CCE_PTY_DEVICE); if ((con->masterPty = open(con->ptyName, O_RDWR | O_NOCTTY)) == -1 || grantpt(con->masterPty) || unlockpt(con->masterPty) || (ttyName = ptsname(con->masterPty)) == NULL) { if (con->masterPty >= 0) close(con->masterPty); PerrorExit(PTY_ERRMSG); } strncpy(con->ptyName, ttyName, sizeof(con->ptyName)); #else for (ls = 'p'; ls <= 's'; ls ++) { for (ln = 0; ln <= 0xF; ln ++) { snprintf(con->ptyName, sizeof(con->ptyName), CCE_PTY_DEVICE "%1c%1x", ls, ln); #ifndef HAVE_SELECT if ((con->masterPty = open(con->ptyName, O_RDWR|O_NONBLOCK)) >= 0) break; #else if ((con->masterPty = open(con->ptyName, O_RDWR)) >= 0) break; #endif } if (con->masterPty >= 0) break; } if (con->masterPty < 0) PerrorExit(PTY_ERRMSG); con->ptyName[5] = 't'; /* slave tty */ #endif if ((con->childPid = fork()) < 0) PerrorExit("fork"); else if (con->childPid == 0) /* in child process */ { int efd; FILE *errfp; efd = dup(2); errfp = fdopen(efd, "w"); setsid(); #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) if ((devtty = open("/dev/tty",O_RDWR|O_NONBLOCK)) >= 0) { ioctl(devtty, TIOCNOTTY, (char *)0); close(devtty); } #endif if ((slavePty = open(con->ptyName, O_RDWR)) < 0) PerrorExit(con->ptyName); #if defined(__SunOS__) if (ioctl(slavePty, I_PUSH, "ptem") < 0) PerrorExit("ioctl(I_PUSH, ptem)"); if (ioctl(slavePty, I_PUSH, "ldterm") < 0) PerrorExit("ioctl(I_PUSH, ldterm)"); if (ioctl(slavePty, I_PUSH, "ttcompat") < 0) PerrorExit("ioctl(I_PUSH, ttcompat)"); #endif close(con->masterPty); if (init.got_oldtio) { tcsetattr(slavePty, TCSANOW, &oldTio); } #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) ioctl(slavePty, TIOCSCTTY, (char *)0); #endif SetTermWinSize(slavePty, 0,0); /* use defauult size */ dup2(slavePty, 0); dup2(slavePty, 1); dup2(slavePty, 2); close(slavePty); ChildStart(errfp); /* execute the shell */ } return 1; /* parent process */ } #endif /* __MSDOS__ || __MINGW32__ */ void TermOpen(void) { ConInfo *con; sigset_t mask; int i; if (numTerms < NR_TERMS) { con = malloc(sizeof(ConInfo)); if (con == NULL) { error("Open New TTY failed\n"); return; } VtStart(con); /* initialize all the buffer and variables, move it here for safety! */ if (TermFork(con)) /* parent process */ { #ifdef SIGCHLD /* MinGW32 has no SIGCHLD */ sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigprocmask(SIG_BLOCK, &mask, NULL); #endif if (curCon) { con->prevCon = curCon; con->nextCon = curCon->nextCon; curCon->nextCon->prevCon = con; curCon->nextCon = con; } else curCon = con->nextCon = con->prevCon = con; numTerms++; for(i = 0; i < NR_TERMS; i++) if (termMask[i] == 0) { con->window = i; termMask[i] = 1; break; } /* find an unused window */ #ifdef SIGCHLD sigprocmask(SIG_UNBLOCK,&mask, NULL); #endif curCon = con; /* activate current */ FD_SET(con->masterPty,&origReadFds); if (con->masterPty >= maxFds) maxFds = con->masterPty+1; } } } void SetConsoleRawMode(void) { #ifdef SUPPORT_POSIX_TERMIOS struct termios newTio; if (isatty(0) && init.got_oldtio) /* In XWindows, probably it's not tty! */ { init.termios = TRUE; newTio = oldTio; newTio.c_lflag &= ~(ECHO|ISIG|ICANON|XCASE); newTio.c_iflag &= 0; newTio.c_cflag |= CS8; newTio.c_oflag &= ~(OPOST); newTio.c_cc[VMIN] = 1; newTio.c_cc[VTIME] = 0; #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) newTio.c_cc[VDISCARD] = _POSIX_VDISABLE; newTio.c_cc[VLNEXT] = _POSIX_VDISABLE; newTio.c_cc[VSTART] = _POSIX_VDISABLE; newTio.c_cc[VSTOP] = _POSIX_VDISABLE; newTio.c_cc[VINTR] = _POSIX_VDISABLE; newTio.c_cc[VSUSP] = _POSIX_VDISABLE; newTio.c_cc[VDSUSP] = _POSIX_VDISABLE; newTio.c_cc[VQUIT] = _POSIX_VDISABLE; #elif defined(linux) newTio.c_line = 0; #endif tcsetattr(0, TCSANOW, &newTio); } #endif /* SUPPORT_POSIX_TERMIOS */ } void TermStart(void) { if (dispInfo.type != TYPE_GGI && dispInfo.type != TYPE_SDL) { if (mInfo.has_mouse) { mouseFd = MouseAttach(); } } atexit(CleanUp); /* program exit cleanup */ SetConsoleRawMode(); SetSignalHandlers(); FD_ZERO(&origReadFds); if (dispInfo.type != TYPE_GGI && dispInfo.type != TYPE_SDL) FD_SET(0, &origReadFds); /* from console */ FontAttach(); TermOpen(); ConsoleStart(); /* switch to graph mode */ init.display = TRUE; #ifdef SUPPORT_ENCODING_FILTER if (UseEncodingFilter) SetupEncodingFilter(lInfo.sysCoding); #endif ConsoleHandler(); /* main loop event */ } void SigChildHandler(int signo) { #ifdef HAVE_WAITPID int status; ConInfo *con; con = curCon; if (curCon) { do { if (waitpid(con->childPid,&status, WNOHANG)) con->terminate = 1; con = con->nextCon; } while (con != curCon ); } signal(SIGCHLD, SigChildHandler); #endif } static void SetSignalHandlers(void) { #ifdef SIGCHLD signal(SIGCHLD, SigChildHandler); #endif #ifdef SIGHUP signal(SIGHUP, ExitTerm); #endif #ifdef SIGTERM signal(SIGTERM, ExitTerm); #endif #if defined(SIGSEGV) && !defined(DEBUG) signal(SIGSEGV, ExitTerm); #endif #ifdef SIGQUIT signal(SIGQUIT, ExitTerm); #endif #ifdef SIGILL signal(SIGILL, ExitTerm); #endif #ifdef SIGABRT signal(SIGABRT, ExitTerm); #endif } int ChangeSystemEncoding(int encoding) { if (encoding == -1) encoding = lInfo.sysCoding + 1; while(encoding != lInfo.sysCoding && lInfo.sysCoding >= CODE_EUC && lInfo.sysCoding <= CODE_KSC) { if (encoding < CODE_EUC || encoding > CODE_KSC) encoding = CODE_EUC; /* 1 */ if (MmapFont(encoding, NULL) == 0) { lInfo.sysCoding = encoding; InputSwitchEncoding(encoding); /* handle input-related stuff */ #ifdef SUPPORT_ENCODING_FILTER if (UseEncodingFilter) SetupEncodingFilter(lInfo.sysCoding); #endif TextRepaintAll(curCon); /* repaint display and input area */ return 0; } encoding++; } return -1; }