/* */
This source file includes following definitions.
- command
- clearprompt
- readrefs
- changestring
- mark
- scrollbar
- countrefs
1 /*===========================================================================
2 Copyright (c) 1998-2000, The Santa Cruz Operation
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 *Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10
11 *Redistributions in binary form must reproduce the above copyright notice,
12 this list of conditions and the following disclaimer in the documentation
13 and/or other materials provided with the distribution.
14
15 *Neither name of The Santa Cruz Operation nor the names of its contributors
16 may be used to endorse or promote products derived from this software
17 without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
20 IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 INTERRUPTION)
27 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
30 DAMAGE.
31 =========================================================================*/
32
33 /** @file
34 * command functions
35 *
36 * @NAME{gtags-cscope} - interactive C symbol or text cross-reference (@NAME{cscope})
37 */
38
39 #include "global-cscope.h"
40 #include "gparam.h"
41 #include "pathconvert.h"
42 #include "build.h" /* for rebuild() */
43 #include "alloc.h"
44
45 #include <stdlib.h>
46 #if defined(USE_NCURSES) && !defined(RENAMED_NCURSES)
47 #include <ncurses.h>
48 #else
49 #include <curses.h>
50 #endif
51 #include <ctype.h>
52
53 static char const rcsid[] = "$Id: command.c,v 1.9 2012/10/13 07:01:58 shigio Exp $";
54
55
56 int selecting;
57 unsigned int curdispline = 0;
58
59 BOOL caseless; /**< ignore letter case when searching */
60 BOOL *change; /**< change this line */
61 BOOL changing; /**< changing text */
62 char newpat[PATLEN + 1]; /**< new pattern */
63 /* HBB 20040430: renamed to avoid lots of clashes with function arguments
64 * also named 'pattern' */
65 char Pattern[PATLEN + 1]; /**< symbol or text pattern */
66
67 /* HBB FIXME 20060419: these should almost certainly be const */
68 static char appendprompt[] = "Append to file: ";
69 static char pipeprompt[] = "Pipe to shell command: ";
70 static char readprompt[] = "Read from file: ";
71 static char globalprompt[] = "Read from: global ";
72 static char globaloption[] = "--encode-path=\" \t\" --result=cscope";
73 static char globalcommand[MAXFILLEN];
74 static char toprompt[] = "To: ";
75
76
77 /* Internal prototypes: */
78 static BOOL changestring(void);
79 static void clearprompt(void);
80 static void mark(unsigned int i);
81 static void scrollbar(MOUSE *p);
82
83
84 /** execute the command */
85 BOOL
86 command(int commandc)
87 {
88 char filename[PATHLEN + 1]; /* file path name */
89 MOUSE *p; /* mouse data */
90 int c, i;
91 FILE *file;
92 struct cmd *curritem, *item; /* command history */
93 char *s;
94
95 switch (commandc) {
96 case ctrl('C'): /* toggle caseless mode */
97 if (caseless == NO) {
98 caseless = YES;
99 postmsg2("Caseless mode is now ON");
100 } else {
101 caseless = NO;
102 postmsg2("Caseless mode is now OFF");
103 }
104 return(NO);
105
106 case ctrl('R'): /* rebuild the cross reference */
107 if (isuptodate == YES) {
108 postmsg("The -d option prevents rebuilding the symbol database");
109 return(NO);
110 }
111 postmsg("Rebuilding cross-reference...");
112 rebuild();
113 postmsg("");
114 totallines = 0;
115 disprefs = 0;
116 topline = nextline = 1;
117 selecting = 0;
118 break;
119
120 #if UNIXPC
121 case ESC: /* possible unixpc mouse selection */
122 #endif
123 case ctrl('X'): /* mouse selection */
124 if ((p = getmouseaction(DUMMYCHAR)) == NULL) {
125 return(NO); /* unknown control sequence */
126 }
127 /* if the button number is a scrollbar tag */
128 if (p->button == '0') {
129 scrollbar(p);
130 break;
131 }
132 /* ignore a sweep */
133 if (p->x2 >= 0) {
134 return(NO);
135 }
136 /* if this is a line selection */
137 if (p->y1 < FLDLINE) {
138
139 /* find the selected line */
140 /* note: the selection is forced into range */
141 for (i = disprefs - 1; i > 0; --i) {
142 if (p->y1 >= displine[i]) {
143 break;
144 }
145 }
146 /* display it in the file with the editor */
147 editref(i);
148 } else { /* this is an input field selection */
149 field = p->y1 - FLDLINE;
150 /* force it into range */
151 if (field >= FIELDS) {
152 field = FIELDS - 1;
153 }
154 setfield();
155 resetcmd();
156 return(NO);
157 }
158 break;
159
160 case '\t': /* go to next input field */
161 if (disprefs) {
162 selecting = !selecting;
163 if (selecting) {
164 move(displine[curdispline], 0);
165 refresh();
166 } else {
167 atfield();
168 resetcmd();
169 }
170 }
171 return(NO);
172
173 #ifdef KEY_ENTER
174 case KEY_ENTER:
175 #endif
176 case '\r':
177 case '\n': /* go to reference */
178 if (selecting) {
179 editref(curdispline);
180 return(YES);
181 }
182 /* FALLTHROUGH */
183
184 case ctrl('N'):
185 #ifdef KEY_DOWN
186 case KEY_DOWN:
187 #endif
188 #ifdef KEY_RIGHT
189 case KEY_RIGHT:
190 #endif
191 if (selecting) {
192 if ((curdispline + 1) < disprefs) {
193 move(displine[++curdispline], 0);
194 refresh();
195 }
196 } else {
197 field = (field + 1) % FIELDS;
198 if (field == 2)
199 field = 3;
200 setfield();
201 atfield();
202 resetcmd();
203 }
204 return(NO);
205
206 case ctrl('P'): /* go to previous input field */
207 #ifdef KEY_UP
208 case KEY_UP:
209 #endif
210 #ifdef KEY_LEFT
211 case KEY_LEFT:
212 #endif
213 if (selecting) {
214 if (curdispline) {
215 move(displine[--curdispline], 0);
216 refresh();
217 }
218 } else {
219 field = (field + (FIELDS - 1)) % FIELDS;
220 if (field == 2)
221 field = 1;
222 setfield();
223 atfield();
224 resetcmd();
225 }
226 return(NO);
227 #ifdef KEY_HOME
228 case KEY_HOME: /* go to first input field */
229 if (selecting) {
230 curdispline = 0;
231 move(REFLINE, 0);
232 refresh();
233 } else {
234 field = 0;
235 setfield();
236 atfield();
237 resetcmd();
238 }
239 return(NO);
240 #endif
241
242 #ifdef KEY_LL
243 case KEY_LL: /* go to last input field */
244 if (selecting) {
245 move(displine[disprefs - 1], 0);
246 refresh();
247 } else {
248 field = FIELDS - 1;
249 setfield();
250 atfield();
251 resetcmd();
252 }
253 return(NO);
254 #endif /* def(KEY_LL) */
255
256 case ' ': /* display next page */
257 case '+':
258 case ctrl('V'):
259 #ifdef KEY_NPAGE
260 case KEY_NPAGE:
261 #endif
262 /* don't redisplay if there are no lines */
263 if (totallines == 0) {
264 return(NO);
265 }
266 /* note: seekline() is not used to move to the next
267 * page because display() leaves the file pointer at
268 * the next page to optimize paging forward
269 */
270 curdispline = 0;
271 break;
272
273 case ctrl('H'):
274 case '-': /* display previous page */
275 #ifdef KEY_PPAGE
276 case KEY_PPAGE:
277 #endif
278 /* don't redisplay if there are no lines */
279 if (totallines == 0) {
280 return(NO);
281 }
282
283 curdispline = 0;
284
285 /* if there are only two pages, just go to the other one */
286 if (totallines <= 2 * mdisprefs) {
287 break;
288 }
289 /* if on first page but not at beginning, go to beginning */
290 nextline -= mdisprefs; /* already at next page */
291 if (nextline > 1 && nextline <= mdisprefs) {
292 nextline = 1;
293 } else {
294 nextline -= mdisprefs;
295 if (nextline < 1) {
296 nextline = totallines - mdisprefs + 1;
297 if (nextline < 1) {
298 nextline = 1;
299 }
300 }
301 }
302 seekline(nextline);
303 break;
304
305 case '>': /* write or append the lines to a file */
306 if (totallines == 0) {
307 postmsg("There are no lines to write to a file");
308 } else { /* get the file name */
309 move(PRLINE, 0);
310 addstr("Write to file: ");
311 s = "w";
312 if ((c = mygetch()) == '>') {
313 move(PRLINE, 0);
314 addstr(appendprompt);
315 c = '\0';
316 s = "a";
317 }
318 if (c != '\r' &&
319 mygetline("", newpat,
320 COLS - sizeof(appendprompt), c, NO) > 0
321 ) {
322 shellpath(filename, sizeof(filename), newpat);
323 if ((file = myfopen(filename, s)) == NULL) {
324 cannotopen(filename);
325 } else {
326 seekline(1);
327 while ((c = getc(refsfound)) != EOF) {
328 putc(c, file);
329 }
330 seekline(topline);
331 fclose(file);
332 }
333 }
334 clearprompt();
335 }
336 return(NO); /* return to the previous field */
337
338 case '<': /* read lines from a file */
339 move(PRLINE, 0);
340 addstr(readprompt);
341 if (mygetline("", newpat, COLS - sizeof(readprompt),
342 '\0', NO) > 0) {
343 clearprompt();
344 shellpath(filename, sizeof(filename), newpat);
345 if (readrefs(filename) == NO) {
346 postmsg2("Ignoring an empty file");
347 return(NO);
348 }
349 return(YES);
350 }
351 clearprompt();
352 return(NO);
353
354 case '^': /* pipe the lines through a shell command */
355 case '|': /* pipe the lines to a shell command */
356 if (totallines == 0) {
357 postmsg("There are no lines to pipe to a shell command");
358 return(NO);
359 }
360 /* get the shell command */
361 move(PRLINE, 0);
362 addstr(pipeprompt);
363 if (mygetline("", newpat, COLS - sizeof(pipeprompt), '\0', NO)
364 == 0) {
365 clearprompt();
366 return(NO);
367 }
368 /* if the ^ command, redirect output to a temp file */
369 if (commandc == '^') {
370 strcat(strcat(newpat, " >"), temp2);
371 /* HBB 20020708: somebody might have even
372 * their non-interactive default shells
373 * complain about clobbering
374 * redirections... --> delete before
375 * overwriting */
376 remove(temp2);
377 }
378 exitcurses();
379 if ((file = mypopen(newpat, "w")) == NULL) {
380 fprintf(stderr, "\
381 cscope: cannot open pipe to shell command: %s\n", newpat);
382 } else {
383 seekline(1);
384 while ((c = getc(refsfound)) != EOF) {
385 putc(c, file);
386 }
387 seekline(topline);
388 mypclose(file);
389 }
390 if (commandc == '^') {
391 if (readrefs(temp2) == NO) {
392 postmsg("Ignoring empty output of ^ command");
393 }
394 }
395 askforreturn();
396 entercurses();
397 break;
398 case ctrl('G'): /* read from the result of global command */
399 /* get the shell command */
400 move(PRLINE, 0);
401 addstr(globalprompt);
402 /* addstr(globaloption);*/
403 if (mygetline("", newpat, COLS - sizeof(globalprompt), '\0', NO) == 0) {
404 clearprompt();
405 return(NO);
406 }
407 snprintf(globalcommand, sizeof(globalcommand), "%s %s %s > %s", global_command, globaloption, newpat, temp2);
408 remove(temp2);
409 postmsg("Searching ...");
410 if (system(globalcommand) != 0) {
411 postmsg("Ignoring failed output of global command");
412 clearprompt();
413 return(NO);
414 }
415 if (readrefs(temp2) == NO) {
416 postmsg("Ignoring empty output of global command");
417 clearprompt();
418 return(NO);
419 }
420 curdispline = 0;
421 return(YES);
422 break;
423 #if defined(KEY_RESIZE) && !defined(__DJGPP__)
424 case KEY_RESIZE:
425 exitcurses();
426 initscr();
427 entercurses();
428 #if TERMINFO
429 keypad(stdscr, TRUE); /* enable the keypad */
430 #ifdef HAVE_FIXKEYPAD
431 fixkeypad(); /* fix for getch() intermittently returning garbage */
432 #endif
433 #endif
434 #if UNIXPC
435 standend(); /* turn off reverse video */
436 #endif
437 dispinit(); /* initialize display parameters */
438 setfield(); /* set the initial cursor position */
439 postmsg(""); /* clear any build progress message */
440 display(); /* display the version number and input fields */
441 break;
442 #endif
443 case ctrl('L'): /* redraw screen */
444 #ifdef KEY_CLEAR
445 case KEY_CLEAR:
446 #endif
447 clearmsg2();
448 clearok(curscr, TRUE);
449 wrefresh(curscr);
450 drawscrollbar(topline, bottomline);
451 return(NO);
452
453 case '!': /* shell escape */
454 execute(shell, shell, NULL);
455 seekline(topline);
456 break;
457
458 case '?': /* help */
459 clear();
460 help();
461 clear();
462 seekline(topline);
463 break;
464
465 case ctrl('E'): /* edit all lines */
466 editall();
467 break;
468
469 case ctrl('A'): /* HBB 20050428: added alt. keymapping */
470 case ctrl('Y'): /* repeat last pattern */
471 if (*Pattern != '\0') {
472 addstr(Pattern);
473 goto repeat;
474 }
475 break;
476
477 case ctrl('B'): /* cmd history back */
478 case ctrl('F'): /* cmd history fwd */
479 if (selecting)
480 return(NO);
481
482 curritem = currentcmd();
483 item = (commandc == ctrl('F')) ? nextcmd() : prevcmd();
484 clearmsg2();
485 if (curritem == item) { /* inform user that we're at history end */
486 postmsg2("End of input field and search pattern history");
487 }
488 if (item) {
489 field = item->field;
490 setfield();
491 atfield();
492 addstr(item->text);
493 strcpy(Pattern, item->text);
494 switch (c = mygetch()) {
495 case '\r':
496 case '\n':
497 goto repeat;
498 case ctrl('F'):
499 case ctrl('B'):
500 myungetch(c);
501 atfield();
502 clrtoeol(); /* clear current field */
503 break;
504 default:
505 myungetch(c);
506 if (mygetline(Pattern, newpat, COLS - fldcolumn - 1, '\0', caseless )) {
507 strcpy (Pattern, newpat);
508 resetcmd();
509 }
510 goto repeat;
511 break;
512 }
513 }
514 return(NO);
515
516 case '\\': /* next character is not a command */
517 addch('\\'); /* display the quote character */
518
519 /* get a character from the terminal */
520 if ((commandc = mygetch()) == EOF) {
521 return(NO); /* quit */
522 }
523 addstr("\b \b"); /* erase the quote character */
524 goto ispat;
525
526 case '.':
527 postmsg("The . command has been replaced by ^Y");
528 atfield(); /* move back to the input field */
529 /* FALLTHROUGH */
530 default:
531 if (selecting && !mouse) {
532 char *c;
533
534 if ((c = strchr(dispchars, commandc)))
535 editref(c - dispchars);
536
537 /* if this is the start of a pattern */
538 } else if (isprint(commandc)) {
539 ispat:
540 if (mygetline("", newpat, COLS - fldcolumn - 1,
541 commandc, caseless) > 0) {
542 strcpy(Pattern, newpat);
543 resetcmd(); /* reset command history */
544 repeat:
545 addcmd(field, Pattern); /* add to command history */
546 if (field == CHANGE) {
547 /* prompt for the new text */
548 move(PRLINE, 0);
549 addstr(toprompt);
550 mygetline("", newpat,
551 COLS - sizeof(toprompt),
552 '\0', NO);
553 }
554 /* search for the pattern */
555 if (search() == YES) {
556 curdispline = 0;
557 ++selecting;
558
559 switch (field) {
560 case DEFINITION:
561 case FILENAME:
562 if (totallines > 1) {
563 break;
564 }
565 topline = 1;
566 editref(0);
567 break;
568 case CHANGE:
569 return(changestring());
570 }
571
572 } else if (field == FILENAME &&
573 access(newpat, READ) == 0) {
574 /* try to edit the file anyway */
575 edit(newpat, "1");
576 }
577 } else { /* no pattern--the input was erased */
578 return(NO);
579 }
580 } else { /* control character */
581 return(NO);
582 }
583 } /* switch(commandc) */
584 return(YES);
585 }
586
587 /** clear the prompt line */
588
589 static void
590 clearprompt(void)
591 {
592 move(PRLINE, 0);
593 clrtoeol();
594 }
595
596 /** read references from a file */
597
598 BOOL
599 readrefs(char *filename)
600 {
601 FILE *file;
602 int c;
603
604 if ((file = myfopen(filename, "rb")) == NULL) {
605 cannotopen(filename);
606 return(NO);
607 }
608 if ((c = getc(file)) == EOF) { /* if file is empty */
609 return(NO);
610 }
611 totallines = 0;
612 disprefs = 0;
613 nextline = 1;
614 if (writerefsfound() == YES) {
615 putc(c, refsfound);
616 while ((c = getc(file)) != EOF) {
617 putc(c, refsfound);
618 }
619 fclose(file);
620 fclose(refsfound);
621 if ( (refsfound = myfopen(temp1, "rb")) == NULL) {
622 cannotopen(temp1);
623 return(NO);
624 }
625 countrefs();
626 }
627 return(YES);
628 }
629
630 /** change one text string to another */
631
632 static BOOL
633 changestring(void)
634 {
635 char newfile[PATHLEN + 1]; /* new file name */
636 char oldfile[PATHLEN + 1]; /* old file name */
637 char linenum[NUMLEN + 1]; /* file line number */
638 char msg[MSGLEN + 1]; /* message */
639 FILE *script; /* shell script file */
640 BOOL anymarked = NO; /* any line marked */
641 MOUSE *p; /* mouse data */
642 int c;
643 unsigned int i;
644 char *s;
645
646 /* open the temporary file */
647 if ((script = myfopen(temp2, "w")) == NULL) {
648 cannotopen(temp2);
649 return(NO);
650 }
651 /* create the line change indicators */
652 change = mycalloc(totallines, sizeof(BOOL));
653 changing = YES;
654 mousemenu();
655
656 /* until the quit command is entered */
657 for (;;) {
658 /* display the current page of lines */
659 display();
660 same:
661 atchange();
662
663 /* get a character from the terminal */
664 if ((c = mygetch()) == EOF
665 || c == ctrl('D')
666 || c == ctrl('Z')) {
667 break; /* change lines */
668 }
669 /* see if the input character is a command */
670 switch (c) {
671 case ' ': /* display next page */
672 case '+':
673 case ctrl('V'):
674 #ifdef KEY_NPAGE
675 case KEY_NPAGE:
676 #endif
677 case '-': /* display previous page */
678 #ifdef KEY_PPAGE
679 case KEY_PPAGE:
680 #endif
681 case '!': /* shell escape */
682 case '?': /* help */
683 command(c);
684 break;
685
686 case ctrl('L'): /* redraw screen */
687 #ifdef KEY_CLEAR
688 case KEY_CLEAR:
689 #endif
690 command(c);
691 goto same;
692
693 case ESC: /* don't change lines */
694 #if UNIXPC
695 if((p = getmouseaction(DUMMYCHAR)) == NULL) {
696 goto nochange; /* unknown escape sequence */
697 }
698 break;
699 #endif
700 case ctrl('G'):
701 goto nochange;
702
703 case '*': /* mark/unmark all displayed lines */
704 for (i = 0; topline + i < nextline; ++i) {
705 mark(i);
706 }
707 goto same;
708
709 case ctrl('A'): /* mark/unmark all lines */
710 for (i = 0; i < totallines; ++i) {
711 if (change[i] == NO) {
712 change[i] = YES;
713 } else {
714 change[i] = NO;
715 }
716 }
717 /* show that all have been marked */
718 seekline(totallines);
719 break;
720
721 case ctrl('X'): /* mouse selection */
722 if ((p = getmouseaction(DUMMYCHAR)) == NULL) {
723 goto same; /* unknown control sequence */
724 }
725 /* if the button number is a scrollbar tag */
726 if (p->button == '0') {
727 scrollbar(p);
728 break;
729 }
730 /* find the selected line */
731 /* note: the selection is forced into range */
732 for (i = disprefs - 1; i > 0; --i) {
733 if (p->y1 >= displine[i]) {
734 break;
735 }
736 }
737 mark(i);
738 goto same;
739
740 default:
741 {
742 /* if a line was selected */
743 char *cc;
744
745 if ((cc = strchr(dispchars, c)))
746 mark(cc - dispchars);
747
748 goto same;
749 } /* default case */
750 } /* switch(change code character) */
751 } /* for(ever) */
752
753 /* for each line containing the old text */
754 fprintf(script, "ed - <<\\!\n");
755 *oldfile = '\0';
756 seekline(1);
757 for (i = 0;
758 fscanf(refsfound, "%" PATHLEN_STR "s%*s%" NUMLEN_STR "s%*[^\n]", newfile, linenum) == 2;
759 ++i) {
760 strcpy(newfile, decode_path(newfile));
761 /* see if the line is to be changed */
762 if (change[i] == YES) {
763 anymarked = YES;
764
765 /* if this is a new file */
766 if (strcmp(newfile, oldfile) != 0) {
767
768 /* make sure it can be changed */
769 if (access(newfile, WRITE) != 0) {
770 snprintf(msg, sizeof(msg), "Cannot write to file %s", newfile);
771 postmsg(msg);
772 anymarked = NO;
773 break;
774 }
775 /* if there was an old file */
776 if (*oldfile != '\0') {
777 fprintf(script, "w\n"); /* save it */
778 }
779 /* edit the new file */
780 strcpy(oldfile, newfile);
781 fprintf(script, "e %s\n", oldfile);
782 }
783 /* output substitute command */
784 fprintf(script, "%ss/", linenum); /* change */
785 for (s = Pattern; *s != '\0'; ++s) {
786 /* old text */
787 if (strchr("/\\[.^*", *s) != NULL) {
788 putc('\\', script);
789 }
790 if (caseless == YES && isalpha((unsigned char)*s)) {
791 putc('[', script);
792 if(islower((unsigned char)*s)) {
793 putc(toupper((unsigned char)*s), script);
794 putc(*s, script);
795 } else {
796 putc(*s, script);
797 putc(tolower((unsigned char)*s), script);
798 }
799 putc(']', script);
800 } else
801 putc(*s, script);
802 }
803 putc('/', script); /* to */
804 for (s = newpat; *s != '\0'; ++s) { /* new text */
805 if (strchr("/\\&", *s) != NULL) {
806 putc('\\', script);
807 }
808 putc(*s, script);
809 }
810 fprintf(script, "/gp\n"); /* and print */
811 }
812 }
813 fprintf(script, "w\nq\n!\n"); /* write and quit */
814 fclose(script);
815
816 /* if any line was marked */
817 if (anymarked == YES) {
818
819 /* edit the files */
820 clearprompt();
821 refresh();
822 fprintf(stderr, "Changed lines:\n\r");
823 execute("sh", "sh", temp2, NULL);
824 askforreturn();
825 seekline(1);
826 } else {
827 nochange:
828 clearprompt();
829 }
830 changing = NO;
831 mousemenu();
832 free(change);
833 return(anymarked);
834 }
835
836
837 /** mark/unmark this displayed line to be changed */
838 static void
839 mark(unsigned int i)
840 {
841 unsigned int j;
842
843 j = i + topline - 1;
844 if (j < totallines) {
845 move(displine[i], 1);
846
847 if (change[j] == NO) {
848 change[j] = YES;
849 addch('>');
850 } else {
851 change[j] = NO;
852 addch(' ');
853 }
854 }
855 }
856
857
858 /** scrollbar actions */
859 static void
860 scrollbar(MOUSE *p)
861 {
862 /* reposition list if it makes sense */
863 if (totallines == 0) {
864 return;
865 }
866 switch (p->percent) {
867
868 case 101: /* scroll down one page */
869 if (nextline + mdisprefs > totallines) {
870 nextline = totallines - mdisprefs + 1;
871 }
872 break;
873
874 case 102: /* scroll up one page */
875 nextline = topline - mdisprefs;
876 if (nextline < 1) {
877 nextline = 1;
878 }
879 break;
880
881 case 103: /* scroll down one line */
882 nextline = topline + 1;
883 break;
884
885 case 104: /* scroll up one line */
886 if (topline > 1) {
887 nextline = topline - 1;
888 }
889 break;
890 default:
891 nextline = p->percent * totallines / 100;
892 }
893 seekline(nextline);
894 }
895
896
897 /** count the references found */
898 void
899 countrefs(void)
900 {
901 char *subsystem; /* OGS subsystem name */
902 char *book; /* OGS book name */
903 char file[PATHLEN + 1]; /* file name */
904 char function[PATLEN + 1]; /* function name */
905 char linenum[NUMLEN + 1]; /* line number */
906 int i;
907
908 /* count the references found and find the length of the file,
909 function, and line number display fields */
910 subsystemlen = 9; /* strlen("Subsystem") */
911 booklen = 4; /* strlen("Book") */
912 filelen = 4; /* strlen("File") */
913 fcnlen = 8; /* strlen("Function") */
914 numlen = 0;
915 while ((i = fscanf(refsfound, "%250s%250s%5s %5000[^\n]", file,
916 function, linenum, tempstring)) != EOF) {
917 if (i != 4 ||
918 !isgraph((unsigned char) *file) ||
919 !isgraph((unsigned char) *function) ||
920 !isdigit((unsigned char) *linenum)) {
921 postmsg("File does not have expected format");
922 totallines = 0;
923 disprefs = 0;
924 return;
925 }
926 if ((i = strlen(pathcomponents(file, dispcomponents))) > filelen) {
927 filelen = i;
928 }
929 if (ogs == YES) {
930 ogsnames(file, &subsystem, &book);
931 if ((i = strlen(subsystem)) > subsystemlen) {
932 subsystemlen = i;
933 }
934 if ((i = strlen(book)) > booklen) {
935 booklen = i;
936 }
937 }
938 if ((i = strlen(function)) > fcnlen) {
939 fcnlen = i;
940 }
941 if ((i = strlen(linenum)) > numlen) {
942 numlen = i;
943 }
944 ++totallines;
945 }
946 rewind(refsfound);
947
948 /* restrict the width of displayed columns */
949 /* HBB FIXME 20060419: magic number alert! */
950 i = (COLS - 5) / 3;
951 if (ogs == YES) {
952 i = (COLS - 7) / 5;
953 }
954 if (filelen > i && i > 4) {
955 filelen = i;
956 }
957 if (subsystemlen > i && i > 9) {
958 subsystemlen = i;
959 }
960 if (booklen > i && i > 4) {
961 booklen = i;
962 }
963 if (fcnlen > i && i > 8) {
964 fcnlen = i;
965 }
966 }
/* */