2023-07-27 14:04:50 -04:00
|
|
|
/*===========================================================================
|
|
|
|
Copyright (c) 1998-2000, The Santa Cruz Operation
|
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
|
|
|
|
*Redistributions of source code must retain the above copyright notice,
|
|
|
|
this list of conditions and the following disclaimer.
|
|
|
|
|
|
|
|
*Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
this list of conditions and the following disclaimer in the documentation
|
|
|
|
and/or other materials provided with the distribution.
|
|
|
|
|
|
|
|
*Neither name of The Santa Cruz Operation nor the names of its contributors
|
|
|
|
may be used to endorse or promote products derived from this software
|
|
|
|
without specific prior written permission.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
|
|
|
|
IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
|
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
|
|
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
|
|
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
INTERRUPTION)
|
|
|
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
|
|
DAMAGE.
|
|
|
|
=========================================================================*/
|
|
|
|
|
|
|
|
/* cscope - interactive C symbol cross-reference
|
|
|
|
*
|
|
|
|
* display functions
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "global.h"
|
|
|
|
#include "build.h"
|
|
|
|
|
|
|
|
#ifdef CCS
|
|
|
|
#include "sgs.h" /* ESG_PKG and ESG_REL */
|
|
|
|
#else
|
|
|
|
#include "version.h" /* FILEVERSION and FIXVERSION */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <ncurses.h>
|
|
|
|
#include <setjmp.h> /* jmp_buf */
|
|
|
|
#include <stdarg.h> /* va_list stuff */
|
|
|
|
#include <time.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdarg.h>
|
2023-07-29 09:40:48 -04:00
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
int subsystemlen = sizeof("Subsystem")-1; /* OGS subsystem name display field length */
|
|
|
|
int booklen = sizeof("Book")-1; /* OGS book name display field length */
|
|
|
|
int filelen = sizeof("File")-1; /* file name display field length */
|
|
|
|
int fcnlen = sizeof("Function")-1; /* function name display field length */
|
|
|
|
int numlen = 0; /* line number display field length */
|
2023-07-27 14:04:50 -04:00
|
|
|
|
|
|
|
int *displine; /* screen line of displayed reference */
|
|
|
|
unsigned int disprefs; /* displayed references */
|
|
|
|
int field; /* input field */
|
|
|
|
unsigned int mdisprefs; /* maximum displayed references */
|
|
|
|
unsigned int nextline; /* next line to be shown */
|
|
|
|
FILE *nonglobalrefs; /* non-global references file */
|
|
|
|
unsigned int topline = 1; /* top line of page */
|
2023-07-29 09:40:48 -04:00
|
|
|
static int bottomline; /* bottom line of page */
|
2023-07-27 14:04:50 -04:00
|
|
|
long searchcount; /* count of files searched */
|
|
|
|
unsigned int totallines; /* total reference lines */
|
|
|
|
unsigned fldcolumn; /* input field column */
|
2023-07-29 09:40:48 -04:00
|
|
|
unsigned int curdispline = 0;
|
|
|
|
|
|
|
|
WINDOW* winput;
|
|
|
|
WINDOW* wmode;
|
|
|
|
WINDOW* wresult;
|
|
|
|
WINDOW** current_window;
|
|
|
|
static WINDOW** last_window;
|
|
|
|
|
|
|
|
static int result_window_height;
|
|
|
|
static int second_col_width;
|
|
|
|
static int first_col_width;
|
|
|
|
static int input_window_height;
|
|
|
|
static int mode_window_height;
|
|
|
|
|
|
|
|
#define WRESULT_TABLE_BODY_START 4
|
2023-07-27 14:04:50 -04:00
|
|
|
|
|
|
|
static enum {
|
2023-07-29 09:40:48 -04:00
|
|
|
CH_RESULT = 0x0001,
|
|
|
|
CH_INPUT = CH_RESULT << 1,
|
|
|
|
CH_MODE = CH_RESULT << 2,
|
|
|
|
CH_ALL = CH_RESULT | CH_INPUT | CH_MODE
|
2023-07-27 14:04:50 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
const char dispchars[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
|
|
|
|
|
|
static int fldline; /* input field line */
|
|
|
|
static sigjmp_buf env; /* setjmp/longjmp buffer */
|
|
|
|
static char lastmsg[MSGLEN + 1]; /* last message displayed */
|
|
|
|
static const char helpstring[] = "Press the ? key for help";
|
|
|
|
static const char selprompt[] =
|
|
|
|
"Select lines to change (press the ? key for help): ";
|
|
|
|
|
|
|
|
typedef char * (*FP)(char *); /* pointer to function returning a character pointer */
|
|
|
|
|
|
|
|
static struct { /* text of input fields */
|
|
|
|
char *text1;
|
|
|
|
char *text2;
|
|
|
|
FP findfcn;
|
|
|
|
} fields[FIELDS + 1] = { /* samuel has a search that is not part of the cscope display */
|
|
|
|
{"Find this", "C symbol", findsymbol},
|
|
|
|
{"Find this", "global definition", finddef},
|
|
|
|
{"Find", "functions called by this function", findcalledby},
|
|
|
|
{"Find", "functions calling this function", findcalling},
|
|
|
|
{"Find this", "text string", findstring},
|
|
|
|
{"Change this", "text string", findstring},
|
|
|
|
{"Find this", "egrep pattern", findregexp},
|
|
|
|
{"Find this", "file", findfile},
|
|
|
|
{"Find", "files #including this file", findinclude},
|
|
|
|
{"Find", "assignments to this symbol", findassign},
|
|
|
|
{"Find all", "function definitions", findallfcns}, /* samuel only */
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Internal prototypes: */
|
|
|
|
static void jumpback(int sig);
|
|
|
|
|
|
|
|
/* initialize display parameters */
|
|
|
|
void
|
|
|
|
dispinit(void)
|
|
|
|
{
|
|
|
|
/* initialize the curses display package */
|
|
|
|
initscr(); /* initialize the screen */
|
|
|
|
entercurses();
|
|
|
|
keypad(stdscr, TRUE); /* enable the keypad */
|
|
|
|
//fixkeypad(); /* fix for getch() intermittently returning garbage */
|
|
|
|
standend(); /* turn off reverse video */
|
2023-07-29 09:40:48 -04:00
|
|
|
curs_set(0);
|
|
|
|
noecho();
|
2023-07-27 14:04:50 -04:00
|
|
|
|
2023-07-29 09:40:48 -04:00
|
|
|
/* Calculate section sizes */
|
|
|
|
result_window_height = LINES - 2;
|
|
|
|
input_window_height = 1;
|
|
|
|
mode_window_height = LINES - input_window_height - 2 - 1;
|
|
|
|
first_col_width = 48; // (((COLS - 2)%2 == 0) ? ((COLS-2)/2) : (((COLS-2)/2)+1));
|
|
|
|
second_col_width = COLS - 2 - 1 - first_col_width; //((COLS - 2) / 2) - 1;
|
|
|
|
mdisprefs = result_window_height - 1;
|
2023-07-27 14:04:50 -04:00
|
|
|
|
|
|
|
if (mdisprefs <= 0) {
|
|
|
|
postfatal("%s: screen too small\n", argv0);
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
2023-07-29 09:40:48 -04:00
|
|
|
if(mdisprefs > strlen(dispchars)){
|
2023-07-27 14:04:50 -04:00
|
|
|
mdisprefs = strlen(dispchars);
|
2023-07-29 09:40:48 -04:00
|
|
|
}
|
2023-07-27 14:04:50 -04:00
|
|
|
|
|
|
|
/* allocate the displayed line array */
|
|
|
|
displine = malloc(mdisprefs * sizeof(*displine));
|
|
|
|
|
|
|
|
/* initialize windows */
|
2023-07-29 09:40:48 -04:00
|
|
|
winput = newwin(input_window_height, first_col_width, 1, 1);
|
|
|
|
wmode = newwin(mode_window_height, first_col_width, input_window_height+1 + 1, 1);
|
|
|
|
wresult = newwin(result_window_height, second_col_width, 1, first_col_width + 1 + 1);
|
2023-07-27 14:04:50 -04:00
|
|
|
refresh();
|
2023-07-29 09:40:48 -04:00
|
|
|
|
|
|
|
current_window = &winput;
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void display_frame(){
|
|
|
|
box(stdscr, 0, 0);
|
2023-07-29 09:40:48 -04:00
|
|
|
/* Vertical line */
|
|
|
|
mvaddch(0, first_col_width + 1, ACS_TTEE);
|
|
|
|
for(int i = 0; i < LINES-2; i++){
|
|
|
|
mvaddch(i+1, first_col_width + 1, ACS_VLINE);
|
|
|
|
}
|
|
|
|
mvaddch(LINES-1, first_col_width + 1, ACS_BTEE);
|
|
|
|
/* Horizontal line */
|
|
|
|
wmove(stdscr, input_window_height + 1, 0);
|
|
|
|
addch(ACS_LTEE);
|
|
|
|
for(int i = 0; i < first_col_width; i++){
|
|
|
|
addch(ACS_HLINE);
|
|
|
|
}
|
|
|
|
addch(ACS_RTEE);
|
2023-07-27 14:04:50 -04:00
|
|
|
/* Title*/
|
|
|
|
const int LEFT_PADDING = 5;
|
|
|
|
wmove(stdscr, 0, LEFT_PADDING);
|
|
|
|
#if CCS
|
|
|
|
if (displayversion == YES) {
|
|
|
|
wprintw(stdscr, "cscope %s", ESG_REL);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
waddstr(stdscr, "cscope");
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
wprintw(stdscr, "Cscope version %d%s", FILEVERSION, FIXVERSION);
|
|
|
|
#endif
|
2023-07-29 09:40:48 -04:00
|
|
|
wmove(stdscr, 0, COLS - (int)sizeof(helpstring) - 3);
|
2023-07-27 14:04:50 -04:00
|
|
|
waddstr(stdscr, helpstring);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void display_input_fields(){
|
|
|
|
for(int i = 0; i < FIELDS; ++i){
|
2023-07-29 09:40:48 -04:00
|
|
|
mvwprintw(wmode, i, 0, "%s %s", fields[i].text1, fields[i].text2);
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void display_command_field(){
|
2023-07-29 09:40:48 -04:00
|
|
|
mvwprintw(winput, 0, 0, INPUT_PROMPT);
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
|
2023-07-29 09:40:48 -04:00
|
|
|
static inline void display_results(){
|
2023-07-27 14:04:50 -04:00
|
|
|
char *subsystem; /* OGS subsystem name */
|
|
|
|
char *book; /* OGS book name */
|
|
|
|
char file[PATHLEN + 1]; /* file name */
|
|
|
|
char function[PATLEN + 1]; /* function name */
|
|
|
|
char linenum[NUMLEN + 1]; /* line number */
|
|
|
|
int screenline; /* screen line number */
|
2023-07-29 09:40:48 -04:00
|
|
|
int srctxtw; /* source line display width */
|
2023-07-27 14:04:50 -04:00
|
|
|
int i;
|
|
|
|
char *s;
|
|
|
|
|
2023-07-29 09:40:48 -04:00
|
|
|
werase(wresult);
|
2023-07-27 14:04:50 -04:00
|
|
|
|
|
|
|
if (totallines == 0) {
|
2023-07-29 09:40:48 -04:00
|
|
|
/* if no references were found */
|
|
|
|
/* redisplay the last message */
|
|
|
|
waddstr(wresult, lastmsg);
|
|
|
|
return;
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
|
|
|
|
2023-07-27 14:04:50 -04:00
|
|
|
/* display the pattern */
|
|
|
|
if (changing == YES) {
|
2023-07-29 09:40:48 -04:00
|
|
|
wprintw(wresult, "Change \"%s\" to \"%s\"", Pattern, newpat);
|
2023-07-27 14:04:50 -04:00
|
|
|
} else {
|
2023-07-29 09:40:48 -04:00
|
|
|
wprintw(wresult, "%c%s: %s", toupper((unsigned char)fields[field].text2[0]),
|
2023-07-27 14:04:50 -04:00
|
|
|
fields[field].text2 + 1, Pattern);
|
|
|
|
}
|
|
|
|
/* display the column headings */
|
2023-07-29 09:40:48 -04:00
|
|
|
wmove(wresult, 2, 2);
|
2023-07-27 14:04:50 -04:00
|
|
|
if (ogs == YES && field != FILENAME) {
|
2023-07-29 09:40:48 -04:00
|
|
|
wprintw(wresult, "%-*s ", subsystemlen, "Subsystem");
|
|
|
|
wprintw(wresult, "%-*s ", booklen, "Book");
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
if (dispcomponents > 0)
|
2023-07-29 09:40:48 -04:00
|
|
|
wprintw(wresult, "%-*s ", filelen, "File");
|
2023-07-27 14:04:50 -04:00
|
|
|
|
|
|
|
if (field == SYMBOL || field == CALLEDBY || field == CALLING) {
|
2023-07-29 09:40:48 -04:00
|
|
|
wprintw(wresult, "%-*s ", fcnlen, "Function");
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
if (field != FILENAME) {
|
2023-07-29 09:40:48 -04:00
|
|
|
waddstr(wresult, "Line");
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
|
2023-07-29 09:40:48 -04:00
|
|
|
wmove(wresult, WRESULT_TABLE_BODY_START, 0);
|
2023-07-27 14:04:50 -04:00
|
|
|
|
2023-07-29 09:40:48 -04:00
|
|
|
/* calculate the source text column */
|
|
|
|
/* NOTE: the +1s are column gaps */
|
|
|
|
srctxtw = second_col_width;
|
|
|
|
srctxtw -= 1+1; // dispchars
|
2023-07-27 14:04:50 -04:00
|
|
|
if (ogs == YES) {
|
2023-07-29 09:40:48 -04:00
|
|
|
srctxtw -= subsystemlen+1 + booklen+1;
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
if (dispcomponents > 0) {
|
2023-07-29 09:40:48 -04:00
|
|
|
srctxtw -= filelen+1;
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
if (field == SYMBOL || field == CALLEDBY || field == CALLING) {
|
2023-07-29 09:40:48 -04:00
|
|
|
srctxtw -= fcnlen+1;
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
2023-07-29 09:40:48 -04:00
|
|
|
srctxtw -= numlen+1;
|
2023-07-27 14:04:50 -04:00
|
|
|
|
|
|
|
/* until the max references have been displayed or
|
|
|
|
there is no more room */
|
|
|
|
topline = nextline;
|
|
|
|
for (disprefs = 0, screenline = REFLINE;
|
2023-07-29 09:40:48 -04:00
|
|
|
disprefs < mdisprefs && screenline <= result_window_height;
|
|
|
|
++disprefs, ++screenline)
|
|
|
|
{
|
2023-07-27 14:04:50 -04:00
|
|
|
/* read the reference line */
|
2023-07-29 09:40:48 -04:00
|
|
|
if (
|
|
|
|
fscanf(refsfound, "%" PATHLEN_STR "s%" PATHLEN_STR "s%" NUMLEN_STR "s %" TEMPSTRING_LEN_STR "[^\n]",
|
|
|
|
file,
|
|
|
|
function,
|
|
|
|
linenum,
|
|
|
|
tempstring
|
|
|
|
)
|
|
|
|
<
|
|
|
|
4
|
|
|
|
)
|
|
|
|
{
|
|
|
|
break;
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
++nextline;
|
|
|
|
displine[disprefs] = screenline;
|
|
|
|
|
2023-07-29 09:40:48 -04:00
|
|
|
wprintw(wresult, "%c", dispchars[disprefs]);
|
2023-07-27 14:04:50 -04:00
|
|
|
|
|
|
|
/* display any change mark */
|
2023-07-29 09:40:48 -04:00
|
|
|
if (changing == YES && change[topline + disprefs - 1] == YES) {
|
|
|
|
waddch(wresult, '>');
|
2023-07-27 14:04:50 -04:00
|
|
|
} else {
|
2023-07-29 09:40:48 -04:00
|
|
|
waddch(wresult, ' ');
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* display the file name */
|
|
|
|
if (field == FILENAME) {
|
2023-07-29 09:40:48 -04:00
|
|
|
wprintw(wresult, "%-*s ", filelen, file);
|
2023-07-27 14:04:50 -04:00
|
|
|
} else {
|
|
|
|
/* if OGS, display the subsystem and book names */
|
|
|
|
if (ogs == YES) {
|
|
|
|
ogsnames(file, &subsystem, &book);
|
2023-07-29 09:40:48 -04:00
|
|
|
wprintw(wresult, "%-*.*s ", subsystemlen, subsystemlen, subsystem);
|
|
|
|
wprintw(wresult, "%-*.*s ", booklen, booklen, book);
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
/* display the requested path components */
|
|
|
|
if (dispcomponents > 0) {
|
2023-07-29 09:40:48 -04:00
|
|
|
wprintw(wresult, "%-*.*s ", filelen, filelen,
|
2023-07-27 14:04:50 -04:00
|
|
|
pathcomponents(file, dispcomponents));
|
|
|
|
}
|
|
|
|
} /* else(field == FILENAME) */
|
|
|
|
|
|
|
|
/* display the function name */
|
|
|
|
if (field == SYMBOL || field == CALLEDBY || field == CALLING) {
|
2023-07-29 09:40:48 -04:00
|
|
|
wprintw(wresult, "%-*.*s ", fcnlen, fcnlen, function);
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
if (field == FILENAME) {
|
2023-07-29 09:40:48 -04:00
|
|
|
waddch(wresult, '\n'); /* go to next line */
|
2023-07-27 14:04:50 -04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* display the line number */
|
2023-07-29 09:40:48 -04:00
|
|
|
wprintw(wresult, "%*s ", numlen, linenum);
|
2023-07-27 14:04:50 -04:00
|
|
|
/* there may be tabs in egrep output */
|
|
|
|
while ((s = strchr(tempstring, '\t')) != NULL) {
|
|
|
|
*s = ' ';
|
|
|
|
}
|
|
|
|
|
|
|
|
/* display the source line */
|
|
|
|
s = tempstring;
|
|
|
|
for (;;) {
|
2023-07-29 09:40:48 -04:00
|
|
|
/* if the source line does not fit */
|
|
|
|
if ((i = strlen(s)) > srctxtw) {
|
2023-07-27 14:04:50 -04:00
|
|
|
|
|
|
|
/* find the nearest blank */
|
2023-07-29 09:40:48 -04:00
|
|
|
for (i = srctxtw; s[i] != ' ' && i > 0; --i) {
|
|
|
|
;
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
2023-07-29 09:40:48 -04:00
|
|
|
|
2023-07-27 14:04:50 -04:00
|
|
|
if (i == 0) {
|
2023-07-29 09:40:48 -04:00
|
|
|
i = srctxtw; /* no blank */
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* print up to this point */
|
2023-07-29 09:40:48 -04:00
|
|
|
wprintw(wresult, "%.*s", i, s);
|
2023-07-27 14:04:50 -04:00
|
|
|
s += i;
|
|
|
|
|
|
|
|
/* if line didn't wrap around */
|
2023-07-29 09:40:48 -04:00
|
|
|
if (i < srctxtw) {
|
|
|
|
waddch(wresult, '\n'); /* go to next line */
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
/* skip blanks */
|
|
|
|
while (*s == ' ') {
|
|
|
|
++s;
|
|
|
|
}
|
|
|
|
/* see if there is more text */
|
|
|
|
if (*s == '\0') {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* if the source line is too long */
|
2023-07-29 09:40:48 -04:00
|
|
|
if (++screenline > result_window_height) {
|
2023-07-27 14:04:50 -04:00
|
|
|
|
|
|
|
/* if this is the first displayed line,
|
|
|
|
display what will fit on the screen */
|
|
|
|
if (topline == nextline -1) {
|
|
|
|
disprefs++;
|
|
|
|
/* break out of two loops */
|
|
|
|
goto endrefs;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* erase the reference */
|
|
|
|
while (--screenline >= displine[disprefs]) {
|
2023-07-29 09:40:48 -04:00
|
|
|
wmove(wresult, screenline, 0);
|
|
|
|
wclrtoeol(wresult);
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
++screenline;
|
|
|
|
|
|
|
|
/* go back to the beginning of this reference */
|
|
|
|
--nextline;
|
|
|
|
seekline(nextline);
|
|
|
|
goto endrefs;
|
|
|
|
}
|
|
|
|
/* indent the continued source line */
|
2023-07-29 09:40:48 -04:00
|
|
|
wmove(wresult, screenline, second_col_width - srctxtw);
|
2023-07-27 14:04:50 -04:00
|
|
|
} /* for(ever) */
|
|
|
|
} /* for(reference output lines) */
|
|
|
|
endrefs:
|
|
|
|
/* position the cursor for the message */
|
|
|
|
i = FLDLINE - 1;
|
|
|
|
if (screenline < i) {
|
2023-07-29 09:40:48 -04:00
|
|
|
waddch(wresult, '\n');
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
else {
|
2023-07-29 09:40:48 -04:00
|
|
|
wmove(wresult, i, 0);
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
/* check for more references */
|
|
|
|
i = totallines - nextline + 1;
|
|
|
|
bottomline = nextline;
|
|
|
|
if (i > 0) {
|
2023-07-29 09:40:48 -04:00
|
|
|
wprintw(wresult, "* Lines %d-%d of %d, %d more - press the space bar to display more *", topline, bottomline, totallines, i);
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
/* if this is the last page of references */
|
|
|
|
else if (topline > 1 && nextline > totallines) {
|
2023-07-29 09:40:48 -04:00
|
|
|
waddstr(wresult, "* Press the space bar to display the first lines again *");
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
2023-07-29 09:40:48 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void display_cursor(void){
|
|
|
|
chtype i;
|
|
|
|
int yoffset = 0, xoffset = 0;
|
|
|
|
|
|
|
|
if(current_window == &winput){
|
|
|
|
xoffset = sizeof(INPUT_PROMPT)-1;
|
|
|
|
}else if(current_window == &wmode){
|
|
|
|
yoffset = field;
|
|
|
|
}else if(current_window == &wresult){
|
|
|
|
yoffset = WRESULT_TABLE_BODY_START + curdispline;
|
|
|
|
}else{
|
|
|
|
assert(("No window selected.", true));
|
|
|
|
}
|
|
|
|
|
|
|
|
wmove(*current_window, yoffset, xoffset);
|
|
|
|
|
|
|
|
i = winch(*current_window);
|
|
|
|
i |= A_REVERSE;
|
|
|
|
waddch(*current_window, i);
|
|
|
|
}
|
2023-07-27 14:04:50 -04:00
|
|
|
|
2023-07-29 09:40:48 -04:00
|
|
|
void
|
|
|
|
display(void)
|
|
|
|
{
|
|
|
|
//drawscrollbar(topline, nextline); /* display the scrollbar */
|
2023-07-27 14:04:50 -04:00
|
|
|
|
2023-07-29 09:40:48 -04:00
|
|
|
display_frame();
|
|
|
|
display_command_field();
|
2023-07-27 14:04:50 -04:00
|
|
|
display_input_fields();
|
2023-07-29 09:40:48 -04:00
|
|
|
display_results();
|
|
|
|
|
|
|
|
display_cursor();
|
2023-07-27 14:04:50 -04:00
|
|
|
|
|
|
|
refresh();
|
2023-07-29 09:40:48 -04:00
|
|
|
wrefresh(winput);
|
|
|
|
wrefresh(wmode);
|
|
|
|
wrefresh(wresult);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
horswp_field(void){
|
|
|
|
if(current_window != &wresult){
|
|
|
|
last_window = current_window;
|
|
|
|
current_window = &wresult;
|
|
|
|
}else{
|
|
|
|
current_window = last_window;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
verswp_field(void){
|
|
|
|
if(current_window == &wresult){ return; }
|
|
|
|
current_window = (current_window == &winput) ? &wmode : &winput;
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* set the cursor position for the field */
|
|
|
|
//void
|
|
|
|
//setfield(void)
|
|
|
|
//{
|
|
|
|
// fldline = FLDLINE + field;
|
|
|
|
// fldcolumn = strlen(fields[field].text1) + strlen(fields[field].text2) + 3;
|
|
|
|
//}
|
|
|
|
|
|
|
|
/* move to the current input field */
|
|
|
|
//
|
|
|
|
//void
|
|
|
|
//atfield(void)
|
|
|
|
//{
|
|
|
|
// wmove(input_fields, fldline, fldcolumn);
|
|
|
|
//}
|
|
|
|
|
|
|
|
/* move to the changing lines prompt */
|
|
|
|
|
|
|
|
//void
|
|
|
|
//atchange(void)
|
|
|
|
//{
|
2023-07-29 09:40:48 -04:00
|
|
|
// wmove(wresult, PRLINE, (int) sizeof(selprompt) - 1);
|
2023-07-27 14:04:50 -04:00
|
|
|
//}
|
|
|
|
|
|
|
|
/* search for the symbol or text pattern */
|
|
|
|
|
|
|
|
/*ARGSUSED*/
|
|
|
|
static void
|
|
|
|
jumpback(int sig)
|
|
|
|
{
|
|
|
|
signal(sig, jumpback);
|
|
|
|
siglongjmp(env, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
search(void)
|
|
|
|
{
|
|
|
|
char *findresult = NULL; /* find function output */
|
|
|
|
BOOL funcexist = YES; /* find "function" error */
|
|
|
|
FINDINIT rc = NOERROR; /* findinit return code */
|
|
|
|
sighandler_t savesig; /* old value of signal */
|
|
|
|
FP f; /* searching function */
|
|
|
|
int c;
|
|
|
|
|
|
|
|
/* open the references found file for writing */
|
|
|
|
if (writerefsfound() == NO) {
|
|
|
|
return(NO);
|
|
|
|
}
|
|
|
|
/* find the pattern - stop on an interrupt */
|
|
|
|
if (linemode == NO) {
|
|
|
|
postmsg("Searching");
|
|
|
|
}
|
|
|
|
searchcount = 0;
|
|
|
|
savesig = signal(SIGINT, jumpback);
|
|
|
|
if (sigsetjmp(env, 1) == 0) {
|
|
|
|
f = fields[field].findfcn;
|
|
|
|
if (f == findregexp || f == findstring) {
|
|
|
|
findresult = (*f)(Pattern);
|
|
|
|
} else {
|
|
|
|
if ((nonglobalrefs = myfopen(temp2, "wb")) == NULL) {
|
|
|
|
cannotopen(temp2);
|
|
|
|
return(NO);
|
|
|
|
}
|
|
|
|
if ((rc = findinit(Pattern)) == NOERROR) {
|
|
|
|
(void) dbseek(0L); /* read the first block */
|
|
|
|
findresult = (*f)(Pattern);
|
|
|
|
if (f == findcalledby)
|
|
|
|
funcexist = (*findresult == 'y');
|
|
|
|
findcleanup();
|
|
|
|
|
|
|
|
/* append the non-global references */
|
|
|
|
(void) fclose(nonglobalrefs);
|
|
|
|
if ((nonglobalrefs = myfopen(temp2, "rb"))
|
|
|
|
== NULL) {
|
|
|
|
cannotopen(temp2);
|
|
|
|
return(NO);
|
|
|
|
}
|
|
|
|
while ((c = getc(nonglobalrefs)) != EOF) {
|
|
|
|
(void) putc(c, refsfound);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(void) fclose(nonglobalrefs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
signal(SIGINT, savesig);
|
|
|
|
|
|
|
|
/* rewind the cross-reference file */
|
|
|
|
(void) lseek(symrefs, (long) 0, 0);
|
|
|
|
|
|
|
|
/* reopen the references found file for reading */
|
|
|
|
(void) fclose(refsfound);
|
|
|
|
if ((refsfound = myfopen(temp1, "rb")) == NULL) {
|
|
|
|
cannotopen(temp1);
|
|
|
|
return(NO);
|
|
|
|
}
|
|
|
|
nextline = 1;
|
|
|
|
totallines = 0;
|
|
|
|
disprefs = 0;
|
|
|
|
|
|
|
|
/* see if it is empty */
|
|
|
|
if ((c = getc(refsfound)) == EOF) {
|
|
|
|
if (findresult != NULL) {
|
|
|
|
(void) snprintf(lastmsg, sizeof(lastmsg), "Egrep %s in this pattern: %s",
|
|
|
|
findresult, Pattern);
|
|
|
|
} else if (rc == NOTSYMBOL) {
|
|
|
|
(void) snprintf(lastmsg, sizeof(lastmsg), "This is not a C symbol: %s",
|
|
|
|
Pattern);
|
|
|
|
} else if (rc == REGCMPERROR) {
|
|
|
|
(void) snprintf(lastmsg, sizeof(lastmsg), "Error in this regcomp(3) regular expression: %s",
|
|
|
|
Pattern);
|
|
|
|
|
|
|
|
} else if (funcexist == NO) {
|
|
|
|
(void) snprintf(lastmsg, sizeof(lastmsg), "Function definition does not exist: %s",
|
|
|
|
Pattern);
|
|
|
|
} else {
|
|
|
|
(void) snprintf(lastmsg, sizeof(lastmsg), "Could not find the %s: %s",
|
|
|
|
fields[field].text2, Pattern);
|
|
|
|
}
|
|
|
|
return(NO);
|
|
|
|
}
|
|
|
|
/* put back the character read */
|
|
|
|
(void) ungetc(c, refsfound);
|
|
|
|
|
|
|
|
/* HBB 20041027: this used to hold a copy of the code of
|
|
|
|
* countrefs(), but with the crucial display width adjustments
|
|
|
|
* missing. Just call the real thing instead! */
|
|
|
|
countrefs();
|
|
|
|
return(YES);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* display search progress with default custom format */
|
|
|
|
void
|
|
|
|
progress(char *what, long current, long max)
|
|
|
|
{
|
|
|
|
static long start;
|
|
|
|
long now;
|
|
|
|
char msg[MSGLEN + 1];
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* save the start time */
|
|
|
|
if (searchcount == 0) {
|
|
|
|
start = time(NULL);
|
|
|
|
}
|
|
|
|
if ((now = time(NULL)) - start >= 1)
|
|
|
|
{
|
|
|
|
if (linemode == NO)
|
|
|
|
{
|
2023-07-29 09:40:48 -04:00
|
|
|
wmove(wresult, MSGLINE, 0);
|
|
|
|
wclrtoeol(wresult);
|
|
|
|
waddstr(wresult, what);
|
2023-07-27 14:04:50 -04:00
|
|
|
snprintf(msg, sizeof(msg), "%ld", current);
|
2023-07-29 09:40:48 -04:00
|
|
|
wmove(wresult, MSGLINE, (COLS / 2) - (strlen(msg) / 2));
|
|
|
|
waddstr(wresult, msg);
|
2023-07-27 14:04:50 -04:00
|
|
|
snprintf(msg, sizeof(msg), "%ld", max);
|
2023-07-29 09:40:48 -04:00
|
|
|
wmove(wresult, MSGLINE, COLS - strlen(msg));
|
|
|
|
waddstr(wresult, msg);
|
2023-07-27 14:04:50 -04:00
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
else if (verbosemode == YES)
|
|
|
|
{
|
|
|
|
snprintf(msg, sizeof(msg), "> %s %ld of %ld", what, current, max);
|
|
|
|
}
|
|
|
|
|
|
|
|
start = now;
|
|
|
|
if ((linemode == NO) && (incurses == YES))
|
|
|
|
{
|
2023-07-29 09:40:48 -04:00
|
|
|
wmove(wresult, MSGLINE, 0);
|
2023-07-27 14:04:50 -04:00
|
|
|
i = (float)COLS * (float)current / (float)max;
|
|
|
|
|
|
|
|
standout();
|
|
|
|
for (; i > 0; i--)
|
2023-07-29 09:40:48 -04:00
|
|
|
waddch(wresult, inch());
|
2023-07-27 14:04:50 -04:00
|
|
|
standend();
|
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (linemode == NO || verbosemode == YES)
|
|
|
|
postmsg(msg);
|
|
|
|
}
|
|
|
|
++searchcount;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* print error message on system call failure */
|
|
|
|
void
|
|
|
|
myperror(char *text)
|
|
|
|
{
|
|
|
|
char msg[MSGLEN + 1]; /* message */
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
s = strerror(errno);
|
|
|
|
|
|
|
|
(void) snprintf(msg, sizeof(msg), "%s: %s", text, s);
|
|
|
|
postmsg(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* postmsg clears the message line and prints the message */
|
|
|
|
|
|
|
|
void
|
|
|
|
postmsg(char *msg)
|
|
|
|
{
|
|
|
|
if (linemode == YES || incurses == NO) {
|
|
|
|
(void) printf("%s\n", msg);
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
clearmsg();
|
2023-07-29 09:40:48 -04:00
|
|
|
waddstr(wresult, msg);
|
|
|
|
wrefresh(wresult);
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
(void) strncpy(lastmsg, msg, sizeof(lastmsg) - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* clearmsg clears the first message line */
|
|
|
|
|
|
|
|
void
|
|
|
|
clearmsg(void)
|
|
|
|
{
|
2023-07-29 09:40:48 -04:00
|
|
|
wmove(wresult, MSGLINE, 0);
|
|
|
|
wclrtoeol(wresult);
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* clearmsg2 clears the second message line */
|
|
|
|
void
|
|
|
|
clearmsg2(void)
|
|
|
|
{
|
|
|
|
if (linemode == NO) {
|
2023-07-29 09:40:48 -04:00
|
|
|
wmove(wresult, MSGLINE + 1, 0);
|
|
|
|
wclrtoeol(wresult);
|
2023-07-27 14:04:50 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* postmsg2 clears the second message line and prints the message */
|
|
|
|
void
|
|
|
|
postmsg2(char *msg)
|
|
|
|
{
|
|
|
|
if (linemode == YES) {
|
|
|
|
(void) printf("%s\n", msg);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
clearmsg2();
|
2023-07-29 09:40:48 -04:00
|
|
|
waddstr(wresult, msg);
|
2023-07-27 14:04:50 -04:00
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* display an error mesg - stdout or on second msg line */
|
|
|
|
void
|
|
|
|
posterr(char *msg, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
char errbuf[MSGLEN];
|
|
|
|
|
|
|
|
va_start(ap, msg);
|
|
|
|
if (linemode == YES || incurses == NO)
|
|
|
|
{
|
|
|
|
(void) vfprintf(stderr, msg, ap);
|
|
|
|
(void) fputc('\n', stderr);
|
|
|
|
} else {
|
|
|
|
vsnprintf(errbuf, sizeof(errbuf), msg, ap);
|
|
|
|
postmsg2(errbuf);
|
|
|
|
}
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* display a fatal error mesg -- stderr *after* shutting down curses */
|
|
|
|
void
|
|
|
|
postfatal(const char *msg, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
char errbuf[MSGLEN];
|
|
|
|
|
|
|
|
va_start(ap, msg);
|
|
|
|
vsnprintf(errbuf, sizeof(errbuf), msg, ap);
|
|
|
|
/* restore the terminal to its original mode */
|
|
|
|
if (incurses == YES) {
|
|
|
|
exitcurses();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* display fatal error messages */
|
|
|
|
fprintf(stderr,"%s",errbuf);
|
|
|
|
|
|
|
|
/* shut down */
|
|
|
|
myexit(1);
|
|
|
|
}
|
|
|
|
|
2023-07-29 09:40:48 -04:00
|
|
|
/* position references found file at specified line */
|
2023-07-27 14:04:50 -04:00
|
|
|
void
|
|
|
|
seekline(unsigned int line)
|
|
|
|
{
|
|
|
|
int c;
|
|
|
|
|
|
|
|
/* verify that there is a references found file */
|
|
|
|
if (refsfound == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* go to the beginning of the file */
|
|
|
|
rewind(refsfound);
|
|
|
|
|
|
|
|
/* find the requested line */
|
|
|
|
nextline = 1;
|
|
|
|
while (nextline < line && (c = getc(refsfound)) != EOF) {
|
|
|
|
if (c == '\n') {
|
|
|
|
nextline++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get the OGS subsystem and book names */
|
|
|
|
void
|
|
|
|
ogsnames(char *file, char **subsystem, char **book)
|
|
|
|
{
|
|
|
|
static char buf[PATHLEN + 1];
|
|
|
|
char *s, *slash;
|
|
|
|
|
|
|
|
*subsystem = *book = "";
|
|
|
|
(void) strcpy(buf,file);
|
|
|
|
s = buf;
|
|
|
|
if (*s == '/') {
|
|
|
|
++s;
|
|
|
|
}
|
|
|
|
while ((slash = strchr(s, '/')) != NULL) {
|
|
|
|
*slash = '\0';
|
|
|
|
if ((int)strlen(s) >= 3 && strncmp(slash - 3, ".ss", 3) == 0) {
|
|
|
|
*subsystem = s;
|
|
|
|
s = slash + 1;
|
|
|
|
if ((slash = strchr(s, '/')) != NULL) {
|
|
|
|
*book = s;
|
|
|
|
*slash = '\0';
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
s = slash + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get the requested path components */
|
|
|
|
char *
|
|
|
|
pathcomponents(char *path, int components)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
s = path + strlen(path) - 1;
|
|
|
|
for (i = 0; i < components; ++i) {
|
|
|
|
while (s > path && *--s != '/') {
|
|
|
|
;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (s > path && *s == '/') {
|
|
|
|
++s;
|
|
|
|
}
|
|
|
|
return(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* open the references found file for writing */
|
|
|
|
BOOL
|
|
|
|
writerefsfound(void)
|
|
|
|
{
|
|
|
|
if (refsfound == NULL) {
|
|
|
|
if ((refsfound = myfopen(temp1, "wb")) == NULL) {
|
|
|
|
cannotopen(temp1);
|
|
|
|
return(NO);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
(void) fclose(refsfound);
|
|
|
|
if ( (refsfound = myfopen(temp1, "wb")) == NULL) {
|
|
|
|
postmsg("Cannot reopen temporary file");
|
|
|
|
return(NO);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(YES);
|
|
|
|
}
|