⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tags.c

📁 nedit 是一款linux下的开发源码的功能强大的编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
static const char CVSID[] = "$Id: tags.c,v 1.51.2.1 2003/07/31 22:35:17 n8gray Exp $";/********************************************************************************                                                                              ** tags.c -- Nirvana editor tag file handling                                   **                                                                              ** Copyright (C) 1999 Mark Edel                                                 **                                                                              ** This is free software; you can redistribute it and/or modify it under the    ** terms of the GNU General Public License as published by the Free Software    ** Foundation; either version 2 of the License, or (at your option) any later   ** version.                                                                     **                                                                              ** This software is distributed in the hope that it will be useful, but WITHOUT ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or        ** FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License        ** for more details.                                                            **                                                                              ** You should have received a copy of the GNU General Public License along with ** software; if not, write to the Free Software Foundation, Inc., 59 Temple     ** Place, Suite 330, Boston, MA  02111-1307 USA                                 **                                                                              ** Nirvana Text Editor                                                          ** July, 1993                                                                   **                                                                              ** Written by Mark Edel                                                         **                                                                              ********************************************************************************/#ifdef HAVE_CONFIG_H#include "../config.h"#endif#include "tags.h"#include "textBuf.h"#include "text.h"#include "nedit.h"#include "window.h"#include "file.h"#include "preferences.h"#include "search.h"#include "selection.h"#include "calltips.h"#include "../util/DialogF.h"#include "../util/fileUtils.h"#include "../util/misc.h"#include "../util/utils.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#ifdef VMS#include "../util/VMSparam.h"#else#ifndef __MVS__#include <sys/param.h>#endif#endif /*VMS*/#include <Xm/PrimitiveP.h> /* For Calltips */#include <Xm/Xm.h>#include <Xm/SelectioB.h>#include <X11/Xatom.h>#ifdef HAVE_DEBUG_H#include "../debug.h"#endif#define MAXLINE 2048#define MAX_TAG_LEN 256#define MAXDUPTAGS 100#define MAX_TAG_INCLUDE_RECURSION_LEVEL 5 /* Take this many lines when making a tip from a tag.   (should probably be a language-dependent option, but...) */#define TIP_DEFAULT_LINES 4#define STRSAVE(a)  ((a!=NULL)?strcpy(malloc(strlen(a)+1),(a)):strcpy(malloc(1),""))typedef struct _tag {    struct _tag *next;    const char *path;    const char *name;    const char *file;    int language;    const char *searchString; /* see comment below */    int posInf;               /* see comment below */    short index;} tag;/***  contents of                   tag->searchString   | tag->posInf**    ctags, line num specified:  ""                  | line num**    ctags, search expr specfd:  ctags search expr   | -1**    etags  (emacs tags)         etags search string | search start pos*/enum searchDirection {FORWARD, BACKWARD};static int loadTagsFile(const char *tagSpec, int index, int recLevel);static void findDefCB(Widget widget, WindowInfo *window, Atom *sel,        Atom *type, char *value, int *length, int *format);static void setTag(tag *t, const char *name, const char *file,                   int language, const char *searchString, int posInf,                    const char * tag);static int fakeRegExSearch(WindowInfo *window, char *buffer,                         const char *searchString, int *startPos, int *endPos);static unsigned hashAddr(const char *key);static void updateMenuItems();static int addTag(const char *name, const char *file, int lang,                     const char *search, int posInf,  const  char *path,                     int index);static int delTag(const char *name, const char *file, int lang,                     const char *search, int posInf,  int index);static tag *getTag(const char *name, int search_type);static int findDef(WindowInfo *window, const char *value, int search_type);static int findAllMatches(WindowInfo *window, const char *string);static void findAllCB(Widget parent, XtPointer client_data, XtPointer call_data);static Widget createSelectMenu(Widget parent, char *label, int nArgs,        char *args[]);static void editTaggedLocation( Widget parent, int i );static void showMatchingCalltip( Widget parent, int i );static const char *rcs_strdup(const char *str);static void rcs_free(const char *str);static int searchLine(char *line, const char *regex);static void rstrip( char *dst, const char *src );static int nextTFBlock(FILE *fp, char *header, char **tiptext, int *lineAt,         int *lineNo);static int loadTipsFile(const char *tipsFile, int index, int recLevel);/* Hash table of tags, implemented as an array.  Each bin contains a     NULL-terminated linked list of parsed tags */static tag **Tags = NULL;static int DefTagHashSize = 10000;/* list of loaded tags files */tagFile *TagsFileList = NULL;/* Hash table of calltip tags */static tag **Tips = NULL;tagFile *TipsFileList = NULL;/* These are all transient global variables -- they don't hold any state    between tag/tip lookups */static int searchMode = TAG;static const char *tagName;static char tagFiles[MAXDUPTAGS][MAXPATHLEN];static char tagSearch[MAXDUPTAGS][MAXPATHLEN];static int  tagPosInf[MAXDUPTAGS];static Boolean globAnchored;static int globPos;static int globHAlign;static int globVAlign;static int globAlignMode;/* A wrapper for calling TextDShowCalltip */static int tagsShowCalltip( WindowInfo *window, char *text ) {    if (text)         return ShowCalltip( window, text, globAnchored, globPos, globHAlign,                 globVAlign, globAlignMode);    else        return 0;}/* Set the head of the proper file list (Tags or Tips) to t */static tagFile *setFileListHead(tagFile *t, int file_type ) {    if (file_type == TAG)        TagsFileList = t;    else        TipsFileList = t;    return t;}/*      Compute hash address from a string key */static unsigned hashAddr(const char *key){    unsigned s=strlen(key);    unsigned a=0,x=0,i;        for (i=0; (i+3)<s; i += 4) {        strncpy((char*)&a,&key[i],4);        x += a;    }        for (a=1; i<(s+1); i++, a *= 256)        x += key[i] * a;            return x;}/*      Retrieve a tag structure from the hash table */static tag *getTag(const char *name, int search_type){    static char lastName[MAXLINE];    static tag *t;    static int addr;    tag **table;        if (search_type == TIP)        table = Tips;    else        table = Tags;            if (table == NULL) return NULL;        if (name) {        addr = hashAddr(name) % DefTagHashSize;        t = table[addr];        strcpy(lastName,name);    }    else if (t) {        name = lastName;        t = t->next;    }    else return NULL;        for (;t; t = t->next)         if (!strcmp(name,t->name)) return t;    return NULL;}/* Add a tag specification to the hash table **   Return Value:  0 ... tag already existing, spec not added**                  1 ... tag spec is new, added.**   (We don't return boolean as the return value is used as counter increment!)***/static int addTag(const char *name, const char *file, int lang,                     const char *search, int posInf, const char *path, int index){    int addr = hashAddr(name) % DefTagHashSize;    tag *t;    char newfile[MAXPATHLEN];    tag **table;    if (searchMode == TIP) {        if (Tips == NULL)             Tips = (tag **)calloc(DefTagHashSize, sizeof(tag*));        table = Tips;    } else {        if (Tags == NULL)             Tags = (tag **)calloc(DefTagHashSize, sizeof(tag*));        table = Tags;    }        if (*file == '/')        strcpy(newfile,file);    else        sprintf(newfile,"%s%s", path, file);        NormalizePathname(newfile);    CompressPathname(newfile);            for (t = table[addr]; t; t = t->next) {        if (strcmp(name,t->name)) continue;        if (lang != t->language) continue;        if (strcmp(search,t->searchString)) continue;        if (posInf != t->posInf) continue;        if (*t->file == '/' && strcmp(newfile,t->file)) continue;        if (*t->file != '/') {            char tmpfile[MAXPATHLEN];            sprintf(tmpfile, "%s%s", t->path, t->file);            NormalizePathname(tmpfile);            CompressPathname(tmpfile);            if (strcmp(newfile, tmpfile)) continue;        }        return 0;    }            t = (tag *) malloc(sizeof(tag));    setTag(t, name, file, lang, search, posInf, path);    t->index = index;    t->next = table[addr];    table[addr] = t;    return 1;}/*  Delete a tag from the cache.   *  Search is limited to valid matches of 'name','file', 'search', posInf, and 'index'. *  EX: delete all tags matching index 2 ==>  *                      delTag(tagname,NULL,-2,NULL,-2,2); *  (posInf = -2 is an invalid match, posInf range: -1 .. +MAXINT,     lang = -2 is also an invalid match) */static int delTag(const char *name, const char *file, int lang,                    const char *search, int posInf, int index){    tag *t, *last;    int start,finish,i,del=0;    tag **table;    if (searchMode == TIP)        table = Tips;    else        table = Tags;            if (table == NULL) return FALSE;    if (name)        start = finish = hashAddr(name) % DefTagHashSize;    else {        start = 0;        finish = DefTagHashSize;    }    for (i = start; i<finish; i++) {        for (last = NULL, t = table[i]; t; last = t, t = t?t->next:table[i]) {            if (name && strcmp(name,t->name)) continue;            if (index && index != t->index) continue;            if (file && strcmp(file,t->file)) continue;            if (lang >= PLAIN_LANGUAGE_MODE && lang != t->language) continue;            if (search && strcmp(search,t->searchString)) continue;            if (posInf == t->posInf) continue;            if (last)                last->next = t->next;            else                table[i] = t->next;            rcs_free(t->name);            rcs_free(t->file);            rcs_free(t->searchString);            rcs_free(t->path);            free(t);            t = NULL;            del++;        }    }    return del>0;}/* used  in AddRelTagsFile and AddTagsFile */static int tagFileIndex = 0; /*  ** AddRelTagsFile():  Rescan tagSpec for relative tag file specs ** (not starting with [/~]) and extend the tag files list if in** windowPath a tags file matching the relative spec has been found.*/int AddRelTagsFile(const char *tagSpec, const char *windowPath, int file_type) {    tagFile *t;    int added=0;    struct stat statbuf;    char *filename;    char pathName[MAXPATHLEN];    char *tmptagSpec;    tagFile *FileList;        searchMode = file_type;    if (searchMode == TAG)        FileList = TagsFileList;    else        FileList = TipsFileList;    tmptagSpec = (char *) malloc(strlen(tagSpec)+1);    strcpy(tmptagSpec, tagSpec);    for (filename = strtok(tmptagSpec, ":"); filename; filename = strtok(NULL, ":")){        if (*filename == '/' || *filename == '~')            continue;        if (windowPath && *windowPath) {            strcpy(pathName, windowPath);        } else {            strcpy(pathName, GetCurrentDir());         }           strcat(pathName, "/");        strcat(pathName, filename);        NormalizePathname(pathName);        CompressPathname(pathName);        for (t = FileList; t && strcmp(t->filename, pathName); t = t->next);        if (t) {            added=1;            continue;        }        if (stat(pathName, &statbuf) != 0)            continue;        t = (tagFile *) malloc(sizeof(tagFile));        t->filename = STRSAVE(pathName);        t->loaded = 0;        t->date = statbuf.st_mtime;        t->index = ++tagFileIndex;        t->next = FileList;        FileList = setFileListHead(t, file_type);        added=1;    }    free(tmptagSpec);    updateMenuItems();    if (added)        return TRUE;    else        return FALSE;} /*  **  AddTagsFile():  Set up the the list of tag files to manage from a file spec.**  The file spec comes from the X-Resource Nedit.tags: It can list multiple **  tags files, specified by separating them with colons. The .Xdefaults would **  look like this:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -