home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
p2demo21.exe
/
PEL
/
TAGS.PEL
< prev
next >
Wrap
Text File
|
1995-03-13
|
32KB
|
1,129 lines
# $Header: P:\source\wmacros\tags.pev 1.41 13 Mar 1995 16:37:52 WALKER $
##############################################################################
#
# Compuware Corporation
# 31440 Northwestern Highway
# Farmington Hills, Michigan 48334-2564
#
# This source code listing contains information that is
# proprietary to Compuware Corporation and may not be copied
# duplicated, translated, transmitted, stored, retrieved
# or in any manner or by any method conveyed or disclosed
# to a third party or parties without express written
# permission from Compuware Corporation.
#
#
##############################################################################
#### $Workfile: tags.pel $: tags support
## overview:
#
# A tags file is a data file which lists identifiers (function names,
# variables, etc.) along with information on where each was defined within
# the source code. With a tags file in place, one can use the functions
# "tags" and "tags_auto" contained herein to "bring in" the appropriate
# source file and position the cursor at the definition.
#
# How does one build a tags file? In addition to the two tags file building
# functions included with the editor (peltags_make and ctags_make), several commercial
# tags file building utilities exist which quickly build tags files for many
# languages. The tags file format used here is compatible with Moderne
# Software's PC-TAGS(tm) progam.
local tags_search_flags = SEARCH_REGEX + SEARCH_MAXIMAL_MATCH + SEARCH_FORWARD
## public entry points:
#
# tags - prompt for a function or variable name and move to its
# definition in the source code. Requires a tags data
# file.
#
# tags_auto - use the function or variable name under the cursor and
# move to its definition in the source code.
#
# (NOTE: The following two "peltags" functions find global functions
# and variables even without a tags data file. The tags file
# is still need to find local functions and variables.)
#
# peltags - like tags, above, but is optimized for pel language source
# code.
#
# peltags_auto- like tags_auto, above, but is optimized for pel language
# source code.
#
# peltags_make- builds a "peltags.tag" data file for all functions and
# initialized global variables in the current cpe.ae file.
#
#
## global variables
## tags_path
#
# The following may contain a ";" separated list of tags data file names.
# The "TAGS" environment variable, of the same format, may be used to
# override the tags_path variable.
#
global tags_path
global IDD_CTAGS_MAKE = 1620
global IDL_TAGS_DIRS = 1621
global IDE_TAGS_ADD_DIRS = 1622
global IDB_TAGS_DELETE = 1623
global IDB_TAGS_ADD = 1635
global IDR_OUTLOC_SOURCE_DIRS = 1624
global IDR_OUTLOC_SPECIFIED = 1625
global IDE_TAGS_OUTPUT_DIR = 1626
global IDE_TAGS_EXT_LIST = 1627
global IDB_TAGS_MAKE = 1628
local time_buf
global function init_timestamp( timefile )
{
time_buf = create_buffer( timefile,
timefile,
BUFFER_SYSTEM + BUFFER_NO_UNDO )
}
global function cleanup_timestamp()
{
local old_cur_buf = current_buffer
if ( time_buf )
{
current_buffer = time_buf
write_buffer()
delete_buffer( time_buf ); time_buf = 0
}
current_buffer = old_cur_buf
}
global function get_timestamp( fname )
{
local old_cur_buf = current_buffer
local line
local timestamp
if ( time_buf )
{
current_buffer = time_buf
if ( search("^" quote_regex(fname), SEARCH_FORWARD + SEARCH_REGEX + SEARCH_WRAPS) )
{
line = read_buffer()
timestamp = suffix( line, length(line) - cindex(line, " ") )
}
}
current_buffer = old_cur_buf
return timestamp+0
}
global function update_timestamp( fname )
{
local old_cur_buf = current_buffer
if ( time_buf )
{
current_buffer = time_buf
# normalize the file name
fname = buildpath( fname )
if ( search("^" quote_regex(fname), SEARCH_FORWARD + SEARCH_REGEX + SEARCH_WRAPS) )
{
delete_line()
goto_bol()
}
else
{
goto_buffer_bottom()
if ( current_column != 1 )
insert_newline()
}
insert_string( fname " " filetime(fname) )
insert_newline()
}
current_buffer = old_cur_buf
}
global function generate_timestamps( files, timefile )
{
local full_spec
local current_file
init_timestamp( timefile )
current_file = findfirst_path( files )
if ( current_file )
{
do
{
full_spec = buildpath( current_find_path() current_file )
update_timestamp( full_spec, filetime(full_spec) )
} while ( (current_file = findnext_path()) );
}
cleanup_timestamp()
}
## tags_auto()
#
# Treats the text under the cursor as a function or variable name, then
# attempts to locate the symbol's definition in source code. If found,
# the cursor is moved to the beginning of the symbol's definition.
#
# Returns TRUE if successful, otherwise FALSE
#
global function tags_auto()
{
return execute_auto("tags")
}
## tags()
#
# Prompts for a symbol to look up in the list of tags files. If found,
# the cursor is moved to the beginning of the function's or variable's
# definition in the source code. "use_symbol" can be use to search for
# the symbol if passed in as specified, w/out us doing any modifications
#
# Returns TRUE if successful, otherwise FALSE
#
global function tags( symbol, use_symbol )
{
local current_symbol = ""
# prompt for command if not specified as an argument
if ( !symbol )
{
current_symbol = symbol_under_cursor()
symbol = prompt_history( "CTAGSLOCATE", "Search for symbol: ", current_symbol, 1, 1, "ctagslocate" )
if ( !symbol )
return FALSE
}
# perform tags operation
if (tolower(path_ext(buffer_filename)) == ".pel")
return peltags( symbol )
else
return tags_find( symbol, use_symbol )
}
## tags_find()
#
# Scan tags data files for a specified symbol. Each tags file contains a
# list of function and variable names, paired with information about where
# the symbol is defined in source code. If an entry is found in one of the
# tags files, a buffer is created for the appropriate file, and the cursor
# is positioned on the first line of the definition.
#
# See tags() for a definition of use_symbol
#
# The rules for locating tags files are as follow:
# 1. Try each name listed in the TAGS environment variable;
# 2. If no TAGS var exists, use the tags_path PEL global variable
# 3. Try each file in the current directory with a ".tag" extension
#
local function tags_find( symbol, use_symbol )
{
local tempTagsPath
local tagsFile
local wildcard
local searched
local paths[]
local i
if ( !symbol )
return FALSE
# search all tags files in TAGS env variable
if ( "TAGS" in ENV )
tempTagsPath = ENV[ "TAGS" ]
else if ( tags_path )
{
# if no TAGS environment variable exists, try tags_path var
tempTagsPath = tags_path
}
else
{
# if neither of the above exist, use any *.tag found in the
# current directory or the directory where the current file
# resides
tempTagsPath = "*.tag;" path_path( buffer_filename ) "*.tag"
}
split( tempTagsPath, paths, ";" )
for ( i in paths )
{
wildcard = buildpath( paths[ i ] )
# if the element is a directory, append *.tag.
if ( and(filemode( wildcard ), _SUBDIR) )
wildcard = wildcard "\\*.tag"
if (( tagsFile = findfirst( wildcard )))
{
tagsFile = tolower( path_path( wildcard ) tagsFile )
if ( tags_lookup( tagsFile, symbol, use_symbol ))
return TRUE
# expand a filespec containng "?" or "*"
if ( wildcard ~ /\?\*/ )
{
while (( tagsFile = findnext()))
{
tagsFile = tolower( path_path( wildcard ) tagsFile )
if ( tags_lookup( tagsFile, symbol, use_symbol ))
return TRUE
}
}
searched = TRUE
}
}
# can't find string in tags file
if ( searched )
warning( "Unknown symbol \"%s\"", symbol )
else
warning( "No tags file found" )
return FALSE
}
# Find all tags that begin with symbol and
# prompt the user to choose between them.
local function prompt_tag_list( symbol, use_symbol )
{
# save search flags
local pattern = search_pattern
local old_search_flags = search_flags
local anIndex
local mysymbol = use_symbol ? symbol : "^" symbol " "
local tempArray
local tag[]
local count
local i
tag.symbol = symbol
# locate all occurrences of mysymbol in the file
search_flags = SEARCH_FORWARD + SEARCH_REGEX
tempArray = find_all( mysymbol, FALSE )
count = tempArray[0]
delete( tempArray[0] )
if ( count == 1 )
{
for ( i in tempArray )
tag.line = i
}
else if ( count > 1 )
{
tag.symbol = prompt_selection( "Which line?", 150, tempArray )
if ( tag.symbol )
tag.line = find_in_array( tempArray, tag.symbol )
}
delete_history_item("SEARCH", mysymbol )
# restore search pattern and flags
search_pattern = pattern
search_flags = old_search_flags
return tag
}
## tags_lookup()
#
# Given the name of a tags data file, and the name of a symbol to look up,
# determine whether the symbol is defined in the tags file. If so, create
# a buffer for the appropriate source file, and position the cursor on
# the first line of the definition.
#
# The format of a line in the tags file is as follows:
# <symbol><space><mode><source filename><space><^><pattern>
# where:
# <mode> determines how to interpret the <pattern> field
# if mode==none then pattern is an exact text match
# if mode=="|" then pattern is a regular expression pattern
# if mode=="#" then pattern is a line number
#
# Returns TRUE if the symbol was successfully matched, FALSE otherwise
#
local function tags_lookup( tagsFile, symbol, use_symbol )
{
local priorBuffer = current_buffer
local definition
local mode
local filename
local line = 0
local theLine
local tag[]
message( "searching %s...", tagsFile )
if ( filemode(tagsFile) == -1 )
{
warning( "Tags file %s not found)", tagsFile )
return FALSE
}
current_buffer = create_buffer( tagsFile, tagsFile, BUFFER_SYSTEM +
BUFFER_NO_UNDO )
# look for symbol string in tags file
goto_buffer_top()
tag = prompt_tag_list( symbol, use_symbol )
if ( tag.line )
{
goto_line( tag.line )
# skip past the symbol name and
# read the definition portion of the line
theLine = read_buffer()
current_column = match( theLine, " " ) + 1
definition = read_buffer()
# read <mode> field if present
if ( match( definition, /^[|#!]/ ))
{
mode = substr( definition, 1, RLENGTH )
definition = substr( definition, RLENGTH+1 )
}
# read the <pattern> field
if ( !match( definition, / \^/ ))
{
if ( mode || !match( definition, /[ \t]\/.+\// ))
{
warning( "Tags file %s - format is invalid", tagsFile )
# return TRUE to end the tags search
return TRUE
}
# convert a unix style tags file to our format
mode = "|"
definition = substr( definition, 1, length(definition) - 1 )
match( definition, /[ \t]+\// )
}
filename = substr( definition, 1, RSTART-1)
definition = substr( definition, RSTART+RLENGTH )
# remove the tags file buffer
if ( current_buffer != priorBuffer )
{
delete_buffer()
current_buffer = priorBuffer
}
# place the cursor at the definition in the source file
if ( !tags_locate(filename, mode, definition) && buffer_filename == filename )
search( tag.symbol, SEARCH_FORWARD )
return TRUE # end the tags search
}
# remove the tags file buffer
if ( current_buffer != priorBuffer )
{
delete_buffer()
current_buffer = priorBuffer
}
return FALSE
}
## tags_locate()
#
# Create a buffer for the specified source file, search for the specified
# line, and position the cursor on the first line of the definition.
#
global function tags_locate( filename, mode, definition )
{
local success
# switch to the new buffer
if ( filemode( filename ) == -1 || !create_buf_and_win( filename ))
{
warning( "Unable to find file %s", filename )
return FALSE
}
goto_buffer_top()
if ( !mode )
{
# exact match (whole line)
success = bol_search( definition "\r" )
}
else if ( mode ~ /\|/ )
{
# context sensitive (regex) search
success = !!search( definition, tags_search_flags )
}
else if ( mode ~ /#/ )
{
# definition is a line number
goto_line( 0+definition )
success = TRUE
}
center_cursor()
display_filename()
return success
}
## bol_search()
#
# Search for an exact match of specified text beginning in column 1
#
local function bol_search( text )
{
save_position()
# search without regex, until we succeed in matching text in col 1
while ( search( text, SEARCH_FORWARD ))
{
if ( current_column == 1 )
return TRUE
current_column = 1
current_line++
}
# text not found
restore_position(1)
return FALSE
}
## execute_auto()
#
# This function executes the function specified by fun and passes it the
# selected text or the symbol_under_cursor as the parameter.
#
global function execute_auto(fun, symbol_regex)
{
local len
local symbol
if (selection_type())
{
len = distance_between_marks(selection_mark_top(), selection_mark_bottom())
if (len)
{
save_position()
end_selection()
goto_mark(selection_mark_top())
symbol = read_buffer(len)
restore_position(1)
}
}
if ( !symbol )
symbol = symbol_under_cursor(symbol_regex)
if ( symbol )
{
if (fun)
return execute_function(function_id(fun, symbol))
else
return symbol
}
else
{
warning( "cursor not on valid symbol" )
return FALSE
}
}
############################### pel tags support ############################
## local variables
local pelTagsFile
## peltags()
#
# Variant of the tags() function which looks first in the current .AE file's
# symbol table for the specified symbol. Only if that fails does the search
# proceed to the tags data files.
#
global function peltags( symbol )
{
local tmp_array
local filename
local definition
local response
# prompt for command if not specified as an argument
if ( !symbol )
{
symbol = prompt_history( "CTAGSLOCATE", "Search for symbol:", "", 1, 1, "peltags_dialog" )
if ( !symbol )
return FALSE
}
# Look in the current .AE file's symbol table for a PEL local or
# global function.
#
message( "Looking for:%s", symbol )
tmp_array = symbol_match( symbol, LOCAL_FUN + GLOBAL_FUN )
if ( tmp_array[1] )
{
# if the symbol matched more than one, or if it was only the
# beginning of one, display choices box.
if (symbol != tmp_array[1] || tmp_array[2])
{
response = prompt_selection("Choose symbol", 25, tmp_array, 0, 1)
if (!response)
return FALSE
else
symbol = response
}
if ( match( symbol , /:/ ))
{
definition = "^local[ \\t]*function[ \\t]+" \
substr( symbol, RSTART+1 ) "\\("
}
else
{
definition = "^(global)?[ \\t]*function[ \\t]+" symbol "\\("
}
filename = source_file_name( function_id( symbol ))
if ( filename )
{
if ( !tags_locate(filename, "|", definition) && buffer_filename == filename )
search( symbol, SEARCH_FORWARD )
return TRUE
}
}
# otherwise pass it on to tags
#
if ( !pelTagsFile )
{
# get name of tags file
initPelTagsFile()
}
return tags_find( symbol )
}
## peltags_auto()
#
# Variant of the tags_auto() function which looks first in the current .AE
# file's symbol table for the symbol under the cursor. Only if that fails
# does the search proceed to the tags data files.
#
global function peltags_auto()
{
return execute_auto("peltags")
}
## peltags_make()
#
# build the PEL tags database
#
global function peltags_make()
{
local priorBuffer = current_buffer
local tagsBuffer
local function_list
local file_list
local tmp_array
local lastUpdate
local symbol
local srch
local fn
local i
local j
local step
local count
local old_sbflags = status_bar_flags
# get name of tags file
if ( !pelTagsFile )
initPelTagsFile()
# this will take a while...
lastUpdate = ctime( filetime( pelTagsFile ) )
if ( lastUpdate )
lastUpdate = "Tags file was last updated " lastUpdate
else
lastUpdate = "This will take a while"
i = confirm( lastUpdate " - really update? [yn] ", "yYnN" )
if ( tolower(i) != "y" )
return
status_bar_flags = or( status_bar_flags, STB_MESSAGES )
message( "Building %s - Please wait...", pelTagsFile )
# create a system buffer for the tags info
# (no file name avoids reading an obsolete file)
current_buffer = tagsBuffer = create_buffer( pelTagsFile, "",
BUFFER_SYSTEM + BUFFER_NO_UNDO )
process_background( DISABLE_FOREGROUND )
##
## create a sorted list of all global functions
##
tmp_array = symbol_match( "", GLOBAL_FUN )
count = 0
for ( i in tmp_array )
{
count++
function_list[ tmp_array[ i ] ] = 0
}
delete tmp_array
# insert the name, source filename, and regex pattern into the buffer
message( "global functions..." )
j = 0
step = count / 100
step += (count % 100) ? 1 : 0
for ( i in function_list )
{
fn = source_file_name( function_id( i ))
file_list[ fn ] = 1
insert_string( i " |" fn " ^^(global)?[ \\t]*function[ \\t]+" i "\\(" )
insert_newline()
if ( (j++ % step) == 0 )
message( "%s( %d%% done )", "global functions", j / step )
}
delete function_list
##
## append a sorted list of all local functions
##
message( "local functions..." )
tmp_array = symbol_match( "", LOCAL_FUN )
count = 0
for ( i in tmp_array )
{
count++
symbol = tmp_array[ i ]
match( symbol, ":" )
function_list[ substr( symbol, RSTART+1 ) ] = \
source_file_name( function_id( symbol ))
}
delete tmp_array
# insert the name, source filename, and regex pattern into the buffer
j = 0
step = count / 100
step += (count % 100) ? 1 : 0
for ( i in function_list )
{
insert_string( i " |" function_list[ i ] \
" ^^local[ \\t]*function[ \\t]+" i "\\(" )
insert_newline()
if ( (j++ % step) == 0 )
message( "%s( %d%% done )", "local functions", j / step )
}
delete function_list
##
## append a list of all global variables
##
message( "global variables..." )
j = 0
for ( fn in file_list )
{
# open the buffer as a system buffer
if ( filemode( fn ) == -1 )
continue
message( "global variables in %s...", fn )
current_buffer = create_buffer( "", fn, BUFFER_SYSTEM + BUFFER_NO_UNDO )
# search for global variable declarations
goto_buffer_top()
while ( search( "global", SEARCH_FORWARD ) )
{
# read the entire line
current_column = 0
symbol = srch = read_buffer()
next_line()
# trim comments
if ( match( symbol, /[ \t]*#/ ))
symbol = substr( symbol, 1, RSTART-1 )
# trim the "="
if ( match( symbol, /[ \t]*=/ ))
symbol = substr( symbol, 1, RSTART-1 )
else
continue
# trim the "global" keyword
if ( match( symbol, /^[ \t]*global[ \t]+/ ) )
symbol = substr( symbol, RSTART+RLENGTH )
else
continue
# add the symbol to the list
function_list[ symbol ] = srch
}
delete_buffer()
# insert the name and source filename in the buffer
current_buffer = tagsBuffer
for ( i in function_list )
{
insert_string( i " " fn " ^" function_list[ i ] )
insert_newline()
}
delete function_list
}
# save the new tags file
current_buffer = tagsBuffer
write_buffer( pelTagsFile )
if ( current_buffer != priorBuffer )
{
delete_buffer()
current_buffer = priorBuffer
}
message( "" )
status_bar_flags = old_sbflags
process_background( END_BACKGROUND )
play( "L4MS<ccc" ) # signal that we are done
}
## initialize the pelTagsFile variable with the full name of the tags file
#
local function initPelTagsFile()
{
local thisFilename = source_file_name( function_id( "tags" ))
# use "peltags.tag" prefixed with the full path
if ( thisFilename )
pelTagsFile = path_path( thisFilename ) "peltags.tag"
else
pelTagsFile = buildpath( "peltags.tag" )
# create the tags_path variable if necessary
if ( !tags_path )
tags_path = pelTagsFile
}
function tags_settings( settings_index, settings_data )
{
local new_array;
settings_data[ settings_index++ ] = sprintf( "tags_path=%s\n", tags_path )
new_array.array = settings_data
new_array.index = settings_index
return new_array
}
local function update_tags_make_config( tags_paths, output_dir )
{
local i
local index
local path
local paths_list
local settings_data[]
for ( index in tags_paths )
if ( paths_list )
paths_list = paths_list ";" tags_paths[ index ]
else
paths_list = tags_paths[ index ]
settings_data[ ++i ] = paths_list "\n"
if ( output_dir )
settings_data[ ++i ] = output_dir "\n"
update_config_section( "$TAGS_MAKE$", settings_data )
}
local start_dir
global function ctags_make_dialog_callback()
{
local ret = DRC_CONTINUE
local index
local count
local path
local str
local tagsDirs[]
local tagsOutput
local config_data
local tag_file_specified
if ( callback_msg == DM_INIT )
{
start_dir = getcwd()
add_dialog_item( callback_dialog_handle, IDE_TAGS_ADD_DIRS, DCTRL_EDIT_KEY )
config_data = read_config_section( "$TAGS_MAKE$", 0, TRUE )
str = config_data[ 1 ]
tagsOutput = config_data[ 2 ]
if ( split(str, tagsDirs, ";") )
{
for ( index in tagsDirs )
{
path = tagsDirs[ index ]
if ( query_dialog_item( callback_dialog_handle,
IDL_TAGS_DIRS,
DAC_FIND,
path) == -1 )
{
set_dialog_item( callback_dialog_handle,
IDL_TAGS_DIRS,
DAC_ADD_ITEM,
path )
}
}
}
# add a blank entry so the user can insert at the end of the list
set_dialog_item( callback_dialog_handle, IDL_TAGS_DIRS, DAC_ADD_ITEM, " " )
set_dialog_item( callback_dialog_handle, IDL_TAGS_DIRS, DAC_SELECT_INDEX, 0 )
if ( tagsOutput )
{
set_dialog_item( callback_dialog_handle,
IDR_OUTLOC_SOURCE_DIRS,
DAC_UNCHECK )
set_dialog_item( callback_dialog_handle,
IDR_OUTLOC_SPECIFIED,
DAC_CHECK )
set_dialog_item( callback_dialog_handle, IDE_TAGS_OUTPUT_DIR, DAC_ENABLE )
set_dialog_item( callback_dialog_handle, IDE_TAGS_OUTPUT_DIR, DAC_TEXT, tagsOutput )
}
else
{
set_dialog_item( callback_dialog_handle,
IDR_OUTLOC_SOURCE_DIRS,
DAC_CHECK )
set_dialog_item( callback_dialog_handle,
IDR_OUTLOC_SPECIFIED,
DAC_UNCHECK )
set_dialog_item( callback_dialog_handle, IDE_TAGS_OUTPUT_DIR, DAC_DISABLE )
}
str = get_ext_list( "c" )
gsub( "\\.", "*.", str )
set_dialog_item( callback_dialog_handle, IDE_TAGS_EXT_LIST, DAC_TEXT, str )
set_dialog_item( callback_dialog_handle, IDL_TAGS_DIRS, DAC_SETFOCUS )
}
else if ( callback_msg == DM_HELPREQUESTED )
{
display_help("ctagsmake")
ret = DRC_MSG_PROCESSED
}
else if ( callback_msg == DM_CLICK || callback_msg == DM_DOUBLE_CLICK )
{
ret = DRC_MSG_PROCESSED
if ( callback_index == IDB_TAGS_DELETE )
{
index = query_dialog_item( callback_dialog_handle, IDL_TAGS_DIRS, DAC_SELECT_INDEX )
if ( index >= 0 )
{
set_dialog_item( callback_dialog_handle, IDL_TAGS_DIRS, DAC_DELETE_INDEX, index )
count = query_dialog_item( callback_dialog_handle, IDL_TAGS_DIRS, DAC_COUNT_ITEMS )
if ( index <= count - 1 )
set_dialog_item( callback_dialog_handle, IDL_TAGS_DIRS, DAC_SELECT_INDEX, index )
else
set_dialog_item( callback_dialog_handle, IDL_TAGS_DIRS, DAC_SELECT_INDEX, count - 1 )
}
}
else if ( callback_index == IDB_TAGS_ADD )
{
ctags_add_path(callback_dialog_handle)
}
else if ( callback_index == IDR_OUTLOC_SOURCE_DIRS )
{
set_dialog_item( callback_dialog_handle, IDR_OUTLOC_SPECIFIED, DAC_UNCHECK )
set_dialog_item( callback_dialog_handle, IDE_TAGS_OUTPUT_DIR, DAC_DISABLE )
}
else if ( callback_index == IDR_OUTLOC_SPECIFIED )
{
set_dialog_item( callback_dialog_handle, IDR_OUTLOC_SOURCE_DIRS, DAC_UNCHECK )
set_dialog_item( callback_dialog_handle, IDE_TAGS_OUTPUT_DIR, DAC_ENABLE )
}
else if ( callback_index == IDB_TAGS_MAKE )
{
count = query_dialog_item( callback_dialog_handle, IDL_TAGS_DIRS, DAC_COUNT_ITEMS )
for ( index = 0; index < count; index++ )
{
str = query_dialog_item( callback_dialog_handle,
IDL_TAGS_DIRS,
DAC_GET_INDEX_ITEM, index )
str = ltrim( trim(str) )
if ( str )
tagsDirs[ index ] = str
}
set_dialog_item( callback_dialog_handle, IDB_TAGS_MAKE, DAC_DISABLE )
if ( !query_dialog_item(callback_dialog_handle, IDR_OUTLOC_SOURCE_DIRS, DAC_CHECK) )
{
str = query_dialog_item( callback_dialog_handle, IDE_TAGS_OUTPUT_DIR, DAC_TEXT )
tag_file_specified = buildpath( str )
if ( filemode(tag_file_specified) == _SUBDIR )
tag_file_specified = tag_file_specified "/ctags.tag"
}
set_dialog_window( callback_dialog_handle, DWC_HIDE )
str = query_dialog_item( callback_dialog_handle, IDE_TAGS_EXT_LIST, DAC_TEXT )
for ( index in tagsDirs )
{
if ( chdir( tagsDirs[index] ) )
{
if ( tag_file_specified )
{
if ( !ctags_make(str, tag_file_specified) )
break # break out of loop if user interrupted tags
}
else if ( !ctags_make(str, buildpath(tagsDirs[index] "/ctags.tag")) )
break # break out of loop if user interrupted tags
}
else
warning( "path " tagsDirs[index] " does not exist" )
}
play( "L4MS<ccc" ) # signal that we are done
update_tags_make_config( tagsDirs, tag_file_specified )
chdir( start_dir )
ret = DRC_CONTINUE
}
else
ret = DRC_CONTINUE
}
else if ( callback_msg == DM_INVALID_PCHAR && callback_index == IDE_TAGS_ADD_DIRS )
{
if ( callback_data == KEYCODE_ENTER || callback_data == KEYCODE_KEYPAD_ENTER )
{
ret = DRC_MSG_PROCESSED
ctags_add_path(callback_dialog_handle)
}
else
ret = DRC_CONTINUE
}
else if ( callback_msg == DM_CANCEL )
{
if ( query_dialog_item(callback_dialog_handle, IDB_TAGS_MAKE, DAC_DISABLE) )
{
process_background( STOP_BACKGROUND )
chdir( start_dir )
}
}
return ret
}
local function ctags_add_path(handle)
{
local str, path
local index
local ret
local oldPE = pause_on_error
# if not enabled, warning message goes on the status bar of parent window
pause_on_error = 1
str = query_dialog_item( handle, IDE_TAGS_ADD_DIRS, DAC_TEXT )
path = buildpath( ltrim(trim(str)) )
if ( path && filemode(path) != -1 )
{
index = query_dialog_item( handle, IDL_TAGS_DIRS, DAC_FIND, path )
if ( index == -1 )
{
# get the index of the currently selected item
index = query_dialog_item( handle, IDL_TAGS_DIRS, DAC_SELECT_INDEX )
if ( index == -1 )
index = 0
# insert the new path before the currently selected item
set_dialog_item( handle, IDL_TAGS_DIRS, DAC_ADD_INDEX, path, index )
# reset index to the currently selected item
index = query_dialog_item( handle, IDL_TAGS_DIRS, DAC_FIND, path )
}
if ( index != -1 )
set_dialog_item( handle, IDL_TAGS_DIRS, DAC_SELECT_INDEX, index )
}
else
warning( "path %s is not valid", path )
pause_on_error = oldPE
set_dialog_item( handle, IDE_TAGS_ADD_DIRS, DAC_SETFOCUS )
set_dialog_item( handle, IDE_TAGS_ADD_DIRS, DAC_SELECTED_RANGE,
0, length(str) )
}
global function ctags_make_dialog()
{
local dlgHand = create_dialog( function_id("ctags_make_dialog_callback"), 0, IDD_CTAGS_MAKE )
set_dialog_item( dlgHand, IDE_TAGS_ADD_DIRS, DAC_SET_TEXT_LEN, 512 )
set_dialog_item( dlgHand, IDE_TAGS_OUTPUT_DIR, DAC_SET_TEXT_LEN, 512 )
set_dialog_item( dlgHand, IDE_TAGS_EXT_LIST, DAC_SET_TEXT_LEN, 512 )
begin_dialog( dlgHand )
delete_dialog(dlgHand)
}