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