📄 tags.c
字号:
if (tf->loaded) { if (stat(tf->filename,&statbuf) != 0) { /* */ fprintf(stderr, TAG_STS_ERR_FMT, tf->filename); } else { if (tf->date == statbuf.st_mtime) { /* current tags file tf is already loaded and up to date */ continue; } } /* tags file has been modified, delete it's entries and reload it */ delTag(NULL,NULL,-2,NULL,-2,tf->index); } /* If we get here we have to try to (re-) load the tags file */ if (FileList == TipsFileList) load_status = loadTipsFile(tf->filename, tf->index, 0); else load_status = loadTagsFile(tf->filename, tf->index, 0); if(load_status) { if (stat(tf->filename,&statbuf) != 0) { if(!tf->loaded) { /* if tf->loaded == 1 we already have seen the error msg */ fprintf(stderr, TAG_STS_ERR_FMT, tf->filename); } } else { tf->date = statbuf.st_mtime; } tf->loaded = 1; } else { tf->loaded = 0; } } t = getTag(name, search_type); if (!t) { return FALSE; } else { *file = t->file; *language = t->language; *searchString = t->searchString; *pos = t->posInf; *path = t->path; return TRUE; }}/* ** This code path is followed if the request came from either** FindDefinition or FindDefCalltip. This should probably be refactored.*/static int findDef(WindowInfo *window, const char *value, int search_type) { static char tagText[MAX_TAG_LEN + 1]; const char *p; char message[MAX_TAG_LEN+40]; int l, ml, status = 0; searchMode = search_type; l = strlen(value); if (l <= MAX_TAG_LEN) { /* should be of type text??? */ for (p = value; *p && isascii(*p); p++) { } if (!(*p)) { ml = ((l < MAX_TAG_LEN) ? (l) : (MAX_TAG_LEN)); strncpy(tagText, value, ml); tagText[ml] = '\0'; /* See if we can find the tip/tag */ status = findAllMatches(window, tagText); /* If we didn't find a requested calltip, see if we can use a tag */ if (status == 0 && search_type == TIP && TagsFileList != NULL) { searchMode = TIP_FROM_TAG; status = findAllMatches(window, tagText); } if (status == 0) { /* Didn't find any matches */ if (searchMode == TIP_FROM_TAG || searchMode == TIP) { sprintf(message, "No match for \"%s\" in calltips or tags.", tagName); tagsShowCalltip( window, message ); } else { DialogF(DF_WARN, window->textArea, 1, "Tags", "\"%s\" not found in tags file%s", "OK", tagName, (TagsFileList && TagsFileList->next) ? "s" : ""); } } } else { fprintf(stderr, "NEdit: Can't handle non 8-bit text\n"); XBell(TheDisplay, 0); } } else { fprintf(stderr, "NEdit: Tag Length too long.\n"); XBell(TheDisplay, 0); } return status;}/*** Lookup the definition for the current primary selection the currently** loaded tags file and bring up the file and line that the tags file** indicates.*/void findDefinitionHelper(WindowInfo *window, Time time, const char *arg, int search_type){ if(arg) { findDef(window, arg, search_type); } else { searchMode = search_type; XtGetSelectionValue(window->textArea, XA_PRIMARY, XA_STRING, (XtSelectionCallbackProc)findDefCB, window, time); }}/*** See findDefHelper*/void FindDefinition(WindowInfo *window, Time time, const char *arg){ findDefinitionHelper(window, time, arg, TAG);}/*** See findDefHelper*/void FindDefCalltip(WindowInfo *window, Time time, const char *arg){ /* Reset calltip parameters to reasonable defaults */ globAnchored = False; globPos = -1; globHAlign = TIP_LEFT; globVAlign = TIP_BELOW; globAlignMode = TIP_SLOPPY; findDefinitionHelper(window, time, arg, TIP);}/* Callback function for FindDefinition */static void findDefCB(Widget widget, WindowInfo *window, Atom *sel, Atom *type, char *value, int *length, int *format){ /* skip if we can't get the selection data, or it's obviously too long */ if (*type == XT_CONVERT_FAIL || value == NULL) { XBell(TheDisplay, 0); } else { findDef(window, value, searchMode); } XtFree(value);}/* ** Try to display a calltip** anchored: If true, tip appears at position pos** lookup: If true, text is considered a key to be searched for in the** tip and/or tag database depending on search_type** search_type: Either TIP or TIP_FROM_TAG*/int ShowTipString(WindowInfo *window, char *text, Boolean anchored, int pos, Boolean lookup, int search_type, int hAlign, int vAlign, int alignMode) { if (search_type == TAG) return 0; /* So we don't have to carry all of the calltip alignment info around */ globAnchored = anchored; globPos = pos; globHAlign = hAlign; globVAlign = vAlign; globAlignMode = alignMode; /* If this isn't a lookup request, just display it. */ if (!lookup) return tagsShowCalltip(window, text); else return findDef(window, text, search_type);}/* store all of the info into a pre-allocated tags struct */static void setTag(tag *t, const char *name, const char *file, int language, const char *searchString, int posInf, const char *path){ t->name = rcs_strdup(name); t->file = rcs_strdup(file); t->language = language; t->searchString = rcs_strdup(searchString); t->posInf = posInf; t->path = rcs_strdup(path);}/*** ctags search expressions are literal strings with a search direction flag, ** line starting "^" and ending "$" delimiters. This routine translates them ** into NEdit compatible regular expressions and does the search.** Etags search expressions are plain literals strings, which ** ** If in_buffer is not NULL then it is searched instead of the window buffer.** In this case in_buffer should be an XtMalloc allocated buffer and the** caller is responsible for freeing it.*/static int fakeRegExSearch(WindowInfo *window, char *in_buffer, const char *searchString, int *startPos, int *endPos){ int found, searchStartPos, dir, ctagsMode; char *fileString, searchSubs[3*MAXLINE+3], *outPtr; const char *inPtr; if (in_buffer == NULL) { /* get the entire (sigh) text buffer from the text area widget */ fileString = BufGetAll(window->buffer); } else { fileString = in_buffer; } /* determine search direction and start position */ if (*startPos != -1) { /* etags mode! */ dir = SEARCH_FORWARD; searchStartPos = *startPos; ctagsMode=0; } else if (searchString[0] == '/') { dir = SEARCH_FORWARD; searchStartPos = 0; ctagsMode=1; } else if (searchString[0] == '?') { dir = SEARCH_BACKWARD; /* searchStartPos = window->buffer->length; */ searchStartPos = strlen(fileString); ctagsMode=1; } else { fprintf(stderr, "NEdit: Error parsing tag file search string"); if(in_buffer == NULL) XtFree(fileString); return FALSE; } /* Build the search regex. */ outPtr=searchSubs; if(ctagsMode) { inPtr=searchString+1; /* searchString[0] is / or ? --> search dir */ if(*inPtr == '^') { /* If the first char is a caret then it's a RE line start delim */ *outPtr++ = *inPtr++; } } else { /* etags mode, no search dir spec, no leading caret */ inPtr=searchString; } while(*inPtr) { if( (*inPtr=='\\' && inPtr[1]=='/') || (*inPtr=='\r' && inPtr[1]=='$' && !inPtr[2]) ) { /* Remove: - escapes (added by standard and exuberant ctags) from slashes - literal CRs generated by standard ctags for DOSified sources */ inPtr++; } else if(strchr("()-[]<>{}.|^*+?&\\", *inPtr) || (*inPtr == '$' && (inPtr[1]||(!ctagsMode)))){ /* Escape RE Meta Characters to match them literally. Don't escape $ if it's the last charcter of the search expr in ctags mode; always escape $ in etags mode. */ *outPtr++ = '\\'; *outPtr++ = *inPtr++; } else if (isspace((unsigned char)*inPtr)) { /* col. multiple spaces */ *outPtr++ = '\\'; *outPtr++ = 's'; *outPtr++ = '+'; do { inPtr++ ; } while(isspace((unsigned char)*inPtr)); } else { /* simply copy all other characters */ *outPtr++ = *inPtr++; } } *outPtr=0; /* Terminate searchSubs */ found = SearchString(fileString, searchSubs, dir, SEARCH_REGEX, False, searchStartPos, startPos, endPos, NULL, NULL, NULL); if(!found && !ctagsMode) { /* position of the target definition could have been drifted before startPos, if nothing has been found by now try searching backward again from startPos. */ found = SearchString(fileString, searchSubs, SEARCH_BACKWARD, SEARCH_REGEX, False, searchStartPos, startPos, endPos, NULL, NULL, NULL); } /* free the text buffer copy returned from XmTextGetString */ if(in_buffer == NULL) XtFree(fileString); /* return the result */ if (found) { /* *startPos and *endPos are set in SearchString*/ return TRUE; } else { /* startPos, endPos left untouched by SearchString if search failed. */ XBell(TheDisplay, 0); return FALSE; }}/* Finds all matches and handles tag "collisions". Prompts user with a list of collided tags in the hash table and allows the user to select the correct one. */static int findAllMatches(WindowInfo *window, const char *string){ Widget dialogParent = window->textArea; char filename[MAXPATHLEN], pathname[MAXPATHLEN]; char temp[32+2*MAXPATHLEN+MAXLINE]; const char *fileToSearch, *searchString, *tagPath; char **dupTagsList; int startPos, i, pathMatch=0, samePath=0, langMode, nMatches=0; /* verify that the string is reasonable as a tag */ if (*string == '\0' || strlen(string) > MAX_TAG_LEN) { XBell(TheDisplay, 0); return -1; } tagName=string; /* First look up all of the matching tags */ while (LookupTag(string, &fileToSearch, &langMode, &searchString, &startPos, &tagPath, searchMode)) { /* Skip this tag if it has a language mode that doesn't match the current language mode, but don't skip anything if the window is in PLAIN_LANGUAGE_MODE. */ if (window->languageMode != PLAIN_LANGUAGE_MODE && GetPrefSmartTags() && langMode != PLAIN_LANGUAGE_MODE && langMode != window->languageMode) { string=NULL; continue; } if (*fileToSearch == '/') strcpy(tagFiles[nMatches], fileToSearch); else sprintf(tagFiles[nMatches],"%s%s",tagPath,fileToSearch); strcpy(tagSearch[nMatches],searchString); tagPosInf[nMatches]=startPos; ParseFilename(tagFiles[nMatches], filename, pathname); /* Is this match in the current file? If so, use it! */ if (GetPrefSmartTags() && !strcmp(window->filename,filename) && !strcmp(window->path,pathname) ) { if (nMatches) { strcpy(tagFiles[0],tagFiles[nMatches]); strcpy(tagSearch[0],tagSearch[nMatches]); tagPosInf[0]=tagPosInf[nMatches]; } nMatches = 1; break; } /* Is this match in the same dir. as the current file? */ if (!strcmp(window->path,pathname)) { samePath++; pathMatch=nMatches; } if (++nMatches >= MAXDUPTAGS) { DialogF(DF_WARN, dialogParent, 1, "Tags", "Too many duplicate tags, first %d shown", "OK", MAXDUPTAGS); break; } /* Tell LookupTag to look for more definitions of the same tag: */ string = NULL; } /* Did we find any matches? */ if (!nMatches) { return 0; } /* Only one of the matches is in the same dir. as this file. Use it. */ if (GetPrefSmartTags() && samePath == 1 && nMatches > 1) { strcpy(tagFiles[0],tagFiles[pathMatch]); strcpy(tagSearch[0],tagSearch[pathMatch]); tagPosInf[0]=tagPosInf[pathMatch]; nMatches = 1; } /* If all of the tag entries are the same file, just use the first. */ if (GetPrefSmartTags()) { for (i=1; i<nMatches; i++) if (strcmp(tagFiles[i],tagFiles[i-1])) break; if (i==nMatches) nMatches = 1; } if (nMatches>1) { if (!(dupTagsList = (char **) malloc(sizeof(char *) * nMatches))) { fprintf(stderr, "NEdit: findDef(): out of heap space!\n"); XBell(TheDisplay, 0); return -1; } for (i=0; i<nMatches; i++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -