/* * REFS.C * * Bringup a cross reference editor window. The file S:dme.refs and * dme.refs in the current directory are searched for the reference. * If found, the file specified is searched and the segment specified * loaded as a new file in a new window. */ #include "defs.h" #include #define PEN struct _PEN PEN { MNODE Node; char *path; }; extern char *breakout(); MLIST PBase; /* special DME paths */ /* * Special DME paths for REF and CTAGS */ #ifndef NO_DO2 void do_addpath() { register PEN *pen; register short len = strlen(av[1]); for (pen = (PEN *)PBase.mlh_Head; pen->Node.mln_Succ; pen = (PEN *)pen->Node.mln_Succ) { if (strcmp(av[1], pen->path) == 0) return; } if (pen = malloc(sizeof(PEN)+len+2)) { pen->path = (char *)(pen + 1); strcpy(pen->path, av[1]); switch(pen->path[len-1]) { case ':': case '/': break; default: strcat(pen->path, "/"); } } AddTail((LIST *)&PBase, (NODE *)pen); } void do_rempath() { register PEN *pen, *npen; for (pen = (PEN *)PBase.mlh_Head; npen = (PEN *)pen->Node.mln_Succ; pen = npen) { if (WildCmp(av[1], pen->path)) { Remove((NODE *)pen); free(pen); } } } #endif #ifndef NO_DO_CTAGS /* * Implement ctags */ void do_ctags() { char str[64]; char path[128]; char buf[128]; char sbuf[128]; short xlen; short slen; short dbaselen; long oldlock = CurrentDir(Ep->dirlock); ED *ed; { register short i, j; for (i = Ep->Column; Current[i] == ' '; ++i); for (j = i; ; ++j) { register short c = Current[j]; if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_') || (c >= '0' && c <= '9')) continue; break; } j -= i; if (j > 63) j = 63; BMov(Current+i, str, j); str[j] = 0; xlen = j; } if (!Ep->iconmode) title("search tags"); { void *xfi; PEN *pen, *npen; register long i; register short j, len; dbaselen = dirpart(Ep->Name); BMov(Ep->Name, path, dbaselen); strcpy(path+dbaselen, "tags"); /* * Note: pen not used first pass and set to list head, so next * pass it will be the first element. * * Note2: The file path depends on several factors. (1) tags in * 'current' directory, use path to name of current window. * (2) tags in directory in DME special path, use special * path. (3) tag entry is a full path name, override * previous directories. */ for (pen = (PEN *)&PBase; npen = (PEN *)pen->Node.mln_Succ; pen = npen) { mountrequest(0); if (xfi = xfopen(path, "r", 4096)) { mountrequest(1); while ((len = xefgets(xfi, buf, 128)) >= 0) { for (j = 0; buf[j] && buf[j] != ' '; ++j); if (j == 0 || buf[0] == '#') continue; if (j == xlen && strncmp(str, buf, j) == 0) { while (buf[j] == ' ') ++j; /* * Extract the file name into str. If the * filename does not contain an absolute path, * prepend it with such. */ { char prep = 1; for (i = 0; buf[j] && buf[j] != ' '; ++i, ++j) { str[i] = buf[j]; if (str[i] == ':') prep = 0; } if (prep) { BMov(str, str + dbaselen, i); BMov(path, str, dbaselen); i += dbaselen; } } str[i] = 0; while (buf[j] && buf[j] != '^') /* SEARCH ARG */ ++j; xfclose(xfi); if (buf[j] != '^') { title("tags error"); goto done; } ++j; strcpy(sbuf, buf+j); slen = strlen(sbuf); if ((ed = finded(str, 0)) == NULL) { strcpy(buf, "newwindow newfile "); strcat(buf, str); do_command(buf); ed = finded(str, 0); } else { WindowToFront(ed->Win); ActivateWindow(ed->Win); } if (ed == NULL) { title("unable to load file"); goto done; } text_switch(ed->Win); if (Ep->iconmode) uniconify(); else text_cursor(0); for (i = 0; i < ed->Lines; ++i) { if (strncmp(ed->List[i], sbuf, slen) == 0) break; } sprintf(buf, "first goto %ld", i+1); do_command(buf); goto done; } } xfclose(xfi); } else { mountrequest(1); } if (npen->Node.mln_Succ) { strcpy(path, npen->path); strcat(path, "tags"); dbaselen = strlen(npen->path); } } title("tag not found"); } done: CurrentDir(oldlock); } #endif #ifndef NO_DO_REFS /* * Implement references */ void do_refs() { char str[256]; char path[128]; char *srch; char *file; char *estr; long len; int bcnt = 10; register short i, j; short slen, elen; void *xfi, *xfj; short tmph, tmpw; long oldlock = CurrentDir(Ep->dirlock); for (i = Ep->Column; Current[i] == ' '; ++i); /* skip spaces */ for (j = i ; ; ++j) { if (Current[j] && Current[j] != ' ') continue; break; } j -= i; if (j > 63) j = 63; BMov(Current+i, str, j); str[j] = 0; title("search .refs"); { register PEN *pen; register PEN *npen; strcpy(path, "dme.refs"); mountrequest(0); for (pen = (PEN *)&PBase; npen = (PEN *)pen->Node.mln_Succ; pen = npen) { if (searchref(path, str, &srch, &file, &len, &estr)) { mountrequest(1); goto found; } if (npen->Node.mln_Succ) { strcpy(path, npen->path); strcat(path, "dme.refs"); } } title("Reference not found"); mountrequest(1); goto done; } found: title("search file"); slen = strlen(srch); if (estr) elen = strlen(estr); if (xfi = xfopen(file, "r", 4096)) { short lenstr; if (srch[0] == '@' && srch[1] == '@') { xfseek(xfi, atoi(srch+2)); if ((lenstr = xefgets(xfi, str, 256)) >= 0) goto autoseek; } while ((lenstr = xefgets(xfi, str, 256)) >= 0) { if (strncmp(str, srch, slen) == 0) { autoseek: title("load.."); if (xfj = xfopen("t:dme_ref", "w", 1024)) { tmph = 0; tmpw = 0; do { if (lenstr > tmpw) tmpw = strlen(str); ++tmph; xfwrite(xfj, str, strlen(str)); xfwrite(xfj, "\n", 1); if (estr && strncmp(str,estr,elen) == 0) break; --len; } while ((lenstr=xefgets(xfi, str, 256)) >= 0 && len); xfclose(xfj); if (tmph > 10) tmph = 10; if (tmpw > 80) tmpw = 80; sprintf(str, "tmpheight %ld tmpwidth %ld newwindow newfile t:dme_ref", (tmph<<3)+24, (tmpw<<3)+24); do_command(str); unlink("t:dme_ref"); } else { title("Unable to open t:dme_ref for write"); } xfclose(xfi); free(srch); free(file); if (estr) free(estr); goto done; } if (--bcnt == 0) { /* check break every so so */ bcnt = 50; if (breakcheck()) break; } } xfclose(xfi); title("Search failed"); } else { title("Unable to open sub document"); } free(srch); free(file); if (estr) free(estr); done: CurrentDir(oldlock); } /* * Reference file format: * * `key' `lines' `file' `searchstring' * * where `lines' can be a string instead ... like a read-until, otherwise * the number of lines to read from the reference. */ searchref(file, find, psstr, pfile, plines, pestr) char *file, *find; char **psstr, **pfile, **pestr; long *plines; { void *xfi; char buf[256]; char *ptr, *base; char *b1, *b2, *b3, *b4; char quoted; if (xfi = xfopen(file, "r", 4096)) { while (xefgets(xfi,(base=buf), 256) >= 0) { if (buf[0]=='#') continue; ptr = breakout(&base, "ed, &b1); if (ptr && *ptr && strncmp(ptr, find, strlen(ptr)) == 0) { if (ptr = breakout(&base, "ed, &b2)) { *pestr = NULL; *plines = atoi(ptr); if (*plines == 0) { *pestr = (char *)malloc(strlen(ptr)+1); strcpy(*pestr, ptr); } if (ptr = breakout(&base, "ed, &b3)) { *pfile = (char *)malloc(strlen(ptr)+1); strcpy(*pfile, ptr); if (ptr = breakout(&base, "ed, &b4)) { *psstr = (char *)malloc(strlen(ptr)+1); strcpy(*psstr, ptr); xfclose(xfi); if (b1) free(b1); if (b2) free(b2); if (b3) free(b3); if (b4) free(b4); return(1); } free(*pfile); if (b4) free(b4); } if (pestr) free (*pestr); if (b3) free (b3); } if (b2) free(b2); } if (b1) free(b1); } xfclose(xfi); } return(0); } #endif #ifndef NO_DO_CTAGS dirpart(str) register char *str; { register short i; for (i = strlen(str) - 1; i >= 0; --i) { if (str[i] == '/' || str[i] == ':') break; } return(i+1); } #endif