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