1 /* $Id: complt.c,v 1.9 2001/07/23 17:09:02 amura Exp $ */
2 /*
3  *	Complete completion functions.
4  */
5 
6 /*
7  * $Log: complt.c,v $
8  * Revision 1.9  2001/07/23 17:09:02  amura
9  * fix raise segmentation fault when completion after shell-command
10  *
11  * Revision 1.8  2001/05/25 15:36:52  amura
12  * now buffers have only one mark (before windows have one mark)
13  *
14  * Revision 1.7  2001/02/18 17:07:24  amura
15  * append AUTOSAVE feature (but NOW not work)
16  *
17  * Revision 1.6  2001/01/05 14:07:00  amura
18  * first implementation of Hojo Kanji support
19  *
20  * Revision 1.5  2000/11/04 13:43:30  amura
21  * estrlen definition is changed to K&R style
22  *
23  * Revision 1.4  2000/09/05 01:04:54  amura
24  * support HANKANA file and buffer
25  *
26  * Revision 1.3  2000/06/27 01:49:42  amura
27  * import to CVS
28  *
29  * Revision 1.2  2000/06/01  05:24:14  amura
30  * More robust
31  *
32  * Revision 1.1  1999/05/21  02:05:34  amura
33  * Initial revision
34  *
35  */
36 /* 90.12.10  Created by Sawayanagi Yosirou */
37 
38 #include    "config.h"
39 #ifdef	NEW_COMPLETE
40 #include    "def.h"
41 #include    "kbd.h"
42 #include    "complt.h"
43 #define    LIST_COL    35
44 
45 static BUFFER    *bp = NULL;
46 static BUFFER    *prev_bp = NULL;
47 static WINDOW    *prev_wp = NULL;
48 static WINDOW    prev_window;
49 
50 static int complete_funcname pro((char *));
51 static int complete_buffername pro((char *));
52 static int complete_filename pro((char *));
53 static int complete_list_funcnames pro((char *, BUFFER *));
54 static int complete_list_buffernames pro((char *, BUFFER *));
55 static int complete_list_filenames pro((char *, BUFFER *));
56 #ifdef	SS_SUPPORT
57 static int estrlen pro((char *));
58 #endif
59 
60 /*
61  * do some completion.
62  */
63 int
complete(buf,flags)64 complete (buf, flags)
65     char    *buf;
66     int    flags;
67 {
68     int    res;
69 
70     switch (flags & EFAUTO)
71       {
72       case EFFUNC:
73 	res = complete_funcname (buf);
74 	break;
75       case EFBUF:
76         res = complete_buffername (buf);
77 	break;
78       case EFFILE:
79 	res = complete_filename (buf);
80 	break;
81       default:
82 	res = 0; /* dummy to prevent compile time warning */
83         panic ("broken complete call: flags");
84       }
85 
86     return (res);
87 }
88 
89 char *
complete_message(matchnum)90 complete_message (matchnum)
91     int    matchnum;
92 {
93     char    *msg;
94 
95     switch (matchnum)
96       {
97       case COMPLT_NOT_UNIQUE:
98 	msg = " [Complete, but not unique]";
99 	break;
100       case COMPLT_AMBIGUOUS:
101 	msg = " [Ambiguous]";
102 	break;
103       case COMPLT_SOLE:
104 /*	msg = "";*/
105 	msg = " [Sole completion]";
106 	break;
107       case COMPLT_NO_MATCH:
108 	msg = " [No match]";
109 	break;
110       default:
111 	msg = " [Internal error]";
112       }
113 
114     return (msg);
115 }
116 
117 /* complete function name */
118 static int
complete_funcname(name)119 complete_funcname (name)
120     char    *name;
121 {
122     int    fnlen;
123     int    minlen = 0;
124     int    matchnum;
125     int    res;
126     int    i, j;
127     char    *cand;
128 
129     fnlen = strlen (name);
130 
131     /* compare names and make the common string of them */
132     matchnum = 0;
133     for (i = name_fent(name, TRUE); i < nfunct; i++)
134       {
135         cand = functnames[i].n_name;
136 	j = strncmp (cand, name, fnlen);
137         if (j < 0)
138 	  continue;
139         else if (j > 0)
140 	  break;	/* because functnames[] are in dictionary order */
141 
142 	if (matchnum == 0)
143 	  {
144 	    for (j = fnlen; cand[j] != '\0'; j++)
145 	      name[j] = cand[j];
146 	    name[j] = '\0';
147 	    minlen = j;
148 	  }
149 	else
150 	  {
151 	    for (j = fnlen; name[j] != '\0'; j++)
152               {
153 		if (cand[j] != name[j])
154 		    break;
155               }
156 	    name[j] = '\0';
157 	    if (cand[j] == '\0')
158 	        minlen = j;
159 	  }
160         matchnum++;
161       }
162 
163     if (matchnum > 1)
164       res = (minlen == (int) strlen (name)) ?
165 	     COMPLT_NOT_UNIQUE : COMPLT_AMBIGUOUS;
166     else if (matchnum == 1)
167       res = COMPLT_SOLE;
168     else if (matchnum == 0)
169       res = COMPLT_NO_MATCH;
170     else
171       res = -1;
172 
173     return (res);
174 }
175 
176 static int
complete_buffername(name)177 complete_buffername (name)
178     char    *name;
179 {
180     int    fnlen;
181     int    minlen = 0;
182     int    matchnum;
183     int    res;
184     int    j;
185     char    *cand;
186     LIST    *lh;
187 
188     fnlen = strlen (name);
189 
190     /* compare names and make the common string of them */
191     matchnum = 0;
192     for (lh = &(bheadp->b_list); lh != NULL; lh = lh->l_next)
193       {
194         cand = lh->l_name;
195         if (strncmp (cand, name, fnlen) != 0)
196 	  continue;
197 	if (matchnum == 0)
198 	  {
199 	    for (j = fnlen; cand[j] != '\0'; j++)
200 	      name[j] = cand[j];
201 	    name[j] = '\0';
202 	    minlen = j;
203 	  }
204 	else
205 	  {
206             for (j = fnlen; name[j] != '\0'; j++)
207               {
208                 if (cand[j] != name[j])
209 	          break;
210               }
211 	    name[j] = '\0';
212 	    if (cand[j] == '\0')
213 	        minlen = j;
214 	  }
215         matchnum++;
216       }
217 
218     if (matchnum > 1)
219       res = (minlen == (int) strlen (name)) ?
220 	    COMPLT_NOT_UNIQUE : COMPLT_AMBIGUOUS;
221     else if (matchnum == 1)
222       res = COMPLT_SOLE;
223     else if (matchnum == 0)
224       res = COMPLT_NO_MATCH;
225     else
226       res = -1;
227 
228     return (res);
229 }
230 
231 #ifndef NO_FILECOMP
232 static int
complete_filename(name)233 complete_filename (name)
234     char    *name;
235 {
236     int    fnlen;
237     int    minlen = 0;
238     int    matchnum;
239     int    res;
240     int    i, j;
241     int    fnnum;
242     char    *cand;
243     char    *filenames;
244     int    fffiles ();
245 
246     fnlen = strlen (name);
247 
248     if ((fnnum = fffiles (name, &filenames)) == -1)
249       return (-1);    /* error */
250 
251     /* compare names and make a common string of them */
252     matchnum = 0;
253     cand = filenames;
254     for (i = 0; i < fnnum; i++)
255       {
256 	if (matchnum == 0)
257 	  {
258 	    for (j = fnlen; cand[j] != '\0'; j++)
259 	      name[j] = cand[j];
260 	    name[j] = '\0';
261 	    minlen = j;
262 	  }
263 	else
264 	  {
265 	    for (j = fnlen; name[j] != '\0'; j++)
266               {
267 		if (cand[j] != name[j])
268 		  break;
269 	      }
270 	    name[j] = '\0';
271 	    if (cand[j] == '\0')
272 	        minlen = j;
273 	  }
274 	matchnum++;
275 	cand += (strlen (cand) + 1);
276       }
277     free (filenames);
278 
279     if (matchnum > 1)
280       res = (minlen == strlen (name)) ? COMPLT_NOT_UNIQUE : COMPLT_AMBIGUOUS;
281     else if (matchnum == 1)
282       res = COMPLT_SOLE;
283     else if (matchnum == 0)
284       res = COMPLT_NO_MATCH;
285     else
286       res = -1;
287 
288     return (res);
289 }
290 #endif	/* NO_FILECOMP */
291 
292 int
complete_list_names(buf,flags)293 complete_list_names (buf, flags)
294     char    *buf;
295     int    flags;
296 {
297     int    res;
298     int    cur_row;
299     int    cur_col;
300     WINDOW    *wp;
301 
302     if ((bp = bfind ("*Completions*", TRUE)) == NULL)
303       return (FALSE);
304 #ifdef	AUTOSAVE	/* 96.12.24 by M.Suzuki	*/
305     bp->b_flag &= ~(BFCHG|BFACHG);    /* avoid recursive veread */
306 #else
307     bp->b_flag &= ~BFCHG;    /* avoid recursive veread */
308 #endif	/* AUTOSAVE	*/
309     if (bclear (bp) != TRUE)
310       return (FALSE);
311 
312     if (addline(bp, "Possible completions are:") == FALSE)
313       return (FALSE);
314 
315     switch (flags & EFAUTO)
316       {
317       case EFFUNC:
318 	res = complete_list_funcnames (buf, bp);
319 	break;
320       case EFBUF:
321         res = complete_list_buffernames (buf, bp);
322 	break;
323       case EFFILE:
324 	res = complete_list_filenames (buf, bp);
325 	break;
326       default:
327         panic ("broken complete_list_names call: flags");
328       }
329 
330     cur_row = ttrow;
331     cur_col = ttcol;
332 
333     bp->b_dotp = lforw (bp->b_linep);	/* put dot at beginning of buffer */
334     bp->b_doto = 0;
335     /* setup window */
336     if (curwp->w_bufp != bp)
337       {
338 	if (wheadp->w_wndp == NULL)
339 	  {
340 	    if (splitwind (FFRAND, 0) == FALSE)
341 	      return (FALSE);
342 	    prev_wp = wheadp;
343 	    curwp = wheadp->w_wndp;
344 	    prev_bp = NULL;
345 	  }
346 	else
347 	  {
348             for (wp = wheadp; wp->w_wndp != NULL; wp = wp->w_wndp)
349               ;
350             prev_wp = curwp;
351 	    curwp = wp;
352 	    prev_bp = curwp->w_bufp;
353 	    prev_window.w_dotp = curwp->w_dotp;
354 	    prev_window.w_doto = curwp->w_doto;
355 	    if (prev_window.w_bufp) {
356 	      prev_window.w_bufp->b_markp = prev_bp->b_markp;
357 	      prev_window.w_bufp->b_marko = prev_bp->b_marko;
358 	    }
359 	  }
360       }
361     for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
362       {
363         if (wp->w_bufp == bp)
364 	  {
365 	    wp->w_flag |= WFMODE | WFFORCE | WFHARD;
366 	    wp->w_dotp = bp->b_dotp;
367 	    wp->w_doto = bp->b_doto;
368 	  }
369       }
370     curbp = bp;
371     if (showbuffer (bp, curwp, WFFORCE | WFHARD) == FALSE)
372       return (FALSE);
373 
374     update ();
375     ttmove (cur_row, cur_col);
376 
377     return (TRUE);
378 }
379 
380 static int
complete_list_funcnames(name,bp)381 complete_list_funcnames (name, bp)
382     char    *name;
383     BUFFER    *bp;
384 {
385     int    fnlen;
386     int    i, j;
387     char    *cand;
388     char    line[NFILEN];
389 
390     fnlen = strlen (name);
391 
392     line[0] = '\0';
393     for (i = name_fent(name, TRUE); i < nfunct; i++)
394       {
395         cand = functnames[i].n_name;
396 	j = strncmp (cand, name, fnlen);
397         if (j < 0)
398 	  continue;
399         else if (j > 0)
400 	  break;	/* because functnames[] are in dictionary order */
401 
402 	if (line[0] == '\0')
403 	  {
404 	    if (strlen (cand) < LIST_COL)
405 	      strcpy (line, cand);
406 	    else
407 	      addline (bp, cand);
408 	  }
409 	else
410 	  {
411 	    if (strlen (cand) < LIST_COL)
412 	      {
413 		for (j = strlen (line); j < LIST_COL; j++)
414 		  line[j] = ' ';
415 		line[j] = '\0';
416 		strcat (line, cand);
417 		addline (bp, line);
418 	      }
419 	    else
420 	      {
421 		addline (bp, line);
422 		addline (bp, cand);
423 	      }
424 	    line[0] = '\0';
425 	  }
426       }
427     if (line[0] != '\0')
428       addline (bp, line);
429     return (TRUE);
430 }
431 
432 static int
complete_list_buffernames(name,bp)433 complete_list_buffernames (name, bp)
434     char    *name;
435     BUFFER    *bp;
436 {
437     int    fnlen;
438     int    j;
439     char    *cand;
440     char    line[NFILEN];
441     LIST    *lh;
442 
443     fnlen = strlen (name);
444 
445     line[0] = '\0';
446     for (lh = &(bheadp->b_list); lh != NULL; lh = lh->l_next)
447       {
448         cand = lh->l_name;
449         if (strncmp (cand, name, fnlen) != 0)
450 	  continue;
451 
452 	if (line[0] == '\0')
453 	  {
454 #ifdef	SS_SUPPORT
455 	    if (estrlen (cand) < LIST_COL)
456 #else
457 	    if (strlen (cand) < LIST_COL)
458 #endif
459 	      strcpy (line, cand);
460 	    else
461 	      addline (bp, cand);
462 	  }
463 	else
464 	  {
465 #ifdef	SS_SUPPORT
466 	    if (estrlen (cand) < LIST_COL)
467 	      {
468 		int k = estrlen(line);
469 		for (j = strlen (line); k < LIST_COL; j++, k++)
470 #else
471 	    if (strlen (cand) < LIST_COL)
472 	      {
473 		for (j = strlen (line); j < LIST_COL; j++)
474 #endif
475 		  line[j] = ' ';
476 		line[j] = '\0';
477 		strcat (line, cand);
478 		addline (bp, line);
479 	      }
480 	    else
481 	      {
482 		addline (bp, line);
483 		addline (bp, cand);
484 	      }
485 	    line[0] = '\0';
486 	  }
487       }
488     if (line[0] != '\0')
489       addline (bp, line);
490     return (TRUE);
491 }
492 
493 static int
complete_list_filenames(name,bp)494 complete_list_filenames (name, bp)
495     char    *name;
496     BUFFER    *bp;
497 {
498     int    dnlen;
499     int    i, j;
500     int    fnnum;
501     char    *cand;
502     char    line[NFILEN];
503     char    *filenames;
504     int    fffiles ();
505     char    *file_name_part ();
506 
507     dnlen = file_name_part (name) - name;
508 
509     if ((fnnum = fffiles (name, &filenames)) == -1)
510       return (FALSE);    /* error */
511 
512     line[0] = '\0';
513     cand = filenames;
514     for (i = 0; i < fnnum; i++)
515       {
516 	cand += dnlen;
517 	if (line[0] == '\0')
518 	  {
519 #ifdef	SS_SUPPORT
520 	    if (estrlen (cand) < LIST_COL)
521 #else
522 	    if (strlen (cand) < LIST_COL)
523 #endif
524 	      strcpy (line, cand);
525 	    else
526 	      addline (bp, cand);
527 	  }
528 	else
529 	  {
530 #ifdef	SS_SUPPORT
531 	    if (estrlen (cand) < LIST_COL)
532 	      {
533 		int k = estrlen(line);
534 		for (j = strlen (line); k < LIST_COL; j++, k++)
535 #else
536 	    if (strlen (cand) < LIST_COL)
537 	      {
538 		for (j = strlen (line); j < LIST_COL; j++)
539 #endif
540 		  line[j] = ' ';
541 		line[j] = '\0';
542 		strcat (line, cand);
543 		addline (bp, line);
544 	      }
545 	    else
546 	      {
547 		addline (bp, line);
548 		addline (bp, cand);
549 	      }
550 	    line[0] = '\0';
551 	  }
552 	cand += (strlen (cand) + 1);
553       }
554     if (line[0] != '\0')
555       addline (bp, line);
556     free (filenames);
557     return (TRUE);
558 }
559 
560 int
complete_del_list()561 complete_del_list ()
562 {
563     int    cur_row;
564     int    cur_col;
565 
566     if (bp == NULL)
567       return (FALSE);
568     cur_row = ttrow;
569     cur_col = ttcol;
570     if (prev_bp == NULL)
571       {
572         if (wheadp->w_wndp != NULL)
573 	  delwind (FFRAND, 0);
574       }
575     else
576       {
577 	curbp = prev_bp;
578 	showbuffer (prev_bp, curwp, WFFORCE | WFHARD);
579 	curwp->w_dotp = prev_window.w_dotp;
580 	curwp->w_doto = prev_window.w_doto;
581 	curwp->w_flag |= WFMOVE;
582 	curwp = prev_wp;
583 	curbp = curwp->w_bufp;
584 	if (prev_window.w_bufp) {
585 	  curbp->b_markp = prev_window.w_bufp->b_markp;
586 	  curbp->b_marko = prev_window.w_bufp->b_marko;
587 	}
588       }
589     bp = NULL;
590     prev_wp = NULL;
591     prev_bp = NULL;
592     update ();
593     ttmove (cur_row, cur_col);
594     /* 91.01.17  Add to delete *Completions* buffer. by S.Yoshida */
595     eargset("*Completions*");
596     killbuffer(0, 1);
597 
598     return (TRUE);
599 }
600 
601 int
complete_scroll_up()602 complete_scroll_up ()
603 {
604     int    cur_row;
605     int    cur_col;
606 
607     if (bp == NULL)
608       return (FALSE);
609     cur_row = ttrow;
610     cur_col = ttcol;
611     backpage (FFRAND, 0);
612     update ();
613     ttmove (cur_row, cur_col);
614     return (TRUE);
615 }
616 
617 int
complete_scroll_down()618 complete_scroll_down ()
619 {
620     int    cur_row;
621     int    cur_col;
622 
623     if (bp == NULL)
624       return (FALSE);
625     cur_row = ttrow;
626     cur_col = ttcol;
627     forwpage (FFRAND, 0);
628     update ();
629     ttmove (cur_row, cur_col);
630     return (TRUE);
631 }
632 
633 #ifdef	SS_SUPPORT
634 static int
estrlen(str)635 estrlen(str)
636 char *str;
637 {
638     int i = 0;
639     while (*str)
640     {
641 #ifdef	HANKANA
642 	if (ISHANKANA(*str))
643 	    ;
644 	else
645 #endif
646 #ifdef	HOJO_KANJI
647 	if (ISHOJO(*str))
648 	    ;
649 	else
650 #endif
651 	    i++;
652 	str++;
653     }
654     return i;
655 }
656 #endif	/* SS_SUPPORT */
657 #endif	/* NEW_COMPLETE */
658