1 /*-------------------------------------------------------*/
2 /* io.c         ( NTHU CS MapleBBS Ver 2.36 )            */
3 /*-------------------------------------------------------*/
4 /* target : basic console/screen/keyboard I/O routines   */
5 /* create : 1995/02/28                                   */
6 /* update : 2009/12/18               Dopin: ���Ϊ������ */
7 /*-------------------------------------------------------*/
8 
9 #include "bbs.h"
10 
11 #ifdef AIX
12 #include <sys/select.h>
13 #endif
14 
15 #ifdef  Linux
16 #define OBUFSIZE  (2048)
17 #define IBUFSIZE  (128)
18 #else
19 #define OBUFSIZE  (4096)
20 #define IBUFSIZE  (256)
21 #endif
22 
23 #define INPUT_ACTIVE    0
24 #define INPUT_IDLE      1
25 
26 int KEY_ESC_arg;
27 
28 static char outbuf[OBUFSIZE];
29 static int obufsize = 0;
30 
31 static char inbuf[IBUFSIZE];
32 static int ibufsize = 0;
33 static int icurrchar = 0;
34 
35 static int i_mode = INPUT_ACTIVE;
36 
37 extern int dumb_term;
38 
39 /* ----------------------------------------------------- */
40 /* output routines                                       */
41 /* ----------------------------------------------------- */
42 
43 void
oflush()44 oflush()
45 {
46   if (obufsize)
47   {
48     write(1, outbuf, obufsize);
49     obufsize = 0;
50   }
51 }
52 
53 void
output(s,len)54 output(s, len)
55   char *s;
56 {
57   /* Invalid if len >= OBUFSIZE */
58 
59   if (obufsize + len > OBUFSIZE)
60   {
61     write(1, outbuf, obufsize);
62     obufsize = 0;
63   }
64   memcpy(outbuf + obufsize, s, len);
65   obufsize += len;
66 }
67 
ochar(c)68 void ochar(c)
69 {
70   if (obufsize > OBUFSIZE - 1)
71   {
72     write(1, outbuf, obufsize);
73     obufsize = 0;
74   }
75   outbuf[obufsize++] = c;
76 }
77 
78 /* ----------------------------------------------------- */
79 /* input routines                                        */
80 /* ----------------------------------------------------- */
81 
82 static int i_newfd = 0;
83 static struct timeval i_to, *i_top = NULL;
84 static int (*flushf) () = NULL;
85 
num_in_buf()86 int num_in_buf()
87 {
88   return icurrchar - ibufsize;
89 }
90 
igetch()91 int igetch()
92 {
93   int ch;
94 
95   for (;;)
96   {
97     if (ibufsize == icurrchar)
98     {
99       fd_set readfds;
100       struct timeval to;
101 
102       to.tv_sec = to.tv_usec = 0;
103       FD_ZERO(&readfds);
104       FD_SET(0, &readfds);
105       if (i_newfd)
106         FD_SET(i_newfd, &readfds);
107       if ((ch = select(FD_SETSIZE, &readfds, NULL, NULL, &to)) <= 0)
108       {
109         if (flushf)
110           (*flushf) ();
111 
112         if (dumb_term)
113           oflush();
114         else
115           refresh();
116 
117         FD_ZERO(&readfds);
118         FD_SET(0, &readfds);
119         if (i_newfd)
120           FD_SET(i_newfd, &readfds);
121 
122         while ((ch = select(FD_SETSIZE, &readfds, NULL, NULL, i_top)) < 0)
123         {
124           if (errno == EINTR)
125             continue;
126           else
127           {
128             perror("select");
129             return -1;
130           }
131         }
132         if (ch == 0)
133           return I_TIMEOUT;
134       }
135       if (i_newfd && FD_ISSET(i_newfd, &readfds))
136         return I_OTHERDATA;
137 
138       while ((ibufsize = read(0, inbuf, IBUFSIZE)) <= 0)
139       {
140         if (ibufsize == 0)
141           longjmp(byebye, -1);
142         if (ibufsize < 0 && errno != EINTR)
143           longjmp(byebye, -1);
144       }
145       icurrchar = 0;
146     }
147 
148     i_mode = INPUT_ACTIVE;
149     ch = inbuf[icurrchar++];
150     if (ch != Ctrl('L'))
151       return (ch);
152 
153     redoscr();
154   }
155 }
156 
phone_char(char c)157 char *phone_char(char c) {
158    switch (c) {
159           case '1':
160              return "�t";
161           case 'q':
162              return "�u";
163           case 'a':
164              return "�v";
165           case 'z':
166              return "�w";
167           case '2':
168              return "�x";
169           case 'w':
170              return "�y";
171           case 's':
172              return "�z";
173           case 'x':
174              return "�{";
175           case 'e':
176              return "�|";
177           case 'd':
178              return "�}";
179           case 'c':
180              return "�~";
181           case 'r':
182              return "��";
183           case 'f':
184              return "��";
185           case 'v':
186              return "��";
187           case '5':
188              return "��";
189           case 't':
190              return "��";
191           case 'g':
192              return "��";
193           case 'b':
194              return "��";
195           case 'y':
196              return "��";
197           case 'h':
198              return "��";
199           case 'n':
200              return "��";
201           case 'u':
202              return "��";
203           case 'j':
204              return "��";
205           case 'm':
206              return "��";
207           case '8':
208              return "��";
209              break;
210           case 'i':
211              return "��";
212           case 'k':
213              return "��";
214           case ',':
215              return "��";
216           case '9':
217              return "��";
218           case 'o':
219              return "��";
220           case 'l':
221              return "��";
222           case '.':
223              return "��";
224           case '0':
225              return "��";
226           case 'p':
227              return "��";
228           case ';':
229              return "��";
230           case '/':
231              return "��";
232           case '-':
233              return "��";
234           case '6':
235              return "��";
236           case '3':
237              return "��";
238           case '4':
239              return "��";
240           case '7':
241              return "��";
242    }
243   return 0;
244 }
245 
getdata(line,col,prompt,buf,len,echo)246 int getdata(line, col, prompt, buf, len, echo)
247   int line, col;
248   char *prompt, *buf;
249   int len, echo;
250 {
251   register int ch;
252   int clen;
253   int x, y;
254   extern unsigned char scr_cols;
255 #define MAXLASTCMD 6
256   static char lastcmd[MAXLASTCMD][80];
257 
258   if (prompt)
259   {
260     move(line, col);
261     clrtoeol();
262     edit_outs(prompt);
263   }
264   else
265     clrtoeol();
266 
267   if (dumb_term || !echo)
268   {
269     len--;
270     clen = 0;
271     while ((ch = igetch()) != '\r')
272     {
273       if (ch == '\n')
274         break;
275       if (ch == '\177' || ch == Ctrl('H'))
276       {
277         if (!clen)
278         {
279           bell();
280           continue;
281         }
282         clen--;
283         if (echo)
284         {
285           ochar(Ctrl('H'));
286           ochar(' ');
287           ochar(Ctrl('H'));
288         }
289         continue;
290       }
291 
292 #ifdef BIT8
293       if (!isprint2(ch))
294 #else
295       if (!isprint(ch))
296 #endif
297 
298       {
299         if (echo)
300           bell();
301         continue;
302       }
303       if (clen >= len)
304       {
305         if (echo)
306           bell();
307         continue;
308       }
309       buf[clen++] = ch;
310       if (echo)
311         ochar(ch);
312     }
313     buf[clen] = '\0';
314     outc('\n');
315     oflush();
316   }
317   else
318   {
319    int cmdpos = -1;
320    int currchar = 0;
321    int phone_mode = 0;
322    char* pstr;
323 
324     getyx(&y, &x);
325     standout();
326     for (clen = len--; clen; clen--)
327       outc(' ');
328     standend();
329     memset(buf, 0, len);
330 
331     while (move(y, x + currchar), (ch = igetkey()) != '\r')
332     {
333 /*
334 woju
335 */
336        switch (ch) {
337        case KEY_DOWN:
338        case Ctrl('N'):
339           cmdpos += MAXLASTCMD - 2;
340        case Ctrl('P'):
341        case KEY_UP: {
342           int i;
343 
344           cmdpos++;
345           cmdpos %= MAXLASTCMD;
346           strncpy(buf, lastcmd[cmdpos], len);
347           buf[len] = 0;
348 
349           move(y, x);                   /* clrtoeof */
350           for (i = 0; i <= clen; i++)
351              outc(' ');
352           move(y, x);
353 
354           edit_outs(buf);
355           clen = currchar = strlen(buf);
356           continue;
357        }
358        case KEY_LEFT:
359           if (currchar)
360              --currchar;
361           continue;
362        case KEY_RIGHT:
363           if (buf[currchar])
364              ++currchar;
365           continue;
366        case KEY_ESC:
367            if (KEY_ESC_arg == 'p')
368               phone_mode ^= 1;
369            continue;
370        }
371 
372       if (ch == '\n' || ch == '\r')
373          break;
374       if (ch == '\177' || ch == Ctrl('H'))
375       {
376         if (currchar) {
377            int i;
378 
379            currchar--;
380            clen--;
381            for (i = currchar; i <= clen; i++)
382               buf[i] = buf[i + 1];
383            move(y, x + clen);
384            outc(' ');
385            move(y, x);
386            edit_outs(buf);
387         }
388 
389         continue;
390       }
391       if (ch == Ctrl('Y')) {
392          int i;
393 
394          buf[0] = 0;
395          currchar = 0;
396          move(y, x);                    /* clrtoeof */
397          for (i = 0; i < clen; i++)
398             outc(' ');
399          clen = 0;
400          continue;
401       }
402       if (ch == Ctrl('S')) {
403          buf[0] = 'S';
404          clen = 1;
405          echo = 0;
406          break;
407       }
408       if (ch == Ctrl('D')) {
409         if (buf[currchar]) {
410            int i;
411 
412            clen--;
413            for (i = currchar; i <= clen; i++)
414               buf[i] = buf[i + 1];
415            move(y, x + clen);
416            outc(' ');
417            move(y, x);
418            edit_outs(buf);
419         }
420         continue;
421       }
422       if (ch == Ctrl('K')) {
423          int i;
424 
425          buf[currchar] = 0;
426          move(y, x + currchar);
427          for (i = currchar; i < clen; i++)
428             outc(' ');
429          clen = currchar;
430          continue;
431       }
432       if (ch == Ctrl('A')) {
433          currchar = 0;
434          continue;
435       }
436       if (ch == Ctrl('E')) {
437          currchar = clen;
438          continue;
439       }
440 
441 
442       if (!(phone_mode && (pstr = phone_char(ch)) || isprint2(ch) || ch == Ctrl('U')))
443       {
444         continue;
445       }
446       if (clen + (phone_mode && pstr) >= len || x + clen >= scr_cols)
447       {
448         continue;
449       }
450 
451 /* woju */
452 
453       if (buf[currchar]) {               /* insert */
454          int i;
455 
456          for (i = currchar; buf[i] && i + (phone_mode && pstr) < len && i + (phone_mode && pstr) < 80; i++)
457             ;
458          buf[i + 1 + (phone_mode && pstr)] = 0;
459          for (; i > currchar; i--)
460             buf[i + (phone_mode && pstr)] = buf[i - 1];
461       }
462       else                              /* append */
463          buf[currchar + 1 + (phone_mode && pstr)] = '\0';
464       if (ch == Ctrl('U'))
465          ch = KEY_ESC;
466       if (phone_mode && pstr) {
467           buf[currchar] = pstr[0];
468           buf[currchar + 1] = pstr[1];
469       }
470       else
471          buf[currchar] = ch;
472       move(y, x + currchar);
473       edit_outs(buf + currchar);
474       currchar++;
475       currchar += phone_mode && pstr;
476       clen++;
477       clen += phone_mode && pstr;
478     }
479     buf[clen] = '\0';
480     if (clen > 1) {
481        for (cmdpos = MAXLASTCMD - 1; cmdpos; cmdpos--)
482           strcpy(lastcmd[cmdpos], lastcmd[cmdpos - 1]);
483        strncpy(lastcmd[0], buf, len);
484     }
485     if (echo)
486       outc('\n');
487     refresh();
488   }
489   if ((echo == LCECHO) && ((ch = buf[0]) >= 'A') && (ch <= 'Z'))
490     buf[0] = ch | 32;
491   return clen;
492 }
493 
494 #define TRAP_ESC
495 #ifdef  TRAP_ESC
496 
igetkey()497 int igetkey()
498 {
499   int mode;
500   int ch, last;
501 
502   mode = last = 0;
503   while (1)
504   {
505     ch = igetch();
506     if (mode == 0)
507     {
508       if (ch == KEY_ESC)
509         mode = 1;
510       else
511         return ch;              /* Normal Key */
512     }
513     else if (mode == 1)
514     {                           /* Escape sequence */
515       if (ch == '[' || ch == 'O')
516         mode = 2;
517       else if (ch == '1' || ch == '4')
518         mode = 3;
519       else
520       {
521         KEY_ESC_arg = ch;
522         return KEY_ESC;
523       }
524     }
525     else if (mode == 2)
526     {                           /* Cursor key */
527       if (ch >= 'A' && ch <= 'D')
528         return KEY_UP + (ch - 'A');
529       else if (ch >= '1' && ch <= '6')
530         mode = 3;
531       else
532         return ch;
533     }
534     else if (mode == 3)
535     {                           /* Ins Del Home End PgUp PgDn */
536       if (ch == '~')
537         return KEY_HOME + (last - '1');
538       else
539         return ch;
540     }
541     last = ch;
542   }
543 }
544 
545 #else                           /* TRAP_ESC */
546 
igetkey(void)547 int igetkey(void) {
548   int mode;
549   int ch, last;
550 
551   mode = last = 0;
552   while (1)
553   {
554     ch = igetch();
555     if (ch == KEY_ESC)
556       mode = 1;
557     else if (mode == 0)         /* Normal Key */
558       return ch;
559     else if (mode == 1)
560     {                           /* Escape sequence */
561       if (ch == '[' || ch == 'O')
562         mode = 2;
563       else if (ch == '1' || ch == '4')
564         mode = 3;
565       else
566         return ch;
567     }
568     else if (mode == 2)
569     {                           /* Cursor key */
570       if (ch >= 'A' && ch <= 'D')
571         return KEY_UP + (ch - 'A');
572       else if (ch >= '1' && ch <= '6')
573         mode = 3;
574       else
575         return ch;
576     }
577     else if (mode == 3)
578     {                           /* Ins Del Home End PgUp PgDn */
579       if (ch == '~')
580         return KEY_HOME + (last - '1');
581       else
582         return ch;
583     }
584     last = ch;
585   }
586 }
587 #endif                          /* TRAP_ESC */
588 
ask(prompt)589 int ask (prompt)
590      char *prompt;
591 {
592   int ch;
593 
594   move (0, 0);
595   clrtoeol ();
596   standout ();
597   prints ("%s", prompt);
598   standend ();
599   ch = igetkey ();
600   move (0, 0);
601   clrtoeol ();
602   return (ch);
603 }
604