#include "global.h"
#ifdef CCS
#include "sgs.h"
#else
#include "version.h"
#endif
#if defined(USE_NCURSES) && !defined(RENAMED_NCURSES)
#include <ncurses.h>
#else
#include <curses.h>
#endif
#include <setjmp.h>
#include <stdarg.h>
#include <time.h>
#include <errno.h>
#include <stdarg.h>
static char const rcsid[] = "$Id: display.c,v 1.4 2002/01/09 19:04:04 umeshv Exp $";
int booklen;
int *displine;
int disprefs;
int field;
int filelen;
int fcnlen;
int mdisprefs;
int nextline;
FILE *nonglobalrefs;
int numlen;
int topline = 1;
int bottomline;
long searchcount;
int subsystemlen;
int totallines;
unsigned fldcolumn;
const char dispchars[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
static int fldline;
static jmp_buf env;
int lastdispline;
static char lastmsg[MSGLEN + 1];
static char helpstring[] = "Press the ? key for help";
static char selprompt[] =
"Select lines to change (press the ? key for help): ";
typedef char * (*FP)(char *);
static struct {
char *text1;
char *text2;
FP findfcn;
} fields[FIELDS + 1] = {
{"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 all", "function definitions", findallfcns},
};
void
dispinit(void)
{
lastdispline = FLDLINE - 3;
mdisprefs = lastdispline - REFLINE + 1;
if (mdisprefs <= 0) {
(void) fprintf(stderr, "%s: screen too small\n", argv0);
myexit(1);
}
if (mouse == NO && mdisprefs > strlen(dispchars))
mdisprefs = strlen(dispchars);
displine = mymalloc(mdisprefs * sizeof(int));
}
void
display(void)
{
char *subsystem;
char *book;
char file[PATHLEN + 1];
char function[PATLEN + 1];
char linenum[NUMLEN + 1];
int screenline;
int width;
int i;
char *s;
erase();
#if Darwin
move(0, 0);
#endif
if (refsfound == NULL) {
#if CCS
if (displayversion == YES) {
printw("cscope %s", ESG_REL);
}
else {
printw("cscope");
}
#else
printw("Cscope version %d%s", FILEVERSION, FIXVERSION);
#endif
move(0, COLS - (int) sizeof(helpstring));
addstr(helpstring);
}
else if (totallines == 0) {
addstr(lastmsg);
}
else {
if (changing == YES) {
printw("Change \"%s\" to \"%s\"", pattern, newpat);
}
else {
printw("%c%s: %s", toupper((unsigned char)fields[field].text2[0]),
fields[field].text2 + 1, pattern);
}
move(2, 2);
if (ogs == YES && field != FILENAME) {
printw("%-*s ", subsystemlen, "Subsystem");
printw("%-*s ", booklen, "Book");
}
if (dispcomponents > 0)
printw("%-*s ", filelen, "File");
if (field == SYMBOL || field == CALLEDBY || field == CALLING) {
printw("%-*s ", fcnlen, "Function");
}
if (field != FILENAME) {
addstr("Line");
}
addch('\n');
if (nextline > totallines) {
seekline(1);
}
width = COLS - numlen - 3;
if (ogs == YES) {
width -= subsystemlen + booklen + 2;
}
if (dispcomponents > 0) {
width -= filelen + 1;
}
if (field == SYMBOL || field == CALLEDBY || field == CALLING) {
width -= fcnlen + 1;
}
topline = nextline;
for (disprefs = 0, screenline = REFLINE;
disprefs < mdisprefs && screenline <= lastdispline;
++disprefs, ++screenline) {
if (fscanf(refsfound, "%s%s%s %[^\n]", file, function,
linenum, tempstring) < 4) {
break;
}
++nextline;
displine[disprefs] = screenline;
if (mouse == YES) {
addch(' ');
}
else
printw("%c", dispchars[disprefs]);
if (changing == YES &&
change[topline + disprefs - 1] == YES) {
addch('>');
}
else {
addch(' ');
}
if (field == FILENAME) {
printw("%-*s ", filelen, file);
}
else {
if (ogs == YES) {
ogsnames(file, &subsystem, &book);
printw("%-*.*s ", subsystemlen, subsystemlen, subsystem);
printw("%-*.*s ", booklen, booklen, book);
}
if (dispcomponents > 0) {
printw("%-*.*s ", filelen, filelen,
pathcomponents(file, dispcomponents));
}
}
if (field == SYMBOL || field == CALLEDBY || field == CALLING) {
printw("%-*.*s ", fcnlen, fcnlen, function);
}
if (field == FILENAME) {
addch('\n');
continue;
}
printw("%*s ", numlen, linenum);
while ((s = strchr(tempstring, '\t')) != NULL) {
*s = ' ';
}
s = tempstring;
for (;;) {
if ((i = strlen(s)) > width) {
for (i = width; s[i] != ' ' && i > 0; --i) {
;
}
if (i == 0) {
i = width;
}
}
printw("%.*s", i, s);
s += i;
if (i < width) {
addch('\n');
}
while (*s == ' ') {
++s;
}
if (*s == '\0') {
break;
}
if (++screenline > lastdispline) {
if (topline == nextline -1) {
goto endrefs;
}
while (--screenline >= displine[disprefs]) {
move(screenline, 0);
clrtoeol();
}
++screenline;
--nextline;
seekline(nextline);
goto endrefs;
}
move(screenline, COLS - width);
}
}
endrefs:
i = FLDLINE - 1;
if (screenline < i) {
addch('\n');
}
else {
move(i, 0);
}
i = totallines - nextline + 1;
bottomline = nextline;
if (i > 0) {
s = "s";
if (i == 1) {
s = "";
}
printw("* %d more line%s - press the space bar to display more *", i, s);
}
else if (topline > 1 && nextline > totallines) {
addstr("* Press the space bar to display the first lines again *");
}
}
move(FLDLINE, 0);
for (i = 0; i < FIELDS; ++i) {
printw("%s %s:\n", fields[i].text1, fields[i].text2);
}
if (changing == YES) {
move(PRLINE, 0);
addstr(selprompt);
}
drawscrollbar(topline, nextline);
refresh();
}
void
setfield(void)
{
fldline = FLDLINE + field;
fldcolumn = strlen(fields[field].text1) + strlen(fields[field].text2) + 3;
}
void
atfield(void)
{
move(fldline, fldcolumn);
}
void
atchange(void)
{
move(PRLINE, (int) sizeof(selprompt) - 1);
}
RETSIGTYPE
jumpback(int sig)
{
(void) sig;
longjmp(env, 1);
}
BOOL
search(void)
{
char *subsystem;
char *book;
char file[PATHLEN + 1];
char function[PATLEN + 1];
char linenum[NUMLEN + 1];
char *findresult = NULL;
BOOL funcexist = YES;
FINDINIT rc = NOERROR;
RETSIGTYPE (*savesig)(int);
FP f;
int c, i;
if (writerefsfound() == NO) {
return(NO);
}
if (linemode == NO) {
postmsg("Searching");
}
searchcount = 0;
if (setjmp(env) == 0) {
savesig = signal(SIGINT, jumpback);
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);
findresult = (*f)(pattern);
if (f == findcalledby)
funcexist = (*findresult == 'y');
findcleanup();
(void) freopen(temp2, "rb", nonglobalrefs);
while ((c = getc(nonglobalrefs)) != EOF) {
(void) putc(c, refsfound);
}
}
(void) fclose(nonglobalrefs);
}
}
signal(SIGINT, savesig);
(void) lseek(symrefs, (long) 0, 0);
(void) freopen(temp1, "rb", refsfound);
nextline = 1;
totallines = 0;
if ((c = getc(refsfound)) == EOF) {
if (findresult != NULL) {
(void) sprintf(lastmsg, "Egrep %s in this pattern: %s",
findresult, pattern);
}
else if (rc == NOTSYMBOL) {
(void) sprintf(lastmsg, "This is not a C symbol: %s",
pattern);
}
else if (rc == REGCMPERROR) {
(void) sprintf(lastmsg, "Error in this regcmp(3X) regular expression: %s",
pattern);
}
else if (funcexist == NO) {
(void) sprintf(lastmsg, "Function definition does not exist: %s",
pattern);
}
else {
(void) sprintf(lastmsg, "Could not find the %s: %s",
fields[field].text2, pattern);
}
return(NO);
}
(void) ungetc(c, refsfound);
subsystemlen = 9;
booklen = 4;
filelen = 4;
fcnlen = 8;
numlen = 0;
while (fscanf(refsfound, "%s%s%s", file, function, linenum) == 3) {
if ((i = strlen(pathcomponents(file, dispcomponents))) > filelen) {
filelen = i;
}
if (ogs == YES) {
ogsnames(file, &subsystem, &book);
if ((i = strlen(subsystem)) > subsystemlen) {
subsystemlen = i;
}
if ((i = strlen(book)) > booklen) {
booklen = i;
}
}
if ((i = strlen(function)) > fcnlen) {
fcnlen = i;
}
if ((i = strlen(linenum)) > numlen) {
numlen = i;
}
while ((c = getc(refsfound)) != EOF && c != '\n') {
;
}
++totallines;
}
rewind(refsfound);
return(YES);
}
void
progress(char *what, long current, long max)
{
static long start;
long now;
char msg[MSGLEN + 1];
int i;
if (searchcount == 0) {
start = time(NULL);
}
if ((now = time(NULL)) - start >= 1)
{
if (linemode == NO)
{
move(MSGLINE, 0);
clrtoeol();
addstr(what);
sprintf(msg, "%ld", current);
move(MSGLINE, (COLS / 2) - (strlen(msg) / 2));
addstr(msg);
sprintf(msg, "%ld", max);
move(MSGLINE, COLS - strlen(msg));
addstr(msg);
refresh();
}
start = now;
if ((linemode == NO) && (incurses == YES))
{
move(MSGLINE, 0);
i = (float)COLS * (float)current / (float)max;
standout();
for (; i > 0; i--)
addch(inch());
standend();
refresh();
}
else
if (linemode == NO)
postmsg(msg);
}
++searchcount;
}
void
myperror(char *text)
{
char msg[MSGLEN + 1];
char *s;
s = "Unknown error";
#ifdef HAVE_STRERROR
s = strerror(errno);
#else
if (errno < sys_nerr) {
s = sys_errlist[errno];
}
#endif
(void) sprintf(msg, "%s: %s", text, s);
postmsg(msg);
}
void
postmsg(char *msg)
{
if (linemode == YES || incurses == NO) {
(void) printf("%s\n", msg);
}
else {
move(MSGLINE, 0);
clrtoeol();
addstr(msg);
refresh();
}
(void) strncpy(lastmsg, msg, sizeof(lastmsg) - 1);
}
void
clearmsg2(void)
{
if (linemode == NO) {
move(MSGLINE + 1, 0);
clrtoeol();
}
}
void
postmsg2(char *msg)
{
if (linemode == YES) {
(void) printf("%s\n", msg);
}
else {
clearmsg2();
addstr(msg);
}
}
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
{
#if HAVE_VSNPRINTF
vsnprintf(errbuf, sizeof(errbuf), msg, ap);
#else
vsprintf(errbuf, msg, ap);
#endif
postmsg2(errbuf);
}
}
void
seekline(int line)
{
int c;
if (refsfound == NULL) {
return;
}
rewind(refsfound);
nextline = 1;
while (nextline < line && (c = getc(refsfound)) != EOF) {
if (c == '\n') {
nextline++;
}
}
}
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;
}
}
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);
}
BOOL
writerefsfound(void)
{
if (refsfound == NULL) {
if ((refsfound = myfopen(temp1, "wb")) == NULL) {
cannotopen(temp1);
return(NO);
}
}
else if (freopen(temp1, "wb", refsfound) == NULL) {
postmsg("Cannot reopen temporary file");
return(NO);
}
return(YES);
}