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