summaryrefslogtreecommitdiffstats
path: root/mbbsd/io.c
diff options
context:
space:
mode:
authorin2 <in2@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2002-03-07 23:13:44 +0800
committerin2 <in2@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2002-03-07 23:13:44 +0800
commitae31e19f92e717919ac8e3db9039eb38d2b89aae (patch)
treec70164d6a1852344f44b04a653ae2815043512af /mbbsd/io.c
downloadpttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar
pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar.gz
pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar.bz2
pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar.lz
pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar.xz
pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar.zst
pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.zip
Initial revision
git-svn-id: http://opensvn.csie.org/pttbbs/pttbbs/trunk/pttbbs@1 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
Diffstat (limited to 'mbbsd/io.c')
-rw-r--r--mbbsd/io.c611
1 files changed, 611 insertions, 0 deletions
diff --git a/mbbsd/io.c b/mbbsd/io.c
new file mode 100644
index 00000000..e3d03b9b
--- /dev/null
+++ b/mbbsd/io.c
@@ -0,0 +1,611 @@
+/* $Id: io.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "perm.h"
+#include "modes.h"
+#include "common.h"
+#include "proto.h"
+
+#if defined(linux)
+#define OBUFSIZE 2048
+#define IBUFSIZE 128
+#else
+#define OBUFSIZE 4096
+#define IBUFSIZE 256
+#endif
+
+extern int current_font_type;
+extern char *fn_proverb;
+extern userinfo_t *currutmp;
+extern unsigned int currstat;
+extern pid_t currpid;
+extern int errno;
+extern screenline_t *big_picture;
+extern int t_lines, t_columns; /* Screen size / width */
+extern int curr_idle_timeout;
+extern water_t water[6], *swater[5], *water_which;
+extern char water_usies;
+
+static char outbuf[OBUFSIZE], inbuf[IBUFSIZE];
+static int obufsize = 0, ibufsize = 0;
+static int icurrchar = 0;
+
+/* ----------------------------------------------------- */
+/* 定時顯示動態看板 */
+/* ----------------------------------------------------- */
+extern userec_t cuser;
+
+static void hit_alarm_clock() {
+ if(HAS_PERM(PERM_NOTIMEOUT) || PERM_HIDE(currutmp) || currstat == MAILALL)
+ return;
+// if(time(0) - currutmp->lastact > IDLE_TIMEOUT - 2) {
+ if(time(0) - currutmp->lastact > curr_idle_timeout - 2) {
+ clear();
+ if(currpid > 0) kill(currpid, SIGHUP);
+ }
+// alarm(IDLE_TIMEOUT);
+ alarm(curr_idle_timeout);
+}
+
+void init_alarm() {
+ signal(SIGALRM, (void (*)(int))hit_alarm_clock);
+// alarm(IDLE_TIMEOUT);
+ alarm(curr_idle_timeout);
+}
+
+/* ----------------------------------------------------- */
+/* output routines */
+/* ----------------------------------------------------- */
+
+void oflush() {
+ if(obufsize) {
+ write(1, outbuf, obufsize);
+ obufsize = 0;
+ }
+}
+
+void init_buf()
+{
+
+ memset(inbuf,0,IBUFSIZE);
+}
+void output(char *s, int len) {
+ /* Invalid if len >= OBUFSIZE */
+
+ if(obufsize + len > OBUFSIZE) {
+ write(1, outbuf, obufsize);
+ obufsize = 0;
+ }
+ memcpy(outbuf + obufsize, s, len);
+ obufsize += len;
+}
+
+int ochar(int c) {
+ if(obufsize > OBUFSIZE - 1) {
+ write(1, outbuf, obufsize);
+ obufsize = 0;
+ }
+ outbuf[obufsize++] = c;
+ return 0;
+}
+
+/* ----------------------------------------------------- */
+/* input routines */
+/* ----------------------------------------------------- */
+
+static int i_newfd = 0;
+static struct timeval i_to, *i_top = NULL;
+static int (*flushf) () = NULL;
+
+void add_io(int fd, int timeout) {
+ i_newfd = fd;
+ if(timeout) {
+ i_to.tv_sec = timeout;
+ i_to.tv_usec = 16384; /* Ptt: 改成16384 避免不按時for loop吃cpu time
+ 16384 約每秒64次 */
+ i_top = &i_to;
+ } else
+ i_top = NULL;
+}
+
+int num_in_buf() {
+ return icurrchar - ibufsize;
+}
+
+int watermode = -1;
+/* Ptt 水球回顧用的參數 */
+/* watermode = -1 沒在回水球
+ = 0 在回上一顆水球 (Ctrl-R)
+ > 0 在回前 n 顆水球 (Ctrl-R Ctrl-R) */
+
+/*
+ dogetch() is not reentrant-safe. SIGUSR[12] might happen at any time,
+ and dogetch() might be called again, and then ibufsize/icurrchar/inbuf
+ might be inconsistent.
+ We try to not segfault here...
+*/
+
+static int dogetch() {
+ int len;
+
+ if(ibufsize <= icurrchar) {
+
+ if(flushf)
+ (*flushf)();
+
+ refresh();
+
+ if(i_newfd) {
+
+ struct timeval timeout;
+ fd_set readfds;
+
+ if(i_top) timeout=*i_top; /* copy it because select() might change it */
+
+ FD_ZERO(&readfds);
+ FD_SET(0, &readfds);
+ FD_SET(i_newfd, &readfds);
+
+ /* jochang: modify first argument of select from FD_SETSIZE */
+ /* since we are only waiting input from fd 0 and i_newfd(>0) */
+
+ while((len = select(i_newfd+1, &readfds, NULL, NULL, i_top?&timeout:NULL))<0)
+ {
+ if(errno != EINTR)
+ abort_bbs(0);
+ /* raise(SIGHUP); */
+ }
+
+ if(len == 0)
+ return I_TIMEOUT;
+
+ if(i_newfd && FD_ISSET(i_newfd, &readfds))
+ return I_OTHERDATA;
+ }
+
+ while((len = read(0, inbuf, IBUFSIZE)) <= 0) {
+ if(len == 0 || errno != EINTR)
+ abort_bbs(0);
+ /* raise(SIGHUP); */
+ }
+ ibufsize = len;
+ icurrchar = 0;
+ }
+
+ if(currutmp)
+ currutmp->lastact = time(0);
+ return inbuf[icurrchar++];
+}
+
+static int water_which_flag=0;
+int igetch() {
+ register int ch;
+ while((ch = dogetch())) {
+ switch(ch) {
+ case Ctrl('L'):
+ redoscr();
+ continue;
+ case Ctrl('U'):
+ if(currutmp != NULL && currutmp->mode != EDITING
+ && currutmp->mode != LUSERS && currutmp->mode) {
+
+ screenline_t *screen0 = calloc(t_lines, sizeof(screenline_t));
+ int y, x, my_newfd;
+
+ getyx(&y, &x);
+ memcpy(screen0, big_picture, t_lines * sizeof(screenline_t));
+ my_newfd = i_newfd;
+ i_newfd = 0;
+ t_users();
+ i_newfd = my_newfd;
+ memcpy(big_picture, screen0, t_lines * sizeof(screenline_t));
+ move(y, x);
+ free(screen0);
+ redoscr();
+ continue;
+ } else
+ return (ch);
+ case KEY_TAB:
+ if( WATERMODE(WATER_ORIG) || WATERMODE(WATER_NEW) )
+ if( currutmp != NULL && watermode > 0 ){
+ watermode = (watermode + water_which->count)
+ % water_which->count + 1;
+ t_display_new();
+ continue;
+ }
+ return ch;
+ break;
+
+ case Ctrl('R'):
+ if(currutmp == NULL)
+ return (ch);
+ if( WATERMODE(WATER_ORIG) || WATERMODE(WATER_NEW) ){
+ if( watermode > 0 ){
+ watermode = (watermode + water_which->count)
+ % water_which->count + 1;
+ t_display_new();
+ continue;
+ }
+ else if( currutmp->mode == 0 &&
+ (currutmp->chatid[0]==2 || currutmp->chatid[0]==3) &&
+ water_which->count != 0 && watermode == 0) {
+ /* 第二次按 Ctrl-R */
+ watermode = 1;
+ t_display_new();
+ continue;
+ }
+ else if(currutmp->msgs[0].pid) {
+ /* 第一次按 Ctrl-R (必須先被丟過水球) */
+ screenline_t *screen0;
+ int y, x, my_newfd;
+ screen0 = calloc(t_lines, sizeof(screenline_t));
+ getyx(&y, &x);
+ memcpy(screen0, big_picture, t_lines*sizeof(screenline_t));
+
+ /* 如果正在talk的話先不處理對方送過來的封包 (不去select) */
+ my_newfd = i_newfd;
+ i_newfd = 0;
+ show_last_call_in(0);
+ watermode = 0;
+ my_write(currutmp->msgs[0].pid, "水球丟過去 : ",
+ currutmp->msgs[0].userid, 0);
+ i_newfd = my_newfd;
+
+ /* 還原螢幕 */
+ memcpy(big_picture, screen0, t_lines*sizeof(screenline_t));
+ move(y, x);
+ free(screen0);
+ redoscr();
+ continue;
+ }
+ else
+ return ch;
+ }
+
+ if( currutmp->msgs[0].pid &&
+ WATERMODE(WATER_OFO) && watermode == -1 ){
+ int y, x, my_newfd;
+ screenline_t *screen0 = calloc(t_lines, sizeof(screenline_t));
+ memcpy(screen0, big_picture, t_lines * sizeof(screenline_t));
+ getyx(&y, &x);
+ my_newfd = i_newfd;
+ i_newfd = 0;
+ my_write2();
+ memcpy(big_picture, screen0, t_lines * sizeof(screenline_t));
+ i_newfd = my_newfd;
+ move(y, x);
+ free(screen0);
+ redoscr();
+ continue;
+ }
+
+ return ch;
+ case '\n': /* Ptt把 \n拿掉 */
+ continue;
+ case Ctrl('T'):
+ if( WATERMODE(WATER_ORIG) || WATERMODE(WATER_NEW) ){
+ if(watermode > 0) {
+ if(watermode>1)
+ watermode--;
+ else
+ watermode = water_which->count;
+ t_display_new();
+ continue;
+ }
+ }
+ return (ch);
+
+ case Ctrl('E'):
+ if( WATERMODE(WATER_ORIG) || WATERMODE(WATER_NEW) ){
+ if(watermode >0){
+ if( water_which_flag == (int)water_usies )
+ water_which_flag = 0;
+ else
+ water_which_flag =
+ (water_which_flag+1) % (int)(water_usies+1);
+ if(water_which_flag==0)
+ water_which = &water[0];
+ else
+ water_which = swater[water_which_flag-1];
+ watermode = 1;
+ t_display_new();
+ continue;
+ }
+ }
+ return ch;
+
+ case Ctrl('W'):
+ if(watermode >0)
+ {
+ water_which_flag=(water_which_flag+water_usies)%(water_usies+1);
+ if(water_which_flag==0)
+ water_which = &water[0];
+ else
+ water_which = swater[water_which_flag-1];
+ watermode = 1;
+ t_display_new();
+ continue;
+ }
+ else return ch;
+ default:
+ return ch;
+ }
+ }
+ return 0;
+}
+
+int oldgetdata(int line, int col, char *prompt, char *buf, int len, int echo) {
+ register int ch, i;
+ int clen;
+ int x = col, y = line;
+ extern unsigned char scr_cols;
+#define MAXLASTCMD 12
+ static char lastcmd[MAXLASTCMD][80];
+
+ strip_ansi(buf, buf, STRIP_ALL);
+
+ if(prompt) {
+
+ move(line, col);
+
+ clrtoeol();
+
+ outs(prompt);
+
+ x += strip_ansi(NULL,prompt,0);
+ }
+
+ if(!echo) {
+ len--;
+ clen = 0;
+ while((ch = igetch()) != '\r') {
+ if(ch == '\177' || ch == Ctrl('H')) {
+ if(!clen) {
+ bell();
+ continue;
+ }
+ clen--;
+ if(echo) {
+ ochar(Ctrl('H'));
+ ochar(' ');
+ ochar(Ctrl('H'));
+ }
+ continue;
+ }
+// Ptt
+#ifdef BIT8
+ if(!isprint2(ch))
+#else
+ if(!isprint(ch))
+#endif
+ {
+ if(echo)
+ bell();
+ continue;
+ }
+
+ if(clen >= len) {
+ if(echo)
+ bell();
+ continue;
+ }
+ buf[clen++] = ch;
+ if(echo)
+ ochar(ch);
+ }
+ buf[clen] = '\0';
+ outc('\n');
+ oflush();
+ } else {
+ int cmdpos = -1;
+ int currchar = 0;
+
+ standout();
+ for(clen = len--; clen; clen--)
+ outc(' ');
+ standend();
+ buf[len] = 0;
+ move(y, x);
+ edit_outs(buf);
+ clen = currchar = strlen(buf);
+
+ while(move(y, x + currchar), (ch = igetkey()) != '\r') {
+ switch(ch) {
+ case KEY_DOWN:
+ case Ctrl('N'):
+ buf[clen] = '\0'; /* Ptt */
+ strncpy(lastcmd[cmdpos], buf, 79);
+ cmdpos += MAXLASTCMD - 2;
+ case Ctrl('P'):
+ case KEY_UP:
+ if(ch == KEY_UP || ch == Ctrl('P')) {
+ buf[clen] = '\0'; /* Ptt */
+ strncpy(lastcmd[cmdpos], buf, 79);
+ }
+ cmdpos++;
+ cmdpos %= MAXLASTCMD;
+ strncpy(buf, lastcmd[cmdpos], len);
+ buf[len] = 0;
+
+ move(y, x); /* clrtoeof */
+ for(i = 0; i <= clen; i++)
+ outc(' ');
+ move(y, x);
+ edit_outs(buf);
+ clen = currchar = strlen(buf);
+ break;
+ case KEY_LEFT:
+ if(currchar)
+ --currchar;
+ break;
+ case KEY_RIGHT:
+ if(buf[currchar])
+ ++currchar;
+ break;
+ case '\177':
+ case Ctrl('H'):
+ if(currchar) {
+ currchar--;
+ clen--;
+ for(i = currchar; i <= clen; i++)
+ buf[i] = buf[i + 1];
+ move(y, x + clen);
+ outc(' ');
+ move(y, x);
+ edit_outs(buf);
+ }
+ break;
+ case Ctrl('Y'):
+ currchar = 0;
+ case Ctrl('K'):
+ buf[currchar] = 0;
+ move(y, x + currchar);
+ for(i = currchar; i < clen; i++)
+ outc(' ');
+ clen = currchar;
+ break;
+ case Ctrl('D'):
+ if(buf[currchar]) {
+ clen--;
+ for(i = currchar; i <= clen; i++)
+ buf[i] = buf[i + 1];
+ move(y, x + clen);
+ outc(' ');
+ move(y, x);
+ edit_outs(buf);
+ }
+ break;
+ case Ctrl('A'):
+ currchar = 0;
+ break;
+ case Ctrl('E'):
+ currchar = clen;
+ break;
+ default:
+ if(isprint2(ch) && clen < len && x + clen < scr_cols) {
+ for(i = clen + 1; i > currchar;i--)
+ buf[i] = buf[i - 1];
+ buf[currchar] = ch;
+ move(y, x + currchar);
+ edit_outs(buf + currchar);
+ currchar++;
+ clen++;
+ }
+ break;
+ }/* end case */
+ } /* end while */
+
+ if(clen > 1)
+ for(cmdpos = MAXLASTCMD - 1; cmdpos; cmdpos--) {
+ strcpy(lastcmd[cmdpos], lastcmd[cmdpos - 1]);
+ strncpy(lastcmd[0], buf, len);
+ }
+ if(echo)
+ outc('\n');
+ refresh();
+ }
+ if((echo == LCECHO) && ((ch = buf[0]) >= 'A') && (ch <= 'Z'))
+ buf[0] = ch | 32;
+#ifdef SUPPORT_GB
+ if(echo == DOECHO && current_font_type == TYPE_GB)
+ {
+ strcpy(buf,hc_convert_str(buf, HC_GBtoBIG, HC_DO_SINGLE));
+ }
+#endif
+ return clen;
+}
+
+/* Ptt */
+int getdata_buf(int line, int col, char *prompt, char *buf, int len, int echo) {
+ return oldgetdata(line, col, prompt, buf, len, echo);
+}
+
+char
+getans(char *prompt)
+{
+ char ans[5];
+
+ getdata(t_lines-1, 0, prompt, ans, 4, LCECHO);
+ return ans[0];
+}
+
+int getdata_str(int line, int col, char *prompt, char *buf, int len, int echo, char *defaultstr) {
+ strncpy(buf, defaultstr, len);
+
+ buf[len] = 0;
+ return oldgetdata(line, col, prompt, buf, len, echo);
+}
+
+int getdata(int line, int col, char *prompt, char *buf, int len, int echo) {
+ buf[0] = 0;
+ return oldgetdata(line, col, prompt, buf, len, echo);
+}
+
+int
+rget(int x,char *prompt)
+{
+ register int ch;
+
+ move(x,0);
+ clrtobot();
+ outs(prompt);
+ refresh();
+
+ ch = igetch();
+ if( ch >= 'A' && ch <= 'Z') ch |= 32;
+
+ return ch;
+}
+
+
+int KEY_ESC_arg;
+
+int igetkey() {
+ int mode;
+ int ch, last;
+
+ mode = last = 0;
+ while(1) {
+ ch = igetch();
+ if(mode == 0) {
+ if(ch == KEY_ESC)
+ mode = 1;
+ else
+ return ch; /* Normal Key */
+ } else if (mode == 1) { /* Escape sequence */
+ if(ch == '[' || ch == 'O')
+ mode = 2;
+ else if(ch == '1' || ch == '4')
+ mode = 3;
+ else {
+ KEY_ESC_arg = ch;
+ return KEY_ESC;
+ }
+ } else if(mode == 2) { /* Cursor key */
+ if(ch >= 'A' && ch <= 'D')
+ return KEY_UP + (ch - 'A');
+ else if(ch >= '1' && ch <= '6')
+ mode = 3;
+ else
+ return ch;
+ } else if (mode == 3) { /* Ins Del Home End PgUp PgDn */
+ if(ch == '~')
+ return KEY_HOME + (last - '1');
+ else
+ return ch;
+ }
+ last = ch;
+ }
+}
+