]> git.rkrishnan.org Git - .emacs.d.git/blob - emacs/xcscope.el
ce382a44b17c21ef589b4b51f3aeb7d8a608cf49
[.emacs.d.git] / emacs / xcscope.el
1 ; -*-Emacs-Lisp-*-
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;
4 ; File:         xcscope.el
5 ; RCS:          $RCSfile: xcscope.el,v $ $Revision: 1.14 $ $Date: 2002/04/10 16:59:00 $ $Author: darrylo $
6 ; Description:  cscope interface for (X)Emacs
7 ; Author:       Darryl Okahata
8 ; Created:      Wed Apr 19 17:03:38 2000
9 ; Modified:     Thu Apr  4 17:22:22 2002 (Darryl Okahata) darrylo@soco.agilent.com
10 ; Language:     Emacs-Lisp
11 ; Package:      N/A
12 ; Status:       Experimental
13 ;
14 ; (C) Copyright 2000, 2001, 2002, Darryl Okahata <darrylo@sonic.net>,
15 ;     all rights reserved.
16 ; GNU Emacs enhancements (C) Copyright 2001,
17 ;         Triet H. Lai <thlai@mail.usyd.edu.au>
18 ; Fuzzy matching and navigation code (C) Copyright 2001,
19 ;         Steven Elliott <selliott4@austin.rr.com>
20 ;
21 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
22 ;; ALPHA VERSION 0.96
23 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
24 ;;
25 ;; This program is free software; you can redistribute it and/or modify
26 ;; it under the terms of the GNU General Public License as published by
27 ;; the Free Software Foundation; either version 2, or (at your option)
28 ;; any later version.
29 ;;
30 ;; This program is distributed in the hope that it will be useful,
31 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
32 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
33 ;; GNU General Public License for more details.
34 ;;
35 ;; You should have received a copy of the GNU General Public License
36 ;; along with GNU Emacs; see the file COPYING.  If not, write to
37 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
38 ;;
39 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
40 ;;
41 ;; This is a cscope interface for (X)Emacs.
42 ;; It currently runs under Unix only.
43 ;;
44 ;; Using cscope, you can easily search for where symbols are used and defined.
45 ;; Cscope is designed to answer questions like:
46 ;;
47 ;;         Where is this variable used?
48 ;;         What is the value of this preprocessor symbol?
49 ;;         Where is this function in the source files?
50 ;;         What functions call this function?
51 ;;         What functions are called by this function?
52 ;;         Where does the message "out of space" come from?
53 ;;         Where is this source file in the directory structure?
54 ;;         What files include this header file?
55 ;;
56 ;; Send comments to one of:     darrylo@soco.agilent.com
57 ;;                              darryl_okahata@agilent.com
58 ;;                              darrylo@sonic.net
59 ;;
60 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
61 ;;
62 ;; ***** INSTALLATION *****
63 ;;
64 ;; * NOTE: this interface currently runs under Unix only.
65 ;;
66 ;; This module needs a shell script called "cscope-indexer", which
67 ;; should have been supplied along with this emacs-lisp file.  The
68 ;; purpose of "cscope-indexer" is to create and optionally maintain
69 ;; the cscope databases.  If all of your source files are in one
70 ;; directory, you don't need this script; it's very nice to have,
71 ;; though, as it handles recursive subdirectory indexing, and can be
72 ;; used in a nightly or weekly cron job to index very large source
73 ;; repositories.  See the beginning of the file, "cscope-indexer", for
74 ;; usage information.
75 ;;
76 ;; Installation steps:
77 ;;
78 ;; 0. (It is, of course, assumed that cscope is already properly
79 ;;    installed on the current system.)
80 ;;
81 ;; 1. Install the "cscope-indexer" script into some convenient
82 ;;    directory in $PATH.  The only real constraint is that (X)Emacs
83 ;;    must be able to find and execute it.  You may also have to edit
84 ;;    the value of PATH in the script, although this is unlikely; the
85 ;;    majority of people should be able to use the script, "as-is".
86 ;;
87 ;; 2. Make sure that the "cscope-indexer" script is executable.  In
88 ;;    particular, if you had to ftp this file, it is probably no
89 ;;    longer executable.
90 ;;
91 ;; 3. Put this emacs-lisp file somewhere where (X)Emacs can find it.  It
92 ;;    basically has to be in some directory listed in "load-path".
93 ;;
94 ;; 4. Edit your ~/.emacs file to add the line:
95 ;;
96 ;;      (require 'xcscope)
97 ;;
98 ;; 5. If you intend to use xcscope.el often you can optionally edit your
99 ;;    ~/.emacs file to add keybindings that reduce the number of keystrokes
100 ;;    required.  For example, the following will add "C-f#" keybindings, which
101 ;;    are easier to type than the usual "C-c s" prefixed keybindings.  Note
102 ;;    that specifying "global-map" instead of "cscope:map" makes the
103 ;;    keybindings available in all buffers:
104 ;;
105 ;;      (define-key global-map [(control f3)]  'cscope-set-initial-directory)
106 ;;      (define-key global-map [(control f4)]  'cscope-unset-initial-directory)
107 ;;      (define-key global-map [(control f5)]  'cscope-find-this-symbol)
108 ;;      (define-key global-map [(control f6)]  'cscope-find-global-definition)
109 ;;      (define-key global-map [(control f7)]
110 ;;        'cscope-find-global-definition-no-prompting)
111 ;;      (define-key global-map [(control f8)]  'cscope-pop-mark)
112 ;;      (define-key global-map [(control f9)]  'cscope-next-symbol)
113 ;;      (define-key global-map [(control f10)] 'cscope-next-file)
114 ;;      (define-key global-map [(control f11)] 'cscope-prev-symbol)
115 ;;      (define-key global-map [(control f12)] 'cscope-prev-file)
116 ;;      (define-key global-map [(meta f9)]  'cscope-display-buffer)
117 ;;      (defin-ekey global-map [(meta f10)] 'cscope-display-buffer-toggle)
118 ;;
119 ;; 6. Restart (X)Emacs.  That's it.
120 ;;
121 ;;
122 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
123 ;;
124 ;; ***** USING THIS MODULE *****
125 ;;
126 ;; * Basic usage:
127 ;;
128 ;; If all of your C/C++/lex/yacc source files are in the same
129 ;; directory, you can just start using this module.  If your files are
130 ;; spread out over multiple directories, see "Advanced usage", below.
131 ;;
132 ;; Just edit a source file, and use the pull-down or pop-up (button 3)
133 ;; menus to select one of:
134 ;;
135 ;;         Find symbol
136 ;;         Find global definition
137 ;;         Find called functions
138 ;;         Find functions calling a function
139 ;;         Find text string
140 ;;         Find egrep pattern
141 ;;         Find a file
142 ;;         Find files #including a file
143 ;;
144 ;; The cscope database will be automatically created in the same
145 ;; directory as the source files (assuming that you've never used
146 ;; cscope before), and a buffer will pop-up displaying the results.
147 ;; You can then use button 2 (the middle button) on the mouse to edit
148 ;; the selected file, or you can move the text cursor over a selection
149 ;; and press [Enter].
150 ;;
151 ;; Hopefully, the interface should be fairly intuitive.
152 ;;
153 ;;
154 ;; * Locating the cscope databases:
155 ;;
156 ;; This module will first use the variable, `cscope-database-regexps',
157 ;; to search for a suitable database directory.  If a database location
158 ;; cannot be found using this variable then a search is begun at the
159 ;; variable, `cscope-initial-directory', if set, or the current
160 ;; directory otherwise.  If the directory is not a cscope database
161 ;; directory then the directory's parent, parent's parent, etc. is
162 ;; searched until a cscope database directory is found, or the root
163 ;; directory is reached.  If the root directory is reached, the current
164 ;; directory will be used.
165 ;;
166 ;; A cscope database directory is one in which EITHER a cscope database
167 ;; file (e.g., "cscope.out") OR a cscope file list (e.g.,
168 ;; "cscope.files") exists.  If only "cscope.files" exists, the
169 ;; corresponding "cscope.out" will be automatically created by cscope
170 ;; when a search is done.  By default, the cscope database file is called
171 ;; "cscope.out", but this can be changed (on a global basis) via the
172 ;; variable, `cscope-database-file'.  There is limited support for cscope
173 ;; databases that are named differently than that given by
174 ;; `cscope-database-file', using the variable, `cscope-database-regexps'.
175 ;;
176 ;; Note that the variable, `cscope-database-regexps', is generally not
177 ;; needed, as the normal hierarchical database search is sufficient
178 ;; for placing and/or locating the cscope databases.  However, there
179 ;; may be cases where it makes sense to place the cscope databases
180 ;; away from where the source files are kept; in this case, this
181 ;; variable is used to determine the mapping.  One use for this
182 ;; variable is when you want to share the database file with other
183 ;; users; in this case, the database may be located in a directory
184 ;; separate from the source files.  
185 ;;
186 ;; Setting the variable, `cscope-initial-directory', is useful when a
187 ;; search is to be expanded by specifying a cscope database directory
188 ;; that is a parent of the directory that this module would otherwise
189 ;; use.  For example, consider a project that contains the following
190 ;; cscope database directories:
191 ;;
192 ;;     /users/jdoe/sources
193 ;;     /users/jdoe/sources/proj1
194 ;;     /users/jdoe/sources/proj2
195 ;;
196 ;; If a search is initiated from a .c file in /users/jdoe/sources/proj1
197 ;; then (assuming the variable, `cscope-database-regexps', is not set)
198 ;; /users/jdoe/sources/proj1 will be used as the cscope data base directory.
199 ;; Only matches in files in /users/jdoe/sources/proj1 will be found.  This
200 ;; can be remedied by typing "C-c s a" and then "M-del" to remove single
201 ;; path element in order to use a cscope database directory of
202 ;; /users/jdoe/sources.  Normal searching can be restored by typing "C-c s A".
203 ;;
204 ;;
205 ;; * Keybindings:
206 ;;
207 ;; All keybindings use the "C-c s" prefix, but are usable only while
208 ;; editing a source file, or in the cscope results buffer:
209 ;;
210 ;;      C-c s s         Find symbol.
211 ;;      C-c s d         Find global definition.
212 ;;      C-c s g         Find global definition (alternate binding).
213 ;;      C-c s G         Find global definition without prompting.
214 ;;      C-c s c         Find functions calling a function.
215 ;;      C-c s C         Find called functions (list functions called
216 ;;                      from a function).
217 ;;      C-c s t         Find text string.
218 ;;      C-c s e         Find egrep pattern.
219 ;;      C-c s f         Find a file.
220 ;;      C-c s i         Find files #including a file.
221 ;;
222 ;; These pertain to navigation through the search results:
223 ;;
224 ;;      C-c s b         Display *cscope* buffer.
225 ;;      C-c s B         Auto display *cscope* buffer toggle.
226 ;;      C-c s n         Next symbol.
227 ;;      C-c s N         Next file.
228 ;;      C-c s p         Previous symbol.
229 ;;      C-c s P         Previous file.
230 ;;      C-c s u         Pop mark.
231 ;;
232 ;; These pertain to setting and unsetting the variable,
233 ;; `cscope-initial-directory', (location searched for the cscope database
234 ;;  directory):
235 ;;
236 ;;      C-c s a         Set initial directory.
237 ;;      C-c s A         Unset initial directory.
238 ;;
239 ;; These pertain to cscope database maintenance:
240 ;;
241 ;;      C-c s L         Create list of files to index.
242 ;;      C-c s I         Create list and index.
243 ;;      C-c s E         Edit list of files to index.
244 ;;      C-c s W         Locate this buffer's cscope directory
245 ;;                      ("W" --> "where").
246 ;;      C-c s S         Locate this buffer's cscope directory.
247 ;;                      (alternate binding: "S" --> "show").
248 ;;      C-c s T         Locate this buffer's cscope directory.
249 ;;                      (alternate binding: "T" --> "tell").
250 ;;      C-c s D         Dired this buffer's directory.
251 ;;
252 ;;
253 ;; * Advanced usage:
254 ;;
255 ;; If the source files are spread out over multiple directories,
256 ;; you've got a few choices:
257 ;;
258 ;; [ NOTE: you will need to have the script, "cscope-indexer",
259 ;;   properly installed in order for the following to work.  ]
260 ;;
261 ;; 1. If all of the directories exist below a common directory
262 ;;    (without any extraneous, unrelated subdirectories), you can tell
263 ;;    this module to place the cscope database into the top-level,
264 ;;    common directory.  This assumes that you do not have any cscope
265 ;;    databases in any of the subdirectories.  If you do, you should
266 ;;    delete them; otherwise, they will take precedence over the
267 ;;    top-level database.
268 ;;
269 ;;    If you do have cscope databases in any subdirectory, the
270 ;;    following instructions may not work right.
271 ;;
272 ;;    It's pretty easy to tell this module to use a top-level, common
273 ;;    directory:
274 ;;
275 ;;    a. Make sure that the menu pick, "Cscope/Index recursively", is
276 ;;       checked (the default value).
277 ;;
278 ;;    b. Select the menu pick, "Cscope/Create list and index", and
279 ;;       specify the top-level directory.  This will run the script,
280 ;;       "cscope-indexer", in the background, so you can do other
281 ;;       things if indexing takes a long time.  A list of files to
282 ;;       index will be created in "cscope.files", and the cscope
283 ;;       database will be created in "cscope.out".
284 ;;
285 ;;    Once this has been done, you can then use the menu picks
286 ;;    (described in "Basic usage", above) to search for symbols.
287 ;;
288 ;;    Note, however, that, if you add or delete source files, you'll
289 ;;    have to either rebuild the database using the above procedure,
290 ;;    or edit the file, "cscope.files" to add/delete the names of the
291 ;;    source files.  To edit this file, you can use the menu pick,
292 ;;    "Cscope/Edit list of files to index".
293 ;;
294 ;;
295 ;; 2. If most of the files exist below a common directory, but a few
296 ;;    are outside, you can use the menu pick, "Cscope/Create list of
297 ;;    files to index", and specify the top-level directory.  Make sure
298 ;;    that "Cscope/Index recursively", is checked before you do so,
299 ;;    though.  You can then edit the list of files to index using the
300 ;;    menu pick, "Cscope/Edit list of files to index".  Just edit the
301 ;;    list to include any additional source files not already listed.
302 ;;
303 ;;    Once you've created, edited, and saved the list, you can then
304 ;;    use the menu picks described under "Basic usage", above, to
305 ;;    search for symbols.  The first time you search, you will have to
306 ;;    wait a while for cscope to fully index the source files, though.
307 ;;    If you have a lot of source files, you may want to manually run
308 ;;    cscope to build the database:
309 ;;
310 ;;            cd top-level-directory    # or wherever
311 ;;            rm -f cscope.out          # not always necessary
312 ;;            cscope -b
313 ;;
314 ;;
315 ;; 3. If the source files are scattered in many different, unrelated
316 ;;    places, you'll have to manually create cscope.files and put a
317 ;;    list of all pathnames into it.  Then build the database using:
318 ;;
319 ;;            cd some-directory         # wherever cscope.files exists
320 ;;            rm -f cscope.out          # not always necessary
321 ;;            cscope -b
322 ;;
323 ;;    Next, read the documentation for the variable,
324 ;;    "cscope-database-regexps", and set it appropriately, such that
325 ;;    the above-created cscope database will be referenced when you
326 ;;    edit a related source file.
327 ;;
328 ;;    Once this has been done, you can then use the menu picks
329 ;;    described under "Basic usage", above, to search for symbols.
330 ;;
331 ;;
332 ;; * Interesting configuration variables:
333 ;;
334 ;; "cscope-truncate-lines"
335 ;;      This is the value of `truncate-lines' to use in cscope
336 ;;      buffers; the default is the current setting of
337 ;;      `truncate-lines'.  This variable exists because it can be
338 ;;      easier to read cscope buffers with truncated lines, while
339 ;;      other buffers do not have truncated lines.
340 ;;
341 ;; "cscope-use-relative-paths"
342 ;;      If non-nil, use relative paths when creating the list of files
343 ;;      to index.  The path is relative to the directory in which the
344 ;;      cscope database will be created.  If nil, absolute paths will
345 ;;      be used.  Absolute paths are good if you plan on moving the
346 ;;      database to some other directory (if you do so, you'll
347 ;;      probably also have to modify `cscope-database-regexps').
348 ;;      Absolute paths may also be good if you share the database file
349 ;;      with other users (you'll probably want to specify some
350 ;;      automounted network path for this).
351 ;;
352 ;; "cscope-index-recursively"
353 ;;      If non-nil, index files in the current directory and all
354 ;;      subdirectories.  If nil, only files in the current directory
355 ;;      are indexed.  This variable is only used when creating the
356 ;;      list of files to index, or when creating the list of files and
357 ;;      the corresponding cscope database.
358 ;;
359 ;; "cscope-name-line-width"
360 ;;      The width of the combined "function name:line number" field in
361 ;;      the cscope results buffer.  If negative, the field is
362 ;;      left-justified.
363 ;;
364 ;; "cscope-do-not-update-database"
365 ;;      If non-nil, never check and/or update the cscope database when
366 ;;      searching.  Beware of setting this to non-nil, as this will
367 ;;      disable automatic database creation, updating, and
368 ;;      maintenance.
369 ;;
370 ;; "cscope-display-cscope-buffer" 
371 ;;      If non-nil, display the *cscope* buffer after each search
372 ;;      (default).  This variable can be set in order to reduce the
373 ;;      number of keystrokes required to navigate through the matches.
374 ;;
375 ;; "cscope-database-regexps"
376 ;;      List to force directory-to-cscope-database mappings.
377 ;;      This is a list of `(REGEXP DBLIST [ DBLIST ... ])', where:
378 ;;
379 ;;      REGEXP is a regular expression matched against the current buffer's
380 ;;      current directory.  The current buffer is typically some source file,
381 ;;      and you're probably searching for some symbol in or related to this
382 ;;      file.  Basically, this regexp is used to relate the current directory
383 ;;      to a cscope database.  You need to start REGEXP with "^" if you want
384 ;;      to match from the beginning of the current directory.
385 ;;
386 ;;      DBLIST is a list that contains one or more of:
387 ;;
388 ;;          ( DBDIR )
389 ;;          ( DBDIR ( OPTIONS ) )
390 ;;          ( t )
391 ;;          t
392 ;;
393 ;;      Here, DBDIR is a directory (or a file) that contains a cscope
394 ;;      database.  If DBDIR is a directory, then it is expected that the
395 ;;      cscope database, if present, has the filename given by the variable,
396 ;;      `cscope-database-file'; if DBDIR is a file, then DBDIR is the path
397 ;;      name to a cscope database file (which does not have to be the same as
398 ;;      that given by `cscope-database-file').  If only DBDIR is specified,
399 ;;      then that cscope database will be searched without any additional
400 ;;      cscope command-line options.  If OPTIONS is given, then OPTIONS is a
401 ;;      list of strings, where each string is a separate cscope command-line
402 ;;      option.
403 ;;
404 ;;      In the case of "( t )", this specifies that the search is to use the
405 ;;      normal hierarchical database search.  This option is used to
406 ;;      explicitly search using the hierarchical database search either before
407 ;;      or after other cscope database directories.
408 ;;
409 ;;      If "t" is specified (not inside a list), this tells the searching
410 ;;      mechanism to stop searching if a match has been found (at the point
411 ;;      where "t" is encountered).  This is useful for those projects that
412 ;;      consist of many subprojects.  You can specify the most-used
413 ;;      subprojects first, followed by a "t", and then followed by a master
414 ;;      cscope database directory that covers all subprojects.  This will
415 ;;      cause the most-used subprojects to be searched first (hopefully
416 ;;      quickly), and the search will then stop if a match was found.  If not,
417 ;;      the search will continue using the master cscope database directory.
418 ;;
419 ;;      Here, `cscope-database-regexps' is generally not used, as the normal
420 ;;      hierarchical database search is sufficient for placing and/or locating
421 ;;      the cscope databases.  However, there may be cases where it makes
422 ;;      sense to place the cscope databases away from where the source files
423 ;;      are kept; in this case, this variable is used to determine the
424 ;;      mapping.
425 ;;
426 ;;      This module searches for the cscope databases by first using this
427 ;;      variable; if a database location cannot be found using this variable,
428 ;;      then the current directory is searched, then the parent, then the
429 ;;      parent's parent, until a cscope database directory is found, or the
430 ;;      root directory is reached.  If the root directory is reached, the
431 ;;      current directory will be used.
432 ;;
433 ;;      A cscope database directory is one in which EITHER a cscope database
434 ;;      file (e.g., "cscope.out") OR a cscope file list (e.g.,
435 ;;      "cscope.files") exists.  If only "cscope.files" exists, the
436 ;;      corresponding "cscope.out" will be automatically created by cscope
437 ;;      when a search is done.  By default, the cscope database file is called
438 ;;      "cscope.out", but this can be changed (on a global basis) via the
439 ;;      variable, `cscope-database-file'.  There is limited support for cscope
440 ;;      databases that are named differently than that given by
441 ;;      `cscope-database-file', using the variable, `cscope-database-regexps'.
442 ;;
443 ;;      Here is an example of `cscope-database-regexps':
444 ;;
445 ;;              (setq cscope-database-regexps
446 ;;                    '(
447 ;;                      ( "^/users/jdoe/sources/proj1"
448 ;;                        ( t )
449 ;;                        ( "/users/jdoe/sources/proj2")
450 ;;                        ( "/users/jdoe/sources/proj3/mycscope.out")
451 ;;                        ( "/users/jdoe/sources/proj4")
452 ;;                        t
453 ;;                        ( "/some/master/directory" ("-d" "-I/usr/local/include") )
454 ;;                        )
455 ;;                      ( "^/users/jdoe/sources/gnome/"
456 ;;                        ( "/master/gnome/database" ("-d") )
457 ;;                        )
458 ;;                      ))
459 ;;
460 ;;      If the current buffer's directory matches the regexp,
461 ;;      "^/users/jdoe/sources/proj1", then the following search will be
462 ;;      done:
463 ;;
464 ;;          1. First, the normal hierarchical database search will be used to
465 ;;             locate a cscope database.
466 ;;
467 ;;          2. Next, searches will be done using the cscope database
468 ;;             directories, "/users/jdoe/sources/proj2",
469 ;;             "/users/jdoe/sources/proj3/mycscope.out", and
470 ;;             "/users/jdoe/sources/proj4".  Note that, instead of the file,
471 ;;             "cscope.out", the file, "mycscope.out", will be used in the
472 ;;             directory "/users/jdoe/sources/proj3".
473 ;;
474 ;;          3. If a match was found, searching will stop.
475 ;;
476 ;;          4. If a match was not found, searching will be done using
477 ;;             "/some/master/directory", and the command-line options "-d"
478 ;;             and "-I/usr/local/include" will be passed to cscope.
479 ;;
480 ;;      If the current buffer's directory matches the regexp,
481 ;;      "^/users/jdoe/sources/gnome", then the following search will be
482 ;;      done:
483 ;;
484 ;;          The search will be done only using the directory,
485 ;;          "/master/gnome/database".  The "-d" option will be passed to
486 ;;          cscope.
487 ;;
488 ;;      If the current buffer's directory does not match any of the above
489 ;;      regexps, then only the normal hierarchical database search will be
490 ;;      done.
491 ;;
492 ;;
493 ;; * Other notes:
494 ;;
495 ;; 1. The script, "cscope-indexer", uses a sed command to determine
496 ;;    what is and is not a C/C++/lex/yacc source file.  It's idea of a
497 ;;    source file may not correspond to yours.
498 ;;
499 ;; 2. This module is called, "xcscope", because someone else has
500 ;;    already written a "cscope.el" (although it's quite old).
501 ;;
502 ;;
503 ;; * KNOWN BUGS:
504 ;;
505 ;; 1. Cannot handle whitespace in directory or file names.
506 ;;
507 ;; 2. By default, colored faces are used to display results.  If you happen
508 ;;    to use a black background, part of the results may be invisible
509 ;;    (because the foreground color may be black, too).  There are at least
510 ;;    two solutions for this:
511 ;;
512 ;;    2a. Turn off colored faces, by setting `cscope-use-face' to `nil',
513 ;;        e.g.:
514 ;;
515 ;;            (setq cscope-use-face nil)
516 ;;
517 ;;    2b. Explicitly set colors for the faces used by cscope.  The faces
518 ;;        are:
519 ;;
520 ;;            cscope-file-face
521 ;;            cscope-function-face
522 ;;            cscope-line-number-face
523 ;;            cscope-line-face
524 ;;            cscope-mouse-face
525 ;;
526 ;;        The face most likely to cause problems (e.g., black-on-black
527 ;;        color) is `cscope-line-face'.
528 ;;
529 ;; 3. The support for cscope databases different from that specified by
530 ;;    `cscope-database-file' is quirky.  If the file does not exist, it
531 ;;    will not be auto-created (unlike files names by
532 ;;    `cscope-database-file').  You can manually force the file to be
533 ;;    created by using touch(1) to create a zero-length file; the
534 ;;    database will be created the next time a search is done.
535 ;;
536 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
537
538 (require 'easymenu)
539
540
541 (defgroup cscope nil
542   "Cscope interface for (X)Emacs.
543 Using cscope, you can easily search for where symbols are used and defined.
544 It is designed to answer questions like:
545
546         Where is this variable used?
547         What is the value of this preprocessor symbol?
548         Where is this function in the source files?
549         What functions call this function?
550         What functions are called by this function?
551         Where does the message \"out of space\" come from?
552         Where is this source file in the directory structure?
553         What files include this header file?
554 "
555   :prefix "cscope-"
556   :group 'tools)
557
558
559 (defcustom cscope-do-not-update-database nil
560   "*If non-nil, never check and/or update the cscope database when searching.
561 Beware of setting this to non-nil, as this will disable automatic database
562 creation, updating, and maintenance."
563   :type 'boolean
564   :group 'cscope)
565
566
567 (defcustom cscope-database-regexps nil
568   "*List to force directory-to-cscope-database mappings.
569 This is a list of `(REGEXP DBLIST [ DBLIST ... ])', where:
570
571 REGEXP is a regular expression matched against the current buffer's
572 current directory.  The current buffer is typically some source file,
573 and you're probably searching for some symbol in or related to this
574 file.  Basically, this regexp is used to relate the current directory
575 to a cscope database.  You need to start REGEXP with \"^\" if you want
576 to match from the beginning of the current directory.
577
578 DBLIST is a list that contains one or more of:
579
580     ( DBDIR )
581     ( DBDIR ( OPTIONS ) )
582     ( t )
583     t
584
585 Here, DBDIR is a directory (or a file) that contains a cscope database.
586 If DBDIR is a directory, then it is expected that the cscope database,
587 if present, has the filename given by the variable,
588 `cscope-database-file'; if DBDIR is a file, then DBDIR is the path name
589 to a cscope database file (which does not have to be the same as that
590 given by `cscope-database-file').  If only DBDIR is specified, then that
591 cscope database will be searched without any additional cscope
592 command-line options.  If OPTIONS is given, then OPTIONS is a list of
593 strings, where each string is a separate cscope command-line option.
594
595 In the case of \"( t )\", this specifies that the search is to use the
596 normal hierarchical database search.  This option is used to
597 explicitly search using the hierarchical database search either before
598 or after other cscope database directories.
599
600 If \"t\" is specified (not inside a list), this tells the searching
601 mechanism to stop searching if a match has been found (at the point
602 where \"t\" is encountered).  This is useful for those projects that
603 consist of many subprojects.  You can specify the most-used
604 subprojects first, followed by a \"t\", and then followed by a master
605 cscope database directory that covers all subprojects.  This will
606 cause the most-used subprojects to be searched first (hopefully
607 quickly), and the search will then stop if a match was found.  If not,
608 the search will continue using the master cscope database directory.
609
610 Here, `cscope-database-regexps' is generally not used, as the normal
611 hierarchical database search is sufficient for placing and/or locating
612 the cscope databases.  However, there may be cases where it makes
613 sense to place the cscope databases away from where the source files
614 are kept; in this case, this variable is used to determine the
615 mapping.
616
617 This module searches for the cscope databases by first using this
618 variable; if a database location cannot be found using this variable,
619 then the current directory is searched, then the parent, then the
620 parent's parent, until a cscope database directory is found, or the
621 root directory is reached.  If the root directory is reached, the
622 current directory will be used.
623
624 A cscope database directory is one in which EITHER a cscope database
625 file (e.g., \"cscope.out\") OR a cscope file list (e.g.,
626 \"cscope.files\") exists.  If only \"cscope.files\" exists, the
627 corresponding \"cscope.out\" will be automatically created by cscope
628 when a search is done.  By default, the cscope database file is called
629 \"cscope.out\", but this can be changed (on a global basis) via the
630 variable, `cscope-database-file'.  There is limited support for cscope
631 databases that are named differently than that given by
632 `cscope-database-file', using the variable, `cscope-database-regexps'.
633
634 Here is an example of `cscope-database-regexps':
635
636         (setq cscope-database-regexps
637               '(
638                 ( \"^/users/jdoe/sources/proj1\"
639                   ( t )
640                   ( \"/users/jdoe/sources/proj2\")
641                   ( \"/users/jdoe/sources/proj3/mycscope.out\")
642                   ( \"/users/jdoe/sources/proj4\")
643                   t
644                   ( \"/some/master/directory\" (\"-d\" \"-I/usr/local/include\") )
645                   )
646                 ( \"^/users/jdoe/sources/gnome/\"
647                   ( \"/master/gnome/database\" (\"-d\") )
648                   )
649                 ))
650
651 If the current buffer's directory matches the regexp,
652 \"^/users/jdoe/sources/proj1\", then the following search will be
653 done:
654
655     1. First, the normal hierarchical database search will be used to
656        locate a cscope database.
657
658     2. Next, searches will be done using the cscope database
659        directories, \"/users/jdoe/sources/proj2\",
660        \"/users/jdoe/sources/proj3/mycscope.out\", and
661        \"/users/jdoe/sources/proj4\".  Note that, instead of the file,
662        \"cscope.out\", the file, \"mycscope.out\", will be used in the
663        directory \"/users/jdoe/sources/proj3\".
664
665     3. If a match was found, searching will stop.
666
667     4. If a match was not found, searching will be done using
668        \"/some/master/directory\", and the command-line options \"-d\"
669        and \"-I/usr/local/include\" will be passed to cscope.
670
671 If the current buffer's directory matches the regexp,
672 \"^/users/jdoe/sources/gnome\", then the following search will be
673 done:
674
675     The search will be done only using the directory,
676     \"/master/gnome/database\".  The \"-d\" option will be passed to
677     cscope.
678
679 If the current buffer's directory does not match any of the above
680 regexps, then only the normal hierarchical database search will be
681 done.
682
683 "
684   :type '(repeat (list :format "%v"
685                        (choice :value ""
686                                (regexp :tag "Buffer regexp")
687                                string)
688                        (choice :value ""
689                                (directory :tag "Cscope database directory")
690                                string)
691                        (string :value ""
692                                :tag "Optional cscope command-line arguments")
693                        ))
694   :group 'cscope)
695 (defcustom cscope-name-line-width -30
696   "*The width of the combined \"function name:line number\" field in the
697 cscope results buffer.  If negative, the field is left-justified."
698   :type 'integer
699   :group 'cscope)
700
701
702 (defcustom cscope-truncate-lines truncate-lines
703   "*The value of `truncate-lines' to use in cscope buffers.
704 This variable exists because it can be easier to read cscope buffers
705 with truncated lines, while other buffers do not have truncated lines."
706   :type 'boolean
707   :group 'cscope)
708
709
710 (defcustom cscope-display-times t
711   "*If non-nil, display how long each search took.
712 The elasped times are in seconds.  Floating-point support is required
713 for this to work."
714   :type 'boolean
715   :group 'cscope)
716
717
718 (defcustom cscope-program "cscope"
719   "*The pathname of the cscope executable to use."
720   :type 'string
721   :group 'cscope)
722
723
724 (defcustom cscope-index-file "cscope.files"
725   "*The name of the cscope file list file."
726   :type 'string
727   :group 'cscope)
728
729
730 (defcustom cscope-database-file "cscope.out"
731   "*The name of the cscope database file."
732   :type 'string
733   :group 'cscope)
734
735
736 (defcustom cscope-edit-single-match t
737   "*If non-nil and only one match is output, edit the matched location."
738   :type 'boolean
739   :group 'cscope)
740
741
742 (defcustom cscope-display-cscope-buffer t
743   "*If non-nil automatically display the *cscope* buffer after each search."
744   :type 'boolean
745   :group 'cscope)
746
747
748 (defcustom cscope-stop-at-first-match-dir nil
749   "*If non-nil, stop searching through multiple databases if a match is found.
750 This option is useful only if multiple cscope database directories are being
751 used.  When multiple databases are searched, setting this variable to non-nil
752 will cause searches to stop when a search outputs anything; no databases after
753 this one will be searched."
754   :type 'boolean
755   :group 'cscope)
756
757
758 (defcustom cscope-use-relative-paths t
759   "*If non-nil, use relative paths when creating the list of files to index.
760 The path is relative to the directory in which the cscope database
761 will be created.  If nil, absolute paths will be used.  Absolute paths
762 are good if you plan on moving the database to some other directory
763 (if you do so, you'll probably also have to modify
764 \`cscope-database-regexps\').  Absolute paths  may also be good if you
765 share the database file with other users (you\'ll probably want to
766 specify some automounted network path for this)."
767   :type 'boolean
768   :group 'cscope)
769
770
771 (defcustom cscope-index-recursively t
772   "*If non-nil, index files in the current directory and all subdirectories.
773 If nil, only files in the current directory are indexed.  This
774 variable is only used when creating the list of files to index, or
775 when creating the list of files and the corresponding cscope database."
776   :type 'boolean
777   :group 'cscope)
778
779
780 (defcustom cscope-no-mouse-prompts nil
781   "*If non-nil, use the symbol under the cursor instead of prompting.
782 Do not prompt for a value, except for when seaching for a egrep pattern
783 or a file."
784   :type 'boolean
785   :group 'cscope)
786
787
788 (defcustom cscope-suppress-empty-matches t
789   "*If non-nil, delete empty matches.")
790
791
792 (defcustom cscope-indexing-script "cscope-indexer"
793   "*The shell script used to create cscope indices."
794   :type 'string
795   :group 'cscope)
796
797
798 (defcustom cscope-symbol-chars "A-Za-z0-9_"
799   "*A string containing legal characters in a symbol.
800 The current syntax table should really be used for this."
801   :type 'string
802   :group 'cscope)
803
804
805 (defcustom cscope-filename-chars "-.,/A-Za-z0-9_~!@#$%&+=\\\\"
806   "*A string containing legal characters in a symbol.
807 The current syntax table should really be used for this."
808   :type 'string
809   :group 'cscope)
810
811
812 (defcustom cscope-allow-arrow-overlays t
813   "*If non-nil, use an arrow overlay to show target lines.
814 Arrow overlays are only used when the following functions are used:
815
816     cscope-show-entry-other-window
817     cscope-show-next-entry-other-window
818     cscope-show-prev-entry-other-window
819
820 The arrow overlay is removed when other cscope functions are used.
821 Note that the arrow overlay is not an actual part of the text, and can
822 be removed by quitting the cscope buffer."
823   :type 'boolean
824   :group 'cscope)
825
826
827 (defcustom cscope-overlay-arrow-string "=>"
828   "*The overlay string to use when displaying arrow overlays."
829   :type 'string
830   :group 'cscope)
831
832
833 (defvar cscope-minor-mode-hooks nil
834   "List of hooks to call when entering cscope-minor-mode.")
835
836
837 (defconst cscope-separator-line
838   "-------------------------------------------------------------------------------\n"
839   "Line of text to use as a visual separator.
840 Must end with a newline.")
841
842
843 ;;;;
844 ;;;; Faces for fontification
845 ;;;;
846
847 (defcustom cscope-use-face t
848   "*Whether to use text highlighting (à la font-lock) or not."
849   :group 'cscope
850   :type '(boolean))
851
852
853 (defface cscope-file-face
854   '((((class color) (background dark))
855      (:foreground "yellow"))
856     (((class color) (background light))
857      (:foreground "blue"))
858     (t (:bold t)))
859   "Face used to highlight file name in the *cscope* buffer."
860   :group 'cscope)
861
862
863 (defface cscope-function-face
864   '((((class color) (background dark))
865      (:foreground "cyan"))
866     (((class color) (background light))
867      (:foreground "magenta"))
868     (t (:bold t)))
869   "Face used to highlight function name in the *cscope* buffer."
870   :group 'cscope)
871
872
873 (defface cscope-line-number-face
874   '((((class color) (background dark))
875      (:foreground "red"))
876     (((class color) (background light))
877      (:foreground "red"))
878     (t (:bold t)))
879   "Face used to highlight line number in the *cscope* buffer."
880   :group 'cscope)
881
882
883 (defface cscope-line-face
884   '((((class color) (background dark))
885      (:foreground "green"))
886     (((class color) (background light))
887      (:foreground "black"))
888     (t (:bold nil)))
889   "Face used to highlight the rest of line in the *cscope* buffer."
890   :group 'cscope)
891
892
893 (defface cscope-mouse-face
894   '((((class color) (background dark))
895      (:foreground "white" :background "blue"))
896     (((class color) (background light))
897      (:foreground "white" :background "blue"))
898     (t (:bold nil)))
899   "Face used when mouse pointer is within the region of an entry."
900   :group 'cscope)
901
902 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
903 ;; Probably, nothing user-customizable past this point.
904 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
905 (defconst cscope-running-in-xemacs (string-match "XEmacs\\|Lucid" emacs-version))
906
907 (defvar cscope-list-entry-keymap nil
908   "The keymap used in the *cscope* buffer which lists search results.")
909 (if cscope-list-entry-keymap
910     nil
911   (setq cscope-list-entry-keymap (make-keymap))
912   (suppress-keymap cscope-list-entry-keymap)
913   ;; The following section does not appear in the "Cscope" menu.
914   (if cscope-running-in-xemacs
915       (define-key cscope-list-entry-keymap [button2] 'cscope-mouse-select-entry-other-window)
916     (define-key cscope-list-entry-keymap [mouse-2] 'cscope-mouse-select-entry-other-window))
917   (define-key cscope-list-entry-keymap [return] 'cscope-select-entry-other-window)
918   (define-key cscope-list-entry-keymap " " 'cscope-show-entry-other-window)
919   (define-key cscope-list-entry-keymap "o" 'cscope-select-entry-one-window)
920   (define-key cscope-list-entry-keymap "q" 'cscope-bury-buffer)
921   (define-key cscope-list-entry-keymap "Q" 'cscope-quit)
922   (define-key cscope-list-entry-keymap "h" 'cscope-help)
923   (define-key cscope-list-entry-keymap "?" 'cscope-help)
924   ;; The following line corresponds to be beginning of the "Cscope" menu.
925   (define-key cscope-list-entry-keymap "s" 'cscope-find-this-symbol)
926   (define-key cscope-list-entry-keymap "d" 'cscope-find-this-symbol)
927   (define-key cscope-list-entry-keymap "g" 'cscope-find-global-definition)
928   (define-key cscope-list-entry-keymap "G"
929     'cscope-find-global-definition-no-prompting)
930   (define-key cscope-list-entry-keymap "c" 'cscope-find-functions-calling-this-function)
931   (define-key cscope-list-entry-keymap "C" 'cscope-find-called-functions)
932   (define-key cscope-list-entry-keymap "t" 'cscope-find-this-text-string)
933   (define-key cscope-list-entry-keymap "e" 'cscope-find-egrep-pattern)
934   (define-key cscope-list-entry-keymap "f" 'cscope-find-this-file)
935   (define-key cscope-list-entry-keymap "i" 'cscope-find-files-including-file)
936   ;; --- (The '---' indicates that this line corresponds to a menu separator.)
937   (define-key cscope-list-entry-keymap "n" 'cscope-next-symbol)
938   (define-key cscope-list-entry-keymap "N" 'cscope-next-file)
939   (define-key cscope-list-entry-keymap "p" 'cscope-prev-symbol)
940   (define-key cscope-list-entry-keymap "P" 'cscope-prev-file)
941   (define-key cscope-list-entry-keymap "u" 'cscope-pop-mark)
942   ;; ---
943   (define-key cscope-list-entry-keymap "a" 'cscope-set-initial-directory)
944   (define-key cscope-list-entry-keymap "A" 'cscope-unset-initial-directory)
945   ;; ---
946   (define-key cscope-list-entry-keymap "L" 'cscope-create-list-of-files-to-index)
947   (define-key cscope-list-entry-keymap "I" 'cscope-index-files)
948   (define-key cscope-list-entry-keymap "E" 'cscope-edit-list-of-files-to-index)
949   (define-key cscope-list-entry-keymap "W" 'cscope-tell-user-about-directory)
950   (define-key cscope-list-entry-keymap "S" 'cscope-tell-user-about-directory)
951   (define-key cscope-list-entry-keymap "T" 'cscope-tell-user-about-directory)
952   (define-key cscope-list-entry-keymap "D" 'cscope-dired-directory)
953   ;; The previous line corresponds to be end of the "Cscope" menu.
954   )
955
956
957 (defvar cscope-list-entry-hook nil
958   "*Hook run after cscope-list-entry-mode entered.")
959
960
961 (defun cscope-list-entry-mode ()
962   "Major mode for jumping/showing entry from the list in the *cscope* buffer.
963
964 \\{cscope-list-entry-keymap}"
965   (use-local-map cscope-list-entry-keymap)
966   (setq buffer-read-only t
967         mode-name "cscope"
968         major-mode 'cscope-list-entry-mode
969         overlay-arrow-string cscope-overlay-arrow-string)
970   (or overlay-arrow-position
971       (setq overlay-arrow-position (make-marker)))
972   (run-hooks 'cscope-list-entry-hook))
973
974 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
975
976 (defvar cscope-output-buffer-name "*cscope*"
977   "The name of the cscope output buffer.")
978
979
980 (defvar cscope-info-buffer-name "*cscope-info*"
981   "The name of the cscope information buffer.")
982
983
984 (defvar cscope-process nil
985   "The current cscope process.")
986 (make-variable-buffer-local 'cscope-process)
987
988
989 (defvar cscope-process-output nil
990   "A buffer for holding partial cscope process output.")
991 (make-variable-buffer-local 'cscope-process-output)
992
993
994 (defvar cscope-command-args nil
995   "Internal variable for holding major command args to pass to cscope.")
996 (make-variable-buffer-local 'cscope-command-args)
997
998
999 (defvar cscope-start-directory nil
1000   "Internal variable used to save the initial start directory.
1001 The results buffer gets reset to this directory when a search has
1002 completely finished.")
1003 (make-variable-buffer-local 'cscope-start-directory)
1004
1005
1006 (defvar cscope-search-list nil
1007   "A list of (DIR . FLAGS) entries.
1008 This is a list of database directories to search.  Each entry in the list
1009 is a (DIR . FLAGS) cell.  DIR is the directory to search, and FLAGS are the
1010 flags to pass to cscope when using this database directory.  FLAGS can be
1011 nil (meaning, \"no flags\").")
1012 (make-variable-buffer-local 'cscope-search-list)
1013
1014
1015 (defvar cscope-searched-dirs nil
1016   "The list of database directories already searched.")
1017 (make-variable-buffer-local 'cscope-searched-dirs)
1018
1019
1020 (defvar cscope-filter-func nil
1021   "Internal variable for holding the filter function to use (if any) when
1022 searching.")
1023 (make-variable-buffer-local 'cscope-filter-func)
1024
1025
1026 (defvar cscope-sentinel-func nil
1027   "Internal variable for holding the sentinel function to use (if any) when
1028 searching.")
1029 (make-variable-buffer-local 'cscope-filter-func)
1030
1031
1032 (defvar cscope-last-file nil
1033   "The file referenced by the last line of cscope process output.")
1034 (make-variable-buffer-local 'cscope-last-file)
1035
1036
1037 (defvar cscope-start-time nil
1038   "The search start time, in seconds.")
1039 (make-variable-buffer-local 'cscope-start-time)
1040
1041
1042 (defvar cscope-first-match nil
1043   "The first match result output by cscope.")
1044 (make-variable-buffer-local 'cscope-first-match)
1045
1046
1047 (defvar cscope-first-match-point nil
1048   "Buffer location of the first match.")
1049 (make-variable-buffer-local 'cscope-first-match-point)
1050
1051
1052 (defvar cscope-item-start nil
1053   "The point location of the start of a search's output, before header info.")
1054 (make-variable-buffer-local 'cscope-output-start)
1055
1056
1057 (defvar cscope-output-start nil
1058   "The point location of the start of a search's output.")
1059 (make-variable-buffer-local 'cscope-output-start)
1060
1061
1062 (defvar cscope-matched-multiple nil
1063   "Non-nil if cscope output multiple matches.")
1064 (make-variable-buffer-local 'cscope-matched-multiple)
1065
1066
1067 (defvar cscope-stop-at-first-match-dir-meta nil
1068   "")
1069 (make-variable-buffer-local 'cscope-stop-at-first-match-dir-meta)
1070
1071
1072 (defvar cscope-symbol nil
1073   "The last symbol searched for.")
1074
1075
1076 (defvar cscope-adjust t
1077   "True if the symbol searched for (cscope-symbol) should be on
1078 the line specified by the cscope database.  In such cases the point will be
1079 adjusted if need be (fuzzy matching).")
1080
1081
1082 (defvar cscope-adjust-range 1000
1083   "How far the point should be adjusted if the symbol is not on the line
1084 specified by the cscope database.")
1085
1086
1087 (defvar cscope-marker nil
1088   "The location from which cscope was invoked.")
1089
1090
1091 (defvar cscope-marker-window nil
1092   "The window which should contain cscope-marker.  This is the window from
1093 which cscope-marker is set when searches are launched from the *cscope*
1094 buffer.")
1095
1096
1097 (defvar cscope-marker-ring-length 16
1098   "Length of the cscope marker ring.")
1099
1100
1101 (defvar cscope-marker-ring (make-ring cscope-marker-ring-length)
1102   "Ring of markers which are locations from which cscope was invoked.")
1103
1104
1105 (defvar cscope-initial-directory nil
1106   "When set the directory in which searches for the cscope database
1107 directory should begin.")
1108
1109
1110 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1111
1112 (defvar cscope:map nil
1113   "The cscope keymap.")
1114 (if cscope:map
1115     nil
1116   (setq cscope:map (make-sparse-keymap))
1117   ;; The following line corresponds to be beginning of the "Cscope" menu.
1118   (define-key cscope:map "\C-css" 'cscope-find-this-symbol)
1119   (define-key cscope:map "\C-csd" 'cscope-find-global-definition)
1120   (define-key cscope:map "\C-csg" 'cscope-find-global-definition)
1121   (define-key cscope:map "\C-csG" 'cscope-find-global-definition-no-prompting)
1122   (define-key cscope:map "\C-csc" 'cscope-find-functions-calling-this-function)
1123   (define-key cscope:map "\C-csC" 'cscope-find-called-functions)
1124   (define-key cscope:map "\C-cst" 'cscope-find-this-text-string)
1125   (define-key cscope:map "\C-cse" 'cscope-find-egrep-pattern)
1126   (define-key cscope:map "\C-csf" 'cscope-find-this-file)
1127   (define-key cscope:map "\C-csi" 'cscope-find-files-including-file)
1128   ;; --- (The '---' indicates that this line corresponds to a menu separator.)
1129   (define-key cscope:map "\C-csb" 'cscope-display-buffer)
1130   (define-key cscope:map "\C-csB" 'cscope-display-buffer-toggle)
1131   (define-key cscope:map "\C-csn" 'cscope-next-symbol)
1132   (define-key cscope:map "\C-csN" 'cscope-next-file)
1133   (define-key cscope:map "\C-csp" 'cscope-prev-symbol)
1134   (define-key cscope:map "\C-csP" 'cscope-prev-file)
1135   (define-key cscope:map "\C-csu" 'cscope-pop-mark)
1136   ;; ---
1137   (define-key cscope:map "\C-csa" 'cscope-set-initial-directory)
1138   (define-key cscope:map "\C-csA" 'cscope-unset-initial-directory)
1139   ;; ---
1140   (define-key cscope:map "\C-csL" 'cscope-create-list-of-files-to-index)
1141   (define-key cscope:map "\C-csI" 'cscope-index-files)
1142   (define-key cscope:map "\C-csE" 'cscope-edit-list-of-files-to-index)
1143   (define-key cscope:map "\C-csW" 'cscope-tell-user-about-directory)
1144   (define-key cscope:map "\C-csS" 'cscope-tell-user-about-directory)
1145   (define-key cscope:map "\C-csT" 'cscope-tell-user-about-directory)
1146   (define-key cscope:map "\C-csD" 'cscope-dired-directory))
1147   ;; The previous line corresponds to be end of the "Cscope" menu.
1148
1149 (easy-menu-define cscope:menu
1150                   (list cscope:map cscope-list-entry-keymap)
1151                   "cscope menu"
1152                   '("Cscope"
1153                     [ "Find symbol" cscope-find-this-symbol t ]
1154                     [ "Find global definition" cscope-find-global-definition t ]
1155                     [ "Find global definition no prompting"
1156                       cscope-find-global-definition-no-prompting t ]
1157                     [ "Find functions calling a function"
1158                       cscope-find-functions-calling-this-function t ]
1159                     [ "Find called functions" cscope-find-called-functions t ]
1160                     [ "Find text string" cscope-find-this-text-string t ]
1161                     [ "Find egrep pattern" cscope-find-egrep-pattern t ]
1162                     [ "Find a file" cscope-find-this-file t ]
1163                     [ "Find files #including a file"
1164                       cscope-find-files-including-file t ]
1165                     "-----------"
1166                     [ "Display *cscope* buffer" cscope-display-buffer t ]
1167                     [ "Auto display *cscope* buffer toggle"
1168                       cscope-display-buffer-toggle t ]
1169                     [ "Next symbol"             cscope-next-symbol t ]
1170                     [ "Next file"               cscope-next-file t ]
1171                     [ "Previous symbol"         cscope-prev-symbol t ]
1172                     [ "Previous file"           cscope-prev-file t ]
1173                     [ "Pop mark"                cscope-pop-mark t ]
1174                     "-----------"
1175                     ( "Cscope Database"
1176                       [ "Set initial directory"
1177                         cscope-set-initial-directory t ]
1178                       [ "Unset initial directory"
1179                         cscope-unset-initial-directory t ]
1180                       "-----------"
1181                       [ "Create list of files to index"
1182                         cscope-create-list-of-files-to-index t ]
1183                       [ "Create list and index"
1184                         cscope-index-files t ]
1185                       [ "Edit list of files to index"
1186                         cscope-edit-list-of-files-to-index t ]
1187                       [ "Locate this buffer's cscope directory"
1188                         cscope-tell-user-about-directory t ]
1189                       [ "Dired this buffer's cscope directory"
1190                         cscope-dired-directory t ]
1191                       )
1192                     "-----------"
1193                     ( "Options"
1194                       [ "Auto edit single match"
1195                         (setq cscope-edit-single-match
1196                               (not cscope-edit-single-match))
1197                         :style toggle :selected cscope-edit-single-match ]
1198                       [ "Auto display *cscope* buffer"
1199                         (setq cscope-display-cscope-buffer
1200                               (not cscope-display-cscope-buffer))
1201                         :style toggle :selected cscope-display-cscope-buffer ]
1202                       [ "Stop at first matching database"
1203                         (setq cscope-stop-at-first-match-dir
1204                               (not cscope-stop-at-first-match-dir))
1205                         :style toggle
1206                         :selected cscope-stop-at-first-match-dir ]
1207                       [ "Never update cscope database"
1208                         (setq cscope-do-not-update-database
1209                               (not cscope-do-not-update-database))
1210                         :style toggle :selected cscope-do-not-update-database ]
1211                       [ "Index recursively"
1212                         (setq cscope-index-recursively
1213                               (not cscope-index-recursively))
1214                         :style toggle :selected cscope-index-recursively ]
1215                       [ "Suppress empty matches"
1216                         (setq cscope-suppress-empty-matches
1217                               (not cscope-suppress-empty-matches))
1218                         :style toggle :selected cscope-suppress-empty-matches ]
1219                       [ "Use relative paths"
1220                         (setq cscope-use-relative-paths
1221                               (not cscope-use-relative-paths))
1222                         :style toggle :selected cscope-use-relative-paths ]
1223                       [ "No mouse prompts" (setq cscope-no-mouse-prompts
1224                                                  (not cscope-no-mouse-prompts))
1225                         :style toggle :selected cscope-no-mouse-prompts ] 
1226                       )
1227                     ))
1228
1229 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1230 ;; Internal functions and variables
1231 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1232
1233 (defvar cscope-common-text-plist
1234   (let (plist)
1235     (setq plist (plist-put plist 'mouse-face 'cscope-mouse-face))
1236     plist)
1237   "List of common text properties to be added to the entry line.")
1238
1239
1240 (defun cscope-insert-with-text-properties (text filename &optional line-number)
1241   "Insert an entry with given TEXT, add entry attributes as text properties.
1242 The text properties to be added:
1243 - common property: mouse-face,
1244 - properties are used to open target file and its location: cscope-file,
1245   cscope-line-number"
1246   (let ((plist cscope-common-text-plist)
1247         beg end)
1248     (setq beg (point))
1249     (insert text)
1250     (setq end (point)
1251           plist (plist-put plist 'cscope-file filename))
1252     (if line-number
1253         (progn
1254           (if (stringp line-number)
1255               (setq line-number (string-to-number line-number)))
1256           (setq plist (plist-put plist 'cscope-line-number line-number))
1257           ))
1258     (add-text-properties beg end plist)
1259     ))
1260
1261
1262 (if cscope-running-in-xemacs
1263     (progn
1264       (defalias 'cscope-event-window 'event-window)
1265       (defalias 'cscope-event-point 'event-point)
1266       (defalias 'cscope-recenter 'recenter)
1267       )
1268   (defun cscope-event-window (event)
1269     "Return the window at which the mouse EVENT occurred."
1270     (posn-window (event-start event)))
1271   (defun cscope-event-point (event)
1272     "Return the point at which the mouse EVENT occurred."
1273     (posn-point (event-start event)))
1274   (defun cscope-recenter (&optional n window)
1275     "Center point in WINDOW and redisplay frame.  With N, put point on line N."
1276     (save-selected-window
1277       (if (windowp window)
1278           (select-window window))
1279       (recenter n)))
1280   )
1281
1282
1283 (defun cscope-show-entry-internal (file line-number 
1284                                         &optional save-mark-p window arrow-p)
1285   "Display the buffer corresponding to FILE and LINE-NUMBER
1286 in some window.  If optional argument WINDOW is given,
1287 display the buffer in that WINDOW instead.  The window is
1288 not selected.  Save point on mark ring before goto
1289 LINE-NUMBER if optional argument SAVE-MARK-P is non-nil.
1290 Put `overlay-arrow-string' if arrow-p is non-nil.
1291 Returns the window displaying BUFFER."
1292   (let (buffer old-pos old-point new-point forward-point backward-point
1293                line-end line-length)
1294     (if (and (stringp file)
1295              (integerp line-number))
1296         (progn
1297           (unless (file-readable-p file)
1298             (error "%s is not readable or exists" file))
1299           (setq buffer (find-file-noselect file))
1300           (if (windowp window)
1301               (set-window-buffer window buffer)
1302             (setq window (display-buffer buffer)))
1303           (set-buffer buffer)
1304           (if (> line-number 0)
1305               (progn
1306                 (setq old-pos (point))
1307                 (goto-line line-number)
1308                 (setq old-point (point))
1309                 (if (and cscope-adjust cscope-adjust-range)
1310                     (progn
1311                       ;; Calculate the length of the line specified by cscope.
1312                       (end-of-line)
1313                       (setq line-end (point))
1314                       (goto-char old-point)
1315                       (setq line-length (- line-end old-point))
1316
1317                       ;; Search forward and backward for the pattern.
1318                       (setq forward-point (search-forward
1319                                            cscope-symbol
1320                                            (+ old-point
1321                                               cscope-adjust-range) t))
1322                       (goto-char old-point)
1323                       (setq backward-point (search-backward
1324                                             cscope-symbol
1325                                             (- old-point
1326                                                cscope-adjust-range) t))
1327                       (if forward-point
1328                           (progn
1329                             (if backward-point
1330                                 (setq new-point
1331                                       ;; Use whichever of forward-point or
1332                                       ;; backward-point is closest to old-point.
1333                                       ;; Give forward-point a line-length advantage
1334                                       ;; so that if the symbol is on the current
1335                                       ;; line the current line is chosen.
1336                                       (if (<= (- (- forward-point line-length)
1337                                                  old-point)
1338                                               (- old-point backward-point))
1339                                           forward-point
1340                                         backward-point))
1341                               (setq new-point forward-point)))
1342                         (if backward-point
1343                             (setq new-point backward-point)
1344                           (setq new-point old-point)))
1345                       (goto-char new-point)
1346                       (beginning-of-line)
1347                       (setq new-point (point)))
1348                   (setq new-point old-point))
1349                 (set-window-point window new-point)
1350                 (if (and cscope-allow-arrow-overlays arrow-p)
1351                     (set-marker overlay-arrow-position (point))
1352                   (set-marker overlay-arrow-position nil))
1353                 (or (not save-mark-p)
1354                     (= old-pos (point))
1355                     (push-mark old-pos))
1356                 ))
1357
1358           (if cscope-marker
1359               (progn ;; The search was successful.  Save the marker so it
1360                      ;; can be returned to by cscope-pop-mark.
1361                 (ring-insert cscope-marker-ring cscope-marker)
1362                 ;; Unset cscope-marker so that moving between matches
1363                 ;; (cscope-next-symbol, etc.) does not fill
1364                 ;; cscope-marker-ring.
1365                 (setq cscope-marker nil)))
1366           (setq cscope-marker-window window)
1367           )
1368       (message "No entry found at point."))
1369     )
1370   window)
1371
1372 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1373 ;; functions in *cscope* buffer which lists the search results
1374 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1375
1376 (defun cscope-select-entry-other-window ()
1377   "Display the entry at point in other window, select the window.
1378 Push current point on mark ring and select the entry window."
1379   (interactive)
1380   (let ((file (get-text-property (point) 'cscope-file))
1381         (line-number (get-text-property (point) 'cscope-line-number))
1382         window)
1383     (setq window (cscope-show-entry-internal file line-number t))
1384     (if (windowp window)
1385         (select-window window))
1386     ))
1387
1388
1389 (defun cscope-select-entry-one-window ()
1390   "Display the entry at point in one window, select the window."
1391   (interactive)
1392   (let ((file (get-text-property (point) 'cscope-file))
1393         (line-number (get-text-property (point) 'cscope-line-number))
1394         window)
1395     (setq window (cscope-show-entry-internal file line-number t))
1396     (if (windowp window)
1397         (progn
1398           (select-window window)
1399           (sit-for 0)   ;; Redisplay hack to allow delete-other-windows
1400                         ;; to continue displaying the correct location.
1401           (delete-other-windows window)
1402           ))
1403     ))
1404
1405
1406 (defun cscope-select-entry-specified-window (window)
1407   "Display the entry at point in a specified window, select the window."
1408   (interactive)
1409   (let ((file (get-text-property (point) 'cscope-file))
1410         (line-number (get-text-property (point) 'cscope-line-number)))
1411     (setq window (cscope-show-entry-internal file line-number t window))
1412     (if (windowp window)
1413           (select-window window))
1414     ))
1415
1416
1417 (defun cscope-mouse-select-entry-other-window (event)
1418   "Display the entry over which the mouse event occurred, select the window."
1419   (interactive "e")
1420   (let ((ep (cscope-event-point event))
1421         (win (cscope-event-window event))
1422         buffer file line-number window)
1423     (if ep
1424         (progn
1425           (setq buffer (window-buffer win)
1426                 file (get-text-property ep 'cscope-file buffer)
1427                 line-number (get-text-property ep 'cscope-line-number buffer))
1428           (select-window win)
1429           (setq window (cscope-show-entry-internal file line-number t))
1430           (if (windowp window)
1431               (select-window window))
1432           )
1433       (message "No entry found at point.")
1434       )
1435     ))
1436
1437
1438 (defun cscope-show-entry-other-window ()
1439   "Display the entry at point in other window.
1440 Point is not saved on mark ring."
1441   (interactive)
1442   (let ((file (get-text-property (point) 'cscope-file))
1443         (line-number (get-text-property (point) 'cscope-line-number)))
1444     (cscope-show-entry-internal file line-number nil nil t)
1445     ))
1446
1447
1448 (defun cscope-buffer-search (do-symbol do-next)
1449   "The body of the following four functions."
1450   (let* (line-number old-point point
1451                      (search-file (not do-symbol))
1452                      (search-prev (not do-next))
1453                      (direction (if do-next 1 -1))
1454                      (old-buffer (current-buffer))
1455                      (old-buffer-window (get-buffer-window old-buffer))
1456                      (buffer (get-buffer cscope-output-buffer-name))
1457                      (buffer-window (get-buffer-window (or buffer (error "The *cscope* buffer does not exist yet"))))
1458                      )
1459     (set-buffer buffer)
1460     (setq old-point (point))
1461     (forward-line direction)
1462     (setq point (point))
1463     (setq line-number (get-text-property point 'cscope-line-number))
1464     (while (or (not line-number)
1465                (or (and do-symbol (= line-number -1))
1466                    (and search-file  (/= line-number -1))))
1467       (forward-line direction)
1468       (setq point (point))
1469       (if (or (and do-next (>= point (point-max)))
1470               (and search-prev (<= point (point-min))))
1471           (progn
1472             (goto-char old-point)
1473             (error "The %s of the *cscope* buffer has been reached"
1474                    (if do-next "end" "beginning"))))
1475       (setq line-number (get-text-property point 'cscope-line-number)))
1476     (if (eq old-buffer buffer) ;; In the *cscope* buffer.
1477         (cscope-show-entry-other-window)
1478       (cscope-select-entry-specified-window old-buffer-window) ;; else
1479       (if (windowp buffer-window)
1480           (set-window-point buffer-window point)))
1481     (set-buffer old-buffer)
1482     ))
1483
1484
1485 (defun cscope-display-buffer ()
1486   "Display the *cscope* buffer."
1487   (interactive)
1488   (let ((buffer (get-buffer cscope-output-buffer-name)))
1489     (if buffer
1490         (pop-to-buffer buffer)
1491       (error "The *cscope* buffer does not exist yet"))))
1492
1493
1494 (defun cscope-display-buffer-toggle ()
1495   "Toggle cscope-display-cscope-buffer, which corresponds to
1496 \"Auto display *cscope* buffer\"."
1497   (interactive)
1498   (setq cscope-display-cscope-buffer (not cscope-display-cscope-buffer))
1499   (message "The cscope-display-cscope-buffer variable is now %s."
1500            (if cscope-display-cscope-buffer "set" "unset")))
1501
1502
1503 (defun cscope-next-symbol ()
1504   "Move to the next symbol in the *cscope* buffer."
1505   (interactive)
1506   (cscope-buffer-search t t))
1507
1508
1509 (defun cscope-next-file ()
1510   "Move to the next file in the *cscope* buffer."
1511   (interactive)
1512   (cscope-buffer-search nil t))
1513
1514
1515 (defun cscope-prev-symbol ()
1516   "Move to the previous symbol in the *cscope* buffer."
1517   (interactive)
1518   (cscope-buffer-search t nil))
1519
1520
1521 (defun cscope-prev-file ()
1522   "Move to the previous file in the *cscope* buffer."
1523   (interactive)
1524   (cscope-buffer-search nil nil))
1525
1526
1527 (defun cscope-pop-mark ()
1528   "Pop back to where cscope was last invoked."
1529   (interactive)
1530
1531   ;; This function is based on pop-tag-mark, which can be found in
1532   ;; lisp/progmodes/etags.el.
1533
1534   (if (ring-empty-p cscope-marker-ring)
1535       (error "There are no marked buffers in the cscope-marker-ring yet"))
1536   (let* ( (marker (ring-remove cscope-marker-ring 0))
1537           (old-buffer (current-buffer))
1538           (marker-buffer (marker-buffer marker))
1539           marker-window
1540           (marker-point (marker-position marker))
1541           (cscope-buffer (get-buffer cscope-output-buffer-name)) )
1542
1543     ;; After the following both cscope-marker-ring and cscope-marker will be
1544     ;; in the state they were immediately after the last search.  This way if
1545     ;; the user now makes a selection in the previously generated *cscope*
1546     ;; buffer things will behave the same way as if that selection had been
1547     ;; made immediately after the last search.
1548     (setq cscope-marker marker)
1549
1550     (if marker-buffer
1551         (if (eq old-buffer cscope-buffer)
1552             (progn ;; In the *cscope* buffer.
1553               (set-buffer marker-buffer)
1554               (setq marker-window (display-buffer marker-buffer))
1555               (set-window-point marker-window marker-point)
1556               (select-window marker-window))
1557           (switch-to-buffer marker-buffer))
1558       (error "The marked buffer has been deleted"))
1559     (goto-char marker-point)
1560     (set-buffer old-buffer)))
1561
1562
1563 (defun cscope-set-initial-directory (cs-id)
1564   "Set the cscope-initial-directory variable.  The
1565 cscope-initial-directory variable, when set, specifies the directory
1566 where searches for the cscope database directory should begin.  This
1567 overrides the current directory, which would otherwise be used."
1568   (interactive "DCscope Initial Directory: ")
1569   (setq cscope-initial-directory cs-id))
1570
1571
1572 (defun cscope-unset-initial-directory ()
1573   "Unset the cscope-initial-directory variable."
1574   (interactive)
1575   (setq cscope-initial-directory nil)
1576   (message "The cscope-initial-directory variable is now unset."))
1577
1578
1579 (defun cscope-help ()
1580   (interactive)
1581   (message
1582    (format "RET=%s, SPC=%s, o=%s, n=%s, p=%s, q=%s, h=%s"
1583            "Select"
1584            "Show"
1585            "SelectOneWin"
1586            "ShowNext"
1587            "ShowPrev"
1588            "Quit"
1589            "Help")))
1590
1591
1592 (defun cscope-bury-buffer ()
1593   "Clean up cscope, if necessary, and bury the buffer."
1594   (interactive)
1595   (let ()
1596     (if overlay-arrow-position
1597         (set-marker overlay-arrow-position nil))
1598     (setq overlay-arrow-position nil
1599           overlay-arrow-string nil)
1600     (bury-buffer (get-buffer cscope-output-buffer-name))
1601     ))
1602
1603
1604 (defun cscope-quit ()
1605   (interactive)
1606   (cscope-bury-buffer)
1607   (kill-buffer cscope-output-buffer-name)
1608   )
1609
1610 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1611
1612 (defun cscope-canonicalize-directory (dir)
1613   (or dir
1614       (setq dir default-directory))
1615   (setq dir (file-name-as-directory
1616              (expand-file-name (substitute-in-file-name dir))))
1617   dir
1618   )
1619
1620
1621 (defun cscope-search-directory-hierarchy (directory)
1622   "Look for a cscope database in the directory hierarchy.
1623 Starting from DIRECTORY, look upwards for a cscope database."
1624   (let (this-directory database-dir)
1625     (catch 'done
1626       (if (file-regular-p directory)
1627           (throw 'done directory))
1628       (setq directory (cscope-canonicalize-directory directory)
1629             this-directory directory)
1630       (while this-directory
1631         (if (or (file-exists-p (concat this-directory cscope-database-file))
1632                 (file-exists-p (concat this-directory cscope-index-file)))
1633             (progn
1634               (setq database-dir this-directory)
1635               (throw 'done database-dir)
1636               ))
1637         (if (string-match "^\\(/\\|[A-Za-z]:[\\/]\\)$" this-directory)
1638             (throw 'done directory))
1639         (setq this-directory (file-name-as-directory
1640                               (file-name-directory
1641                                (directory-file-name this-directory))))
1642         ))
1643     ))
1644
1645
1646 (defun cscope-find-info (top-directory)
1647   "Locate a suitable cscope database directory.
1648 First, `cscope-database-regexps' is used to search for a suitable
1649 database directory.  If a database location cannot be found using this
1650 variable, then the current directory is searched, then the parent,
1651 then the parent's parent, until a cscope database directory is found,
1652 or the root directory is reached.  If the root directory is reached,
1653 the current directory will be used."
1654   (let (info regexps dir-regexp this-directory)
1655     (setq top-directory (cscope-canonicalize-directory
1656                          (or top-directory cscope-initial-directory)))
1657     (catch 'done
1658       ;; Try searching using `cscope-database-regexps' ...
1659       (setq regexps cscope-database-regexps)
1660       (while regexps
1661         (setq dir-regexp (car (car regexps)))
1662         (cond
1663          ( (stringp dir-regexp)
1664            (if (string-match dir-regexp top-directory)
1665                (progn
1666                  (setq info (cdr (car regexps)))
1667                  (throw 'done t)
1668                  )) )
1669          ( (and (symbolp dir-regexp) dir-regexp)
1670            (progn
1671              (setq info (cdr (car regexps)))
1672              (throw 'done t)
1673              ) ))
1674         (setq regexps (cdr regexps))
1675         )
1676
1677       ;; Try looking in the directory hierarchy ...
1678       (if (setq this-directory
1679                 (cscope-search-directory-hierarchy top-directory))
1680           (progn
1681             (setq info (list (list this-directory)))
1682             (throw 'done t)
1683             ))
1684
1685       ;; Should we add any more places to look?
1686
1687       )         ;; end catch
1688     (if (not info)
1689         (setq info (list (list top-directory))))
1690     info
1691     ))
1692
1693
1694 (defun cscope-make-entry-line (func-name line-number line)
1695   ;; The format of entry line:
1696   ;; func-name[line-number]______line
1697   ;; <- cscope-name-line-width ->
1698   ;; `format' of Emacs doesn't have "*s" spec.
1699   (let* ((fmt (format "%%%ds %%s" cscope-name-line-width))
1700          (str (format fmt (format "%s[%s]" func-name line-number) line))
1701          beg end)
1702     (if cscope-use-face
1703         (progn
1704           (setq end (length func-name))
1705           (put-text-property 0 end 'face 'cscope-function-face str)
1706           (setq beg (1+ end)
1707                 end (+ beg (length line-number)))
1708           (put-text-property beg end 'face 'cscope-line-number-face str)
1709           (setq end (length str)
1710                 beg (- end (length line)))
1711           (put-text-property beg end 'face 'cscope-line-face str)
1712           ))
1713     str))
1714
1715
1716 (defun cscope-process-filter (process output)
1717   "Accept cscope process output and reformat it for human readability.
1718 Magic text properties are added to allow the user to select lines
1719 using the mouse."
1720   (let ( (old-buffer (current-buffer)) )
1721     (unwind-protect
1722         (progn
1723           (set-buffer (process-buffer process))
1724           ;; Make buffer-read-only nil
1725           (let (buffer-read-only line file function-name line-number moving)
1726             (setq moving (= (point) (process-mark process)))
1727             (save-excursion
1728               (goto-char (process-mark process))
1729               ;; Get the output thus far ...
1730               (if cscope-process-output
1731                   (setq cscope-process-output (concat cscope-process-output
1732                                                       output))
1733                 (setq cscope-process-output output))
1734               ;; Slice and dice it into lines.
1735               ;; While there are whole lines left ...
1736               (while (and cscope-process-output
1737                           (string-match "\\([^\n]+\n\\)\\(\\(.\\|\n\\)*\\)"
1738                                         cscope-process-output))
1739                 (setq file                              nil
1740                       glimpse-stripped-directory        nil
1741                       )
1742                 ;; Get a line
1743                 (setq line (substring cscope-process-output
1744                                       (match-beginning 1) (match-end 1)))
1745                 (setq cscope-process-output (substring cscope-process-output
1746                                                        (match-beginning 2)
1747                                                        (match-end 2)))
1748                 (if (= (length cscope-process-output) 0)
1749                     (setq cscope-process-output nil))
1750
1751                 ;; This should always match.
1752                 (if (string-match
1753                      "^\\([^ \t]+\\)[ \t]+\\([^ \t]+\\)[ \t]+\\([0-9]+\\)[ \t]+\\(.*\\)\n"
1754                      line)
1755                     (progn
1756                       (let (str)
1757                         (setq file (substring line (match-beginning 1)
1758                                               (match-end 1))
1759                               function-name (substring line (match-beginning 2)
1760                                                        (match-end 2))
1761                               line-number (substring line (match-beginning 3)
1762                                                      (match-end 3))
1763                               line (substring line (match-beginning 4)
1764                                               (match-end 4))
1765                               )
1766                         ;; If the current file is not the same as the previous
1767                         ;; one ...
1768                         (if (not (and cscope-last-file
1769                                       (string= file cscope-last-file)))
1770                             (progn
1771                               ;; The current file is different.
1772
1773                               ;; Insert a separating blank line if
1774                               ;; necessary.
1775                               (if cscope-last-file (insert "\n"))
1776                               ;; Insert the file name
1777                               (setq str (concat "*** " file ":"))
1778                               (if cscope-use-face
1779                                   (put-text-property 0 (length str)
1780                                                      'face 'cscope-file-face
1781                                                      str))
1782                               (cscope-insert-with-text-properties
1783                                str
1784                                (expand-file-name file)
1785                                ;; Yes, -1 is intentional
1786                                -1)
1787                               (insert "\n")
1788                               ))
1789                         (if (not cscope-first-match)
1790                             (setq cscope-first-match-point (point)))
1791                         ;; ... and insert the line, with the
1792                         ;; appropriate indentation.
1793                         (cscope-insert-with-text-properties
1794                          (cscope-make-entry-line function-name
1795                                                  line-number
1796                                                  line)
1797                          (expand-file-name file)
1798                          line-number)
1799                         (insert "\n")
1800                         (setq cscope-last-file file)
1801                         (if cscope-first-match
1802                             (setq cscope-matched-multiple t)
1803                           (setq cscope-first-match
1804                                 (cons (expand-file-name file)
1805                                       (string-to-number line-number))))
1806                         ))
1807                   (insert line "\n")
1808                   ))
1809               (set-marker (process-mark process) (point))
1810               )
1811             (if moving
1812                 (goto-char (process-mark process)))
1813             (set-buffer-modified-p nil)
1814             ))
1815       (set-buffer old-buffer))
1816     ))
1817
1818
1819 (defun cscope-process-sentinel (process event)
1820   "Sentinel for when the cscope process dies."
1821   (let* ( (buffer (process-buffer process)) window update-window
1822          (done t) (old-buffer (current-buffer))
1823          (old-buffer-window (get-buffer-window old-buffer)) )
1824     (set-buffer buffer)
1825     (save-window-excursion
1826       (save-excursion
1827         (if (or (and (setq window (get-buffer-window buffer))
1828                      (= (window-point window) (point-max)))
1829                 (= (point) (point-max)))
1830             (progn
1831               (setq update-window t)
1832               ))
1833         (delete-process process)
1834         (let (buffer-read-only continue)
1835           (goto-char (point-max))
1836           (if (and cscope-suppress-empty-matches
1837                    (= cscope-output-start (point)))
1838               (delete-region cscope-item-start (point-max))
1839             (progn
1840               (if (not cscope-start-directory)
1841                   (setq cscope-start-directory default-directory))
1842               (insert cscope-separator-line)
1843               ))
1844           (setq continue
1845                 (and cscope-search-list
1846                      (not (and cscope-first-match
1847                                cscope-stop-at-first-match-dir
1848                                (not cscope-stop-at-first-match-dir-meta)))))
1849           (if continue
1850               (setq continue (cscope-search-one-database)))
1851           (if continue
1852               (progn
1853                 (setq done nil)
1854                 )
1855             (progn
1856               (insert "\nSearch complete.")
1857               (if cscope-display-times
1858                   (let ( (times (current-time)) cscope-stop elapsed-time )
1859                     (setq cscope-stop (+ (* (car times) 65536.0)
1860                                          (car (cdr times))
1861                                          (* (car (cdr (cdr times))) 1.0E-6)))
1862                     (setq elapsed-time (- cscope-stop cscope-start-time))
1863                     (insert (format "  Search time = %.2f seconds."
1864                                     elapsed-time))
1865                     ))
1866               (setq cscope-process nil)
1867               (if cscope-running-in-xemacs
1868                   (setq modeline-process ": Search complete"))
1869               (if cscope-start-directory
1870                   (setq default-directory cscope-start-directory))
1871               (if (not cscope-first-match)
1872                   (message "No matches were found."))
1873               )
1874             ))
1875         (set-buffer-modified-p nil)
1876         ))
1877     (if (and done cscope-first-match-point update-window)
1878         (if window
1879             (set-window-point window cscope-first-match-point)
1880           (goto-char cscope-first-match-point))
1881       )
1882     (cond
1883      ( (not done)               ;; we're not done -- do nothing for now
1884        (if update-window
1885            (if window
1886                (set-window-point window (point-max))
1887              (goto-char (point-max))))
1888        )
1889      ( cscope-first-match
1890        (if cscope-display-cscope-buffer
1891            (if (and cscope-edit-single-match (not cscope-matched-multiple))
1892                (cscope-show-entry-internal(car cscope-first-match)
1893                                            (cdr cscope-first-match) t))
1894          (cscope-select-entry-specified-window old-buffer-window))
1895        )
1896      )
1897     (if (and done (eq old-buffer buffer) cscope-first-match)
1898         (cscope-help))
1899     (set-buffer old-buffer)
1900     ))
1901
1902
1903 (defun cscope-search-one-database ()
1904   "Pop a database entry from cscope-search-list and do a search there."
1905   (let ( next-item options cscope-directory database-file outbuf done
1906                    base-database-file-name)
1907     (setq outbuf (get-buffer-create cscope-output-buffer-name))
1908     (save-excursion
1909       (catch 'finished
1910         (set-buffer outbuf)
1911         (setq options '("-L"))
1912         (while (and (not done) cscope-search-list)
1913           (setq next-item (car cscope-search-list)
1914                 cscope-search-list (cdr cscope-search-list)
1915                 base-database-file-name cscope-database-file
1916                 )
1917           (if (listp next-item)
1918               (progn
1919                 (setq cscope-directory (car next-item))
1920                 (if (not (stringp cscope-directory))
1921                     (setq cscope-directory
1922                           (cscope-search-directory-hierarchy
1923                            default-directory)))
1924                 (if (file-regular-p cscope-directory)
1925                     (progn
1926                       ;; Handle the case where `cscope-directory' is really
1927                       ;; a full path name to a cscope database.
1928                       (setq base-database-file-name
1929                             (file-name-nondirectory cscope-directory)
1930                             cscope-directory
1931                             (file-name-directory cscope-directory))
1932                       ))
1933                 (setq cscope-directory 
1934                       (file-name-as-directory cscope-directory))
1935                 (if (not (member cscope-directory cscope-searched-dirs))
1936                     (progn
1937                       (setq cscope-searched-dirs (cons cscope-directory
1938                                                        cscope-searched-dirs)
1939                             done t)
1940                       ))
1941                 )
1942             (progn
1943               (if (and cscope-first-match
1944                        cscope-stop-at-first-match-dir
1945                        cscope-stop-at-first-match-dir-meta)
1946                   (throw 'finished nil))
1947               ))
1948           )
1949         (if (not done)
1950             (throw 'finished nil))
1951         (if (car (cdr next-item))
1952             (let (newopts)
1953               (setq newopts (car (cdr next-item)))
1954               (if (not (listp newopts))
1955                   (error (format "Cscope options must be a list: %s" newopts)))
1956               (setq options (append options newopts))
1957               ))
1958         (if cscope-command-args
1959             (setq options (append options cscope-command-args)))
1960         (setq database-file (concat cscope-directory base-database-file-name)
1961               cscope-searched-dirs (cons cscope-directory
1962                                          cscope-searched-dirs)
1963               )
1964
1965         ;; The database file and the directory containing the database file
1966         ;; must both be writable.
1967         (if (or (not (file-writable-p database-file))
1968                 (not (file-writable-p (file-name-directory database-file)))
1969                 cscope-do-not-update-database)
1970             (setq options (cons "-d" options)))
1971
1972         (goto-char (point-max))
1973         (setq cscope-item-start (point))
1974         (if (string= base-database-file-name cscope-database-file)
1975             (insert "\nDatabase directory: " cscope-directory "\n"
1976                     cscope-separator-line)
1977           (insert "\nDatabase directory/file: "
1978                   cscope-directory base-database-file-name "\n"
1979                   cscope-separator-line))
1980         ;; Add the correct database file to search
1981         (setq options (cons base-database-file-name options))
1982         (setq options (cons "-f" options))
1983         (setq cscope-output-start (point))
1984         (setq default-directory cscope-directory)
1985         (if cscope-filter-func
1986             (progn
1987               (setq cscope-process-output nil
1988                     cscope-last-file nil
1989                     )
1990               (setq cscope-process
1991                     (apply 'start-process "cscope" outbuf
1992                            cscope-program options))
1993               (set-process-filter cscope-process cscope-filter-func)
1994               (set-process-sentinel cscope-process cscope-sentinel-func)
1995               (set-marker (process-mark cscope-process) (point))
1996               (process-kill-without-query cscope-process)
1997               (if cscope-running-in-xemacs
1998                   (setq modeline-process ": Searching ..."))
1999               (setq buffer-read-only t)
2000               )
2001           (apply 'call-process cscope-program nil outbuf t options)
2002           )
2003         t
2004         ))
2005     ))
2006
2007
2008 (defun cscope-call (msg args &optional directory filter-func sentinel-func)
2009   "Generic function to call to process cscope requests.
2010 ARGS is a list of command-line arguments to pass to the cscope
2011 process.  DIRECTORY is the current working directory to use (generally,
2012 the directory in which the cscope database is located, but not
2013 necessarily), if different that the current one.  FILTER-FUNC and
2014 SENTINEL-FUNC are optional process filter and sentinel, respectively."
2015   (let ( (outbuf (get-buffer-create cscope-output-buffer-name))
2016          (old-buffer (current-buffer)) )
2017     (if cscope-process
2018         (error "A cscope search is still in progress -- only one at a time is allowed"))
2019     (setq directory (cscope-canonicalize-directory
2020                      (or cscope-initial-directory directory)))
2021     (if (eq outbuf old-buffer) ;; In the *cscope* buffer.
2022         (if cscope-marker-window
2023             (progn
2024               ;; Assume that cscope-marker-window is the window, from the
2025               ;; users perspective, from which the search was launched and the
2026               ;; window that should be returned to upon cscope-pop-mark.
2027               (set-buffer (window-buffer cscope-marker-window))
2028               (setq cscope-marker (point-marker))
2029               (set-buffer old-buffer)))
2030         (progn ;; Not in the *cscope buffer.
2031           ;; Set the cscope-marker-window to whichever window this search
2032           ;; was launched from.
2033           (setq cscope-marker-window (get-buffer-window old-buffer))
2034         (setq cscope-marker (point-marker))))
2035     (save-excursion
2036       (set-buffer outbuf)
2037       (if cscope-display-times
2038           (let ( (times (current-time)) )
2039             (setq cscope-start-time (+ (* (car times) 65536.0) (car (cdr times))
2040                                        (* (car (cdr (cdr times))) 1.0E-6)))))
2041       (setq default-directory directory
2042             cscope-start-directory nil
2043             cscope-search-list (cscope-find-info directory)
2044             cscope-searched-dirs nil
2045             cscope-command-args args
2046             cscope-filter-func filter-func
2047             cscope-sentinel-func sentinel-func
2048             cscope-first-match nil
2049             cscope-first-match-point nil
2050             cscope-stop-at-first-match-dir-meta (memq t cscope-search-list)
2051             cscope-matched-multiple nil
2052             buffer-read-only nil)
2053       (buffer-disable-undo)
2054       (erase-buffer)
2055       (setq truncate-lines cscope-truncate-lines)
2056       (if msg
2057           (insert msg "\n"))
2058       (cscope-search-one-database)
2059       )
2060     (if cscope-display-cscope-buffer
2061         (progn
2062           (pop-to-buffer outbuf)
2063           (cscope-help))
2064       (set-buffer outbuf))
2065     (goto-char (point-max))
2066     (cscope-list-entry-mode)
2067     ))
2068
2069
2070 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2071
2072 (defvar cscope-unix-index-process-buffer-name "*cscope-indexing-buffer*"
2073   "The name of the buffer to use for displaying indexing status/progress.")
2074
2075
2076 (defvar cscope-unix-index-process-buffer nil
2077   "The buffer to use for displaying indexing status/progress.")
2078
2079
2080 (defvar cscope-unix-index-process nil
2081   "The current indexing process.")
2082
2083
2084 (defun cscope-unix-index-files-sentinel (process event)
2085   "Simple sentinel to print a message saying that indexing is finished."
2086   (let (buffer)
2087     (save-window-excursion
2088       (save-excursion
2089         (setq buffer (process-buffer process))
2090         (set-buffer buffer)
2091         (goto-char (point-max))
2092         (insert cscope-separator-line "\nIndexing finished\n")
2093         (delete-process process)
2094         (setq cscope-unix-index-process nil)
2095         (set-buffer-modified-p nil)
2096         ))
2097     ))
2098
2099
2100 (defun cscope-unix-index-files-internal (top-directory header-text args)
2101   "Core function to call the indexing script."
2102   (let ()
2103     (save-excursion
2104       (setq top-directory (cscope-canonicalize-directory top-directory))
2105       (setq cscope-unix-index-process-buffer
2106             (get-buffer-create cscope-unix-index-process-buffer-name))
2107       (display-buffer cscope-unix-index-process-buffer)
2108       (set-buffer cscope-unix-index-process-buffer)
2109       (setq buffer-read-only nil)
2110       (setq default-directory top-directory)
2111       (buffer-disable-undo)
2112       (erase-buffer)
2113       (if header-text
2114           (insert header-text))
2115       (setq args (append args
2116                          (list "-v"
2117                                "-i" cscope-index-file
2118                                "-f" cscope-database-file
2119                                (if cscope-use-relative-paths
2120                                    "." top-directory))))
2121       (if cscope-index-recursively
2122           (setq args (cons "-r" args)))
2123       (setq cscope-unix-index-process
2124             (apply 'start-process "cscope-indexer"
2125                    cscope-unix-index-process-buffer
2126                    cscope-indexing-script args))
2127       (set-process-sentinel cscope-unix-index-process
2128                             'cscope-unix-index-files-sentinel)
2129       (process-kill-without-query cscope-unix-index-process)
2130       )
2131     ))
2132
2133
2134 (defun cscope-index-files (top-directory)
2135   "Index files in a directory.
2136 This function creates a list of files to index, and then indexes
2137 the listed files.
2138 The variable, \"cscope-index-recursively\", controls whether or not
2139 subdirectories are indexed."
2140   (interactive "DIndex files in directory: ")
2141   (let ()
2142     (cscope-unix-index-files-internal
2143      top-directory
2144      (format "Creating cscope index `%s' in:\n\t%s\n\n%s"
2145              cscope-database-file top-directory cscope-separator-line)
2146      nil)
2147     ))
2148
2149
2150 (defun cscope-create-list-of-files-to-index (top-directory)
2151   "Create a list of files to index.
2152 The variable, \"cscope-index-recursively\", controls whether or not
2153 subdirectories are indexed."
2154   (interactive "DCreate file list in directory: ")
2155   (let ()
2156     (cscope-unix-index-files-internal
2157      top-directory
2158      (format "Creating cscope file list `%s' in:\n\t%s\n\n"
2159              cscope-index-file top-directory)
2160      '("-l"))
2161     ))
2162
2163
2164 (defun cscope-edit-list-of-files-to-index ()
2165   "Search for and edit the list of files to index.
2166 If this functions causes a new file to be edited, that means that a
2167 cscope.out file was found without a corresponding cscope.files file."
2168   (interactive)
2169   (let (info directory file)
2170     (setq info (cscope-find-info nil))
2171     (if (/= (length info) 1)
2172         (error "There is no unique cscope database directory!"))
2173     (setq directory (car (car info)))
2174     (if (not (stringp directory))
2175         (setq directory
2176               (cscope-search-directory-hierarchy default-directory)))
2177     (setq file (concat (file-name-as-directory directory) cscope-index-file))
2178     (find-file file)
2179     (message (concat "File: " file))
2180     ))
2181
2182
2183 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2184
2185 (defun cscope-tell-user-about-directory ()
2186   "Display the name of the directory containing the cscope database."
2187   (interactive)
2188   (let (info directory)
2189     (setq info (cscope-find-info nil))
2190     (if (= (length info) 1)
2191         (progn
2192           (setq directory (car (car info)))
2193           (message (concat "Cscope directory: " directory))
2194           )
2195       (let ( (outbuf (get-buffer-create cscope-info-buffer-name)) )
2196         (display-buffer outbuf)
2197         (save-excursion
2198           (set-buffer outbuf)
2199           (buffer-disable-undo)
2200           (erase-buffer)
2201           (insert "Cscope search directories:\n")
2202           (while info
2203             (if (listp (car info))
2204                 (progn
2205                   (setq directory (car (car info)))
2206                   (if (not (stringp directory))
2207                       (setq directory
2208                             (cscope-search-directory-hierarchy
2209                              default-directory)))
2210                   (insert "\t" directory "\n")
2211                   ))
2212             (setq info (cdr info))
2213             )
2214           )
2215         ))
2216     ))
2217
2218
2219 (defun cscope-dired-directory ()
2220   "Run dired upon the cscope database directory.
2221 If possible, the cursor is moved to the name of the cscope database
2222 file."
2223   (interactive)
2224   (let (info directory buffer p1 p2 pos)
2225     (setq info (cscope-find-info nil))
2226     (if (/= (length info) 1)
2227         (error "There is no unique cscope database directory!"))
2228     (setq directory (car (car info)))
2229     (if (not (stringp directory))
2230         (setq directory
2231               (cscope-search-directory-hierarchy default-directory)))
2232     (setq buffer (dired-noselect directory nil))
2233     (switch-to-buffer buffer)
2234     (set-buffer buffer)
2235     (save-excursion
2236       (goto-char (point-min))
2237       (setq p1 (search-forward cscope-index-file nil t))
2238       (if p1
2239           (setq p1 (- p1 (length cscope-index-file))))
2240       )
2241     (save-excursion
2242       (goto-char (point-min))
2243       (setq p2 (search-forward cscope-database-file nil t))
2244       (if p2
2245           (setq p2 (- p2 (length cscope-database-file))))
2246       )
2247     (cond
2248      ( (and p1 p2)
2249        (if (< p1 p2)
2250            (setq pos p1)
2251          (setq pos p2))
2252        )
2253      ( p1
2254        (setq pos p1)
2255        )
2256      ( p2
2257        (setq pos p2)
2258        )
2259      )
2260     (if pos
2261         (set-window-point (get-buffer-window buffer) pos))
2262     ))
2263
2264
2265 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2266
2267 (defun cscope-extract-symbol-at-cursor (extract-filename)
2268   (let* ( (symbol-chars (if extract-filename
2269                             cscope-filename-chars
2270                           cscope-symbol-chars))
2271           (symbol-char-regexp (concat "[" symbol-chars "]"))
2272           )
2273     (save-excursion
2274       (buffer-substring-no-properties
2275        (progn
2276          (if (not (looking-at symbol-char-regexp))
2277              (re-search-backward "\\w" nil t))
2278          (skip-chars-backward symbol-chars)
2279          (point))
2280        (progn
2281          (skip-chars-forward symbol-chars)
2282          (point)
2283          )))
2284     ))
2285
2286
2287 (defun cscope-prompt-for-symbol (prompt extract-filename)
2288   "Prompt the user for a cscope symbol."
2289   (let (sym)
2290     (setq sym (cscope-extract-symbol-at-cursor extract-filename))
2291     (if (or (not sym)
2292             (string= sym "")
2293             (not (and cscope-running-in-xemacs
2294                       cscope-no-mouse-prompts current-mouse-event
2295                       (or (mouse-event-p current-mouse-event)
2296                           (misc-user-event-p current-mouse-event))))
2297             ;; Always prompt for symbol in dired mode.
2298             (eq major-mode 'dired-mode)
2299             )
2300         (setq sym (read-from-minibuffer prompt sym))
2301       sym)
2302     ))
2303
2304
2305 (defun cscope-find-this-symbol (symbol)
2306   "Locate a symbol in source code."
2307   (interactive (list
2308                 (cscope-prompt-for-symbol "Find this symbol: " nil)
2309                 ))
2310   (let ( (cscope-adjust t) )     ;; Use fuzzy matching.
2311     (setq cscope-symbol symbol)
2312     (cscope-call (format "Finding symbol: %s" symbol)
2313                  (list "-0" symbol) nil 'cscope-process-filter
2314                  'cscope-process-sentinel)
2315     ))
2316
2317
2318 (defun cscope-find-global-definition (symbol)
2319   "Find a symbol's global definition."
2320   (interactive (list
2321                 (cscope-prompt-for-symbol "Find this global definition: " nil)
2322                 ))
2323   (let ( (cscope-adjust t) )     ;; Use fuzzy matching.
2324     (setq cscope-symbol symbol)
2325     (cscope-call (format "Finding global definition: %s" symbol)
2326                  (list "-1" symbol) nil 'cscope-process-filter
2327                  'cscope-process-sentinel)
2328     ))
2329
2330
2331 (defun cscope-find-global-definition-no-prompting ()
2332   "Find a symbol's global definition without prompting."
2333   (interactive)
2334   (let ( (symbol (cscope-extract-symbol-at-cursor nil))
2335          (cscope-adjust t) )     ;; Use fuzzy matching.
2336     (setq cscope-symbol symbol)
2337     (cscope-call (format "Finding global definition: %s" symbol)
2338                  (list "-1" symbol) nil 'cscope-process-filter
2339                  'cscope-process-sentinel)
2340     ))
2341
2342
2343 (defun cscope-find-called-functions (symbol)
2344   "Display functions called by a function."
2345   (interactive (list
2346                 (cscope-prompt-for-symbol
2347                  "Find functions called by this function: " nil)
2348                 ))
2349   (let ( (cscope-adjust nil) )   ;; Disable fuzzy matching.
2350     (setq cscope-symbol symbol)
2351     (cscope-call (format "Finding functions called by: %s" symbol)
2352                  (list "-2" symbol) nil 'cscope-process-filter
2353                  'cscope-process-sentinel)
2354     ))
2355
2356
2357 (defun cscope-find-functions-calling-this-function (symbol)
2358   "Display functions calling a function."
2359   (interactive (list
2360                 (cscope-prompt-for-symbol
2361                  "Find functions calling this function: " nil)
2362                 ))
2363   (let ( (cscope-adjust t) )     ;; Use fuzzy matching.
2364     (setq cscope-symbol symbol)
2365     (cscope-call (format "Finding functions calling: %s" symbol)
2366                  (list "-3" symbol) nil 'cscope-process-filter
2367                  'cscope-process-sentinel)
2368     ))
2369
2370
2371 (defun cscope-find-this-text-string (symbol)
2372   "Locate where a text string occurs."
2373   (interactive (list
2374                 (cscope-prompt-for-symbol "Find this text string: " nil)
2375                 ))
2376   (let ( (cscope-adjust t) )     ;; Use fuzzy matching.
2377     (setq cscope-symbol symbol)
2378     (cscope-call (format "Finding text string: %s" symbol)
2379                  (list "-4" symbol) nil 'cscope-process-filter
2380                  'cscope-process-sentinel)
2381     ))
2382
2383
2384 (defun cscope-find-egrep-pattern (symbol)
2385   "Run egrep over the cscope database."
2386   (interactive (list
2387                 (let (cscope-no-mouse-prompts)
2388                   (cscope-prompt-for-symbol "Find this egrep pattern: " nil))
2389                 ))
2390   (let ( (cscope-adjust t) )     ;; Use fuzzy matching.
2391     (setq cscope-symbol symbol)
2392     (cscope-call (format "Finding egrep pattern: %s" symbol)
2393                  (list "-6" symbol) nil 'cscope-process-filter
2394                  'cscope-process-sentinel)
2395     ))
2396
2397
2398 (defun cscope-find-this-file (symbol)
2399   "Locate a file."
2400   (interactive (list
2401                 (let (cscope-no-mouse-prompts)
2402                   (cscope-prompt-for-symbol "Find this file: " t))
2403                 ))
2404   (let ( (cscope-adjust nil) )   ;; Disable fuzzy matching.
2405     (setq cscope-symbol symbol)
2406     (cscope-call (format "Finding file: %s" symbol)
2407                  (list "-7" symbol) nil 'cscope-process-filter
2408                  'cscope-process-sentinel)
2409     ))
2410
2411
2412 (defun cscope-find-files-including-file (symbol)
2413   "Locate all files #including a file."
2414   (interactive (list
2415                 (let (cscope-no-mouse-prompts)
2416                   (cscope-prompt-for-symbol
2417                    "Find files #including this file: " t))
2418                 ))
2419   (let ( (cscope-adjust t) )    ;; Use fuzzy matching.
2420     (setq cscope-symbol symbol)
2421     (cscope-call (format "Finding files #including file: %s" symbol)
2422                  (list "-8" symbol) nil 'cscope-process-filter
2423                  'cscope-process-sentinel)
2424     ))
2425
2426
2427 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2428
2429 (defvar cscope-minor-mode nil
2430   "")
2431 (make-variable-buffer-local 'cscope-minor-mode)
2432 (put 'cscope-minor-mode 'permanent-local t)
2433
2434
2435 (defun cscope-minor-mode (&optional arg)
2436   ""
2437   (progn
2438     (setq cscope-minor-mode (if (null arg) t (car arg)))
2439     (if cscope-minor-mode
2440         (progn
2441           (easy-menu-add cscope:menu cscope:map)
2442           (run-hooks 'cscope-minor-mode-hooks)
2443           ))
2444     cscope-minor-mode
2445     ))
2446
2447
2448 (defun cscope:hook ()
2449   ""
2450   (progn
2451     (cscope-minor-mode)
2452     ))
2453
2454
2455 (or (assq 'cscope-minor-mode minor-mode-map-alist)
2456     (setq minor-mode-map-alist (cons (cons 'cscope-minor-mode cscope:map)
2457                                      minor-mode-map-alist)))
2458
2459 (add-hook 'c-mode-hook (function cscope:hook))
2460 (add-hook 'c++-mode-hook (function cscope:hook))
2461 (add-hook 'dired-mode-hook (function cscope:hook))
2462
2463 (provide 'xcscope)