1 /* $Id: echo.c,v 1.8.2.1 2003/03/02 15:29:37 amura Exp $ */
2 /*
3 * Echo line reading and writing.
4 *
5 * Common routines for reading
6 * and writing characters in the echo line area
7 * of the display screen. Used by the entire
8 * known universe.
9 */
10 /*
11 * The varargs lint directive comments are 0 an attempt to get lint to shup
12 * up about CORRECT usage of varargs.h. It won't.
13 */
14
15 /*
16 * $Log: echo.c,v $
17 * Revision 1.8.2.1 2003/03/02 15:29:37 amura
18 * add minibuffer history (thanks to kakugawa)
19 *
20 * Revision 1.8 2001/01/05 14:07:01 amura
21 * first implementation of Hojo Kanji support
22 *
23 * Revision 1.7 2000/11/19 18:15:11 amura
24 * rename sput?() functions because HP-UX have sputl() function
25 * in its library
26 *
27 * Revision 1.6 2000/07/18 12:38:56 amura
28 * remove some compile warning
29 *
30 * Revision 1.5 2000/06/27 01:49:43 amura
31 * import to CVS
32 *
33 * Revision 1.4 2000/06/04 06:21:47 amura
34 * To be able to compile without KANJI
35 *
36 * Revision 1.3 2000/06/01 05:26:18 amura
37 * Debug CANNA support
38 *
39 * Revision 1.2 2000/03/28 02:38:37 amura
40 * CANNA support.
41 * ,
42 *
43 * Revision 1.1 2000/03/10 21:32:52 amura
44 * Initial revision
45 *
46 */
47 /* 90.01.29 Modified for Ng 1.0 by S.Yoshida */
48
49 #include "config.h" /* 90.12.20 by S.Yoshida */
50 #include "def.h"
51 #include "key.h"
52 #ifdef SUPPORT_ANSI
53 # include <stdarg.h>
54 #else /* !SUPPPORT_ANSI */
55 # ifdef LOCAL_VARARGS
56 # include "varargs.h"
57 # else
58 # include <varargs.h>
59 # endif
60 #endif /* SUPPORT_ANSI */
61 #ifndef NO_MACRO
62 # include "macro.h"
63 #endif
64
65 static int veread();
66 #ifdef SUPPORT_ANSI
67 VOID ewprintf(char *fp, ...);
68 int message(char *fp,...);
69 #else
70 VOID ewprintf();
71 int message();
72 #endif
73
74 static VOID eformat pro((register char *fp, register va_list *ap));
75 static VOID eputi();
76 static VOID eputl();
77 static VOID eputs();
78 static VOID eputc();
79 #ifndef NEW_COMPLETE /* 90.12.10 Sawayanagi Yosirou */
80 static int complt();
81 #endif /* NEW_COMPLETE */
82
83 #ifdef ADDFUNC /* 91.01.16 by S.Yoshida */
84 int earg_exist = FALSE; /* Extra argument existing flag. */
85 char *earg_text; /* Extra argument text body. */
86
87 /*
88 * Set extra argument using in veread().
89 */
90 VOID
eargset(earg)91 eargset(earg)
92 char *earg;
93 {
94 earg_exist = TRUE;
95 earg_text = earg;
96 }
97 #endif /* ADDFUNC */
98 #ifdef EXTD_DIR
99 static char *edef_text; /* Default argument text body */
100
101 /*
102 * Set extra argument using in veread().
103 */
104 VOID
edefset(earg)105 edefset(earg)
106 char *earg;
107 {
108 edef_text = earg;
109 }
110 #endif /* EXTD_DIR */
111
112 int epresf = FALSE; /* Stuff in echo line flag. */
113 /*
114 * Erase the echo line.
115 */
116 VOID
eerase()117 eerase() {
118 ttcolor(CTEXT);
119 ttmove(nrow-1, 0);
120 tteeol();
121 ttflush();
122 epresf = FALSE;
123 }
124
125 /*
126 * Ask "yes" or "no" question.
127 * Return ABORT if the user answers the question
128 * with the abort ("^G") character. Return FALSE
129 * for "no" and TRUE for "yes". No formatting
130 * services are available. No newline required.
131 */
eyorn(sp)132 eyorn(sp) char *sp; {
133 register int s;
134
135 #ifndef NO_MACRO
136 if(inmacro) return TRUE;
137 #endif
138 ewprintf("%s? (y or n) ", sp);
139 #ifdef FEPCTRL /* 90.11.26 by K.Takano */
140 fepmode_off();
141 #endif
142 for (;;) {
143 s = getkey(FALSE);
144 if (s == 'y' || s == 'Y') return TRUE;
145 if (s == 'n' || s == 'N') return FALSE;
146 if (s == CCHR('[') || s == CCHR('G')) return ctrlg(FFRAND, 1);
147 ewprintf("Please answer y or n. %s? (y or n) ", sp);
148 }
149 /*NOTREACHED*/
150 }
151
152 /*
153 * Like eyorn, but for more important question. User must type either all of
154 * "yes" or "no", and the trainling newline.
155 */
eyesno(sp)156 eyesno(sp) char *sp; {
157 register int s;
158 char buf[64];
159
160 #ifndef NO_MACRO
161 if(inmacro) return TRUE;
162 #endif
163 s = ereply("%s? (yes or no) ", buf, sizeof(buf), sp);
164 for (;;) {
165 if (s == ABORT) return ABORT;
166 if (s != FALSE) {
167 #ifndef NO_MACRO
168 if (macrodef) {
169 LINE *lp = maclcur;
170
171 maclcur = lp->l_bp;
172 maclcur->l_fp = lp->l_fp;
173 free((char *)lp);
174 }
175 #endif
176 if ((buf[0] == 'y' || buf[0] == 'Y')
177 && (buf[1] == 'e' || buf[1] == 'E')
178 && (buf[2] == 's' || buf[2] == 'S')
179 && (buf[3] == '\0')) return TRUE;
180 if ((buf[0] == 'n' || buf[0] == 'N')
181 && (buf[1] == 'o' || buf[0] == 'O')
182 && (buf[2] == '\0')) return FALSE;
183 }
184 #ifdef notyet
185 message("Please answer yes or no.");
186 ttwait();
187 s = ereply("%s? (yes or no) ", buf, sizeof(buf), sp);
188 #else
189 s = ereply("Please answer yes or no. %s? (yes or no) ",
190 buf, sizeof(buf), sp);
191 #endif
192 }
193 /*NOTREACHED*/
194 }
195
196 /*
197 * Write out a prompt, and read back a
198 * reply. The prompt is now written out with full "ewprintf"
199 * formatting, although the arguments are in a rather strange
200 * place. This is always a new message, there is no auto
201 * completion, and the return is echoed as such.
202 */
203 /*VARARGS 0*/
204 #ifdef SUPPORT_ANSI
205 int
ereply(char * fp,char * buf,int nbuf,...)206 ereply(char *fp, char *buf, int nbuf, ... )
207 {
208 int i;
209 va_list pvar;
210
211 va_start(pvar, nbuf) ;
212 i = veread(fp, buf, nbuf, EFNEW|EFCR, &pvar) ;
213 va_end(pvar) ;
214 return i;
215 }
216 #else /* SUPPORT_ANSI */
ereply(va_alist)217 ereply(va_alist)
218 va_dcl
219 {
220 va_list pvar;
221 register char *fp, *buf;
222 register int nbuf;
223 register int i;
224
225 va_start(pvar);
226 fp = va_arg(pvar, char *);
227 buf = va_arg(pvar, char *);
228 nbuf = va_arg(pvar, int);
229 i = veread(fp, buf, nbuf, EFNEW|EFCR, &pvar);
230 va_end(pvar);
231 return i;
232 }
233 #endif /* SUPPORT_ANSI */
234
235 /*
236 * This is the general "read input from the
237 * echo line" routine. The basic idea is that the prompt
238 * string "prompt" is written to the echo line, and a one
239 * line reply is read back into the supplied "buf" (with
240 * maximum length "len"). The "flag" contains EFNEW (a
241 * new prompt), an EFFUNC (autocomplete), or EFCR (echo
242 * the carriage return as CR).
243 */
244 /* VARARGS 0 */
245 #ifdef SUPPORT_ANSI
246 int
eread(char * fp,char * buf,int nbuf,int flag,...)247 eread(char *fp, char *buf, int nbuf, int flag, ...)
248 {
249 int i;
250 va_list pvar;
251 va_start(pvar, flag);
252
253 i = veread(fp, buf, nbuf, flag, &pvar);
254 va_end(pvar) ;
255 return i;
256 }
257 #else /* SUPPORT_ANSI */
eread(va_alist)258 eread(va_alist)
259 va_dcl
260 {
261 va_list pvar;
262 char *fp, *buf;
263 int nbuf, flag, i;
264
265 va_start(pvar);
266 fp = va_arg(pvar, char *);
267 buf = va_arg(pvar, char *);
268 nbuf = va_arg(pvar, int);
269 flag = va_arg(pvar, int);
270 i = veread(fp, buf, nbuf, flag, &pvar);
271 va_end(pvar);
272 return i;
273 }
274 #endif /* SUPPORT_ANSI */
275
276 #ifdef NEW_COMPLETE /* 90.12.10 Sawayanagi Yosirou */
277 #include "complt.h"
278
279 #ifdef MINIBUF_EDIT
280 /* Minibuffer hack from NGSCM by H.Kakugawa */
281
282 #define MB_NHISTS 10
283 #define MB_HIST_FUNC 0
284 #define MB_HIST_BUF 1
285 #define MB_HIST_FILE 2
286 #define MB_HIST_MISC 3
287 #define MB_HIST_NTYPES 4
288 /* Note: mb_hist_buf[*][0] plays a special role. */
289 static char *mb_hist_buf[MB_HIST_NTYPES][MB_NHISTS+1];
290 #define mb_get_hist_buf(flag) \
291 (((flag)&EFFUNC) ? mb_hist_buf[MB_HIST_FUNC] : \
292 (((flag)&EFBUF) ? mb_hist_buf[MB_HIST_BUF] : \
293 (((flag)&EFFILE) ? mb_hist_buf[MB_HIST_FILE] : \
294 mb_hist_buf[MB_HIST_MISC]))) \
295
296 extern int refresh();
297
298 static int mb_init();
299 static int mb_get_buffer();
300 static int mb_bufsize();
301 static int mb_pointchar();
302 static int mb_pointoverwrite();
303 static int mb_point();
304 static int mb_iseol();
305 static int mb_isbol();
306 static int mb_isword();
307 static int mb_gotochar();
308 static int mb2_gotochar();
309 static int mb_insert();
310 static int mb2_insert();
311 static int mb_insertstr();
312 static VOID mb_insertcmplmsg();
313 static int mb2_insertcmplmsg();
314 static int mb_delcmplmsg();
315 static int mb_appenddiff();
316 static int mb2_appenddiff();
317 static int mb_delc();
318 static int mb2_delc();
319 static int mb_erasec();
320 static int mb2_erasec();
321 static int mb_killw();
322 static int mb_delw();
323 static int mb_forwc();
324 static int mb_backwc();
325 static int mb2_forwc();
326 static int mb2_backwc();
327 static int mb_forww();
328 static int mb_backww();
329 static int mb_begl();
330 static int mb_endl();
331 static int mb_upw();
332 static int mb_downw();
333 static int mb_cancel();
334 static int mb2_cancel();
335 static int mb_kill();
336 static int mb_yank();
337 static int mb_trans();
338 static int mb_matchparen();
339 static int mb_col();
340 static int mb_putchar();
341 static VOID mb_move();
342 static VOID mb_movech();
343 static int mb_fixlines();
344 static VOID mb_redisplay();
345 static VOID mb_refresh();
346 static VOID mb_flush();
347 static VOID mb_hist_save();
348 static char* sformat();
349 static int s_put_i();
350 static int s_put_l();
351 static int s_put_s();
352 static int s_put_c();
353 static VOID chsize();
354 static VOID chsize2();
355
356 #ifdef CANNA
357 #include <canna/jrkanji.h>
358 #define CANBUF 1024
359
360 extern jrKanjiStatus ks;
361 static int mb_henkan();
362 char mbMode[CANBUF];
363 int mb_cannamode;
364 #endif
365
366 #ifdef CLIPBOARD
367 extern int send_clipboard();
368 extern int receive_clipboard();
369 #endif
370
371 static int veread_complete();
372
373 static int
veread(fp,buf,nbuf,flag,ap)374 veread(fp, buf, nbuf, flag, ap)
375 char *fp;
376 char *buf;
377 int nbuf;
378 int flag;
379 va_list *ap;
380 {
381 int MetaPrefix, CtluPrefix, nargs, cmp_msg_len, sign, ctluf;
382 int c;
383 char **hist_buf;
384 int hist_idx;
385
386 #ifdef ADDFUNC
387 /* If an extra argument exists, use it. */
388 /* This is a very easy way of not getting an argument from */
389 /* the keyboard. */
390 if(earg_exist)
391 {
392 strcpy(buf, earg_text);
393 earg_exist = FALSE;
394 #ifdef EXTD_DIR
395 edef_text = NULL;
396 #endif
397 return (TRUE);
398 }
399 #endif /* ADDFUNC */
400 #ifndef NO_MACRO
401 if(inmacro)
402 {
403 bcopy (maclcur->l_text, buf, maclcur->l_used);
404 buf[maclcur->l_used] = '\0';
405 maclcur = maclcur->l_fp;
406 #ifdef EXTD_DIR
407 edef_text = NULL;
408 #endif
409 return (TRUE);
410 }
411 #endif
412
413 mb_init(nbuf, fp, ap);
414 cmp_msg_len = 0;
415 MetaPrefix = 0;
416 CtluPrefix = 0;
417 nargs = 1;
418 sign = 1;
419 ctluf = 0;
420 #ifdef CANNA
421 mb_cannamode = FALSE;
422 mbMode[0] = '\0';
423 #endif
424 hist_buf = mb_get_hist_buf(flag);
425 hist_buf[0] = buf;
426 hist_idx = 0;
427
428 for (;;){
429 ttflush();
430 lastflag = thisflag;
431 thisflag = 0;
432
433 c = getkey(FALSE);
434 #ifdef CANNA
435 if(mb_cannamode &&
436 (ks.length != 0 || !(c==' '||ISCTRL(c)||ISKANJI(c))) ){
437 if (mb_henkan(c))
438 continue;
439 }
440 #endif
441
442 if (CtluPrefix == 1){
443 switch (c){
444 case CCHR('G'):
445 nargs = 1;
446 sign = 1;
447 ctluf = 0;
448 CtluPrefix = 0;
449 thisflag = lastflag;
450 continue;
451 break;
452 case CCHR('U'):
453 if (ctluf == 0){
454 ctluf = 1;
455 nargs = 4;
456 sign = 1;
457 } else
458 nargs *= 4;
459 break;
460 case '0':case '1':case '2':case '3':case '4':
461 case '5':case '6':case '7':case '8':case '9':
462 if (ctluf == 1){
463 nargs = (c - '0');
464 ctluf = 0;
465 } else {
466 nargs = (10*nargs + (c - '0'));
467 }
468 break;
469 case '-':
470 if (ctluf == 1){
471 sign = -1;
472 ctluf = 0;
473 nargs = 0;
474 break;
475 } else {
476 hist_buf[0] = NULL; /* reset top of history */
477 return (ABORT);
478 }
479 default:
480 goto Cmd;
481 }
482 thisflag = lastflag;
483 continue;
484 }
485 Cmd:
486 nargs = sign * nargs;
487 CtluPrefix = 0;
488
489 if (MetaPrefix == 1){
490 switch (c){
491 case CCHR('G'): /* Espace from Meta prefix */
492 break;
493 case '<': /* Beginning of Line */
494 mb_begl();
495 break;
496 case '>': /* End of Line */
497 mb_endl();
498 break;
499 case 'B': case 'b': /* Backword word */
500 mb_backww(nargs);
501 break;
502 case 'F': case 'f': /* Forward word */
503 mb_forww(nargs);
504 break;
505 case 'D': case 'd': /* Delete word */
506 if ((lastflag&CFKILL) == 0)
507 kdelete();
508 thisflag |= CFKILL;
509 mb_delw(nargs);
510 break;
511 case 'u': case 'U': /* Upcase word */
512 mb_upw(nargs);
513 break;
514 case 'l': case 'L': /* Downcase word */
515 mb_downw(nargs);
516 break;
517 case CCHR('V'): /* Scroll down completion window */
518 if (nargs > 0)
519 while (nargs-- > 0)
520 complete_scroll_down();
521 else
522 while (nargs++ < 0)
523 complete_scroll_up();
524 break;
525 case 'p': case 'P': /* History, prev */
526 if (hist_idx < MB_NHISTS && hist_buf[hist_idx+1] != NULL) {
527 if (hist_idx == 0)
528 mb_get_buffer(buf, nbuf);
529 hist_idx++;
530 mb_begl();
531 mb_kill();
532 mb_insertstr(hist_buf[hist_idx]);
533 mb_begl();
534 }
535 else {
536 message("Beginning of history; no preceding item");
537 ttwait();
538 }
539 mb_redisplay();
540 break;
541 case 'n': case 'N': /* History, next */
542 if (hist_buf[1] == NULL) {
543 message("End of history; no default available");
544 ttwait();
545 }
546 else if (hist_idx == 0) {
547 message("End of history; no next item");
548 ttwait();
549 }
550 else {
551 hist_idx--;
552 mb_begl();
553 mb_kill();
554 mb_insertstr(hist_buf[hist_idx]);
555 mb_begl();
556 }
557 mb_redisplay();
558 break;
559
560 default:
561 ttbeep();
562 }
563 MetaPrefix = 0;
564 } else {
565 switch (c){
566 case CCHR('['): /* META prefix */
567 MetaPrefix = 1;
568 thisflag = lastflag;
569 continue;
570 case CCHR('U'): /* Ctl-U prefix */
571 CtluPrefix = 1;
572 nargs = 4;
573 ctluf = 1;
574 sign = 1;
575 thisflag = lastflag;
576 continue;
577 case ' ':
578 case CCHR('I'): /* SPC/TAB, or completion */
579 if (flag & EFAUTO)
580 cmp_msg_len = veread_complete(buf, nbuf, c, flag);
581 else
582 mb_insert(1, (char) c);
583 break;
584 case CCHR('J'): /* End of input */
585 c = CCHR('M');
586 case CCHR('M'): /* Return, done. */
587 mb_get_buffer(buf, nbuf);
588 if (flag & EFFUNC){
589 int matchnum;
590 matchnum = complete(buf, flag);
591 if (matchnum != COMPLT_SOLE
592 && matchnum != COMPLT_NOT_UNIQUE){
593 /* complete() will be called again, but i don't mind it */
594 cmp_msg_len = veread_complete(buf, nbuf, (int)CCHR('I'), flag);
595 break;
596 }
597 }
598 complete_del_list();
599 if (flag & EFCR){
600 ttputc(CCHR('M'));
601 ttflush ();
602 }
603 hist_buf[0] = NULL; /* reset top of history */
604 #ifndef NO_MACRO
605 if (macrodef){
606 LINE *lp;
607
608 if((lp = lalloc(mb_bufsize())) == NULL)
609 return FALSE;
610 lp->l_fp = maclcur->l_fp;
611 maclcur->l_fp = lp;
612 lp->l_bp = maclcur;
613 maclcur = lp;
614 bcopy(buf, lp->l_text, mb_bufsize());
615 }
616 #endif
617 if (mb_bufsize() == 0)
618 return FALSE;
619 mb_hist_save(hist_buf, buf);
620 return TRUE;
621 case CCHR('G'): /* Abort */
622 (VOID) ctrlg(FFRAND, 0);
623 mb_flush();
624 complete_del_list();
625 hist_buf[0] = NULL; /* reset top of history */
626 return (ABORT);
627 case CCHR('A'): /* Beginning of line */
628 mb_begl();
629 break;
630 case CCHR('B'): /* Backword char */
631 mb_backwc(nargs);
632 break;
633 case CCHR('D'): /* Delete */
634 mb_delc(nargs);
635 break;
636 case CCHR('E'): /* End of line */
637 mb_endl();
638 break;
639 case CCHR('F'): /* Forward char */
640 mb_forwc(nargs);
641 break;
642 case CCHR('H'):
643 case CCHR('?'): /* Rubout, erase */
644 mb_erasec(nargs);
645 break;
646 case CCHR('K'): /* Kill after point */
647 if ((lastflag&CFKILL) == 0)
648 kdelete();
649 thisflag |= CFKILL;
650 mb_kill();
651 break;
652 case CCHR('L'): /* redraw */
653 refresh(FFRAND, 0);
654 update();
655 mb_redisplay();
656 break;
657 case CCHR('N'): /* Scroll down completion window */
658 if (nargs > 0)
659 while (nargs-- > 0)
660 complete_scroll_down();
661 else
662 while (nargs++ < 0)
663 complete_scroll_up();
664 break;
665 case CCHR('P'): /* Scroll up completion window */
666 if (nargs > 0)
667 while (nargs-- > 0)
668 complete_scroll_up();
669 else
670 while (nargs++ < 0)
671 complete_scroll_down();
672 break;
673 case CCHR('T'): /* Transpose char */
674 mb_trans(nargs);
675 break;
676 case CCHR('W'): /* Kill a word around point */
677 mb_killw(nargs);
678 break;
679 case CCHR('X'): /* Kill line */
680 mb_cancel();
681 break;
682 case CCHR('Y'): /* Yank */
683 mb_yank(nargs);
684 break;
685 case ')':
686 mb_matchparen(nargs, '(', ')');
687 break;
688 case ']':
689 mb_matchparen(nargs, '[', ']');
690 break;
691 case '}':
692 mb_matchparen(nargs, '{', '}');
693 break;
694 case CCHR('\\'):
695 #ifdef CANNA
696 case CCHR('O'):
697 mb_cannamode = mb_cannamode ? FALSE : TRUE;
698 if (!mb_cannamode)
699 mbMode[0] = '\0';
700 break;
701 #endif
702 case CCHR('Q'): /* Quote next */
703 c = getkey(FALSE);
704 default: /* All the rest */
705 if (mb_insert(nargs, (char) c) < 0)
706 break;
707 }
708 }
709 nargs = 1;
710 ctluf = 0;
711 sign = 1;
712 }
713 }
714
715 static int
veread_complete(buf,nbuf,c,flag)716 veread_complete(buf, nbuf, c, flag)
717 char *buf;
718 int nbuf, c, flag;
719 {
720 int matchnum, wflag;
721
722 mb_endl();
723 wflag = (c == ' ');
724 if (wflag){
725 mb2_insert(1, ' ');
726 mb_get_buffer(buf, nbuf);
727 if (complete(buf, flag) == COMPLT_NO_MATCH){
728 mb2_erasec(1);
729 } else {
730 mb_appenddiff(buf);
731 return 0;
732 }
733 }
734 mb_get_buffer(buf, nbuf);
735 matchnum = complete(buf, flag);
736 mb_appenddiff(buf);
737 if (wflag){
738 if (matchnum == COMPLT_AMBIGUOUS
739 || matchnum == COMPLT_NOT_UNIQUE)
740 complete_list_names(buf, flag);
741 else if (matchnum == COMPLT_NO_MATCH) {
742 mb_insertcmplmsg(complete_message(matchnum));
743 ttwait();
744 mb_delcmplmsg();
745 }
746 } else {
747 if (matchnum == COMPLT_AMBIGUOUS)
748 complete_list_names(buf, flag);
749 else {
750 mb_insertcmplmsg(complete_message(matchnum));
751 ttwait();
752 mb_delcmplmsg();
753 }
754 }
755 return 0;
756 }
757
758 /*VARARGS 0*/
759 #ifdef SUPPORT_ANSI
760 int
message(char * fp,...)761 message(char *fp,...)
762 {
763 va_list pvar;
764 va_start(pvar, fp);
765 ewprintf(fp);
766 va_end(pvar);
767 return 0;
768 }
769 #else
770 int
message(va_alist)771 message(va_alist)
772 va_dcl
773 {
774 va_list pvar;
775 register char *fp;
776
777 va_start(pvar);
778 fp = va_arg(pvar, char *);
779 ewprintf(fp);
780 va_end(pvar);
781 return 0;
782 }
783 #endif /* SUPPORT_ANSI */
784
785 struct _Line {
786 int idx;
787 int lno;
788 struct _Line *prev;
789 struct _Line *next;
790 };
791
792 static int _mb_ccol;
793 static int _mb_crow;
794 static char *_mb_buf = NULL;
795 static int _mb_size = 0;
796 static int _mb_point = 0;
797 static int _mb_gapend = 0;
798 static int _mb_prompt = 0;
799 static int _mb_bufsize = 0;
800 struct
801 _Line Line = {0, 0, NULL, NULL};
802 struct _Line *CLine;
803
804 static int
mb_init(nbuf,fp,ap)805 mb_init(nbuf, fp, ap)
806 int nbuf;
807 register char *fp;
808 register va_list *ap;
809 {
810 char *prompt;
811 struct _Line *lp, *lp2;
812 char *sformat();
813
814 prompt = sformat(fp, ap);
815 if (_mb_buf == NULL){
816 _mb_size = nbuf + strlen(prompt) + 10;
817 if ((_mb_buf = malloc(_mb_size)) == NULL)
818 return -1;
819 }
820 if (ttrow != nrow - 1){
821 ttcolor(CTEXT);
822 epresf = TRUE;
823 }
824
825 _mb_ccol = 0;
826 _mb_crow = nrow-1;
827 _mb_prompt = 0;
828 _mb_point = 0;
829 _mb_gapend = _mb_size;
830 _mb_bufsize = 0;
831
832 if (Line.next != NULL){
833 lp = Line.next;
834 while (lp != &Line){
835 lp2 = lp->next;
836 free(lp);
837 lp = lp2;
838 }
839 Line.prev = NULL;
840 Line.next = NULL;
841 }
842 if ((lp = (struct _Line*) malloc(sizeof(struct _Line))) == NULL)
843 return 0;
844 Line.prev = lp;
845 Line.next = lp;
846 lp->idx = 0;
847 lp->lno = 1;
848 lp->prev = &Line;
849 lp->next = &Line;
850 CLine = lp;
851
852 mb_insertstr(prompt);
853 _mb_prompt = strlen(prompt);
854 free(prompt);
855 #ifdef EXTD_DIR
856 if (edef_text) {
857 mb_insertstr(edef_text);
858 edef_text = NULL;
859 }
860 #endif
861 return 0;
862 }
863 static int
mb_get_buffer(buf,nbuf)864 mb_get_buffer(buf, nbuf)
865 char *buf;
866 int nbuf;
867 {
868 register int i, j;
869
870 j = 0;
871 for (i = _mb_prompt; i < _mb_point;){
872 if (j >= nbuf-1){
873 #ifdef KANJI
874 if (ISKANJI(_mb_buf[i])) {
875 #ifdef HOJO_KANJI
876 if (i>=1 && ISHOJO(_mb_buf[i-1])) buf[j-2] = '\0';
877 else
878 #endif
879 buf[j-1] = '\0';
880 } else
881 #endif /* KANJI */
882 buf[j] = '\0';
883 return 0;
884 }
885 buf[j++] = _mb_buf[i++];
886 }
887 for (i = _mb_gapend; i < _mb_size;){
888 if (j >= nbuf-1){
889 #ifdef KANJI
890 if (ISKANJI(_mb_buf[i])) {
891 #ifdef HOJO_KANJI
892 if (i>=1 && ISHOJO(_mb_buf[i-1])) buf[j-2] = '\0';
893 else
894 #endif
895 buf[j-1] = '\0';
896 } else
897 #endif
898 buf[j] = '\0';
899 return 0;
900 }
901 buf[j++] = _mb_buf[i++];
902 }
903 buf[j] = '\0';
904 return mb_bufsize();
905 }
906 static int
mb_bufsize()907 mb_bufsize()
908 {
909 return _mb_bufsize-_mb_prompt;
910 }
911 static int
mb_pointchar()912 mb_pointchar()
913 {
914 unsigned int ch;
915
916 ch = _mb_buf[_mb_point-1];
917 return ch;
918 }
919 static int
mb_pointoverwrite(ch)920 mb_pointoverwrite(ch)
921 unsigned int ch;
922 {
923 _mb_buf[_mb_point-1] = ch;
924 return ch;
925 }
926 static int
mb_point()927 mb_point()
928 {
929 return _mb_point;
930 }
931 static int
mb_iseol()932 mb_iseol()
933 {
934 return (_mb_gapend == _mb_size);
935 }
936 static int
mb_isbol()937 mb_isbol()
938 {
939 return (_mb_point == _mb_prompt);
940 }
941 static int
mb_isword()942 mb_isword()
943 {
944 return ISWORD(_mb_buf[_mb_gapend]);
945 }
946 static int
mb_gotochar(i)947 mb_gotochar(i)
948 int i;
949 {
950 int col, pt, ocol, opt;
951 struct _Line *lp;
952
953 if (i == _mb_point)
954 return mb_point();
955 ocol = _mb_ccol;
956 opt = _mb_point;
957 lp = CLine;
958 mb2_gotochar(i);
959 if (i < opt)
960 mb_fixlines(0, Line.next, 0, &col, &pt);
961 else
962 mb_fixlines(ocol, lp, opt, &col, &pt);
963 if (lp == CLine)
964 ttmove(_mb_crow, _mb_ccol);
965 else
966 mb_refresh(col, pt);
967 return mb_point();
968 }
969 static int
mb2_gotochar(i)970 mb2_gotochar(i)
971 int i;
972 {
973 if (i != _mb_point)
974 mb_move(i-_mb_point);
975 return mb_point();
976 }
977 static int
mb_insert(n,c)978 mb_insert(n, c)
979 int n;
980 char c;
981 {
982 int col, pt, ocol, opt;
983 #ifdef KANJI
984 static int k1 = 0, nnn;
985 #ifdef HOJO_KANJI
986 static int k2 = 0;
987 #endif
988 #endif
989 struct _Line *lp;
990
991 #ifndef KANJI
992 if (n < 0)
993 return -1;
994 ocol = _mb_ccol;
995 opt = _mb_point;
996 lp = CLine;
997 mb2_insert(n, c);
998 mb_fixlines(ocol, lp, opt, &col, &pt);
999 mb_refresh(col, pt);
1000 #else /* KANJI is TRUE */
1001 if (k1 == 0){
1002 if (n < 0)
1003 return -1;
1004 if (ISKANJI(c)){
1005 k1 = c;
1006 nnn = n;
1007 } else {
1008 ocol = _mb_ccol;
1009 opt = _mb_point;
1010 lp = CLine;
1011 mb2_insert(n, c);
1012 mb_fixlines(ocol, lp, opt, &col, &pt);
1013 mb_refresh(col, pt);
1014 }
1015 #ifdef HOJO_KANJI
1016 } else if (ISHOJO(k1) && k2 == 0) {
1017 if (ISKANJI(c)) {
1018 k2 = c;
1019 nnn = n;
1020 } else {
1021 ocol = _mb_ccol;
1022 opt = _mb_point;
1023 lp = CLine;
1024 mb2_insert(n, c);
1025 mb_fixlines(ocol, lp, opt, &col, &pt);
1026 mb_refresh(col, pt);
1027 }
1028 #endif /* HOJO_KANJI */
1029 } else {
1030 ocol = _mb_ccol;
1031 opt = _mb_point;
1032 lp = CLine;
1033 while (nnn-- > 0){
1034 mb2_insert(1, k1);
1035 #ifdef HOJO_KANJI
1036 if (k2 != 0) mb2_insert(1, k2);
1037 #endif
1038 mb2_insert(1, c);
1039 }
1040 mb_fixlines(ocol, lp, opt, &col, &pt);
1041 mb_refresh(col, pt);
1042 k1 = 0;
1043 #ifdef HOJO_KANJI
1044 k2 = 0;
1045 #endif
1046 }
1047 #endif /* NOT KANJI */
1048 return 0;
1049 }
1050 static int
mb2_insert(n,c)1051 mb2_insert(n, c)
1052 int n;
1053 char c;
1054 {
1055 if (n < 0)
1056 return -1;
1057 while (n-- > 0)
1058 mb_putchar(c);
1059 return mb_point();
1060 }
1061 static int
mb_insertstr(s)1062 mb_insertstr(s)
1063 char *s;
1064 {
1065 int col, pt, ocol, opt;
1066 struct _Line *lp;
1067
1068 if (*s == '\0')
1069 return 0;
1070 ocol = _mb_ccol;
1071 opt = _mb_point;
1072 lp = CLine;
1073 while (*s != '\0')
1074 mb_putchar(*(s++));
1075 if (mb_fixlines(ocol, lp, opt, &col, &pt) == 0)
1076 mb_refresh(ocol, opt);
1077 else
1078 mb_refresh(col, pt);
1079 return mb_point();
1080 }
1081
1082 static _mb_cmpl_msg_len = 0;
1083
1084 static VOID
mb_insertcmplmsg(s)1085 mb_insertcmplmsg(s)
1086 char *s;
1087 {
1088 int pt, col;
1089
1090 mb2_insertcmplmsg(s);
1091 mb_fixlines(_mb_ccol, CLine, _mb_point, &col, &pt);
1092 mb_refresh(_mb_ccol, _mb_point);
1093 }
1094 static int
mb2_insertcmplmsg(s)1095 mb2_insertcmplmsg(s)
1096 char *s;
1097 {
1098 int pt;
1099
1100 _mb_cmpl_msg_len = strlen(s);
1101 pt = mb_point();
1102 while (*s != '\0')
1103 mb_putchar(*(s++));
1104 mb2_gotochar(pt);
1105 return pt;
1106 }
1107 static int
mb_delcmplmsg()1108 mb_delcmplmsg()
1109 {
1110 int col, pt;
1111 struct _Line *lp;
1112
1113 if (_mb_cmpl_msg_len == 0)
1114 return 0;
1115 _mb_gapend += _mb_cmpl_msg_len;
1116 _mb_bufsize -= _mb_cmpl_msg_len;
1117 _mb_cmpl_msg_len = 0;
1118 lp = CLine;
1119 mb_fixlines(_mb_ccol, CLine, _mb_point, &col, &pt);
1120 if (lp == CLine)
1121 tteeol();
1122 else
1123 mb_refresh(col, pt);
1124 _mb_cmpl_msg_len = 0;
1125 return mb_point();
1126 }
1127 static int
mb_appenddiff(buf)1128 mb_appenddiff(buf)
1129 char *buf;
1130 {
1131 int ocol, opt, col, pt;
1132 struct _Line *lp;
1133
1134 ocol = _mb_ccol;
1135 opt = _mb_point;
1136 lp = CLine;
1137 mb2_appenddiff(buf);
1138 if (mb_fixlines(ocol, lp, opt, &col, &pt) == 0)
1139 mb_refresh(ocol, opt);
1140 else
1141 mb_redisplay();
1142 return mb_point();
1143 }
1144 static int
mb2_appenddiff(buf)1145 mb2_appenddiff(buf)
1146 char *buf;
1147 {
1148 int p2;
1149 char *p1;
1150
1151 for (p1 = buf, p2 = _mb_prompt; p2 < _mb_point; p1++, p2++)
1152 ;
1153 while (*p1 != '\0')
1154 mb_putchar(*(p1++));
1155 return mb_point();
1156 }
1157 static int
mb_delc(n)1158 mb_delc(n)
1159 int n;
1160 {
1161 int col, pt;
1162
1163 if (n < 0)
1164 return -1;
1165 if (mb2_delc(n) < 0)
1166 return -1;
1167 mb_fixlines(_mb_ccol, CLine, _mb_point, &col, &pt);
1168 mb_refresh(col, pt);
1169 return mb_point();
1170 }
1171 static int
mb2_delc(n)1172 mb2_delc(n)
1173 int n;
1174 {
1175 int v, m;
1176
1177 while (n-- > 0){
1178 if (_mb_gapend == _mb_size)
1179 break;
1180 chsize(&_mb_buf[_mb_gapend], &v, &m);
1181 _mb_gapend += m;
1182 _mb_bufsize -= m;
1183 }
1184 return mb_point();
1185 }
1186 static int
mb_erasec(n)1187 mb_erasec(n)
1188 int n;
1189 {
1190 int col, pt;
1191 struct _Line *lp;
1192
1193 lp = CLine;
1194 mb2_erasec(n);
1195 mb_fixlines(0, Line.next, 0, &col, &pt);
1196 if (lp == CLine)
1197 mb_refresh(_mb_ccol, _mb_point);
1198 else
1199 mb_redisplay();
1200 return mb_point();
1201 }
1202 static int
mb2_erasec(n)1203 mb2_erasec(n)
1204 int n;
1205 {
1206 if (n < 0)
1207 return -1;
1208 while (n-- > 0){
1209 if (_mb_point <= _mb_prompt)
1210 return -1;
1211 if (mb2_backwc(1) < 0)
1212 return -1;
1213 if (mb2_delc(1) < 0)
1214 return -1;
1215 }
1216 return mb_point();
1217 }
1218 static int
mb_killw(n)1219 mb_killw(n)
1220 int n;
1221 {
1222 int col, pt;
1223 struct _Line *lp;
1224
1225 if (n < 0)
1226 return -1;
1227 lp = CLine;
1228 while (n-- > 0){
1229 if (!mb_iseol())
1230 mb2_forwc(1);
1231 while (!mb_iseol() && mb_isword())
1232 mb2_delc(1);
1233 if (!mb_isbol())
1234 mb2_backwc(1);
1235 while (!mb_isbol() && !mb_isword()){
1236 mb2_delc(1);
1237 mb2_backwc(1);
1238 }
1239 while (!mb_isbol() && mb_isword()){
1240 mb2_delc(1);
1241 mb2_backwc(1);
1242 }
1243 if (mb_isbol())
1244 mb2_delc(1);
1245 }
1246 mb_fixlines(0, Line.next, 0, &col, &pt);
1247 if (CLine != lp)
1248 mb_refresh(_mb_ccol, _mb_point);
1249 else
1250 mb_refresh(col, pt);
1251 return mb_point();
1252 }
1253 static int
mb_delw(n)1254 mb_delw(n)
1255 int n;
1256 {
1257 int v, m, ocol, opt, col, pt, i;
1258 struct _Line *lp;
1259
1260 if (n <= 0)
1261 return mb_point();
1262
1263 ocol = _mb_ccol;
1264 opt = _mb_point;
1265 lp = CLine;
1266 while (n-- > 0){
1267 if (_mb_gapend == _mb_size)
1268 goto End;
1269 if (!mb_isword()){
1270 while (!mb_iseol() && !mb_isword()){
1271 chsize(&_mb_buf[_mb_gapend], &v, &m);
1272 for (i = 0; i < m; i++)
1273 if (kinsert(_mb_buf[_mb_gapend+i], KFORW) < 0)
1274 break;
1275 _mb_gapend += m;
1276 _mb_bufsize -= m;
1277 if (_mb_gapend == _mb_size)
1278 goto End;
1279 }
1280 }
1281 while (!mb_iseol() && mb_isword()){
1282 chsize(&_mb_buf[_mb_gapend], &v, &m);
1283 for (i = 0; i < m; i++)
1284 if (kinsert(_mb_buf[_mb_gapend+i], KFORW) < 0)
1285 break;
1286 _mb_gapend += m;
1287 _mb_bufsize -= m;
1288 if (_mb_gapend == _mb_size)
1289 goto End;
1290 }
1291 }
1292 End:
1293 #ifdef CLIPBOARD
1294 send_clipboard();
1295 #endif
1296 mb_fixlines(_mb_ccol, CLine, _mb_point, &col, &pt);
1297 mb_refresh(col, pt);
1298 return mb_point();
1299 }
1300 static int
mb_forwc(n)1301 mb_forwc(n)
1302 int n;
1303 {
1304 int ocol, opt, col, pt;
1305 struct _Line *lp;
1306
1307 if (n < 0)
1308 return mb_backwc(-n);
1309 ocol = _mb_ccol;
1310 opt = _mb_point;
1311 lp = CLine;
1312 mb2_forwc(n);
1313 if (mb_fixlines(ocol, lp, opt, &col, &pt) == 0)
1314 ttmove(_mb_crow, _mb_ccol);
1315 else
1316 mb_refresh(col, pt);
1317 return mb_point();
1318 }
1319 static int
mb_backwc(n)1320 mb_backwc(n)
1321 int n;
1322 {
1323 int col, pt;
1324 struct _Line *lp;
1325
1326 if (n < 0)
1327 return mb_forwc(-n);
1328 lp = CLine;
1329 mb2_backwc(n);
1330 mb_fixlines(0, Line.next, 0, &col, &pt);
1331 if (lp == CLine)
1332 ttmove(_mb_crow, _mb_ccol);
1333 else
1334 mb_refresh(col, pt);
1335 return mb_point();
1336 }
1337 static int
mb2_forwc(n)1338 mb2_forwc(n)
1339 int n;
1340 {
1341 int v, m;
1342
1343 if (_mb_gapend == _mb_size)
1344 return mb_point();
1345 while ((n-- > 0) && (_mb_gapend < _mb_size)){
1346 chsize(&_mb_buf[_mb_gapend], &v, &m);
1347 mb_move(m);
1348 }
1349 return mb_point();
1350 }
1351 static int
mb2_backwc(n)1352 mb2_backwc(n)
1353 int n;
1354 {
1355 int m, v;
1356
1357 if (_mb_point == _mb_prompt)
1358 return mb_point();
1359 while ((n-- > 0) && (_mb_point > _mb_prompt)){
1360 chsize2(&_mb_buf[_mb_point-1], &v, &m);
1361 mb_move(-m);
1362 }
1363 return mb_point();
1364 }
1365 static int
mb_forww(n)1366 mb_forww(n)
1367 int n;
1368 {
1369 int ocol, opt, col, pt;
1370 struct _Line *lp;
1371
1372 if (n < 0)
1373 return mb_backww(-n);
1374 ocol = _mb_ccol;
1375 opt = _mb_point;
1376 lp = CLine;
1377 while (n-- > 0){
1378 /**
1379 if (!mb_iseol())
1380 mb2_forwc(1);
1381 **/
1382 if (!mb_isword()){
1383 while (!mb_iseol() && !mb_isword())
1384 mb2_forwc(1);
1385 }
1386 while (!mb_iseol() && mb_isword())
1387 mb2_forwc(1);
1388 }
1389 if (mb_fixlines(ocol, lp, opt, &col, &pt) == 0)
1390 ttmove(_mb_crow, _mb_ccol);
1391 else
1392 mb_refresh(col, pt);
1393 return mb_point();
1394 }
1395 static int
mb_backww(n)1396 mb_backww(n)
1397 int n;
1398 {
1399 int ocol, opt, col, pt;
1400 struct _Line *lp;
1401
1402 if (n < 0)
1403 return mb_forww(-n);
1404 ocol = _mb_ccol;
1405 opt = _mb_point;
1406 lp = CLine;
1407 while (n-- > 0){
1408 if (!mb_isbol())
1409 mb2_backwc(1);
1410 if (!mb_isword()){
1411 while (!mb_isbol() && !mb_isword())
1412 mb2_backwc(1);
1413 }
1414 while (!mb_isbol() && mb_isword())
1415 mb2_backwc(1);
1416 if (!mb_isbol())
1417 mb2_forwc(1);
1418 }
1419 mb_fixlines(0, Line.next, 0, &col, &pt);
1420 if (lp == CLine)
1421 ttmove(_mb_crow, _mb_ccol);
1422 else
1423 mb_refresh(col, pt);
1424 return mb_point();
1425 }
1426 static int
mb_begl()1427 mb_begl()
1428 {
1429 return mb_gotochar(_mb_prompt);
1430 }
1431 static int
mb_endl()1432 mb_endl()
1433 {
1434 return mb_gotochar(_mb_bufsize);
1435 }
1436 static int
mb_upw(n)1437 mb_upw(n)
1438 int n;
1439 {
1440 int ocol, opt, col, pt;
1441 struct _Line *lp;
1442
1443 if (n <= 0)
1444 return mb_point();
1445
1446 ocol = _mb_ccol;
1447 opt = _mb_point;
1448 lp = CLine;
1449 while (n-- > 0){
1450 if (!mb_isword()){
1451 while (!mb_iseol() && !mb_isword())
1452 mb2_forwc(1);
1453 }
1454 while (!mb_iseol() && mb_isword()){
1455 mb2_forwc(1);
1456 if (ISLOWER(mb_pointchar()))
1457 mb_pointoverwrite(TOUPPER(mb_pointchar()));
1458 }
1459 }
1460 if (mb_fixlines(ocol, lp, opt, &col, &pt) == 0)
1461 mb_refresh(ocol, opt);
1462 else
1463 mb_redisplay();
1464 return mb_point();
1465 }
1466 static int
mb_downw(n)1467 mb_downw(n)
1468 int n;
1469 {
1470 int ocol, opt, col, pt;
1471 struct _Line *lp;
1472
1473 if (n <= 0)
1474 return mb_point();
1475
1476 ocol = _mb_ccol;
1477 opt = _mb_point;
1478 lp = CLine;
1479 while (n-- > 0){
1480 if (!mb_isword()){
1481 while (!mb_iseol() && !mb_isword())
1482 mb2_forwc(1);
1483 }
1484 while (!mb_iseol() && mb_isword()){
1485 mb2_forwc(1);
1486 if (ISUPPER(mb_pointchar()))
1487 mb_pointoverwrite(TOLOWER(mb_pointchar()));
1488 }
1489 }
1490 if (mb_fixlines(ocol, lp, opt, &col, &pt) == 0)
1491 mb_refresh(ocol, opt);
1492 else
1493 mb_redisplay();
1494 return mb_point();
1495 }
1496
1497 static int
mb_cancel()1498 mb_cancel()
1499 {
1500 struct _Line *lp;
1501
1502 lp = CLine;
1503 mb2_cancel();
1504 if (lp == CLine){
1505 ttmove(_mb_crow, _mb_ccol);
1506 tteeol();
1507 } else
1508 mb_redisplay();
1509 return mb_point();
1510 }
1511 static int
mb2_cancel()1512 mb2_cancel()
1513 {
1514 int col, pt;
1515
1516 _mb_point = _mb_prompt;
1517 _mb_gapend = _mb_size;
1518 _mb_bufsize = _mb_prompt;
1519 mb_fixlines(0, Line.next, 0, &col, &pt);
1520 return mb_point();
1521 }
1522 static int
mb_kill()1523 mb_kill()
1524 {
1525 int col, pt;
1526
1527 while (_mb_gapend < _mb_size){
1528 if (kinsert(_mb_buf[_mb_gapend], KFORW) < 0)
1529 break;
1530 _mb_gapend++;
1531 _mb_bufsize--;
1532 }
1533 #ifdef CLIPBOARD
1534 send_clipboard();
1535 #endif
1536 if (mb_fixlines(_mb_ccol, CLine, _mb_point, &col, &pt) == 0)
1537 tteeol();
1538 else
1539 mb_refresh(col, pt);
1540 return mb_point();
1541 }
1542 static int
mb_yank(n)1543 mb_yank(n)
1544 int n;
1545 {
1546 int col, pt, ocol, opt, i;
1547 int ch;
1548 struct _Line *lp;
1549
1550 if (n < 0)
1551 return -1;
1552 ocol = _mb_ccol;
1553 opt = _mb_point;
1554 lp = CLine;
1555 #ifdef CLIPBOARD
1556 receive_clipboard();
1557 #endif
1558 while (n-- > 0){
1559 i = 0;
1560 while ((ch=kremove(i++)) >= 0){
1561 mb_putchar(ch);
1562 }
1563 }
1564 mb_fixlines(ocol, lp, opt, &col, &pt);
1565 if (lp == CLine)
1566 mb_refresh(ocol, opt);
1567 else
1568 mb_redisplay();
1569 return mb_point();
1570 }
1571 static int
mb_trans(n)1572 mb_trans(n)
1573 int n;
1574 {
1575 int ocol, opt, col, pt, v1, m1, v2, m2, i;
1576 struct _Line *lp;
1577 char s[2];
1578
1579 if (n > 0){
1580 ocol = 0;
1581 opt = _mb_point;
1582 lp = CLine;
1583 while (n-- > 0){
1584 if (CLine == Line.next){
1585 lp = CLine;
1586 opt = 0;
1587 } else {
1588 lp = CLine->prev;
1589 opt = lp->idx;
1590 }
1591 if (mb_isbol())
1592 break;
1593 if (mb_iseol()){
1594 mb2_backwc(1);
1595 if (mb_isbol()){
1596 mb2_forwc(1);
1597 break;
1598 }
1599 }
1600 chsize2(&_mb_buf[_mb_point-1], &v1, &m1);
1601 for (i = m1-1; i >= 0; i--)
1602 s[i] = _mb_buf[--_mb_point];
1603 chsize(&_mb_buf[_mb_gapend], &v2, &m2);
1604 for (i = 0; i < m2; i++)
1605 _mb_buf[_mb_point++] = _mb_buf[_mb_gapend++];
1606 for (i = 0; i < m1; i++)
1607 _mb_buf[--_mb_gapend] = s[m1-i-1];
1608
1609 if (mb_iseol())
1610 break;
1611 mb2_forwc(1);
1612 }
1613 if (mb_fixlines(ocol, lp, opt, &col, &pt) == 0)
1614 mb_refresh(ocol, opt);
1615 else
1616 mb_redisplay();
1617 } else if (n < 0){
1618 while (n++ < 0){
1619 if (mb_isbol())
1620 break;
1621 if (mb_iseol()){
1622 mb2_backwc(1);
1623 if (mb_isbol()){
1624 mb2_forwc(1);
1625 break;
1626 }
1627 }
1628 chsize2(&_mb_buf[_mb_point-1], &v1, &m1);
1629 for (i = m1-1; i >= 0; i--)
1630 s[i] = _mb_buf[--_mb_point];
1631 chsize(&_mb_buf[_mb_gapend], &v2, &m2);
1632 for (i = 0; i < m2; i++)
1633 _mb_buf[_mb_point++] = _mb_buf[_mb_gapend++];
1634 for (i = 0; i < m1; i++)
1635 _mb_buf[--_mb_gapend] = s[m1-i-1];
1636
1637 if (mb_isbol())
1638 break;
1639 mb2_backwc(1);
1640 }
1641 if (mb_fixlines(0, Line.next, 0, &col, &pt) == 0)
1642 mb_refresh(col, pt);
1643 else
1644 mb_redisplay();
1645 }
1646 return mb_point();
1647 }
1648 static int
mb_matchparen(n,opar,cpar)1649 mb_matchparen(n, opar, cpar)
1650 int n;
1651 char opar, cpar;
1652 {
1653 int i, dep, dep2, instr, oinstr, point, v, m;
1654 int col, ocol, pt, opt, red, match, on;
1655 struct _Line *clp, *dlp, *lp;
1656
1657 if (n <= 0)
1658 return mb_point();
1659
1660 instr = 0;
1661 for (i = _mb_prompt; i < _mb_point; i++){
1662 if (_mb_buf[i] == '"'){
1663 if (instr == 0)
1664 instr = 1;
1665 else
1666 instr = 0;
1667 } else if (_mb_buf[i] == '\\')
1668 i++;
1669 }
1670 oinstr = instr;
1671
1672 on = n;
1673 match = 0;
1674 red = 0;
1675 ocol = _mb_ccol;
1676 opt = _mb_point;
1677 lp = CLine;
1678 clp = dlp = CLine;
1679 while (n-- > 0){
1680 clp = CLine;
1681 point = _mb_point;
1682 mb_putchar(cpar);
1683 mb_fixlines(ocol, lp, opt, &col, &pt);
1684 if (clp != CLine){
1685 red = 1;
1686 col = _mb_ccol-1;
1687 }
1688 clp = CLine;
1689 if (red == 0){
1690 mb_refresh(col, pt);
1691 dlp = clp;
1692 }
1693 dep = 0;
1694 dep2 = 0;
1695 while (point >= _mb_prompt){
1696 if (instr == 0){
1697 if (_mb_buf[point] == '"'){
1698 if ((point > _mb_prompt) && (_mb_buf[point-1] == '\\'))
1699 point--;
1700 else {
1701 instr = 1;
1702 dep2 = dep;
1703 }
1704 } else if ((_mb_buf[point] == cpar) && (oinstr == 0)){
1705 dep++;
1706 } else if ((_mb_buf[point] == opar) && (oinstr == 0)){
1707 if (--dep == 0){
1708 match++;
1709 if (dlp != clp){
1710 dlp = clp;
1711 red = 1;
1712 _mb_ccol = mb_col(clp, point);
1713 mb_refresh(0, clp->idx);
1714 } else
1715 ttmove(_mb_crow, mb_col(clp, point));
1716 ttflush();
1717 ttwait();
1718 break;
1719 }
1720 }
1721 } else {
1722 if (_mb_buf[point] == '"'){
1723 if ((point > _mb_prompt) && (_mb_buf[point-1] == '\\'))
1724 point--;
1725 else {
1726 instr = 0;
1727 dep = dep2;
1728 }
1729 } else if ((_mb_buf[point] == cpar) && (oinstr == 1)){
1730 dep++;
1731 } else if ((_mb_buf[point] == opar) && (oinstr == 1)){
1732 if (--dep == 0){
1733 match++;
1734 if (dlp != clp){
1735 dlp = clp;
1736 red = 1;
1737 _mb_ccol = mb_col(clp, point);
1738 mb_refresh(0, clp->idx);
1739 } else
1740 ttmove(_mb_crow, mb_col(clp, point));
1741 ttflush();
1742 ttwait();
1743 break;
1744 }
1745 }
1746 }
1747 chsize2(&_mb_buf[point], &v, &m);
1748 if (point == clp->idx)
1749 clp = clp->prev;
1750 point -= m;
1751 }
1752 }
1753 if (red == 1){
1754 mb_fixlines(ocol, lp, opt, NULL, NULL);
1755 mb_redisplay();
1756 } else
1757 ttmove(_mb_crow, _mb_ccol);
1758 if (match != on)
1759 ttbeep();
1760 return mb_point();
1761 }
1762 static int
mb_col(lp,pt)1763 mb_col(lp, pt)
1764 struct _Line *lp;
1765 int pt;
1766 {
1767 int col, point, v, m;
1768
1769 col = 0;
1770 for (point = lp->idx; point < pt; ){
1771 chsize(&_mb_buf[point], &v, &m);
1772 col += v;
1773 point += m;
1774 }
1775 return col;
1776 }
1777 static int
mb_putchar(c)1778 mb_putchar(c)
1779 char c;
1780 {
1781 int i, more;
1782 char *new_mb_buf;
1783 struct _Line *lp;
1784
1785 if (_mb_point == (_mb_gapend-1)){
1786 more = _mb_size;
1787 if ((new_mb_buf = malloc(_mb_size+more)) == NULL)
1788 return -1;
1789 for (i = 0; i < _mb_point; i++)
1790 new_mb_buf[i] = _mb_buf[i];
1791 for (i = _mb_gapend; i < _mb_size; i++)
1792 new_mb_buf[i+more] = _mb_buf[i];
1793 free(_mb_buf);
1794 _mb_buf = new_mb_buf;
1795 _mb_gapend += more;
1796 _mb_size = _mb_size + more;
1797 if (_mb_point != _mb_prompt)
1798 for (lp = CLine->next; lp != &Line; lp = lp->next)
1799 lp->idx += more;
1800 }
1801 _mb_buf[_mb_point++] = c;
1802 _mb_bufsize++;
1803 return 0;
1804 }
1805 static VOID
mb_move(m)1806 mb_move(m)
1807 int m;
1808 {
1809 if (m > 0){
1810 while (m > 0){
1811 _mb_buf[_mb_point++] = _mb_buf[_mb_gapend++];
1812 --m;
1813 }
1814 } else {
1815 while (m < 0){
1816 _mb_buf[--_mb_gapend] = _mb_buf[--_mb_point];
1817 ++m;
1818 }
1819 }
1820 }
1821 static VOID
mb_movech(n)1822 mb_movech(n)
1823 int n;
1824 {
1825 int v, m;
1826
1827 if (n > 0){
1828 while (n > 0){
1829 chsize(&_mb_buf[_mb_point-1], &v, &m);
1830 while ((m--) > 0)
1831 _mb_buf[_mb_point++] = _mb_buf[_mb_gapend++];
1832 --n;
1833 }
1834 } else {
1835 while (n < 0){
1836 chsize2(&_mb_buf[_mb_point-1], &v, &m);
1837 while ((m--) > 0)
1838 _mb_buf[--_mb_gapend] = _mb_buf[--_mb_point];
1839 ++n;
1840 }
1841 }
1842 }
1843 static int
mb_fixlines(col,line,point,colp,ptp)1844 mb_fixlines(col, line, point, colp, ptp)
1845 int col, point, *colp, *ptp;
1846 struct _Line *line;
1847 {
1848 int v, m, bp, ccol, opt, redraw, lno;
1849 struct _Line *lp0, *lp1;
1850
1851 if (colp != NULL) *colp = col;
1852 if (ptp != NULL) *ptp = point;
1853 ccol = col;
1854 redraw = 0;
1855 bp = 1;
1856 lno = line->lno;
1857 for (;;){
1858 if (point == _mb_point){
1859 _mb_ccol = col;
1860 CLine = line;
1861 point = _mb_gapend;
1862 bp = 0;
1863 }
1864 if (point == _mb_size){
1865 /* ASSRT: line != &Line */
1866 goto End;
1867 }
1868
1869 opt = point;
1870 chsize(&_mb_buf[point], &v, &m);
1871 col += v;
1872 ccol += v;
1873 point += m;
1874
1875 if (col >= (ncol-1)-1){
1876 if (line->next == &Line){
1877 if ((lp0 = (struct _Line*) malloc(sizeof (struct _Line))) == NULL)
1878 return -1;
1879 line->next = lp0;
1880 lp0->next = &Line;
1881 Line.prev = lp0;
1882 lp0->prev = line;
1883 }
1884 line = line->next;
1885 line->lno = ++lno;
1886 line->idx = opt;
1887 if (bp == 1){
1888 if (colp != NULL) *colp = 0;
1889 if (ptp != NULL) *ptp = line->idx;
1890 redraw = 1;
1891 }
1892 col = v;
1893 }
1894 }
1895
1896 End:
1897 for (lp0 = line->next; lp0 != &Line; lp0 = lp1){
1898 lp1 = lp0->next;
1899 free(lp0);
1900 }
1901 line->next = &Line;
1902 Line.prev = line;
1903 if ((_mb_ccol == (ncol-1)-2) && (_mb_gapend < _mb_size)){
1904 CLine = CLine->next;
1905 _mb_ccol = 0;
1906 if (colp != NULL) *colp = 0;
1907 if (ptp != NULL) *ptp = CLine->idx;
1908 redraw = 1;
1909 } else
1910 if ((_mb_ccol == 0) && (_mb_gapend == _mb_size)){
1911 lp0 = CLine;
1912 CLine = CLine->prev;
1913 free(lp0);
1914 CLine->next = &Line;
1915 Line.prev = CLine;
1916 mb_fixlines(0, CLine, CLine->idx, colp, ptp);
1917 redraw = 1;
1918 }
1919 return redraw;
1920 }
1921 static VOID
mb_redisplay()1922 mb_redisplay()
1923 {
1924 mb_refresh(0, CLine->idx);
1925 }
1926 static VOID
mb_refresh(col,idx)1927 mb_refresh(col, idx)
1928 int col, idx;
1929 {
1930 int v, m, limit;
1931
1932 limit = (ncol-1)-2;
1933 ttmove(_mb_crow, col);
1934 for ( ; idx < _mb_point; ){
1935 if (col >= limit)
1936 break;
1937 chsize(&_mb_buf[idx], &v, &m);
1938 while (m-- > 0)
1939 eputc(_mb_buf[idx++]);
1940 col += v;
1941 }
1942 for (idx = _mb_gapend; idx < _mb_size; ){
1943 if (col >= limit)
1944 break;
1945 chsize(&_mb_buf[idx], &v, &m);
1946 while (m-- > 0)
1947 eputc(_mb_buf[idx++]);
1948 col += v;
1949 }
1950 if (CLine->next != &Line){
1951 for ( ; col <= (ncol-1); col++)
1952 eputc('\\');
1953 } else
1954 tteeol();
1955 ttmove(_mb_crow, _mb_ccol);
1956 mb_flush();
1957 }
1958 static VOID
mb_flush()1959 mb_flush()
1960 {
1961 ttflush();
1962 }
1963 #ifdef CANNA
1964 static int
mb_henkan(c)1965 mb_henkan( c )
1966 int c;
1967 {
1968 int ilen;
1969 int i;
1970 static char kakutei[CANBUF];
1971 static int oldlength, oldrevPos;
1972 int col, pt;
1973 struct _Line *lp;
1974 lp = CLine;
1975
1976 ilen = jrKanjiString(0, c, kakutei, CANBUF, &ks);
1977
1978 if (oldrevPos == 0)
1979 oldrevPos = mb_point();
1980 if (oldlength == 0)
1981 oldlength = mb_point();
1982
1983 if (ilen < 0)
1984 return FALSE;
1985 if (ks.info & KanjiModeInfo){
1986 jrKanjiControl(0,KC_QUERYMODE, mbMode);
1987 }
1988
1989 if ( ilen > 0) {
1990 mb2_gotochar(oldlength);
1991 while (mb_point() > oldrevPos)
1992 mb2_erasec(1);
1993 mb_fixlines(0, Line.next, 0, &col, &pt);
1994 if (lp == CLine)
1995 mb_refresh(_mb_ccol, _mb_point);
1996 else
1997 mb_redisplay();
1998 mb_insertstr(kakutei);
1999 oldlength = oldrevPos = 0;
2000 }
2001 if ( ks.length > 0) {
2002 mb2_gotochar(oldlength);
2003 while (mb_point() > oldrevPos)
2004 mb2_erasec(1);
2005 mb_fixlines(0, Line.next, 0, &col, &pt);
2006 if (lp == CLine)
2007 mb_refresh(_mb_ccol, _mb_point);
2008 else
2009 mb_redisplay();
2010 oldrevPos = mb_point();
2011 mb_insert( 1, '|');
2012 mb_insertstr(ks.echoStr);
2013 mb_insert( 1, '|');
2014 oldlength = mb_point();
2015 mb_backwc(1);
2016 }
2017 else if ( ks.length == 0 && ilen == 0) {
2018 mb2_gotochar(oldlength);
2019 while (mb_point() > oldrevPos)
2020 mb2_erasec(1);
2021 mb_fixlines(0, Line.next, 0, &col, &pt);
2022 if (lp == CLine)
2023 mb_refresh(_mb_ccol, _mb_point);
2024 else
2025 mb_redisplay();
2026 oldlength = oldrevPos = 0;
2027 }
2028
2029 return TRUE;
2030 }
2031 #endif /* CANNA */
2032
2033 static char*
sformat(fp,ap)2034 sformat(fp, ap)
2035 register char *fp;
2036 register va_list *ap;
2037 {
2038 register char *s;
2039 register int n;
2040 int c, idx;
2041 char kname[NKNAME];
2042 char *keyname();
2043 char *cp;
2044
2045 n = ncol + 1;
2046 if ((s = malloc(n)) == NULL)
2047 return NULL;
2048 idx = 0;
2049 while ((c = *fp++) != '\0'){
2050 if (c != '%')
2051 idx = s_put_c(s, idx, n, c);
2052 else {
2053 c = *fp++;
2054 switch (c){
2055 case 'c':
2056 (VOID) keyname(kname, va_arg(*ap, int));
2057 idx = s_put_s(s, idx, n, kname);
2058 break;
2059 case 'k':
2060 cp = kname;
2061 for(c=0; c < key.k_count; c++) {
2062 cp = keyname(cp, key.k_chars[c]);
2063 *cp++ = ' ';
2064 }
2065 *--cp = '\0';
2066 idx = s_put_s(s, idx, n, kname);
2067 break;
2068 case 'd':
2069 idx = s_put_i(s, idx, n, va_arg(*ap, int), 10);
2070 break;
2071 case 'o':
2072 idx = s_put_i(s, idx, n, va_arg(*ap, int), 8);
2073 break;
2074 case 's':
2075 idx = s_put_s(s, idx, n, va_arg(*ap, char *));
2076 break;
2077 case 'l':/* explicit longword */
2078 c = *fp++;
2079 switch(c) {
2080 case 'd':
2081 idx = s_put_l(s, idx, n, (long)va_arg(*ap, long), 10);
2082 break;
2083 default:
2084 idx = s_put_c(s, idx, n, c);
2085 break;
2086 }
2087 break;
2088 default:
2089 idx = s_put_c(s, idx, n, c);
2090 }
2091 }
2092 }
2093 s[idx] = '\0';
2094 return s;
2095 }
2096
2097 static int
s_put_i(p,idx,n,i,r)2098 s_put_i(p, idx, n, i, r)
2099 register char *p;
2100 register int idx, n;
2101 register int i;
2102 register int r;
2103 {
2104 register int q;
2105
2106 if(i<0) {
2107 idx = s_put_c(p, idx, n, '-');
2108 i = -i;
2109 }
2110 if ((q=i/r) != 0)
2111 idx = s_put_i(p, idx, n, q, r);
2112 return s_put_c(p, idx, n, i%r+'0');
2113 }
2114
2115 static int
s_put_l(p,idx,n,l,r)2116 s_put_l(p, idx, n, l, r)
2117 register char *p;
2118 register int idx, n;
2119 register long l;
2120 register int r;
2121 {
2122 register long q;
2123
2124 if(l < 0) {
2125 idx = s_put_c(p, idx, n, '-');
2126 l = -l;
2127 }
2128 if ((q=l/r) != 0)
2129 idx = s_put_l(p, idx, n, q, r);
2130 return s_put_c(p, idx, n, (int)(l%r)+'0');
2131 }
2132
2133 static int
s_put_s(p,idx,n,s)2134 s_put_s(p, idx, n, s)
2135 register char *p, *s;
2136 register int idx, n;
2137 {
2138 register int c;
2139
2140 while ((c = *s++) != '\0')
2141 idx = s_put_c(p, idx, n, c);
2142 return idx;
2143 }
2144
2145 static int
s_put_c(p,idx,n,c)2146 s_put_c(p, idx, n, c)
2147 register char *p;
2148 register int idx, n;
2149 register char c;
2150 {
2151 epresf = TRUE;
2152
2153 if (idx < n) {
2154 if (ISCTRL(c)) {
2155 idx = s_put_c(p, idx, n, '^');
2156 c = CCHR(c);
2157 }
2158 #ifdef KANJI
2159 #ifdef HANKANA
2160 {
2161 static int c1=0;
2162
2163 if (ISKANJI(c)) {
2164 if (c1==0) c1=1;
2165 else c1=0;
2166 } else c1=0;
2167 if (ISHANKANA(c) && (c1 == 1))
2168 idx--;
2169 }
2170 #endif /* HANKANA */
2171 p[idx++] = c;
2172 #else /* NOT KANJI */
2173 p[idx++] = c;
2174 #endif /* KANJI */
2175 }
2176 return idx;
2177 }
2178
2179 static VOID
chsize(s,visu,mem)2180 chsize(s, visu, mem)
2181 register char *s;
2182 register int *visu, *mem;
2183 {
2184 if (ISCTRL(*s)){
2185 *visu = 2;
2186 *mem = 1;
2187 #ifdef KANJI
2188 } else if (ISKANJI(*s)){
2189 *mem = 2;
2190 #ifdef HOJO_KANJI
2191 if (ISHOJO(*s)) {
2192 *mem = 3;
2193 *visu = 2;
2194 } else
2195 #endif /* HOJO_KANJI */
2196 #ifdef HANKANA
2197 if (ISHANKANA(*s))
2198 *visu = 1;
2199 else
2200 #endif /* HANKANA */
2201 *visu = 2;
2202 #endif /* KANJI */
2203 } else {
2204 *visu = 1;
2205 *mem = 1;
2206 }
2207 }
2208
2209 static VOID
chsize2(s,visu,mem)2210 chsize2(s, visu, mem)
2211 register char *s;
2212 register int *visu, *mem;
2213 {
2214 if (ISCTRL(*s)){
2215 *visu = 2;
2216 *mem = 1;
2217 #ifdef KANJI
2218 } else if (ISKANJI(*s)){
2219 *mem = 2;
2220 #ifdef HOJO_KANJI
2221 if (ISHOJO(*(s-2)) && ISKANJI(*(s-1))) {
2222 *mem = 3;
2223 *visu = 2;
2224 } else
2225 #endif /* HOJO_KANJI */
2226 #ifdef HANKANA
2227 if (ISHANKANA(*(s-1)))
2228 *visu = 1;
2229 else
2230 #endif /* HANKANA */
2231 *visu = 2;
2232 #endif /* KANJI */
2233 } else {
2234 *visu = 1;
2235 *mem = 1;
2236 }
2237 }
2238
2239 static VOID
mb_hist_save(hist_buf,buf)2240 mb_hist_save(hist_buf, buf)
2241 char *hist_buf[];
2242 char *buf;
2243 {
2244 int i;
2245 if (hist_buf[MB_NHISTS] != NULL)
2246 free(hist_buf[MB_NHISTS]);
2247 /* rotate history */
2248 for (i = MB_NHISTS; i > 1; i--)
2249 hist_buf[i] = hist_buf[i-1];
2250 /* and insert new history to head */
2251 hist_buf[1] = malloc(strlen(buf)+1);
2252 strcpy(hist_buf[1], buf);
2253 }
2254 #else /* NOT MINIBUF_EDIT */
2255 static int veread_del_char ();
2256 static int veread_complete ();
2257
2258 static int
veread(fp,buf,nbuf,flag,ap)2259 veread(fp, buf, nbuf, flag, ap)
2260 char *fp;
2261 char *buf;
2262 int nbuf;
2263 int flag;
2264 va_list *ap;
2265 {
2266 int cpos;
2267 int c;
2268
2269 #ifdef ADDFUNC /* 91.01.16 by S.Yoshida */
2270 /* If an extra argument exists, use it. */
2271 /* This is a very easy way of not getting an argument from */
2272 /* the keyboard. */
2273 if(earg_exist)
2274 {
2275 strcpy(buf, earg_text);
2276 earg_exist = FALSE;
2277 edef_text = NULL;
2278 return (TRUE);
2279 }
2280 #endif /* ADDFUNC */
2281 #ifndef NO_MACRO
2282 if(inmacro)
2283 {
2284 bcopy (maclcur->l_text, buf, maclcur->l_used);
2285 buf[maclcur->l_used] = '\0';
2286 maclcur = maclcur->l_fp;
2287 #ifdef EXTD_DIR
2288 edef_text = NULL;
2289 #endif
2290 return (TRUE);
2291 }
2292 #endif
2293 if ((flag & EFNEW) || ttrow != nrow - 1)
2294 {
2295 ttcolor(CTEXT);
2296 ttmove(nrow - 1, 0);
2297 epresf = TRUE;
2298 }
2299 else
2300 eputc(' ');
2301 eformat(fp, ap);
2302 tteeol();
2303
2304 #ifdef EXTD_DIR
2305 if (edef_text) {
2306 strcpy(buf, edef_text);
2307 edef_text = NULL;
2308 eputs(buf);
2309 cpos = strlen(buf);
2310 } else
2311 #endif
2312 {
2313 buf[0] = '\0';
2314 cpos = 0;
2315 }
2316 for (;;)
2317 {
2318 ttflush();
2319 c = getkey(FALSE);
2320 tteeol();
2321 switch (c)
2322 {
2323 case ' ':
2324 case CCHR('I'):
2325 if (flag & EFAUTO)
2326 {
2327 #if 0 /* 90.12.10 Sawayanagi Yosirou */
2328 if (flag & EFFILE)
2329 {
2330 char *p;
2331
2332 p = adjustname (buf);
2333 while (cpos > 0)
2334 cpos = veread_del_char (buf, cpos);
2335 strcpy (buf, p);
2336 eputs (buf);
2337 cpos = strlen (buf);
2338 }
2339 #endif
2340 cpos = veread_complete (buf, cpos, c, flag);
2341 }
2342 else if (cpos < nbuf - 1)
2343 {
2344 buf[cpos++] = (char) c;
2345 buf[cpos] = '\0';
2346 eputc((char) c);
2347 }
2348 break;
2349 case CCHR('J'):
2350 c = CCHR('M'); /* and continue */
2351 case CCHR('M'): /* Return, done. */
2352 if (flag & EFFUNC)
2353 {
2354 int matchnum;
2355
2356 matchnum = complete (buf, flag);
2357 eputs (&buf[cpos]);
2358 tteeol();
2359 cpos = strlen (buf);
2360 if (matchnum != COMPLT_SOLE
2361 && matchnum != COMPLT_NOT_UNIQUE)
2362 {
2363 /* complete() will be called again, but i don't mind it */
2364 cpos = veread_complete (buf, cpos, (int)CCHR('I'), flag);
2365 break;
2366 }
2367 }
2368 complete_del_list ();
2369 if (flag & EFCR)
2370 {
2371 ttputc(CCHR('M'));
2372 ttflush ();
2373 }
2374 #ifndef NO_MACRO
2375 if (macrodef)
2376 {
2377 LINE *lp;
2378
2379 if((lp = lalloc(cpos)) == NULL)
2380 return FALSE;
2381 lp->l_fp = maclcur->l_fp;
2382 maclcur->l_fp = lp;
2383 lp->l_bp = maclcur;
2384 maclcur = lp;
2385 bcopy(buf, lp->l_text, cpos);
2386 }
2387 #endif
2388 return ((buf[0] == '\0') ? FALSE : TRUE);
2389 case CCHR('G'): /* Bell, abort. */
2390 case CCHR('['):
2391 (VOID) ctrlg(FFRAND, 0);
2392 ttflush();
2393 complete_del_list ();
2394 return (ABORT);
2395 case CCHR('N'):
2396 complete_scroll_down ();
2397 break;
2398 case CCHR('P'):
2399 complete_scroll_up ();
2400 break;
2401 case CCHR('H'):
2402 case CCHR('?'): /* Rubout, erase. */
2403 cpos = veread_del_char (buf, cpos);
2404 break;
2405 case CCHR('X'): /* C-X */
2406 case CCHR('U'): /* C-U, kill line. */
2407 while (cpos > 0)
2408 cpos = veread_del_char (buf, cpos);
2409 break;
2410 case CCHR('W'): /* C-W, kill to beginning of */
2411 /* previous word */
2412 /* back up to first word character or beginning */
2413 while ((cpos > 0) && !ISWORD(buf[cpos - 1]))
2414 cpos = veread_del_char (buf, cpos);
2415 while ((cpos > 0) && ISWORD(buf[cpos - 1]))
2416 cpos = veread_del_char (buf, cpos);
2417 break;
2418 case CCHR('\\'):
2419 case CCHR('Q'): /* C-Q, quote next */
2420 c = getkey(FALSE); /* and continue */
2421 default: /* All the rest. */
2422 if (cpos < nbuf - 1)
2423 {
2424 buf[cpos++] = (char) c;
2425 buf[cpos] = '\0';
2426 eputc((char) c);
2427 }
2428 }
2429 }
2430 }
2431
2432 static int
veread_del_char(buf,cpos)2433 veread_del_char (buf, cpos)
2434 char *buf;
2435 int cpos;
2436 {
2437 if (cpos <= 0)
2438 return (0);
2439 ttputc('\b');
2440 ttputc(' ');
2441 ttputc('\b');
2442 --ttcol;
2443 --cpos;
2444 if (ISCTRL(buf[cpos]) != FALSE)
2445 {
2446 ttputc('\b');
2447 ttputc(' ');
2448 ttputc('\b');
2449 --ttcol;
2450 }
2451 #ifdef KANJI /* 90.01.29 by S.Yoshida */
2452 else if (ISKANJI(buf[cpos]))
2453 {
2454 #ifdef HANKANA /* 92.11.21 by S.Sasaki */
2455 if (!ISHANKANA(buf[--cpos])) {
2456 ttputc('\b');
2457 ttputc(' ');
2458 ttputc('\b');
2459 --ttcol;
2460 }
2461 #else /* not HANKANA */
2462 ttputc('\b');
2463 ttputc(' ');
2464 ttputc('\b');
2465 --ttcol;
2466 --cpos;
2467 #endif /* HANKANA */
2468 }
2469 #endif /* KANJI */
2470 buf[cpos] = '\0';
2471 return (cpos);
2472 }
2473
2474 static int
veread_complete(buf,cpos,c,flag)2475 veread_complete (buf, cpos, c, flag)
2476 char *buf;
2477 int cpos;
2478 int c;
2479 int flag;
2480 {
2481 int matchnum;
2482 int i;
2483 int wflag;
2484 int cur_ttrow;
2485 int cur_ttcol;
2486
2487 wflag = (c == ' ');
2488 if (wflag)
2489 {
2490 buf[cpos] = ' ';
2491 buf[cpos + 1] = '\0';
2492 if (complete (buf, flag) == COMPLT_NO_MATCH)
2493 buf[cpos] = '\0';
2494 else
2495 {
2496 buf[cpos + 1] = '\0';
2497 eputs (&buf[cpos]);
2498 tteeol();
2499 ++cpos;
2500 return (cpos);
2501 }
2502 }
2503 matchnum = complete (buf, flag);
2504 if (buf[cpos] == '\0')
2505 {
2506 if (wflag)
2507 {
2508 if (matchnum == COMPLT_AMBIGUOUS
2509 || matchnum == COMPLT_NOT_UNIQUE)
2510 complete_list_names (buf, flag);
2511 else if (matchnum == COMPLT_NO_MATCH)
2512 {
2513 cur_ttrow = ttrow;
2514 cur_ttcol = ttcol;
2515 eputs (complete_message (matchnum));
2516 tteeol();
2517 ttmove (cur_ttrow, cur_ttcol);
2518 }
2519 }
2520 else
2521 {
2522 if (matchnum == COMPLT_AMBIGUOUS)
2523 complete_list_names (buf, flag);
2524 else
2525 {
2526 cur_ttrow = ttrow;
2527 cur_ttcol = ttcol;
2528 eputs (complete_message (matchnum));
2529 tteeol();
2530 ttmove (cur_ttrow, cur_ttcol);
2531 }
2532 }
2533 }
2534 else
2535 {
2536 if (wflag)
2537 {
2538 for (i = cpos + 1; buf[i] != '\0'; i++)
2539 {
2540 if (i > cpos && ! ISWORD(buf[i - 1]))
2541 {
2542 buf[i] = '\0';
2543 break;
2544 }
2545 }
2546 }
2547 eputs (&buf[cpos]);
2548 tteeol();
2549 cpos = strlen (buf);
2550 }
2551 return (cpos);
2552 }
2553 #endif /* MINIBUF_EDIT */
2554 #else /* NOT NEW_COMPLETE */
veread(fp,buf,nbuf,flag,ap)2555 static veread(fp, buf, nbuf, flag, ap) char *fp; char *buf; va_list *ap; {
2556 register int cpos;
2557 register int i;
2558 register int c;
2559
2560 #ifdef ADDFUNC /* 91.01.16 by S.Yoshida */
2561 /* If extra argument is exist, use it. */
2562 /* This is very easy way to not get argument from keyboard. */
2563 if(earg_exist)
2564 {
2565 strcpy(buf, earg_text);
2566 earg_exist = FALSE;
2567 return (TRUE);
2568 }
2569 #endif /* ADDFUNC */
2570 #ifndef NO_MACRO
2571 if(inmacro) {
2572 bcopy(maclcur->l_text, buf, maclcur->l_used);
2573 buf[maclcur->l_used] = '\0';
2574 maclcur = maclcur->l_fp;
2575 return TRUE;
2576 }
2577 #endif
2578 cpos = 0;
2579 if ((flag&EFNEW)!=0 || ttrow!=nrow-1) {
2580 ttcolor(CTEXT);
2581 ttmove(nrow-1, 0);
2582 epresf = TRUE;
2583 } else
2584 eputc(' ');
2585 eformat(fp, ap);
2586 tteeol();
2587 ttflush();
2588 #ifdef FEPCTRL /* 90.11.26 by K.Takano */
2589 fepmode_off();
2590 #endif
2591 for (;;) {
2592 c = getkey(FALSE);
2593 if ((flag&EFAUTO) != 0 && (c == ' ' || c == CCHR('I'))) {
2594 cpos += complt(flag, c, buf, cpos);
2595 continue;
2596 }
2597 switch (c) {
2598 case CCHR('J'):
2599 c = CCHR('M'); /* and continue */
2600 case CCHR('M'): /* Return, done. */
2601 if ((flag&EFFUNC) != 0) {
2602 if ((i = complt(flag, c, buf, cpos)) == 0)
2603 continue;
2604 if (i > 0) cpos += i;
2605 }
2606 buf[cpos] = '\0';
2607 if ((flag&EFCR) != 0) {
2608 ttputc(CCHR('M'));
2609 ttflush();
2610 }
2611 #ifndef NO_MACRO
2612 if(macrodef) {
2613 LINE *lp;
2614
2615 if((lp = lalloc(cpos)) == NULL) return FALSE;
2616 lp->l_fp = maclcur->l_fp;
2617 maclcur->l_fp = lp;
2618 lp->l_bp = maclcur;
2619 maclcur = lp;
2620 bcopy(buf, lp->l_text, cpos);
2621 }
2622 #endif
2623 goto done;
2624
2625 case CCHR('G'): /* Bell, abort. */
2626 case CCHR('['):
2627 eputc(CCHR('G'));
2628 (VOID) ctrlg(FFRAND, 0);
2629 ttflush();
2630 return ABORT;
2631
2632 case CCHR('H'):
2633 case CCHR('?'): /* Rubout, erase. */
2634 if (cpos != 0) {
2635 ttputc('\b');
2636 ttputc(' ');
2637 ttputc('\b');
2638 --ttcol;
2639 if (ISCTRL(buf[--cpos]) != FALSE) {
2640 ttputc('\b');
2641 ttputc(' ');
2642 ttputc('\b');
2643 --ttcol;
2644 }
2645 #ifdef KANJI /* 90.01.29 by S.Yoshida */
2646 else if (ISKANJI(buf[cpos])) {
2647 #ifdef HANKANA /* 92.11.21 by S.Sasaki */
2648 if (!ISHANKANA(buf[--cpos])) {
2649 ttputc('\b');
2650 ttputc(' ');
2651 ttputc('\b');
2652 --ttcol;
2653 }
2654
2655 #else /* HANKANA */
2656 ttputc('\b');
2657 ttputc(' ');
2658 ttputc('\b');
2659 --ttcol;
2660 --cpos;
2661 #endif /* HANKANA */
2662 }
2663 #endif /* KANJI */
2664 ttflush();
2665 }
2666 break;
2667
2668 case CCHR('X'): /* C-X */
2669 case CCHR('U'): /* C-U, kill line. */
2670 while (cpos != 0) {
2671 ttputc('\b');
2672 ttputc(' ');
2673 ttputc('\b');
2674 --ttcol;
2675 if (ISCTRL(buf[--cpos]) != FALSE) {
2676 ttputc('\b');
2677 ttputc(' ');
2678 ttputc('\b');
2679 --ttcol;
2680 }
2681 #ifdef KANJI /* 90.01.29 by S.Yoshida */
2682 else if (ISKANJI(buf[cpos])) {
2683 #ifdef HANKANA /* 92.11.21 by S.Sasaki */
2684 if (!ISHANKANA(buf[--cpos])) {
2685 ttputc('\b');
2686 ttputc(' ');
2687 ttputc('\b');
2688 --ttcol;
2689 }
2690 #else /* HANKANA */
2691 ttputc('\b');
2692 ttputc(' ');
2693 ttputc('\b');
2694 --ttcol;
2695 --cpos;
2696 #endif /* HANKANA */
2697 }
2698 #endif /* KANJI */
2699 }
2700 ttflush();
2701 break;
2702
2703 case CCHR('W'): /* C-W, kill to beginning of */
2704 /* previous word */
2705 /* back up to first word character or beginning */
2706 while ((cpos > 0) && !ISWORD(buf[cpos - 1])) {
2707 ttputc('\b');
2708 ttputc(' ');
2709 ttputc('\b');
2710 --ttcol;
2711 if (ISCTRL(buf[--cpos]) != FALSE) {
2712 ttputc('\b');
2713 ttputc(' ');
2714 ttputc('\b');
2715 --ttcol;
2716 }
2717 #ifdef KANJI /* 90.01.29 by S.Yoshida */
2718 else if (ISKANJI(buf[cpos])) {
2719 ttputc('\b');
2720 ttputc(' ');
2721 ttputc('\b');
2722 --ttcol;
2723 --cpos;
2724 }
2725 #endif /* KANJI */
2726 }
2727 while ((cpos > 0) && ISWORD(buf[cpos - 1])) {
2728 ttputc('\b');
2729 ttputc(' ');
2730 ttputc('\b');
2731 --ttcol;
2732 if (ISCTRL(buf[--cpos]) != FALSE) {
2733 ttputc('\b');
2734 ttputc(' ');
2735 ttputc('\b');
2736 --ttcol;
2737 }
2738 #ifdef KANJI /* 90.01.29 by S.Yoshida */
2739 else if (ISKANJI(buf[cpos])) {
2740 #ifdef HANKANA /* 92.11.21 by S.Sasaki */
2741 if (ISHANKANA(buf[--cpos])) {
2742 ttputc('\b');
2743 ttputc(' ');
2744 ttputc('\b');
2745 --ttcol;
2746 }
2747 #else /* not HANKANA */
2748 ttputc('\b');
2749 ttputc(' ');
2750 ttputc('\b');
2751 --ttcol;
2752 --cpos;
2753 #endif /* HANKANA */
2754 }
2755 #endif /* KANJI */
2756 }
2757 ttflush();
2758 break;
2759
2760 case CCHR('\\'):
2761 case CCHR('Q'): /* C-Q, quote next */
2762 c = getkey(FALSE); /* and continue */
2763 default: /* All the rest. */
2764 if (cpos < nbuf-1) {
2765 buf[cpos++] = (char) c;
2766 eputc((char) c);
2767 ttflush();
2768 }
2769 }
2770 }
2771 done: return buf[0] != '\0';
2772 }
2773
2774 /*
2775 * do completion on a list of objects.
2776 */
complt(flags,c,buf,cpos)2777 static int complt(flags, c, buf, cpos)
2778 register char *buf;
2779 register int cpos;
2780 {
2781 register LIST *lh, *lh2;
2782 int i, nxtra;
2783 int nhits, bxtra;
2784 int wflag = FALSE;
2785 int msglen, nshown;
2786 char *msg;
2787
2788 if ((flags&EFFUNC) != 0) {
2789 buf[cpos] = '\0';
2790 i = complete_function(buf, c);
2791 if(i>0) {
2792 eputs(&buf[cpos]);
2793 ttflush();
2794 return i;
2795 }
2796 switch(i) {
2797 case -3:
2798 msg = " [Ambiguous]";
2799 break;
2800 case -2:
2801 i=0;
2802 msg = " [No match]";
2803 break;
2804 case -1:
2805 case 0:
2806 return i;
2807 default:
2808 msg = " [Internal error]";
2809 break;
2810 }
2811 #ifndef NO_FILECOMP /* 90.04.04 by K.Maeda */
2812 } else if ((flags&EFFILE)!=0) {
2813 if (c != '\t' && c != ' ') panic("broken complt call: c");
2814 buf[cpos] = '\0';
2815 i = complete_filename(buf, cpos, c);
2816 if(i>0) {
2817 eputs(&buf[cpos]);
2818 ttflush();
2819 return i;
2820 }
2821 switch(i) {
2822 case -3:
2823 msg = " [Ambiguous]";
2824 break;
2825 case -2: /* no match */
2826 #ifdef HUMAN68K /* 90.11.15 Sawayanagi Yosirou */
2827 msg = " [No match]";
2828 break;
2829 #else /* NOT HUMAN68K */
2830 i=0;
2831 #endif /* HUMAN68K */
2832 case -1: /* single match */
2833 case 0:
2834 return i;
2835 default:
2836 msg = " [Internal error]";
2837 break;
2838 }
2839 #endif /* NO_FILECOMP */
2840 } else {
2841 if ((flags&EFBUF) != 0) lh = &(bheadp->b_list);
2842 else panic("broken complt call: flags");
2843
2844 if (c == ' ') wflag = TRUE;
2845 else if (c != '\t' && c != CCHR('M')) panic("broken complt call: c");
2846
2847 nhits = 0;
2848 nxtra = HUGE;
2849
2850 while (lh != NULL) {
2851 for (i=0; i<cpos; ++i) {
2852 if (buf[i] != lh->l_name[i])
2853 break;
2854 }
2855 if (i == cpos) {
2856 if (nhits == 0)
2857 lh2 = lh;
2858 ++nhits;
2859 if (lh->l_name[i] == '\0') nxtra = -1;
2860 else {
2861 bxtra = getxtra(lh, lh2, cpos, wflag);
2862 if (bxtra < nxtra) nxtra = bxtra;
2863 lh2 = lh;
2864 }
2865 }
2866 lh = lh->l_next;
2867 }
2868 if (nhits == 0)
2869 msg = " [No match]";
2870 else if (nhits > 1 && nxtra == 0)
2871 msg = " [Ambiguous]";
2872 else { /* Got a match, do it to it */
2873 /*
2874 * Being lazy - ought to check length, but all things
2875 * autocompleted have known types/lengths.
2876 */
2877 if (nxtra < 0 && nhits > 1 && c == ' ') nxtra = 1;
2878 for (i = 0; i < nxtra; ++i) {
2879 buf[cpos] = lh2->l_name[cpos];
2880 eputc(buf[cpos++]);
2881 }
2882 ttflush();
2883 if (nxtra < 0 && c != CCHR('M')) return 0;
2884 return nxtra;
2885 }
2886 }
2887 /* Set up backspaces, etc., being mindful of echo line limit */
2888 msglen = strlen(msg);
2889 nshown = (ttcol + msglen + 2 > ncol) ?
2890 ncol - ttcol - 2 : msglen;
2891 eputs(msg);
2892 ttcol -= (i = nshown); /* update ttcol! */
2893 while (i--) /* move back before msg */
2894 ttputc('\b');
2895 ttflush(); /* display to user */
2896 i = nshown;
2897 while (i--) /* blank out on next flush */
2898 eputc(' ');
2899 ttcol -= (i = nshown); /* update ttcol on BS's */
2900 while (i--)
2901 ttputc('\b'); /* update ttcol again! */
2902 return 0;
2903 }
2904
2905 /*
2906 * The "lp1" and "lp2" point to list structures. The
2907 * "cpos" is a horizontal position in the name.
2908 * Return the longest block of characters that can be
2909 * autocompleted at this point. Sometimes the two
2910 * symbols are the same, but this is normal.
2911 */
getxtra(lp1,lp2,cpos,wflag)2912 getxtra(lp1, lp2, cpos, wflag) register LIST *lp1, *lp2; register int wflag; {
2913 register int i;
2914
2915 i = cpos;
2916 for (;;) {
2917 if (lp1->l_name[i] != lp2->l_name[i]) break;
2918 if (lp1->l_name[i] == '\0') break;
2919 ++i;
2920 if (wflag && !ISWORD(lp1->l_name[i-1])) break;
2921 }
2922 return (i - cpos);
2923 }
2924 #endif /* NEW_COMPLETE */
2925
2926 /*
2927 * Special "printf" for the echo line.
2928 * Each call to "ewprintf" starts a new line in the
2929 * echo area, and ends with an erase to end of the
2930 * echo line. The formatting is done by a call
2931 * to the standard formatting routine.
2932 */
2933 /*VARARGS 0 */
2934 #ifdef SUPPORT_ANSI
2935 VOID
ewprintf(char * fp,...)2936 ewprintf(char *fp, ...)
2937 {
2938 va_list pvar;
2939
2940 #ifndef NO_MACRO
2941 if (inmacro)
2942 return;
2943 #endif
2944 va_start(pvar, fp);
2945 ttcolor(CTEXT);
2946 ttmove(nrow - 1, 0);
2947 eformat(fp, &pvar);
2948 va_end(pvar);
2949 tteeol();
2950 ttflush();
2951 epresf = TRUE;
2952 }
2953 #else /* SUPPORT_ANSI */
2954 VOID
ewprintf(va_alist)2955 ewprintf(va_alist)
2956 va_dcl
2957 {
2958 va_list pvar;
2959 register char *fp;
2960
2961 #ifndef NO_MACRO
2962 if(inmacro) return;
2963 #endif
2964 va_start(pvar);
2965 fp = va_arg(pvar, char *);
2966 ttcolor(CTEXT);
2967 ttmove(nrow-1, 0);
2968 eformat(fp, &pvar);
2969 va_end(pvar);
2970 tteeol();
2971 ttflush();
2972 epresf = TRUE;
2973 }
2974 #endif /* SUPPORT_ANSI */
2975
2976 /*
2977 * Printf style formatting. This is
2978 * called by both "ewprintf" and "ereply" to provide
2979 * formatting services to their clients. The move to the
2980 * start of the echo line, and the erase to the end of
2981 * the echo line, is done by the caller.
2982 * Note: %c works, and prints the "name" of the character.
2983 * %k prints the name of a key (and takes no arguments).
2984 */
2985 static VOID
eformat(fp,ap)2986 eformat(fp, ap)
2987 register char *fp;
2988 register va_list *ap;
2989 {
2990 register int c;
2991 char kname[NKNAME];
2992 char *keyname();
2993 char *cp;
2994
2995 while ((c = *fp++) != '\0') {
2996 if (c != '%')
2997 eputc(c);
2998 else {
2999 c = *fp++;
3000 switch (c) {
3001 case 'c':
3002 (VOID) keyname(kname, va_arg(*ap, int));
3003 eputs(kname);
3004 break;
3005
3006 case 'k':
3007 cp = kname;
3008 for(c=0; c < key.k_count; c++) {
3009 cp = keyname(cp, key.k_chars[c]);
3010 *cp++ = ' ';
3011 }
3012 *--cp = '\0';
3013 eputs(kname);
3014 break;
3015
3016 case 'd':
3017 eputi(va_arg(*ap, int), 10);
3018 break;
3019
3020 case 'o':
3021 eputi(va_arg(*ap, int), 8);
3022 break;
3023
3024 case 's':
3025 eputs(va_arg(*ap, char *));
3026 break;
3027
3028 case 'l':/* explicit longword */
3029 c = *fp++;
3030 switch(c) {
3031 case 'd':
3032 eputl((long)va_arg(*ap, long), 10);
3033 break;
3034 default:
3035 eputc(c);
3036 break;
3037 }
3038 break;
3039
3040 default:
3041 eputc(c);
3042 }
3043 }
3044 }
3045 }
3046
3047 /*
3048 * Put integer, in radix "r".
3049 */
3050 static VOID
eputi(i,r)3051 eputi(i, r)
3052 register int i;
3053 register int r;
3054 {
3055 register int q;
3056
3057 if(i<0) {
3058 eputc('-');
3059 i = -i;
3060 }
3061 if ((q=i/r) != 0)
3062 eputi(q, r);
3063 eputc(i%r+'0');
3064 }
3065
3066 /*
3067 * Put long, in radix "r".
3068 */
3069 static VOID
eputl(l,r)3070 eputl(l, r)
3071 register long l;
3072 register int r;
3073 {
3074 register long q;
3075
3076 if(l < 0) {
3077 eputc('-');
3078 l = -l;
3079 }
3080 if ((q=l/r) != 0)
3081 eputl(q, r);
3082 eputc((int)(l%r)+'0');
3083 }
3084
3085 /*
3086 * Put string.
3087 */
3088 static VOID
eputs(s)3089 eputs(s)
3090 register char *s;
3091 {
3092 register int c;
3093
3094 while ((c = *s++) != '\0')
3095 eputc(c);
3096 }
3097
3098 /*
3099 * Put character. Watch for
3100 * control characters, and for the line
3101 * getting too long.
3102 */
3103 static VOID
eputc(c)3104 eputc(c)
3105 register char c;
3106 {
3107 epresf = TRUE;
3108 #ifdef MINIBUF_EDIT
3109 if (ttcol <= (ncol-1)-1)
3110 #else
3111 if (ttcol+2 < ncol)
3112 #endif
3113 {
3114 if (ISCTRL(c)) {
3115 eputc('^');
3116 c = CCHR(c);
3117 }
3118 #ifdef KANJI /* 90.01.29 by S.Yoshida */
3119 #ifdef SS_SUPPORT /* 92.11.21 by S.Sasaki */
3120 {
3121 static int c1=0;
3122
3123 if (ISKANJI(c)) {
3124 #ifdef HOJO_KANJI
3125 if (ISHOJO(c)) {
3126 c1 = 2;
3127 ttcol--;
3128 } else
3129 #endif
3130 if (c1==0) c1=1;
3131 else c1--;
3132 } else c1=0;
3133 #ifdef HANKANA
3134 if (ISHANKANA(c) && c1 == 1)
3135 ttcol--;
3136 #endif
3137 }
3138 #endif /* SS_SUPPORT */
3139 kttputc(c);
3140 #else /* NOT KANJI */
3141 ttputc(c);
3142 #endif /* KANJI */
3143 ++ttcol;
3144 }
3145 }
3146
3147 #ifndef NEW_COMPLETE /* 90.12.10 Sawayanagi Yosirou */
3148 #ifndef NO_FILECOMP /* 90.04.04 by K.Maeda */
complete_filename(buf,cpos,c)3149 complete_filename(buf, cpos, c)
3150 char *buf;
3151 int cpos, c;
3152 {
3153 register int nhits, i, j;
3154 char *files, *try, *hit;
3155 int nxtra, wflag, bxtra, res;
3156
3157 if ((nhits=fffiles(buf, &files)) < 0)
3158 return -4; /* error */
3159 if (nhits == 0) {
3160 res = -2; /* no match */
3161 goto end;
3162 }
3163
3164 if (c == ' ') wflag = TRUE;
3165 else wflag = FALSE;
3166 nxtra = HUGE; hit = files;
3167
3168 for(try=files, i=0; i<nhits; i++) {
3169 if (try[cpos] == '\0') nxtra = -1;
3170 else {
3171 bxtra = cpos;
3172 for(;;) {
3173 if (try[bxtra] != hit[bxtra]) break;
3174 if (try[bxtra] == '\0') break;
3175 bxtra++;
3176 if (wflag && !ISWORD(try[bxtra-1])) break;
3177 }
3178 if (hit[bxtra] == '\0')
3179 hit = try;
3180 bxtra -= cpos;
3181 if (bxtra < nxtra) nxtra = bxtra;
3182 }
3183 try += strlen(try)+1;
3184 }
3185 if (nhits > 1 && nxtra == 0) {
3186 res = -3; /* ambiguous */
3187 goto end;
3188 }
3189 if (nxtra < 0 && nhits > 1 && c == ' ') nxtra = 1;
3190 if (nxtra >= 0) {
3191 for (i=cpos; i<cpos+nxtra; i++)
3192 buf[i] = hit[i];
3193 buf[i] = '\0';
3194 res = nxtra;
3195 } else { /* sole completion */
3196 for (i=cpos, j=strlen(files); i<j;) {
3197 buf[i] = files[i];
3198 i++;
3199 if (wflag && !ISWORD(buf[i-1]))
3200 break;
3201 }
3202 buf[i] = '\0';
3203 res = i-cpos;
3204 }
3205 end:
3206 free(files);
3207 return res;
3208 }
3209 #endif /* NO_FILECOMP */
3210 #endif /* NEW_COMPLETE */
3211