remove debug fprintf
[nedit-bw.git] / matching_patterns.patch
blob0615d81e07ff2980e650c84438c788e48434cd0c
1 From: Uwe Lehnert <ulehnert@users.sourceforge.net>
2 Subject: Matching patterns (keyword matching)
4 Short feature description:
6 'Matching patterns' - in context of the patch - are defined as groups of single
7 characters (like '(', ')'), literal strings (like '#ifdef', '#endif') or even a
8 regular expression (like '\</.*\>', which match to each other.
10 A matching pattern set is a collection of such matching patterns.
12 'Opposite pattern highlighting' (aka 'flashing') or 'Goto Matching' feature are
13 adapted by above patch to use user defineable matching pattern sets i.s.o. a
14 constant table.
16 Alternative start / end patterns as well as 'middle' patterns are allowed
17 (Example 'C preprocessor conditional statement': Start = '#if' or '#ifndef' or
18 '#ifdef'; middle = '#elif' or '#else'; end = '#endif').
20 More info about the 'matching pattern' feature can be found
22 a.) 'FEATURE.txt' document (included in patch tar ball)
23 b.) by selecting menu item
25 'Help' -> 'Features for Programming' -> 'Matching Parentheses'
29 'Help' -> 'Customizing' -> 'Matching Patterns'
31 after patch was applied and NEdit was compiled of course :-)
33 File 'mp041114-V3-0.tar.gz' holds version 3.0 of the matching patterns (keyword
34 matching) patch.
36 Version 3.0 of the patch is based on nedit-5.5 (available at
37 ftp://ftp.nedit.org/pub/NEdit/v5_5/). README.txt (included in patch tar ball)
38 holds hints about how to apply the patch.
40 Changes since Version 2.1:
41 * Adaption of this patch to 'Tabbed Editing Interface'.
42 * New built-in macro subroutine 'get_matching' added.
43 * Bug fixes: NULL pointer exception corrected, if pull-down menu child widgets
44 were already destroyed.
45 * C / C++ pattern: #ifdef statement adapted - whitespaces after '#' are now
46 recognized.
47 * CSS pattern introduced.
48 * Sh Ksh Bash pattern: back quotes added.
49 * XML pattern completely revised.
50 * NEdit Macro pattern: single quotes & '/* .. */' comment removed.
52 ---
54 doc/help.etx | 258 +
55 source/Makefile.common | 4
56 source/Makefile.dependencies | 11
57 source/built-ins.h | 2
58 source/highlightData.c | 13
59 source/macro.c | 99
60 source/menu.c | 63
61 source/nedit.h | 6
62 source/patternMatch.c | 2202 ++++++++++++
63 source/patternMatch.h | 170
64 source/patternMatchData.c | 7780 +++++++++++++++++++++++++++++++++++++++++++
65 source/patternMatchData.h | 24
66 source/preferences.c | 167
67 source/preferences.h | 4
68 source/search.c | 231 -
69 source/smartIndent.c | 7
70 source/window.c | 18
71 17 files changed, 10765 insertions(+), 294 deletions(-)
73 diff --quilt old/doc/help.etx new/doc/help.etx
74 --- old/doc/help.etx
75 +++ new/doc/help.etx
76 @@ -866,8 +866,9 @@ Programming with NEdit
77 Though general in appearance, NEdit has many features intended specifically
78 for programmers. Major programming-related topics are listed in separate
79 sections under the heading: "Features for Programming": Syntax_Highlighting_,
80 - Tabs/Emulated_Tabs_, Finding_Declarations_(ctags)_, Calltips_, and
81 - Auto/Smart_Indent_. Minor topics related to programming are discussed below:
82 + Tabs/Emulated_Tabs_, Matching_Parentheses_, Finding_Declarations_(ctags)_,
83 + Calltips_, and Auto/Smart_Indent_. Minor topics related to programming are
84 + discussed below:
86 3>Language Modes
88 @@ -925,26 +926,6 @@ Programming with NEdit
89 a column on the current line just leave out the line number. (e.g. Enter
90 ",45" to go the column 45 on the current line.)
92 -3>Matching Parentheses
94 - To help you inspect nested parentheses, brackets, braces, quotes, and other
95 - characters, NEdit has both an automatic parenthesis matching mode, and a Goto
96 - Matching command. Automatic parenthesis matching is activated when you type,
97 - or move the insertion cursor after a parenthesis, bracket, or brace. It
98 - momentarily highlights either the opposite character ('Delimiter') or the
99 - entire expression ('Range') when the opposite character is visible in the
100 - window. To find a matching character anywhere in the file, select it or
101 - position the cursor after it, and choose Goto Matching from the Search menu.
102 - If the character matches itself, such as a quote or slash, select the first
103 - character of the pair. NEdit will match {, (, [, <, ", ', `, /, and \.
104 - Holding the Shift key while typing the accelerator key (Shift+Ctrl+M, by
105 - default), will select all of the text between the matching characters.
107 - When syntax highlighting is enabled, the matching routines can optionally
108 - make use of the syntax information for improved accuracy. In that case,
109 - a brace inside a highlighted string will not match a brace inside a comment,
110 - for instance.
112 3>Opening Included Files
114 The Open Selected command in the File menu understands the C preprocessor's
115 @@ -1222,6 +1203,39 @@ Syntax Highlighting
116 possible, but unlikely if you are only using the built-in patterns.
117 ----------------------------------------------------------------------
119 +Matching Parentheses
120 +--------------------
122 +3>Matching Parentheses (Patterns)
124 + To help you inspect nested parentheses (e.g. brackets, braces, quotes
125 + etc.) or nested constructs (e.g. "begin" .. "end"), NEdit has both an
126 + automatic parenthesis matching mode, and a Goto Matching command.
128 + A matching pattern can be a single character (like '(', ')'), a literal
129 + string (like '#ifdef', '#endif') or a regular expression (like
130 + '\</.*\>').
132 + Automatic parenthesis matching is activated when you type, or move the
133 + insertion cursor after a parenthesis, bracket, or brace. It momentarily
134 + highlights either the opposite pattern ('Delimiter') or the entire expression
135 + ('Range') when the opposite pattern is visible in the window. To find a
136 + matching pattern anywhere in the file, select it or position the cursor after
137 + it, and choose Goto Matching from the Search menu. If the pattern matches
138 + itself, such as a quote or slash, select the first pattern of the pair.
139 + Holding the Shift key while typing the accelerator key (Shift+Ctrl+M, by
140 + default), will select all of the text between the matching patterns.
142 + When syntax highlighting is enabled, the matching routines can optionally
143 + make use of the syntax information for improved accuracy. In that case,
144 + a brace inside a highlighted string will not match a brace inside a comment,
145 + for instance.
147 + Matching patterns are language dependent. Matching patterns can be
148 + configured by the user. If no matching patterns are available for the
149 + language that you want to use, you can create new patterns relatively quickly.
150 + The Help section "Matching_Patterns_" under "Customizing", has details.
152 Finding Declarations (ctags)
153 ----------------------------
155 @@ -2580,9 +2594,6 @@ Macro Subroutines
156 Contains the current preference for showing matching pairs,
157 such as "[]" and "{}" pairs. Can be "off", "delimiter", or "range".
159 -**$match_syntax_based**
160 - Whether pair matching should use syntax information, if available.
162 **$statistics_line**
163 Has a value of 1 if the statistics line is shown, otherwise 0.
165 @@ -2697,6 +2708,15 @@ Macro Subroutines
166 Returns the single character at the position
167 indicated by the first argument to the routine from the current window.
169 +**get_matching( position )**
170 + Find a matching pattern string related to the given position.
171 + Returns info about matching pattern within an array. The array has
172 + the following keys: **pos** (position of the first character of the
173 + matching pattern), **len** (length of the matching pattern), **direction**
174 + (direction where the matching pattern was found: ~0~ = forward;
175 + ~1~ = backward). If no matching pattern was found, then array element
176 + of **pos** holds ~-1~, **len** holds ~0~ and **direction** holds ~-1~.
178 **get_range( start, end )**
179 Returns the text between a starting and ending position from the current
180 window.
181 @@ -3406,9 +3426,6 @@ Action Routines
182 **set_show_matching( "off" | "delimiter" | "range" )**
183 Set show matching (...) mode for the current window.
185 -**set_match_syntax_based( [0 | 1] )**
186 - Set whether matching should be syntax based for the current window.
188 **set_statistics_line( [0 | 1] )**
189 Show or hide the statistics line for the current window.
190 A value of 0 turns it off and a value of 1 turns it on.
191 @@ -3944,10 +3961,6 @@ Preferences
192 matching delimiter, while Range highlights the whole range of text between
193 the matching delimiters.
195 - Optionally, the matching can make use of syntax information if syntax
196 - highlighting is enabled. Alternatively, the matching is purely character
197 - based. In general, syntax based matching results in fewer false matches.
199 **Overtype**
200 In overtype mode, new characters entered replace the characters in front of
201 the insertion cursor, rather than being inserted before them.
202 @@ -5053,6 +5066,185 @@ Smart Indent Macros
203 keystroke typed, so if you try to get too fancy, you may degrade performance.
204 ----------------------------------------------------------------------
206 +Matching Patterns
207 +-----------------
209 +3>Writing Matching Pattern Sets
211 + Matching Patterns Sets are groups of single characters (like '(', ')'),
212 + literal strings (like '#ifdef', '#endif') or a regular expressions (like
213 + '\</.*\>'), which match to each other.
215 + Examples: An open bracket '(' belongs a closing one ')'.
216 + Or: '#ifdef'(start), '#ifndef'(alternative start), '#ifndef' (another
217 + alternative start),'#elif' (optional), '#else' (optional), '#endif' (end)
218 + define a "#ifdef statement matching pattern".
220 + "Opposite pattern highlighting" or "Goto Matching" features are implemented
221 + in NEdit using this matching pattern sets (see Matching_Parentheses_ under
222 + the heading of Features for Programming).
224 + During definition of a new language mode a standard matching pattern set
225 + is assigned to this new language mode.
227 + To modify a matching pattern set, select "Matching Patterns ..." from
228 + "Show Matching (..)" sub-section of the "Default Settings" sub-menu
229 + of the "Preferences" menu.
231 + A matching pattern set is a collection of matching patterns.
233 + A matching pattern usually consists out of string patterns.
235 + The name of a matching pattern set needs to be defined within field "Matching
236 + Pattern Name".
238 +4>Attributes of matching pattern
240 + A matching pattern holds two types of attributes:
242 +* "Matching Pattern Type" and
243 +* "Global Attributes"
245 + The matching pattern type specifies the kind of the matching pattern
246 + entry:
248 +* "Individual" or
249 +* "Sub-pattern" or
250 +* "Context group"
252 + Each matching pattern can be defined as "Individual" or as "Sub-pattern".
253 + A "Sub-pattern" belongs to a context group. A context group is simply a
254 + collection of sub-patterns.
256 + During search for a corresponding pattern, an "Individual" matching pattern
257 + does not care about nesting of other matching patterns.
259 + If a matching pattern out of a "Context group" is searched, then all
260 + sub-pattern sets defined in this group are taken into account during the
261 + search.
263 + In fact, "Individual" matching pattern search is faster than "Context group" /
264 + "Sub-pattern" search. "Context group" / "Sub-pattern" search results in fewer
265 + false matches.
267 + To define a context group, set "Matching Pattern Type" to "Context group".
268 + Select out of "Sub-Pattern Name" pop-up field all sub-patterns, which
269 + should be placed into this group. **Note**: all "Sub-pattern" used by a context
270 + group must be defined **before** the context group itself.
272 + "Global Attributes" of a matching pattern are
274 +* "Skip content between start / end pattern"
275 +* "Flash matching pattern"
276 +* "Syntax based"
278 + If "Skip content between start / end pattern" is checked, then all text
279 + between the first / last string pattern of the related matching pattern is
280 + not scanned for other string patterns. This is useful for specifying comments.
282 + "Flash matching pattern" indicates, if the string patterns are flashed during
283 + typing. If not checked, then only the "Goto Matching" feature works for the
284 + related matching pattern. Note: if lots of "Flash matching pattern" are
285 + specified, then this may slow down the performance of NEdit: after each
286 + character typed all "Flash matching pattern" are scanned for being
287 + applicable ...
289 + "Syntax based" defines, if the matching pattern can make use of syntax
290 + information if syntax highlighting is enabled. Alternatively, the matching is
291 + purely character based. In general, syntax based matching results in fewer
292 + false matches.
294 +4>Content of matching pattern
296 + An "Individual" pattern or a "Sub-pattern" may consist out of only one string
297 + pattern (e.g. double quotes '"'). Such a pattern is called "mono pattern".
298 + You can imagine, that a match for a mono pattern is hard to find. A matching
299 + mono pattern search is always started in forward direction. If no match is
300 + found in forward direction, a backward search is started. If the "Global
301 + Attribute" "Syntax based" is selected for a mono pattern, then the character
302 + before / after the match is checked to have the same highlighting style than
303 + the pattern itself. This may help to determine the correct match for a mono
304 + pattern.
306 + Usually a matching pattern holds two string patterns (e.g. 'begin' and
307 + 'end'). One ('begin') is the start pattern. The other one ('end') is the
308 + end pattern. If the cursor is located behind the start pattern, then a
309 + corresponding end pattern is searched (in forward direction). If the
310 + cursor is located behind the end pattern, then a start pattern is search
311 + (in backward direction):
313 +! +--> start ---> end --+
314 +! +-----------<---------+
316 + Alternative start / end patterns can be defined. In this case one of the
317 + start / end patterns must be in front of the cursor to detect one of the
318 + related end / start patterns:
320 +! +-> start1 -+ +-> end1 -+
321 +! +-+-> start2 -+---+ +--+
322 +! + +-> start3 -+ +-> end2 -+ |
323 +! +---------------<-------------+
325 + At least also "middle" patterns can be defined (e.g. middle patterns
326 + 'elif' or 'else'). If the cursor is located behind a middle pattern then a
327 + next middle pattern or the end pattern is searched in forward direction:
329 +! +-----<-----+
330 +! +--> start -+-> middle -+-> end --+
331 +! +-----------<---------------------+
333 +4>String pattern
335 + A string pattern holds three attributes:
337 +* "String Pattern Type"
338 +* "Word Boundary"
339 +* "String Attributes"
341 + String Pattern Type specifies if the related string pattern is
342 + a "start", middle, or "end" pattern (see above).
344 + Word boundary defines, if before / after a string pattern a delimiter must be
345 + located ("Both" = pattern is framed by delimiters. "Left" = before pattern
346 + must be a delimiter. "Right" = after pattern must be a delimiter. "None" =
347 + there must be no delimiter before or after pattern).
349 + There are two "String Attributes":
351 +* "Case Sensitive"
352 +* "Regular Expression"
354 + If "Case Sensitive" is checked (= default), then the matching pattern search
355 + concerning this string pattern differs between upper / lower case of the
356 + characters. If "Case Sensitive" is not set, then the case of the checked
357 + characters is not considered.
359 + "Regular Expression" indicates, that string pattern is treated as
360 + regular expression (if "Regular Expression" is checked) or as literal
361 + string (if "Regular Expression" is not checked).
363 +4>Regular Expression String Pattern
365 + Syntax of regular expression is described by NEdit Help menu item
366 + Regular_Expressions_. Following deviations from this syntax are
367 + existing concerning string patterns:
369 +5>Capturing Parentheses
371 + Capturing Parentheses inside string patterns are of the form `(*n<regex>)',
372 + where n = 1 .. 9. Standard "capturing parentheses" of form `(<regex>)' are
373 + treated as "non-capturing parentheses" by the matching pattern feature.
374 + "n" defines the **global** backreference number, which can be used inside any string
375 + pattern of the same matching pattern (= set of string patterns). So
376 + matching patterns like "\<(*1[^/>])\>" (start string pattern) and "\</\1\>"
377 + (end string pattern) are possible. This matching pattern will match e.g.
378 + <body> .. </body> but will not match <body> .. </head>.
380 +5>Non-Capturing Parentheses
382 + As described above: parentheses constructs like (<regex>) are treated
383 + as `(?:<regex>)' (non-capturing parentheses) by the matching pattern feature.
385 NEdit Command Line
386 ------------------
388 @@ -6083,6 +6275,7 @@ Problems/Defects
389 .. Menu: Tabs/Emulated Tabs # tabs
390 .. Menu: Auto/Smart Indent # indent
391 .. Menu: Syntax Highlighting # syntax
392 +.. Menu: Matching Parentheses # pattern_matching
393 .. Menu: Finding Declarations (ctags) # tags
394 .. Menu: Calltips # calltips
396 @@ -6110,6 +6303,7 @@ Problems/Defects
397 .. Menu: Key Binding # binding
398 .. Menu: Highlighting Patterns # patterns
399 .. Menu: Smart Indent Macros # smart_indent
400 +.. Menu: Matching Patterns # matching_patterns
402 .. Menu: NEdit Command Line # command_line
403 .. Menu: Client/Server Mode # server
404 diff --quilt old/source/Makefile.common new/source/Makefile.common
405 --- old/source/Makefile.common
406 +++ new/source/Makefile.common
407 @@ -9,6 +9,7 @@ OBJS = nedit.o file.o menu.o window.o se
408 highlightData.o interpret.o parse.o smartIndent.o regexConvert.o \
409 rbTree.o windowTitle.o calltips.o server_common.o rangeset.o
410 OBJS += hooks.o
411 +OBJS += patternMatch.o patternMatchData.o
413 XLTLIB = ../Xlt/libXlt.a
414 XMLLIB = ../Microline/XmL/libXmL.a
415 @@ -38,6 +39,9 @@ smartIndent.o: smartIndent.c
416 highlightData.o: highlightData.c
417 $(CC) $(CFLAGS) $(BIGGER_STRINGS) -c highlightData.c -o $@
419 +patternMatchData.o: patternMatchData.c
420 + $(CC) $(CFLAGS) $(BIGGER_STRINGS) -c patternMatchData.c -o $@
422 clean:
423 rm -f $(OBJS) nedit nc nc.o parse.c parse_noyacc.c linkdate.o
425 diff --quilt old/source/Makefile.dependencies new/source/Makefile.dependencies
426 --- old/source/Makefile.dependencies
427 +++ new/source/Makefile.dependencies
428 @@ -87,3 +87,14 @@ windowTitle.o: windowTitle.c windowTitle
429 parse.c: parse.h textBuf.h nedit.h rbTree.h interpret.h ops.h
430 server.o file.o preferences.o selection.o window.o: hooks.h
431 hooks.o: hooks.c hooks.h macro.h
432 +patternMatch.o: patternMatch.c regularExp.h \
433 + textBuf.h search.h window.h preferences.h highlight.h\
434 + patternMatch.h patternMatchData.h
435 +patternMatchData.o: patternMatchData.c ../util/DialogF.h ../util/misc.h \
436 + ../util/managedList.h regularExp.h textBuf.h nedit.h window.h \
437 + preferences.h help.h file.h textP.h patternMatch.h patternMatchData.h
438 +macro.o: patternMatch.h regularExp.h
439 +menu.o: patternMatchData.h
440 +preferences.o: patternMatchData.h
441 +search.o: patternMatch.h
442 +window.o: patternMatchData.h
443 diff --quilt old/source/highlightData.c new/source/highlightData.c
444 --- old/source/highlightData.c
445 +++ new/source/highlightData.c
446 @@ -551,7 +551,7 @@ static char *DefaultPatternSets[] = {
447 Built-in Misc Vars:\"(?<!\\Y)\\$(?:active_pane|calltip_ID|column|cursor|display_width|empty_array|file_name|file_path|language_mode|line|locked|max_font_width|min_font_width|modified|n_display_lines|n_panes|rangeset_list|read_only|selection_(?:start|end|left|right)|server_name|text_length|top_line|transient|VERSION|NEDIT_HOME)>\":::Identifier::\n\
448 Built-in Pref Vars:\"(?<!\\Y)\\$(?:auto_indent|em_tab_dist|file_format|font_name|font_name_bold|font_name_bold_italic|font_name_italic|highlight_syntax|incremental_backup|incremental_search_line|make_backup_copy|match_syntax_based|overtype_mode|show_line_numbers|show_matching|statistics_line|tab_dist|use_tabs|wrap_margin|wrap_text)>\":::Identifier2::\n\
449 Built-in Special Vars:\"(?<!\\Y)\\$(?:args|[1-9]|list_dialog_button|n_args|read_status|search_end|shell_cmd_status|string_dialog_button|sub_sep)>\":::String1::\n\
450 - Built-in Subrs:\"<(?:args|append_file|beep|call|calltip|clipboard_to_string|dialog|filename_dialog|focus_window|get_character|get_pattern_(by_name|at_pos)|get_range|get_selection|get_style_(by_name|at_pos)|getenv|highlight_calltip_line|kill_calltip|length|list_dialog|max|min|n_args|rangeset_(?:add|create|destroy|get_by_name|includes|info|invert|range|set_color|set_mode|set_name|subtract)|read_file|replace_in_string|replace_range|replace_selection|replace_substring|search|search_string|select|select_rectangle|set_cursor_pos|set_transient|shell_command|split|string_compare|string_dialog|string_to_clipboard|substring|t_print|tolower|toupper|valid_number|write_file)(?=\\s*\\()\":::Subroutine::\n\
451 + Built-in Subrs:\"<(?:args|append_file|beep|call|calltip|clipboard_to_string|dialog|filename_dialog|focus_window|get_character|get_matching|get_pattern_(by_name|at_pos)|get_range|get_selection|get_style_(by_name|at_pos)|getenv|highlight_calltip_line|kill_calltip|length|list_dialog|max|min|n_args|rangeset_(?:add|create|destroy|get_by_name|includes|info|invert|range|set_color|set_mode|set_name|subtract)|read_file|replace_in_string|replace_range|replace_selection|replace_substring|search|search_string|select|select_rectangle|set_cursor_pos|set_transient|shell_command|split|string_compare|string_dialog|string_to_clipboard|substring|t_print|tolower|toupper|valid_number|write_file)(?=\\s*\\()\":::Subroutine::\n\
452 Menu Actions:\"<(?:new(?:_tab|_opposite)?|open|open-dialog|open_dialog|open-selected|open_selected|close|save|save-as|save_as|save-as-dialog|save_as_dialog|revert-to-saved|revert_to_saved|revert_to_saved_dialog|include-file|include_file|include-file-dialog|include_file_dialog|load-macro-file|load_macro_file|load-macro-file-dialog|load_macro_file_dialog|load-tags-file|load_tags_file|load-tags-file-dialog|load_tags_file_dialog|unload_tags_file|load_tips_file|load_tips_file_dialog|unload_tips_file|print|print-selection|print_selection|exit|undo|redo|delete|select-all|select_all|shift-left|shift_left|shift-left-by-tab|shift_left_by_tab|shift-right|shift_right|shift-right-by-tab|shift_right_by_tab|find|find-dialog|find_dialog|find-again|find_again|find-selection|find_selection|find_incremental|start_incremental_find|replace|replace-dialog|replace_dialog|replace-all|replace_all|replace-in-selection|replace_in_selection|replace-again|replace_again|replace_find|replace_find_same|replace_find_again|goto-line-number|goto_line_number|goto-line-number-dialog|goto_line_number_dialog|goto-selected|goto_selected|mark|mark-dialog|mark_dialog|goto-mark|goto_mark|goto-mark-dialog|goto_mark_dialog|match|select_to_matching|goto_matching|find-definition|find_definition|show_tip|split-pane|split_pane|close-pane|close_pane|detach_document(?:_dialog)?|move_document_dialog|(?:next|previous|last)_document|uppercase|lowercase|fill-paragraph|fill_paragraph|control-code-dialog|control_code_dialog|filter-selection-dialog|filter_selection_dialog|filter-selection|filter_selection|execute-command|execute_command|execute-command-dialog|execute_command_dialog|execute-command-line|execute_command_line|shell-menu-command|shell_menu_command|macro-menu-command|macro_menu_command|bg_menu_command|post_window_bg_menu|post_tab_context_menu|beginning-of-selection|beginning_of_selection|end-of-selection|end_of_selection|repeat_macro|repeat_dialog|raise_window|focus_pane|set_statistics_line|set_incremental_search_line|set_show_line_numbers|set_auto_indent|set_wrap_text|set_wrap_margin|set_highlight_syntax|set_make_backup_copy|set_incremental_backup|set_show_matching|set_match_syntax_based|set_overtype_mode|set_locked|set_tab_dist|set_em_tab_dist|set_use_tabs|set_fonts|set_language_mode)(?=\\s*\\()\":::Subroutine::\n\
453 Text Actions:\"<(?:self-insert|self_insert|grab-focus|grab_focus|extend-adjust|extend_adjust|extend-start|extend_start|extend-end|extend_end|secondary-adjust|secondary_adjust|secondary-or-drag-adjust|secondary_or_drag_adjust|secondary-start|secondary_start|secondary-or-drag-start|secondary_or_drag_start|process-bdrag|process_bdrag|move-destination|move_destination|move-to|move_to|move-to-or-end-drag|move_to_or_end_drag|end_drag|copy-to|copy_to|copy-to-or-end-drag|copy_to_or_end_drag|exchange|process-cancel|process_cancel|paste-clipboard|paste_clipboard|copy-clipboard|copy_clipboard|cut-clipboard|cut_clipboard|copy-primary|copy_primary|cut-primary|cut_primary|newline|newline-and-indent|newline_and_indent|newline-no-indent|newline_no_indent|delete-selection|delete_selection|delete-previous-character|delete_previous_character|delete-next-character|delete_next_character|delete-previous-word|delete_previous_word|delete-next-word|delete_next_word|delete-to-start-of-line|delete_to_start_of_line|delete-to-end-of-line|delete_to_end_of_line|forward-character|forward_character|backward-character|backward_character|key-select|key_select|process-up|process_up|process-down|process_down|process-shift-up|process_shift_up|process-shift-down|process_shift_down|process-home|process_home|forward-word|forward_word|backward-word|backward_word|forward-paragraph|forward_paragraph|backward-paragraph|backward_paragraph|beginning-of-line|beginning_of_line|end-of-line|end_of_line|beginning-of-file|beginning_of_file|end-of-file|end_of_file|next-page|next_page|previous-page|previous_page|page-left|page_left|page-right|page_right|toggle-overstrike|toggle_overstrike|scroll-up|scroll_up|scroll-down|scroll_down|scroll_left|scroll_right|scroll-to-line|scroll_to_line|select-all|select_all|deselect-all|deselect_all|focusIn|focusOut|process-return|process_return|process-tab|process_tab|insert-string|insert_string|mouse_pan)(?=\\s*\\()\":::Subroutine::\n\
454 Macro Hooks:\"<(?:(?:pre|post)_(?:open|save)|cursor_moved|modified|(?:losing_)?focus|language_mode)_hook(?=\\s*\\()\":::Subroutine1::\n\
455 @@ -2346,8 +2346,9 @@ void EditHighlightPatterns(WindowInfo *w
456 XmNrightPosition, 99,
457 NULL);
459 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
460 HighlightDialog.lmPulldown = CreateLanguageModeMenu(lmForm, langModeCB,
461 - NULL);
462 + NULL, FALSE);
463 n = 0;
464 XtSetArg(args[n], XmNspacing, 0); n++;
465 XtSetArg(args[n], XmNmarginWidth, 0); n++;
466 @@ -2881,8 +2882,9 @@ void UpdateLanguageModeMenu(void)
467 return;
469 oldMenu = HighlightDialog.lmPulldown;
470 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
471 HighlightDialog.lmPulldown = CreateLanguageModeMenu(
472 - XtParent(XtParent(oldMenu)), langModeCB, NULL);
473 + XtParent(XtParent(oldMenu)), langModeCB, NULL, FALSE);
474 XtVaSetValues(XmOptionButtonGadget(HighlightDialog.lmOptMenu),
475 XmNsubMenuId, HighlightDialog.lmPulldown, NULL);
476 SetLangModeMenu(HighlightDialog.lmOptMenu, HighlightDialog.langModeName);
477 @@ -2941,6 +2943,9 @@ static void langModeCB(Widget w, XtPoint
479 SetLangModeMenu(HighlightDialog.lmOptMenu,
480 HighlightDialog.langModeName);
482 + freePatternSet(newPatSet);
484 return;
486 if (resp == 1)
487 @@ -3040,6 +3045,8 @@ static void restoreCB(Widget w, XtPointe
488 "patterns for language mode %s?", "Discard", "Cancel",
489 HighlightDialog.langModeName) == 2)
491 + freePatternSet(defaultPatSet);
493 return;
496 diff --quilt old/source/macro.c new/source/macro.c
497 --- old/source/macro.c
498 +++ new/source/macro.c
499 @@ -57,6 +57,8 @@ static const char CVSID[] = "$Id: macro.
500 #include "highlight.h"
501 #include "highlightData.h"
502 #include "rangeset.h"
503 +#include "patternMatch.h"
504 +#include "regularExp.h"
506 #include <stdio.h>
507 #include <stdlib.h>
508 @@ -4217,16 +4219,6 @@ static int showMatchingMV(WindowInfo *wi
509 return True;
512 -static int matchSyntaxBasedMV(WindowInfo *window, DataValue *argList, int nArgs,
513 - DataValue *result, char **errMsg)
515 - result->tag = INT_TAG;
516 - result->val.n = window->matchSyntaxBased ? 1 : 0;
517 - return True;
522 static int overTypeModeMV(WindowInfo *window, DataValue *argList, int nArgs,
523 DataValue *result, char **errMsg)
525 @@ -5627,6 +5619,93 @@ static int getPatternAtPosMS(WindowInfo
526 HighlightStyleOfCode(window, patCode), bufferPos);
530 +** Pattern Match Feature:
531 +** Find a matching pattern string related to the given position.
533 +** Syntax:
534 +** get_matching(position)
536 +** Returns info about matching pattern within an array. The array has
537 +** the following keys: "pos" (position of the first character of the
538 +** matching pattern), "len" (length of the matching pattern), "direction"
539 +** (direction where the matching pattern was found: "0" = forward;
540 +** "1" = backward). If no matching pattern was found, then array element
541 +** of "pos" holds "-1", "len" holds "0" and "direction" holds "-1".
544 +static int getMatchingMS(WindowInfo *window, DataValue *argList, int nArgs,
545 + DataValue *result, char **errMsg)
547 + int startPos;
548 + int matchPos, matchLen;
549 + int direction;
550 + textBuffer *buf = window->buffer;
551 + DataValue dv;
553 + /*
554 + * Perform syntax & semantic check
555 + */
556 + if (nArgs != 1 )
557 + return wrongNArgsErr(errMsg);
559 + if (!readIntArg(argList[0], &startPos, errMsg))
560 + return False;
562 + startPos ++;
564 + /*
565 + * do the search; provide default values, if search fails
566 + */
567 + if (!FindMatchingString(window, MT_MACRO, &startPos, 0, buf->length,
568 + &matchPos, &matchLen, &direction))
570 + matchPos = -1;
571 + matchLen = 0;
572 + direction = -1;
575 + /*
576 + * initialize array holding info about matching string
577 + */
578 + result->tag = ARRAY_TAG;
579 + result->val.arrayPtr = ArrayNew();
581 + /*
582 + * the following array entries will be integers
583 + */
584 + dv.tag = INT_TAG;
586 + /*
587 + * insert match position
588 + */
589 + dv.val.n = matchPos;
590 + if (!ArrayInsert(result, PERM_ALLOC_STR("pos"), &dv))
592 + M_ARRAY_INSERT_FAILURE();
595 + /*
596 + * insert length of matching pattern
597 + */
598 + dv.val.n = matchLen;
599 + if (!ArrayInsert(result, PERM_ALLOC_STR("len"), &dv))
601 + M_ARRAY_INSERT_FAILURE();
604 + /*
605 + * insert direction where the matching pattern was found
606 + */
607 + dv.val.n = direction;
608 + if (!ArrayInsert(result, PERM_ALLOC_STR("direction"), &dv))
610 + M_ARRAY_INSERT_FAILURE();
613 + return True;
616 static int wrongNArgsErr(char **errMsg)
618 *errMsg = "Wrong number of arguments to function %s";
619 diff --quilt old/source/menu.c new/source/menu.c
620 --- old/source/menu.c
621 +++ new/source/menu.c
622 @@ -49,6 +49,7 @@ static const char CVSID[] = "$Id: menu.c
623 #include "macro.h"
624 #include "highlight.h"
625 #include "highlightData.h"
626 +#include "patternMatchData.h"
627 #include "interpret.h"
628 #include "smartIndent.h"
629 #include "windowTitle.h"
630 @@ -134,7 +135,6 @@ static void backlightCharsCB(Widget w, W
631 static void showMatchingOffCB(Widget w, WindowInfo *window, caddr_t callData);
632 static void showMatchingDelimitCB(Widget w, WindowInfo *window, caddr_t callData);
633 static void showMatchingRangeCB(Widget w, WindowInfo *window, caddr_t callData);
634 -static void matchSyntaxBasedCB(Widget w, WindowInfo *window, caddr_t callData);
635 static void statsCB(Widget w, WindowInfo *window, caddr_t callData);
636 static void autoIndentOffDefCB(Widget w, WindowInfo *window, caddr_t callData);
637 static void autoIndentDefCB(Widget w, WindowInfo *window, caddr_t callData);
638 @@ -161,9 +161,9 @@ static void tabsDefCB(Widget w, WindowIn
639 static void showMatchingOffDefCB(Widget w, WindowInfo *window, caddr_t callData);
640 static void showMatchingDelimitDefCB(Widget w, WindowInfo *window, caddr_t callData);
641 static void showMatchingRangeDefCB(Widget w, WindowInfo *window, caddr_t callData);
642 -static void matchSyntaxBasedDefCB(Widget w, WindowInfo *window, caddr_t callData);
643 static void highlightOffDefCB(Widget w, WindowInfo *window, caddr_t callData);
644 static void highlightDefCB(Widget w, WindowInfo *window, caddr_t callData);
645 +static void matchPatternsDefCB(Widget w, WindowInfo *window, caddr_t callData);
646 static void backlightCharsDefCB(Widget w, WindowInfo *window, caddr_t callData);
647 static void fontDefCB(Widget w, WindowInfo *window, caddr_t callData);
648 static void colorDefCB(Widget w, WindowInfo *window, caddr_t callData);
649 @@ -410,8 +410,6 @@ static void setIncrementalBackupAP(Widge
650 Cardinal *nArgs);
651 static void setShowMatchingAP(Widget w, XEvent *event, String *args,
652 Cardinal *nArgs);
653 -static void setMatchSyntaxBasedAP(Widget w, XEvent *event, String *args,
654 - Cardinal *nArgs);
655 static void setOvertypeModeAP(Widget w, XEvent *event, String *args,
656 Cardinal *nArgs);
657 static void setLockedAP(Widget w, XEvent *event, String *args,
658 @@ -585,7 +583,6 @@ static XtActionsRec Actions[] = {
659 #endif
660 {"set_incremental_backup", setIncrementalBackupAP},
661 {"set_show_matching", setShowMatchingAP},
662 - {"set_match_syntax_based", setMatchSyntaxBasedAP},
663 {"set_overtype_mode", setOvertypeModeAP},
664 {"set_locked", setLockedAP},
665 {"set_transient", setTransientAP},
666 @@ -1031,9 +1028,8 @@ Widget CreateMenuBar(Widget parent, Wind
667 "range", "Range", 'R', showMatchingRangeDefCB, window,
668 GetPrefShowMatching() == FLASH_RANGE, SHORT);
669 createMenuSeparator(subSubPane, "sep", SHORT);
670 - window->matchSyntaxBasedDefItem = createMenuToggle(subSubPane,
671 - "matchSyntax", "Syntax Based", 'S', matchSyntaxBasedDefCB, window,
672 - GetPrefMatchSyntaxBased(), SHORT);
673 + createMenuItem(subSubPane, "matchPatterns", "Matching Patterns...",
674 + 'M', matchPatternsDefCB, window, FULL);
676 /* Show Cursorline */
677 window->showCursorlineItem = createMenuToggle(subPane,
678 @@ -1155,10 +1151,6 @@ Widget CreateMenuBar(Widget parent, Wind
679 window->showMatchingRangeItem = createMenuRadioToggle(subPane, "range",
680 "Range", 'R', showMatchingRangeCB, window,
681 window->showMatchingStyle == FLASH_RANGE, SHORT);
682 - createMenuSeparator(subPane, "sep", SHORT);
683 - window->matchSyntaxBasedItem = createMenuToggle(subPane, "matchSyntax",
684 - "Syntax Based", 'S', matchSyntaxBasedCB, window,
685 - window->matchSyntaxBased, SHORT);
687 #ifndef SGI_CUSTOM
688 createMenuSeparator(menuPane, "sep2", SHORT);
689 @@ -1690,24 +1682,6 @@ static void showMatchingRangeCB(Widget w
690 ((XmAnyCallbackStruct *)callData)->event, params, 1);
693 -static void matchSyntaxBasedCB(Widget w, WindowInfo *window, caddr_t callData)
695 - Widget menu = MENU_WIDGET(w);
697 - window = WidgetToWindow(menu);
699 -#ifdef SGI_CUSTOM
700 - if (shortPrefAskDefault(window->shell, w, "Match Syntax Based")) {
701 - matchSyntaxBasedDefCB(w, window, callData);
702 - SaveNEditPrefs(window->shell, GetPrefShortMenus());
704 -#endif
705 - HidePointerOnKeyedEvent(WidgetToWindow(menu)->lastFocus,
706 - ((XmAnyCallbackStruct *)callData)->event);
707 - XtCallActionProc(WidgetToWindow(menu)->lastFocus, "set_match_syntax_based",
708 - ((XmAnyCallbackStruct *)callData)->event, NULL, 0);
711 static void fontCB(Widget w, WindowInfo *window, caddr_t callData)
713 ChooseFonts(WidgetToWindow(MENU_WIDGET(w)), True);
714 @@ -2035,18 +2009,14 @@ static void showMatchingRangeDefCB(Widge
718 -static void matchSyntaxBasedDefCB(Widget w, WindowInfo *window, caddr_t callData)
719 +static void matchPatternsDefCB(Widget w, WindowInfo *window, caddr_t callData)
721 - WindowInfo *win;
723 - int state = XmToggleButtonGetState(w);
724 + Widget menu = MENU_WIDGET(w);
725 + WindowInfo *activeWindow = WidgetToWindow(menu);
727 - /* Set the preference and make the other windows' menus agree */
728 - SetPrefMatchSyntaxBased(state);
729 - for (win=WindowList; win!=NULL; win=win->next) {
730 - if (IsTopDocument(win))
731 - XmToggleButtonSetState(win->matchSyntaxBasedDefItem, state, False);
733 + HidePointerOnKeyedEvent(activeWindow->lastFocus,
734 + ((XmAnyCallbackStruct *)callData)->event);
735 + EditMatchPatterns(activeWindow);
738 static void backlightCharsDefCB(Widget w, WindowInfo *window, caddr_t callData)
739 @@ -4267,19 +4237,6 @@ static void setShowMatchingAP(Widget w,
743 -static void setMatchSyntaxBasedAP(Widget w, XEvent *event, String *args,
744 - Cardinal *nArgs)
746 - WindowInfo *window = WidgetToWindow(w);
747 - Boolean newState;
749 - ACTION_BOOL_PARAM_OR_TOGGLE(newState, *nArgs, args, window->matchSyntaxBased, "set_match_syntax_based");
751 - if (IsTopDocument(window))
752 - XmToggleButtonSetState(window->matchSyntaxBasedItem, newState, False);
753 - window->matchSyntaxBased = newState;
756 static void setOvertypeModeAP(Widget w, XEvent *event, String *args,
757 Cardinal *nArgs)
759 diff --quilt old/source/nedit.h new/source/nedit.h
760 --- old/source/nedit.h
761 +++ new/source/nedit.h
762 @@ -366,7 +366,6 @@ typedef struct _WindowInfo {
763 Widget showMatchingOffItem;
764 Widget showMatchingDelimitItem;
765 Widget showMatchingRangeItem;
766 - Widget matchSyntaxBasedItem;
767 Widget overtypeModeItem;
768 Widget highlightItem;
769 Widget windowMenuPane;
770 @@ -392,7 +391,6 @@ typedef struct _WindowInfo {
771 Widget showMatchingOffDefItem;
772 Widget showMatchingDelimitDefItem;
773 Widget showMatchingRangeDefItem;
774 - Widget matchSyntaxBasedDefItem;
775 Widget highlightOffDefItem;
776 Widget highlightDefItem;
777 Widget backlightCharsItem;
778 @@ -512,7 +510,6 @@ typedef struct _WindowInfo {
779 char showMatchingStyle; /* How to show matching parens:
780 NO_FLASH, FLASH_DELIMIT, or
781 FLASH_RANGE */
782 - char matchSyntaxBased; /* Use syntax info to show matching */
783 Boolean showStats; /* is stats line supposed to be shown */
784 Boolean showISearchLine; /* is incr. search line to be shown */
785 Boolean showLineNumbers; /* is the line number display shown */
786 @@ -558,6 +555,9 @@ typedef struct _WindowInfo {
787 Bool findLastRegexCase; /* idem, for regex mode in find dialog */
788 Bool findLastLiteralCase; /* idem, for literal mode */
790 + /* Pattern Match Feature */
791 + void *stringMatchTable; /* match pattern info related to this window */
793 #ifdef REPLACE_SCOPE
794 int replaceScope; /* Current scope for replace dialog */
795 Widget replaceScopeWinToggle; /* Scope for replace = window */
796 diff --quilt /dev/null new/source/patternMatch.c
797 --- /dev/null
798 +++ new/source/patternMatch.c
799 @@ -0,0 +1,2202 @@
800 +static const char CVSID[] = "$Id: patternMatch.c,v 1.4 2003/10/27 21:59:14 uleh Exp $";
801 +/*******************************************************************************
802 +* *
803 +* patternMatch.c -- Nirvana Editor pattern matching functions *
804 +* *
805 +* Copyright (C) 2003-2004, Uwe Lehnert *
806 +* *
807 +* This is free software; you can redistribute it and/or modify it under the *
808 +* terms of the GNU General Public License as published by the Free Software *
809 +* Foundation; either version 2 of the License, or (at your option) any later *
810 +* version. In addition, you may distribute versions of this program linked to *
811 +* Motif or Open Motif. See README for details. *
812 +* *
813 +* This software is distributed in the hope that it will be useful, but WITHOUT *
814 +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
815 +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
816 +* for more details. *
817 +* *
818 +* You should have received a copy of the GNU General Public License along with *
819 +* software; if not, write to the Free Software Foundation, Inc., 59 Temple *
820 +* Place, Suite 330, Boston, MA 02111-1307 USA *
821 +* *
822 +* Nirvana Text Editor *
823 +* October 27, 2004 *
824 +* *
825 +* Written by Uwe Lehnert *
826 +* *
827 +*******************************************************************************/
829 +#ifdef HAVE_CONFIG_H
830 +#include "../config.h"
831 +#endif
833 +#include <stdlib.h>
834 +#include <stdio.h>
835 +#include <limits.h>
836 +#include <string.h>
837 +#include <ctype.h>
839 +#ifdef VMS
840 +#include "../util/VMSparam.h"
841 +#else
842 +#ifndef __MVS__
843 +#include <sys/param.h>
844 +#endif
845 +#endif /*VMS*/
847 +#include "regularExp.h"
848 +#include "textBuf.h"
849 +#include "search.h"
850 +#include "window.h"
851 +#include "preferences.h"
852 +#include "highlight.h"
854 +#include "patternMatch.h"
855 +#include "patternMatchData.h"
857 +#ifdef HAVE_DEBUG_H
858 +#include "../debug.h"
859 +#endif
861 +#define MAX_NESTED_PATTERNS 100
863 +#define IGNORE_HIGHLIGHT_CODE -1
865 +typedef struct _SearchRegionInfo {
866 + WindowInfo *sriWindow;
867 + char *sriText;
868 + char sriPrevChar;
869 + char sriSuccChar;
870 + int sriStartOfTextPos;
871 +} SearchRegionInfo;
873 +typedef struct _FoundStringInfo {
874 + char *fsiStartPtr;
875 + char *fsiEndPtr;
876 + int fsiLength;
877 + char fsiPrevChar;
878 + char fsiSuccChar;
879 + const char *fsiDelimiters;
880 +} FoundStringInfo;
882 +typedef struct _BackRefInfo {
883 + int briAvailable;
884 + int briCaseInsensitive;
885 + char *briStartPtr[MAX_GLOBAL_BACK_REF_ID];
886 + char *briEndPtr[MAX_GLOBAL_BACK_REF_ID];
887 +} BackRefInfo;
889 +typedef struct _MatchingElementInfo {
890 + MatchPatternTableElement *meiElement;
891 + PatternReference meiPatRef;
892 + int meiDirection;
893 + int meiHighLightCode;
894 + int meiAbsStartPos;
895 + int meiLength;
896 + BackRefInfo meiBackRefInfo;
897 +} MatchingElementInfo;
899 +typedef struct _PatternStackElement {
900 + PatternReference psePatRef;
901 + int pseHighLightCode;
902 + BackRefInfo pseBackRefInfo;
903 +} PatternStackElement;
906 + * Prototypes of local functions
907 + */
908 +void adaptPatternPositions(
909 + MatchingType matchingType,
910 + int direction,
911 + int *charPos,
912 + int startPatternLength,
913 + int *matchPos,
914 + int matchedPatternLength);
916 +static int findMatchingStringElement(
917 + StringMatchTable *smTable,
918 + SearchRegionInfo *searchRegion,
919 + MatchingElementInfo *matchInfo,
920 + int *charPos,
921 + const char *delimiters);
923 +static PatternElementMonoInfo determineMonoPatInfo(
924 + WindowInfo *window,
925 + int patHighLightCode,
926 + int leftPos,
927 + int rightPos,
928 + PatternElementKind *patElementKind);
930 +static void assignBackRefInfo(
931 + StringPattern *strPat,
932 + BackRefInfo *backRefInfo);
933 +static int doesBackRefInfoMatch(
934 + BackRefInfo *backRefInfo1,
935 + BackRefInfo *backRefInfo2);
936 +static int compareBackRef(
937 + char *startPtr1,
938 + char *endPtr1,
939 + char *startPtr2,
940 + char *endPtr2,
941 + int caseInsensitive);
943 +static int doesPatternElementMatch(
944 + PatternElement *patElement,
945 + FoundStringInfo *foundStringInfo,
946 + BackRefInfo *backRefInfo);
947 +static int doesMPTableElementMatch(
948 + MatchPatternTableElement *element,
949 + FoundStringInfo *foundStringInfo,
950 + PatternElementKind *patternElementKind,
951 + int *patternElementIdx,
952 + BackRefInfo *backRefInfo);
953 +static int getPatternInfo(
954 + MatchPatternTable *table,
955 + FoundStringInfo *foundStringInfo,
956 + PatternReference *patRef,
957 + BackRefInfo *backRefInfo);
959 +static int isPartOfPattern(
960 + MatchPatternTable *table,
961 + int parentElementIdx,
962 + int childElementIdx,
963 + PatternElementKind patElementKind);
964 +static int isPartOfPatternElementSet(
965 + PatternElementSet *patElementSet,
966 + int patternElementIdx);
967 +static int isPartOfMiddlePatternElementSet(
968 + PatternElementSet *patElementSet,
969 + int patternElementIdx);
970 +static void considerNextPatternReference(
971 + MatchPatternTable *table,
972 + PatternReference *startPatRef,
973 + PatternReference nxtPatRef,
974 + int groupIdx);
976 +static int searchPatternForward(
977 + MatchPatternTable *table,
978 + regexp *compiledRE,
979 + SearchRegionInfo *searchRegion,
980 + const char *delimiters,
981 + int beginPos,
982 + int *matchEndPos,
983 + PatternReference *patRef,
984 + int *highLightCode,
985 + BackRefInfo *backRefInfo);
986 +static int searchPatternBackward(
987 + MatchPatternTable *table,
988 + regexp *compiledRE,
989 + SearchRegionInfo *searchRegion,
990 + const char *delimiters,
991 + int beginPos,
992 + PatternReference *patRef,
993 + int *highLightCode,
994 + int *matchedPatternLength,
995 + BackRefInfo *backRefInfo);
997 +static int parseStringElementForward(
998 + MatchingElementInfo *matchInfo,
999 + SearchRegionInfo *searchRegion,
1000 + int relCharPos,
1001 + int *matchPos,
1002 + int *matchedPatternLength,
1003 + const char *delimiters);
1004 +static int findRelatedForwardPattern(
1005 + StringMatchTable *table,
1006 + SearchRegionInfo *searchRegion,
1007 + const char *delimiters,
1008 + PatternReference beginPatRef,
1009 + int beginPatHighLightCode,
1010 + BackRefInfo *beginPatBackRefInfo,
1011 + int beginPos,
1012 + int *matchEndPos);
1014 +static int parseStringElementBackward(
1015 + MatchingElementInfo *matchInfo,
1016 + SearchRegionInfo *searchRegion,
1017 + int relCharPos,
1018 + int *matchPos,
1019 + int *matchedPatternLength,
1020 + const char *delimiters);
1021 +static int findRelatedStartPattern(
1022 + StringMatchTable *table,
1023 + SearchRegionInfo *searchRegion,
1024 + const char *delimiters,
1025 + PatternReference beginPatRef,
1026 + int beginPatHighLightCode,
1027 + BackRefInfo *beginPatBackRefInfo,
1028 + int beginPos,
1029 + int *matchedPatternLength);
1030 +static void considerStackPatReference(
1031 + PatternElementSet *patSet,
1032 + int stackElementIdx,
1033 + int *foundElementIdx);
1035 +static int getPatternLocatedAtPos(
1036 + regexp *usedPatRE,
1037 + MatchPatternTable *table,
1038 + SearchRegionInfo *searchRegion,
1039 + int *relBeginPos,
1040 + MatchingElementInfo *matchInfo,
1041 + const char *delimiters);
1042 +static int getMatchedElementInfo(
1043 + WindowInfo *window,
1044 + MatchPatternTable *table,
1045 + FoundStringInfo *foundStringInfo,
1046 + MatchingElementInfo *matchInfo);
1048 +static PatternElement *getPatternOfReference(
1049 + MatchPatternTable *table,
1050 + PatternReference patRef);
1052 +#ifdef DEBUG_FIND
1053 +static char *getPatternForDebug(
1054 + MatchPatternTable *table,
1055 + PatternReference patRef );
1056 +static char *patElemKindToString(
1057 + PatternElementKind patElemKind);
1058 +static void printFoundStringForDebug(
1059 + WindowInfo *window,
1060 + int absStartPos,
1061 + int length);
1062 +#endif
1065 +** Try to find a matching pattern string related to the given "charPos"
1066 +** inside the given range (defined by startLimit & endLimit).
1067 +** Determine the matching position & the match pattern length (depending
1068 +** on given matchingType), if a matching pattern was found.
1069 +** Returns true, if a matching pattern string was found.
1071 +int FindMatchingString(
1072 + WindowInfo *window,
1073 + MatchingType matchingType,
1074 + int *charPos,
1075 + int startLimit,
1076 + int endLimit,
1077 + int *matchPos,
1078 + int *matchedPatternLength,
1079 + int *direction)
1081 + StringMatchTable *smTable = (StringMatchTable *)window->stringMatchTable;
1082 + const char *delimiters;
1083 + SearchRegionInfo searchRegion;
1084 + MatchingElementInfo matchInfo;
1085 + int matchingPatternFound = FALSE;
1086 + int relCharPos;
1088 + if (smTable == NULL || smTable->smtAllPatRE == NULL)
1090 + /*
1091 + * No match pattern table available:
1092 + */
1093 + return FALSE;
1096 + /*
1097 + * Get delimiters related to window
1098 + */
1099 + delimiters = GetWindowDelimiters(window);
1100 + if (delimiters == NULL)
1101 + delimiters = GetPrefDelimiters();
1103 + /*
1104 + * Select the start pattern reg. exp. to use
1105 + */
1106 + if (matchingType == MT_FLASH_RANGE ||
1107 + matchingType == MT_FLASH_DELIMIT)
1109 + smTable->smtUsedPatRE = smTable->smtFlashPatRE;
1111 + else
1113 + smTable->smtUsedPatRE = smTable->smtAllPatRE;
1116 + /*
1117 + * Get a copy of the text buffer area to parse
1118 + */
1119 + searchRegion.sriWindow = window;
1120 + searchRegion.sriText = BufGetRange(window->buffer, startLimit, endLimit);
1121 + searchRegion.sriPrevChar = BufGetCharacter(window->buffer, startLimit - 1);
1122 + searchRegion.sriSuccChar = BufGetCharacter(window->buffer, endLimit);
1123 + searchRegion.sriStartOfTextPos = startLimit;
1125 + relCharPos = *charPos - startLimit;
1127 + /*
1128 + * Try to find a matching pattern string using string match table
1129 + * of window
1130 + */
1131 + if (findMatchingStringElement(
1132 + smTable,
1133 + &searchRegion,
1134 + &matchInfo,
1135 + &relCharPos,
1136 + delimiters ))
1138 +#ifdef DEBUG_FIND
1139 + printf("--- Start at : ");
1140 + printFoundStringForDebug(
1141 + window,
1142 + matchInfo.meiAbsStartPos,
1143 + matchInfo.meiLength);
1144 + printf(" ---\n");
1145 +#endif
1146 + if (matchInfo.meiDirection == SEARCH_FORWARD)
1148 + matchingPatternFound =
1149 + parseStringElementForward(
1150 + &matchInfo,
1151 + &searchRegion,
1152 + relCharPos,
1153 + matchPos,
1154 + matchedPatternLength,
1155 + delimiters );
1157 + else
1159 + matchingPatternFound =
1160 + parseStringElementBackward(
1161 + &matchInfo,
1162 + &searchRegion,
1163 + relCharPos,
1164 + matchPos,
1165 + matchedPatternLength,
1166 + delimiters );
1169 + if (matchingPatternFound)
1171 + /*
1172 + * Calc. abs. start char pos. (may have been changed if
1173 + * cursor was located inside a string pattern). Adapt
1174 + * pattern positions depending on matchingType.
1175 + */
1176 + *charPos = relCharPos + startLimit;
1177 + *direction = matchInfo.meiDirection;
1179 + adaptPatternPositions(
1180 + matchingType,
1181 + matchInfo.meiDirection,
1182 + charPos,
1183 + matchInfo.meiLength,
1184 + matchPos,
1185 + *matchedPatternLength);
1189 + XtFree(searchRegion.sriText);
1191 + return matchingPatternFound;
1195 +** Adapt match pattern position / start position depending on the
1196 +** given matching type.
1198 +void adaptPatternPositions(
1199 + MatchingType matchingType,
1200 + int direction,
1201 + int *charPos,
1202 + int startPatternLength,
1203 + int *matchPos,
1204 + int matchedPatternLength)
1206 + switch (matchingType)
1208 + case MT_FLASH_DELIMIT:
1209 + case MT_MACRO:
1210 + if (direction == SEARCH_FORWARD)
1212 + (*matchPos) -= matchedPatternLength - 1;
1214 + break;
1216 + case MT_FLASH_RANGE:
1217 + case MT_SELECT:
1218 + if (direction == SEARCH_FORWARD)
1220 + (*charPos) -= startPatternLength;
1222 + else
1224 + (*charPos) --;
1226 + break;
1228 + case MT_GOTO:
1229 + if (direction == SEARCH_FORWARD)
1231 + (*matchPos) ++;
1233 + else
1235 + (*matchPos) += matchedPatternLength;
1237 + break;
1242 +** Try to find a string pattern at given buffer position 'charPos'.
1243 +** A string pattern is found, if pattern is located before 'charPos' or
1244 +** 'charPos' is located within a pattern.
1245 +** If a string pattern is found, then search direction and string pattern
1246 +** reference / properties are determined.
1247 +** Returns true, if a string pattern was found.
1249 +static int findMatchingStringElement(
1250 + StringMatchTable *smTable,
1251 + SearchRegionInfo *searchRegion,
1252 + MatchingElementInfo *matchInfo,
1253 + int *charPos,
1254 + const char *delimiters)
1256 + if (getPatternLocatedAtPos(
1257 + smTable->smtUsedPatRE,
1258 + smTable->smtAllPatterns,
1259 + searchRegion,
1260 + charPos,
1261 + matchInfo,
1262 + delimiters))
1264 + /*
1265 + * Pattern found -> define search direction:
1266 + * - START & MIDDLE pattern: matching pattern is searched in
1267 + * forward direction
1268 + * - END pattern: matching pattern is searched in backward
1269 + * direction
1270 + */
1271 + if (matchInfo->meiPatRef.prKind == PEK_END)
1272 + matchInfo->meiDirection = SEARCH_BACKWARD;
1273 + else
1274 + matchInfo->meiDirection = SEARCH_FORWARD;
1276 + return TRUE;
1279 + return FALSE;
1283 +** Return mono pattern info depending on highlight codes
1284 +** of left / right side of string pattern. Update pattern
1285 +** kind if applicable.
1287 +static PatternElementMonoInfo determineMonoPatInfo(
1288 + WindowInfo *window,
1289 + int patHighLightCode,
1290 + int leftPos,
1291 + int rightPos,
1292 + PatternElementKind *patElementKind)
1294 + int leftSideHasSameHC;
1295 + int rightSideHasSameHC;
1297 + /*
1298 + * Determine, if left side holds same highlight code than
1299 + * found string pattern
1300 + */
1301 + if (leftPos >= 0)
1302 + leftSideHasSameHC =
1303 + (HighlightCodeOfPos(window, leftPos) == patHighLightCode);
1304 + else
1305 + leftSideHasSameHC = FALSE;
1307 + /*
1308 + * Determine, if right side holds same highlight code than
1309 + * found string pattern
1310 + */
1311 + if (rightPos < window->buffer->length)
1312 + rightSideHasSameHC =
1313 + (HighlightCodeOfPos(window, rightPos) == patHighLightCode);
1314 + else
1315 + rightSideHasSameHC = FALSE;
1317 + if ((rightSideHasSameHC && leftSideHasSameHC) ||
1318 + (!rightSideHasSameHC && !leftSideHasSameHC))
1320 + return PEMI_MONO_AMBIGUOUS_SYNTAX;
1322 + else if (leftSideHasSameHC)
1324 + *patElementKind = PEK_END;
1325 + return PEMI_MONO_DEFINITE_SYNTAX;
1327 + else
1329 + *patElementKind = PEK_START;
1330 + return PEMI_MONO_DEFINITE_SYNTAX;
1335 +** Get backref info out of found string pattern and
1336 +** put it into given backRefInfo.
1338 +static void assignBackRefInfo(
1339 + StringPattern *strPat,
1340 + BackRefInfo *backRefInfo)
1342 + int i;
1343 + int localId;
1344 + regexp *patRE = strPat->spTextRE;
1346 + backRefInfo->briAvailable = FALSE;
1347 + backRefInfo->briCaseInsensitive = strPat->spCaseInsensitive;
1349 + for (i=0; i<MAX_GLOBAL_BACK_REF_ID; i++)
1351 + localId = strPat->spGlobalToLocalBackRef[i];
1353 + if (localId != NO_LOCAL_BACK_REF_ID)
1355 + backRefInfo->briAvailable = TRUE;
1357 + backRefInfo->briStartPtr[i] = patRE->startp[localId];
1358 + backRefInfo->briEndPtr[i] = patRE->endp[localId];
1360 + else
1362 + backRefInfo->briStartPtr[i] = NULL;
1363 + backRefInfo->briEndPtr[i] = NULL;
1369 +** Check, if given backref infos match.
1370 +** Returns true, if backref infos match.
1372 +static int doesBackRefInfoMatch(
1373 + BackRefInfo *backRefInfo1,
1374 + BackRefInfo *backRefInfo2)
1376 + int i;
1378 + /*
1379 + * if min. one string pattern doesn't hold backref info, then nothing
1380 + * could be compared -> both string pattern are matching.
1381 + */
1382 + if (!backRefInfo1->briAvailable || !backRefInfo2->briAvailable)
1383 + return TRUE;
1385 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
1387 + if (!compareBackRef(
1388 + backRefInfo1->briStartPtr[i],
1389 + backRefInfo1->briEndPtr[i],
1390 + backRefInfo2->briStartPtr[i],
1391 + backRefInfo2->briEndPtr[i],
1392 + backRefInfo1->briCaseInsensitive || backRefInfo2->briCaseInsensitive))
1394 + return FALSE;
1398 + return TRUE;
1402 +** Compares two backref content.
1403 +** Returns true, if backref contents match.
1405 +static int compareBackRef(
1406 + char *startPtr1,
1407 + char *endPtr1,
1408 + char *startPtr2,
1409 + char *endPtr2,
1410 + int caseInsensitive)
1412 + char *s1;
1413 + char *s2;
1415 + if (startPtr1 == NULL && startPtr2 == NULL)
1416 + return TRUE;
1418 + if (startPtr1 == NULL || startPtr2 == NULL)
1419 + return FALSE;
1421 + if ((endPtr1 - startPtr1) != (endPtr2 - startPtr2))
1422 + return FALSE;
1424 + s1 = startPtr1;
1425 + s2 = startPtr2;
1427 + if (caseInsensitive)
1429 + while (s1 != endPtr1)
1431 + if (tolower((unsigned char)*s1++) != tolower((unsigned char)*s2++))
1432 + return FALSE;
1435 + else
1437 + while (s1 != endPtr1)
1439 + if (*s1++ != *s2++)
1440 + return FALSE;
1443 + return TRUE;
1447 +** Verify if given pattern element is located between given
1448 +** start / end pointer of "foundStringInfo". Assign backreference
1449 +** information, if pattern element matches.
1450 +** Returns true, if given pattern element matches.
1452 +static int doesPatternElementMatch(
1453 + PatternElement *patElement,
1454 + FoundStringInfo *foundStringInfo,
1455 + BackRefInfo *backRefInfo)
1457 + char *s;
1458 + char *p;
1459 + StringPattern *strPat;
1460 + int elementMatch;
1462 + switch (patElement->peType)
1464 + case PET_SINGLE:
1465 + strPat = &patElement->peVal.peuSingle;
1466 + break;
1467 + case PET_MULTIPLE:
1468 + strPat = &patElement->peVal.peuMulti.mpStringPattern;
1469 + break;
1470 + default:
1471 + return FALSE;
1474 + if (strPat->spRegularExpression)
1476 + /*
1477 + * check reg. expression:
1478 + */
1479 + elementMatch =
1480 + ExecRE(
1481 + strPat->spTextRE,
1482 + foundStringInfo->fsiStartPtr,
1483 + foundStringInfo->fsiEndPtr,
1484 + FALSE,
1485 + foundStringInfo->fsiPrevChar,
1486 + foundStringInfo->fsiSuccChar,
1487 + foundStringInfo->fsiDelimiters,
1488 + NULL,
1489 + NULL);
1491 + if (elementMatch)
1492 + assignBackRefInfo(strPat, backRefInfo);
1494 + return elementMatch;
1496 + else
1498 + backRefInfo->briAvailable = FALSE;
1500 + /*
1501 + * check literal string:
1502 + */
1503 + p = strPat->spText;
1505 + /*
1506 + * if length of found string is different from length of
1507 + * given string pattern, then there is no match.
1508 + */
1509 + if (strPat->spLength != foundStringInfo->fsiLength)
1510 + return FALSE;
1512 + s = foundStringInfo->fsiStartPtr;
1514 + if (strPat->spCaseInsensitive)
1516 + while (s != foundStringInfo->fsiEndPtr)
1518 + if (tolower((unsigned char)*s++) != *p++)
1519 + return FALSE;
1522 + else
1524 + while (s != foundStringInfo->fsiEndPtr)
1526 + if (*s++ != *p++)
1527 + return FALSE;
1532 + return TRUE;
1536 +** Verify if a pattern element of given MatchPatternTableElement is
1537 +** located between given start / end pointer of "foundStringInfo".
1538 +** Returns true, if so.
1540 +static int doesMPTableElementMatch(
1541 + MatchPatternTableElement *element,
1542 + FoundStringInfo *foundStringInfo,
1543 + PatternElementKind *patternElementKind,
1544 + int *patternElementIdx,
1545 + BackRefInfo *backRefInfo)
1547 + int i;
1549 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i ++)
1551 + if (doesPatternElementMatch(
1552 + element->mpteAll.pesPattern[i],
1553 + foundStringInfo,
1554 + backRefInfo))
1556 + *patternElementKind = element->mpteAll.pesPattern[i]->peKind;
1557 + *patternElementIdx = i;
1559 + return TRUE;
1563 + return FALSE;
1567 +** Determine the pattern element of given MatchPatternTable, which is
1568 +** located between given start / end pointer of "foundStringInfo".
1569 +** Setup related pattern element reference.
1570 +** Returns true, if a pattern element was found.
1572 +static int getPatternInfo(
1573 + MatchPatternTable *table,
1574 + FoundStringInfo *foundStringInfo,
1575 + PatternReference *patRef,
1576 + BackRefInfo *backRefInfo)
1578 + int i;
1580 + for (i=0; i<table->mptNumberOfElements; i++)
1582 + if (doesMPTableElementMatch(
1583 + table->mptElements[i],
1584 + foundStringInfo,
1585 + &patRef->prKind,
1586 + &patRef->prPatternIdx,
1587 + backRefInfo))
1589 + patRef->prElementIdx = i;
1591 + return TRUE;
1595 + /*
1596 + * Should never been reached !
1597 + */
1598 + patRef->prElementIdx = NO_ELEMENT_IDX;
1599 + patRef->prKind = PEK_UNKNOWN;
1600 + patRef->prPatternIdx = NO_PATTERN_IDX;
1602 + return FALSE;
1606 +** Check, if given child pattern element is part of given
1607 +** parent pattern element.
1608 +** Returns true, if child is part of parent.
1610 +static int isPartOfPattern(
1611 + MatchPatternTable *table,
1612 + int parentElementIdx,
1613 + int childElementIdx,
1614 + PatternElementKind patElementKind)
1616 + MatchPatternTableElement *parent = table->mptElements[parentElementIdx];
1617 + MatchPatternTableElement *child = table->mptElements[childElementIdx];
1619 + if (childElementIdx == parentElementIdx)
1620 + return TRUE;
1622 + if (patElementKind == PEK_START)
1624 + if (isPartOfPatternElementSet(&parent->mpteStart, childElementIdx))
1625 + return TRUE;
1627 + return( isPartOfPatternElementSet(&child->mpteStart, parentElementIdx) );
1629 + else if (patElementKind == PEK_END)
1631 + if (isPartOfPatternElementSet(&parent->mpteEnd, childElementIdx))
1632 + return TRUE;
1634 + return( isPartOfPatternElementSet(&child->mpteEnd, parentElementIdx) );
1636 + else
1638 + /*
1639 + * Given child pattern element is middle pattern: the given pattern element
1640 + * is part of parent pattern, if it's a reference of a middle pattern
1641 + */
1642 + if (isPartOfMiddlePatternElementSet(&parent->mpteMiddle, childElementIdx))
1643 + return TRUE;
1645 + return( isPartOfMiddlePatternElementSet(&child->mpteMiddle, parentElementIdx) );
1650 +** Check, if given pattern element is part of given pattern element set.
1651 +** Returns true, if so.
1653 +static int isPartOfPatternElementSet(
1654 + PatternElementSet *patElementSet,
1655 + int patternElementIdx)
1657 + PatternElement *patElement;
1658 + int i;
1660 + for (i=0; i<patElementSet->pesNumberOfPattern; i++)
1662 + if (patElementSet->pesPattern[i]->peType == PET_REFERENCE)
1664 + patElement = patElementSet->pesPattern[i];
1666 + if (patElement->peVal.peuRef.prElementIdx == patternElementIdx)
1668 + return TRUE;
1673 + return FALSE;
1677 +** Verify, if given pattern element is part of middle pattern set.
1678 +** That's the case, if an element of the pattern set is reference
1679 +** of a middle pattern, which fits to given pattern element.
1680 +** Returns true, if pattern element is part of middle pattern set.
1681 + */
1682 +static int isPartOfMiddlePatternElementSet(
1683 + PatternElementSet *patElementSet,
1684 + int patternElementIdx)
1686 + PatternElement *patElement;
1687 + int i;
1689 + for (i=0; i<patElementSet->pesNumberOfPattern; i++)
1691 + if (patElementSet->pesPattern[i]->peType == PET_REFERENCE)
1693 + patElement = patElementSet->pesPattern[i];
1695 + if (patElement->peVal.peuRef.prElementIdx == patternElementIdx &&
1696 + patElement->peKind == PEK_MIDDLE)
1698 + return TRUE;
1703 + return FALSE;
1707 +** Update start pattern reference depending on next pattern located
1708 +** after start pattern.
1710 +static void considerNextPatternReference(
1711 + MatchPatternTable *table,
1712 + PatternReference *startPatRef,
1713 + PatternReference nxtPatRef,
1714 + int groupIdx)
1716 + MatchPatternTableElement *tabElement;
1717 + PatternElement *startPat;
1718 + MultiPattern *multiStartPat;
1719 + PatternReference patRef;
1720 + int i;
1722 + /*
1723 + * startPatRef needs no adaption, if element index of start pattern
1724 + * and next pattern are equal (i.e. start and next pattern belong
1725 + * to same pattern element).
1726 + */
1727 + if (startPatRef->prElementIdx == nxtPatRef.prElementIdx)
1728 + return;
1730 + /*
1731 + * Verify, if start pattern belongs to multiple pattern elements
1732 + * (like "ELSE .. FI" & "ELSE .. ESAC").
1733 + */
1734 + startPat = getPatternOfReference( table, *startPatRef );
1736 + if (startPat->peType == PET_MULTIPLE)
1738 + /*
1739 + * Check, if next pattern fits to one of the references of
1740 + * the start multi pattern. If so: adapt start pattern reference.
1741 + */
1742 + multiStartPat = &startPat->peVal.peuMulti;
1744 + for (i=0; i<multiStartPat->mpNumberOfReferences; i ++)
1746 + patRef = multiStartPat->mpRefList[i];
1747 + tabElement = table->mptElements[patRef.prElementIdx];
1749 + if (nxtPatRef.prElementIdx == patRef.prElementIdx &&
1750 + tabElement->mpteGroup == groupIdx)
1752 + *startPatRef = patRef;
1753 + return;
1760 +** Search for a string pattern in forward direction, starting at
1761 +** given beginPos. Determine related pattern reference of a found
1762 +** string pattern.
1763 +** Returns true, if a next string pattern was found.
1765 +static int searchPatternForward(
1766 + MatchPatternTable *table,
1767 + regexp *compiledRE,
1768 + SearchRegionInfo *searchRegion,
1769 + const char *delimiters,
1770 + int beginPos,
1771 + int *matchEndPos,
1772 + PatternReference *patRef,
1773 + int *highLightCode,
1774 + BackRefInfo *backRefInfo)
1776 + FoundStringInfo foundStringInfo;
1777 + int matchStartPos;
1778 + int absMatchStartPos;
1779 + MatchPatternTableElement *matchedElement;
1781 + *matchEndPos = -1;
1783 + patRef->prElementIdx = NO_ELEMENT_IDX;
1784 + patRef->prKind = PEK_UNKNOWN;
1785 + patRef->prPatternIdx = NO_PATTERN_IDX;
1787 + *highLightCode = IGNORE_HIGHLIGHT_CODE;
1789 + if (ExecRE(
1790 + compiledRE,
1791 + searchRegion->sriText + beginPos,
1792 + NULL,
1793 + FALSE,
1794 + beginPos==0 ? searchRegion->sriPrevChar : searchRegion->sriText[beginPos-1],
1795 + searchRegion->sriSuccChar,
1796 + delimiters,
1797 + searchRegion->sriText,
1798 + NULL))
1800 + foundStringInfo.fsiStartPtr = compiledRE->startp[0];
1801 + foundStringInfo.fsiEndPtr = compiledRE->endp[0];
1802 + foundStringInfo.fsiLength =
1803 + foundStringInfo.fsiEndPtr - foundStringInfo.fsiStartPtr;
1805 + foundStringInfo.fsiPrevChar =
1806 + foundStringInfo.fsiStartPtr == searchRegion->sriText ?
1807 + searchRegion->sriPrevChar : *(foundStringInfo.fsiStartPtr - 1);
1809 + foundStringInfo.fsiSuccChar =
1810 + *(foundStringInfo.fsiEndPtr) == '\0' ?
1811 + searchRegion->sriSuccChar : *(foundStringInfo.fsiEndPtr);
1813 + foundStringInfo.fsiDelimiters = delimiters;
1815 + if (getPatternInfo(
1816 + table,
1817 + &foundStringInfo,
1818 + patRef,
1819 + backRefInfo))
1821 + /*
1822 + * Next string pattern was found in forward direction and
1823 + * a pattern reference could be assigned to: calculate
1824 + * relative & absolute match positions.
1825 + */
1826 + matchStartPos = foundStringInfo.fsiStartPtr - searchRegion->sriText;
1827 + *matchEndPos = foundStringInfo.fsiEndPtr - searchRegion->sriText;
1829 + absMatchStartPos = matchStartPos + searchRegion->sriStartOfTextPos;
1831 + matchedElement = table->mptElements[patRef->prElementIdx];
1833 + /*
1834 + * get highlight code of found string pattern, if applicable
1835 + */
1836 + if (!matchedElement->mpteIgnoreHighLightInfo)
1838 + *highLightCode =
1839 + HighlightCodeOfPos(searchRegion->sriWindow, absMatchStartPos);
1842 + /*
1843 + * setup mono pattern info of found string pattern
1844 + */
1845 + if (matchedElement->mpteIsMonoPattern)
1847 + if (matchedElement->mpteIgnoreHighLightInfo)
1849 + patRef->prMonoInfo = PEMI_MONO_NOT_SYNTAX_BASED;
1851 + else
1853 + /*
1854 + * determine mono pattern info depending on highLightCodes
1855 + * before / after found string pattern.
1856 + */
1857 + patRef->prMonoInfo =
1858 + determineMonoPatInfo(
1859 + searchRegion->sriWindow,
1860 + *highLightCode,
1861 + absMatchStartPos - 1,
1862 + *matchEndPos + searchRegion->sriStartOfTextPos,
1863 + &patRef->prKind);
1866 + else
1868 + patRef->prMonoInfo = PEMI_NOT_MONO;
1871 + return matchStartPos;
1873 + else
1875 + /*
1876 + * Found string can't be assigned to a pattern element
1877 + * (should never occur).
1878 + */
1879 + return -1;
1882 + else
1884 + /*
1885 + * No next string pattern is found in forward direction.
1886 + */
1887 + return -1;
1892 +** Search for a string pattern in backward direction, starting at
1893 +** given beginPos. Determine related pattern reference of a found
1894 +** string pattern.
1895 +** Returns true, if a next string pattern was found.
1897 +static int searchPatternBackward(
1898 + MatchPatternTable *table,
1899 + regexp *compiledRE,
1900 + SearchRegionInfo *searchRegion,
1901 + const char *delimiters,
1902 + int beginPos,
1903 + PatternReference *patRef,
1904 + int *highLightCode,
1905 + int *matchedPatternLength,
1906 + BackRefInfo *backRefInfo)
1908 + FoundStringInfo foundStringInfo;
1909 + int matchStartPos;
1910 + int absMatchStartPos;
1911 + MatchPatternTableElement *matchedElement;
1913 + patRef->prElementIdx = NO_ELEMENT_IDX;
1914 + patRef->prKind = PEK_UNKNOWN;
1915 + patRef->prPatternIdx = NO_PATTERN_IDX;
1917 + *highLightCode = IGNORE_HIGHLIGHT_CODE;
1919 + if (ExecRE(
1920 + compiledRE,
1921 + searchRegion->sriText,
1922 + searchRegion->sriText + beginPos,
1923 + TRUE,
1924 + searchRegion->sriPrevChar,
1925 + searchRegion->sriText[beginPos] == '\0' ?
1926 + searchRegion->sriSuccChar : searchRegion->sriText[beginPos + 1],
1927 + delimiters,
1928 + searchRegion->sriText,
1929 + NULL))
1931 + foundStringInfo.fsiStartPtr = compiledRE->startp[0];
1932 + foundStringInfo.fsiEndPtr = compiledRE->endp[0];
1933 + foundStringInfo.fsiLength =
1934 + foundStringInfo.fsiEndPtr - foundStringInfo.fsiStartPtr;
1936 + foundStringInfo.fsiPrevChar =
1937 + foundStringInfo.fsiStartPtr == searchRegion->sriText ?
1938 + searchRegion->sriPrevChar : *(foundStringInfo.fsiStartPtr - 1);
1940 + foundStringInfo.fsiSuccChar =
1941 + *(foundStringInfo.fsiEndPtr) == '\0' ?
1942 + searchRegion->sriSuccChar : *(foundStringInfo.fsiEndPtr);
1944 + foundStringInfo.fsiDelimiters = delimiters;
1946 + if (getPatternInfo(
1947 + table,
1948 + &foundStringInfo,
1949 + patRef,
1950 + backRefInfo))
1952 + /*
1953 + * Next string pattern was found in backward direction and
1954 + * a pattern reference could be assigned to: calculate
1955 + * relative & absolute match positions.
1956 + */
1957 + matchStartPos = foundStringInfo.fsiStartPtr - searchRegion->sriText;
1958 + *matchedPatternLength = foundStringInfo.fsiLength;
1960 + absMatchStartPos = matchStartPos + searchRegion->sriStartOfTextPos;
1962 + matchedElement = table->mptElements[patRef->prElementIdx];
1964 + /*
1965 + * get highlight code of found string pattern, if applicable
1966 + */
1967 + if (!matchedElement->mpteIgnoreHighLightInfo)
1969 + *highLightCode =
1970 + HighlightCodeOfPos(searchRegion->sriWindow, absMatchStartPos);
1973 + /*
1974 + * setup mono pattern info of found string pattern
1975 + */
1976 + if (matchedElement->mpteIsMonoPattern)
1978 + if (matchedElement->mpteIgnoreHighLightInfo)
1980 + patRef->prMonoInfo = PEMI_MONO_NOT_SYNTAX_BASED;
1982 + else
1984 + /*
1985 + * determine mono pattern info depending on highLightCodes
1986 + * before / after found string pattern.
1987 + */
1988 + patRef->prMonoInfo =
1989 + determineMonoPatInfo(
1990 + searchRegion->sriWindow,
1991 + *highLightCode,
1992 + absMatchStartPos - 1,
1993 + absMatchStartPos + *matchedPatternLength,
1994 + &patRef->prKind);
1997 + else
1999 + patRef->prMonoInfo = PEMI_NOT_MONO;
2002 + return matchStartPos;
2004 + else
2006 + /*
2007 + * Found string can't be assigned to a pattern element
2008 + * (should never occur).
2009 + */
2010 + return -1;
2013 + else
2015 + /*
2016 + * No next string pattern is found in backward direction.
2017 + */
2018 + return -1;
2023 +** Find matching pattern related to given pattern (stored in
2024 +** 'matchInfo') in forward direction by considering the rules stored in
2025 +** string match table of given window. Determine match position (= abs.
2026 +** pos. of last character of matching string) and length of matching
2027 +** string. If a mono matching pattern couldn't be found in forward
2028 +** direction, then try finding it in backward direction (if found in
2029 +** backward direction, then match position indicates the 1st char. of
2030 +** matching string).
2031 +** Returns true, if a matching pattern was found.
2033 +static int parseStringElementForward(
2034 + MatchingElementInfo *matchInfo,
2035 + SearchRegionInfo *searchRegion,
2036 + int relCharPos,
2037 + int *matchPos,
2038 + int *matchedPatternLength,
2039 + const char *delimiters)
2041 + StringMatchTable *smTable =
2042 + (StringMatchTable *)searchRegion->sriWindow->stringMatchTable;
2043 + MatchPatternTableElement *matchElement = matchInfo->meiElement;
2044 + int beginPos = relCharPos;
2045 + int endStartPos;
2046 + int startStartPos;
2047 + int endEndPos;
2048 + int matchingPatternFound = FALSE;
2050 + /*
2051 + * Find matching pattern within text buffer area to parse in
2052 + * forward direction.
2053 + */
2054 + endStartPos =
2055 + findRelatedForwardPattern(
2056 + smTable,
2057 + searchRegion,
2058 + delimiters,
2059 + matchInfo->meiPatRef,
2060 + matchInfo->meiHighLightCode,
2061 + &matchInfo->meiBackRefInfo,
2062 + beginPos,
2063 + &endEndPos);
2065 + if (endEndPos != -1)
2067 + *matchPos = endEndPos - 1 + searchRegion->sriStartOfTextPos;
2068 + *matchedPatternLength = endEndPos - endStartPos;
2070 + matchingPatternFound = TRUE;
2072 + else if (matchElement->mpteIsMonoPattern)
2074 + /*
2075 + * mono pattern: forward find fails -> try backward direction.
2076 + * Calc. relative position of 1st char. before found string pattern.
2077 + */
2078 + beginPos = beginPos - matchInfo->meiLength - 1;
2080 + if (beginPos > 0)
2082 + startStartPos =
2083 + findRelatedStartPattern(
2084 + smTable,
2085 + searchRegion,
2086 + delimiters,
2087 + matchInfo->meiPatRef,
2088 + matchInfo->meiHighLightCode,
2089 + &matchInfo->meiBackRefInfo,
2090 + beginPos,
2091 + matchedPatternLength);
2093 + if (startStartPos != -1)
2095 + matchInfo->meiDirection = SEARCH_BACKWARD;
2097 + *matchPos = startStartPos + searchRegion->sriStartOfTextPos;
2099 + matchingPatternFound = TRUE;
2104 + return matchingPatternFound;
2108 +** Find matching pattern related to given begin pattern reference
2109 +** in forward direction by considering the rules stored in given
2110 +** string match table. Determine match position (= relative
2111 +** pos. of last character of matching string).
2112 +** Returns -1, if no matching pattern was found. Else the relative
2113 +** position of 1st char. of matching string is returned.
2115 +static int findRelatedForwardPattern(
2116 + StringMatchTable *table,
2117 + SearchRegionInfo *searchRegion,
2118 + const char *delimiters,
2119 + PatternReference beginPatRef,
2120 + int beginPatHighLightCode,
2121 + BackRefInfo *beginPatBackRefInfo,
2122 + int beginPos,
2123 + int *matchEndPos)
2125 + MatchPatternTable *patTable = table->smtAllPatterns;
2126 + int startPos = beginPos;
2127 + int nxtPatStartPos = 0;
2128 + int nxtPatEndPos = 0;
2129 + PatternReference nxtPatRef;
2130 + int nxtPatHighLightCode;
2131 + BackRefInfo nxtPatBackRefInfo;
2132 + PatternStackElement stack[MAX_NESTED_PATTERNS];
2133 + int stackIdx = 0;
2134 + PatternReference startPatRef;
2135 + MatchPatternTableElement *currentElement;
2136 + int groupIdx;
2137 + regexp *groupPatRE;
2138 + regexp *currentPatRE;
2139 + int skipToEnd = FALSE;
2140 + int beginPatternIsMono;
2142 +#ifdef DEBUG_FIND
2143 + printf("Forward Start Pos: %d K: %s EI: %d PI: %d HC: %d <%s>\n",
2144 + startPos,
2145 + patElemKindToString(beginPatRef.prKind),
2146 + beginPatRef.prElementIdx,
2147 + beginPatRef.prPatternIdx,
2148 + beginPatHighLightCode,
2149 + getPatternForDebug(patTable, beginPatRef) );
2150 +#endif
2152 + /*
2153 + * put begin pattern info on stack
2154 + */
2155 + stack[stackIdx].psePatRef = beginPatRef;
2156 + stack[stackIdx].pseHighLightCode = beginPatHighLightCode;
2157 + stack[stackIdx].pseBackRefInfo = *beginPatBackRefInfo;
2158 + stackIdx ++;
2160 + currentElement = patTable->mptElements[beginPatRef.prElementIdx];
2162 + beginPatternIsMono = currentElement->mpteIsMonoPattern;
2164 + groupIdx = currentElement->mpteGroup;
2166 + /*
2167 + * no next pattern can be found, if there is no group assigned
2168 + * to begin pattern (should never occur)
2169 + */
2170 + if (groupIdx == NO_GROUP_IDX)
2172 + *matchEndPos = -1;
2174 + return -1;
2177 + /*
2178 + * Remember pattern (= keywords) regular expression of context
2179 + * group related to begin pattern. Use it for forward search.
2180 + */
2181 + groupPatRE = table->smtGroups[groupIdx]->mpgeKeywordRE;
2182 + currentPatRE = groupPatRE;
2184 + /*
2185 + * Use start / end pattern regular expression if skip to end is
2186 + * set for begin pattern.
2187 + */
2188 + if (currentElement->mpteSkipBtwnStartEnd)
2190 + currentPatRE = currentElement->mpteStartEndRE;
2191 + skipToEnd = TRUE;
2194 + while (stackIdx > 0 && nxtPatStartPos != -1)
2196 + /*
2197 + * Search for next string pattern in forward direction.
2198 + */
2199 + nxtPatStartPos =
2200 + searchPatternForward(
2201 + patTable,
2202 + currentPatRE,
2203 + searchRegion,
2204 + delimiters,
2205 + startPos,
2206 + &nxtPatEndPos,
2207 + &nxtPatRef,
2208 + &nxtPatHighLightCode,
2209 + &nxtPatBackRefInfo );
2211 + startPatRef = stack[stackIdx-1].psePatRef;
2213 + if (nxtPatStartPos == -1)
2215 + /*
2216 + * no next pattern found -> leave loop
2217 + */
2218 +#ifdef DEBUG_FIND
2219 + printf(" SI: %d [start K: %s EI: %d PI %d] Pos: %d --> no next pat. found\n",
2220 + stackIdx,
2221 + patElemKindToString(startPatRef.prKind),
2222 + startPatRef.prElementIdx,
2223 + startPatRef.prPatternIdx,
2224 + startPos);
2225 +#endif
2226 + break;
2229 + /*
2230 + * Update start pattern reference depending on next pattern
2231 + * located after start pattern.
2232 + */
2233 + considerNextPatternReference(
2234 + patTable,
2235 + &startPatRef,
2236 + nxtPatRef,
2237 + groupIdx );
2239 + /*
2240 + * If current found match pattern table element is a mono pattern and
2241 + * skip to start pattern is active, then the found pattern string is
2242 + * a END one in case of ambiguous or no syntax was detected.
2243 + */
2244 + if (skipToEnd &&
2245 + (nxtPatRef.prMonoInfo == PEMI_MONO_AMBIGUOUS_SYNTAX ||
2246 + nxtPatRef.prMonoInfo == PEMI_MONO_NOT_SYNTAX_BASED))
2248 + nxtPatRef.prKind = PEK_END;
2251 +#ifdef DEBUG_FIND
2252 + printf(" SI: %d [start K: %s EI: %d PI %d] Pos: %d-%d K: %s EI: %d PI: %d HC: %d f=<%s> ",
2253 + stackIdx,
2254 + patElemKindToString(startPatRef.prKind),
2255 + startPatRef.prElementIdx,
2256 + startPatRef.prPatternIdx,
2257 + nxtPatStartPos,
2258 + nxtPatEndPos,
2259 + patElemKindToString(nxtPatRef.prKind),
2260 + nxtPatRef.prElementIdx,
2261 + nxtPatRef.prPatternIdx,
2262 + nxtPatHighLightCode,
2263 + getPatternForDebug(patTable, nxtPatRef) );
2264 + printFoundStringForDebug(
2265 + searchRegion->sriWindow,
2266 + nxtPatStartPos + searchRegion->sriStartOfTextPos,
2267 + nxtPatEndPos - nxtPatStartPos);
2268 + printf("\n");
2269 +#endif
2271 + if (nxtPatRef.prKind == PEK_START)
2273 + if (stackIdx >= MAX_NESTED_PATTERNS)
2275 +#ifdef DEBUG_FIND
2276 + printf("FORWARD: MAX. NESTED PATTERN DEPTH REACHED !\n");
2277 +#endif
2278 + nxtPatStartPos = -1;
2279 + nxtPatEndPos = -1;
2281 + else if (!skipToEnd)
2283 + /*
2284 + * Put next pattern on stack, if contents between start /
2285 + * end shouldn't be skipped (if "skipToEnd" is set,
2286 + * a (usually illegal) start pattern to skip inside the
2287 + * skipped one is found (e.g. \* \* ..)
2288 + */
2289 + stack[stackIdx].psePatRef = nxtPatRef;
2290 + stack[stackIdx].pseHighLightCode = nxtPatHighLightCode;
2291 + stack[stackIdx].pseBackRefInfo = nxtPatBackRefInfo;
2292 + stackIdx ++;
2294 + currentElement = patTable->mptElements[nxtPatRef.prElementIdx];
2296 + /*
2297 + * Use start / end pattern regular expression if skip to
2298 + * end is set for found start pattern.
2299 + */
2300 + if (currentElement->mpteSkipBtwnStartEnd)
2302 + currentPatRE = currentElement->mpteStartEndRE;
2303 + skipToEnd = TRUE;
2306 + else if (beginPatternIsMono)
2308 + /*
2309 + * skip to end is set and a mono pattern start is reached:
2310 + * trigger backward search by returning "not found"
2311 + */
2312 +#ifdef DEBUG_FIND
2313 + printf(" ---> mono pattern (re-)start -> trigger backward search\n");
2314 +#endif
2315 + nxtPatStartPos = -1;
2316 + nxtPatEndPos = -1;
2318 +#ifdef DEBUG_FIND
2319 + else
2321 + printf(" ---> skip to end: illegal (re-)start pattern !\n");
2323 +#endif
2325 + else if (nxtPatRef.prKind == PEK_END)
2327 + /*
2328 + * ignore current found pattern, if it doesn't fit to the prev.
2329 + * opened one.
2330 + */
2331 + if (isPartOfPattern(
2332 + patTable,
2333 + nxtPatRef.prElementIdx,
2334 + startPatRef.prElementIdx,
2335 + PEK_END) &&
2336 + (stack[stackIdx - 1].pseHighLightCode == nxtPatHighLightCode ||
2337 + stack[stackIdx - 1].pseHighLightCode == IGNORE_HIGHLIGHT_CODE ||
2338 + nxtPatHighLightCode == IGNORE_HIGHLIGHT_CODE) &&
2339 + doesBackRefInfoMatch(
2340 + &stack[stackIdx - 1].pseBackRefInfo,
2341 + &nxtPatBackRefInfo))
2343 + /*
2344 + * use context group pattern again, if end pattern to skip
2345 + * to was found.
2346 + */
2347 + if (skipToEnd)
2349 + currentPatRE = groupPatRE;
2350 + skipToEnd = FALSE;
2353 + /*
2354 + * pop. related start pattern from stack.
2355 + */
2356 + stackIdx --;
2359 + else if (!skipToEnd)
2361 + /*
2362 + * middle pattern was found: ignore it, if found middle pattern
2363 + * doesn't belong to begin pattern.
2364 + */
2365 + if (stackIdx == 1 &&
2366 + isPartOfPattern(
2367 + patTable,
2368 + startPatRef.prElementIdx,
2369 + nxtPatRef.prElementIdx,
2370 + nxtPatRef.prKind) &&
2371 + (beginPatHighLightCode == nxtPatHighLightCode ||
2372 + beginPatHighLightCode == IGNORE_HIGHLIGHT_CODE ||
2373 + nxtPatHighLightCode == IGNORE_HIGHLIGHT_CODE) &&
2374 + doesBackRefInfoMatch(
2375 + beginPatBackRefInfo,
2376 + &nxtPatBackRefInfo))
2379 + stackIdx --;
2383 + startPos = nxtPatEndPos;
2386 + *matchEndPos = nxtPatEndPos;
2388 + return nxtPatStartPos;
2392 +** Find matching pattern related to given pattern (stored in
2393 +** 'matchInfo') in backward direction by considering the rules stored in
2394 +** string match table of given window. Determine match position (= abs.
2395 +** pos. of 1st character of matching string) and length of matching
2396 +** string.
2397 +** Returns true, if a matching pattern was found.
2399 +static int parseStringElementBackward(
2400 + MatchingElementInfo *matchInfo,
2401 + SearchRegionInfo *searchRegion,
2402 + int relCharPos,
2403 + int *matchPos,
2404 + int *matchedPatternLength,
2405 + const char *delimiters)
2407 + StringMatchTable *smTable =
2408 + (StringMatchTable *)searchRegion->sriWindow->stringMatchTable;
2409 + int beginPos;
2410 + int startStartPos;
2411 + int matchingPatternFound = FALSE;
2413 + /*
2414 + * determine begin of search in string buffer (= relative position
2415 + * of 1st char. before found string pattern.)
2416 + */
2417 + beginPos = relCharPos - matchInfo->meiLength - 1;
2419 + if (beginPos < 0)
2420 + return FALSE;
2422 + /*
2423 + * Find matching pattern within text buffer area to parse in
2424 + * backward direction.
2425 + */
2426 + startStartPos =
2427 + findRelatedStartPattern(
2428 + smTable,
2429 + searchRegion,
2430 + delimiters,
2431 + matchInfo->meiPatRef,
2432 + matchInfo->meiHighLightCode,
2433 + &matchInfo->meiBackRefInfo,
2434 + beginPos,
2435 + matchedPatternLength);
2437 + if (startStartPos != -1)
2439 + *matchPos = startStartPos + searchRegion->sriStartOfTextPos;
2440 + matchingPatternFound = TRUE;
2443 + return matchingPatternFound;
2447 +** Find matching pattern related to given begin pattern reference
2448 +** in backward direction by considering the rules stored in given
2449 +** string match table. Determine match position (= relative
2450 +** pos. of 1st character of matching string).
2451 +** Returns -1, if no matching pattern was found. Else the relative
2452 +** position of 1st char. of matching string is returned.
2454 +static int findRelatedStartPattern(
2455 + StringMatchTable *table,
2456 + SearchRegionInfo *searchRegion,
2457 + const char *delimiters,
2458 + PatternReference beginPatRef,
2459 + int beginPatHighLightCode,
2460 + BackRefInfo *beginPatBackRefInfo,
2461 + int beginPos,
2462 + int *matchedPatternLength)
2464 + MatchPatternTable *patTable = table->smtAllPatterns;
2465 + int startPos = beginPos;
2466 + int prevStartPos = 0;
2467 + PatternReference prevPatRef;
2468 + int prevPatHighLightCode;
2469 + BackRefInfo prevPatBackRefInfo;
2470 + PatternStackElement stack[MAX_NESTED_PATTERNS];
2471 + int stackIdx = 0;
2472 + MatchPatternTableElement *currentElement;
2473 + int groupIdx;
2474 + regexp *groupPatRE;
2475 + regexp *currentPatRE;
2476 + int skipToStart = FALSE;
2478 + /*
2479 + * put begin pattern info on stack
2480 + */
2481 + stack[stackIdx].psePatRef = beginPatRef;
2482 + stack[stackIdx].pseHighLightCode = beginPatHighLightCode;
2483 + stack[stackIdx].pseBackRefInfo = *beginPatBackRefInfo;
2484 + stackIdx ++;
2486 + currentElement = patTable->mptElements[beginPatRef.prElementIdx];
2488 +#ifdef DEBUG_FIND
2489 + printf("Backward Start Pos: %d K: %s EI: %d PI: %d HC: %d <%s>\n",
2490 + startPos,
2491 + patElemKindToString(beginPatRef.prKind),
2492 + beginPatRef.prElementIdx,
2493 + beginPatRef.prPatternIdx,
2494 + beginPatHighLightCode,
2495 + getPatternForDebug(patTable, beginPatRef) );
2496 +#endif
2498 + groupIdx = currentElement->mpteGroup;
2500 + /*
2501 + * no start pattern can be found, if there is no group assigned
2502 + * to begin pattern (should never occur)
2503 + */
2504 + if (groupIdx == NO_GROUP_IDX)
2506 + return -1;
2509 + /*
2510 + * Remember pattern (= keywords) regular expression of context
2511 + * group related to begin pattern. Use it for backward search.
2512 + */
2513 + groupPatRE = table->smtGroups[groupIdx]->mpgeKeywordRE;
2514 + currentPatRE = groupPatRE;
2516 + /*
2517 + * Use start / end pattern regular expression if skip to start is
2518 + * set for begin pattern.
2519 + */
2520 + if (currentElement->mpteSkipBtwnStartEnd)
2522 + currentPatRE = currentElement->mpteStartEndRE;
2523 + skipToStart = TRUE;
2526 + while (stackIdx > 0 && prevStartPos != -1)
2528 + /*
2529 + * Search for previous string pattern in backward direction.
2530 + */
2531 + prevStartPos =
2532 + searchPatternBackward(
2533 + patTable,
2534 + currentPatRE,
2535 + searchRegion,
2536 + delimiters,
2537 + startPos,
2538 + &prevPatRef,
2539 + &prevPatHighLightCode,
2540 + matchedPatternLength,
2541 + &prevPatBackRefInfo );
2543 + if (prevStartPos == -1)
2545 + /*
2546 + * no previous pattern found -> leave loop
2547 + */
2548 +#ifdef DEBUG_FIND
2549 + printf(" SI: %d [K: %s start EI: %d PI %d] Pos: %d --> no next pat. found\n",
2550 + stackIdx,
2551 + patElemKindToString(stack[stackIdx -1].psePatRef.prKind),
2552 + stack[stackIdx -1].psePatRef.prElementIdx,
2553 + stack[stackIdx -1].psePatRef.prPatternIdx,
2554 + startPos);
2555 +#endif
2556 + break;
2559 + /*
2560 + * Update previous pattern reference depending on last stack
2561 + * pattern, which is located in text puffer after previous
2562 + * start pattern.
2563 + */
2564 + considerNextPatternReference(
2565 + patTable,
2566 + &prevPatRef,
2567 + stack[stackIdx - 1].psePatRef,
2568 + groupIdx);
2570 + /*
2571 + * If current found match pattern table element is a mono pattern and
2572 + * skip to start pattern is active, then the found pattern string is
2573 + * a START one in case of ambiguous or no syntax was detected.
2574 + */
2575 + if (skipToStart &&
2576 + (prevPatRef.prMonoInfo == PEMI_MONO_AMBIGUOUS_SYNTAX ||
2577 + prevPatRef.prMonoInfo == PEMI_MONO_NOT_SYNTAX_BASED))
2579 + prevPatRef.prKind = PEK_START;
2582 +#ifdef DEBUG_FIND
2583 + printf(" SI: %d [K: %s start EI: %d PI %d] Pos: %d K: %s EI: %d PI: %d HC: %d f=<%s> ",
2584 + stackIdx,
2585 + patElemKindToString(stack[stackIdx -1].psePatRef.prKind),
2586 + stack[stackIdx -1].psePatRef.prElementIdx,
2587 + stack[stackIdx -1].psePatRef.prPatternIdx,
2588 + prevStartPos,
2589 + patElemKindToString(prevPatRef.prKind),
2590 + prevPatRef.prElementIdx,
2591 + prevPatRef.prPatternIdx,
2592 + prevPatHighLightCode,
2593 + getPatternForDebug(patTable, prevPatRef) );
2594 + printFoundStringForDebug(
2595 + searchRegion->sriWindow,
2596 + prevStartPos + searchRegion->sriStartOfTextPos,
2597 + *matchedPatternLength);
2598 + printf("\n");
2599 +#endif
2601 + if (prevPatRef.prKind == PEK_START)
2603 + /*
2604 + * If the end pattern of the previous pattern set is a reference,
2605 + * then the prev. element index is the one of the ref. (due to this
2606 + * string was found before and was stored on stack)
2607 + */
2608 + if (patTable->mptElements[prevPatRef.prElementIdx]->mpteGroup == groupIdx)
2610 + considerStackPatReference(
2611 + &patTable->mptElements[prevPatRef.prElementIdx]->mpteEnd,
2612 + stack[stackIdx - 1].psePatRef.prElementIdx,
2613 + &prevPatRef.prElementIdx);
2616 + /*
2617 + * Ignore current found pattern, if it doesn't fit to the prev.
2618 + * opened one.
2619 + */
2620 + if (stack[stackIdx - 1].psePatRef.prElementIdx == prevPatRef.prElementIdx &&
2621 + (stack[stackIdx - 1].pseHighLightCode == prevPatHighLightCode ||
2622 + stack[stackIdx - 1].pseHighLightCode == IGNORE_HIGHLIGHT_CODE ||
2623 + prevPatHighLightCode == IGNORE_HIGHLIGHT_CODE) &&
2624 + doesBackRefInfoMatch(
2625 + &stack[stackIdx - 1].pseBackRefInfo,
2626 + &prevPatBackRefInfo))
2628 + /*
2629 + * use context group pattern again, if start pattern
2630 + * to skip to was found.
2631 + */
2632 + if (skipToStart)
2634 + currentPatRE = groupPatRE;
2635 + skipToStart = FALSE;
2638 + /*
2639 + * pop. related end pattern from stack.
2640 + */
2641 + stackIdx --;
2644 + else if (prevPatRef.prKind == PEK_END)
2646 + if (stackIdx >= MAX_NESTED_PATTERNS)
2648 +#ifdef DEBUG_FIND
2649 + printf("BACKWARD: MAX. NESTED PATTERN DEPTH REACHED !\n");
2650 +#endif
2651 + prevStartPos = -1;
2653 + else if (!skipToStart)
2655 + /*
2656 + * Put prev. pattern on stack, if contents between start /
2657 + * end shouldn't be skipped (if "skipToStart" is set,
2658 + * a (usually illegal) end pattern to skip inside the
2659 + * skipped one is found (e.g. *\ *\ ..)
2660 + */
2661 + stack[stackIdx].psePatRef = prevPatRef;
2662 + stack[stackIdx].pseHighLightCode = prevPatHighLightCode;
2663 + stack[stackIdx].pseBackRefInfo = prevPatBackRefInfo;
2664 + stackIdx ++;
2666 + currentElement =
2667 + patTable->mptElements[prevPatRef.prElementIdx];
2669 + /*
2670 + * Use start / end pattern regular expression if skip to
2671 + * end is set for found end pattern.
2672 + */
2673 + if (currentElement->mpteSkipBtwnStartEnd)
2675 + currentPatRE = currentElement->mpteStartEndRE;
2676 + skipToStart = TRUE;
2680 + startPos = prevStartPos - 1;
2683 + return prevStartPos;
2687 +** Adapt found pattern element index depending on
2688 +** the info stored on (last) stack element and
2689 +** a given pattern set (belonging to the found pattern).
2691 +static void considerStackPatReference(
2692 + PatternElementSet *patSet,
2693 + int stackElementIdx,
2694 + int *foundElementIdx)
2696 + PatternElement *patElement;
2697 + int i;
2699 + /*
2700 + * If found pattern index already indicates, that found pattern
2701 + * belongs to pattern set stored on stack, then no adaption is needed
2702 + */
2703 + if (*foundElementIdx == stackElementIdx)
2704 + return;
2706 + /*
2707 + * Check all elements of given pattern element set:
2708 + */
2709 + for (i=0; i < patSet->pesNumberOfPattern; i++)
2711 + patElement = patSet->pesPattern[i];
2713 + /*
2714 + * If this set element is a reference and this reference fits
2715 + * to the element stored on stack, then adapt found element index:
2716 + * indicate, that found pattern belongs to pattern set stored on stack
2717 + */
2718 + if (patElement->peType == PET_REFERENCE &&
2719 + patElement->peVal.peuRef.prElementIdx == stackElementIdx)
2721 + *foundElementIdx = stackElementIdx;
2723 + return;
2729 +** Determines, if a string pattern is located at the given position
2730 +** "relBeginPos" in the given "searchRegion". A string pattern is
2731 +** found, if the pattern is located just before given position
2732 +** "relBeginPos" OR if "relBeginPos" is located within a string pattern.
2734 +** Returns true, if the given "pattern" is located at
2735 +** "relBeginPos". "matchInfo" holds all info needed about matched
2736 +** "start" string pattern.
2738 +static int getPatternLocatedAtPos(
2739 + regexp *usedPatRE,
2740 + MatchPatternTable *table,
2741 + SearchRegionInfo *searchRegion,
2742 + int *relBeginPos,
2743 + MatchingElementInfo *matchInfo,
2744 + const char *delimiters)
2746 + int searchStartPos = *relBeginPos;
2747 + PatternReference *patRef = &matchInfo->meiPatRef;
2748 + FoundStringInfo foundStringInfo;
2749 + int relMatchStartPos;
2750 + int relMatchEndPos;
2752 + patRef->prElementIdx = NO_ELEMENT_IDX;
2753 + patRef->prKind = PEK_UNKNOWN;
2754 + patRef->prPatternIdx = NO_PATTERN_IDX;
2756 + matchInfo->meiHighLightCode = IGNORE_HIGHLIGHT_CODE;
2757 + matchInfo->meiAbsStartPos = -1;
2758 + matchInfo->meiLength = 0;
2760 + /*
2761 + * No backward search possible, if we are at beginning of
2762 + * search region
2763 + */
2764 + if (searchStartPos == 0)
2765 + return FALSE;
2767 + /*
2768 + * Search in backward direction for 1st occurance of a string pattern
2769 + * starting one char before "searchStartPos".
2770 + */
2771 + if (ExecRE(
2772 + usedPatRE,
2773 + searchRegion->sriText,
2774 + searchRegion->sriText + searchStartPos - 1,
2775 + TRUE,
2776 + searchRegion->sriPrevChar,
2777 + searchRegion->sriText[searchStartPos],
2778 + delimiters,
2779 + searchRegion->sriText,
2780 + NULL))
2782 + /*
2783 + * String pattern was found:
2784 + */
2785 + foundStringInfo.fsiStartPtr = usedPatRE->startp[0];
2786 + foundStringInfo.fsiEndPtr = usedPatRE->endp[0];
2787 + foundStringInfo.fsiLength =
2788 + foundStringInfo.fsiEndPtr - foundStringInfo.fsiStartPtr;
2790 + relMatchEndPos = foundStringInfo.fsiEndPtr - searchRegion->sriText;
2791 + relMatchStartPos = foundStringInfo.fsiStartPtr - searchRegion->sriText;
2793 + /*
2794 + * Is found pattern located exactly one char before "relBeginPos" OR
2795 + * is "relBeginPos" located within found string pattern ?
2796 + * Note: "relMatchEndPos" indicates 1st pos. in "sriText"
2797 + * which does *not* belong to found string anymore.
2798 + */
2799 + if ((*relBeginPos == relMatchEndPos) ||
2800 + (*relBeginPos >= relMatchStartPos &&
2801 + *relBeginPos < relMatchEndPos))
2803 + *relBeginPos = relMatchEndPos;
2805 + /*
2806 + * Determine match element info related to found string.
2807 + */
2808 + matchInfo->meiAbsStartPos =
2809 + foundStringInfo.fsiStartPtr - searchRegion->sriText +
2810 + searchRegion->sriStartOfTextPos;
2811 + matchInfo->meiLength = foundStringInfo.fsiLength;
2813 + foundStringInfo.fsiPrevChar =
2814 + foundStringInfo.fsiStartPtr == searchRegion->sriText ?
2815 + searchRegion->sriPrevChar : *(foundStringInfo.fsiStartPtr - 1);
2817 + foundStringInfo.fsiSuccChar =
2818 + *(foundStringInfo.fsiEndPtr) == '\0' ?
2819 + searchRegion->sriSuccChar : *(foundStringInfo.fsiEndPtr);
2821 + foundStringInfo.fsiDelimiters = delimiters;
2823 + return(
2824 + getMatchedElementInfo(
2825 + searchRegion->sriWindow,
2826 + table,
2827 + &foundStringInfo,
2828 + matchInfo));
2832 + return FALSE;
2836 +** Get all needed info related to matched "start" string pattern
2837 +** (given by parameter "foundStringInfo").
2839 +** Returns true, if info was determined successfully.
2841 +static int getMatchedElementInfo(
2842 + WindowInfo *window,
2843 + MatchPatternTable *table,
2844 + FoundStringInfo *foundStringInfo,
2845 + MatchingElementInfo *matchInfo)
2847 + PatternReference *patRef = &matchInfo->meiPatRef;
2848 + int absMatchStartPos = matchInfo->meiAbsStartPos;
2849 + MatchPatternTableElement *matchedElement;
2851 + if (getPatternInfo(
2852 + table,
2853 + foundStringInfo,
2854 + patRef,
2855 + &matchInfo->meiBackRefInfo))
2857 + /*
2858 + * A pattern reference could be assigned to found string:
2859 + */
2860 + matchedElement = table->mptElements[patRef->prElementIdx];
2862 + matchInfo->meiElement = matchedElement;
2864 + /*
2865 + * get highlight code of found string pattern, if applicable
2866 + */
2867 + if (!matchedElement->mpteIgnoreHighLightInfo)
2869 + matchInfo->meiHighLightCode =
2870 + HighlightCodeOfPos(window, absMatchStartPos);
2873 + /*
2874 + * setup mono pattern info of found string pattern
2875 + */
2876 + if (matchedElement->mpteIsMonoPattern)
2878 + if (matchedElement->mpteIgnoreHighLightInfo)
2880 + patRef->prMonoInfo = PEMI_MONO_NOT_SYNTAX_BASED;
2882 + else
2884 + /*
2885 + * determine mono pattern info depending on highLightCodes
2886 + * before / after found string pattern.
2887 + */
2888 + patRef->prMonoInfo =
2889 + determineMonoPatInfo(
2890 + window,
2891 + matchInfo->meiHighLightCode,
2892 + absMatchStartPos - 1,
2893 + absMatchStartPos + matchInfo->meiLength,
2894 + &patRef->prKind);
2897 + else
2899 + patRef->prMonoInfo = PEMI_NOT_MONO;
2902 + return TRUE;
2904 + else
2906 + /*
2907 + * Found string can't be assigned to a pattern element
2908 + * (should never occur).
2909 + */
2910 + return FALSE;
2915 +** Returns string pattern of given pattern element.
2917 +StringPattern *GetStringPattern(
2918 + MatchPatternTable *table,
2919 + PatternElement *pattern )
2921 + switch (pattern->peType)
2923 + case PET_SINGLE:
2924 + return &pattern->peVal.peuSingle;
2925 + break;
2927 + case PET_MULTIPLE:
2928 + return &pattern->peVal.peuMulti.mpStringPattern;
2929 + break;
2931 + case PET_REFERENCE:
2932 + return GetStringPattern(
2933 + table,
2934 + getPatternOfReference(table, pattern->peVal.peuRef));
2935 + break;
2938 + /*
2939 + * never reached; just to make compiler happy
2940 + */
2941 + return NULL;
2945 +** Returns pattern element of given pattern reference.
2947 +static PatternElement *getPatternOfReference(
2948 + MatchPatternTable *table,
2949 + PatternReference patRef)
2951 + MatchPatternTableElement **element = table->mptElements;
2953 + return element[ patRef.prElementIdx ]->mpteAll.pesPattern[patRef.prPatternIdx];
2956 +#ifdef DEBUG_FIND
2957 +static char *getPatternForDebug(
2958 + MatchPatternTable *table,
2959 + PatternReference patRef )
2961 + if (patRef.prElementIdx < 0)
2963 + return "---";
2966 + return
2967 + GetStringPattern(
2968 + table,
2969 + getPatternOfReference(table, patRef))->spText;
2972 +static char *patElemKindToString(
2973 + PatternElementKind patElemKind)
2975 + if (patElemKind == PEK_START)
2976 + return "START";
2977 + else if (patElemKind == PEK_MIDDLE)
2978 + return "MIDDLE";
2979 + else if (patElemKind == PEK_END)
2980 + return "END";
2981 + else
2982 + return "UNKNOWN";
2985 +static void printFoundStringForDebug(
2986 + WindowInfo *window,
2987 + int absStartPos,
2988 + int length)
2990 + char *foundStr =
2991 + BufGetRange( window->buffer, absStartPos, absStartPos + length);
2993 + printf("%d (abs.) <%s>",
2994 + absStartPos,
2995 + foundStr);
2997 + XtFree(foundStr);
2999 +#endif
3002 diff --quilt /dev/null new/source/patternMatch.h
3003 --- /dev/null
3004 +++ new/source/patternMatch.h
3005 @@ -0,0 +1,170 @@
3006 +/* $Id: patternMatch.h,v 1.2 2003/10/11 16:45:25 uleh Exp $ */
3008 +#ifndef NEDIT_PATTERNMATCH_H_INCLUDED
3009 +#define NEDIT_PATTERNMATCH_H_INCLUDED
3011 +#include "regularExp.h"
3013 +#define NO_GROUP_IDX -1
3014 +#define NO_ELEMENT_IDX -1
3015 +#define NO_PATTERN_IDX -1
3017 +#define MAX_GLOBAL_BACK_REF_ID 9
3018 +#define NO_LOCAL_BACK_REF_ID -1
3020 +typedef enum {
3021 + PEK_UNKNOWN,
3022 + PEK_START,
3023 + PEK_END,
3024 + PEK_MIDDLE
3025 +} PatternElementKind;
3027 +typedef enum {
3028 + PEMI_NOT_MONO,
3029 + PEMI_MONO_NOT_SYNTAX_BASED,
3030 + PEMI_MONO_AMBIGUOUS_SYNTAX,
3031 + PEMI_MONO_DEFINITE_SYNTAX
3032 +} PatternElementMonoInfo;
3034 +typedef struct _PatternReference {
3035 + PatternElementKind prKind;
3036 + PatternElementMonoInfo prMonoInfo;
3037 + int prElementIdx;
3038 + int prPatternIdx;
3039 +} PatternReference;
3041 +typedef enum {
3042 + MPT_INDIVIDUAL,
3043 + MPT_SUB,
3044 + MPT_GROUP
3045 +} MatchPatternType;
3047 +typedef struct _MatchPatternSequenceElement {
3048 + char *mpseName;
3049 + MatchPatternType mpseType;
3050 + int mpseIndex;
3051 +} MatchPatternSequenceElement;
3053 +typedef struct _MatchPatternGroupElement {
3054 + char *mpgeName;
3055 + int mpgeNumberOfSubPatterns;
3056 + char **mpgeSubPatternIds;
3057 + regexp *mpgeKeywordRE;
3058 +} MatchPatternGroupElement;
3060 +typedef enum {
3061 + PWB_NONE,
3062 + PWB_LEFT,
3063 + PWB_RIGHT,
3064 + PWB_BOTH
3065 +} PatternWordBoundary;
3067 +typedef struct _StrPatBackRefElement{
3068 + int spbreLocalBackRefID;
3069 + char *spbreRegExpText;
3070 +} StrPatBackRefElement;
3072 +typedef struct _StringPattern {
3073 + char *spText;
3074 + int spLength;
3075 + PatternWordBoundary spWordBoundary;
3076 + int spCaseInsensitive;
3077 + int spRegularExpression;
3078 + regexp *spTextRE;
3079 + char *spOrigText;
3080 + int spBackRefParsed;
3081 + int spBackRefResolved;
3082 + StrPatBackRefElement spOwnGlobalBackRef[MAX_GLOBAL_BACK_REF_ID];
3083 + int spGlobalToLocalBackRef[MAX_GLOBAL_BACK_REF_ID];
3084 +} StringPattern;
3086 +typedef struct _MultiPattern {
3087 + StringPattern mpStringPattern;
3088 + int mpNumberOfReferences;
3089 + PatternReference *mpRefList;
3090 +} MultiPattern;
3092 +typedef enum {
3093 + PET_SINGLE,
3094 + PET_MULTIPLE,
3095 + PET_REFERENCE
3096 +} PatternElementType;
3098 +typedef struct _PatternElement {
3099 + int peIndex;
3100 + PatternElementKind peKind;
3101 + PatternElementType peType;
3102 + union {
3103 + StringPattern peuSingle;
3104 + MultiPattern peuMulti;
3105 + PatternReference peuRef;
3106 + } peVal;
3107 +} PatternElement;
3109 +typedef struct _PatternElementSet {
3110 + int pesNumberOfPattern;
3111 + PatternElement **pesPattern;
3112 +} PatternElementSet;
3114 +typedef struct _GlobalBackRefElement{
3115 + StringPattern *gbreDefByStrPat;
3116 + char *gbreRegExpText;
3117 +} GlobalBackRefElement;
3119 +typedef struct _MatchPatternTableElement {
3120 + char *mpteName;
3121 + int mpteIndex;
3122 + MatchPatternType mpteType;
3123 + int mpteGroup;
3124 + PatternElementSet mpteAll;
3125 + PatternElementSet mpteStart;
3126 + PatternElementSet mpteMiddle;
3127 + PatternElementSet mpteEnd;
3128 + int mpteFlash;
3129 + int mpteIsMonoPattern;
3130 + int mpteSkipBtwnStartEnd;
3131 + int mpteIgnoreHighLightInfo;
3132 + regexp *mpteStartEndRE;
3133 + GlobalBackRefElement mpteGlobalBackRef[MAX_GLOBAL_BACK_REF_ID];
3134 +} MatchPatternTableElement;
3136 +typedef struct _MatchPatternTable {
3137 + int mptNumberOfElements;
3138 + MatchPatternTableElement **mptElements;
3139 +} MatchPatternTable;
3141 +typedef struct _StringMatchTable {
3142 + char *smtLanguageMode;
3143 + MatchPatternTable *smtAllPatterns;
3144 + regexp *smtAllPatRE;
3145 + regexp *smtFlashPatRE;
3146 + regexp *smtUsedPatRE;
3147 + int smtNumberOfGroups;
3148 + MatchPatternGroupElement **smtGroups;
3149 + int smtNumberOfSeqElements;
3150 + MatchPatternSequenceElement **smtSequence;
3151 +} StringMatchTable;
3153 +typedef enum {
3154 + MT_FLASH_DELIMIT,
3155 + MT_FLASH_RANGE,
3156 + MT_SELECT,
3157 + MT_GOTO,
3158 + MT_MACRO
3159 +} MatchingType;
3161 +int FindMatchingString(
3162 + WindowInfo *window,
3163 + MatchingType matchingType,
3164 + int *charPos,
3165 + int startLimit,
3166 + int endLimit,
3167 + int *matchPos,
3168 + int *matchLength,
3169 + int *direction);
3171 +StringPattern *GetStringPattern(
3172 + MatchPatternTable *table,
3173 + PatternElement *pattern);
3175 +#endif /* NEDIT_PATTERNMATCH_H_INCLUDED */
3176 diff --quilt /dev/null new/source/patternMatchData.c
3177 --- /dev/null
3178 +++ new/source/patternMatchData.c
3179 @@ -0,0 +1,7780 @@
3180 +static const char CVSID[] = "$Id: patternMatchData.c,v 1.4 2004/10/27 21:57:12 uleh Exp $";
3181 +/*******************************************************************************
3182 +* *
3183 +* patternMatchData.c -- Maintain and allow user to edit a matching pattern list*
3184 +* used for pattern matching *
3185 +* *
3186 +* Copyright (C) 2003-2004, Uwe Lehnert *
3187 +* *
3188 +* This is free software; you can redistribute it and/or modify it under the *
3189 +* terms of the GNU General Public License as published by the Free Software *
3190 +* Foundation; either version 2 of the License, or (at your option) any later *
3191 +* version. In addition, you may distribute versions of this program linked to *
3192 +* Motif or Open Motif. See README for details. *
3193 +* *
3194 +* This software is distributed in the hope that it will be useful, but WITHOUT *
3195 +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
3196 +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
3197 +* for more details. *
3198 +* *
3199 +* You should have received a copy of the GNU General Public License along with *
3200 +* software; if not, write to the Free Software Foundation, Inc., 59 Temple *
3201 +* Place, Suite 330, Boston, MA 02111-1307 USA *
3202 +* *
3203 +* Nirvana Text Editor *
3204 +* October 27, 2004 *
3205 +* *
3206 +* Written by Uwe Lehnert *
3207 +* *
3208 +*******************************************************************************/
3209 +#ifdef HAVE_CONFIG_H
3210 +#include "../config.h"
3211 +#endif
3213 +#include <stdlib.h>
3214 +#include <stdio.h>
3215 +#include <limits.h>
3216 +#include <string.h>
3217 +#include <ctype.h>
3219 +#ifdef VMS
3220 +#include "../util/VMSparam.h"
3221 +#else
3222 +#ifndef __MVS__
3223 +#include <sys/param.h>
3224 +#endif
3225 +#endif /*VMS*/
3227 +#include <Xm/Xm.h>
3228 +#include <Xm/Form.h>
3229 +#include <Xm/Frame.h>
3230 +#include <Xm/Text.h>
3231 +#include <Xm/LabelG.h>
3232 +#include <Xm/PushB.h>
3233 +#include <Xm/PushBG.h>
3234 +#include <Xm/ToggleB.h>
3235 +#include <Xm/RowColumn.h>
3236 +#include <Xm/SeparatoG.h>
3238 +#include "../util/misc.h"
3239 +#include "../util/DialogF.h"
3240 +#include "../util/managedList.h"
3242 +#include "regularExp.h"
3243 +#include "textBuf.h"
3244 +#include "nedit.h"
3245 +#include "window.h"
3246 +#include "preferences.h"
3247 +#include "help.h"
3248 +#include "file.h"
3249 +#include "textP.h"
3251 +#include "patternMatch.h"
3252 +#include "patternMatchData.h"
3254 +#ifdef HAVE_DEBUG_H
3255 +#include "../debug.h"
3256 +#endif
3259 + * local synonyms
3260 + */
3261 +#define MAX_LOCAL_BACK_REF_ID 9
3262 +#define LOCAL_BACK_REF_ID_USED -2
3264 +#define MAX_NUMBER_MIDDLE_PATTERN 10
3265 +#define MAX_STRING_PATTERNS 30
3266 +#define MAX_NBR_MATCH_PATTERNS 50
3267 +#define MAX_NBR_MATCH_PATTERN_GROUPS 50
3268 +#define MAX_NBR_SEQ_ELEMENTS MAX_NBR_MATCH_PATTERNS + MAX_NBR_MATCH_PATTERN_GROUPS
3270 +#define MATCH_PAT_NAME_LBL_TXT "Matching Pattern Name"
3271 +#define STRING_PATTERNS_LBL_TXT "String Patterns"
3273 +#define BORDER 4
3274 +#define LIST_RIGHT 41
3275 +#define PLAIN_LM_STRING "PLAIN"
3277 +#define SPNM_NONE_SELECTED "none selected"
3279 +#define KEEP_LANGUAGE_MODE True
3280 +#define DISCARD_LANGUAGE_MODE False
3282 +#define STRING_PATTERN_DIALOG True
3283 +#define CONTEXT_GROUP_DIALOG False
3286 + * local data definitions
3287 + */
3288 +typedef struct _ErrorInfo {
3289 + char *eiDetail;
3290 + char *eiLanguageMode;
3291 + char *eiMPTabElementName;
3292 + char *eiStringPatText;
3293 + char *eiRegExpCompileMsg;
3294 + int eiBackRefNbr;
3295 +} ErrorInfo;
3297 +typedef struct _BackRefBracketInfo {
3298 + int brbiGlobalId;
3299 + char *brbiContentStart;
3300 + int brbiNestingLevel;
3301 +} BackRefBracketInfo;
3303 +typedef struct _RegExpStringInfo {
3304 + int resiNbrOfAddedMultiPat;
3305 + PatternReference **resiAddedMultiPat;
3306 + char *resiNoneWBRegExpString;
3307 + char *resiLeftWBRegExpString;
3308 + char *resiRightWBRegExpString;
3309 + char *resiBothWBRegExpString;
3310 + int resiLocalBackRefID;
3311 +} RegExpStringInfo;
3313 +typedef struct _ReadMatchPatternInfo {
3314 + int rmpiNbrOfElements;
3315 + MatchPatternTableElement *rmpiElement[MAX_NBR_MATCH_PATTERNS];
3316 + int rmpiNbrOfGroups;
3317 + MatchPatternGroupElement *rmpiGroup[MAX_NBR_MATCH_PATTERN_GROUPS];
3318 + int rmpiNbrOfSeqElements;
3319 + MatchPatternSequenceElement *rmpiSequence[MAX_NBR_SEQ_ELEMENTS];
3320 + regexp *rmpiAllPatRE;
3321 + regexp *rmpiFlashPatRE;
3322 +} ReadMatchPatternInfo;
3324 +typedef struct _DialogStringPatternElement {
3325 + char *dspeText;
3326 + PatternElementKind dspeKind;
3327 + PatternWordBoundary dspeWordBoundary;
3328 + int dspeCaseInsensitive;
3329 + int dspeRegularExpression;
3330 +} DialogStringPatternElement;
3332 +typedef struct _DialogStringPatterns {
3333 + int dspNumberOfPatterns;
3334 + DialogStringPatternElement *dspElements[MAX_STRING_PATTERNS];
3335 +} DialogStringPatterns;
3337 +typedef struct _DialogMatchPatternTableElement {
3338 + char *dmpteName;
3339 + MatchPatternType dmpteType;
3340 + DialogStringPatterns dmptePatterns;
3341 + int dmpteSkipBtwnStartEnd;
3342 + int dmpteIgnoreHighLightInfo;
3343 + int dmpteFlash;
3344 +} DialogMatchPatternTableElement;
3346 +typedef struct _DialogMatchPatternGroupElement {
3347 + char *dmpgeName;
3348 + int dmpgeNumberOfSubPatterns;
3349 + char *dmpgeSubPatternIds[MAX_NBR_MATCH_PATTERNS];
3350 +} DialogMatchPatternGroupElement;
3352 +typedef struct _DialogMatchPatternSequenceElement {
3353 + char *dmpseName;
3354 + MatchPatternType dmpseType;
3355 + int dmpseValid;
3356 + void *dmpsePtr;
3357 +} DialogMatchPatternSequenceElement;
3359 +typedef struct _DialogMatchPatternInfo {
3360 + int dmpiNbrOfSeqElements;
3361 + DialogMatchPatternSequenceElement *dmpiSequence[MAX_NBR_SEQ_ELEMENTS];
3362 +} DialogMatchPatternInfo;
3364 +typedef enum {
3365 + DMPTR_OK,
3366 + DMPTR_EMPTY,
3367 + DMPTR_INCOMPLETE
3368 +} DMPTranslationResult;
3370 +typedef struct _NameList {
3371 + int nlNumber;
3372 + char *nlId[MAX_NBR_SEQ_ELEMENTS + 1];
3373 +} NameList;
3376 + * prototypes of local functions
3377 + */
3378 +static void treatDuplicatedPattern(
3379 + MatchPatternTable *table,
3380 + PatternElement *prevPattern,
3381 + PatternReference prevPatRef,
3382 + PatternElement *lastPattern,
3383 + PatternReference lastPatRef);
3384 +static void treatDuplicatedPatternElements(
3385 + MatchPatternTable *table,
3386 + MatchPatternTableElement *prevElement,
3387 + int prevElementIdx,
3388 + PatternElement *lastPattern,
3389 + PatternReference lastPatRef);
3390 +static void treatDuplicatedMTElements(
3391 + MatchPatternTable *table,
3392 + MatchPatternTableElement *prevElement,
3393 + int prevElementIdx,
3394 + MatchPatternTableElement *lastElement,
3395 + int lastElementIdx);
3396 +static void treatDuplicatedMTEntries(
3397 + MatchPatternTableElement **element,
3398 + int nbrOfElements);
3400 +static int createStrPatRegExpOfElement(
3401 + ReadMatchPatternInfo *readPatInfo,
3402 + MatchPatternTableElement *element,
3403 + ErrorInfo *errInfo);
3404 +static int createStrPatRegExp(
3405 + StringPattern *strPat,
3406 + ErrorInfo *errInfo);
3407 +static void adaptCompileMsg(
3408 + char *compileMsg,
3409 + int *globalToLocalBackRef);
3410 +static int localToGlobalBackRef(
3411 + int *globalToLocalBackRef,
3412 + int localId);
3413 +static int createStartEndRegExp(
3414 + ReadMatchPatternInfo *readMatchPatternInfo,
3415 + MatchPatternTableElement *element,
3416 + ErrorInfo *errInfo);
3417 +static int createGroupRegExp(
3418 + ReadMatchPatternInfo *readPatInfo,
3419 + MatchPatternGroupElement *group,
3420 + ErrorInfo *errInfo);
3421 +static void setupRegExpStringBuffers(
3422 + ReadMatchPatternInfo *readMatchPatternInfo,
3423 + RegExpStringInfo *regExpStringInfo);
3424 +static void addSMTRegExpString(
3425 + char *result,
3426 + char *partToAdd,
3427 + const char *postfix);
3428 +static void composeStartEndRegExpString(
3429 + ReadMatchPatternInfo *readMatchPatternInfo,
3430 + MatchPatternTableElement *element,
3431 + char **regExpString);
3432 +static void addElementToRegExpString(
3433 + MatchPatternTableElement *element,
3434 + ReadMatchPatternInfo *readMatchPatternInfo,
3435 + RegExpStringInfo *regExpStringInfo);
3436 +static void addUniquePatternToRegExpString(
3437 + PatternElement *patElement,
3438 + PatternReference *patElementReference,
3439 + ReadMatchPatternInfo *readMatchPatternInfo,
3440 + RegExpStringInfo *regExpStringInfo);
3441 +static void addPatternToRegExpString(
3442 + StringPattern *pattern,
3443 + RegExpStringInfo *regExpStringInfo);
3444 +static char *adaptLocalBackRefs(
3445 + char *regExpText,
3446 + int *commonLocalId);
3447 +static void scanForLocalBackRefs(
3448 + char *regExpText,
3449 + int *localBackRefList);
3450 +static int isMultiPatternNotAdded(
3451 + RegExpStringInfo *regExpStringInfo,
3452 + PatternReference *toBeAddedPR);
3453 +static void catSMTRegExpStrings(
3454 + RegExpStringInfo *regExpStringInfo,
3455 + char **regExpString);
3456 +static void freeRegExpStringInfo(
3457 + RegExpStringInfo *regExpStringInfo);
3458 +static int totalKeywordOfTableLen(
3459 + ReadMatchPatternInfo *info,
3460 + int *nbrOfMultiPatterns);
3461 +static int totalMatchPatternTableElementLen(
3462 + ReadMatchPatternInfo *info,
3463 + MatchPatternTableElement *element,
3464 + int *nbrOfMultiPatterns);
3465 +static int patternElementLen(
3466 + ReadMatchPatternInfo *info,
3467 + PatternElement *patElement,
3468 + int *nbrOfMultiPatterns);
3470 +static void parseMatchingPatternSetError(
3471 + const char *stringStart,
3472 + const char *stoppedAt,
3473 + ErrorInfo *errInfo);
3474 +static void dialogMatchingPatternSetError(
3475 + char *title,
3476 + ErrorInfo *errInfo);
3478 +static char *createMatchPatternsString(
3479 + StringMatchTable *table,
3480 + char *indentStr);
3481 +static char *createPatternElementString(
3482 + MatchPatternTable *table,
3483 + PatternElement *pat);
3485 +static StringMatchTable *readDefaultStringMatchTable(const char *langModeName);
3486 +static int isDefaultMatchPatternTable(StringMatchTable *table);
3488 +static void freeReadMatchPatternInfo( ReadMatchPatternInfo *readPatInfo );
3489 +static void freeStringMatchTable( StringMatchTable *table );
3490 +static void freeMatchPatternTableElement( MatchPatternTableElement *element );
3491 +static void freePatternElement( PatternElement *element );
3492 +static void freeStringPattern( StringPattern *strPat );
3493 +static void freeMatchPatternGroupElement( MatchPatternGroupElement *group );
3494 +static void freeMatchPatternSequenceElement( MatchPatternSequenceElement *sequence );
3496 +static StringMatchTable *readMatchPatternSet(char **inPtr);
3497 +static StringMatchTable *readMatchPatternSetContent(
3498 + char **inPtr,
3499 + char *stringStart,
3500 + char *languageMode);
3501 +static int createRegExpOfPatterns(
3502 + ReadMatchPatternInfo *readPatInfo,
3503 + ErrorInfo *errInfo);
3504 +static int createRegExpOfAllPatterns(
3505 + ReadMatchPatternInfo *readPatInfo,
3506 + ErrorInfo *errInfo);
3507 +static int createRegExpOfStrPatterns(
3508 + ReadMatchPatternInfo *readPatInfo,
3509 + ErrorInfo *errInfo);
3510 +static StringMatchTable *createStringMatchTable(
3511 + ReadMatchPatternInfo *readPatInfo,
3512 + char *languageMode);
3513 +static int readMatchPatternEntry(
3514 + char **inPtr,
3515 + ErrorInfo *errInfo,
3516 + ReadMatchPatternInfo *info);
3517 +static void recordPatternSequence(
3518 + ReadMatchPatternInfo *info,
3519 + char *name,
3520 + MatchPatternType type,
3521 + int index);
3522 +static int assignIndividualGroup(
3523 + ReadMatchPatternInfo *info,
3524 + char **errMsg,
3525 + MatchPatternTableElement *element);
3526 +static MatchPatternTableElement *getPatternOfName(
3527 + ReadMatchPatternInfo *info,
3528 + char *subPatToSearch);
3529 +static MatchPatternGroupElement *readMatchPatternGroup(
3530 + char **inPtr,
3531 + ErrorInfo *errInfo,
3532 + char *name,
3533 + ReadMatchPatternInfo *info);
3534 +static int readPatternElement(
3535 + char **inPtr,
3536 + char **errMsg,
3537 + PatternElement **pattern);
3538 +static PatternElement *createPatternElement(
3539 + char *patternText,
3540 + PatternElementKind patternKind,
3541 + PatternWordBoundary wordBoundary,
3542 + int caseInsensitive,
3543 + int regularExpression);
3545 +static int createGlobalBackRefList(
3546 + ReadMatchPatternInfo *readPatInfo,
3547 + MatchPatternTableElement *element,
3548 + ErrorInfo *errInfo);
3549 +StringPattern *getReadStringPattern(
3550 + ReadMatchPatternInfo *readPatInfo,
3551 + PatternElement *pattern );
3552 +static PatternElement *getReadPatternOfReference(
3553 + ReadMatchPatternInfo *readPatInfo,
3554 + PatternReference *patRef);
3555 +static char *replaceCapturingParentheses(
3556 + const char *source);
3557 +static int parseGlobalBackRefs(
3558 + StringPattern *strPat,
3559 + GlobalBackRefElement *backRefList,
3560 + ErrorInfo *errInfo);
3561 +static int updateGlobalBackRefs(
3562 + StringPattern *strPat,
3563 + GlobalBackRefElement *backRefList,
3564 + ErrorInfo *errInfo);
3565 +static char *createBackRefRegExpText(
3566 + const char *start,
3567 + const char *end);
3568 +static int resolveGlobalBackRefs(
3569 + ReadMatchPatternInfo *readPatInfo,
3570 + MatchPatternTableElement *element,
3571 + ErrorInfo *errInfo);
3572 +static int resolveGlobalBackRefsOfStrPat(
3573 + StringPattern *strPat,
3574 + GlobalBackRefElement *backRefList,
3575 + ErrorInfo *errInfo);
3576 +static char *substituteGlobalBackRef(
3577 + StringPattern *strPat,
3578 + char *subsPtr,
3579 + int globalId,
3580 + int *localId,
3581 + GlobalBackRefElement *backRefList,
3582 + ErrorInfo *errInfo);
3583 +static char *replaceBackRefIdByRegExp(
3584 + StringPattern *strPat,
3585 + char *replaceStartPtr,
3586 + char *regExp);
3587 +static char *convertGlobalToLocalBackRef(
3588 + StringPattern *strPat,
3589 + char *convertPtr);
3591 +static MatchPatternTableElement *readMatchPatternTableElement(
3592 + char **inPtr,
3593 + char **errMsg,
3594 + char *name,
3595 + MatchPatternType type);
3596 +static int sortReadPatternElementSet(
3597 + PatternElementSet *allPat,
3598 + char **errMsg,
3599 + MatchPatternTableElement *result);
3600 +static void countPatternElementKind(
3601 + PatternElementSet *allPat,
3602 + MatchPatternTableElement *result);
3603 +static void sortPatternElementSet(
3604 + PatternElementSet *allPat,
3605 + MatchPatternTableElement *result);
3606 +static void copyPatternSet(
3607 + PatternElementSet *sourcePS,
3608 + PatternElementSet *destPS);
3610 +static int getMPSName(
3611 + char **inPtr,
3612 + ErrorInfo *errInfo,
3613 + char **name );
3614 +static int getMPSTypeAttribute(
3615 + char **inPtr,
3616 + ErrorInfo *errInfo,
3617 + MatchPatternType *type);
3618 +static int getMPSGlobalAttribute(
3619 + char **inPtr,
3620 + char **errMsg,
3621 + int *isMonoPattern,
3622 + int *comment,
3623 + int *flash,
3624 + int *ignoreHighLightInfo);
3625 +static int getMPSPatternAttribute(
3626 + char **inPtr,
3627 + char **errMsg,
3628 + PatternElementKind *patternKind,
3629 + PatternWordBoundary *wordBoundary,
3630 + int *caseInsensitive,
3631 + int *regularExpression);
3633 +static void copyStringMatchTableForDialog(
3634 + StringMatchTable *sourceTable,
3635 + DialogMatchPatternInfo *dialogTable );
3636 +static void *copyMatchPatternElementForDialog(
3637 + MatchPatternTable *table,
3638 + int sourceElementIdx);
3639 +static void copyPatternForDialog(
3640 + MatchPatternTable *table,
3641 + PatternElement *sourcePattern,
3642 + DialogStringPatternElement **dialogPattern );
3643 +static void *copyGroupElementForDialog(
3644 + MatchPatternGroupElement *sourceGroup);
3645 +static void copySequenceElementForDialog(
3646 + StringMatchTable *sourceTable,
3647 + MatchPatternSequenceElement *sourceSeqElement,
3648 + DialogMatchPatternSequenceElement **dialogSeqElement );
3649 +static DialogMatchPatternSequenceElement *copyDialogSequenceElement(
3650 + DialogMatchPatternSequenceElement *sourceSeq);
3651 +static void freeDialogMatchPatternElement(
3652 + DialogMatchPatternTableElement *dialogElement );
3653 +static void freeDialogStringPatternElement(
3654 + DialogStringPatternElement *element);
3655 +static void freeDialogGroupElement(
3656 + DialogMatchPatternGroupElement *dialogGroup );
3657 +static void freeDialogSequenceElement(
3658 + DialogMatchPatternSequenceElement *dialogSeq );
3660 +static void copyDialogStringPatternsFromTable(
3661 + DialogMatchPatternTableElement *tableElement,
3662 + DialogStringPatterns *destPatterns);
3663 +static void copyDialogStringPatterns(
3664 + DialogStringPatterns *sourcePatterns,
3665 + DialogStringPatterns *destPatterns);
3666 +static void freeDialogStringPatterns(
3667 + DialogStringPatterns *patterns);
3669 +static DialogStringPatternElement *copyDialogStringPatternElement(
3670 + DialogStringPatternElement *sourceElement);
3672 +static void copyDialogPatternNamesFromGroup(
3673 + DialogMatchPatternGroupElement *group,
3674 + DialogStringPatterns *destPatterns);
3675 +static DialogStringPatternElement *copyDialogPatternName(
3676 + char *sourcePatternId);
3677 +static void copyDialogPatternNamesToGroup(
3678 + DialogStringPatterns *sourceNames,
3679 + DialogMatchPatternGroupElement *destGroup);
3681 +static void setDialogType(int dialogShowsStringPattern);
3682 +static void setSensitiveWordBoundaryBox(int enable);
3684 +static void *getStringPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
3685 + void *cbArg);
3686 +static void setStringPatternDisplayedCB(void *item, void *cbArg);
3687 +static void freeStringPatternItemCB(void *item);
3689 +static void *getMatchPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
3690 + void *cbArg);
3691 +static void setMatchPatternDisplayedCB(void *item, void *cbArg);
3692 +static void freeMatchPatternItemCB(void *item);
3693 +static int deleteMatchPatternItemCB(int itemIndex, void *cbArg);
3695 +static void matchPatternLangModeCB(Widget w, XtPointer clientData, XtPointer callData);
3696 +static void pmLanguageModeDialogCB(Widget w, XtPointer clientData, XtPointer callData);
3698 +static void destroyCB(Widget w, XtPointer clientData, XtPointer callData);
3699 +static void okCB(Widget w, XtPointer clientData, XtPointer callData);
3700 +static void applyCB(Widget w, XtPointer clientData, XtPointer callData);
3701 +static void checkCB(Widget w, XtPointer clientData, XtPointer callData);
3702 +static void restoreCB(Widget w, XtPointer clientData, XtPointer callData);
3703 +static void deleteCB(Widget w, XtPointer clientData, XtPointer callData);
3704 +static void closeCB(Widget w, XtPointer clientData, XtPointer callData);
3705 +static void helpCB(Widget w, XtPointer clientData, XtPointer callData);
3707 +static void matchPatTypeCB(Widget w, XtPointer clientData, XtPointer callData);
3708 +static void strPatRegExpressionCB(Widget w, XtPointer clientData, XtPointer callData);
3709 +static void changeExistingSubPattern(char *warnTitle);
3710 +static void changeStringPatternToGroup(void);
3711 +static void changeGroupToStringPattern(char *warnTitle);
3713 +static Widget createSubPatternNameMenu(
3714 + Widget parent,
3715 + char *currentSubPatName,
3716 + int allSubPatterns);
3717 +static void setupSubPatternNameList(
3718 + char *currentSubPatName,
3719 + int allSubPatterns,
3720 + NameList *nameList);
3721 +static void createSubPatNameMenuEntry(
3722 + Widget menu,
3723 + char *subPatName);
3724 +static void setSubPatternNameMenu(
3725 + const char *subPatName);
3726 +static void updateSubPatternNameMenu(
3727 + char *currentSubPatName,
3728 + int allSubPatterns);
3729 +static char *getSelectedSubPatternName(void);
3730 +static int isSubPatternNameInCurStrPat(
3731 + char *subPatName);
3733 +static DialogMatchPatternSequenceElement *readMatchPatternFields(int silent);
3734 +static int isStartPatternElementAvailable(
3735 + DialogStringPatterns *dialogPatterns);
3736 +static DialogStringPatternElement *readStringPatternFrameFields(int silent);
3738 +static int matchPatternDialogEmpty(void);
3739 +static int stringPatternFrameEmpty(void);
3740 +static int stringPatternFieldsEmpty(
3741 + int strPatIsRelatedToGroup);
3743 +static int getAndUpdateStringMatchTable(void);
3744 +static void updateStringMatchTable(
3745 + StringMatchTable *newTable);
3747 +static StringMatchTable *getDialogStringMatchTable(
3748 + DMPTranslationResult *result);
3749 +static StringMatchTable *translateDialogStringMatchTable(
3750 + DialogMatchPatternInfo *dialogTable,
3751 + DMPTranslationResult *result);
3752 +static MatchPatternTableElement *translateDialogMatchPatternTableElement(
3753 + DialogMatchPatternTableElement *dialogElement);
3754 +static void translateDialogPatterns(
3755 + DialogStringPatterns *dialogPatterns,
3756 + MatchPatternTableElement *newElement);
3757 +static MatchPatternGroupElement *translateDialogMatchPatternGroupElement(
3758 + ReadMatchPatternInfo *info,
3759 + DialogMatchPatternGroupElement *dialogGroup);
3760 +static void sortDialogPatternElementSet(
3761 + PatternElementSet *allPat,
3762 + MatchPatternTableElement *result);
3764 +static int stringMatchTableDiffer(
3765 + StringMatchTable *oldTable,
3766 + StringMatchTable *newTable);
3768 +static int patternElementDiffer(
3769 + PatternElement *oldPE,
3770 + MatchPatternTable *oldTab,
3771 + PatternElement *newPE,
3772 + MatchPatternTable *newTab);
3774 +static DialogMatchPatternGroupElement *getDialogGroupUsingMatchPattern(
3775 + char *matchPatternName);
3776 +static void removeMatchPatternFromGroup(
3777 + char *matchPatternName,
3778 + DialogMatchPatternGroupElement *group);
3779 +static void removeMatchPatternFromAllGroups(
3780 + char *matchPatternName);
3781 +static void renameMatchPatternInGroup(
3782 + char *oldMatchPatternName,
3783 + char *newMatchPatternName,
3784 + DialogMatchPatternGroupElement *group);
3785 +static void renameMatchPatternInAllGroups(
3786 + char *oldMatchPatternName,
3787 + char *newMatchPatternName);
3789 +static void freeVariableDialogData(
3790 + int keepLanguageModeName);
3792 +static void initGlobalBackRefList(
3793 + GlobalBackRefElement *list);
3794 +static void initStrPatBackRefList(
3795 + StringPattern *strPat);
3797 +StringPattern *getUniqueStringPattern(
3798 + PatternElement *pattern );
3800 +static void initErrorInfo(
3801 + ErrorInfo *errInfo);
3802 +static void freeErrorInfo(
3803 + ErrorInfo *errInfo);
3805 +static void freeXtPtr(void **ptr);
3806 +static void freePtr(void **ptr);
3809 + * matching pattern dialog information
3810 + */
3811 +static struct {
3812 + Widget mpdShell;
3813 + Widget mpdLmOptMenu;
3814 + Widget mpdLmPulldown;
3815 + Widget mpdMatchPatternNamesListW;
3816 + Widget mpdMatchPatternNameLbl;
3817 + Widget mpdMatchPatternNameW;
3818 + Widget mptbIndividualW;
3819 + Widget mptbSubPatternW;
3820 + Widget mptbContextGroupW;
3821 + Widget mpdGlobalAttributesLbl;
3822 + Widget gabSkipBtwStartEndW;
3823 + Widget gabFlashW;
3824 + Widget gabSyntaxBasedW;
3825 + Widget mpdStringPatternsLbl;
3826 + Widget mpdStringPatternsListW;
3827 + Widget mpdStringPatternTypeLbl;
3828 + Widget sptStartW;
3829 + Widget sptMiddleW;
3830 + Widget sptEndW;
3831 + Widget mpdWordBoundaryLbl;
3832 + Widget wbbBothW;
3833 + Widget wbbLeftW;
3834 + Widget wbbRightW;
3835 + Widget wbbNoneW;
3836 + Widget mpdStringAttributesLbl;
3837 + Widget sabCaseSensitiveW;
3838 + Widget sabRegularExpressionW;
3839 + Widget mpdStringPatternLbl;
3840 + Widget mpdStringPatternW;
3841 + Widget mpdSubPatNamesLbl;
3842 + Widget mpdSubPatNamesOptMenu;
3843 + Widget mpdSubPatNamesPulldown;
3844 + char *mpdLangModeName;
3845 + DialogMatchPatternSequenceElement *currentDmptSeqElement;
3846 + DialogMatchPatternTableElement *currentDmptElement;
3847 + DialogMatchPatternGroupElement *currentDmptGroup;
3848 + DialogStringPatterns currentStringPatterns;
3849 + DialogMatchPatternInfo mpdTable;
3850 + int mpdStringPatternIsDisplayed;
3851 +} MatchPatternDialog =
3852 + {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3853 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3854 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3855 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3856 + NULL, NULL, NULL, NULL,
3857 + {0, {NULL}},
3858 + {0, {NULL}},
3859 + True
3860 + };
3863 + * Matching pattern sources loaded from the nedit resources file or set
3864 + * by the user
3865 + */
3866 +static int NbrMatchTables = 0;
3867 +static StringMatchTable *MatchTables[MAX_LANGUAGE_MODES];
3870 + * Syntax:
3871 + * LanguagePatternSet ::=
3872 + * LanguageName{PatternStatement..}
3874 + * PatternStatement ::=
3875 + * name:[s]:[c][f][m][p][u]:([s|m|e][w|l|r][i]:"pattern":)..)\n)|
3876 + * name:g:"sub-pattern name":..\n..
3878 + * TypeAttribute:
3879 + * s : sub-pattern (pattern is only matched, if part of a pattern group).
3880 + * g : pattern (context) group (i.e. a sequence of sub-patterns).
3881 + * default: individual pattern (pattern is matched individually).
3882 + * GlobalAttribute:
3883 + * c : the content between start and end pattern is skipped
3884 + * during parsing (e.g. pattern encloses a comment).
3885 + * f : flash matching pattern (if not set, then only jump
3886 + * to matching pattern is supported).
3887 + * m : mono pattern - set exist out of only one single pattern
3888 + * (start pattern = end pattern; e.g. quotes like ")
3889 + * p : ignore highlight info code of single patterns of this set
3890 + * ("plain").
3891 + * StringPatternKind:
3892 + * s : start string pattern.
3893 + * m : middle string pattern.
3894 + * e : end string pattern.
3895 + * WordBoundaryAttribute:
3896 + * w : pattern is word (i.e. before and after pattern
3897 + * there must be a delimiter).
3898 + * l : before pattern must be a delimiter (left side).
3899 + * r : after pattern must be a delimiter (right side).
3900 + * default: neither before nor after pattern must be a delimiter.
3901 + * StringAttribute:
3902 + * i : pattern is case insensitive (if not set: pattern is
3903 + * case sensitive).
3904 + * x : pattern is regular expression (if not set: pattern is
3905 + * literal string).
3907 + * \n : end of pattern
3908 + */
3910 +static char *DefaultStringMatchTable[] = {
3911 + "PLAIN{"
3912 + "Round braces::fp:s:\"(\":e:\")\":\n"
3913 + "Curly braces::fp:s:\"{\":e:\"}\":\n"
3914 + "Squared braces::fp:s:\"[\":e:\"]\":\n"
3915 + "Sharp braces::fp:s:\"<\":e:\">\":\n}",
3916 + "C++{"
3917 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
3918 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3919 + "Single Quotes:s:cmf:s:\"'\":\n"
3920 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3921 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3922 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3923 + "#ifdef statement:s:f:sx:\"#\\s*ifdef\":sx:\"#\\s*ifndef\":sx:\"#\\s*if\":mx:\"#\\s*elif\":mx:\"#\\s*else\":ex:\"#\\s*endif\":\n"
3924 + "#if group:g:Comment:Double Quotes:Single Quotes:#ifdef statement:\n"
3925 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
3926 + "C{"
3927 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
3928 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3929 + "Single Quotes:s:cmf:s:\"'\":\n"
3930 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3931 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3932 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3933 + "#ifdef statement:s:f:sx:\"#\\s*ifdef\":sx:\"#\\s*ifndef\":sx:\"#\\s*if\":mx:\"#\\s*elif\":mx:\"#\\s*else\":ex:\"#\\s*endif\":\n"
3934 + "#if group:g:Comment:Double Quotes:Single Quotes:#ifdef statement:\n"
3935 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
3936 + "CSS{"
3937 + "comment:s:cf:s:\"/*\":e:\"*/\":\n"
3938 + "curly braces:s:f:s:\"{\":e:\"}\":\n"
3939 + "round braces:s:f:s:\"(\":e:\")\":\n"
3940 + "double quotes:s:cfm:s:\"\"\"\":\n"
3941 + "single quotes:s:cfm:s:\"'\":\n"
3942 + "braces:g:comment:single quotes:double quotes:curly braces:round braces:\n}",
3943 + "Csh{"
3944 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3945 + "Single Quotes:s:cmf:s:\"'\":\n"
3946 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3947 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3948 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3949 + "if statement:s:f:sw:\"if\":mw:\"else\":ew:\"endif\":\n"
3950 + "switch statement:s:f:sw:\"switch\":mw:\"case\":mw:\"default\":ew:\"endsw\":\n"
3951 + "foreach statement:s:f:sw:\"for\":ew:\"end\":\n"
3952 + "while statement:s:f:sw:\"while\":ew:\"end\":\n"
3953 + "statement group:g:Double Quotes:Single Quotes:if statement:switch statement:foreach statement:while statement:\n"
3954 + "Braces:g:Double Quotes:Single Quotes:Squared braces:Round braces:Curly braces:\n}",
3955 + "Java{"
3956 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
3957 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3958 + "Single Quotes:s:cmf:s:\"'\":\n"
3959 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3960 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3961 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3962 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
3963 + "JavaScript{"
3964 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
3965 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3966 + "Single Quotes:s:cmf:s:\"'\":\n"
3967 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3968 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3969 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3970 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
3971 + "Makefile{"
3972 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3973 + "Single Quotes:s:cmf:s:\"'\":\n"
3974 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3975 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3976 + "Braces:g:Double Quotes:Single Quotes:Curly braces:Round braces:\n}",
3977 + "NEdit Macro{"
3978 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3979 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3980 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3981 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3982 + "Braces:g:Double Quotes:Curly braces:Round braces:Squared braces:\n}",
3983 + "Pascal{"
3984 + "Single Quotes:s:cmf:s:\"'\":\n"
3985 + "Comment1:s:cf:s:\"(*\":e:\"*)\":\n"
3986 + "Comment2:s:cf:s:\"{\":e:\"}\":\n"
3987 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3988 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3989 + "Block:s:f:swi:\"begin\":ewi:\"end\":\n"
3990 + "Case:s:fp:swi:\"case\":ewi:\"end\":\n"
3991 + "Record:s:f:swi:\"record\":ewi:\"end\":\n"
3992 + "Statement:g:Comment1:Comment2:Single Quotes:Block:Case:Record:\n"
3993 + "Braces:g:Comment1:Comment2:Single Quotes:Round braces:Squared braces:\n}",
3994 + "Perl{"
3995 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
3996 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3997 + "Single Quotes:s:cmf:s:\"'\":\n"
3998 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3999 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4000 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4001 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
4002 + "SGML HTML{"
4003 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4004 + "Single Quotes:s:cmf:s:\"'\":\n"
4005 + "Sharp braces:s:f:s:\"<\":e:\">\":\n"
4006 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4007 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4008 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4009 + "Braces:g:Double Quotes:Single Quotes:Sharp braces:Curly braces:Round braces:Squared braces:\n}",
4010 + "Sh Ksh Bash{"
4011 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4012 + "Single Quotes:s:cmf:s:\"'\":\n"
4013 + "Back Quotes:s:cfm:s:\"`\":\n"
4014 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4015 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4016 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4017 + "if statement:s:f:sw:\"if\":mw:\"elif\":mw:\"else\":ew:\"fi\":\n"
4018 + "case statement:s:f:sw:\"case\":ew:\"esac\":\n"
4019 + "for statement:s:f:sw:\"for\":mw:\"do\":ew:\"done\":\n"
4020 + "while statement:s:f:sw:\"while\":mw:\"do\":ew:\"done\":\n"
4021 + "statement group:g:Double Quotes:Single Quotes:if statement:case statement:for statement:while statement:\n"
4022 + "Braces:g:Double Quotes:Single Quotes:Back Quotes:Squared braces:Round braces:Curly braces:\n}",
4023 + "XML{"
4024 + "round braces:s:f:s:\"(\":e:\")\":\n"
4025 + "comment:s:cf:s:\"<!--\":e:\"-->\":\n"
4026 + "cdata + ignore:s:cf:sx:\"\\<!\\[((?icdata)|(\\s*IGNORE\\s*))\\[\":ex:\"\\]\\]\\>\":\n"
4027 + "short element:s:cf:sx:\"(?n\\<[\\l_][^@$%/\"\"';!>\\s]*(?=[^>]*/\\>))\":ex:\"/\\>\":\n"
4028 + "element pair:s:f:sx:\"(?n\\<(*1[\\l|_][^@$%/\"\"';!>\\s]*)\\>)\":sx:\"(?n\\<(*1[\\l|_][^@$%/\"\"';!>\\s]*)(?=[^>]*[^/]\\>))\":eix:\"\\</\\1\\>\":\n"
4029 + "processing instruction:s:f:sx:\"\\<\\?\\S+\":ex:\"\\?\\>\":\n"
4030 + "double quotes:s:cmf:s:\"\"\"\":\n"
4031 + "single quotes:s:cmf:s:\"'\":\n"
4032 + "tags:g:comment:double quotes:single quotes:round braces:cdata + ignore:element pair:short element:processing instruction:\n}",
4033 + };
4035 +static char *StandardStringMatchTable =
4036 + "{Round braces::fp:s:\"(\":e:\")\":\n"
4037 + "Curly braces::fp:s:\"{\":e:\"}\":\n"
4038 + "Squared braces::fp:s:\"[\":e:\"]\":\n}";
4041 +** Return string match table related to given language mode name.
4042 +** Return NULL, if no table is found.
4044 +void *FindStringMatchTable(const char *langModeName)
4046 + const char *nameToSearch;
4047 + int i;
4049 + if (langModeName == NULL)
4050 + nameToSearch = PLAIN_LM_STRING;
4051 + else
4052 + nameToSearch = langModeName;
4054 + for (i=0; i<NbrMatchTables; i++)
4055 + if (!strcmp(nameToSearch, MatchTables[i]->smtLanguageMode))
4056 + return (void *)MatchTables[i];
4057 + return NULL;
4061 +** Change the language mode name of string match tables for language
4062 +** "oldName" to "newName" in both the stored tables, and the table
4063 +** currently being edited in the dialog.
4065 +void RenameStringMatchTable(const char *oldName, const char *newName)
4067 + int i;
4069 + for (i=0; i<NbrMatchTables; i++)
4071 + if (!strcmp(oldName, MatchTables[i]->smtLanguageMode))
4073 + XtFree(MatchTables[i]->smtLanguageMode);
4074 + MatchTables[i]->smtLanguageMode = XtNewString(newName);
4077 + if (MatchPatternDialog.mpdShell != NULL)
4079 + if (!strcmp(MatchPatternDialog.mpdLangModeName, oldName))
4081 + XtFree(MatchPatternDialog.mpdLangModeName);
4082 + MatchPatternDialog.mpdLangModeName = XtNewString(newName);
4088 +** Delete string match table related to given language mode name.
4090 +void DeleteStringMatchTable(const char *langModeName)
4092 + int i;
4094 + for (i=0; i<NbrMatchTables; i++)
4096 + if (!strcmp(langModeName, MatchTables[i]->smtLanguageMode))
4098 + /*
4099 + * free (delete) existing matching pattern
4100 + */
4101 + freeStringMatchTable(MatchTables[i]);
4102 + memmove(
4103 + &MatchTables[i],
4104 + &MatchTables[i+1],
4105 + (NbrMatchTables-1 - i) * sizeof(StringMatchTable *));
4106 + NbrMatchTables--;
4107 + break;
4113 +** Assign a standard string match table to a given new language mode.
4115 +void AssignStandardStringMatchTable(const char *langModeName)
4117 + char *list;
4118 + StringMatchTable *newTable;
4120 + /*
4121 + * assign standard table for new language mode
4122 + * add table to end
4123 + */
4124 + list = StandardStringMatchTable;
4125 + newTable =
4126 + readMatchPatternSetContent(&list, list, XtNewString(langModeName));
4128 + /*
4129 + * add table to end
4130 + */
4131 + MatchTables[NbrMatchTables++] = newTable;
4135 +** Returns True if there is a string match table, or potential table
4136 +** not yet committed in the match pattern dialog for a language mode,
4138 +int LMHasStringMatchTable(const char *languageMode)
4140 + StringMatchTable *table = FindStringMatchTable(languageMode);
4142 + if (table != NULL && table->smtNumberOfSeqElements != 0)
4143 + return True;
4144 + return MatchPatternDialog.mpdShell != NULL &&
4145 + !strcmp(MatchPatternDialog.mpdLangModeName, languageMode) &&
4146 + MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements != 0;
4150 +** Read a string representing string matching pattern sets and add them
4151 +** to the StringMatchTable list of loaded string match patterns.
4152 +** Returns true, if read of string was successful.
4154 +int LoadMatchPatternString(char *inString)
4156 + char *inPtr = inString;
4157 + StringMatchTable *table;
4158 + int i;
4160 + for (;;)
4162 + /*
4163 + * read each matching pattern set
4164 + */
4165 + table = readMatchPatternSet(&inPtr);
4167 + if (table != NULL)
4169 + /*
4170 + * add/change the pattern set in the list
4171 + */
4172 + for (i=0; i<NbrMatchTables; i++)
4174 + if (!strcmp(MatchTables[i]->smtLanguageMode, table->smtLanguageMode))
4176 + freeStringMatchTable(MatchTables[i]);
4177 + MatchTables[i] = table;
4178 + break;
4181 + if (i == NbrMatchTables)
4183 + MatchTables[NbrMatchTables++] = table;
4184 + if (NbrMatchTables > MAX_LANGUAGE_MODES)
4186 + return False;
4191 + /*
4192 + * find end of this pattern. if the string ends here, we're done
4193 + */
4194 + inPtr = strstr(inPtr, "\n");
4195 + if (inPtr == NULL)
4197 + return True;
4200 + /*
4201 + * skip newline, tabs & spaces in front of next pattern.
4202 + * if the string ends here, we're done
4203 + */
4204 + inPtr += strspn(inPtr, " \t\n");
4205 + if (*inPtr == '\0')
4207 + return True;
4213 +** Create a string in the correct format for the matchPatterns resource,
4214 +** containing all of the matching pattern information from the stored
4215 +** matching pattern sets for this NEdit session.
4217 +char *WriteMatchPatternString(void)
4219 + char *outStr, *str, *escapedStr;
4220 + textBuffer *outBuf;
4221 + int i, written = False;
4222 + StringMatchTable *table;
4224 + outBuf = BufCreate();
4226 + for (i=0; i<NbrMatchTables; i++)
4228 + table = MatchTables[i];
4230 + written = True;
4232 + BufInsert(outBuf, outBuf->length, table->smtLanguageMode);
4233 + BufInsert(outBuf, outBuf->length, ":");
4235 + if (isDefaultMatchPatternTable(table))
4237 + BufInsert(outBuf, outBuf->length, "Default\n\t");
4239 + else
4241 + BufInsert(outBuf, outBuf->length, "{\n");
4242 + BufInsert(outBuf, outBuf->length,
4243 + str = createMatchPatternsString(table, "\t\t"));
4244 + XtFree(str);
4245 + BufInsert(outBuf, outBuf->length, "\t}\n\t");
4249 + /*
4250 + * Get the output string, and lop off the trailing newline and tab
4251 + */
4252 + outStr = BufGetRange(outBuf, 0, outBuf->length - (written?2:0));
4253 + BufFree(outBuf);
4255 + /*
4256 + * Protect newlines and backslashes from translation by the resource
4257 + * reader
4258 + */
4259 + escapedStr = EscapeSensitiveChars(outStr);
4261 + XtFree(outStr);
4263 + return escapedStr;
4267 +** Check, if last pattern is a duplicate of a previous pattern.
4268 +** Convert last pattern to a reference, if so.
4270 +static void treatDuplicatedPattern(
4271 + MatchPatternTable *table,
4272 + PatternElement *prevPattern,
4273 + PatternReference prevPatRef,
4274 + PatternElement *lastPattern,
4275 + PatternReference lastPatRef)
4277 + StringPattern *prevStringPat;
4278 + StringPattern *lastStringPat;
4279 + StringPattern *stringPat;
4280 + PatternReference *oldList;
4281 + int nbrOfRef;
4283 + /*
4284 + * No duplicate check needed, if previous pattern is a reference,
4285 + * due to the related multi pattern element is checked before.
4286 + */
4287 + if (prevPattern->peType == PET_REFERENCE)
4288 + return;
4290 + prevStringPat = GetStringPattern(table, prevPattern);
4291 + lastStringPat = GetStringPattern(table, lastPattern);
4293 + if (!AllocatedStringsDiffer(prevStringPat->spText, lastStringPat->spText) &&
4294 + !AllocatedStringsDiffer(prevStringPat->spOrigText, lastStringPat->spOrigText) &&
4295 + prevStringPat->spWordBoundary == lastStringPat->spWordBoundary &&
4296 + prevStringPat->spCaseInsensitive == lastStringPat->spCaseInsensitive &&
4297 + prevStringPat->spRegularExpression == lastStringPat->spRegularExpression)
4299 + /*
4300 + * Patterns are identical: Is prevPattern already a multi pattern ?
4301 + */
4302 + if (prevPattern->peType == PET_MULTIPLE)
4304 + /*
4305 + * just add ref. to "lastPattern" to the ref. list
4306 + */
4307 + (prevPattern->peVal.peuMulti.mpNumberOfReferences) ++;
4308 + nbrOfRef = prevPattern->peVal.peuMulti.mpNumberOfReferences;
4309 + oldList = prevPattern->peVal.peuMulti.mpRefList;
4310 + prevPattern->peVal.peuMulti.mpRefList =
4311 + (PatternReference *)XtMalloc( nbrOfRef * sizeof(PatternReference) );
4312 + memcpy(
4313 + prevPattern->peVal.peuMulti.mpRefList,
4314 + oldList,
4315 + (nbrOfRef-1) * sizeof(PatternReference) );
4316 + prevPattern->peVal.peuMulti.mpRefList[nbrOfRef-1] = lastPatRef;
4317 + XtFree( (char *)oldList );
4319 + else
4321 + /*
4322 + * convert prev. single pattern to multi pattern
4323 + */
4324 + stringPat = &prevPattern->peVal.peuSingle;
4325 + prevPattern->peType = PET_MULTIPLE;
4326 + prevPattern->peVal.peuMulti.mpStringPattern = *stringPat;
4327 + prevPattern->peVal.peuMulti.mpNumberOfReferences = 1;
4328 + prevPattern->peVal.peuMulti.mpRefList =
4329 + (PatternReference *)XtMalloc( sizeof(PatternReference) );
4330 + prevPattern->peVal.peuMulti.mpRefList[0] = lastPatRef;
4333 + /*
4334 + * convert last single pattern to reference
4335 + */
4336 + freeStringPattern( &(lastPattern->peVal.peuSingle) );
4337 + lastPattern->peType = PET_REFERENCE;
4338 + lastPattern->peVal.peuRef = prevPatRef;
4343 +** Check, if last pattern is a duplicate of a pattern stored within a
4344 +** previous match pattern table element.
4345 +** Convert last pattern to a reference, if so.
4347 +static void treatDuplicatedPatternElements(
4348 + MatchPatternTable *table,
4349 + MatchPatternTableElement *prevElement,
4350 + int prevElementIdx,
4351 + PatternElement *lastPattern,
4352 + PatternReference lastPatRef)
4354 + int i;
4355 + PatternReference prevPatRef;
4357 + prevPatRef.prElementIdx = prevElementIdx;
4359 + for (i=0; i<prevElement->mpteAll.pesNumberOfPattern; i++)
4361 + prevPatRef.prPatternIdx = i;
4362 + treatDuplicatedPattern(
4363 + table,
4364 + prevElement->mpteAll.pesPattern[i],
4365 + prevPatRef,
4366 + lastPattern,
4367 + lastPatRef);
4372 +** Check, if a pattern of last match pattern table element is a
4373 +** duplicate of a pattern stored within a previous match pattern table
4374 +** element.
4375 +** Convert duplicated last patterns to references, if so.
4377 +static void treatDuplicatedMTElements(
4378 + MatchPatternTable *table,
4379 + MatchPatternTableElement *prevElement,
4380 + int prevElementIdx,
4381 + MatchPatternTableElement *lastElement,
4382 + int lastElementIdx)
4384 + int i;
4385 + PatternReference lastPatRef;
4387 + lastPatRef.prElementIdx = lastElementIdx;
4389 + for (i=0; i<lastElement->mpteAll.pesNumberOfPattern; i++)
4391 + lastPatRef.prPatternIdx = i;
4392 + treatDuplicatedPatternElements(
4393 + table,
4394 + prevElement,
4395 + prevElementIdx,
4396 + lastElement->mpteAll.pesPattern[i],
4397 + lastPatRef);
4402 +** Convert all duplicated patterns of given match pattern table to
4403 +** references.
4405 +static void treatDuplicatedMTEntries(
4406 + MatchPatternTableElement **element,
4407 + int nbrOfElements)
4409 + int i;
4410 + MatchPatternTableElement *lastElement;
4411 + int lastElementIdx;
4412 + MatchPatternTable table;
4414 + if (nbrOfElements < 2)
4415 + return;
4417 + lastElementIdx = nbrOfElements - 1;
4418 + lastElement = element[lastElementIdx];
4420 + table.mptElements = element;
4421 + table.mptNumberOfElements = nbrOfElements;
4423 + for (i=0; i<nbrOfElements-1; i ++)
4425 + treatDuplicatedMTElements( &table, element[i], i, lastElement, lastElementIdx );
4430 +** Compile regular expressions of all string patterns of given
4431 +** match pattern table element.
4432 +** Returns true, if compilation fails.
4434 +static int createStrPatRegExpOfElement(
4435 + ReadMatchPatternInfo *readPatInfo,
4436 + MatchPatternTableElement *element,
4437 + ErrorInfo *errInfo)
4439 + int i;
4440 + StringPattern *strPat;
4442 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
4444 + strPat = getReadStringPattern(readPatInfo, element->mpteAll.pesPattern[i]);
4446 + /*
4447 + * if current string pattern holds a regular expression, then
4448 + * compile it
4449 + */
4450 + if (strPat->spRegularExpression)
4452 + if (createStrPatRegExp(strPat, errInfo))
4454 + /*
4455 + * compilation was not successful
4456 + */
4457 + errInfo->eiMPTabElementName = XtNewString(element->mpteName);
4458 + return True;
4463 + return False;
4467 +** Compile regular expressions of given string pattern.
4468 +** Returns true, if compilation fails.
4470 +static int createStrPatRegExp(
4471 + StringPattern *strPat,
4472 + ErrorInfo *errInfo)
4474 + char *regExpString;
4475 + char *compileMsg;
4477 + /*
4478 + * compose regular expression for start string pattern.
4479 + */
4480 + if( strPat->spCaseInsensitive)
4482 + /*
4483 + * Add '(?i .. )' to given text for case insensitive search.
4484 + * Allocate buffer to hold 5 more char than text length
4485 + * (4 char '(?i)' + \0 char.
4486 + */
4487 + regExpString = XtMalloc(strPat->spLength + 5);
4488 + strcpy(regExpString, "(?i");
4489 + strcat(regExpString, strPat->spText);
4490 + strcat(regExpString, ")");
4492 + else
4494 + regExpString = strPat->spText;
4497 + /*
4498 + * compile regular expression & free allocated string buffer,
4499 + * if applicable.
4500 + */
4501 + strPat->spTextRE =
4502 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
4504 + if (strPat->spTextRE == NULL)
4506 + /*
4507 + * compilation was not successful: adapt error reason by
4508 + * converting local backrefs to global ones.
4509 + */
4510 + adaptCompileMsg(compileMsg, strPat->spGlobalToLocalBackRef);
4512 + errInfo->eiRegExpCompileMsg = compileMsg;
4513 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
4516 + if (strPat->spCaseInsensitive)
4517 + XtFree( regExpString );
4519 + return (strPat->spTextRE == NULL);
4523 +** adapt regular expression compilation message by converting local
4524 +** backrefs to global ones.
4526 +static void adaptCompileMsg(
4527 + char *compileMsg,
4528 + int *globalToLocalBackRef)
4530 + int localId;
4531 + int globalId;
4532 + char *s = compileMsg;
4534 + while (*s != '\0')
4536 + if (*s == '\\')
4538 + if (isdigit((unsigned char)*(s+1)))
4540 + /*
4541 + * \n (n=1..9) found: substitute local by global back ref.
4542 + */
4543 + s ++;
4545 + localId =
4546 + (int)((unsigned char)*s - (unsigned char)'0');
4548 + globalId = localToGlobalBackRef(globalToLocalBackRef, localId);
4550 + *s = (char)((int)('0') + globalId);
4552 + else if (*(s+1) != '\0')
4553 + s ++;
4555 + s ++;
4560 +** translate given local backref to global backref by using
4561 +** given globalToLocalBackRef list.
4563 +static int localToGlobalBackRef(
4564 + int *globalToLocalBackRef,
4565 + int localId)
4567 + int i;
4569 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
4571 + if (globalToLocalBackRef[i] == localId)
4572 + return i+1;
4575 + return 0;
4579 +** Create a regular expression holding keywords of given start & end
4580 +** pattern set.
4581 +** Returns true, if creation of regular expression has failed.
4583 +static int createStartEndRegExp(
4584 + ReadMatchPatternInfo *readMatchPatternInfo,
4585 + MatchPatternTableElement *element,
4586 + ErrorInfo *errInfo)
4588 + char *regExpString;
4589 + char *compileMsg;
4591 + /*
4592 + * compose regular expression for start / end pattern.
4593 + */
4594 + composeStartEndRegExpString(
4595 + readMatchPatternInfo,
4596 + element,
4597 + &regExpString);
4599 + /*
4600 + * compile regular expression & free allocated string buffer.
4601 + */
4602 + element->mpteStartEndRE =
4603 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
4605 + XtFree( regExpString );
4607 + if( element->mpteStartEndRE == NULL)
4609 + errInfo->eiRegExpCompileMsg = compileMsg;
4610 + errInfo->eiDetail = "Error compiling start / end reg. exp.";
4613 + return (element->mpteStartEndRE == NULL);
4617 +** Create a regular expression holding keywords of given group element.
4618 +** Returns true, if creation of regular expression has failed.
4620 +static int createGroupRegExp(
4621 + ReadMatchPatternInfo *readPatInfo,
4622 + MatchPatternGroupElement *group,
4623 + ErrorInfo *errInfo)
4625 + int i;
4626 + MatchPatternTableElement *element;
4627 + RegExpStringInfo regExpStringInfo;
4628 + char *regExpString;
4629 + regexp *keywordRE;
4630 + char *compileMsg;
4632 + /*
4633 + * Allocate buffers for keyword regular expression of this group.
4634 + */
4635 + setupRegExpStringBuffers(
4636 + readPatInfo,
4637 + &regExpStringInfo);
4639 + for (i=0; i<group->mpgeNumberOfSubPatterns; i++)
4641 + element = getPatternOfName(readPatInfo, group->mpgeSubPatternIds[i]);
4642 + /*
4643 + * Add the keywords of the sub pattern to the keyword regular
4644 + * expression string buffer of new group.
4645 + */
4646 + addElementToRegExpString(
4647 + element,
4648 + readPatInfo,
4649 + &regExpStringInfo);
4652 + /*
4653 + * Assemble and compile the resulting keyword regular expression string.
4654 + */
4655 + catSMTRegExpStrings(
4656 + &regExpStringInfo,
4657 + &regExpString);
4659 + keywordRE = CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
4661 + XtFree( regExpString );
4663 + if (keywordRE == NULL)
4665 + errInfo->eiMPTabElementName = XtNewString(group->mpgeName);
4666 + errInfo->eiRegExpCompileMsg = compileMsg;
4667 + errInfo->eiDetail = "Group: Compile reg. exp. error";
4670 + group->mpgeKeywordRE = keywordRE;
4672 + return (keywordRE == NULL);
4676 +** Allocate memory for regular expression strings to be
4677 +** created out of read match pattern info.
4679 +static void setupRegExpStringBuffers(
4680 + ReadMatchPatternInfo *readMatchPatternInfo,
4681 + RegExpStringInfo *regExpStringInfo)
4683 + int totalLen;
4684 + int nbrOfMultiPatterns;
4685 + int sizeOfPatRefs;
4687 + /*
4688 + * determine total length of pattern characters to determine
4689 + * the size of a string buffer for the regular expression to
4690 + * compose. Count number of total multi patterns, too.
4691 + */
4692 + totalLen =
4693 + totalKeywordOfTableLen( readMatchPatternInfo, &nbrOfMultiPatterns );
4695 + /*
4696 + * allocate memory to store added multi pattern references (to avoid
4697 + * duplicated keywords strings later on).
4698 + */
4699 + sizeOfPatRefs = sizeof(PatternReference *) * nbrOfMultiPatterns;
4701 + regExpStringInfo->resiAddedMultiPat =
4702 + (PatternReference **)XtMalloc( sizeOfPatRefs );
4704 + regExpStringInfo->resiNbrOfAddedMultiPat = 0;
4706 + /*
4707 + * init. ID of capturing local backrefs
4708 + */
4709 + regExpStringInfo->resiLocalBackRefID = 1;
4711 + /*
4712 + * allocate & init. string buffers for regular expression:
4713 + * 3 times the size + x of all pattern characters (due to
4714 + * a.) each char may need to be escaped
4715 + * b.) '<(?:', ')>', ')' and '|' need to be added.
4716 + */
4717 + regExpStringInfo->resiNoneWBRegExpString = XtMalloc( 3 * totalLen );
4718 + regExpStringInfo->resiLeftWBRegExpString = XtMalloc( 3 * totalLen + 5 );
4719 + regExpStringInfo->resiRightWBRegExpString = XtMalloc( 3 * totalLen + 5 );
4720 + regExpStringInfo->resiBothWBRegExpString = XtMalloc( 3 * totalLen + 6 );
4722 + strcpy( regExpStringInfo->resiNoneWBRegExpString, "" );
4723 + strcpy( regExpStringInfo->resiLeftWBRegExpString, "" );
4724 + strcpy( regExpStringInfo->resiRightWBRegExpString, "" );
4725 + strcpy( regExpStringInfo->resiBothWBRegExpString, "" );
4729 +** Concatenate given 'partToAdd' string to result string, separated
4730 +** by an OR ('|'). Add 'postfix' at end of result string.
4732 +static void addSMTRegExpString(
4733 + char *result,
4734 + char *partToAdd,
4735 + const char *postfix)
4737 + if (strlen(partToAdd) != 0)
4739 + if (strlen(result) != 0)
4741 + strcat( result, "|" );
4744 + strcat( result, partToAdd );
4746 + strcat( result, postfix );
4752 +** Return a string representing given string match table.
4754 +static char *createMatchPatternsString(
4755 + StringMatchTable *table,
4756 + char *indentStr)
4758 + char *outStr, *str;
4759 + textBuffer *outBuf;
4760 + int i, j;
4761 + MatchPatternSequenceElement *seq;
4762 + MatchPatternTableElement *element;
4763 + MatchPatternGroupElement *group;
4765 + outBuf = BufCreate();
4767 + for (i=0; i<table->smtNumberOfSeqElements; i++)
4769 + seq = table->smtSequence[i];
4771 + BufInsert(outBuf, outBuf->length, indentStr);
4772 + BufInsert(outBuf, outBuf->length, seq->mpseName);
4773 + BufInsert(outBuf, outBuf->length, ":");
4775 + if (seq->mpseType == MPT_GROUP)
4777 + BufInsert(outBuf, outBuf->length, "g:");
4779 + group = table->smtGroups[seq->mpseIndex];
4781 + for (j=0; j < group->mpgeNumberOfSubPatterns; j ++)
4783 + BufInsert(outBuf, outBuf->length, group->mpgeSubPatternIds[j]);
4784 + BufInsert(outBuf, outBuf->length, ":");
4787 + else
4789 + if (seq->mpseType == MPT_SUB)
4791 + BufInsert(outBuf, outBuf->length, "s");
4793 + BufInsert(outBuf, outBuf->length, ":");
4795 + element = table->smtAllPatterns->mptElements[seq->mpseIndex];
4797 + /*
4798 + * write global attributes
4799 + */
4800 + if (element->mpteSkipBtwnStartEnd)
4801 + BufInsert(outBuf, outBuf->length, "c");
4802 + if (element->mpteFlash)
4803 + BufInsert(outBuf, outBuf->length, "f");
4804 + if (element->mpteIsMonoPattern)
4805 + BufInsert(outBuf, outBuf->length, "m");
4806 + if (element->mpteIgnoreHighLightInfo)
4807 + BufInsert(outBuf, outBuf->length, "p");
4808 + BufInsert(outBuf, outBuf->length, ":");
4810 + /*
4811 + * write string patterns
4812 + */
4813 + for (j=0; j < element->mpteAll.pesNumberOfPattern; j ++)
4815 + BufInsert(
4816 + outBuf,
4817 + outBuf->length,
4818 + str =
4819 + createPatternElementString(
4820 + table->smtAllPatterns,
4821 + element->mpteAll.pesPattern[j]));
4822 + XtFree(str);
4826 + BufInsert(outBuf, outBuf->length, "\n");
4829 + outStr = BufGetAll(outBuf);
4830 + BufFree(outBuf);
4832 + return outStr;
4836 +** Return a string representing given pattern element.
4838 +static char *createPatternElementString(
4839 + MatchPatternTable *table,
4840 + PatternElement *pat)
4842 + char *outStr, *str;
4843 + textBuffer *outBuf;
4844 + StringPattern *strPat;
4846 + outBuf = BufCreate();
4848 + strPat = GetStringPattern(table, pat);
4850 + /*
4851 + * write string pattern kind
4852 + */
4853 + if (pat->peKind == PEK_START)
4854 + BufInsert(outBuf, outBuf->length, "s");
4855 + else if (pat->peKind == PEK_MIDDLE)
4856 + BufInsert(outBuf, outBuf->length, "m");
4857 + else if (pat->peKind == PEK_END)
4858 + BufInsert(outBuf, outBuf->length, "e");
4860 + /*
4861 + * write word boundary
4862 + */
4863 + if (strPat->spWordBoundary == PWB_BOTH)
4864 + BufInsert(outBuf, outBuf->length, "w");
4865 + else if (strPat->spWordBoundary == PWB_LEFT)
4866 + BufInsert(outBuf, outBuf->length, "l");
4867 + else if (strPat->spWordBoundary == PWB_RIGHT)
4868 + BufInsert(outBuf, outBuf->length, "r");
4870 + /*
4871 + * write case insensitive flag
4872 + */
4873 + if (strPat->spCaseInsensitive)
4874 + BufInsert(outBuf, outBuf->length, "i");
4876 + /*
4877 + * write regular expression flag
4878 + */
4879 + if (strPat->spRegularExpression)
4880 + BufInsert(outBuf, outBuf->length, "x");
4882 + BufInsert(outBuf, outBuf->length, ":");
4884 + /*
4885 + * write pattern string
4886 + */
4887 + if( strPat->spOrigText != NULL)
4888 + BufInsert(
4889 + outBuf,
4890 + outBuf->length,
4891 + str = MakeQuotedString(strPat->spOrigText));
4892 + else
4893 + BufInsert(
4894 + outBuf,
4895 + outBuf->length,
4896 + str = MakeQuotedString(strPat->spText));
4897 + XtFree(str);
4899 + BufInsert(outBuf, outBuf->length, ":");
4901 + outStr = BufGetAll(outBuf);
4902 + BufFree(outBuf);
4904 + return outStr;
4908 +** Given a language mode name, determine if there is a default (built-in)
4909 +** string match table available for that language mode, and if so, read it and
4910 +** return a new allocated copy of it. The returned pattern set should be
4911 +** freed by the caller with freeStringMatchTable().
4913 +static StringMatchTable *readDefaultStringMatchTable(const char *langModeName)
4915 + int i, modeNameLen;
4916 + char *list;
4918 + modeNameLen = strlen(langModeName);
4920 + for (i=0; i<(int)XtNumber(DefaultStringMatchTable); i++)
4922 + if (!strncmp(langModeName, DefaultStringMatchTable[i], modeNameLen) &&
4923 + DefaultStringMatchTable[i][modeNameLen] == '{')
4925 + list = DefaultStringMatchTable[i];
4926 + return readMatchPatternSet(&list);
4930 + list = StandardStringMatchTable;
4931 + return readMatchPatternSetContent(&list, list, XtNewString(langModeName));
4935 +** Return true, if table exactly matches one of the default matching
4936 +** pattern tables.
4938 +static int isDefaultMatchPatternTable(StringMatchTable *table)
4940 + StringMatchTable *defaultTable;
4941 + int retVal;
4943 + defaultTable = readDefaultStringMatchTable(table->smtLanguageMode);
4945 + if (defaultTable == NULL)
4946 + return False;
4948 + retVal = !stringMatchTableDiffer(table, defaultTable);
4950 + freeStringMatchTable(defaultTable);
4952 + return retVal;
4956 +** Read in a string match pattern table character string,
4957 +** and advance *inPtr beyond it.
4958 +** Returns NULL and outputs an error to stderr on failure.
4960 +static StringMatchTable *readMatchPatternSet(char **inPtr)
4962 + char *languageMode;
4963 + StringMatchTable *table = NULL;
4964 + char *stringStart = *inPtr;
4965 + ErrorInfo errInfo;
4967 + initErrorInfo(&errInfo);
4969 + /*
4970 + * remove leading whitespace
4971 + */
4972 + *inPtr += strspn(*inPtr, " \t\n");
4974 + /*
4975 + * read language mode field
4976 + */
4977 + languageMode = ReadSymbolicField(inPtr);
4979 + /*
4980 + * look for initial brace
4981 + */
4982 + if (**inPtr == ':')
4984 + (*inPtr) ++;
4985 + /*
4986 + * look for "Default" keyword, and if it's there, return the default
4987 + * pattern set
4988 + */
4989 + if (!strncmp(*inPtr, "Default", 7))
4991 + *inPtr += 7;
4992 + table = readDefaultStringMatchTable(languageMode);
4993 + XtFree(languageMode);
4995 + return table;
4999 + table = readMatchPatternSetContent(inPtr, stringStart, languageMode);
5001 + if (table == NULL)
5002 + XtFree(languageMode);
5004 + return table;
5008 +** Read in a content string ("{..}") of match pattern table,
5009 +** and advance *inPtr beyond it.
5010 +** Returns NULL and outputs an error to stderr on failure.
5012 +static StringMatchTable *readMatchPatternSetContent(
5013 + char **inPtr,
5014 + char *stringStart,
5015 + char *languageMode)
5017 + ReadMatchPatternInfo readPatInfo;
5018 + StringMatchTable *table = NULL;
5019 + ErrorInfo errInfo;
5020 + int successful = True;
5021 + int endOfPatternSet = False;
5023 + initErrorInfo(&errInfo);
5025 + /*
5026 + * look for initial brace
5027 + */
5028 + if (**inPtr != '{')
5030 + errInfo.eiLanguageMode = XtNewString(languageMode);
5031 + errInfo.eiDetail = "pattern list must begin with \"{\"";
5032 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo );
5034 + return NULL;
5037 + (*inPtr)++;
5039 + readPatInfo.rmpiNbrOfElements = 0;
5040 + readPatInfo.rmpiNbrOfGroups = 0;
5041 + readPatInfo.rmpiNbrOfSeqElements = 0;
5042 + readPatInfo.rmpiAllPatRE = NULL;
5043 + readPatInfo.rmpiFlashPatRE = NULL;
5045 + /*
5046 + * parse each pattern in the list
5047 + */
5048 + while (successful && !endOfPatternSet)
5050 + *inPtr += strspn(*inPtr, " \t\n");
5051 + if (**inPtr == '\0')
5053 + errInfo.eiLanguageMode = XtNewString(languageMode);
5054 + errInfo.eiDetail = "end of pattern list not found";
5055 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo);
5056 + successful = False;
5058 + else if (**inPtr == '}')
5060 + (*inPtr)++;
5061 + endOfPatternSet = True;
5063 + else
5065 + if (!readMatchPatternEntry(inPtr, &errInfo, &readPatInfo))
5067 + errInfo.eiLanguageMode = XtNewString(languageMode);
5068 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo);
5069 + successful = False;
5074 + if (successful)
5076 + /*
5077 + * compile regular expressions of read patterns
5078 + */
5079 + if (createRegExpOfPatterns(&readPatInfo, &errInfo))
5081 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo);
5082 + successful = False;
5086 + if (successful)
5088 + return createStringMatchTable(&readPatInfo, languageMode);
5090 + else
5092 + /*
5093 + * free memory of already read patterns
5094 + */
5095 + freeReadMatchPatternInfo(&readPatInfo);
5097 + return NULL;
5100 + return table;
5104 +** Create a reg. exp. of all patterns contained
5105 +** in given read match pattern info.
5107 +static int createRegExpOfPatterns(
5108 + ReadMatchPatternInfo *readPatInfo,
5109 + ErrorInfo *errInfo)
5111 + if (createRegExpOfStrPatterns(readPatInfo, errInfo))
5112 + return True;
5114 + if (createRegExpOfAllPatterns(readPatInfo, errInfo))
5115 + return True;
5117 + return False;
5121 +** Create a "total pattern reg. exp." of all patterns / flash patterns
5122 +** contained in given read match pattern info.
5123 +** Returns true, if create of reg. exp. has failed.
5125 +static int createRegExpOfAllPatterns(
5126 + ReadMatchPatternInfo *readPatInfo,
5127 + ErrorInfo *errInfo)
5129 + int i;
5130 + RegExpStringInfo allPatRegExpSI;
5131 + RegExpStringInfo flashPatRegExpSI;
5132 + MatchPatternTableElement *element;
5133 + char *regExpString;
5134 + char *compileMsg;
5136 + /*
5137 + * Allocate buffers for keyword regular expressions.
5138 + */
5139 + setupRegExpStringBuffers(readPatInfo, &allPatRegExpSI);
5140 + setupRegExpStringBuffers(readPatInfo, &flashPatRegExpSI);
5142 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5144 + element = readPatInfo->rmpiElement[i];
5146 + /*
5147 + * Add the keywords of the matching pattern to the keyword
5148 + * regular expression string buffer of all patterns.
5149 + */
5150 + addElementToRegExpString(
5151 + element,
5152 + readPatInfo,
5153 + &allPatRegExpSI);
5155 + /*
5156 + * If flash attribute is set, then add the keywords of the
5157 + * matching pattern also to the keyword regular expression
5158 + * string buffer of flash patterns.
5159 + */
5160 + if (element->mpteFlash)
5162 + addElementToRegExpString(
5163 + element,
5164 + readPatInfo,
5165 + &flashPatRegExpSI);
5169 + /*
5170 + * Assemble and compile the resulting all keywords reg. exp. string.
5171 + */
5172 + catSMTRegExpStrings(
5173 + &allPatRegExpSI,
5174 + &regExpString);
5176 + readPatInfo->rmpiAllPatRE =
5177 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
5179 + XtFree( regExpString );
5181 + if (readPatInfo->rmpiAllPatRE == NULL)
5183 + errInfo->eiRegExpCompileMsg = compileMsg;
5184 + errInfo->eiDetail = "All patterns: compile reg. exp. error";
5185 + return True;
5188 + /*
5189 + * Assemble and compile the resulting flash keywords reg. exp. string.
5190 + */
5191 + catSMTRegExpStrings(
5192 + &flashPatRegExpSI,
5193 + &regExpString);
5195 + readPatInfo->rmpiFlashPatRE =
5196 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
5198 + XtFree( regExpString );
5200 + if (readPatInfo->rmpiFlashPatRE == NULL)
5202 + errInfo->eiRegExpCompileMsg = compileMsg;
5203 + errInfo->eiDetail = "Flash patterns: compile reg. exp. error";
5204 + return True;
5207 + /*
5208 + * Pattern reg. exp. successful created:
5209 + */
5210 + return False;
5214 +** Create reg. exp. of single patterns contained in given
5215 +** read match pattern info.
5216 +** Returns true, if create of reg. exp. has failed.
5218 +static int createRegExpOfStrPatterns(
5219 + ReadMatchPatternInfo *readPatInfo,
5220 + ErrorInfo *errInfo)
5222 + int i;
5223 + MatchPatternTableElement *element;
5224 + MatchPatternGroupElement *group;
5226 + /*
5227 + * create global backref list of all elements of read info
5228 + */
5229 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5231 + element = readPatInfo->rmpiElement[i];
5233 + if (!createGlobalBackRefList(readPatInfo, element, errInfo))
5234 + return True;
5237 + /*
5238 + * resolve global backrefs of all elements of read info
5239 + */
5240 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5242 + element = readPatInfo->rmpiElement[i];
5244 + if (!resolveGlobalBackRefs(readPatInfo, element, errInfo))
5245 + return True;
5248 + /*
5249 + * compile reg. exp. of all elements of read info
5250 + */
5251 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5253 + element = readPatInfo->rmpiElement[i];
5255 + if (createStrPatRegExpOfElement(readPatInfo, element, errInfo))
5256 + return True;
5258 + /*
5259 + * create start / end reg. exp. if applicable.
5260 + */
5261 + if (element->mpteSkipBtwnStartEnd)
5263 + if (createStartEndRegExp(readPatInfo, element, errInfo))
5264 + return True;
5268 + /*
5269 + * compile reg. exp. of all groups of read info
5270 + */
5271 + for (i=0; i < readPatInfo->rmpiNbrOfGroups; i ++)
5273 + group = readPatInfo->rmpiGroup[i];
5275 + if (createGroupRegExp(readPatInfo, group, errInfo))
5277 + return True;
5281 + return False;
5285 +** Create a string match table out of read match pattern info.
5287 +static StringMatchTable *createStringMatchTable(
5288 + ReadMatchPatternInfo *readPatInfo,
5289 + char *languageMode)
5291 + StringMatchTable *table;
5292 + MatchPatternTable *patTable;
5293 + int sizeOfElements;
5295 + table = (StringMatchTable *)XtMalloc(sizeof(StringMatchTable));
5296 + table->smtLanguageMode = languageMode;
5298 + /*
5299 + * allocate a more appropriately sized list to return matching patterns
5300 + */
5301 + patTable = (MatchPatternTable *)XtMalloc(sizeof(MatchPatternTable));
5302 + patTable->mptNumberOfElements = readPatInfo->rmpiNbrOfElements;
5304 + if (readPatInfo->rmpiNbrOfElements > 0)
5306 + sizeOfElements =
5307 + sizeof(MatchPatternTableElement *) * readPatInfo->rmpiNbrOfElements;
5308 + patTable->mptElements =
5309 + (MatchPatternTableElement **)XtMalloc(sizeOfElements);
5310 + memcpy(patTable->mptElements, readPatInfo->rmpiElement, sizeOfElements);
5312 + else
5314 + patTable->mptElements = NULL;
5317 + table->smtAllPatterns = patTable;
5319 + table->smtAllPatRE = readPatInfo->rmpiAllPatRE;
5320 + table->smtFlashPatRE = readPatInfo->rmpiFlashPatRE;
5321 + table->smtUsedPatRE = NULL;
5323 + /*
5324 + * allocate a more appropriately sized list to return matching pattern groups
5325 + */
5326 + table->smtNumberOfGroups = readPatInfo->rmpiNbrOfGroups;
5327 + if (readPatInfo->rmpiNbrOfGroups > 0)
5329 + sizeOfElements =
5330 + sizeof(MatchPatternGroupElement *) * readPatInfo->rmpiNbrOfGroups;
5331 + table->smtGroups =
5332 + (MatchPatternGroupElement **)XtMalloc(sizeOfElements);
5333 + memcpy(table->smtGroups, readPatInfo->rmpiGroup, sizeOfElements);
5335 + else
5337 + table->smtGroups = NULL;
5339 + /*
5340 + * allocate a more appropriately sized list to return matching pattern sequence
5341 + */
5342 + table->smtNumberOfSeqElements = readPatInfo->rmpiNbrOfSeqElements;
5343 + if (readPatInfo->rmpiNbrOfSeqElements > 0)
5345 + sizeOfElements =
5346 + sizeof(MatchPatternSequenceElement *) * readPatInfo->rmpiNbrOfSeqElements;
5347 + table->smtSequence =
5348 + (MatchPatternSequenceElement **)XtMalloc(sizeOfElements);
5349 + memcpy(table->smtSequence, readPatInfo->rmpiSequence, sizeOfElements);
5351 + else
5353 + table->smtSequence = NULL;
5356 + return table;
5360 +** Read one match pattern entry of a match pattern string.
5361 +** Returns true, if read was successful.
5363 +static int readMatchPatternEntry(
5364 + char **inPtr,
5365 + ErrorInfo *errInfo,
5366 + ReadMatchPatternInfo *info)
5368 + char *name;
5369 + MatchPatternType type;
5370 + MatchPatternGroupElement *readGroup;
5371 + MatchPatternTableElement *readElement;
5373 + if (!getMPSName( inPtr, errInfo, &name ))
5375 + return False;
5378 + if (!getMPSTypeAttribute( inPtr, errInfo, &type ))
5380 + errInfo->eiMPTabElementName = XtNewString(name);
5381 + return False;
5384 + if (type == MPT_GROUP)
5386 + if (info->rmpiNbrOfGroups >= MAX_NBR_MATCH_PATTERN_GROUPS)
5388 + errInfo->eiMPTabElementName = XtNewString(name);
5389 + errInfo->eiDetail = "max number of match pattern groups exceeded";
5390 + return False;
5393 + readGroup = readMatchPatternGroup( inPtr, errInfo, name, info );
5395 + if (readGroup == NULL)
5397 + errInfo->eiMPTabElementName = XtNewString(name);
5398 + XtFree( name );
5400 + else
5402 + info->rmpiGroup[info->rmpiNbrOfGroups ++] = readGroup;
5404 + recordPatternSequence( info, name, type, info->rmpiNbrOfGroups-1 );
5407 + return (readGroup != NULL);
5409 + else
5411 + if (info->rmpiNbrOfElements >= MAX_NBR_MATCH_PATTERNS)
5413 + errInfo->eiMPTabElementName = XtNewString(name);
5414 + errInfo->eiDetail = "max number of match patterns exceeded";
5415 + XtFree( name );
5416 + return False;
5419 + readElement =
5420 + readMatchPatternTableElement( inPtr, &errInfo->eiDetail, name, type );
5422 + if (readElement == NULL)
5424 + errInfo->eiMPTabElementName = XtNewString(name);
5425 + XtFree( name );
5427 + else
5429 + readElement->mpteIndex = info->rmpiNbrOfElements;
5431 + info->rmpiElement[info->rmpiNbrOfElements ++] = readElement;
5433 + if (type == MPT_INDIVIDUAL)
5435 + if (!assignIndividualGroup( info, &errInfo->eiDetail, readElement ))
5437 + errInfo->eiMPTabElementName = XtNewString(name);
5438 + return False;
5442 + treatDuplicatedMTEntries(
5443 + info->rmpiElement, info->rmpiNbrOfElements );
5445 + recordPatternSequence( info, name, type, info->rmpiNbrOfElements-1 );
5448 + return (readElement != NULL);
5453 +** Record match pattern sequence for display of match pattern dialog.
5455 +static void recordPatternSequence(
5456 + ReadMatchPatternInfo *info,
5457 + char *name,
5458 + MatchPatternType type,
5459 + int index)
5461 + MatchPatternSequenceElement *sequence;
5463 + sequence =
5464 + (MatchPatternSequenceElement *)XtMalloc( sizeof(MatchPatternSequenceElement) );
5466 + sequence->mpseName = XtNewString(name);
5467 + sequence->mpseType = type;
5468 + sequence->mpseIndex = index;
5470 + info->rmpiSequence[info->rmpiNbrOfSeqElements ++] = sequence;
5474 +** Assign a new group to an individual match pattern.
5475 +** Returns true, if assignment was successful.
5477 +static int assignIndividualGroup(
5478 + ReadMatchPatternInfo *info,
5479 + char **errMsg,
5480 + MatchPatternTableElement *element)
5482 + MatchPatternGroupElement *group = NULL;
5484 + if (info->rmpiNbrOfGroups >= MAX_NBR_MATCH_PATTERN_GROUPS)
5486 + *errMsg = "max. number of matching pattern groups exceeded\n";
5487 + return False;
5490 + /*
5491 + * Assign the index of new group to the individual matching pattern
5492 + */
5493 + element->mpteGroup = info->rmpiNbrOfGroups;
5495 + /*
5496 + * Allocate memory for the matching pattern group and copy the
5497 + * info into this group element.
5498 + */
5499 + group =
5500 + (MatchPatternGroupElement *)XtMalloc( sizeof(MatchPatternGroupElement) );
5502 + group->mpgeName = NULL;
5503 + group->mpgeKeywordRE = NULL;
5505 + /*
5506 + * remember name of match pattern table element, which is
5507 + * represented by this group.
5508 + */
5509 + group->mpgeNumberOfSubPatterns = 1;
5510 + group->mpgeSubPatternIds = (char **)XtMalloc( sizeof(char *) );
5511 + group->mpgeSubPatternIds[0] = XtNewString(element->mpteName);
5513 + info->rmpiGroup[info->rmpiNbrOfGroups ++] = group;
5515 + return True;
5519 +** Get the match pattern table element of given 'patToSearch'
5520 +** name.
5521 +** Returns NULL, if no element was found.
5523 +static MatchPatternTableElement *getPatternOfName(
5524 + ReadMatchPatternInfo *info,
5525 + char *patToSearch)
5527 + int i;
5528 + MatchPatternTableElement *element;
5530 + for (i=0; i<info->rmpiNbrOfElements; i ++)
5532 + element = info->rmpiElement[i];
5534 + if (strcmp( element->mpteName, patToSearch ) == 0)
5536 + /*
5537 + * Related sub-pattern found:
5538 + */
5539 + return element;
5543 + /*
5544 + * No sub-pattern found:
5545 + */
5546 + return NULL;
5550 +** Read match pattern group of given match pattern string.
5551 +** Returns NULL, if read fails.
5553 +static MatchPatternGroupElement *readMatchPatternGroup(
5554 + char **inPtr,
5555 + ErrorInfo *errInfo,
5556 + char *name,
5557 + ReadMatchPatternInfo *info)
5559 + int i;
5560 + int error = False;
5561 + char *patNameInPtr;
5562 + char *subPatName;
5563 + MatchPatternTableElement *subPatElement;
5564 + int numberOfRelatedSubPattern = 0;
5565 + char *relatedSubPatternId[MAX_NBR_MATCH_PATTERNS];
5566 + int sizeOfIds;
5567 + MatchPatternGroupElement *group = NULL;
5569 + /*
5570 + * Read sub-matching patterns of this group.
5571 + */
5572 + while (**inPtr != '\n' && !error)
5574 + /*
5575 + * Read next pattern name from inPtr.
5576 + */
5577 + patNameInPtr = *inPtr;
5578 + subPatName = ReadSymbolicField(inPtr);
5580 + if (subPatName == NULL)
5582 + errInfo->eiDetail = "Sub-Matching Pattern Name expected";
5583 + error = True;
5585 + else
5587 + /*
5588 + * Get matching pattern related to sub-matching pattern name.
5589 + */
5590 + subPatElement =
5591 + getPatternOfName( info, subPatName );
5593 + if (subPatElement == NULL)
5595 + errInfo->eiStringPatText = XtNewString(subPatName);
5596 + errInfo->eiDetail = "Sub-Matching Pattern not defined before";
5597 + error = True;
5599 + else if (numberOfRelatedSubPattern >= MAX_NBR_MATCH_PATTERNS)
5601 + errInfo->eiDetail = "Group holds too many Sub-Matching Patterns";
5602 + error = True;
5604 + else if (subPatElement->mpteType != MPT_SUB)
5606 + errInfo->eiStringPatText = XtNewString(subPatName);
5607 + errInfo->eiDetail = "Not a Sub-Matching Pattern";
5608 + error = True;
5610 + else
5612 + /*
5613 + * Remember sub-matching pattern ID
5614 + */
5615 + relatedSubPatternId[numberOfRelatedSubPattern ++] = subPatName;
5617 + /*
5618 + * Assign the index of this group to the sub-matching pattern
5619 + * if no group index was assigned before.
5620 + */
5621 + if (subPatElement->mpteGroup == NO_GROUP_IDX)
5623 + subPatElement->mpteGroup = info->rmpiNbrOfGroups;
5627 + /*
5628 + * Skip to the start of the next matching pattern name.
5629 + */
5630 + if (!error && !SkipDelimiter(inPtr, &errInfo->eiDetail))
5632 + error = True;
5637 + if (error)
5639 + for (i=0; i < numberOfRelatedSubPattern; i++)
5641 + XtFree( relatedSubPatternId[i] );
5644 + return NULL;
5646 + else
5648 + /*
5649 + * Allocate memory for the matching pattern group and copy the
5650 + * info into this group element.
5651 + */
5652 + group =
5653 + (MatchPatternGroupElement *)XtMalloc( sizeof(MatchPatternGroupElement) );
5655 + group->mpgeName = name;
5656 + group->mpgeKeywordRE = NULL;
5658 + /*
5659 + * Allocate memory for the sub-matching pattern IDs & copy
5660 + * related sub-matching pattern into the group element.
5661 + */
5662 + sizeOfIds = sizeof(char *) * numberOfRelatedSubPattern;
5663 + group->mpgeSubPatternIds = (char **)XtMalloc( sizeOfIds );
5665 + memcpy(group->mpgeSubPatternIds, relatedSubPatternId, sizeOfIds);
5667 + group->mpgeNumberOfSubPatterns = numberOfRelatedSubPattern;
5669 + return group;
5674 +** Read one match pattern element from given match pattern string.
5675 +** Returns true, if read was successful.
5677 +static int readPatternElement(
5678 + char **inPtr,
5679 + char **errMsg,
5680 + PatternElement **pattern)
5682 + PatternElementKind patternKind;
5683 + PatternWordBoundary wordBoundary;
5684 + int caseInsensitive;
5685 + int regularExpression;
5686 + char *string;
5688 + if (!getMPSPatternAttribute(
5689 + inPtr,
5690 + errMsg,
5691 + &patternKind,
5692 + &wordBoundary,
5693 + &caseInsensitive,
5694 + &regularExpression ))
5696 + return False;
5699 + if (!ReadQuotedString(inPtr, errMsg, &string))
5701 + return False;
5704 + if (!SkipDelimiter(inPtr, errMsg))
5706 + XtFree( string );
5707 + return False;
5710 + *pattern =
5711 + createPatternElement(
5712 + string,
5713 + patternKind,
5714 + wordBoundary,
5715 + caseInsensitive,
5716 + regularExpression);
5718 + return True;
5722 +** Create a pattern element.
5724 +static PatternElement *createPatternElement(
5725 + char *patternText,
5726 + PatternElementKind patternKind,
5727 + PatternWordBoundary wordBoundary,
5728 + int caseInsensitive,
5729 + int regularExpression)
5731 + PatternElement *pattern;
5732 + char *s;
5734 + /*
5735 + * Convert pattern text to lower case, if case insensitive
5736 + * attribute is set.
5737 + */
5738 + if (caseInsensitive)
5740 + for (s = patternText; *s != '\0'; s ++)
5742 + *s = tolower(*s);
5746 + /*
5747 + * Allocate memory for the new pattern element and init. / copy
5748 + * related info into this pattern element.
5749 + */
5750 + pattern = (PatternElement *)XtMalloc( sizeof(PatternElement) );
5752 + initStrPatBackRefList(&pattern->peVal.peuSingle);
5754 + pattern->peKind = patternKind;
5755 + pattern->peIndex = NO_PATTERN_IDX;
5756 + pattern->peType = PET_SINGLE;
5758 + pattern->peVal.peuSingle.spLength = strlen(patternText);
5759 + pattern->peVal.peuSingle.spBackRefParsed = False;
5760 + pattern->peVal.peuSingle.spBackRefResolved = False;
5762 + pattern->peVal.peuSingle.spCaseInsensitive = caseInsensitive;
5763 + pattern->peVal.peuSingle.spRegularExpression = regularExpression;
5764 + pattern->peVal.peuSingle.spTextRE = NULL;
5766 + /*
5767 + * Store original string of regular expression patterns due to
5768 + * it may be later adapted (e.g. due to global backrefs etc.).
5769 + */
5770 + if (regularExpression)
5772 + pattern->peVal.peuSingle.spOrigText = patternText;
5773 + pattern->peVal.peuSingle.spText = NULL;
5774 + pattern->peVal.peuSingle.spWordBoundary = PWB_NONE;
5776 + else
5778 + pattern->peVal.peuSingle.spOrigText = NULL;
5779 + pattern->peVal.peuSingle.spText = patternText;
5780 + pattern->peVal.peuSingle.spWordBoundary = wordBoundary;
5783 + return pattern;
5787 +** Create a list holding all global backref definitions of given
5788 +** match pattern table element. The list is stored in this given
5789 +** element.
5790 +** Returns true, if list was successfully created.
5792 +static int createGlobalBackRefList(
5793 + ReadMatchPatternInfo *readPatInfo,
5794 + MatchPatternTableElement *element,
5795 + ErrorInfo *errInfo)
5797 + int i;
5798 + StringPattern *strPat;
5800 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
5802 + strPat = getReadStringPattern(readPatInfo, element->mpteAll.pesPattern[i]);
5804 + if (strPat->spRegularExpression)
5806 + if (strPat->spBackRefParsed)
5808 + /*
5809 + * Global backrefs or this string pattern already parsed:
5810 + * just merge string pattern list with elements one.
5811 + */
5812 + if (!updateGlobalBackRefs(
5813 + strPat,
5814 + element->mpteGlobalBackRef,
5815 + errInfo))
5817 + return False;
5820 + else
5822 + /*
5823 + * parse string pattern for global backrefs and
5824 + * merge string pattern list with elements one.
5825 + */
5826 + if (!parseGlobalBackRefs(
5827 + strPat,
5828 + element->mpteGlobalBackRef,
5829 + errInfo))
5831 + return False;
5837 + return True;
5841 +** Returns read string pattern of given pattern element.
5843 +StringPattern *getReadStringPattern(
5844 + ReadMatchPatternInfo *readPatInfo,
5845 + PatternElement *pattern )
5847 + switch (pattern->peType)
5849 + case PET_SINGLE:
5850 + return &pattern->peVal.peuSingle;
5851 + break;
5853 + case PET_MULTIPLE:
5854 + return &pattern->peVal.peuMulti.mpStringPattern;
5855 + break;
5857 + case PET_REFERENCE:
5858 + return getReadStringPattern(
5859 + readPatInfo,
5860 + getReadPatternOfReference(readPatInfo, &pattern->peVal.peuRef));
5861 + break;
5864 + /*
5865 + * never reached; just to make compiler happy
5866 + */
5867 + return NULL;
5871 +** Returns read pattern element of given pattern reference.
5873 +static PatternElement *getReadPatternOfReference(
5874 + ReadMatchPatternInfo *readPatInfo,
5875 + PatternReference *patRef)
5877 + MatchPatternTableElement **element = readPatInfo->rmpiElement;
5879 + return element[ patRef->prElementIdx ]->mpteAll.pesPattern[patRef->prPatternIdx];
5883 +** Allocate a new copy of given string and substitute each capturing
5884 +** parentheses inside given string by a non-capturing one.
5885 +** Returns resulting string.
5887 +static char *replaceCapturingParentheses(
5888 + const char *source)
5890 + char *destination;
5891 + const char *s;
5892 + char *d;
5893 + int nbrOfOpenBraces = 0;
5895 + s = source;
5897 + /*
5898 + * count number of open braces
5899 + */
5900 + while (*s != '\0')
5902 + if (*s++ == '(')
5903 + nbrOfOpenBraces ++;
5906 + /*
5907 + * allocate memory for substitued reg. exp. text
5908 + */
5909 + destination = XtMalloc(strlen(source) + 2*nbrOfOpenBraces);
5911 + /*
5912 + * substitute each capturing open brace by a non-capturing one
5913 + */
5914 + s = source;
5915 + d = destination;
5917 + while (*s != '\0')
5919 + if (*s == '\\')
5921 + *d++ = *s++;
5923 + if (*s != '\0')
5924 + *d++ = *s++;
5926 + else if (*s == '(')
5928 + *d++ = *s++;
5930 + if (*s != '?' && *s != '*')
5932 + *d++ = '?';
5933 + *d++ = ':';
5936 + else
5938 + *d++ = *s++;
5942 + *d = '\0';
5944 + return destination;
5948 +** Parse given string pattern for global backrefs definitions
5949 +** (syntax: "(*n", where n=1..9). Add found global backrefs to
5950 +** given backRefList.
5951 +** Returns false, if parse fails.
5953 +static int parseGlobalBackRefs(
5954 + StringPattern *strPat,
5955 + GlobalBackRefElement *backRefList,
5956 + ErrorInfo *errInfo)
5958 + char *s;
5959 + char *backRefContent;
5960 + int nestingLevel = 0;
5961 + int stackIdx = -1;
5962 + BackRefBracketInfo backRefInfo[MAX_GLOBAL_BACK_REF_ID+1];
5963 + StrPatBackRefElement *curStrPatBRE;
5965 + strPat->spText = replaceCapturingParentheses(strPat->spOrigText);
5966 + strPat->spLength = strlen(strPat->spText);
5967 + strPat->spBackRefParsed = True;
5969 + s = strPat->spText;
5971 + while (*s != '\0')
5973 + if (*s == '\\')
5975 + /*
5976 + * Ignore escaped characters
5977 + */
5978 + if (*(s+1) != '\0')
5979 + s ++;
5981 + else if (*s == '(')
5983 + if (*(s+1) == '*')
5985 + if (isdigit((unsigned char)*(s+2)))
5987 + /*
5988 + * Global backref. definition start found:
5989 + */
5990 + stackIdx ++;
5992 + backRefInfo[stackIdx].brbiGlobalId =
5993 + (int)((unsigned char)*(s+2) - (unsigned char)'0') - 1;
5995 + if(backRefInfo[stackIdx].brbiGlobalId < 0)
5997 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
5998 + errInfo->eiDetail = "Backref '0' not allowed";
5999 + return False;
6002 + backRefInfo[stackIdx].brbiContentStart = s+3;
6003 + backRefInfo[stackIdx].brbiNestingLevel = nestingLevel;
6004 + s ++;
6006 + s ++;
6008 + nestingLevel ++;
6010 + else if (*s == ')')
6012 + nestingLevel --;
6013 + if (stackIdx != -1 &&
6014 + backRefInfo[stackIdx].brbiNestingLevel == nestingLevel)
6016 + /*
6017 + * Global backref. definition end found: add it to
6018 + * backref. list of string pattern.
6019 + */
6020 + curStrPatBRE =
6021 + &strPat->spOwnGlobalBackRef[backRefInfo[stackIdx].brbiGlobalId];
6023 + backRefContent =
6024 + createBackRefRegExpText(
6025 + backRefInfo[stackIdx].brbiContentStart,
6026 + s);
6028 + if (curStrPatBRE->spbreRegExpText != NULL)
6030 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6031 + errInfo->eiBackRefNbr = backRefInfo[stackIdx].brbiGlobalId + 1;
6032 + errInfo->eiDetail = "already defined before";
6033 + XtFree(backRefContent);
6034 + return False;
6036 + else
6038 + curStrPatBRE->spbreRegExpText = backRefContent;
6041 + stackIdx --;
6044 + s ++;
6047 + /*
6048 + * Merge global backref. list of string pattern with given backRefList.
6049 + */
6050 + return updateGlobalBackRefs(
6051 + strPat,
6052 + backRefList,
6053 + errInfo);
6057 +** Merge global backref. list of given string pattern with given backRefList.
6058 +** Returns false, if merge fails.
6060 +static int updateGlobalBackRefs(
6061 + StringPattern *strPat,
6062 + GlobalBackRefElement *backRefList,
6063 + ErrorInfo *errInfo)
6065 + int i;
6066 + StrPatBackRefElement *curStrPatBRE;
6067 + GlobalBackRefElement *curGlobalBRE;
6069 + for (i=0;i < MAX_GLOBAL_BACK_REF_ID; i ++)
6071 + curStrPatBRE = &strPat->spOwnGlobalBackRef[i];
6073 + if (curStrPatBRE->spbreRegExpText != NULL)
6075 + curGlobalBRE = &backRefList[i];
6077 + if (curGlobalBRE->gbreDefByStrPat != NULL)
6079 + if (strcmp(curGlobalBRE->gbreRegExpText, curStrPatBRE->spbreRegExpText) != 0)
6081 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6082 + errInfo->eiBackRefNbr = i+1;
6083 + errInfo->eiDetail = "already defined before";
6085 + return False;
6088 + else
6090 + curGlobalBRE->gbreDefByStrPat = strPat;
6091 + curGlobalBRE->gbreRegExpText = curStrPatBRE->spbreRegExpText;
6096 + return True;
6100 +** Allocate and return a new string holding content of
6101 +** global backref. definition.
6103 +static char *createBackRefRegExpText(
6104 + const char *start,
6105 + const char *end)
6107 + int len = end - start;
6108 + char *regExpText = XtMalloc( len+1 );
6110 + memcpy( regExpText, start, len );
6112 + regExpText[len] = '\0';
6114 + return regExpText;
6118 +** Resolve all global backrefs of given match pattern table element.
6119 +** Returns false, if resolve fails.
6121 +static int resolveGlobalBackRefs(
6122 + ReadMatchPatternInfo *readPatInfo,
6123 + MatchPatternTableElement *element,
6124 + ErrorInfo *errInfo)
6126 + int i;
6127 + StringPattern *strPat;
6129 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
6131 + strPat = getReadStringPattern(readPatInfo, element->mpteAll.pesPattern[i]);
6133 + if (strPat->spRegularExpression && !strPat->spBackRefResolved)
6135 + if (!resolveGlobalBackRefsOfStrPat(strPat, element->mpteGlobalBackRef, errInfo))
6136 + return False;
6138 + strPat->spBackRefResolved = True;
6142 + return True;
6146 +** Resolve global backrefs of given string pattern.
6147 +** Returns false, if resolve fails.
6149 +static int resolveGlobalBackRefsOfStrPat(
6150 + StringPattern *strPat,
6151 + GlobalBackRefElement *backRefList,
6152 + ErrorInfo *errInfo)
6154 + char *s;
6155 + int globalId;
6156 + int localId = 1;
6158 + s = strPat->spText;
6160 + while (*s != '\0')
6162 + if (*s == '\\')
6164 + if (isdigit((unsigned char)*(s+1)))
6166 + /*
6167 + * \n (n=1..9) found: substitute global backref.
6168 + */
6169 + globalId =
6170 + (int)((unsigned char)*(s+1) - (unsigned char)'0') - 1;
6172 + if(globalId < 0)
6174 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6175 + errInfo->eiDetail = "backref '\\0' not allowed";
6176 + return False;
6179 + s = substituteGlobalBackRef(strPat, s, globalId, &localId, backRefList, errInfo);
6181 + if (s == NULL)
6182 + return False;
6184 + else if (*(s+1) != '\0')
6185 + s ++;
6187 + else if (*s == '(')
6189 + if (*(s+1) == '*')
6191 + if (isdigit((unsigned char)*(s+2)))
6193 + /*
6194 + * "(*n" (n=1..9) found: substitute global backref. definition.
6195 + */
6196 + globalId =
6197 + (int)((unsigned char)*(s+2) - (unsigned char)'0') - 1;
6199 + strPat->spOwnGlobalBackRef[globalId].spbreLocalBackRefID = localId;
6200 + strPat->spGlobalToLocalBackRef[globalId] = localId;
6202 + localId ++;
6204 + s = convertGlobalToLocalBackRef(strPat, s);
6206 + else
6208 + s ++;
6212 + s ++;
6215 + return True;
6219 +** Substitute global backref (\n, n=1..9) located at given "subsPtr"
6220 +** by its definition or by a local backref.
6221 +** Returns
6222 +** - NULL, if substitute fails or
6223 +** - substituted string pointer, where scan shall continue with.
6225 +static char *substituteGlobalBackRef(
6226 + StringPattern *strPat,
6227 + char *subsPtr,
6228 + int globalId,
6229 + int *localId,
6230 + GlobalBackRefElement *backRefList,
6231 + ErrorInfo *errInfo)
6233 + StrPatBackRefElement *strPatBackRef = &strPat->spOwnGlobalBackRef[globalId];
6234 + char *s;
6236 + if (strPatBackRef->spbreRegExpText == NULL)
6238 + /*
6239 + * given global backref definition is not located in given
6240 + * string pattern -> replace backref ID by backref reg. exp.
6241 + */
6242 + if (backRefList[globalId].gbreRegExpText == NULL)
6244 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6245 + errInfo->eiBackRefNbr = globalId + 1;
6246 + errInfo->eiDetail = "not defined within any string pattern";
6247 + return NULL;
6250 + if (strPat->spGlobalToLocalBackRef[globalId] == NO_LOCAL_BACK_REF_ID)
6252 + /*
6253 + * 1st occurence of global backref ID in this pattern ->
6254 + * replace global backref ID by backref reg. exp.
6255 + */
6256 + s = replaceBackRefIdByRegExp(strPat, subsPtr, backRefList[globalId].gbreRegExpText);
6258 + strPat->spGlobalToLocalBackRef[globalId] = *localId;
6259 + (*localId) ++;
6261 + else
6263 + /*
6264 + * next occurence of global backref ID in this pattern ->
6265 + * replace global backref ID by local one
6266 + */
6267 + s = subsPtr + 1;
6268 + *s = (char)((int)('0') + strPat->spGlobalToLocalBackRef[globalId]);
6271 + else
6273 + /*
6274 + * given global backref definition is located in given string pattern
6275 + */
6276 + if (strPatBackRef->spbreLocalBackRefID == NO_LOCAL_BACK_REF_ID)
6278 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6279 + errInfo->eiBackRefNbr = globalId + 1;
6280 + errInfo->eiDetail = "not defined before";
6281 + return NULL;
6284 + /*
6285 + * replace global backref ID by local one
6286 + */
6287 + s = subsPtr + 1;
6288 + *s = (char)((int)('0') + strPatBackRef->spbreLocalBackRefID);
6291 + return s;
6295 +** Replace global backref ID ("\n", n=1..9), located at given
6296 +** replaceStartPtr, by its definition (given by regExp parameter).
6297 +** Returns string pointer, where scan shall continue with
6299 +static char *replaceBackRefIdByRegExp(
6300 + StringPattern *strPat,
6301 + char *replaceStartPtr,
6302 + char *regExp)
6304 + char *oldText = strPat->spText;
6305 + char *newText;
6306 + char *n;
6307 + char *continueScanPtr;
6308 + int oldLen = strlen(oldText);
6309 + int regExpLen = strlen(regExp);
6310 + int replacePos = replaceStartPtr - oldText;
6311 + int remainingLen = oldLen-replacePos-2;
6313 + /*
6314 + * replace "\n" - located at replaceStartPtr - by "(regExp)"
6315 + */
6316 + newText = XtMalloc(oldLen + regExpLen + 3);
6318 + memcpy(newText, oldText, replacePos);
6319 + n = newText + replacePos;
6320 + *n = '(';
6321 + continueScanPtr = n;
6322 + n ++;
6323 + memcpy(n, regExp, regExpLen);
6324 + n += regExpLen;
6325 + *n = ')';
6326 + n ++;
6327 + memcpy(n, replaceStartPtr+2, remainingLen);
6328 + *(n + remainingLen) = '\0';
6330 + XtFree(oldText);
6332 + strPat->spText = newText;
6333 + strPat->spLength = strlen(newText);
6335 + return continueScanPtr;
6339 +** Convert global backref definition ("(*n", n=1..9), located at given
6340 +** convertPtr, by capturing parentheses "(".
6341 +** Returns string pointer, where scan shall continue with
6343 +static char *convertGlobalToLocalBackRef(
6344 + StringPattern *strPat,
6345 + char *convertPtr)
6347 + char *oldText = strPat->spText;
6348 + char *newText;
6349 + int oldLen = strlen(oldText);
6350 + int convertPos = convertPtr - oldText;
6352 + /*
6353 + * replace "(*n" - located at convertPtr - by "("
6354 + */
6355 + newText = XtMalloc(oldLen - 1);
6357 + memcpy(newText, oldText, convertPos+1);
6358 + memcpy(newText+convertPos+1, convertPtr+3, oldLen-convertPos-3);
6360 + *(newText + oldLen - 2) = '\0';
6362 + XtFree(oldText);
6364 + strPat->spText = newText;
6365 + strPat->spLength = strlen(newText);
6367 + return newText + convertPos;
6371 +** Read a match pattern table element from given input string.
6372 +** Return NULL, if read fails.
6374 +static MatchPatternTableElement *readMatchPatternTableElement(
6375 + char **inPtr,
6376 + char **errMsg,
6377 + char *name,
6378 + MatchPatternType type)
6380 + int error = False;
6381 + PatternElement *pattern;
6382 + PatternElement *allPat[MAX_STRING_PATTERNS];
6383 + int nbrOfPat = 0;
6384 + int sizeOfPat;
6385 + MatchPatternTableElement *result;
6386 + int isMonoPattern;
6387 + int skipBtwStartEnd;
6388 + int flash;
6389 + int ignoreHighLightInfo;
6390 + int i;
6392 + if (!getMPSGlobalAttribute(
6393 + inPtr,
6394 + errMsg,
6395 + &isMonoPattern,
6396 + &skipBtwStartEnd,
6397 + &flash,
6398 + &ignoreHighLightInfo ))
6400 + return NULL;
6403 + /*
6404 + * read all patterns
6405 + */
6406 + while (**inPtr != '\n' && !error)
6408 + if (!readPatternElement( inPtr, errMsg, &pattern ))
6410 + error = True;
6412 + else if (nbrOfPat >= MAX_STRING_PATTERNS)
6414 + *errMsg = "max. number of string patterns exceeded";
6415 + error = True;
6417 + else
6419 + pattern->peIndex = nbrOfPat;
6421 + allPat[nbrOfPat ++] = pattern;
6425 + if (error)
6427 + for (i=0; i < nbrOfPat; i ++)
6428 + freePatternElement( allPat[i] );
6430 + return NULL;
6433 + if (nbrOfPat == 0)
6435 + *errMsg = "min. one string pattern needed";
6436 + return NULL;
6439 + /*
6440 + * allocate & init. MatchPatternTableElement
6441 + */
6442 + result =
6443 + (MatchPatternTableElement *)XtMalloc(sizeof(MatchPatternTableElement));
6445 + result->mpteName = name;
6446 + result->mpteIndex = NO_ELEMENT_IDX;
6447 + result->mpteType = type;
6448 + result->mpteGroup = NO_GROUP_IDX;
6450 + sizeOfPat = sizeof(PatternElement *) * nbrOfPat;
6451 + result->mpteAll.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6453 + memcpy(result->mpteAll.pesPattern, allPat, sizeOfPat);
6455 + result->mpteAll.pesNumberOfPattern = nbrOfPat;
6457 + result->mpteIsMonoPattern = isMonoPattern;
6458 + result->mpteSkipBtwnStartEnd = skipBtwStartEnd;
6459 + result->mpteFlash = flash;
6460 + result->mpteIgnoreHighLightInfo = ignoreHighLightInfo;
6462 + result->mpteStartEndRE = NULL;
6464 + initGlobalBackRefList( result->mpteGlobalBackRef );
6466 + /*
6467 + * sort start / end / middle pattern
6468 + */
6469 + error = !sortReadPatternElementSet( &result->mpteAll, errMsg, result );
6471 + if (error)
6473 + freeMatchPatternTableElement( result );
6474 + return NULL;
6476 + else
6478 + return result;
6483 + * Sort read pattern element set into start, middle & end arrays.
6484 + * Validate "monopattern" attribute.
6485 + * Returns true, if validation was successful.
6486 + */
6487 +static int sortReadPatternElementSet(
6488 + PatternElementSet *allPat,
6489 + char **errMsg,
6490 + MatchPatternTableElement *result)
6492 + int sizeOfPat;
6493 + int isMonoPattern = result->mpteIsMonoPattern;
6495 + /*
6496 + * count number of start, middle & end pattern elements.
6497 + */
6498 + countPatternElementKind( allPat, result );
6500 + /*
6501 + * validate and allocate pattern elements.
6502 + */
6503 + if (result->mpteStart.pesNumberOfPattern != 0)
6505 + sizeOfPat = sizeof(PatternElement *) * result->mpteStart.pesNumberOfPattern;
6506 + result->mpteStart.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6508 + else
6510 + *errMsg = "min. one start pattern needed";
6511 + return False;
6514 + if (isMonoPattern &&
6515 + (result->mpteMiddle.pesNumberOfPattern != 0 ||
6516 + result->mpteEnd.pesNumberOfPattern !=0))
6518 + *errMsg = "mono pattern: only start pattern(s) allowed due to attribute [m]";
6519 + return False;
6522 + if (result->mpteMiddle.pesNumberOfPattern != 0)
6524 + sizeOfPat = sizeof(PatternElement *) * result->mpteMiddle.pesNumberOfPattern;
6525 + result->mpteMiddle.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6528 + if (result->mpteEnd.pesNumberOfPattern != 0)
6530 + sizeOfPat = sizeof(PatternElement *) * result->mpteEnd.pesNumberOfPattern;
6531 + result->mpteEnd.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6533 + else
6535 + if (!isMonoPattern)
6537 + *errMsg = "min. one end pattern needed";
6538 + return False;
6542 + /*
6543 + * sort pattern elements into start, middle & end arrays.
6544 + */
6545 + sortPatternElementSet( allPat, result );
6547 + if (isMonoPattern)
6549 + copyPatternSet( &result->mpteStart, &result->mpteEnd );
6552 + return True;
6556 + * Count number of start, middle & end patterns stored in "allPat".
6557 + */
6558 +static void countPatternElementKind(
6559 + PatternElementSet *allPat,
6560 + MatchPatternTableElement *result)
6562 + int i;
6564 + result->mpteStart.pesNumberOfPattern = 0;
6565 + result->mpteEnd.pesNumberOfPattern = 0;
6566 + result->mpteMiddle.pesNumberOfPattern = 0;
6568 + result->mpteStart.pesPattern = NULL;
6569 + result->mpteEnd.pesPattern = NULL;
6570 + result->mpteMiddle.pesPattern = NULL;
6572 + for (i=0; i < allPat->pesNumberOfPattern; i ++)
6574 + switch (allPat->pesPattern[i]->peKind)
6576 + case PEK_START:
6577 + result->mpteStart.pesNumberOfPattern ++;
6578 + break;
6579 + case PEK_MIDDLE:
6580 + result->mpteMiddle.pesNumberOfPattern ++;
6581 + break;
6582 + case PEK_END:
6583 + result->mpteEnd.pesNumberOfPattern ++;
6584 + break;
6585 + default:;
6591 + * Sort start, middle & end pattern elements into related arrays.
6592 + */
6593 +static void sortPatternElementSet(
6594 + PatternElementSet *allPat,
6595 + MatchPatternTableElement *result)
6597 + int i;
6598 + int s,m,e;
6600 + for (i=0, s=0, m=0, e=0; i < allPat->pesNumberOfPattern; i ++)
6602 + switch (allPat->pesPattern[i]->peKind)
6604 + case PEK_START:
6605 + result->mpteStart.pesPattern[s ++] = allPat->pesPattern[i];
6606 + break;
6607 + case PEK_MIDDLE:
6608 + result->mpteMiddle.pesPattern[m ++] = allPat->pesPattern[i];
6609 + break;
6610 + case PEK_END:
6611 + result->mpteEnd.pesPattern[e ++] = allPat->pesPattern[i];
6612 + break;
6613 + default:;
6618 +static void copyPatternSet(
6619 + PatternElementSet *sourcePS,
6620 + PatternElementSet *destPS)
6622 + int sizeOfPat;
6624 + destPS->pesNumberOfPattern = sourcePS->pesNumberOfPattern;
6626 + sizeOfPat = sizeof(PatternElement *) * destPS->pesNumberOfPattern;
6627 + destPS->pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6629 + memcpy(destPS->pesPattern, sourcePS->pesPattern, sizeOfPat);
6633 +** Free the allocated memory contained in a ReadMatchPatternInfo data structure
6635 +static void freeReadMatchPatternInfo( ReadMatchPatternInfo *readPatInfo )
6637 + int i;
6639 + for (i=0; i<readPatInfo->rmpiNbrOfElements; i++)
6640 + freeMatchPatternTableElement(readPatInfo->rmpiElement[i]);
6642 + for (i=0; i<readPatInfo->rmpiNbrOfGroups; i++)
6643 + freeMatchPatternGroupElement(readPatInfo->rmpiGroup[i]);
6645 + for (i=0; i<readPatInfo->rmpiNbrOfSeqElements; i++)
6646 + freeMatchPatternSequenceElement(readPatInfo->rmpiSequence[i]);
6648 + freePtr((void **)&readPatInfo->rmpiAllPatRE);
6650 + freePtr((void **)&readPatInfo->rmpiFlashPatRE);
6654 +** Free the allocated memory contained in a StringMatchTable data structure
6656 +static void freeStringMatchTable( StringMatchTable *table )
6658 + MatchPatternTable *patTable;
6659 + int i;
6661 + if (table == NULL)
6662 + return;
6664 + XtFree(table->smtLanguageMode);
6666 + /*
6667 + * Free all matching patterns
6668 + */
6669 + patTable = table->smtAllPatterns;
6671 + for (i=0; i<patTable->mptNumberOfElements; i++)
6672 + freeMatchPatternTableElement(patTable->mptElements[i]);
6674 + XtFree((char *)patTable);
6676 + /*
6677 + * Free matching pattern group elements
6678 + */
6679 + for (i=0; i<table->smtNumberOfGroups; i++)
6680 + freeMatchPatternGroupElement(table->smtGroups[i]);
6682 + /*
6683 + * Free matching pattern sequence elements
6684 + */
6685 + for (i=0; i<table->smtNumberOfSeqElements; i++)
6686 + freeMatchPatternSequenceElement(table->smtSequence[i]);
6688 + /*
6689 + * Free keyword reg. expressions
6690 + */
6691 + freePtr((void **)&table->smtAllPatRE);
6693 + freePtr((void **)&table->smtFlashPatRE);
6695 + XtFree((char *)table);
6699 +** Free the allocated memory contained in a MatchPatternTableElement data structure
6701 +static void freeMatchPatternTableElement( MatchPatternTableElement *element )
6703 + int i;
6705 + XtFree(element->mpteName);
6707 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
6709 + freePatternElement(element->mpteAll.pesPattern[i]);
6712 + freePtr((void **)&element->mpteStartEndRE);
6714 + freeXtPtr((void **)&element->mpteStart.pesPattern);
6716 + freeXtPtr((void **)&element->mpteMiddle.pesPattern);
6718 + freeXtPtr((void **)&element->mpteEnd.pesPattern);
6720 + XtFree((char *)element);
6724 +** Free the allocated memory contained in a PatternElement data structure
6726 +static void freePatternElement( PatternElement *element )
6728 + if (element->peType == PET_SINGLE)
6729 + freeStringPattern( &(element->peVal.peuSingle) );
6730 + else if (element->peType == PET_MULTIPLE)
6732 + freeStringPattern( &(element->peVal.peuMulti.mpStringPattern) );
6733 + XtFree( (char *)element->peVal.peuMulti.mpRefList );
6736 + XtFree( (char *)element );
6740 +** Free the allocated memory contained in a StringPattern data structure
6742 +static void freeStringPattern( StringPattern *strPat )
6744 + int i;
6746 + freeXtPtr((void **)&strPat->spText);
6747 + freeXtPtr((void **)&strPat->spOrigText);
6749 + freePtr((void **)&strPat->spTextRE);
6751 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
6752 + freeXtPtr((void **)&strPat->spOwnGlobalBackRef[i].spbreRegExpText);
6756 +** Free the allocated memory contained in a MatchPatternGroupElement data structure
6758 +static void freeMatchPatternGroupElement( MatchPatternGroupElement *group )
6760 + int i;
6762 + freeXtPtr((void **)&group->mpgeName);
6764 + freePtr((void **)&group->mpgeKeywordRE);
6766 + if (group->mpgeSubPatternIds != NULL)
6768 + for (i=0; i < group->mpgeNumberOfSubPatterns; i++)
6770 + XtFree(group->mpgeSubPatternIds[i]);
6772 + XtFree((char *)group->mpgeSubPatternIds);
6775 + XtFree((char *)group);
6779 +** Free the allocated memory contained in a MatchPatternSequenceElement data structure
6781 +static void freeMatchPatternSequenceElement( MatchPatternSequenceElement *sequence )
6783 + XtFree( sequence->mpseName );
6785 + XtFree( (char *)sequence );
6790 +** Format a matching pattern set parse error.
6792 +static void parseMatchingPatternSetError(
6793 + const char *stringStart,
6794 + const char *stoppedAt,
6795 + ErrorInfo *errInfo)
6797 + char *message = "";
6798 + int msgLen;
6799 + char *errorInForm = "matching pattern of \"%s\"";
6800 + char *errorIn;
6802 + if (errInfo->eiLanguageMode == NULL)
6804 + errorIn = "matching pattern";
6806 + else
6808 + errorIn = XtMalloc(strlen(errorInForm) + strlen(errInfo->eiLanguageMode)+1);
6809 + sprintf(errorIn, "matching pattern of \"%s\"", errInfo->eiLanguageMode);
6812 + if (errInfo->eiRegExpCompileMsg != NULL)
6814 + /*
6815 + * Error message of form:
6816 + * "MP \"eiMPTabElementName\", SP \"eiStringPatText\": eiRegExpCompileMsg" or
6817 + * "MP \"eiMPTabElementName\" - eiDetail: eiRegExpCompileMsg"
6818 + */
6820 + msgLen = strlen(errInfo->eiRegExpCompileMsg) + 1;
6822 + if (errInfo->eiMPTabElementName != NULL)
6823 + msgLen += strlen(errInfo->eiMPTabElementName) + 10;
6825 + if (errInfo->eiDetail != NULL)
6827 + msgLen += strlen(errInfo->eiDetail + 2);
6829 + else
6831 + if (errInfo->eiStringPatText != NULL)
6832 + msgLen += strlen(errInfo->eiStringPatText) + 9;
6835 + message = XtMalloc(msgLen);
6837 + strcpy(message, "");
6839 + if (errInfo->eiMPTabElementName != NULL)
6840 + sprintf( message, "MP \"%s\"", errInfo->eiMPTabElementName);
6842 + if (errInfo->eiDetail == NULL)
6844 + if (errInfo->eiStringPatText != NULL)
6845 + sprintf( message, "%s, SP \"%s\"", message, errInfo->eiStringPatText);
6847 + else
6849 + if (strlen(message) != 0)
6850 + strcat(message, " - ");
6852 + strcat(message, errInfo->eiDetail);
6855 + if (strlen(message) != 0)
6856 + strcat(message, ": ");
6858 + strcat(message, errInfo->eiRegExpCompileMsg);
6860 + else if (errInfo->eiDetail != NULL)
6862 + /*
6863 + * Error message of form:
6864 + * "MP \"eiMPTabElementName\", SP \"eiStringPatText\": Backref %d eiDetail
6865 + */
6866 + msgLen = strlen(errInfo->eiDetail) + 1;
6868 + if (errInfo->eiMPTabElementName != NULL)
6869 + msgLen += strlen(errInfo->eiMPTabElementName) + 7;
6870 + if (errInfo->eiStringPatText != NULL)
6871 + msgLen += strlen(errInfo->eiStringPatText) + 9;
6872 + if (errInfo->eiBackRefNbr != 0)
6873 + msgLen += 15;
6875 + message = XtMalloc(msgLen);
6877 + strcpy(message, "");
6879 + if (errInfo->eiMPTabElementName != NULL)
6880 + sprintf( message, "MP \"%s\"", errInfo->eiMPTabElementName);
6881 + if (errInfo->eiStringPatText != NULL)
6882 + sprintf( message, "%s, SP \"%s\"", message, errInfo->eiStringPatText);
6884 + if (strlen(message) != 0)
6885 + strcat(message, ": ");
6887 + if (errInfo->eiBackRefNbr != 0)
6888 + sprintf( message, "%s Backref %d ", message, errInfo->eiBackRefNbr);
6890 + strcat(message, errInfo->eiDetail);
6893 + ParseError(NULL, stringStart, stoppedAt, errorIn, message);
6895 + if (errInfo->eiRegExpCompileMsg != NULL || errInfo->eiDetail != NULL)
6897 + XtFree(message);
6900 + if (errInfo->eiLanguageMode != NULL)
6902 + XtFree(errorIn);
6905 + freeErrorInfo(errInfo);
6906 + initErrorInfo(errInfo);
6910 + * Pop-up a warning dialog showing a matching pattern set error.
6911 + */
6912 +static void dialogMatchingPatternSetError(
6913 + char *title,
6914 + ErrorInfo *errInfo)
6916 + char *message;
6917 + int msgLen = 1;
6919 + /*
6920 + * Error message of form:
6921 + * "Name : \"eiMPTabElementName\"\n
6922 + * "String: \"eiStringPatText\"\n
6923 + * eiDetail\n
6924 + * eiRegExpCompileMsg\n"
6925 + */
6927 + if (errInfo->eiMPTabElementName != NULL)
6928 + msgLen += strlen(errInfo->eiMPTabElementName) + 15;
6929 + if (errInfo->eiStringPatText != NULL)
6930 + msgLen += strlen(errInfo->eiStringPatText) + 15;
6931 + if (errInfo->eiDetail != NULL)
6932 + msgLen += strlen(errInfo->eiDetail) + 15;
6933 + if (errInfo->eiBackRefNbr != 0)
6934 + msgLen += 15;
6935 + if (errInfo->eiRegExpCompileMsg != NULL)
6936 + msgLen += strlen(errInfo->eiRegExpCompileMsg) + 15;
6938 + message = XtMalloc(msgLen);
6940 + strcpy(message, "");
6942 + if (errInfo->eiMPTabElementName != NULL)
6943 + sprintf( message, "%sName : \"%s\"\n", message, errInfo->eiMPTabElementName);
6944 + if (errInfo->eiStringPatText != NULL)
6945 + sprintf( message, "%sPattern: \"%s\"\n", message, errInfo->eiStringPatText);
6946 + if (errInfo->eiBackRefNbr != 0)
6947 + sprintf( message, "%sBackref %d ", message, errInfo->eiBackRefNbr);
6948 + if (errInfo->eiDetail != NULL)
6949 + sprintf( message, "%s%s\n", message, errInfo->eiDetail);
6950 + if (errInfo->eiRegExpCompileMsg != NULL)
6951 + sprintf( message, "%s%s\n", message, errInfo->eiRegExpCompileMsg);
6953 + DialogF(
6954 + DF_WARN, MatchPatternDialog.mpdShell, 1,
6955 + title,
6956 + "%s(language mode '%s')",
6957 + "OK",
6958 + message,
6959 + errInfo->eiLanguageMode);
6961 + XtFree(message);
6963 + freeErrorInfo(errInfo);
6964 + initErrorInfo(errInfo);
6968 +** Get matching pattern set name.
6969 +** Syntax:
6970 +** patternName ::= "name:"
6971 +** Returns true, if get was successful.
6973 +static int getMPSName(
6974 + char **inPtr,
6975 + ErrorInfo *errInfo,
6976 + char **name )
6978 + char *dummy;
6979 + char *field = ReadSymbolicField(inPtr);
6981 + if (field == NULL)
6983 + errInfo->eiDetail = "matching pattern name missing";
6984 + return False;
6987 + if (!SkipDelimiter(inPtr, &dummy))
6989 + errInfo->eiMPTabElementName = XtNewString(field);
6990 + errInfo->eiDetail = "':' missing after matching pattern name";
6991 + XtFree( field );
6992 + return False;
6995 + *name = field;
6997 + return True;
7001 +** Get matching pattern set type attribute.
7002 +** TypeAttribute ::=
7003 +** [s|g]:
7005 +** s : sub-pattern (pattern is only matched, if part of a pattern group).
7006 +** g : pattern (context) group (i.e. a sequence of sub-patterns).
7007 +** default: individual pattern (pattern is not part of a group and is
7008 +** matched individually.
7009 +** Returns true, if get was successful.
7011 +static int getMPSTypeAttribute(
7012 + char **inPtr,
7013 + ErrorInfo *errInfo,
7014 + MatchPatternType *type)
7016 + char *field = ReadSymbolicField(inPtr);
7017 + int successful = True;
7019 + *type = MPT_INDIVIDUAL;
7021 + if (field != NULL)
7023 + switch (*field)
7025 + case 'g':
7026 + *type = MPT_GROUP;
7027 + break;
7028 + case 's':
7029 + *type = MPT_SUB;
7030 + break;
7031 + default:
7032 + errInfo->eiDetail = "unknown matching pattern type attribute";
7033 + successful = False;
7037 + if (successful)
7039 + if (!SkipDelimiter(inPtr, &errInfo->eiDetail))
7041 + successful = False;
7045 + freeXtPtr((void **)&field);
7047 + return successful;
7051 +** Syntax:
7053 +** GlobalAttribute ::=
7054 +** [c][f][m][p][u]:
7056 +** c : the content between start and end pattern is skipped
7057 +** during parsing (e.g. pattern encloses a comment).
7058 +** f : flash matching pattern (if not set, then only jump
7059 +** to matching pattern is supported).
7060 +** m : mono pattern - set exist out of only one single pattern
7061 +** (start pattern = end pattern; e.g. quotes like ")
7062 +** p : ignore highlight info code of single patterns of this set
7063 +** ("plain").
7065 +** Returns TRUE, if global attribute was successful read.
7067 +static int getMPSGlobalAttribute(
7068 + char **inPtr,
7069 + char **errMsg,
7070 + int *isMonoPattern,
7071 + int *comment,
7072 + int *flash,
7073 + int *ignoreHighLightInfo)
7075 + char *field = ReadSymbolicField(inPtr);
7076 + char *attribute;
7077 + int successful = True;
7079 + *isMonoPattern = False;
7080 + *comment = False;
7081 + *flash = False;
7082 + *ignoreHighLightInfo = False;
7084 + if (field != NULL)
7086 + attribute = field;
7087 + while (*attribute != '\0' && successful)
7089 + switch (*attribute)
7091 + case 'c':
7092 + *comment = True;
7093 + break;
7094 + case 'f':
7095 + *flash = True;
7096 + break;
7097 + case 'm':
7098 + *isMonoPattern = True;
7099 + break;
7100 + case 'p':
7101 + *ignoreHighLightInfo = True;
7102 + break;
7103 + default:
7104 + *errMsg = "unknown global attribute";
7105 + successful = False;
7107 + attribute ++;
7111 + if (successful)
7113 + if (!SkipDelimiter(inPtr, errMsg))
7115 + successful = False;
7119 + freeXtPtr((void **)&field);
7121 + return successful;
7125 +** Get matching pattern set attribute.
7127 +** Syntax:
7129 +** patternAttribute ::=
7130 +** [s|m|e][w|l|r][i]:
7132 +** StringPatternKind:
7133 +** s : start string pattern.
7134 +** m : middle string pattern.
7135 +** e : end string pattern.
7136 +** WordBoundaryAttribute:
7137 +** w : pattern is word (i.e. before and after pattern
7138 +** there must be a delimiter).
7139 +** l : before pattern must be a delimiter (left side).
7140 +** r : after pattern must be a delimiter (right side).
7141 +** default: neither before nor after pattern must be a delimiter.
7142 +** StringAttribute:
7143 +** i : pattern is case insensitive (if not set: pattern is
7144 +** case sensitive).
7145 +** x : pattern is regular expression (if not set: pattern is
7146 +** literal string).
7148 +** Returns TRUE, if pattern attribute was successful read.
7150 +static int getMPSPatternAttribute(
7151 + char **inPtr,
7152 + char **errMsg,
7153 + PatternElementKind *patternKind,
7154 + PatternWordBoundary *wordBoundary,
7155 + int *caseInsensitive,
7156 + int *regularExpression)
7158 + char *field = ReadSymbolicField(inPtr);
7159 + char *attribute;
7160 + int successful = True;
7162 + *patternKind = PEK_UNKNOWN;
7163 + *wordBoundary = PWB_NONE;
7164 + *caseInsensitive = False;
7165 + *regularExpression = False;
7167 + if (field != NULL)
7169 + attribute = field;
7170 + while (*attribute != '\0' && successful)
7172 + switch (*attribute)
7174 + case 'e':
7175 + *patternKind = PEK_END;
7176 + break;
7177 + case 'i':
7178 + *caseInsensitive = True;
7179 + break;
7180 + case 'l':
7181 + *wordBoundary = PWB_LEFT;
7182 + break;
7183 + case 'm':
7184 + *patternKind = PEK_MIDDLE;
7185 + break;
7186 + case 'r':
7187 + *wordBoundary = PWB_RIGHT;
7188 + break;
7189 + case 's':
7190 + *patternKind = PEK_START;
7191 + break;
7192 + case 'w':
7193 + *wordBoundary = PWB_BOTH;
7194 + break;
7195 + case 'x':
7196 + *regularExpression = True;
7197 + break;
7198 + default:
7199 + *errMsg = "unknown string pattern attribute";
7200 + successful = False;
7202 + attribute ++;
7206 + if (successful)
7208 + if (!SkipDelimiter(inPtr, errMsg))
7210 + successful = False;
7214 + freeXtPtr((void **)&field);
7216 + return successful;
7220 +** Returns the (to be reserved) reg. ex. length of an pattern element.
7221 +** Update total number of multi patterns, too.
7223 +static int patternElementLen(
7224 + ReadMatchPatternInfo *info,
7225 + PatternElement *patElement,
7226 + int *nbrOfMultiPatterns)
7228 + PatternElement *referredElement;
7229 + StringPattern *strPat = NULL;
7230 + int patElementLen;
7232 + switch (patElement->peType)
7234 + case PET_SINGLE:
7235 + strPat = &patElement->peVal.peuSingle;
7236 + break;
7238 + case PET_MULTIPLE:
7239 + strPat = &patElement->peVal.peuMulti.mpStringPattern;
7241 + (*nbrOfMultiPatterns) ++;
7243 + break;
7245 + case PET_REFERENCE:
7246 + referredElement =
7247 + info->rmpiElement[patElement->peVal.peuRef.prElementIdx]->
7248 + mpteAll.pesPattern[patElement->peVal.peuRef.prPatternIdx];
7250 + strPat = &referredElement->peVal.peuMulti.mpStringPattern;
7251 + break;
7254 + /*
7255 + * reserve additional 4 characters ("(?i)") for case insensitive search
7256 + */
7257 + if (strPat->spCaseInsensitive)
7258 + patElementLen = strPat->spLength + 4;
7259 + else
7260 + patElementLen = strPat->spLength;
7262 + /*
7263 + * reserve additional 4 characters ("(?:)") for regular expression
7264 + */
7265 + if (strPat->spRegularExpression)
7266 + patElementLen += 4;
7268 + return patElementLen;
7272 +** Returns the (to be reserved) total reg. ex. length of given
7273 +** MatchPatternTableElement. Update total number of multi patterns, too.
7275 +static int totalMatchPatternTableElementLen(
7276 + ReadMatchPatternInfo *info,
7277 + MatchPatternTableElement *element,
7278 + int *nbrOfMultiPatterns)
7280 + int i;
7281 + int totalLen = 0;
7283 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i ++)
7285 + totalLen +=
7286 + patternElementLen(
7287 + info,
7288 + element->mpteAll.pesPattern[i],
7289 + nbrOfMultiPatterns );
7292 + return totalLen;
7296 +** Returns the (to be reserved) total reg. ex. length of given
7297 +** read match pattern info. Counts total number of multi patterns, too.
7299 +static int totalKeywordOfTableLen(
7300 + ReadMatchPatternInfo *info,
7301 + int *nbrOfMultiPatterns)
7303 + int i;
7304 + int totalLen = 0;
7306 + *nbrOfMultiPatterns = 0;
7308 + for (i=0; i<info->rmpiNbrOfElements; i ++)
7310 + totalLen +=
7311 + totalMatchPatternTableElementLen(
7312 + info,
7313 + info->rmpiElement[i],
7314 + nbrOfMultiPatterns);
7317 + return totalLen;
7321 +** Add given StringPattern to given reg. ex. strings
7323 +static void addPatternToRegExpString(
7324 + StringPattern *pattern,
7325 + RegExpStringInfo *regExpStringInfo)
7327 + char *r = NULL, *s;
7328 + char *adaptedRegExpText = NULL;
7329 + int prevLen = 0;
7331 + /*
7332 + * Select the buffer, where the pattern needs to be added
7333 + * to (depending on its word boundary). Prepare the buffer
7334 + * by evtl. adding a prefix, if related buffer is empty.
7335 + */
7336 + switch (pattern->spWordBoundary)
7338 + case PWB_NONE:
7339 + prevLen = strlen( regExpStringInfo->resiNoneWBRegExpString );
7341 + r = regExpStringInfo->resiNoneWBRegExpString + strlen( regExpStringInfo->resiNoneWBRegExpString );
7342 + break;
7343 + case PWB_LEFT:
7344 + prevLen = strlen( regExpStringInfo->resiLeftWBRegExpString );
7345 + if (prevLen == 0)
7347 + strcpy( regExpStringInfo->resiLeftWBRegExpString, "<(?:" );
7349 + r = regExpStringInfo->resiLeftWBRegExpString + strlen( regExpStringInfo->resiLeftWBRegExpString );
7350 + break;
7351 + case PWB_RIGHT:
7352 + prevLen = strlen( regExpStringInfo->resiRightWBRegExpString );
7353 + if (prevLen == 0)
7355 + strcpy( regExpStringInfo->resiRightWBRegExpString, "(?:" );
7357 + r = regExpStringInfo->resiRightWBRegExpString + strlen( regExpStringInfo->resiRightWBRegExpString );
7358 + break;
7359 + case PWB_BOTH:
7360 + prevLen = strlen( regExpStringInfo->resiBothWBRegExpString );
7361 + if (prevLen == 0)
7363 + strcpy( regExpStringInfo->resiBothWBRegExpString, "<(?:" );
7365 + r = regExpStringInfo->resiBothWBRegExpString + strlen( regExpStringInfo->resiBothWBRegExpString );
7366 + break;
7369 + /*
7370 + * add an "or" if there is already a pattern in the buffer
7371 + */
7372 + if (prevLen != 0)
7374 + *r++ = '|';
7377 + /*
7378 + * add "(?i" to order case insensitive search
7379 + */
7380 + if (pattern->spCaseInsensitive)
7382 + *r++ = '(';
7383 + *r++ = '?';
7384 + *r++ = 'i';
7387 + /*
7388 + * add "(?:" to group this regular expression
7389 + */
7390 + if (pattern->spRegularExpression)
7392 + *r++ = '(';
7393 + *r++ = '?';
7394 + *r++ = ':';
7396 + adaptedRegExpText =
7397 + adaptLocalBackRefs(
7398 + pattern->spText,
7399 + &regExpStringInfo->resiLocalBackRefID);
7401 + s = adaptedRegExpText;
7403 + else
7405 + s = pattern->spText;
7408 + /*
7409 + * add the pattern characters - evtl. escaped, if special
7410 + * regular expression symbols & pattern is no reg. exp. -
7411 + * to the buffer:
7412 + */
7414 + while (*s != '\0')
7416 + if (!pattern->spRegularExpression)
7418 + switch (*s)
7420 + case '(':
7421 + case ')':
7422 + case '-':
7423 + case '[':
7424 + case ']':
7425 + case '<':
7426 + case '>':
7427 + case '{':
7428 + case '}':
7429 + case '.':
7430 + case '\\':
7431 + case '|':
7432 + case '^':
7433 + case '$':
7434 + case '*':
7435 + case '+':
7436 + case '?':
7437 + case '&':
7438 + *r++ = '\\';
7439 + break;
7440 + };
7443 + *r++ = *s++;
7446 + /*
7447 + * close "reg. exp. group" bracket
7448 + */
7449 + if (pattern->spRegularExpression)
7451 + *r++ = ')';
7453 + XtFree(adaptedRegExpText);
7456 + /*
7457 + * close case insensitive search bracket
7458 + */
7459 + if (pattern->spCaseInsensitive)
7461 + *r++ = ')';
7464 + /*
7465 + * terminate added string
7466 + */
7467 + *r = '\0';
7471 +** Adapt local backrefs inside given regExpText by common local IDs.
7472 +** Returns new allocated reg. exp. string holding common local backrefs.
7474 +static char *adaptLocalBackRefs(
7475 + char *regExpText,
7476 + int *commonLocalId)
7478 + int id;
7479 + int ownLocalId = 0;
7480 + char *s = regExpText;
7481 + char *newRegExpText = XtMalloc(strlen(regExpText)*3);
7482 + char *n = newRegExpText;
7483 + int localBackRefList[MAX_LOCAL_BACK_REF_ID];
7485 + /*
7486 + * put all local backrefs into "localBackRefList".
7487 + */
7488 + scanForLocalBackRefs(regExpText, localBackRefList);
7490 + while (*s != '\0')
7492 + *n++ = *s;
7494 + if (*s == '\\')
7496 + s++;
7498 + if (isdigit((unsigned char)*s))
7500 + /*
7501 + * \n (n=1..9) found: replace local backref.
7502 + * by "common local ID"
7503 + */
7504 + id =
7505 + (int)((unsigned char)*s - (unsigned char)'0') - 1;
7507 + if (localBackRefList[id] != NO_LOCAL_BACK_REF_ID &&
7508 + localBackRefList[id] != LOCAL_BACK_REF_ID_USED)
7510 + *n++ = (char)((int)('0') + localBackRefList[id]);
7512 + else
7514 + *n++ = '0';
7517 + s ++;
7519 + else if (*s != '\0')
7521 + /*
7522 + * copy escaped character
7523 + */
7524 + *n++ = *s++;
7527 + else if (*s == '(')
7529 + s ++;
7531 + if (*s == '?')
7533 + /*
7534 + * non capturing parentheses found -> just copy it
7535 + */
7536 + *n++ = *s++;
7538 + else
7540 + /*
7541 + * capturing parentheses found:
7542 + */
7543 + if (localBackRefList[ownLocalId] == LOCAL_BACK_REF_ID_USED)
7545 + /*
7546 + * backref used within given reg. exp. text:
7547 + * remember common local id for replacement later on
7548 + */
7549 + localBackRefList[ownLocalId] = *commonLocalId;
7550 + (*commonLocalId) ++;
7551 + ownLocalId ++;
7553 + else
7555 + /*
7556 + * backref not used within given reg. exp. text:
7557 + * replace capturing parentheses by non capturing one
7558 + */
7559 + *n++ = '?';
7560 + *n++ = ':';
7564 + else
7566 + s ++;
7570 + /*
7571 + * terminate adapted string
7572 + */
7573 + *n = '\0';
7575 + return newRegExpText;
7579 +** Get all local backrefs of given regExpText and put them into
7580 +** given localBackRefList.
7582 +static void scanForLocalBackRefs(
7583 + char *regExpText,
7584 + int *localBackRefList)
7586 + int i;
7587 + int localId;
7588 + char *s = regExpText;
7590 + for (i=0; i<MAX_LOCAL_BACK_REF_ID; i++)
7592 + localBackRefList[i] = NO_LOCAL_BACK_REF_ID;
7595 + while (*s != '\0')
7597 + if (*s == '\\')
7599 + if (isdigit((unsigned char)*(s+1)))
7601 + /*
7602 + * \n (n=1..9) found: flag usage in local backref list
7603 + */
7604 + localId =
7605 + (int)((unsigned char)*(s+1) - (unsigned char)'0') - 1;
7607 + localBackRefList[localId] = LOCAL_BACK_REF_ID_USED;
7609 + s ++;
7611 + else if (*(s+1) != '\0')
7612 + s ++;
7614 + s ++;
7619 +** Returns true, if string of given multi pattern reference was
7620 +** not added to regExpStringInfo.
7622 +static int isMultiPatternNotAdded(
7623 + RegExpStringInfo *regExpStringInfo,
7624 + PatternReference *toBeAddedPR)
7626 + int i;
7627 + PatternReference *addedPR;
7628 + PatternReference *newPR;
7630 + for (i=0; i < regExpStringInfo->resiNbrOfAddedMultiPat; i++)
7632 + addedPR = regExpStringInfo->resiAddedMultiPat[i];
7634 + if (addedPR->prElementIdx == toBeAddedPR->prElementIdx &&
7635 + addedPR->prPatternIdx == toBeAddedPR->prPatternIdx)
7637 + return False;
7641 + newPR = (PatternReference *)XtMalloc(sizeof(PatternReference));
7643 + *newPR = *toBeAddedPR;
7645 + regExpStringInfo->resiAddedMultiPat[regExpStringInfo->resiNbrOfAddedMultiPat ++] = newPR;
7647 + return True;
7651 +** add given PatternElement to given reg. exp. strings
7653 +static void addUniquePatternToRegExpString(
7654 + PatternElement *patElement,
7655 + PatternReference *patElementReference,
7656 + ReadMatchPatternInfo *readMatchPatternInfo,
7657 + RegExpStringInfo *regExpStringInfo)
7659 + PatternElement *referredElement;
7660 + PatternReference referredPatReference;
7662 + switch (patElement->peType)
7664 + case PET_SINGLE:
7665 + addPatternToRegExpString(
7666 + &(patElement->peVal.peuSingle),
7667 + regExpStringInfo);
7668 + break;
7670 + case PET_MULTIPLE:
7671 + /*
7672 + * add element to reg. exp. string only, if it was
7673 + * not added before.
7674 + */
7675 + if (isMultiPatternNotAdded(regExpStringInfo, patElementReference))
7677 + addPatternToRegExpString(
7678 + &(patElement->peVal.peuMulti.mpStringPattern),
7679 + regExpStringInfo);
7681 + break;
7683 + case PET_REFERENCE:
7684 + /*
7685 + * add referred element to reg. exp. string only, if related
7686 + * multi pattern was not added before.
7687 + */
7688 + referredPatReference = patElement->peVal.peuRef;
7690 + referredElement =
7691 + readMatchPatternInfo->rmpiElement[referredPatReference.prElementIdx]->
7692 + mpteAll.pesPattern[referredPatReference.prPatternIdx];
7694 + if (isMultiPatternNotAdded(regExpStringInfo, &referredPatReference))
7696 + addPatternToRegExpString(
7697 + &(referredElement->peVal.peuMulti.mpStringPattern),
7698 + regExpStringInfo);
7700 + break;
7705 +** add given MatchPatternTableElement to given reg. ex. strings
7707 +static void addElementToRegExpString(
7708 + MatchPatternTableElement *element,
7709 + ReadMatchPatternInfo *readMatchPatternInfo,
7710 + RegExpStringInfo *regExpStringInfo)
7712 + int i;
7713 + PatternReference elementRef;
7715 + elementRef.prElementIdx = element->mpteIndex;
7717 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i ++)
7719 + elementRef.prPatternIdx = i;
7721 + addUniquePatternToRegExpString(
7722 + element->mpteAll.pesPattern[i],
7723 + &elementRef,
7724 + readMatchPatternInfo,
7725 + regExpStringInfo);
7730 +** Concatenate strings stored by regExpStringInfo.
7731 +** Free given regExpStringInfo afterwards.
7732 +** Returns resulting string.
7734 +static void catSMTRegExpStrings(
7735 + RegExpStringInfo *regExpStringInfo,
7736 + char **regExpString)
7738 + int resultingLen;
7740 + /*
7741 + * allocate & init. a buffer for the resulting regular expression
7742 + */
7743 + resultingLen =
7744 + strlen( regExpStringInfo->resiNoneWBRegExpString ) +
7745 + strlen( regExpStringInfo->resiLeftWBRegExpString ) +
7746 + strlen( regExpStringInfo->resiRightWBRegExpString ) +
7747 + strlen( regExpStringInfo->resiBothWBRegExpString ) + 5;
7749 + *regExpString = XtMalloc( resultingLen );
7751 + strcpy( *regExpString, "" );
7753 + /*
7754 + * add the single parts to the resulting regular expression
7755 + * (= cat of parts separated by an "or")
7756 + */
7757 + addSMTRegExpString( *regExpString, regExpStringInfo->resiNoneWBRegExpString, "" );
7758 + addSMTRegExpString( *regExpString, regExpStringInfo->resiLeftWBRegExpString, ")" );
7759 + addSMTRegExpString( *regExpString, regExpStringInfo->resiRightWBRegExpString, ")>" );
7760 + addSMTRegExpString( *regExpString, regExpStringInfo->resiBothWBRegExpString, ")>" );
7762 + /*
7763 + * free buffers
7764 + */
7765 + freeRegExpStringInfo( regExpStringInfo );
7769 +** Free the allocated memory contained in a RegExpStringInfo data structure
7771 +static void freeRegExpStringInfo(
7772 + RegExpStringInfo *regExpStringInfo)
7774 + int i;
7776 + XtFree( regExpStringInfo->resiNoneWBRegExpString );
7777 + XtFree( regExpStringInfo->resiLeftWBRegExpString );
7778 + XtFree( regExpStringInfo->resiRightWBRegExpString );
7779 + XtFree( regExpStringInfo->resiBothWBRegExpString );
7781 + for (i=0; i < regExpStringInfo->resiNbrOfAddedMultiPat; i ++)
7782 + XtFree( (char *)regExpStringInfo->resiAddedMultiPat[i] );
7784 + XtFree( (char *)regExpStringInfo->resiAddedMultiPat);
7788 +** Compose regular expression for start / end pattern.
7790 +static void composeStartEndRegExpString(
7791 + ReadMatchPatternInfo *readMatchPatternInfo,
7792 + MatchPatternTableElement *element,
7793 + char **regExpString)
7795 + int i;
7796 + RegExpStringInfo regExpStringInfo;
7797 + PatternReference elementRef;
7798 + PatternElementSet startPat = element->mpteStart;
7799 + PatternElementSet endPat = element->mpteEnd;
7801 + /*
7802 + * Allocate buffers for keyword regular expression.
7803 + */
7804 + setupRegExpStringBuffers(
7805 + readMatchPatternInfo,
7806 + &regExpStringInfo);
7808 + /*
7809 + * Treat start / end element of MatchPatternTableElement
7810 + */
7812 + elementRef.prElementIdx = element->mpteIndex;
7814 + for (i=0; i < startPat.pesNumberOfPattern; i ++)
7816 + elementRef.prPatternIdx = startPat.pesPattern[i]->peIndex;
7818 + addUniquePatternToRegExpString(
7819 + startPat.pesPattern[i],
7820 + &elementRef,
7821 + readMatchPatternInfo,
7822 + &regExpStringInfo);
7825 + for (i=0; i < endPat.pesNumberOfPattern; i ++)
7827 + elementRef.prPatternIdx = endPat.pesPattern[i]->peIndex;
7829 + addUniquePatternToRegExpString(
7830 + endPat.pesPattern[i],
7831 + &elementRef,
7832 + readMatchPatternInfo,
7833 + &regExpStringInfo);
7836 + /*
7837 + * Assemble the resulting regular expression
7838 + */
7839 + catSMTRegExpStrings(
7840 + &regExpStringInfo,
7841 + regExpString);
7844 +static void copyStringMatchTableForDialog(
7845 + StringMatchTable *sourceTable,
7846 + DialogMatchPatternInfo *dialogTable )
7848 + int i;
7850 + /*
7851 + * if no source table exist (yet), then set nbr. of elements / groups to 0
7852 + */
7853 + if (sourceTable == NULL)
7855 + dialogTable->dmpiNbrOfSeqElements = 0;
7857 + return;
7860 + /*
7861 + * copy matching pattern sequence
7862 + */
7863 + dialogTable->dmpiNbrOfSeqElements = sourceTable->smtNumberOfSeqElements;
7865 + for (i=0; i < sourceTable->smtNumberOfSeqElements; i ++)
7867 + copySequenceElementForDialog(
7868 + sourceTable,
7869 + sourceTable->smtSequence[i],
7870 + &dialogTable->dmpiSequence[i] );
7874 +static void *copyMatchPatternElementForDialog(
7875 + MatchPatternTable *table,
7876 + int sourceElementIdx)
7878 + int i;
7879 + int patIdx = 0;
7880 + MatchPatternTableElement *sourceElement;
7881 + DialogMatchPatternTableElement *destination;
7883 + sourceElement = table->mptElements[sourceElementIdx];
7885 + destination =
7886 + (DialogMatchPatternTableElement *)XtMalloc( sizeof(DialogMatchPatternTableElement) );
7888 + destination->dmpteName = XtNewString(sourceElement->mpteName);
7889 + destination->dmpteType = sourceElement->mpteType;
7890 + destination->dmpteSkipBtwnStartEnd = sourceElement->mpteSkipBtwnStartEnd;
7891 + destination->dmpteIgnoreHighLightInfo = sourceElement->mpteIgnoreHighLightInfo;
7892 + destination->dmpteFlash = sourceElement->mpteFlash;
7894 + for (i=0; i<sourceElement->mpteAll.pesNumberOfPattern; i++)
7896 + copyPatternForDialog(
7897 + table,
7898 + sourceElement->mpteAll.pesPattern[i],
7899 + &destination->dmptePatterns.dspElements[patIdx ++]);
7902 + destination->dmptePatterns.dspNumberOfPatterns = patIdx;
7904 + return (void *)destination;
7907 +static void copyPatternForDialog(
7908 + MatchPatternTable *table,
7909 + PatternElement *sourcePattern,
7910 + DialogStringPatternElement **dialogPattern )
7912 + DialogStringPatternElement *newPat;
7913 + StringPattern *strSourcePat = GetStringPattern( table, sourcePattern );
7915 + newPat = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
7916 + *dialogPattern = newPat;
7918 + if( strSourcePat->spOrigText != NULL)
7919 + newPat->dspeText = XtNewString(strSourcePat->spOrigText);
7920 + else
7921 + newPat->dspeText = XtNewString(strSourcePat->spText);
7923 + newPat->dspeKind = sourcePattern->peKind;
7924 + newPat->dspeWordBoundary = strSourcePat->spWordBoundary;
7925 + newPat->dspeCaseInsensitive = strSourcePat->spCaseInsensitive;
7926 + newPat->dspeRegularExpression = strSourcePat->spRegularExpression;
7929 +static void *copyGroupElementForDialog(
7930 + MatchPatternGroupElement *sourceGroup)
7932 + int i;
7933 + DialogMatchPatternGroupElement *destination;
7935 + destination =
7936 + (DialogMatchPatternGroupElement *)XtMalloc( sizeof(DialogMatchPatternGroupElement) );
7938 + destination->dmpgeName = XtNewString(sourceGroup->mpgeName);
7939 + destination->dmpgeNumberOfSubPatterns = sourceGroup->mpgeNumberOfSubPatterns;
7941 + for ( i=0; i<destination->dmpgeNumberOfSubPatterns; i ++)
7943 + destination->dmpgeSubPatternIds[i] =
7944 + XtNewString(sourceGroup->mpgeSubPatternIds[i]);
7947 + return destination;
7950 +static void copySequenceElementForDialog(
7951 + StringMatchTable *sourceTable,
7952 + MatchPatternSequenceElement *sourceSeqElement,
7953 + DialogMatchPatternSequenceElement **dialogSeqElement )
7955 + DialogMatchPatternSequenceElement *destSeqElement;
7957 + destSeqElement =
7958 + (DialogMatchPatternSequenceElement *)XtMalloc( sizeof(DialogMatchPatternSequenceElement) );
7960 + *dialogSeqElement = destSeqElement;
7962 + destSeqElement->dmpseName = XtNewString(sourceSeqElement->mpseName);
7963 + destSeqElement->dmpseType = sourceSeqElement->mpseType;
7964 + destSeqElement->dmpseValid = True;
7966 + if (destSeqElement->dmpseType == MPT_GROUP)
7968 + destSeqElement->dmpsePtr =
7969 + copyGroupElementForDialog(
7970 + sourceTable->smtGroups[sourceSeqElement->mpseIndex]);
7972 + else
7974 + destSeqElement->dmpsePtr =
7975 + copyMatchPatternElementForDialog(
7976 + sourceTable->smtAllPatterns,
7977 + sourceSeqElement->mpseIndex);
7981 +static DialogMatchPatternSequenceElement *copyDialogSequenceElement(
7982 + DialogMatchPatternSequenceElement *sourceSeq)
7984 + DialogMatchPatternSequenceElement *destSeq;
7986 + destSeq =
7987 + (DialogMatchPatternSequenceElement *)XtMalloc(sizeof(DialogMatchPatternSequenceElement));
7989 + destSeq->dmpseName = XtNewString(sourceSeq->dmpseName);
7990 + destSeq->dmpseType = sourceSeq->dmpseType;
7991 + destSeq->dmpseValid = True;
7993 + destSeq->dmpsePtr = sourceSeq->dmpsePtr;
7995 + return destSeq;
7998 +static void freeDialogMatchPatternElement(
7999 + DialogMatchPatternTableElement *dialogElement )
8001 + int i;
8003 + for (i=0; i<dialogElement->dmptePatterns.dspNumberOfPatterns; i ++)
8005 + freeDialogStringPatternElement(
8006 + dialogElement->dmptePatterns.dspElements[i]);
8009 + freeXtPtr((void **)&dialogElement->dmpteName);
8011 + freeXtPtr((void **)&dialogElement);
8014 +static void freeDialogStringPatternElement(
8015 + DialogStringPatternElement *element)
8017 + freeXtPtr((void **)&element->dspeText);
8019 + freeXtPtr((void **)&element);
8022 +static void freeDialogGroupElement(
8023 + DialogMatchPatternGroupElement *dialogGroup )
8025 + int i;
8027 + for (i=0; i<dialogGroup->dmpgeNumberOfSubPatterns; i ++)
8029 + freeXtPtr((void **)&dialogGroup->dmpgeSubPatternIds[i]);
8032 + freeXtPtr((void **)&dialogGroup->dmpgeName);
8034 + freeXtPtr((void **)&dialogGroup);
8037 +static void freeDialogSequenceElement(
8038 + DialogMatchPatternSequenceElement *dialogSeq )
8040 + freeXtPtr((void **)&dialogSeq->dmpseName);
8042 + if (dialogSeq->dmpseType == MPT_GROUP)
8044 + freeDialogGroupElement(
8045 + (DialogMatchPatternGroupElement *)dialogSeq->dmpsePtr );
8047 + else
8049 + freeDialogMatchPatternElement(
8050 + (DialogMatchPatternTableElement *)dialogSeq->dmpsePtr );
8053 + freeXtPtr((void **)&dialogSeq);
8056 +static void copyDialogStringPatternsFromTable(
8057 + DialogMatchPatternTableElement *tableElement,
8058 + DialogStringPatterns *destPatterns)
8060 + int i;
8062 + destPatterns->dspNumberOfPatterns =
8063 + tableElement->dmptePatterns.dspNumberOfPatterns;
8065 + for (i=0; i<destPatterns->dspNumberOfPatterns; i++)
8067 + destPatterns->dspElements[i] =
8068 + copyDialogStringPatternElement(
8069 + tableElement->dmptePatterns.dspElements[i] );
8073 +static void copyDialogStringPatterns(
8074 + DialogStringPatterns *sourcePatterns,
8075 + DialogStringPatterns *destPatterns)
8077 + int i;
8079 + destPatterns->dspNumberOfPatterns =
8080 + sourcePatterns->dspNumberOfPatterns;
8082 + for (i=0; i<destPatterns->dspNumberOfPatterns; i++)
8084 + destPatterns->dspElements[i] =
8085 + copyDialogStringPatternElement(
8086 + sourcePatterns->dspElements[i] );
8090 +static void freeDialogStringPatterns(
8091 + DialogStringPatterns *patterns)
8093 + int i;
8095 + for (i=0; i<patterns->dspNumberOfPatterns; i++)
8097 + freeDialogStringPatternElement(patterns->dspElements[i]);
8100 + patterns->dspNumberOfPatterns = 0;
8103 +static DialogStringPatternElement *copyDialogStringPatternElement(
8104 + DialogStringPatternElement *sourceElement)
8106 + DialogStringPatternElement *newPatElement;
8108 + newPatElement = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
8110 + newPatElement->dspeText = XtNewString(sourceElement->dspeText);
8111 + newPatElement->dspeKind = sourceElement->dspeKind;
8112 + newPatElement->dspeWordBoundary = sourceElement->dspeWordBoundary;
8113 + newPatElement->dspeCaseInsensitive = sourceElement->dspeCaseInsensitive;
8114 + newPatElement->dspeRegularExpression = sourceElement->dspeRegularExpression;
8116 + return newPatElement;
8119 +static void copyDialogPatternNamesFromGroup(
8120 + DialogMatchPatternGroupElement *group,
8121 + DialogStringPatterns *destPatterns)
8123 + int i;
8125 + destPatterns->dspNumberOfPatterns =
8126 + group->dmpgeNumberOfSubPatterns;
8128 + for (i=0; i<destPatterns->dspNumberOfPatterns; i++)
8130 + destPatterns->dspElements[i] =
8131 + copyDialogPatternName(
8132 + group->dmpgeSubPatternIds[i] );
8136 +static DialogStringPatternElement *copyDialogPatternName(
8137 + char *sourcePatternId)
8139 + DialogStringPatternElement *newPatElement;
8141 + newPatElement = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
8143 + newPatElement->dspeText = XtNewString(sourcePatternId);
8144 + newPatElement->dspeKind = PEK_START;
8145 + newPatElement->dspeWordBoundary = PWB_NONE;
8146 + newPatElement->dspeCaseInsensitive = False;
8147 + newPatElement->dspeRegularExpression = False;
8149 + return newPatElement;
8152 +static void copyDialogPatternNamesToGroup(
8153 + DialogStringPatterns *sourceNames,
8154 + DialogMatchPatternGroupElement *destGroup)
8156 + int i;
8158 + destGroup->dmpgeNumberOfSubPatterns =
8159 + sourceNames->dspNumberOfPatterns;
8161 + for (i=0; i<destGroup->dmpgeNumberOfSubPatterns; i++)
8163 + destGroup->dmpgeSubPatternIds[i] =
8164 + XtNewString(
8165 + sourceNames->dspElements[i]->dspeText);
8171 +** Present a dialog for editing matching pattern information
8173 +void EditMatchPatterns(WindowInfo *window)
8175 + Widget form, lmOptMenu;
8176 + Widget lmForm;
8177 + Widget okBtn, applyBtn, checkBtn, deleteBtn, closeBtn, helpBtn;
8178 + Widget restoreBtn, lmBtn;
8179 + Widget matchPatternsForm, matchPatternsFrame, matchPatternsLbl;
8180 + Widget matchPatternTypeBox, matchPatternTypeLbl;
8181 + Widget globalAttributesBox;
8182 + Widget stringPatternsFrame, stringPatternsForm;
8183 + Widget stringPatternTypeBox;
8184 + Widget wordBoundaryBox;
8185 + Widget stringAttributesBox;
8186 + StringMatchTable *table;
8187 + XmString s1;
8188 + int n;
8189 + Arg args[20];
8191 + /*
8192 + * if the dialog is already displayed, just pop it to the top and return
8193 + */
8194 + if (MatchPatternDialog.mpdShell != NULL)
8196 + RaiseDialogWindow(MatchPatternDialog.mpdShell);
8197 + return;
8200 + /*
8201 + * decide on an initial language mode
8202 + */
8203 + MatchPatternDialog.mpdLangModeName =
8204 + XtNewString(
8205 + window->languageMode == PLAIN_LANGUAGE_MODE ?
8206 + PLAIN_LM_STRING : LanguageModeName(window->languageMode));
8208 + /*
8209 + * find the associated matching pattern table to edit
8210 + */
8211 + table = (StringMatchTable *)FindStringMatchTable(MatchPatternDialog.mpdLangModeName);
8213 + /*
8214 + * copy the list of patterns to one that the user can freely edit
8215 + */
8216 + copyStringMatchTableForDialog( table, &MatchPatternDialog.mpdTable );
8218 + /*
8219 + * init. status information of dialog
8220 + */
8221 + MatchPatternDialog.currentDmptSeqElement = NULL;
8222 + MatchPatternDialog.currentDmptElement = NULL;
8223 + MatchPatternDialog.currentDmptGroup = NULL;
8225 + MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns = 0;
8226 + MatchPatternDialog.mpdStringPatternIsDisplayed = True;
8228 + /*
8229 + * Create a form widget in an application shell
8230 + */
8231 + n = 0;
8232 + XtSetArg(args[n], XmNdeleteResponse, XmDO_NOTHING); n++;
8233 + XtSetArg(args[n], XmNiconName, "Matching Patterns"); n++;
8234 + XtSetArg(args[n], XmNtitle, "Matching (Parenthesis) Patterns"); n++;
8235 + MatchPatternDialog.mpdShell = CreateShellWithBestVis(APP_NAME, APP_CLASS,
8236 + applicationShellWidgetClass, TheDisplay, args, n);
8237 + AddSmallIcon(MatchPatternDialog.mpdShell);
8238 + form = XtVaCreateManagedWidget("editMatchPatterns", xmFormWidgetClass,
8239 + MatchPatternDialog.mpdShell, XmNautoUnmanage, False,
8240 + XmNresizePolicy, XmRESIZE_NONE, NULL);
8241 + XtAddCallback(form, XmNdestroyCallback, destroyCB, NULL);
8242 + AddMotifCloseCallback(MatchPatternDialog.mpdShell, closeCB, NULL);
8244 + lmForm = XtVaCreateManagedWidget("lmForm", xmFormWidgetClass,
8245 + form,
8246 + XmNleftAttachment, XmATTACH_POSITION,
8247 + XmNleftPosition, 1,
8248 + XmNtopAttachment, XmATTACH_POSITION,
8249 + XmNtopPosition, 1,
8250 + XmNrightAttachment, XmATTACH_POSITION,
8251 + XmNrightPosition, 99, NULL);
8253 + MatchPatternDialog.mpdLmPulldown =
8254 + CreateLanguageModeMenu(lmForm, matchPatternLangModeCB, NULL, True);
8256 + n = 0;
8257 + XtSetArg(args[n], XmNspacing, 0); n++;
8258 + XtSetArg(args[n], XmNmarginWidth, 0); n++;
8259 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
8260 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8261 + XtSetArg(args[n], XmNleftPosition, 50); n++;
8262 + XtSetArg(args[n], XmNsubMenuId, MatchPatternDialog.mpdLmPulldown); n++;
8263 + lmOptMenu = XmCreateOptionMenu(lmForm, "langModeOptMenu", args, n);
8264 + XtManageChild(lmOptMenu);
8265 + MatchPatternDialog.mpdLmOptMenu = lmOptMenu;
8267 + XtVaCreateManagedWidget("lmLbl", xmLabelGadgetClass, lmForm,
8268 + XmNlabelString, s1=XmStringCreateSimple("Language Mode:"),
8269 + XmNmnemonic, 'M',
8270 + XmNuserData, XtParent(MatchPatternDialog.mpdLmOptMenu),
8271 + XmNalignment, XmALIGNMENT_END,
8272 + XmNrightAttachment, XmATTACH_POSITION,
8273 + XmNrightPosition, 50,
8274 + XmNtopAttachment, XmATTACH_FORM,
8275 + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
8276 + XmNbottomWidget, lmOptMenu, NULL);
8277 + XmStringFree(s1);
8279 + lmBtn = XtVaCreateManagedWidget("lmBtn", xmPushButtonWidgetClass, lmForm,
8280 + XmNlabelString, s1=MKSTRING("Add / Modify\nLanguage Mode..."),
8281 + XmNmnemonic, 'A',
8282 + XmNrightAttachment, XmATTACH_FORM,
8283 + XmNtopAttachment, XmATTACH_FORM, NULL);
8284 + XtAddCallback(lmBtn, XmNactivateCallback, pmLanguageModeDialogCB, NULL);
8285 + XmStringFree(s1);
8287 + okBtn = XtVaCreateManagedWidget("ok", xmPushButtonWidgetClass, form,
8288 + XmNlabelString, s1=XmStringCreateSimple("OK"),
8289 + XmNleftAttachment, XmATTACH_POSITION,
8290 + XmNleftPosition, 1,
8291 + XmNrightAttachment, XmATTACH_POSITION,
8292 + XmNrightPosition, 13,
8293 + XmNbottomAttachment, XmATTACH_FORM,
8294 + XmNbottomOffset, BORDER, NULL);
8295 + XtAddCallback(okBtn, XmNactivateCallback, okCB, NULL);
8296 + XmStringFree(s1);
8298 + applyBtn = XtVaCreateManagedWidget("apply", xmPushButtonWidgetClass, form,
8299 + XmNlabelString, s1=XmStringCreateSimple("Apply"),
8300 + XmNmnemonic, 'y',
8301 + XmNleftAttachment, XmATTACH_POSITION,
8302 + XmNleftPosition, 13,
8303 + XmNrightAttachment, XmATTACH_POSITION,
8304 + XmNrightPosition, 26,
8305 + XmNbottomAttachment, XmATTACH_FORM,
8306 + XmNbottomOffset, BORDER, NULL);
8307 + XtAddCallback(applyBtn, XmNactivateCallback, applyCB, NULL);
8308 + XmStringFree(s1);
8310 + checkBtn = XtVaCreateManagedWidget("check", xmPushButtonWidgetClass, form,
8311 + XmNlabelString, s1=XmStringCreateSimple("Check"),
8312 + XmNmnemonic, 'k',
8313 + XmNleftAttachment, XmATTACH_POSITION,
8314 + XmNleftPosition, 26,
8315 + XmNrightAttachment, XmATTACH_POSITION,
8316 + XmNrightPosition, 39,
8317 + XmNbottomAttachment, XmATTACH_FORM,
8318 + XmNbottomOffset, BORDER, NULL);
8319 + XtAddCallback(checkBtn, XmNactivateCallback, checkCB, NULL);
8320 + XmStringFree(s1);
8322 + deleteBtn = XtVaCreateManagedWidget("delete", xmPushButtonWidgetClass, form,
8323 + XmNlabelString, s1=XmStringCreateSimple("Delete"),
8324 + XmNmnemonic, 'D',
8325 + XmNleftAttachment, XmATTACH_POSITION,
8326 + XmNleftPosition, 39,
8327 + XmNrightAttachment, XmATTACH_POSITION,
8328 + XmNrightPosition, 52,
8329 + XmNbottomAttachment, XmATTACH_FORM,
8330 + XmNbottomOffset, BORDER, NULL);
8331 + XtAddCallback(deleteBtn, XmNactivateCallback, deleteCB, NULL);
8332 + XmStringFree(s1);
8334 + restoreBtn = XtVaCreateManagedWidget("restore", xmPushButtonWidgetClass, form,
8335 + XmNlabelString, s1=XmStringCreateSimple("Restore Defaults"),
8336 + XmNmnemonic, 'f',
8337 + XmNleftAttachment, XmATTACH_POSITION,
8338 + XmNleftPosition, 52,
8339 + XmNrightAttachment, XmATTACH_POSITION,
8340 + XmNrightPosition, 73,
8341 + XmNbottomAttachment, XmATTACH_FORM,
8342 + XmNbottomOffset, BORDER, NULL);
8343 + XtAddCallback(restoreBtn, XmNactivateCallback, restoreCB, NULL);
8344 + XmStringFree(s1);
8346 + closeBtn = XtVaCreateManagedWidget("close", xmPushButtonWidgetClass,
8347 + form,
8348 + XmNlabelString, s1=XmStringCreateSimple("Close"),
8349 + XmNleftAttachment, XmATTACH_POSITION,
8350 + XmNleftPosition, 73,
8351 + XmNrightAttachment, XmATTACH_POSITION,
8352 + XmNrightPosition, 86,
8353 + XmNbottomAttachment, XmATTACH_FORM,
8354 + XmNbottomOffset, BORDER, NULL);
8355 + XtAddCallback(closeBtn, XmNactivateCallback, closeCB, NULL);
8356 + XmStringFree(s1);
8358 + helpBtn = XtVaCreateManagedWidget("help", xmPushButtonWidgetClass,
8359 + form,
8360 + XmNlabelString, s1=XmStringCreateSimple("Help"),
8361 + XmNmnemonic, 'H',
8362 + XmNleftAttachment, XmATTACH_POSITION,
8363 + XmNleftPosition, 86,
8364 + XmNrightAttachment, XmATTACH_POSITION,
8365 + XmNrightPosition, 99,
8366 + XmNbottomAttachment, XmATTACH_FORM,
8367 + XmNbottomOffset, BORDER, NULL);
8368 + XtAddCallback(helpBtn, XmNactivateCallback, helpCB, NULL);
8369 + XmStringFree(s1);
8371 + stringPatternsFrame = XtVaCreateManagedWidget("stringPatternsFrame", xmFrameWidgetClass,
8372 + form,
8373 + XmNleftAttachment, XmATTACH_POSITION,
8374 + XmNleftPosition, 1,
8375 + XmNrightAttachment, XmATTACH_POSITION,
8376 + XmNrightPosition, 99,
8377 + XmNbottomAttachment, XmATTACH_WIDGET,
8378 + XmNbottomWidget, okBtn,
8379 + XmNbottomOffset, BORDER, NULL);
8380 + stringPatternsForm = XtVaCreateManagedWidget("stringPatternsForm", xmFormWidgetClass,
8381 + stringPatternsFrame, NULL);
8382 + MatchPatternDialog.mpdStringPatternsLbl = XtVaCreateManagedWidget("mpdStringPatternsLbl", xmLabelGadgetClass,
8383 + stringPatternsFrame,
8384 + XmNlabelString, s1=XmStringCreateSimple(STRING_PATTERNS_LBL_TXT),
8385 + XmNmarginHeight, 0,
8386 + XmNchildType, XmFRAME_TITLE_CHILD, NULL);
8387 + XmStringFree(s1);
8389 + n = 0;
8390 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
8391 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8392 + XtSetArg(args[n], XmNleftPosition, 1); n++;
8393 + XtSetArg(args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
8394 + XtSetArg(args[n], XmNrightPosition, LIST_RIGHT-1); n++;
8395 + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
8396 + XtSetArg(args[n], XmNbottomOffset, BORDER); n++;
8397 + MatchPatternDialog.mpdStringPatternsListW =
8398 + CreateManagedList(stringPatternsForm, "stringPatternsList", args,
8399 + n, (void **)MatchPatternDialog.currentStringPatterns.dspElements,
8400 + &MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns,
8401 + MAX_STRING_PATTERNS, 18,
8402 + getStringPatternDisplayedCB, NULL,
8403 + setStringPatternDisplayedCB, NULL,
8404 + freeStringPatternItemCB);
8405 + XtVaSetValues(MatchPatternDialog.mpdStringPatternsLbl, XmNuserData, MatchPatternDialog.mpdStringPatternsListW, NULL);
8407 + MatchPatternDialog.mpdStringPatternTypeLbl = XtVaCreateManagedWidget("mpdStringPatternTypeLbl", xmLabelGadgetClass,
8408 + stringPatternsForm,
8409 + XmNlabelString, s1=XmStringCreateSimple("String Pattern Type:"),
8410 + XmNmarginHeight, 0,
8411 + XmNalignment, XmALIGNMENT_BEGINNING,
8412 + XmNleftAttachment, XmATTACH_POSITION,
8413 + XmNleftPosition, LIST_RIGHT,
8414 + XmNtopAttachment, XmATTACH_FORM, NULL);
8415 + XmStringFree(s1);
8417 + stringPatternTypeBox = XtVaCreateManagedWidget("stringPatternTypeBox", xmRowColumnWidgetClass,
8418 + stringPatternsForm,
8419 + XmNorientation, XmHORIZONTAL,
8420 + XmNpacking, XmPACK_TIGHT,
8421 + XmNradioBehavior, True,
8422 + XmNleftAttachment, XmATTACH_POSITION,
8423 + XmNleftPosition, LIST_RIGHT,
8424 + XmNtopAttachment, XmATTACH_WIDGET,
8425 + XmNtopWidget, MatchPatternDialog.mpdStringPatternTypeLbl, NULL);
8426 + MatchPatternDialog.sptStartW = XtVaCreateManagedWidget("sptStartW",
8427 + xmToggleButtonWidgetClass, stringPatternTypeBox,
8428 + XmNset, True,
8429 + XmNmarginHeight, 0,
8430 + XmNlabelString, s1=XmStringCreateSimple(
8431 + "Start"),
8432 + NULL);
8433 + XmStringFree(s1);
8434 + MatchPatternDialog.sptMiddleW = XtVaCreateManagedWidget("sptMiddleW",
8435 + xmToggleButtonWidgetClass, stringPatternTypeBox,
8436 + XmNmarginHeight, 0,
8437 + XmNlabelString, s1=XmStringCreateSimple(
8438 + "Middle"),
8439 + NULL);
8440 + XmStringFree(s1);
8441 + MatchPatternDialog.sptEndW = XtVaCreateManagedWidget("sptEndW",
8442 + xmToggleButtonWidgetClass, stringPatternTypeBox,
8443 + XmNmarginHeight, 0,
8444 + XmNlabelString, s1=XmStringCreateSimple(
8445 + "End"),
8446 + NULL);
8447 + XmStringFree(s1);
8449 + MatchPatternDialog.mpdWordBoundaryLbl = XtVaCreateManagedWidget("mpdWordBoundaryLbl", xmLabelGadgetClass,
8450 + stringPatternsForm,
8451 + XmNlabelString, s1=XmStringCreateSimple("Word boundary:"),
8452 + XmNmarginHeight, 0,
8453 + XmNalignment, XmALIGNMENT_BEGINNING,
8454 + XmNleftAttachment, XmATTACH_POSITION,
8455 + XmNleftPosition, LIST_RIGHT,
8456 + XmNtopAttachment, XmATTACH_WIDGET,
8457 + XmNtopWidget, stringPatternTypeBox,
8458 + NULL);
8459 + XmStringFree(s1);
8461 + wordBoundaryBox = XtVaCreateManagedWidget("wordBoundaryBox", xmRowColumnWidgetClass,
8462 + stringPatternsForm,
8463 + XmNorientation, XmHORIZONTAL,
8464 + XmNpacking, XmPACK_TIGHT,
8465 + XmNradioBehavior, True,
8466 + XmNleftAttachment, XmATTACH_POSITION,
8467 + XmNleftPosition, LIST_RIGHT,
8468 + XmNtopAttachment, XmATTACH_WIDGET,
8469 + XmNtopWidget, MatchPatternDialog.mpdWordBoundaryLbl, NULL);
8470 + MatchPatternDialog.wbbBothW = XtVaCreateManagedWidget("wbbBothW",
8471 + xmToggleButtonWidgetClass, wordBoundaryBox,
8472 + XmNset, True,
8473 + XmNmarginHeight, 0,
8474 + XmNlabelString, s1=XmStringCreateSimple(
8475 + "Both (pattern is word)"),
8476 + NULL);
8477 + XmStringFree(s1);
8478 + MatchPatternDialog.wbbLeftW = XtVaCreateManagedWidget("wbbLeftW",
8479 + xmToggleButtonWidgetClass, wordBoundaryBox,
8480 + XmNmarginHeight, 0,
8481 + XmNlabelString, s1=XmStringCreateSimple(
8482 + "Left"),
8483 + NULL);
8484 + XmStringFree(s1);
8485 + MatchPatternDialog.wbbRightW = XtVaCreateManagedWidget("wbbRightW",
8486 + xmToggleButtonWidgetClass, wordBoundaryBox,
8487 + XmNmarginHeight, 0,
8488 + XmNlabelString, s1=XmStringCreateSimple(
8489 + "Right"),
8490 + NULL);
8491 + XmStringFree(s1);
8492 + MatchPatternDialog.wbbNoneW = XtVaCreateManagedWidget("wbbNoneW",
8493 + xmToggleButtonWidgetClass, wordBoundaryBox,
8494 + XmNmarginHeight, 0,
8495 + XmNlabelString, s1=XmStringCreateSimple(
8496 + "None"),
8497 + NULL);
8498 + XmStringFree(s1);
8500 + MatchPatternDialog.mpdStringAttributesLbl = XtVaCreateManagedWidget("mpdStringAttributesLbl", xmLabelGadgetClass,
8501 + stringPatternsForm,
8502 + XmNlabelString, s1=XmStringCreateSimple("String Attributes:"),
8503 + XmNmarginHeight, 0,
8504 + XmNalignment, XmALIGNMENT_BEGINNING,
8505 + XmNleftAttachment, XmATTACH_POSITION,
8506 + XmNleftPosition, LIST_RIGHT,
8507 + XmNtopAttachment, XmATTACH_WIDGET,
8508 + XmNtopWidget, wordBoundaryBox, NULL);
8509 + XmStringFree(s1);
8511 + stringAttributesBox = XtVaCreateManagedWidget("stringAttributesBox", xmRowColumnWidgetClass,
8512 + stringPatternsForm,
8513 + XmNorientation, XmHORIZONTAL,
8514 + XmNpacking, XmPACK_TIGHT,
8515 + XmNleftAttachment, XmATTACH_POSITION,
8516 + XmNleftPosition, LIST_RIGHT,
8517 + XmNtopAttachment, XmATTACH_WIDGET,
8518 + XmNtopWidget, MatchPatternDialog.mpdStringAttributesLbl, NULL);
8519 + MatchPatternDialog.sabRegularExpressionW = XtVaCreateManagedWidget("sabRegularExpressionW",
8520 + xmToggleButtonWidgetClass, stringAttributesBox,
8521 + XmNset, False,
8522 + XmNmarginHeight, 0,
8523 + XmNlabelString, s1=XmStringCreateSimple(
8524 + "Regular Expression"),
8525 + NULL);
8526 + XmStringFree(s1);
8527 + XtAddCallback(MatchPatternDialog.sabRegularExpressionW, XmNvalueChangedCallback,
8528 + strPatRegExpressionCB, NULL);
8529 + MatchPatternDialog.sabCaseSensitiveW = XtVaCreateManagedWidget("sabCaseSensitiveW",
8530 + xmToggleButtonWidgetClass, stringAttributesBox,
8531 + XmNset, True,
8532 + XmNmarginHeight, 0,
8533 + XmNlabelString, s1=XmStringCreateSimple(
8534 + "Case Sensitive"),
8535 + NULL);
8536 + XmStringFree(s1);
8538 + MatchPatternDialog.mpdStringPatternLbl = XtVaCreateManagedWidget("mpdStringPatternLbl", xmLabelGadgetClass,
8539 + stringPatternsForm,
8540 + XmNlabelString, s1=XmStringCreateSimple("String Pattern"),
8541 + XmNmnemonic, 'S',
8542 + XmNalignment, XmALIGNMENT_BEGINNING,
8543 + XmNleftAttachment, XmATTACH_POSITION,
8544 + XmNleftPosition, LIST_RIGHT,
8545 + XmNtopAttachment, XmATTACH_WIDGET,
8546 + XmNtopWidget, stringAttributesBox,
8547 + XmNtopOffset, BORDER,
8548 + NULL);
8549 + XmStringFree(s1);
8551 + MatchPatternDialog.mpdStringPatternW = XtVaCreateManagedWidget("mpdStringPatternW", xmTextWidgetClass,
8552 + stringPatternsForm,
8553 + XmNleftAttachment, XmATTACH_POSITION,
8554 + XmNleftPosition, LIST_RIGHT,
8555 + XmNtopAttachment, XmATTACH_WIDGET,
8556 + XmNtopWidget, MatchPatternDialog.mpdStringPatternLbl,
8557 + XmNrightAttachment, XmATTACH_FORM,
8558 + XmNrightOffset, BORDER,
8559 + NULL);
8560 + RemapDeleteKey(MatchPatternDialog.mpdStringPatternW);
8561 + XtVaSetValues(MatchPatternDialog.mpdStringPatternLbl, XmNuserData, MatchPatternDialog.mpdStringPatternW, NULL);
8563 + MatchPatternDialog.mpdSubPatNamesLbl = XtVaCreateManagedWidget("mpdSubPatNamesLbl", xmLabelGadgetClass,
8564 + stringPatternsForm,
8565 + XmNlabelString, s1=XmStringCreateSimple("Sub-Pattern Name"),
8566 + XmNmnemonic, 't',
8567 + XmNalignment, XmALIGNMENT_BEGINNING,
8568 + XmNleftAttachment, XmATTACH_POSITION,
8569 + XmNleftPosition, LIST_RIGHT,
8570 + XmNtopAttachment, XmATTACH_WIDGET,
8571 + XmNtopWidget, MatchPatternDialog.mpdStringPatternW,
8572 + XmNtopOffset, BORDER,
8573 + NULL);
8574 + XmStringFree(s1);
8576 + MatchPatternDialog.mpdSubPatNamesPulldown =
8577 + createSubPatternNameMenu(stringPatternsForm, NULL, False);
8579 + n = 0;
8580 + XtSetArg(args[n], XmNspacing, 0); n++;
8581 + XtSetArg(args[n], XmNmarginWidth, 0); n++;
8582 + XtSetArg(args[n], XmNresizeWidth, True); n++;
8583 + XtSetArg(args[n], XmNresizeHeight, True); n++;
8584 + XtSetArg(args[n], XmNnavigationType, XmTAB_GROUP); n++;
8585 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
8586 + XtSetArg(args[n], XmNtopWidget, MatchPatternDialog.mpdSubPatNamesLbl); n++;
8587 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8588 + XtSetArg(args[n], XmNleftPosition, LIST_RIGHT); n++;
8589 + XtSetArg(args[n], XmNsubMenuId, MatchPatternDialog.mpdSubPatNamesPulldown); n++;
8590 + MatchPatternDialog.mpdSubPatNamesOptMenu =
8591 + XmCreateOptionMenu(stringPatternsForm, "subPatNamesOptMenu", args, n);
8592 + XtManageChild(MatchPatternDialog.mpdSubPatNamesOptMenu);
8594 + XtVaSetValues(
8595 + MatchPatternDialog.mpdSubPatNamesLbl,
8596 + XmNuserData, XtParent(MatchPatternDialog.mpdSubPatNamesOptMenu),
8597 + NULL);
8599 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesLbl, False);
8600 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesOptMenu, False);
8602 + matchPatternsFrame = XtVaCreateManagedWidget("matchPatternsFrame", xmFrameWidgetClass,
8603 + form,
8604 + XmNleftAttachment, XmATTACH_POSITION,
8605 + XmNleftPosition, 1,
8606 + XmNtopAttachment, XmATTACH_WIDGET,
8607 + XmNtopWidget, lmForm,
8608 + XmNrightAttachment, XmATTACH_POSITION,
8609 + XmNrightPosition, 99,
8610 + XmNbottomAttachment, XmATTACH_WIDGET,
8611 + XmNbottomWidget, stringPatternsFrame,
8612 + XmNbottomOffset, BORDER, NULL);
8613 + matchPatternsForm = XtVaCreateManagedWidget("matchPatternsForm", xmFormWidgetClass,
8614 + matchPatternsFrame, NULL);
8615 + matchPatternsLbl = XtVaCreateManagedWidget("matchPatternsLbl", xmLabelGadgetClass,
8616 + matchPatternsFrame,
8617 + XmNlabelString, s1=XmStringCreateSimple("Matching Patterns"),
8618 + XmNmnemonic, 'P',
8619 + XmNmarginHeight, 0,
8620 + XmNchildType, XmFRAME_TITLE_CHILD, NULL);
8621 + XmStringFree(s1);
8623 + matchPatternTypeLbl = XtVaCreateManagedWidget("matchPatternTypeLbl", xmLabelGadgetClass,
8624 + matchPatternsForm,
8625 + XmNlabelString, s1=XmStringCreateSimple("Matching Pattern Type:"),
8626 + XmNmarginHeight, 0,
8627 + XmNalignment, XmALIGNMENT_BEGINNING,
8628 + XmNleftAttachment, XmATTACH_POSITION,
8629 + XmNleftPosition, LIST_RIGHT,
8630 + XmNtopAttachment, XmATTACH_FORM, NULL);
8631 + XmStringFree(s1);
8633 + matchPatternTypeBox = XtVaCreateManagedWidget("matchPatternTypeBox", xmRowColumnWidgetClass,
8634 + matchPatternsForm,
8635 + XmNpacking, XmPACK_COLUMN,
8636 + XmNradioBehavior, True,
8637 + XmNleftAttachment, XmATTACH_POSITION,
8638 + XmNleftPosition, LIST_RIGHT,
8639 + XmNtopAttachment, XmATTACH_WIDGET,
8640 + XmNtopWidget, matchPatternTypeLbl, NULL);
8641 + MatchPatternDialog.mptbIndividualW = XtVaCreateManagedWidget("mptbIndividualW",
8642 + xmToggleButtonWidgetClass, matchPatternTypeBox,
8643 + XmNset, True,
8644 + XmNmarginHeight, 0,
8645 + XmNlabelString, s1=XmStringCreateSimple(
8646 + "Individual"),
8647 + XmNmnemonic, 'I', NULL);
8648 + XmStringFree(s1);
8649 + XtAddCallback(MatchPatternDialog.mptbIndividualW, XmNvalueChangedCallback,
8650 + matchPatTypeCB, NULL);
8651 + MatchPatternDialog.mptbSubPatternW = XtVaCreateManagedWidget("mptbSubPatternW",
8652 + xmToggleButtonWidgetClass, matchPatternTypeBox,
8653 + XmNmarginHeight, 0,
8654 + XmNlabelString, s1=XmStringCreateSimple(
8655 + "Sub-pattern (belongs to context group)"),
8656 + XmNmnemonic, 'u', NULL);
8657 + XmStringFree(s1);
8658 + XtAddCallback(MatchPatternDialog.mptbSubPatternW, XmNvalueChangedCallback,
8659 + matchPatTypeCB, NULL);
8660 + MatchPatternDialog.mptbContextGroupW = XtVaCreateManagedWidget("mptbContextGroupW",
8661 + xmToggleButtonWidgetClass, matchPatternTypeBox,
8662 + XmNmarginHeight, 0,
8663 + XmNlabelString, s1=XmStringCreateSimple(
8664 + "Context group"),
8665 + XmNmnemonic, 'g', NULL);
8666 + XmStringFree(s1);
8667 + XtAddCallback(MatchPatternDialog.mptbContextGroupW, XmNvalueChangedCallback,
8668 + matchPatTypeCB, NULL);
8670 + MatchPatternDialog.mpdGlobalAttributesLbl = XtVaCreateManagedWidget("mpdGlobalAttributesLbl",
8671 + xmLabelGadgetClass, matchPatternsForm,
8672 + XmNlabelString, s1=XmStringCreateSimple("Global Attributes:"),
8673 + XmNmarginHeight, 0,
8674 + XmNalignment, XmALIGNMENT_BEGINNING,
8675 + XmNleftAttachment, XmATTACH_POSITION,
8676 + XmNleftPosition, LIST_RIGHT,
8677 + XmNtopAttachment, XmATTACH_WIDGET,
8678 + XmNtopOffset, BORDER,
8679 + XmNtopWidget, matchPatternTypeBox, NULL);
8680 + XmStringFree(s1);
8682 + globalAttributesBox = XtVaCreateManagedWidget("globalAttributesBox", xmRowColumnWidgetClass,
8683 + matchPatternsForm,
8684 + XmNpacking, XmPACK_COLUMN,
8685 + XmNleftAttachment, XmATTACH_POSITION,
8686 + XmNleftPosition, LIST_RIGHT,
8687 + XmNtopAttachment, XmATTACH_WIDGET,
8688 + XmNtopWidget, MatchPatternDialog.mpdGlobalAttributesLbl, NULL);
8689 + MatchPatternDialog.gabSkipBtwStartEndW = XtVaCreateManagedWidget("gabSkipBtwStartEndW",
8690 + xmToggleButtonWidgetClass, globalAttributesBox,
8691 + XmNmarginHeight, 0,
8692 + XmNlabelString, s1=XmStringCreateSimple(
8693 + "Skip content between start / end pattern"),
8694 + XmNmnemonic, 'c', NULL);
8695 + XmStringFree(s1);
8696 + MatchPatternDialog.gabFlashW = XtVaCreateManagedWidget("gabFlashW",
8697 + xmToggleButtonWidgetClass, globalAttributesBox,
8698 + XmNset, True,
8699 + XmNmarginHeight, 0,
8700 + XmNlabelString, s1=XmStringCreateSimple(
8701 + "Flash matching pattern"),
8702 + XmNmnemonic, 'l', NULL);
8703 + XmStringFree(s1);
8704 + MatchPatternDialog.gabSyntaxBasedW = XtVaCreateManagedWidget("gabSyntaxBasedW",
8705 + xmToggleButtonWidgetClass, globalAttributesBox,
8706 + XmNset, True,
8707 + XmNmarginHeight, 0,
8708 + XmNlabelString, s1=XmStringCreateSimple(
8709 + "Syntax based"),
8710 + XmNmnemonic, 'b', NULL);
8711 + XmStringFree(s1);
8713 + MatchPatternDialog.mpdMatchPatternNameLbl = XtVaCreateManagedWidget("mpdMatchPatternNameLbl", xmLabelGadgetClass,
8714 + matchPatternsForm,
8715 + XmNlabelString, s1=XmStringCreateSimple(MATCH_PAT_NAME_LBL_TXT),
8716 + XmNmnemonic, 'N',
8717 + XmNalignment, XmALIGNMENT_BEGINNING,
8718 + XmNleftAttachment, XmATTACH_POSITION,
8719 + XmNleftPosition, LIST_RIGHT,
8720 + XmNtopAttachment, XmATTACH_WIDGET,
8721 + XmNtopWidget, globalAttributesBox,
8722 + XmNtopOffset, BORDER, NULL);
8723 + XmStringFree(s1);
8725 + MatchPatternDialog.mpdMatchPatternNameW = XtVaCreateManagedWidget("mpdMatchPatternNameW", xmTextWidgetClass,
8726 + matchPatternsForm,
8727 + XmNleftAttachment, XmATTACH_POSITION,
8728 + XmNleftPosition, LIST_RIGHT,
8729 + XmNtopAttachment, XmATTACH_WIDGET,
8730 + XmNtopWidget, MatchPatternDialog.mpdMatchPatternNameLbl,
8731 + XmNrightAttachment, XmATTACH_FORM,
8732 + XmNrightOffset, BORDER,
8733 + XmNbottomAttachment, XmATTACH_FORM,
8734 + XmNbottomOffset, BORDER,
8735 + NULL);
8736 + RemapDeleteKey(MatchPatternDialog.mpdMatchPatternNameW);
8737 + XtVaSetValues(MatchPatternDialog.mpdMatchPatternNameLbl, XmNuserData, MatchPatternDialog.mpdMatchPatternNameW, NULL);
8739 + n = 0;
8740 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
8741 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8742 + XtSetArg(args[n], XmNleftPosition, 1); n++;
8743 + XtSetArg(args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
8744 + XtSetArg(args[n], XmNrightPosition, LIST_RIGHT-1); n++;
8745 + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
8747 + XtSetArg(args[n], XmNbottomOffset, BORDER); n++;
8748 + MatchPatternDialog.mpdMatchPatternNamesListW =
8749 + CreateManagedList(
8750 + matchPatternsForm, "mpdMatchPatternNamesListW",
8751 + args, n,
8752 + (void **)MatchPatternDialog.mpdTable.dmpiSequence, &MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements,
8753 + MAX_NBR_MATCH_PATTERNS, 18,
8754 + getMatchPatternDisplayedCB, NULL,
8755 + setMatchPatternDisplayedCB, NULL,
8756 + freeMatchPatternItemCB);
8757 + AddDeleteConfirmCB(MatchPatternDialog.mpdMatchPatternNamesListW, deleteMatchPatternItemCB, NULL);
8759 + XtVaSetValues(matchPatternsLbl, XmNuserData, MatchPatternDialog.mpdMatchPatternNamesListW, NULL);
8761 + /*
8762 + * set initial default button
8763 + */
8764 + XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
8765 + XtVaSetValues(form, XmNcancelButton, closeBtn, NULL);
8767 + /*
8768 + * handle mnemonic selection of buttons and focus to dialog
8769 + */
8770 + AddDialogMnemonicHandler(form, False);
8772 + /*
8773 + * fill in the dialog information for the selected language mode
8774 + */
8775 + SetLangModeMenu(MatchPatternDialog.mpdLmOptMenu, MatchPatternDialog.mpdLangModeName);
8777 + /*
8778 + * realize all of the widgets in the new dialog
8779 + */
8780 + RealizeWithoutForcingPosition(MatchPatternDialog.mpdShell);
8784 +** Modify match pattern dialog depending on showing a string pattern
8785 +** or a context group.
8787 +static void setDialogType(int dialogShowsStringPattern)
8789 + char *matchPatternNameText;
8790 + char *strPatCxtGrpListText;
8791 + XmString s1;
8792 + int regularExpression =
8793 + XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
8795 + /*
8796 + * check, if dialog mode needs to be switched
8797 + */
8798 + if (MatchPatternDialog.mpdStringPatternIsDisplayed == dialogShowsStringPattern)
8800 + return;
8803 + if (dialogShowsStringPattern)
8805 + matchPatternNameText = MATCH_PAT_NAME_LBL_TXT;
8806 + strPatCxtGrpListText = STRING_PATTERNS_LBL_TXT;
8808 + else
8810 + matchPatternNameText = "Context Group Name";
8811 + strPatCxtGrpListText = "Related Sub-Patterns";
8814 + XtSetSensitive(MatchPatternDialog.mpdGlobalAttributesLbl, dialogShowsStringPattern);
8815 + XtSetSensitive(MatchPatternDialog.gabSkipBtwStartEndW, dialogShowsStringPattern);
8816 + XtSetSensitive(MatchPatternDialog.gabFlashW, dialogShowsStringPattern);
8817 + XtSetSensitive(MatchPatternDialog.gabSyntaxBasedW, dialogShowsStringPattern);
8819 + XtSetSensitive(MatchPatternDialog.mpdStringPatternTypeLbl, dialogShowsStringPattern);
8820 + XtSetSensitive(MatchPatternDialog.sptStartW, dialogShowsStringPattern);
8821 + XtSetSensitive(MatchPatternDialog.sptMiddleW, dialogShowsStringPattern);
8822 + XtSetSensitive(MatchPatternDialog.sptEndW, dialogShowsStringPattern);
8824 + setSensitiveWordBoundaryBox( dialogShowsStringPattern && !regularExpression );
8826 + XtSetSensitive(MatchPatternDialog.mpdStringAttributesLbl, dialogShowsStringPattern);
8827 + XtSetSensitive(MatchPatternDialog.sabCaseSensitiveW, dialogShowsStringPattern);
8828 + XtSetSensitive(MatchPatternDialog.sabRegularExpressionW, dialogShowsStringPattern);
8830 + XtSetSensitive(MatchPatternDialog.mpdStringPatternLbl, dialogShowsStringPattern);
8831 + XtSetSensitive(MatchPatternDialog.mpdStringPatternW, dialogShowsStringPattern);
8833 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesLbl, !dialogShowsStringPattern);
8834 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesOptMenu, !dialogShowsStringPattern);
8836 + XtVaSetValues(
8837 + MatchPatternDialog.mpdMatchPatternNameLbl,
8838 + XmNlabelString, s1=XmStringCreateSimple(matchPatternNameText),
8839 + NULL);
8840 + XmStringFree(s1);
8842 + XtVaSetValues(
8843 + MatchPatternDialog.mpdStringPatternsLbl,
8844 + XmNlabelString, s1=XmStringCreateSimple(strPatCxtGrpListText),
8845 + NULL);
8846 + XmStringFree(s1);
8848 + MatchPatternDialog.mpdStringPatternIsDisplayed = dialogShowsStringPattern;
8851 +static void setSensitiveWordBoundaryBox(int enable)
8853 + XtSetSensitive(MatchPatternDialog.mpdWordBoundaryLbl, enable);
8854 + XtSetSensitive(MatchPatternDialog.wbbBothW , enable);
8855 + XtSetSensitive(MatchPatternDialog.wbbLeftW , enable);
8856 + XtSetSensitive(MatchPatternDialog.wbbRightW, enable);
8857 + XtSetSensitive(MatchPatternDialog.wbbNoneW , enable);
8860 +static void matchPatternLangModeCB(Widget w, XtPointer clientData, XtPointer callData)
8862 + char *modeName;
8863 + StringMatchTable *oldTable, *newTable;
8864 + StringMatchTable emptyTable = {"", NULL, NULL, NULL, NULL, 0, NULL, 0, NULL};
8865 + StringMatchTable *table;
8866 + DMPTranslationResult translResult;
8867 + int resp;
8869 + /*
8870 + * Get the newly selected mode name. If it's the same, do nothing
8871 + */
8872 + XtVaGetValues(w, XmNuserData, &modeName, NULL);
8873 + if (!strcmp(modeName, MatchPatternDialog.mpdLangModeName))
8874 + return;
8876 + /*
8877 + * Look up the original version of the patterns being edited
8878 + */
8879 + oldTable = (StringMatchTable *)FindStringMatchTable(MatchPatternDialog.mpdLangModeName);
8880 + if (oldTable == NULL)
8881 + oldTable = &emptyTable;
8883 + /*
8884 + * Get the current information displayed by the dialog. If it's bad,
8885 + * give the user the chance to throw it out or go back and fix it. If
8886 + * it has changed, give the user the chance to apply discard or cancel.
8887 + */
8888 + newTable = getDialogStringMatchTable(&translResult);
8890 + if (translResult == DMPTR_EMPTY)
8892 + newTable = &emptyTable;
8895 + if (newTable == NULL)
8897 + if (DialogF(
8898 + DF_WARN, MatchPatternDialog.mpdShell, 2,
8899 + "Incomplete Matching Patterns for Language Mode",
8900 + "Discard incomplete entry for language mode '%s'?",
8901 + "Keep", "Discard",
8902 + MatchPatternDialog.mpdLangModeName) == 1)
8904 + SetLangModeMenu(
8905 + MatchPatternDialog.mpdLmOptMenu,
8906 + MatchPatternDialog.mpdLangModeName);
8908 + return;
8911 + else if (stringMatchTableDiffer(oldTable, newTable))
8913 + if (newTable == &emptyTable)
8914 + newTable = NULL;
8916 + resp =
8917 + DialogF(
8918 + DF_WARN, MatchPatternDialog.mpdShell, 3,
8919 + "Change Language Mode",
8920 + "Apply changes for language mode '%s'?",
8921 + "Apply Changes", "Discard Changes", "Cancel",
8922 + MatchPatternDialog.mpdLangModeName);
8924 + if (resp == 3)
8926 + SetLangModeMenu(
8927 + MatchPatternDialog.mpdLmOptMenu,
8928 + MatchPatternDialog.mpdLangModeName);
8930 + freeStringMatchTable( newTable );
8932 + return;
8934 + else if (resp == 1)
8936 + updateStringMatchTable( newTable );
8938 + /*
8939 + * Don't free the new table due to it's stored in MatchTables now
8940 + */
8941 + newTable = NULL;
8945 + if (newTable != NULL && newTable != &emptyTable)
8946 + freeStringMatchTable(newTable);
8948 + /*
8949 + * Free the old dialog information
8950 + */
8951 + freeVariableDialogData(DISCARD_LANGUAGE_MODE);
8953 + /*
8954 + * Fill the dialog with the new language mode information
8955 + */
8956 + MatchPatternDialog.mpdLangModeName = XtNewString(modeName);
8958 + /*
8959 + * Find the associated matching pattern table to edit
8960 + */
8961 + table = (StringMatchTable *)FindStringMatchTable(MatchPatternDialog.mpdLangModeName);
8963 + /*
8964 + * Copy the list of patterns to one that the user can freely edit
8965 + */
8966 + copyStringMatchTableForDialog( table, &MatchPatternDialog.mpdTable );
8968 + /*
8969 + * Update dialog fields
8970 + */
8971 + ChangeManagedListData(MatchPatternDialog.mpdMatchPatternNamesListW);
8972 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
8975 +static void pmLanguageModeDialogCB(Widget w, XtPointer clientData, XtPointer callData)
8977 + EditLanguageModes();
8981 +** If a matching pattern dialog is up, ask to have the option menu for
8982 +** chosing language mode updated (via a call to CreateLanguageModeMenu)
8984 +void UpdateLanguageModeMenuMatchPattern(void)
8986 + Widget oldMenu;
8988 + if (MatchPatternDialog.mpdShell == NULL)
8989 + return;
8991 + oldMenu = MatchPatternDialog.mpdLmPulldown;
8992 + /*
8993 + * don't include "PLAIN" (4th parameter) in LM menu
8994 + */
8995 + MatchPatternDialog.mpdLmPulldown = CreateLanguageModeMenu(
8996 + XtParent(XtParent(oldMenu)), matchPatternLangModeCB, NULL, False);
8997 + XtVaSetValues(XmOptionButtonGadget(MatchPatternDialog.mpdLmOptMenu),
8998 + XmNsubMenuId, MatchPatternDialog.mpdLmPulldown, NULL);
8999 + SetLangModeMenu(MatchPatternDialog.mpdLmOptMenu, MatchPatternDialog.mpdLangModeName);
9001 + XtDestroyWidget(oldMenu);
9004 +static void *getMatchPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
9005 + void *cbArg)
9007 + DialogMatchPatternSequenceElement *newSeq;
9009 + /*
9010 + * If the dialog is currently displaying the "new" entry and the
9011 + * fields are empty, that's just fine
9012 + */
9013 + if (oldItem == NULL && matchPatternDialogEmpty())
9014 + return NULL;
9016 + /*
9017 + * Read string patterns / sub-pattern names area first
9018 + */
9019 + UpdateManagedList(MatchPatternDialog.mpdStringPatternsListW, True);
9021 + /*
9022 + * If there are no problems reading the data, just return it
9023 + */
9024 + newSeq = readMatchPatternFields(True);
9025 + if (newSeq != NULL)
9026 + return (void *)newSeq;
9028 + /*
9029 + * If there are problems, and the user didn't ask for the fields to be
9030 + * read, give more warning
9031 + */
9032 + if (!explicitRequest)
9034 + if (DialogF(
9035 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9036 + "Discard Matching Pattern Entry",
9037 + "Discard incomplete entry\nfor current matching pattern?",
9038 + "Keep", "Discard") == 2)
9040 + return oldItem == NULL
9041 + ? NULL
9042 + : (void *)copyDialogSequenceElement(
9043 + (DialogMatchPatternSequenceElement *)oldItem);
9047 + /*
9048 + * read data again without "silent" mode to display warning
9049 + */
9050 + newSeq = readMatchPatternFields(False);
9051 + *abort = True;
9053 + return NULL;
9056 +static void setMatchPatternDisplayedCB(void *item, void *cbArg)
9058 + DialogMatchPatternSequenceElement *seqElement;
9059 + DialogMatchPatternTableElement *element;
9060 + DialogMatchPatternGroupElement *group;
9061 + int isGroup;
9063 + seqElement = (DialogMatchPatternSequenceElement *)item;
9065 + MatchPatternDialog.currentDmptSeqElement = seqElement;
9067 + if (item == NULL)
9069 + MatchPatternDialog.currentDmptElement = NULL;
9070 + MatchPatternDialog.currentDmptGroup = NULL;
9072 + XmTextSetString(MatchPatternDialog.mpdMatchPatternNameW, "");
9073 + RadioButtonChangeState(MatchPatternDialog.mptbIndividualW, True, True);
9074 + RadioButtonChangeState(MatchPatternDialog.gabSkipBtwStartEndW, False, False);
9075 + RadioButtonChangeState(MatchPatternDialog.gabFlashW, True, False);
9076 + RadioButtonChangeState(MatchPatternDialog.gabSyntaxBasedW, True, False);
9078 + freeDialogStringPatterns(
9079 + &MatchPatternDialog.currentStringPatterns);
9081 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9083 + setDialogType( STRING_PATTERN_DIALOG );
9085 + else
9087 + isGroup = (seqElement->dmpseType == MPT_GROUP);
9089 + XmTextSetString(MatchPatternDialog.mpdMatchPatternNameW, seqElement->dmpseName);
9091 + if (seqElement->dmpseType == MPT_INDIVIDUAL)
9092 + RadioButtonChangeState(MatchPatternDialog.mptbIndividualW, True, True);
9093 + else if (seqElement->dmpseType == MPT_SUB)
9094 + RadioButtonChangeState(MatchPatternDialog.mptbSubPatternW, True, True);
9095 + else
9096 + RadioButtonChangeState(MatchPatternDialog.mptbContextGroupW, True, True);
9098 + freeDialogStringPatterns(
9099 + &MatchPatternDialog.currentStringPatterns);
9101 + if (isGroup)
9103 + group = (DialogMatchPatternGroupElement *)seqElement->dmpsePtr;
9104 + MatchPatternDialog.currentDmptElement = NULL;
9105 + MatchPatternDialog.currentDmptGroup = group;
9107 + copyDialogPatternNamesFromGroup(
9108 + group,
9109 + &MatchPatternDialog.currentStringPatterns);
9111 + else
9113 + element = (DialogMatchPatternTableElement *)seqElement->dmpsePtr;
9114 + MatchPatternDialog.currentDmptElement = element;
9115 + MatchPatternDialog.currentDmptGroup = NULL;
9117 + RadioButtonChangeState(
9118 + MatchPatternDialog.gabSkipBtwStartEndW,
9119 + element->dmpteSkipBtwnStartEnd,
9120 + False);
9121 + RadioButtonChangeState(
9122 + MatchPatternDialog.gabFlashW,
9123 + element->dmpteFlash,
9124 + False);
9125 + RadioButtonChangeState(
9126 + MatchPatternDialog.gabSyntaxBasedW,
9127 + !element->dmpteIgnoreHighLightInfo,
9128 + False);
9130 + copyDialogStringPatternsFromTable(
9131 + element,
9132 + &MatchPatternDialog.currentStringPatterns);
9135 + setDialogType( !isGroup );
9137 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9141 +static void freeMatchPatternItemCB(void *item)
9143 + freeDialogSequenceElement((DialogMatchPatternSequenceElement *)item);
9147 +** Use "delete confirm" to delete matching pattern name from
9148 +** any group of this matching pattern set, in case of sub-pattern.
9149 +** Always confirm the delete.
9151 +static int deleteMatchPatternItemCB(int itemIndex, void *cbArg)
9153 + DialogMatchPatternSequenceElement *seqElement;
9155 + seqElement = MatchPatternDialog.mpdTable.dmpiSequence[itemIndex];
9157 + if (seqElement->dmpseType == MPT_SUB)
9159 + removeMatchPatternFromAllGroups( seqElement->dmpseName );
9162 + return True;
9165 +static void *getStringPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
9166 + void *cbArg)
9168 + DialogStringPatternElement *newPat;
9169 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
9171 + /*
9172 + * If the string pattern frame is currently displaying the "new" entry and the
9173 + * fields are empty, that's just fine
9174 + */
9175 + if (oldItem == NULL && stringPatternFieldsEmpty(isRelatedToGroup))
9176 + return NULL;
9178 + /*
9179 + * If there are no problems reading the data, just return it
9180 + */
9181 + newPat = readStringPatternFrameFields(True);
9182 + if (newPat != NULL)
9183 + return (void *)newPat;
9185 + /*
9186 + * If there are problems, and the user didn't ask for the fields to be
9187 + * read, give more warning
9188 + */
9190 + if (!explicitRequest)
9192 + if (DialogF(
9193 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9194 + "Discard String Pattern Entry",
9195 + "Discard incomplete entry\nfor current string pattern?",
9196 + "Keep", "Discard") == 2)
9198 + return oldItem == NULL
9199 + ? NULL
9200 + : (void *)copyDialogStringPatternElement(
9201 + (DialogStringPatternElement *)oldItem);
9205 + /*
9206 + * read data again without "silent" mode to display warning
9207 + */
9208 + newPat = readStringPatternFrameFields(False);
9209 + *abort = True;
9211 + return NULL;
9214 +static void setStringPatternDisplayedCB(void *item, void *cbArg)
9216 + DialogStringPatternElement *element = (DialogStringPatternElement *)item;
9217 + PatternElementKind peKind;
9218 + PatternWordBoundary wordBoundary;
9219 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
9221 + if (item == NULL)
9223 + if (isRelatedToGroup)
9225 + updateSubPatternNameMenu(NULL, False);
9227 + else
9229 + XmTextSetString(MatchPatternDialog.mpdStringPatternW, "");
9231 + setSensitiveWordBoundaryBox( True );
9233 + RadioButtonChangeState(MatchPatternDialog.wbbBothW, True, True);
9235 + /*
9236 + * type of "new" string pattern:
9237 + * preset "start", if no string pattern exists at all;
9238 + * else select "end"
9239 + */
9240 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0)
9241 + RadioButtonChangeState(MatchPatternDialog.sptStartW, True, True);
9242 + else
9243 + RadioButtonChangeState(MatchPatternDialog.sptEndW, True, True);
9245 + RadioButtonChangeState(MatchPatternDialog.sabCaseSensitiveW, True, False);
9246 + RadioButtonChangeState(MatchPatternDialog.sabRegularExpressionW, False, False);
9249 + else
9251 + if (isRelatedToGroup)
9253 + updateSubPatternNameMenu(element->dspeText, False);
9255 + else
9257 + XmTextSetString(MatchPatternDialog.mpdStringPatternW, element->dspeText);
9259 + peKind = element->dspeKind;
9260 + wordBoundary = element->dspeWordBoundary;
9262 + if (peKind == PEK_START)
9263 + RadioButtonChangeState(MatchPatternDialog.sptStartW, True, True);
9264 + else if (peKind == PEK_MIDDLE)
9265 + RadioButtonChangeState(MatchPatternDialog.sptMiddleW, True, True);
9266 + else
9267 + RadioButtonChangeState(MatchPatternDialog.sptEndW, True, True);
9269 + if (wordBoundary == PWB_BOTH)
9270 + RadioButtonChangeState(MatchPatternDialog.wbbBothW, True, True);
9271 + else if (wordBoundary == PWB_LEFT)
9272 + RadioButtonChangeState(MatchPatternDialog.wbbLeftW, True, True);
9273 + else if (wordBoundary == PWB_RIGHT)
9274 + RadioButtonChangeState(MatchPatternDialog.wbbRightW, True, True);
9275 + else
9276 + RadioButtonChangeState(MatchPatternDialog.wbbNoneW, True, True);
9278 + RadioButtonChangeState(
9279 + MatchPatternDialog.sabCaseSensitiveW,
9280 + !element->dspeCaseInsensitive,
9281 + False);
9283 + RadioButtonChangeState(
9284 + MatchPatternDialog.sabRegularExpressionW,
9285 + element->dspeRegularExpression,
9286 + False);
9288 + setSensitiveWordBoundaryBox( !element->dspeRegularExpression );
9293 +static void freeStringPatternItemCB(void *item)
9295 + DialogStringPatternElement *patElement;
9297 + patElement = (DialogStringPatternElement *)item;
9299 + freeDialogStringPatternElement(patElement);
9302 +static void destroyCB(Widget w, XtPointer clientData, XtPointer callData)
9304 + freeVariableDialogData(DISCARD_LANGUAGE_MODE);
9306 + MatchPatternDialog.mpdShell = NULL;
9309 +static void okCB(Widget w, XtPointer clientData, XtPointer callData)
9311 + /*
9312 + * change the matching pattern
9313 + */
9314 + if (!getAndUpdateStringMatchTable())
9315 + return;
9317 + /*
9318 + * pop down and destroy the dialog
9319 + */
9320 + XtDestroyWidget(MatchPatternDialog.mpdShell);
9323 +static void applyCB(Widget w, XtPointer clientData, XtPointer callData)
9325 + /*
9326 + * change the matching pattern
9327 + */
9328 + getAndUpdateStringMatchTable();
9331 +static void checkCB(Widget w, XtPointer clientData, XtPointer callData)
9333 + StringMatchTable *newTable;
9334 + DMPTranslationResult translResult;
9336 + /*
9337 + * Get the current information displayed by the dialog.
9338 + * If a new table is available, then the test is passed successfully.
9339 + */
9340 + newTable = getDialogStringMatchTable(&translResult);
9342 + if (newTable != NULL)
9344 + DialogF(
9345 + DF_INF, MatchPatternDialog.mpdShell, 1,
9346 + "Matching Patterns Checked",
9347 + "Matching Patterns checked without error",
9348 + "OK");
9350 + freeStringMatchTable(newTable);
9354 +static void restoreCB(Widget w, XtPointer clientData, XtPointer callData)
9356 + StringMatchTable *defaultTable;
9358 + defaultTable = readDefaultStringMatchTable(MatchPatternDialog.mpdLangModeName);
9360 + if (defaultTable == NULL)
9362 + DialogF(
9363 + DF_WARN, MatchPatternDialog.mpdShell, 1,
9364 + "No Default Matching Pattern",
9365 + "There is no default matching pattern set\nfor language mode %s",
9366 + "OK",
9367 + MatchPatternDialog.mpdLangModeName);
9369 + return;
9372 + if (DialogF(
9373 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9374 + "Discard Changes",
9375 + "Are you sure you want to discard\n"
9376 + "all changes to matching patterns\n"
9377 + "for language mode %s?",
9378 + "Discard", "Cancel",
9379 + MatchPatternDialog.mpdLangModeName) == 2)
9381 + freeStringMatchTable(defaultTable);
9383 + return;
9386 + /*
9387 + * if a stored version of the matching pattern set exists, replace it.
9388 + * if it doesn't, add a new one.
9389 + */
9390 + updateStringMatchTable( defaultTable );
9392 + /*
9393 + * free the old dialog information
9394 + */
9395 + freeVariableDialogData(KEEP_LANGUAGE_MODE);
9397 + /*
9398 + * update the dialog
9399 + */
9400 + copyStringMatchTableForDialog( defaultTable, &MatchPatternDialog.mpdTable );
9402 + ChangeManagedListData(MatchPatternDialog.mpdMatchPatternNamesListW);
9403 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9406 +static void deleteCB(Widget w, XtPointer clientData, XtPointer callData)
9408 + if (DialogF(
9409 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9410 + "Delete Matching Patterns",
9411 + "Are you sure you want to delete\n"
9412 + "all matching patterns for\n"
9413 + "language mode %s?",
9414 + "Yes, Delete", "Cancel",
9415 + MatchPatternDialog.mpdLangModeName) == 2)
9417 + return;
9420 + /*
9421 + * if a stored version of the matching pattern exists, delete it from the list
9422 + */
9423 + DeleteStringMatchTable(MatchPatternDialog.mpdLangModeName);
9425 + /*
9426 + * free the old dialog information
9427 + */
9428 + freeVariableDialogData(KEEP_LANGUAGE_MODE);
9430 + /*
9431 + * clear out the dialog
9432 + */
9433 + ChangeManagedListData(MatchPatternDialog.mpdMatchPatternNamesListW);
9434 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9437 +static void closeCB(Widget w, XtPointer clientData, XtPointer callData)
9439 + /*
9440 + * pop down and destroy the dialog
9441 + */
9442 + XtDestroyWidget(MatchPatternDialog.mpdShell);
9445 +static void helpCB(Widget w, XtPointer clientData, XtPointer callData)
9448 + Help(HELP_MATCHING_PATTERNS);
9452 +static void strPatRegExpressionCB(Widget w, XtPointer clientData, XtPointer callData)
9454 + int regularExpression =
9455 + XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
9457 + setSensitiveWordBoundaryBox( !regularExpression );
9459 + if (regularExpression)
9460 + RadioButtonChangeState(MatchPatternDialog.sabCaseSensitiveW, True, False);
9463 +static void matchPatTypeCB(Widget w, XtPointer clientData, XtPointer callData)
9465 + if (MatchPatternDialog.currentDmptSeqElement != NULL)
9467 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW))
9469 + if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_SUB)
9471 + changeExistingSubPattern("Change to Context Group");
9474 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW) &&
9475 + MatchPatternDialog.currentDmptSeqElement->dmpseType != MPT_GROUP)
9477 + changeStringPatternToGroup();
9480 + else if (XmToggleButtonGetState(MatchPatternDialog.mptbIndividualW))
9482 + if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_SUB)
9484 + changeExistingSubPattern("Change to Individual Matching Pattern");
9486 + else if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_GROUP)
9488 + changeGroupToStringPattern("Change to Individual Matching Pattern");
9491 + else if (XmToggleButtonGetState(MatchPatternDialog.mptbSubPatternW))
9493 + if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_GROUP)
9495 + changeGroupToStringPattern("Change to Sub-Matching Pattern");
9500 + /*
9501 + * if context group button is (still) selected, then update labels etc.
9502 + */
9503 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW))
9505 + setDialogType(CONTEXT_GROUP_DIALOG);
9507 + else
9509 + setDialogType(STRING_PATTERN_DIALOG);
9512 + /*
9513 + * if a "new" entry is selected in matching patterns names list, then provide a
9514 + * list of all sub-pattern names
9515 + */
9516 + if (MatchPatternDialog.currentDmptSeqElement == NULL)
9518 + updateSubPatternNameMenu(NULL, True);
9522 +static void changeExistingSubPattern(
9523 + char *warnTitle)
9525 + DialogMatchPatternGroupElement *group;
9526 + int resp;
9528 + group =
9529 + getDialogGroupUsingMatchPattern(
9530 + MatchPatternDialog.currentDmptElement->dmpteName );
9532 + while ( group != NULL )
9534 + resp =
9535 + DialogF(
9536 + DF_WARN, MatchPatternDialog.mpdShell, 3,
9537 + warnTitle,
9538 + "Sub-pattern '%s' is used at least\n"
9539 + "by context group '%s'.\n\n"
9540 + "Remove this sub-pattern from this resp. all context group(s) ?",
9541 + "No, Keep", "Yes, Remove", "Yes, Remove All",
9542 + MatchPatternDialog.currentDmptElement->dmpteName,
9543 + group->dmpgeName);
9545 + if (resp == 1)
9547 + RadioButtonChangeState(MatchPatternDialog.mptbSubPatternW, True, True);
9549 + return;
9551 + else if (resp == 2)
9553 + removeMatchPatternFromGroup(
9554 + MatchPatternDialog.currentDmptElement->dmpteName,
9555 + group);
9557 + /*
9558 + * look for evtl. next context group holding this matching pattern
9559 + */
9560 + group =
9561 + getDialogGroupUsingMatchPattern(
9562 + MatchPatternDialog.currentDmptElement->dmpteName );
9564 + else
9566 + /*
9567 + * remove this matching pattern form all context groups
9568 + */
9569 + removeMatchPatternFromAllGroups(
9570 + MatchPatternDialog.currentDmptElement->dmpteName);
9572 + return;
9577 +static void changeStringPatternToGroup(void)
9579 + int resp;
9580 + int isSubPattern;
9582 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns != 0)
9584 + resp =
9585 + DialogF(
9586 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9587 + "Change to Context Group",
9588 + "All string patterns of '%s'\n"
9589 + "need to be discarded.\n\n"
9590 + "Discard related string patterns ?",
9591 + "No, Keep", "Yes, Discard",
9592 + MatchPatternDialog.currentDmptElement->dmpteName);
9594 + if (resp == 1)
9596 + isSubPattern = (MatchPatternDialog.currentDmptElement->dmpteType == MPT_SUB);
9598 + if (isSubPattern)
9599 + RadioButtonChangeState(MatchPatternDialog.mptbSubPatternW, True, True);
9600 + else
9601 + RadioButtonChangeState(MatchPatternDialog.mptbIndividualW, True, True);
9603 + return;
9606 + /*
9607 + * remove string patterns & update dialog fields
9608 + */
9609 + freeDialogStringPatterns(&MatchPatternDialog.currentStringPatterns);
9611 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9614 + /*
9615 + * invalidate this sub-/individual pattern
9616 + */
9617 + MatchPatternDialog.currentDmptSeqElement->dmpseValid = False;
9619 + /*
9620 + * update sub-pattern menu due to change to context group
9621 + */
9622 + updateSubPatternNameMenu(NULL, True);
9625 +static void changeGroupToStringPattern(
9626 + char *warnTitle)
9628 + int resp;
9630 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0)
9631 + return;
9633 + resp =
9634 + DialogF(
9635 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9636 + warnTitle,
9637 + "Content of context group '%s'\n"
9638 + "needs to be discarded.\n\n"
9639 + "Discard content ?",
9640 + "No, Keep", "Yes, Discard",
9641 + MatchPatternDialog.currentDmptGroup->dmpgeName);
9643 + if (resp == 1)
9645 + RadioButtonChangeState(MatchPatternDialog.mptbContextGroupW, True, True);
9647 + else
9649 + /*
9650 + * remove string patterns & update dialog fields
9651 + */
9652 + freeDialogStringPatterns(&MatchPatternDialog.currentStringPatterns);
9654 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9659 +** Create a pulldown menu pane with the names of the sub-patterns of
9660 +** the current matching pattern set.
9662 +static Widget createSubPatternNameMenu(
9663 + Widget parent,
9664 + char *currentSubPatName,
9665 + int allSubPatterns)
9667 + NameList nameList;
9668 + Widget menu;
9669 + int i;
9671 + setupSubPatternNameList(currentSubPatName, allSubPatterns, &nameList);
9673 + menu = CreatePulldownMenu(parent, "subPatternNames", NULL, 0);
9675 + for (i=0; i<nameList.nlNumber; i++)
9677 + createSubPatNameMenuEntry(menu, nameList.nlId[i]);
9680 + return menu;
9683 +static void setupSubPatternNameList(
9684 + char *currentSubPatName,
9685 + int allSubPatterns,
9686 + NameList *nameList)
9688 + int n = 0;
9689 + int i;
9690 + DialogMatchPatternSequenceElement *seq;
9691 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
9693 + if (isRelatedToGroup || allSubPatterns)
9695 + /*
9696 + * add "none selected" (default) item
9697 + */
9698 + nameList->nlId[n ++] = SPNM_NONE_SELECTED;
9700 + /*
9701 + * add one item for each (not assigned) sub-pattern name
9702 + */
9703 + for (i=0; i<MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i++)
9705 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
9707 + if (seq->dmpseType == MPT_SUB &&
9708 + seq->dmpseValid &&
9709 + (allSubPatterns ||
9710 + (!isSubPatternNameInCurStrPat(seq->dmpseName) ||
9711 + (currentSubPatName != NULL &&
9712 + (strcmp(seq->dmpseName, currentSubPatName) == 0))) ))
9714 + nameList->nlId[n ++] = seq->dmpseName;
9718 + else
9720 + nameList->nlId[n ++] = "none available ";
9723 + nameList->nlNumber = n;
9727 +** Create a menu entry with the names of one sub-pattern.
9728 +** XmNuserData of this item contains the sub-pattern name.
9730 +static void createSubPatNameMenuEntry(
9731 + Widget menu,
9732 + char *subPatName)
9734 + Widget btn;
9735 + XmString s1;
9737 + btn = XtVaCreateManagedWidget("subPattern", xmPushButtonGadgetClass,
9738 + menu,
9739 + XmNlabelString, s1=XmStringCreateSimple(subPatName),
9740 + XmNmarginHeight, 0,
9741 + XmNuserData, (void *)subPatName, NULL);
9742 + XmStringFree(s1);
9746 +** Set the sub-patterns menu to show a particular sub-pattern name
9748 +static void setSubPatternNameMenu(
9749 + const char *subPatName)
9751 + int i;
9752 + Cardinal nItems;
9753 + WidgetList items;
9754 + Widget pulldown, selectedItem;
9755 + char *itemName;
9757 + XtVaGetValues(MatchPatternDialog.mpdSubPatNamesOptMenu, XmNsubMenuId, &pulldown, NULL);
9758 + XtVaGetValues(pulldown, XmNchildren, &items, XmNnumChildren, &nItems, NULL);
9760 + if (nItems == 0)
9761 + return;
9763 + selectedItem = items[0];
9765 + /*
9766 + * if no subPatName is given, then select first item of option menu
9767 + */
9768 + if (subPatName != NULL)
9770 + for (i=0; i<(int)nItems; i++)
9772 + if (items[i] != NULL && !items[i]->core.being_destroyed)
9774 + XtVaGetValues(items[i], XmNuserData, &itemName, NULL);
9775 + if (!strcmp(itemName, subPatName))
9777 + selectedItem = items[i];
9778 + break;
9784 + XtVaSetValues(MatchPatternDialog.mpdSubPatNamesOptMenu, XmNmenuHistory, selectedItem, NULL);
9788 +** Update sub-pattern names menu, e.g. when a new sub-pattern is defined
9790 +static void updateSubPatternNameMenu(
9791 + char *currentSubPatName,
9792 + int allSubPatterns)
9794 + NameList nameList;
9795 + WidgetList items;
9796 + Cardinal nItems;
9797 + int n;
9798 + XmString st1;
9800 + setupSubPatternNameList(currentSubPatName, allSubPatterns, &nameList);
9802 + /*
9803 + * Go thru all of the items in the sub-pattern names menu
9804 + * and rename them to match the current sub-patterns.
9805 + * Delete any extras.
9806 + */
9807 + XtVaGetValues(
9808 + MatchPatternDialog.mpdSubPatNamesPulldown,
9809 + XmNchildren, &items,
9810 + XmNnumChildren, &nItems,
9811 + NULL);
9813 + for (n=0; n<(int)nItems; n++)
9815 + if (n >= nameList.nlNumber)
9817 + /*
9818 + * unmanaging before destroying stops parent from displaying
9819 + */
9820 + XtUnmanageChild(items[n]);
9821 + XtDestroyWidget(items[n]);
9823 + else
9825 + if (items[n] == NULL || items[n]->core.being_destroyed)
9827 + /*
9828 + * create a new entry (widget) if this one is not existing or
9829 + * if it is marked as to be destroyed
9830 + */
9831 + createSubPatNameMenuEntry(
9832 + MatchPatternDialog.mpdSubPatNamesPulldown, nameList.nlId[n]);
9834 + else
9836 + XtVaSetValues(
9837 + items[n],
9838 + XmNlabelString, st1=XmStringCreateSimple(nameList.nlId[n]),
9839 + XmNuserData, (void *)nameList.nlId[n],
9840 + NULL);
9842 + XmStringFree(st1);
9847 + /*
9848 + * add new items for remaining sub-patterns names
9849 + */
9850 + for (n=(int)nItems; n<nameList.nlNumber; n++)
9852 + createSubPatNameMenuEntry(
9853 + MatchPatternDialog.mpdSubPatNamesPulldown, nameList.nlId[n]);
9856 + /*
9857 + * select entry shown in sub-pattern name option menu
9858 + */
9859 + setSubPatternNameMenu(currentSubPatName);
9862 +static char *getSelectedSubPatternName(void)
9864 + Widget selectedItem;
9865 + char *itemName;
9867 + XtVaGetValues(MatchPatternDialog.mpdSubPatNamesOptMenu, XmNmenuHistory, &selectedItem, NULL);
9868 + XtVaGetValues(selectedItem, XmNuserData, &itemName, NULL);
9870 + return itemName;
9873 +static int isSubPatternNameInCurStrPat(
9874 + char *subPatName)
9876 + int i;
9877 + DialogStringPatterns *curPatNames = &MatchPatternDialog.currentStringPatterns;
9879 + for (i=0; i<curPatNames->dspNumberOfPatterns; i++)
9881 + if (strcmp(curPatNames->dspElements[i]->dspeText, subPatName) == 0)
9882 + return True;
9885 + return False;
9889 +** Read the matching pattern fields of the matching pattern dialog and produce an
9890 +** allocated DialogMatchPatternSequenceElement structure reflecting the contents.
9891 +** Pop up dialogs telling the user what's wrong (Passing "silent" as True,
9892 +** suppresses these dialogs).
9893 +** Returns NULL on error.
9895 +static DialogMatchPatternSequenceElement *readMatchPatternFields(int silent)
9897 + int isGroup;
9898 + char *name;
9899 + char *nameLabel;
9900 + char *nameTitle;
9901 + char *contentTitle;
9902 + char *contentWarningText;
9903 + DialogMatchPatternSequenceElement *newSeq;
9904 + DialogMatchPatternTableElement *newElement;
9905 + DialogMatchPatternGroupElement *newGroup;
9907 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW))
9909 + nameLabel = "context group name";
9910 + nameTitle = "Context Group Name";
9911 + contentTitle = "Context Group Content";
9912 + contentWarningText = "Please assign min. 1\nsub-pattern";
9913 + isGroup = True;
9915 + else
9917 + nameLabel = "matching pattern name";
9918 + nameTitle = "Matching Pattern Name";
9919 + contentTitle = "Matching Pattern Content";
9920 + contentWarningText = "Please specify min. 1\nstring pattern";
9921 + isGroup = False;
9924 + name =
9925 + ReadSymbolicFieldTextWidget(
9926 + MatchPatternDialog.mpdMatchPatternNameW,
9927 + nameLabel,
9928 + silent);
9930 + if (name == NULL)
9932 + return NULL;
9934 + else if (*name == '\0')
9936 + if (!silent)
9938 + DialogF(
9939 + DF_WARN, MatchPatternDialog.mpdShell, 1,
9940 + nameTitle,
9941 + "Please specify a valid name",
9942 + "OK");
9943 + XmProcessTraversal(MatchPatternDialog.mpdMatchPatternNameW, XmTRAVERSE_CURRENT);
9945 + XtFree(name);
9946 + return NULL;
9949 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0)
9951 + if (!silent)
9953 + DialogF(
9954 + DF_WARN, MatchPatternDialog.mpdShell, 1,
9955 + contentTitle,
9956 + contentWarningText,
9957 + "OK");
9959 + XtFree(name);
9960 + return NULL;
9962 + else
9964 + if (!isGroup &&
9965 + !isStartPatternElementAvailable(&MatchPatternDialog.currentStringPatterns))
9967 + if (!silent)
9969 + DialogF(
9970 + DF_WARN, MatchPatternDialog.mpdShell, 1,
9971 + contentTitle,
9972 + "Please specify min. 1 string pattern\nof type 'start'",
9973 + "OK");
9975 + XtFree(name);
9976 + return NULL;
9980 + if (MatchPatternDialog.currentDmptElement != NULL &&
9981 + MatchPatternDialog.currentDmptElement->dmpteType == MPT_SUB &&
9982 + strcmp(MatchPatternDialog.currentDmptElement->dmpteName, name) != 0)
9984 + renameMatchPatternInAllGroups(
9985 + MatchPatternDialog.currentDmptElement->dmpteName,
9986 + name);
9989 + newSeq =
9990 + (DialogMatchPatternSequenceElement *)XtMalloc(sizeof(DialogMatchPatternSequenceElement));
9992 + newSeq->dmpseName = name;
9993 + newSeq->dmpseValid = True;
9995 + if (isGroup)
9997 + newSeq->dmpseType = MPT_GROUP;
9999 + newGroup =
10000 + (DialogMatchPatternGroupElement *)XtMalloc(sizeof(DialogMatchPatternGroupElement));
10002 + newGroup->dmpgeName = XtNewString(name);
10004 + copyDialogPatternNamesToGroup(
10005 + &MatchPatternDialog.currentStringPatterns,
10006 + newGroup);
10008 + newSeq->dmpsePtr = (void *)newGroup;
10010 + else
10012 + if (XmToggleButtonGetState(MatchPatternDialog.mptbIndividualW))
10013 + newSeq->dmpseType = MPT_INDIVIDUAL;
10014 + else
10015 + newSeq->dmpseType = MPT_SUB;
10017 + newElement =
10018 + (DialogMatchPatternTableElement *)XtMalloc(sizeof(DialogMatchPatternTableElement));
10020 + newElement->dmpteName = XtNewString(name);
10021 + newElement->dmpteType = newSeq->dmpseType;
10023 + newElement->dmpteSkipBtwnStartEnd =
10024 + XmToggleButtonGetState(MatchPatternDialog.gabSkipBtwStartEndW);
10026 + newElement->dmpteFlash =
10027 + XmToggleButtonGetState(MatchPatternDialog.gabFlashW);
10029 + newElement->dmpteIgnoreHighLightInfo =
10030 + !XmToggleButtonGetState(MatchPatternDialog.gabSyntaxBasedW);
10032 + copyDialogStringPatterns(
10033 + &MatchPatternDialog.currentStringPatterns,
10034 + &newElement->dmptePatterns);
10036 + newSeq->dmpsePtr = (void *)newElement;
10039 + return newSeq;
10043 +** Check, if min. 1 string pattern of type 'start' is
10044 +** available within dialog.
10045 +** Returns True, if min. 1 start string pattern is
10046 +** populated in dialog.
10048 +static int isStartPatternElementAvailable(
10049 + DialogStringPatterns *dialogPatterns)
10051 + int i;
10053 + for (i=0; i < dialogPatterns->dspNumberOfPatterns; i++)
10055 + if (dialogPatterns->dspElements[i]->dspeKind == PEK_START)
10056 + return True;
10059 + return False;
10063 +** Read the string pattern fields of the string pattern frame and produce an
10064 +** allocated DialogStringPatternElement structure reflecting the contents.
10065 +** Pop up dialogs telling the user what's wrong (Passing "silent" as True,
10066 +** suppresses these dialogs).
10067 +** Returns NULL on error.
10069 +static DialogStringPatternElement *readStringPatternFrameFields(int silent)
10071 + char *stringPatText;
10072 + DialogStringPatternElement *newPatElement;
10073 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
10075 + if (isRelatedToGroup)
10077 + stringPatText = getSelectedSubPatternName();
10078 + if (strcmp(stringPatText, SPNM_NONE_SELECTED) == 0)
10080 + return NULL;
10083 + stringPatText = XtNewString(stringPatText);
10085 + else
10087 + stringPatText =
10088 + XmTextGetString(MatchPatternDialog.mpdStringPatternW);
10090 + if (stringPatText == NULL)
10092 + return NULL;
10094 + else if (*stringPatText == '\0')
10096 + if (!silent)
10098 + DialogF(
10099 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10100 + "String Pattern",
10101 + "Please specify string\npattern content",
10102 + "OK");
10103 + XmProcessTraversal(MatchPatternDialog.mpdStringPatternW, XmTRAVERSE_CURRENT);
10105 + XtFree(stringPatText);
10106 + return NULL;
10110 + newPatElement = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
10112 + newPatElement->dspeText = stringPatText;
10114 + if (isRelatedToGroup)
10116 + newPatElement->dspeKind = PEK_START;
10117 + newPatElement->dspeWordBoundary = PWB_NONE;
10118 + newPatElement->dspeCaseInsensitive = False;
10119 + newPatElement->dspeRegularExpression = False;
10121 + else
10123 + newPatElement->dspeRegularExpression =
10124 + XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
10126 + if (XmToggleButtonGetState(MatchPatternDialog.sptStartW))
10127 + newPatElement->dspeKind = PEK_START;
10128 + else if (XmToggleButtonGetState(MatchPatternDialog.sptMiddleW))
10129 + newPatElement->dspeKind = PEK_MIDDLE;
10130 + else
10131 + newPatElement->dspeKind = PEK_END;
10133 + if (newPatElement->dspeRegularExpression)
10134 + newPatElement->dspeWordBoundary = PWB_NONE;
10135 + else if (XmToggleButtonGetState(MatchPatternDialog.wbbBothW))
10136 + newPatElement->dspeWordBoundary = PWB_BOTH;
10137 + else if (XmToggleButtonGetState(MatchPatternDialog.wbbLeftW))
10138 + newPatElement->dspeWordBoundary = PWB_LEFT;
10139 + else if (XmToggleButtonGetState(MatchPatternDialog.wbbRightW))
10140 + newPatElement->dspeWordBoundary = PWB_RIGHT;
10141 + else
10142 + newPatElement->dspeWordBoundary = PWB_NONE;
10144 + newPatElement->dspeCaseInsensitive =
10145 + !XmToggleButtonGetState(MatchPatternDialog.sabCaseSensitiveW);
10148 + return newPatElement;
10152 +** Returns true if the pattern fields of the matching pattern dialog are set to
10153 +** the default ("New" pattern) state.
10155 +static int matchPatternDialogEmpty(void)
10157 + return
10158 + TextWidgetIsBlank(MatchPatternDialog.mpdMatchPatternNameW) &&
10159 + XmToggleButtonGetState(MatchPatternDialog.mptbIndividualW) &&
10160 + XmToggleButtonGetState(MatchPatternDialog.gabFlashW) &&
10161 + XmToggleButtonGetState(MatchPatternDialog.gabSyntaxBasedW) &&
10162 + stringPatternFrameEmpty();
10166 +** Returns true if the string pattern frame of the matching pattern dialog is set to
10167 +** the default state.
10169 +static int stringPatternFrameEmpty(void)
10171 + return
10172 + stringPatternFieldsEmpty(False) &&
10173 + MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0;
10177 +** Returns true if the string pattern fields of the string pattern frame are set to
10178 +** the default state.
10180 +static int stringPatternFieldsEmpty(
10181 + int strPatIsRelatedToGroup)
10183 + if (strPatIsRelatedToGroup)
10185 + return(
10186 + strcmp( getSelectedSubPatternName(), SPNM_NONE_SELECTED ) == 0);
10188 + else
10190 + return
10191 + TextWidgetIsBlank(MatchPatternDialog.mpdStringPatternW) &&
10192 + XmToggleButtonGetState(MatchPatternDialog.wbbBothW) &&
10193 + XmToggleButtonGetState(MatchPatternDialog.sabCaseSensitiveW) &&
10194 + !XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
10199 +** Get the current content of the matching pattern dialog.
10200 +** If the matching pattern is o.k., then update & apply it
10201 +** to any window which is currently using the matching pattern.
10202 +** If it's bad, then only report it.
10204 +static int getAndUpdateStringMatchTable(void)
10206 + StringMatchTable *newTable;
10207 + DMPTranslationResult translResult;
10209 + /*
10210 + * Get the current information displayed by the dialog. If it's bad,
10211 + * report it to the user & return.
10212 + */
10213 + newTable = getDialogStringMatchTable(&translResult);
10215 + if (newTable == NULL && translResult != DMPTR_EMPTY)
10217 + DialogF(
10218 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10219 + "Incomplete Matching Patterns for Language Mode",
10220 + "Incomplete matching patterns for language mode '%s'.\n"
10221 + "Please complete them first",
10222 + "OK",
10223 + MatchPatternDialog.mpdLangModeName);
10225 + return False;
10228 + /*
10229 + * change the matching pattern
10230 + */
10231 + updateStringMatchTable( newTable );
10233 + return True;
10237 +** Update the matching pattern set being edited in the matching pattern dialog
10238 +** with the information that the dialog is currently displaying, and
10239 +** apply changes to any window which is currently using the matching pattern.
10241 +static void updateStringMatchTable(
10242 + StringMatchTable *newTable)
10244 + WindowInfo *window;
10245 + int i;
10247 + /*
10248 + * Find the matching pattern being modified
10249 + */
10250 + for (i=0; i<NbrMatchTables; i++)
10252 + if (!strcmp(MatchPatternDialog.mpdLangModeName, MatchTables[i]->smtLanguageMode))
10254 + /*
10255 + * replace existing matching pattern
10256 + */
10257 + freeStringMatchTable(MatchTables[i]);
10258 + MatchTables[i] = newTable;
10259 + break;
10263 + if (i == NbrMatchTables)
10265 + /*
10266 + * new match table for language mode -> add it to end
10267 + */
10268 + MatchTables[NbrMatchTables++] = newTable;
10271 + /*
10272 + * Find windows that are currently using this matching pattern set and
10273 + * update this windows
10274 + */
10275 + for (window=WindowList; window!=NULL; window=window->next)
10277 + if ((window->languageMode == PLAIN_LANGUAGE_MODE &&
10278 + !strcmp(PLAIN_LM_STRING, newTable->smtLanguageMode)) ||
10279 + (window->languageMode != PLAIN_LANGUAGE_MODE &&
10280 + !strcmp(LanguageModeName(window->languageMode), newTable->smtLanguageMode)))
10282 + window->stringMatchTable = newTable;
10286 + /*
10287 + * Note that preferences have been changed
10288 + */
10289 + MarkPrefsChanged();
10292 +static StringMatchTable *getDialogStringMatchTable(
10293 + DMPTranslationResult *result)
10295 + int matchPatListIdx =
10296 + ManagedListSelectedIndex(MatchPatternDialog.mpdMatchPatternNamesListW);
10297 + int stringPatListIdx =
10298 + ManagedListSelectedIndex(MatchPatternDialog.mpdStringPatternsListW);
10300 + /*
10301 + * Get the current content of the matching pattern dialog fields
10302 + */
10303 + if (!UpdateManagedList(MatchPatternDialog.mpdStringPatternsListW, True))
10305 + *result = DMPTR_INCOMPLETE;
10307 + return NULL;
10310 + if (!UpdateManagedList(MatchPatternDialog.mpdMatchPatternNamesListW, True))
10312 + *result = DMPTR_INCOMPLETE;
10314 + return NULL;
10317 + SelectManagedListItem(MatchPatternDialog.mpdMatchPatternNamesListW, matchPatListIdx);
10318 + SelectManagedListItem(MatchPatternDialog.mpdStringPatternsListW, stringPatListIdx);
10320 + /*
10321 + * Translate dialog match table to string match table
10322 + */
10323 + return translateDialogStringMatchTable(&MatchPatternDialog.mpdTable, result);
10326 +static StringMatchTable *translateDialogStringMatchTable(
10327 + DialogMatchPatternInfo *dialogTable,
10328 + DMPTranslationResult *result)
10330 + ReadMatchPatternInfo readPatInfo;
10331 + DialogMatchPatternSequenceElement *seq;
10332 + MatchPatternTableElement *newPatElement;
10333 + MatchPatternGroupElement *newGroupElement;
10334 + char *errMsg;
10335 + ErrorInfo errInfo;
10336 + int i;
10338 + initErrorInfo(&errInfo);
10340 + readPatInfo.rmpiNbrOfElements = 0;
10341 + readPatInfo.rmpiNbrOfGroups = 0;
10342 + readPatInfo.rmpiNbrOfSeqElements = 0;
10343 + readPatInfo.rmpiAllPatRE = NULL;
10344 + readPatInfo.rmpiFlashPatRE = NULL;
10346 + /*
10347 + * if no dialog patterns are defined, return "empty" table
10348 + */
10349 + if (dialogTable->dmpiNbrOfSeqElements == 0)
10351 + *result = DMPTR_EMPTY;
10353 + return createStringMatchTable(
10354 + &readPatInfo,
10355 + XtNewString(MatchPatternDialog.mpdLangModeName));
10358 + /*
10359 + * translate dialog matching pattern elements
10360 + */
10361 + for (i=0; i < dialogTable->dmpiNbrOfSeqElements; i++)
10363 + seq = dialogTable->dmpiSequence[i];
10365 + if (seq->dmpseType == MPT_GROUP)
10367 + newGroupElement =
10368 + translateDialogMatchPatternGroupElement(
10369 + &readPatInfo,
10370 + (DialogMatchPatternGroupElement *)seq->dmpsePtr);
10372 + if (newGroupElement == NULL)
10374 + freeReadMatchPatternInfo(&readPatInfo);
10376 + *result = DMPTR_INCOMPLETE;
10378 + return NULL;
10381 + readPatInfo.rmpiGroup[readPatInfo.rmpiNbrOfGroups ++] =
10382 + newGroupElement;
10384 + recordPatternSequence(
10385 + &readPatInfo,
10386 + seq->dmpseName,
10387 + seq->dmpseType,
10388 + readPatInfo.rmpiNbrOfGroups-1 );
10390 + else
10392 + newPatElement =
10393 + translateDialogMatchPatternTableElement(
10394 + (DialogMatchPatternTableElement *)seq->dmpsePtr);
10396 + newPatElement->mpteIndex = readPatInfo.rmpiNbrOfElements;
10398 + readPatInfo.rmpiElement[readPatInfo.rmpiNbrOfElements ++] =
10399 + newPatElement;
10401 + if (newPatElement->mpteType == MPT_INDIVIDUAL)
10403 + if (!assignIndividualGroup(&readPatInfo, &errMsg, newPatElement))
10405 + DialogF(
10406 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10407 + "Assign reg. exp.",
10408 + "%s\n(Pattern: '%s')",
10409 + "OK",
10410 + errMsg,
10411 + newPatElement->mpteName);
10413 + freeReadMatchPatternInfo(&readPatInfo);
10415 + *result = DMPTR_INCOMPLETE;
10417 + return NULL;
10421 + treatDuplicatedMTEntries(readPatInfo.rmpiElement, readPatInfo.rmpiNbrOfElements);
10423 + recordPatternSequence(
10424 + &readPatInfo,
10425 + seq->dmpseName,
10426 + seq->dmpseType,
10427 + newPatElement->mpteIndex );
10431 + /*
10432 + * compile reg. expressions of "read" patterns
10433 + */
10434 + if (createRegExpOfPatterns( &readPatInfo, &errInfo ))
10436 + errInfo.eiLanguageMode = XtNewString(MatchPatternDialog.mpdLangModeName);
10437 + dialogMatchingPatternSetError(
10438 + "Assign all patterns reg. exp.",
10439 + &errInfo);
10441 + freeReadMatchPatternInfo(&readPatInfo);
10443 + *result = DMPTR_INCOMPLETE;
10445 + return NULL;
10448 + *result = DMPTR_OK;
10450 + return createStringMatchTable(
10451 + &readPatInfo,
10452 + XtNewString(MatchPatternDialog.mpdLangModeName));
10455 +static MatchPatternTableElement *translateDialogMatchPatternTableElement(
10456 + DialogMatchPatternTableElement *dialogElement)
10458 + MatchPatternTableElement *newElement;
10460 + newElement =
10461 + (MatchPatternTableElement *)XtMalloc(sizeof(MatchPatternTableElement));
10463 + newElement->mpteName = XtNewString(dialogElement->dmpteName);
10464 + newElement->mpteIndex = NO_ELEMENT_IDX;
10465 + newElement->mpteType = dialogElement->dmpteType;
10466 + newElement->mpteGroup = NO_GROUP_IDX;
10468 + translateDialogPatterns(&dialogElement->dmptePatterns, newElement);
10470 + newElement->mpteSkipBtwnStartEnd = dialogElement->dmpteSkipBtwnStartEnd;
10471 + newElement->mpteFlash = dialogElement->dmpteFlash;
10472 + newElement->mpteIgnoreHighLightInfo = dialogElement->dmpteIgnoreHighLightInfo;
10473 + newElement->mpteStartEndRE = NULL;
10475 + initGlobalBackRefList( newElement->mpteGlobalBackRef );
10477 + return newElement;
10480 +static void translateDialogPatterns(
10481 + DialogStringPatterns *dialogPatterns,
10482 + MatchPatternTableElement *newElement)
10484 + int sizeOfPat;
10485 + int i;
10487 + /*
10488 + * allocate memory for patterns
10489 + */
10490 + newElement->mpteAll.pesNumberOfPattern = dialogPatterns->dspNumberOfPatterns;
10492 + sizeOfPat =
10493 + sizeof(PatternElement *) * dialogPatterns->dspNumberOfPatterns;
10495 + newElement->mpteAll.pesPattern = (PatternElement **)XtMalloc(sizeOfPat);
10497 + /*
10498 + * assign dialog patterns to patterns of MatchPatternTableElement
10499 + */
10500 + for (i=0; i < dialogPatterns->dspNumberOfPatterns; i++)
10502 + newElement->mpteAll.pesPattern[i] =
10503 + createPatternElement(
10504 + XtNewString(dialogPatterns->dspElements[i]->dspeText),
10505 + dialogPatterns->dspElements[i]->dspeKind,
10506 + dialogPatterns->dspElements[i]->dspeWordBoundary,
10507 + dialogPatterns->dspElements[i]->dspeCaseInsensitive,
10508 + dialogPatterns->dspElements[i]->dspeRegularExpression);
10510 + newElement->mpteAll.pesPattern[i]->peIndex = i;
10513 + /*
10514 + * sort pattern elements into start, middle & end arrays
10515 + */
10516 + sortDialogPatternElementSet( &newElement->mpteAll, newElement );
10518 + /*
10519 + * determine mono pattern
10520 + */
10521 + if (newElement->mpteEnd.pesNumberOfPattern == 0)
10523 + newElement->mpteIsMonoPattern = True;
10525 + copyPatternSet( &newElement->mpteStart, &newElement->mpteEnd );
10527 + else
10529 + newElement->mpteIsMonoPattern = False;
10534 + * Sort dialog pattern element set into start, middle & end arrays.
10535 + */
10536 +static void sortDialogPatternElementSet(
10537 + PatternElementSet *allPat,
10538 + MatchPatternTableElement *result)
10540 + int sizeOfPat;
10542 + /*
10543 + * count number of start, middle & end pattern elements
10544 + */
10545 + countPatternElementKind( allPat, result );
10547 + /*
10548 + * allocate pattern elements
10549 + */
10550 + sizeOfPat = sizeof(PatternElement *) * result->mpteStart.pesNumberOfPattern;
10551 + result->mpteStart.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
10553 + if (result->mpteMiddle.pesNumberOfPattern != 0)
10555 + sizeOfPat = sizeof(PatternElement *) * result->mpteMiddle.pesNumberOfPattern;
10556 + result->mpteMiddle.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
10559 + if (result->mpteEnd.pesNumberOfPattern != 0)
10561 + sizeOfPat = sizeof(PatternElement *) * result->mpteEnd.pesNumberOfPattern;
10562 + result->mpteEnd.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
10565 + /*
10566 + * sort pattern elements into start, middle & end arrays
10567 + */
10568 + sortPatternElementSet( allPat, result );
10571 +static MatchPatternGroupElement *translateDialogMatchPatternGroupElement(
10572 + ReadMatchPatternInfo *info,
10573 + DialogMatchPatternGroupElement *dialogGroup)
10575 + int i;
10576 + int error = False;
10577 + MatchPatternTableElement *subPatElement;
10578 + int sizeOfIds;
10579 + MatchPatternGroupElement *group;
10581 + /*
10582 + * Allocate memory for the matching pattern group. Copy name & number of
10583 + * sub patterns.
10584 + */
10585 + group =
10586 + (MatchPatternGroupElement *)XtMalloc( sizeof(MatchPatternGroupElement) );
10588 + group->mpgeName = XtNewString(dialogGroup->dmpgeName);
10589 + group->mpgeNumberOfSubPatterns = dialogGroup->dmpgeNumberOfSubPatterns;
10590 + group->mpgeKeywordRE = NULL;
10592 + /*
10593 + * Allocate memory for the sub-matching pattern IDs
10594 + */
10595 + sizeOfIds = sizeof(char *) * group->mpgeNumberOfSubPatterns;
10596 + group->mpgeSubPatternIds = (char **)XtMalloc( sizeOfIds );
10598 + for (i=0; i < group->mpgeNumberOfSubPatterns; i ++)
10600 + /*
10601 + * Remember sub-matching pattern ID
10602 + */
10603 + group->mpgeSubPatternIds[i] = XtNewString(dialogGroup->dmpgeSubPatternIds[i]);
10605 + /*
10606 + * Assign the index of this group to the sub-matching pattern
10607 + * if no group index was assigned before.
10608 + */
10609 + subPatElement =
10610 + getPatternOfName( info, dialogGroup->dmpgeSubPatternIds[i]);
10612 + if (subPatElement == NULL)
10614 + DialogF(
10615 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10616 + "Group Compilation",
10617 + "Group '%s':\nsub-matching pattern '%s' not defined before",
10618 + "OK",
10619 + group->mpgeName,
10620 + dialogGroup->dmpgeSubPatternIds[i]);
10622 + error = True;
10624 + else
10626 + if (subPatElement->mpteGroup == NO_GROUP_IDX)
10628 + subPatElement->mpteGroup = info->rmpiNbrOfGroups;
10633 + if (error)
10635 + freeMatchPatternGroupElement(group);
10637 + return NULL;
10640 + return group;
10643 +static int stringMatchTableDiffer(
10644 + StringMatchTable *oldTable,
10645 + StringMatchTable *newTable)
10647 + int i, j;
10648 + MatchPatternTable *oldPatTab = oldTable->smtAllPatterns;
10649 + MatchPatternTable *newPatTab = newTable->smtAllPatterns;
10650 + MatchPatternTableElement *oldPat;
10651 + MatchPatternTableElement *newPat;
10652 + MatchPatternGroupElement *oldGroup;
10653 + MatchPatternGroupElement *newGroup;
10654 + MatchPatternSequenceElement *oldSeq;
10655 + MatchPatternSequenceElement *newSeq;
10657 + if (oldTable->smtNumberOfSeqElements != newTable->smtNumberOfSeqElements)
10658 + return True;
10660 + for (i=0; i < oldTable->smtNumberOfSeqElements; i++)
10662 + oldSeq = oldTable->smtSequence[i];
10663 + newSeq = newTable->smtSequence[i];
10665 + if (AllocatedStringsDiffer(oldSeq->mpseName, newSeq->mpseName))
10666 + return True;
10667 + if (oldSeq->mpseType != newSeq->mpseType)
10668 + return True;
10670 + if (oldSeq->mpseType == MPT_GROUP)
10672 + oldGroup = oldTable->smtGroups[oldSeq->mpseIndex];
10673 + newGroup = newTable->smtGroups[newSeq->mpseIndex];
10675 + if (AllocatedStringsDiffer(oldGroup->mpgeName, newGroup->mpgeName))
10676 + return True;
10678 + if (oldGroup->mpgeNumberOfSubPatterns != newGroup->mpgeNumberOfSubPatterns)
10679 + return True;
10681 + for (j=0; j < oldGroup->mpgeNumberOfSubPatterns; j++)
10683 + if (AllocatedStringsDiffer(
10684 + oldGroup->mpgeSubPatternIds[j],
10685 + newGroup->mpgeSubPatternIds[j]))
10686 + return True;
10689 + else
10691 + oldPat = oldPatTab->mptElements[oldSeq->mpseIndex];
10692 + newPat = newPatTab->mptElements[newSeq->mpseIndex];
10694 + if (AllocatedStringsDiffer(oldPat->mpteName, newPat->mpteName))
10695 + return True;
10697 + if (oldPat->mpteType != newPat->mpteType)
10698 + return True;
10700 + if (oldPat->mpteGroup != newPat->mpteGroup)
10701 + return True;
10703 + if (oldPat->mpteAll.pesNumberOfPattern != newPat->mpteAll.pesNumberOfPattern)
10704 + return True;
10706 + for (j=0; j < oldPat->mpteAll.pesNumberOfPattern; j ++)
10708 + if (patternElementDiffer(
10709 + oldPat->mpteAll.pesPattern[j], oldPatTab,
10710 + newPat->mpteAll.pesPattern[j], newPatTab ) )
10711 + return True;
10714 + if (oldPat->mpteIsMonoPattern != newPat->mpteIsMonoPattern)
10715 + return True;
10717 + if (oldPat->mpteSkipBtwnStartEnd != newPat->mpteSkipBtwnStartEnd)
10718 + return True;
10720 + if (oldPat->mpteIgnoreHighLightInfo != newPat->mpteIgnoreHighLightInfo)
10721 + return True;
10723 + if (oldPat->mpteFlash != newPat->mpteFlash)
10724 + return True;
10728 + return False;
10731 +static int patternElementDiffer(
10732 + PatternElement *oldPE,
10733 + MatchPatternTable *oldTab,
10734 + PatternElement *newPE,
10735 + MatchPatternTable *newTab)
10737 + StringPattern *oldSP;
10738 + StringPattern *newSP;
10740 + oldSP = GetStringPattern(oldTab, oldPE);
10741 + newSP = GetStringPattern(newTab, newPE);
10743 + if (AllocatedStringsDiffer(oldSP->spText, newSP->spText))
10744 + return True;
10745 + if (AllocatedStringsDiffer(oldSP->spOrigText, newSP->spOrigText))
10746 + return True;
10747 + if (oldPE->peKind != newPE->peKind)
10748 + return True;
10749 + if (oldSP->spWordBoundary != newSP->spWordBoundary)
10750 + return True;
10751 + if (oldSP->spCaseInsensitive != newSP->spCaseInsensitive)
10752 + return True;
10753 + if (oldSP->spRegularExpression != newSP->spRegularExpression)
10754 + return True;
10756 + return False;
10759 +static DialogMatchPatternGroupElement *getDialogGroupUsingMatchPattern(
10760 + char *matchPatternName)
10762 + DialogMatchPatternSequenceElement *seq;
10763 + DialogMatchPatternGroupElement *group;
10764 + int i, j;
10766 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10768 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
10770 + if (seq->dmpseType == MPT_GROUP)
10772 + group = (DialogMatchPatternGroupElement *)seq->dmpsePtr;
10774 + for (j=0; j < group->dmpgeNumberOfSubPatterns; j ++)
10776 + if (strcmp(group->dmpgeSubPatternIds[j], matchPatternName) == 0)
10777 + return group;
10782 + return NULL;
10785 +static void removeMatchPatternFromGroup(
10786 + char *matchPatternName,
10787 + DialogMatchPatternGroupElement *group)
10789 + int i;
10791 + for (i=0; i < group->dmpgeNumberOfSubPatterns; i ++)
10793 + if (strcmp(group->dmpgeSubPatternIds[i], matchPatternName) == 0)
10795 + /*
10796 + * remove existing matching pattern name from sub-pattern list
10797 + */
10798 + freeXtPtr((void **)&group->dmpgeSubPatternIds[i]);
10799 + memmove(
10800 + &group->dmpgeSubPatternIds[i],
10801 + &group->dmpgeSubPatternIds[i+1],
10802 + (group->dmpgeNumberOfSubPatterns-1 - i) * sizeof(char *));
10803 + group->dmpgeNumberOfSubPatterns --;
10805 + return;
10810 +static void removeMatchPatternFromAllGroups(
10811 + char *matchPatternName)
10813 + DialogMatchPatternSequenceElement *seq;
10814 + DialogMatchPatternGroupElement *group;
10815 + int i;
10817 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10819 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
10821 + if (seq->dmpseType == MPT_GROUP)
10823 + group = (DialogMatchPatternGroupElement *)seq->dmpsePtr;
10825 + removeMatchPatternFromGroup(matchPatternName, group);
10830 +static void renameMatchPatternInGroup(
10831 + char *oldMatchPatternName,
10832 + char *newMatchPatternName,
10833 + DialogMatchPatternGroupElement *group)
10835 + int i;
10837 + for (i=0; i < group->dmpgeNumberOfSubPatterns; i ++)
10839 + if (strcmp(group->dmpgeSubPatternIds[i], oldMatchPatternName) == 0)
10841 + /*
10842 + * rename existing matching pattern name in sub-pattern list
10843 + */
10844 + freeXtPtr((void **)&group->dmpgeSubPatternIds[i]);
10846 + group->dmpgeSubPatternIds[i] =
10847 + XtNewString(newMatchPatternName);
10849 + return;
10854 +static void renameMatchPatternInAllGroups(
10855 + char *oldMatchPatternName,
10856 + char *newMatchPatternName)
10858 + DialogMatchPatternSequenceElement *seq;
10859 + DialogMatchPatternGroupElement *group;
10860 + int i;
10862 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10864 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
10866 + if (seq->dmpseType == MPT_GROUP)
10868 + group = (DialogMatchPatternGroupElement *)seq->dmpsePtr;
10870 + renameMatchPatternInGroup(
10871 + oldMatchPatternName,
10872 + newMatchPatternName,
10873 + group);
10878 +static void freeVariableDialogData(
10879 + int keepLanguageModeName)
10881 + int i;
10883 + if (!keepLanguageModeName)
10884 + freeXtPtr((void **)&MatchPatternDialog.mpdLangModeName);
10886 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10888 + freeDialogSequenceElement(
10889 + MatchPatternDialog.mpdTable.dmpiSequence[i] );
10892 + MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements = 0;
10894 + freeDialogStringPatterns(
10895 + &MatchPatternDialog.currentStringPatterns);
10898 +static void initGlobalBackRefList(
10899 + GlobalBackRefElement *list)
10901 + int i;
10903 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
10905 + list[i].gbreDefByStrPat = NULL;
10906 + list[i].gbreRegExpText = NULL;
10910 +static void initStrPatBackRefList(
10911 + StringPattern *strPat)
10913 + int i;
10915 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
10917 + strPat->spOwnGlobalBackRef[i].spbreRegExpText = NULL;
10918 + strPat->spOwnGlobalBackRef[i].spbreLocalBackRefID = NO_LOCAL_BACK_REF_ID;
10920 + strPat->spGlobalToLocalBackRef[i] = NO_LOCAL_BACK_REF_ID;
10924 +static void initErrorInfo(
10925 + ErrorInfo *errInfo)
10927 + errInfo->eiDetail = NULL;
10928 + errInfo->eiLanguageMode = NULL;
10929 + errInfo->eiMPTabElementName = NULL;
10930 + errInfo->eiStringPatText = NULL;
10931 + errInfo->eiRegExpCompileMsg = NULL;
10932 + errInfo->eiBackRefNbr = 0;
10935 +static void freeErrorInfo(
10936 + ErrorInfo *errInfo)
10938 + freeXtPtr((void **)&errInfo->eiLanguageMode);
10939 + freeXtPtr((void **)&errInfo->eiMPTabElementName);
10940 + freeXtPtr((void **)&errInfo->eiStringPatText);
10943 +static void freeXtPtr(void **ptr)
10945 + if (*ptr != NULL)
10947 + XtFree((char *)*ptr);
10948 + *ptr = NULL;
10952 +static void freePtr(void **ptr)
10954 + if (*ptr != NULL)
10956 + free((char *)*ptr);
10957 + *ptr = NULL;
10960 diff --quilt /dev/null new/source/patternMatchData.h
10961 --- /dev/null
10962 +++ new/source/patternMatchData.h
10963 @@ -0,0 +1,24 @@
10964 +/* $Id: patternMatchData.h,v 1.3 2003/12/12 16:45:25 uleh Exp $ */
10966 +#ifndef NEDIT_PATTERNMATCHDATA_H_INCLUDED
10967 +#define NEDIT_PATTERNMATCHDATA_H_INCLUDED
10969 +void *FindStringMatchTable(const char *langModeName);
10971 +void RenameStringMatchTable(const char *oldName, const char *newName);
10973 +void DeleteStringMatchTable(const char *langModeName);
10975 +void AssignStandardStringMatchTable(const char *langModeName);
10977 +int LMHasStringMatchTable(const char *languageMode);
10979 +int LoadMatchPatternString(char *inString);
10981 +char *WriteMatchPatternString(void);
10983 +void EditMatchPatterns(WindowInfo *window);
10985 +void UpdateLanguageModeMenuMatchPattern(void);
10987 +#endif /* NEDIT_PATTERNMATCHDATA_H_INCLUDED */
10988 diff --quilt old/source/preferences.c new/source/preferences.c
10989 --- old/source/preferences.c
10990 +++ new/source/preferences.c
10991 @@ -48,6 +48,7 @@ static const char CVSID[] = "$Id: prefer
10992 #include "server.h"
10993 #include "tags.h"
10994 #include "hooks.h"
10995 +#include "patternMatchData.h"
10996 #include "../util/prefFile.h"
10997 #include "../util/misc.h"
10998 #include "../util/DialogF.h"
10999 @@ -281,7 +282,6 @@ static struct prefData {
11000 int emTabDist; /* non-zero tab dist. if emulated tabs are on */
11001 int insertTabs; /* whether to use tabs for padding */
11002 int showMatchingStyle; /* how to flash matching parenthesis */
11003 - int matchSyntaxBased; /* use syntax info to match parenthesis */
11004 int highlightSyntax; /* whether to highlight syntax by default */
11005 int smartTags; /* look for tag in current window first */
11006 int alwaysCheckRelativeTagsSpecs; /* for every new opened file of session */
11007 @@ -351,6 +351,7 @@ static struct {
11008 char *smartIndent;
11009 char *smartIndentCommon;
11010 char *shell;
11011 + char *matchPattern;
11012 } TempStringPrefs;
11014 /* preference descriptions for SavePreferences and RestorePreferences. */
11015 @@ -856,6 +857,72 @@ static PrefDescripRec PrefDescrip[] = {
11016 Matlab:Default", &TempStringPrefs.smartIndent, NULL, True},
11017 {"smartIndentInitCommon", "SmartIndentInitCommon", PREF_ALLOC_STRING,
11018 "Default", &TempStringPrefs.smartIndentCommon, NULL, True},
11019 +/* Pattern Match Feature: matchPatterns resource added */
11020 +#ifdef VMS
11021 +/* The VAX compiler can't compile Java-Script's definition in highlightData.c */
11022 + {"matchPatterns", "MatchPatterns", PREF_ALLOC_STRING,
11023 + "PLAIN:Default\n\
11024 + Ada:Default\n\
11025 + Awk:Default\n\
11026 + C++:Default\n\
11027 + C:Default\n\
11028 + CSS:Default\n\
11029 + Csh:Default\n\
11030 + Fortran:Default\n\
11031 + Java:Default\n\
11032 + LaTeX:Default\n\
11033 + Lex:Default\n\
11034 + Makefile:Default\n\
11035 + Matlab:Default\n\
11036 + NEdit Macro:Default\n\
11037 + Pascal:Default\n\
11038 + Perl:Default\n\
11039 + PostScript:Default\n\
11040 + Python:Default\n\
11041 + Regex:Default\n\
11042 + SGML HTML:Default\n\
11043 + SQL:Default\n\
11044 + Sh Ksh Bash:Default\n\
11045 + Tcl:Default\n\
11046 + VHDL:Default\n\
11047 + Verilog:Default\n\
11048 + XML:Default\n\
11049 + X Resources:Default\n\
11050 + Yacc:Default\n",
11051 + &TempStringPrefs.matchPattern, NULL, True},
11052 +#else
11053 + {"matchPatterns", "MatchPatterns", PREF_ALLOC_STRING,
11054 + "PLAIN:Default\n\
11055 + Ada:Default\n\
11056 + Awk:Default\n\
11057 + C++:Default\n\
11058 + C:Default\n\
11059 + CSS:Default\n\
11060 + Csh:Default\n\
11061 + Fortran:Default\n\
11062 + Java:Default\n\
11063 + JavaScript:Default\n\
11064 + LaTeX:Default\n\
11065 + Lex:Default\n\
11066 + Makefile:Default\n\
11067 + Matlab:Default\n\
11068 + NEdit Macro:Default\n\
11069 + Pascal:Default\n\
11070 + Perl:Default\n\
11071 + PostScript:Default\n\
11072 + Python:Default\n\
11073 + Regex:Default\n\
11074 + SGML HTML:Default\n\
11075 + SQL:Default\n\
11076 + Sh Ksh Bash:Default\n\
11077 + Tcl:Default\n\
11078 + VHDL:Default\n\
11079 + Verilog:Default\n\
11080 + XML:Default\n\
11081 + X Resources:Default\n\
11082 + Yacc:Default\n",
11083 + &TempStringPrefs.matchPattern, NULL, True},
11084 +#endif
11085 {"autoWrap", "AutoWrap", PREF_ENUM, "Continuous",
11086 &PrefData.wrapStyle, AutoWrapTypes, True},
11087 {"wrapMargin", "WrapMargin", PREF_INT, "0",
11088 @@ -872,8 +939,6 @@ static PrefDescripRec PrefDescrip[] = {
11089 &PrefData.saveOldVersion, NULL, True},
11090 {"showMatching", "ShowMatching", PREF_ENUM, "Delimiter",
11091 &PrefData.showMatchingStyle, ShowMatchingTypes, True},
11092 - {"matchSyntaxBased", "MatchSyntaxBased", PREF_BOOLEAN, "True",
11093 - &PrefData.matchSyntaxBased, NULL, True},
11094 {"highlightSyntax", "HighlightSyntax", PREF_BOOLEAN, "True",
11095 &PrefData.highlightSyntax, NULL, True},
11096 {"backlightChars", "BacklightChars", PREF_BOOLEAN, "False",
11097 @@ -1246,6 +1311,7 @@ static void lmApplyCB(Widget w, XtPointe
11098 static void lmCloseCB(Widget w, XtPointer clientData, XtPointer callData);
11099 static int lmDeleteConfirmCB(int itemIndex, void *cbArg);
11100 static int updateLMList(void);
11101 +static int isOldLanguageMode(const char *lmDialogName, const char *oldModeName);
11102 static languageModeRec *copyLanguageModeRec(languageModeRec *lm);
11103 static void *lmGetDisplayedCB(void *oldItem, int explicitRequest, int *abort,
11104 void *cbArg);
11105 @@ -1428,6 +1494,11 @@ static void translatePrefFormats(int con
11106 XtFree(TempStringPrefs.smartIndentCommon);
11107 TempStringPrefs.smartIndentCommon = NULL;
11109 + if (TempStringPrefs.matchPattern != NULL) {
11110 + LoadMatchPatternString(TempStringPrefs.matchPattern);
11111 + XtFree(TempStringPrefs.matchPattern);
11112 + TempStringPrefs.matchPattern = NULL;
11115 /* translate the font names into fontLists suitable for the text widget */
11116 font = XLoadQueryFont(TheDisplay, PrefData.fontString);
11117 @@ -1507,6 +1578,7 @@ void SaveNEditPrefs(Widget parent, int q
11118 TempStringPrefs.styles = WriteStylesString();
11119 TempStringPrefs.smartIndent = WriteSmartIndentString();
11120 TempStringPrefs.smartIndentCommon = WriteSmartIndentCommonString();
11121 + TempStringPrefs.matchPattern = WriteMatchPatternString();
11122 strcpy(PrefData.fileVersion, PREF_FILE_VERSION);
11124 if (!SavePreferences(XtDisplay(parent), prefFileName, HeaderText,
11125 @@ -1526,6 +1598,7 @@ void SaveNEditPrefs(Widget parent, int q
11126 XtFree(TempStringPrefs.styles);
11127 XtFree(TempStringPrefs.smartIndent);
11128 XtFree(TempStringPrefs.smartIndentCommon);
11129 + XtFree(TempStringPrefs.matchPattern);
11131 PrefsHaveChanged = False;
11133 @@ -1921,16 +1994,6 @@ int GetPrefShowMatching(void)
11134 return PrefData.showMatchingStyle;
11137 -void SetPrefMatchSyntaxBased(int state)
11139 - setIntPref(&PrefData.matchSyntaxBased, state);
11142 -int GetPrefMatchSyntaxBased(void)
11144 - return PrefData.matchSyntaxBased;
11147 void SetPrefHighlightSyntax(Boolean state)
11149 setIntPref(&PrefData.highlightSyntax, state);
11150 @@ -3479,6 +3542,21 @@ static int lmDeleteConfirmCB(int itemInd
11151 return False;
11154 + /* Pattern Match Feature: don't allow deletion if data will be lost */
11155 + if (LMHasStringMatchTable(LMDialog.languageModeList[itemIndex]->name))
11157 + DialogF(DF_WARN, LMDialog.shell, 1, "Matching Patterns exist",
11158 + "This language mode has matching patterns\n"
11159 + "defined. Please delete the patterns first,\n"
11160 + "in Preferences -> Default Settings ->\n"
11161 + "Show Matching (..) -> Matching Patterns ..,\n"
11162 + "before proceeding here.", "Dismiss");
11163 + return False;
11166 + /* delete "empty" string match table related to language mode to be deleted */
11167 + DeleteStringMatchTable(LMDialog.languageModeList[itemIndex]->name);
11169 return True;
11172 @@ -3499,15 +3577,15 @@ static int updateLMList(void)
11173 return False;
11175 /* Fix up language mode indices in all open windows (which may change
11176 - if the currently selected mode is deleted or has changed position),
11177 - and update word delimiters */
11178 + if the currently selected mode is renamed, deleted or has changed
11179 + position), and update word delimiters */
11180 for (window=WindowList; window!=NULL; window=window->next) {
11181 if (window->languageMode != PLAIN_LANGUAGE_MODE) {
11182 oldLanguageMode = window->languageMode;
11183 oldModeName = LanguageModes[window->languageMode]->name;
11184 window->languageMode = PLAIN_LANGUAGE_MODE;
11185 for (i=0; i<LMDialog.nLanguageModes; i++) {
11186 - if (!strcmp(oldModeName, LMDialog.languageModeList[i]->name)) {
11187 + if (isOldLanguageMode(LMDialog.languageModeList[i]->name, oldModeName)) {
11188 newDelimiters = LMDialog.languageModeList[i]->delimiters;
11189 if (newDelimiters == NULL)
11190 newDelimiters = GetPrefDelimiters();
11191 @@ -3537,6 +3615,7 @@ static int updateLMList(void)
11192 *strchr(LMDialog.languageModeList[i]->name, ':') = '\0';
11193 RenameHighlightPattern(LMDialog.languageModeList[i]->name, newName);
11194 RenameSmartIndentMacros(LMDialog.languageModeList[i]->name, newName);
11195 + RenameStringMatchTable(LMDialog.languageModeList[i]->name, newName);
11196 memmove(LMDialog.languageModeList[i]->name, newName,
11197 strlen(newName) + 1);
11198 ChangeManagedListData(LMDialog.managedListW);
11199 @@ -3554,13 +3633,24 @@ static int updateLMList(void)
11200 user menu items */
11201 UpdateUserMenuInfo();
11203 + /* Pattern Match Feature: assign standard string match table to new
11204 + language modes */
11205 + for (i=0; i<NLanguageModes; i++) {
11206 + if (FindStringMatchTable(LanguageModeName(i)) == NULL)
11207 + AssignStandardStringMatchTable(LanguageModeName(i));
11210 /* Update the menus in the window menu bars and load any needed
11211 - calltips files */
11212 + calltips files and reassign string match tables */
11213 for (window=WindowList; window!=NULL; window=window->next) {
11214 updateLanguageModeSubmenu(window);
11215 if (window->languageMode != PLAIN_LANGUAGE_MODE &&
11216 LanguageModes[window->languageMode]->defTipsFile != NULL)
11217 AddTagsFile(LanguageModes[window->languageMode]->defTipsFile, TIP);
11219 + window->stringMatchTable =
11220 + FindStringMatchTable(LanguageModeName(window->languageMode));
11222 /* cache user menus: Rebuild all user menus of this window */
11223 RebuildAllMenus(window);
11225 @@ -3569,12 +3659,32 @@ static int updateLMList(void)
11226 UpdateLanguageModeMenu();
11227 /* The same for the smart indent macro dialog */
11228 UpdateLangModeMenuSmartIndent();
11229 + /* The same for the match pattern dialog */
11230 + UpdateLanguageModeMenuMatchPattern();
11231 /* Note that preferences have been changed */
11232 MarkPrefsChanged();
11234 return True;
11238 +** Returns true, if the given old language mode name matches the
11239 +** given (new) language mode dialog name.
11241 +static int isOldLanguageMode(const char *lmDialogName, const char *oldModeName)
11243 + char *c = strchr(lmDialogName, ':');
11244 + int isOldMode = !strcmp(oldModeName, lmDialogName);
11246 + if (!isOldMode && c != NULL) {
11247 + *c = '\0';
11248 + isOldMode = !strcmp(lmDialogName, oldModeName);
11249 + *c = ':';
11252 + return isOldMode;
11255 static void *lmGetDisplayedCB(void *oldItem, int explicitRequest, int *abort,
11256 void *cbArg)
11258 @@ -4568,6 +4678,10 @@ static void reapplyLanguageMode(WindowIn
11259 DeleteTagsFile( LanguageModes[oldMode]->defTipsFile, TIP, False );
11262 + /* Pattern Match Feature: Assign the match pattern related to
11263 + the language mode */
11264 + window->stringMatchTable = FindStringMatchTable(LanguageModeName(mode));
11266 /* Set delimiters for all text widgets */
11267 if (mode == PLAIN_LANGUAGE_MODE || LanguageModes[mode]->delimiters == NULL)
11268 delimiters = GetPrefDelimiters();
11269 @@ -5187,14 +5301,31 @@ char *ReadSymbolicFieldTextWidget(Widget
11271 ** Create a pulldown menu pane with the names of the current language modes.
11272 ** XmNuserData for each item contains the language mode name.
11273 +** Pattern Match Feature: if "includePlain" is set, then 1st menu entry
11274 +** holds "PLAIN".
11276 -Widget CreateLanguageModeMenu(Widget parent, XtCallbackProc cbProc, void *cbArg)
11277 +Widget CreateLanguageModeMenu(
11278 + Widget parent,
11279 + XtCallbackProc cbProc,
11280 + void *cbArg,
11281 + int includePlain)
11283 Widget menu, btn;
11284 int i;
11285 XmString s1;
11287 menu = CreatePulldownMenu(parent, "languageModes", NULL, 0);
11289 + if (includePlain) {
11290 + btn = XtVaCreateManagedWidget("languageMode", xmPushButtonGadgetClass,
11291 + menu,
11292 + XmNlabelString, s1=XmStringCreateSimple("PLAIN"),
11293 + XmNmarginHeight, 0,
11294 + XmNuserData, (void *)"PLAIN", NULL);
11295 + XmStringFree(s1);
11296 + XtAddCallback(btn, XmNactivateCallback, cbProc, cbArg);
11299 for (i=0; i<NLanguageModes; i++) {
11300 btn = XtVaCreateManagedWidget("languageMode", xmPushButtonGadgetClass,
11301 menu,
11302 diff --quilt old/source/preferences.h new/source/preferences.h
11303 --- old/source/preferences.h
11304 +++ new/source/preferences.h
11305 @@ -111,8 +111,6 @@ void SetPrefInsertTabs(int state);
11306 int GetPrefInsertTabs(void);
11307 void SetPrefShowMatching(int state);
11308 int GetPrefShowMatching(void);
11309 -void SetPrefMatchSyntaxBased(int state);
11310 -int GetPrefMatchSyntaxBased(void);
11311 void SetPrefHighlightSyntax(Boolean state);
11312 Boolean GetPrefHighlightSyntax(void);
11313 void SetPrefBacklightChars(int state);
11314 @@ -192,7 +190,7 @@ int FindLanguageMode(const char *languag
11315 void UnloadLanguageModeTipsFile(WindowInfo *window);
11316 void DetermineLanguageMode(WindowInfo *window, int forceNewDefaults);
11317 Widget CreateLanguageModeMenu(Widget parent, XtCallbackProc cbProc,
11318 - void *cbArg);
11319 + void *cbArg, int includePlain);
11320 void SetLangModeMenu(Widget optMenu, const char *modeName);
11321 void CreateLanguageModeSubMenu(WindowInfo* window, const Widget parent,
11322 const char* name, const char* label, const char mnemonic);
11323 diff --quilt old/source/search.c new/source/search.c
11324 --- old/source/search.c
11325 +++ new/source/search.c
11326 @@ -85,6 +85,7 @@ static const char CVSID[] = "$Id: search
11327 #include "../debug.h"
11328 #endif
11330 +#include "patternMatch.h"
11332 int NHist = 0;
11334 @@ -173,6 +174,7 @@ static void checkMultiReplaceListForDoom
11335 WindowInfo* doomedWindow);
11336 static void removeDoomedWindowFromList(WindowInfo* window, int index);
11337 static void unmanageReplaceDialogs(const WindowInfo *window);
11338 +static int getPosForMatchingCharacter(WindowInfo *window);
11339 static void flashTimeoutProc(XtPointer clientData, XtIntervalId *id);
11340 static void eraseFlash(WindowInfo *window);
11341 static int getReplaceDlogInfo(WindowInfo *window, int *direction,
11342 @@ -213,9 +215,6 @@ static void resetReplaceTabGroup(WindowI
11343 static int searchMatchesSelection(WindowInfo *window, const char *searchString,
11344 int searchType, int *left, int *right, int *searchExtentBW,
11345 int *searchExtentFW);
11346 -static int findMatchingChar(WindowInfo *window, char toMatch,
11347 - void *toMatchStyle, int charPos, int startLimit, int endLimit,
11348 - int *matchPos);
11349 static Boolean replaceUsingRE(const char* searchStr, const char* replaceStr,
11350 const char* sourceStr, int beginPos, char* destStr, int maxDestLen,
11351 int prevChar, const char* delimiters, int defaultFlags);
11352 @@ -253,24 +252,6 @@ typedef struct _charMatchTable {
11353 char direction;
11354 } charMatchTable;
11356 -#define N_MATCH_CHARS 13
11357 -#define N_FLASH_CHARS 6
11358 -static charMatchTable MatchingChars[N_MATCH_CHARS] = {
11359 - {'{', '}', SEARCH_FORWARD},
11360 - {'}', '{', SEARCH_BACKWARD},
11361 - {'(', ')', SEARCH_FORWARD},
11362 - {')', '(', SEARCH_BACKWARD},
11363 - {'[', ']', SEARCH_FORWARD},
11364 - {']', '[', SEARCH_BACKWARD},
11365 - {'<', '>', SEARCH_FORWARD},
11366 - {'>', '<', SEARCH_BACKWARD},
11367 - {'/', '/', SEARCH_FORWARD},
11368 - {'"', '"', SEARCH_FORWARD},
11369 - {'\'', '\'', SEARCH_FORWARD},
11370 - {'`', '`', SEARCH_FORWARD},
11371 - {'\\', '\\', SEARCH_FORWARD},
11375 ** Definitions for the search method strings, used as arguments for
11376 ** macro search subroutines and search action routines
11377 @@ -3342,18 +3323,18 @@ static void iSearchTextKeyEH(Widget w, W
11381 -** Check the character before the insertion cursor of textW and flash
11382 -** matching parenthesis, brackets, or braces, by temporarily highlighting
11383 -** the matching character (a timer procedure is scheduled for removing the
11384 -** highlights)
11385 +** Check the characters before the insertion cursor of textW and flash
11386 +** matching patterns (parenthesis e.g. brackets, braces ..) by temporarily
11387 +** highlighting matching characters (a timer procedure is scheduled for
11388 +** removing the highlights)
11390 void FlashMatching(WindowInfo *window, Widget textW)
11392 - char c;
11393 - void *style;
11394 - int pos, matchIndex;
11395 - int startPos, endPos, searchPos, matchPos;
11396 + int pos;
11397 + int direction;
11398 + int startPos, endPos, matchPos, matchLen;
11399 int constrain;
11400 + MatchingType matchingType;
11402 /* if a marker is already drawn, erase it and cancel the timeout */
11403 if (window->flashTimeoutID != 0) {
11404 @@ -3371,48 +3352,43 @@ void FlashMatching(WindowInfo *window, W
11405 if (window->buffer->primary.selected)
11406 return;
11408 - /* get the character to match and the position to start from */
11409 - pos = TextGetCursorPos(textW) - 1;
11410 + /* get the position to start from */
11411 + pos = TextGetCursorPos(textW);
11412 if (pos < 0)
11413 return;
11414 - c = BufGetCharacter(window->buffer, pos);
11415 - style = GetHighlightInfo(window, pos);
11417 - /* is the character one we want to flash? */
11418 - for (matchIndex = 0; matchIndex<N_FLASH_CHARS; matchIndex++) {
11419 - if (MatchingChars[matchIndex].c == c)
11420 - break;
11422 - if (matchIndex == N_FLASH_CHARS)
11423 - return;
11425 /* constrain the search to visible text only when in single-pane mode
11426 AND using delimiter flashing (otherwise search the whole buffer) */
11427 constrain = ((window->nPanes == 0) &&
11428 (window->showMatchingStyle == FLASH_DELIMIT));
11430 - if (MatchingChars[matchIndex].direction == SEARCH_BACKWARD) {
11431 startPos = constrain ? TextFirstVisiblePos(textW) : 0;
11432 - endPos = pos;
11433 - searchPos = endPos;
11434 - } else {
11435 - startPos = pos;
11436 endPos = constrain ? TextLastVisiblePos(textW) :
11437 window->buffer->length;
11438 - searchPos = startPos;
11440 + /* cursor pos. must be between start / end pos. */
11441 + if (pos < startPos || pos > endPos)
11442 + return;
11444 + /* Pattern Match Feature: determine matching type
11445 + (here: flash delimiter or range) */
11446 + if (window->showMatchingStyle == FLASH_DELIMIT) {
11447 + matchingType = MT_FLASH_DELIMIT;
11448 + } else {
11449 + matchingType = MT_FLASH_RANGE;
11452 - /* do the search */
11453 - if (!findMatchingChar(window, c, style, searchPos, startPos, endPos,
11454 - &matchPos))
11455 + /* Pattern Match Feature: do the search */
11456 + if (!FindMatchingString(window, matchingType, &pos, startPos, endPos,
11457 + &matchPos, &matchLen, &direction))
11458 return;
11460 if (window->showMatchingStyle == FLASH_DELIMIT) {
11461 - /* Highlight either the matching character ... */
11462 - BufHighlight(window->buffer, matchPos, matchPos+1);
11463 + /* Highlight either the matching characters ... */
11464 + BufHighlight(window->buffer, matchPos, matchPos + matchLen);
11465 } else {
11466 /* ... or the whole range. */
11467 - if (MatchingChars[matchIndex].direction == SEARCH_BACKWARD) {
11468 + if (direction == SEARCH_BACKWARD) {
11469 BufHighlight(window->buffer, matchPos, pos+1);
11470 } else {
11471 BufHighlight(window->buffer, matchPos+1, pos);
11472 @@ -3426,38 +3402,46 @@ void FlashMatching(WindowInfo *window, W
11473 window->flashPos = matchPos;
11476 -void SelectToMatchingCharacter(WindowInfo *window)
11478 +** Pattern Match Feature:
11479 +** get position of the character to match from the selection, or
11480 +** the character before the insert point if nothing is selected.
11483 +static int getPosForMatchingCharacter(WindowInfo *window)
11485 + int pos;
11486 int selStart, selEnd;
11487 - int startPos, endPos, matchPos;
11488 textBuffer *buf = window->buffer;
11490 - /* get the character to match and its position from the selection, or
11491 - the character before the insert point if nothing is selected.
11492 - Give up if too many characters are selected */
11493 - if (!GetSimpleSelection(buf, &selStart, &selEnd)) {
11494 - selEnd = TextGetCursorPos(window->lastFocus);
11495 - if (window->overstrike)
11496 - selEnd += 1;
11497 - selStart = selEnd - 1;
11498 - if (selStart < 0) {
11499 - XBell(TheDisplay, 0);
11500 - return;
11502 + if (GetSimpleSelection(buf, &selStart, &selEnd)) {
11503 + pos = selEnd;
11505 - if ((selEnd - selStart) != 1) {
11506 - XBell(TheDisplay, 0);
11507 - return;
11508 + else {
11509 + pos = TextGetCursorPos(window->lastFocus);
11513 + return pos;
11516 +void SelectToMatchingCharacter(WindowInfo *window)
11518 + int pos;
11519 + int startPos, endPos, matchPos, matchLen;
11520 + int direction;
11521 + textBuffer *buf = window->buffer;
11523 + /* Pattern Match Feature: get position of the character to match */
11524 + pos = getPosForMatchingCharacter(window);
11526 /* Search for it in the buffer */
11527 - if (!findMatchingChar(window, BufGetCharacter(buf, selStart),
11528 - GetHighlightInfo(window, selStart), selStart, 0, buf->length, &matchPos)) {
11529 + if (!FindMatchingString(window, MT_SELECT, &pos, 0,
11530 + buf->length, &matchPos, &matchLen, &direction)) {
11531 XBell(TheDisplay, 0);
11532 return;
11534 - startPos = (matchPos > selStart) ? selStart : matchPos;
11535 - endPos = (matchPos > selStart) ? matchPos : selStart;
11536 + startPos = (matchPos > pos) ? pos : matchPos;
11537 + endPos = (matchPos > pos) ? matchPos : pos;
11539 /* temporarily shut off autoShowInsertPos before setting the cursor
11540 position so MakeSelectionVisible gets a chance to place the cursor
11541 @@ -3473,32 +3457,17 @@ void SelectToMatchingCharacter(WindowInf
11543 void GotoMatchingCharacter(WindowInfo *window)
11545 - int selStart, selEnd;
11546 - int matchPos;
11547 + int pos;
11548 + int matchPos, matchLen;
11549 + int direction;
11550 textBuffer *buf = window->buffer;
11552 - /* get the character to match and its position from the selection, or
11553 - the character before the insert point if nothing is selected.
11554 - Give up if too many characters are selected */
11555 - if (!GetSimpleSelection(buf, &selStart, &selEnd)) {
11556 - selEnd = TextGetCursorPos(window->lastFocus);
11557 - if (window->overstrike)
11558 - selEnd += 1;
11559 - selStart = selEnd - 1;
11560 - if (selStart < 0) {
11561 - XBell(TheDisplay, 0);
11562 - return;
11565 - if ((selEnd - selStart) != 1) {
11566 - XBell(TheDisplay, 0);
11567 - return;
11569 + /* Pattern Match Feature: get position of the character to match */
11570 + pos = getPosForMatchingCharacter(window);
11572 /* Search for it in the buffer */
11573 - if (!findMatchingChar(window, BufGetCharacter(buf, selStart),
11574 - GetHighlightInfo(window, selStart), selStart, 0,
11575 - buf->length, &matchPos)) {
11576 + if (!FindMatchingString(window, MT_GOTO, &pos, 0,
11577 + buf->length, &matchPos, &matchLen, &direction)) {
11578 XBell(TheDisplay, 0);
11579 return;
11581 @@ -3509,77 +3478,11 @@ void GotoMatchingCharacter(WindowInfo *w
11582 be automatically scrolled on screen and MakeSelectionVisible would do
11583 nothing) */
11584 XtVaSetValues(window->lastFocus, textNautoShowInsertPos, False, NULL);
11585 - TextSetCursorPos(window->lastFocus, matchPos+1);
11586 + TextSetCursorPos(window->lastFocus, matchPos);
11587 MakeSelectionVisible(window, window->lastFocus);
11588 XtVaSetValues(window->lastFocus, textNautoShowInsertPos, True, NULL);
11591 -static int findMatchingChar(WindowInfo *window, char toMatch,
11592 - void* styleToMatch, int charPos, int startLimit, int endLimit,
11593 - int *matchPos)
11595 - int nestDepth, matchIndex, direction, beginPos, pos;
11596 - char matchChar, c;
11597 - void *style = NULL;
11598 - textBuffer *buf = window->buffer;
11599 - int matchSyntaxBased = window->matchSyntaxBased;
11601 - /* If we don't match syntax based, fake a matching style. */
11602 - if (!matchSyntaxBased) style = styleToMatch;
11604 - /* Look up the matching character and match direction */
11605 - for (matchIndex = 0; matchIndex<N_MATCH_CHARS; matchIndex++) {
11606 - if (MatchingChars[matchIndex].c == toMatch)
11607 - break;
11609 - if (matchIndex == N_MATCH_CHARS)
11610 - return FALSE;
11611 - matchChar = MatchingChars[matchIndex].match;
11612 - direction = MatchingChars[matchIndex].direction;
11614 - /* find it in the buffer */
11615 - beginPos = (direction==SEARCH_FORWARD) ? charPos+1 : charPos-1;
11616 - nestDepth = 1;
11617 - if (direction == SEARCH_FORWARD) {
11618 - for (pos=beginPos; pos<endLimit; pos++) {
11619 - c=BufGetCharacter(buf, pos);
11620 - if (c == matchChar) {
11621 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11622 - if (style == styleToMatch) {
11623 - nestDepth--;
11624 - if (nestDepth == 0) {
11625 - *matchPos = pos;
11626 - return TRUE;
11629 - } else if (c == toMatch) {
11630 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11631 - if (style == styleToMatch)
11632 - nestDepth++;
11635 - } else { /* SEARCH_BACKWARD */
11636 - for (pos=beginPos; pos>=startLimit; pos--) {
11637 - c=BufGetCharacter(buf, pos);
11638 - if (c == matchChar) {
11639 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11640 - if (style == styleToMatch) {
11641 - nestDepth--;
11642 - if (nestDepth == 0) {
11643 - *matchPos = pos;
11644 - return TRUE;
11647 - } else if (c == toMatch) {
11648 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11649 - if (style == styleToMatch)
11650 - nestDepth++;
11654 - return FALSE;
11658 ** Xt timer procedure for erasing the matching parenthesis marker.
11660 diff --quilt old/source/smartIndent.c new/source/smartIndent.c
11661 --- old/source/smartIndent.c
11662 +++ new/source/smartIndent.c
11663 @@ -983,9 +983,9 @@ void EditSmartIndentMacros(WindowInfo *w
11664 XmNtopPosition, 1,
11665 XmNrightAttachment, XmATTACH_POSITION,
11666 XmNrightPosition, 99, NULL);
11668 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
11669 SmartIndentDialog.lmPulldown = CreateLanguageModeMenu(lmForm, langModeCB,
11670 - NULL);
11671 + NULL, FALSE);
11672 n = 0;
11673 XtSetArg(args[n], XmNspacing, 0); n++;
11674 XtSetArg(args[n], XmNmarginWidth, 0); n++;
11675 @@ -2155,8 +2155,9 @@ void UpdateLangModeMenuSmartIndent(void)
11676 return;
11678 oldMenu = SmartIndentDialog.lmPulldown;
11679 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
11680 SmartIndentDialog.lmPulldown = CreateLanguageModeMenu(
11681 - XtParent(XtParent(oldMenu)), langModeCB, NULL);
11682 + XtParent(XtParent(oldMenu)), langModeCB, NULL, FALSE);
11683 XtVaSetValues(XmOptionButtonGadget(SmartIndentDialog.lmOptMenu),
11684 XmNsubMenuId, SmartIndentDialog.lmPulldown, NULL);
11685 SetLangModeMenu(SmartIndentDialog.lmOptMenu, SmartIndentDialog.langModeName);
11686 diff --quilt old/source/window.c new/source/window.c
11687 --- old/source/window.c
11688 +++ new/source/window.c
11689 @@ -56,6 +56,7 @@ static const char CVSID[] = "$Id: window
11690 #include "interpret.h"
11691 #include "rangeset.h"
11692 #include "hooks.h"
11693 +#include "patternMatchData.h"
11694 #include "../util/clearcase.h"
11695 #include "../util/misc.h"
11696 #include "../util/fileUtils.h"
11697 @@ -278,7 +279,6 @@ WindowInfo *CreateWindow(const char *nam
11698 window->showWrapMargin = GetPrefShowWrapMargin();
11699 window->overstrike = False;
11700 window->showMatchingStyle = GetPrefShowMatching();
11701 - window->matchSyntaxBased = GetPrefMatchSyntaxBased();
11702 window->showStats = GetPrefStatsLine();
11703 window->showISearchLine = GetPrefISearchLine();
11704 window->showLineNumbers = GetPrefLineNums();
11705 @@ -317,6 +317,10 @@ WindowInfo *CreateWindow(const char *nam
11706 window->macroCmdData = NULL;
11707 window->smartIndentData = NULL;
11708 window->languageMode = PLAIN_LANGUAGE_MODE;
11710 + /* Pattern Match Feature: assign "PLAIN" string match table*/
11711 + window->stringMatchTable = FindStringMatchTable(NULL);
11713 window->iSearchHistIndex = 0;
11714 window->iSearchStartPos = -1;
11715 window->replaceLastRegexCase = TRUE;
11716 @@ -3444,7 +3448,6 @@ WindowInfo* CreateDocument(WindowInfo* s
11717 window->showWrapMargin = GetPrefShowWrapMargin();
11718 window->overstrike = False;
11719 window->showMatchingStyle = GetPrefShowMatching();
11720 - window->matchSyntaxBased = GetPrefMatchSyntaxBased();
11721 window->highlightSyntax = GetPrefHighlightSyntax();
11722 window->backlightCharTypes = NULL;
11723 window->backlightChars = GetPrefBacklightChars();
11724 @@ -3479,6 +3482,12 @@ WindowInfo* CreateDocument(WindowInfo* s
11725 window->macroCmdData = NULL;
11726 window->smartIndentData = NULL;
11727 window->languageMode = PLAIN_LANGUAGE_MODE;
11729 + /*
11730 + * Pattern Match Feature:
11731 + */
11732 + window->stringMatchTable = FindStringMatchTable(NULL);
11734 window->iSearchHistIndex = 0;
11735 window->iSearchStartPos = -1;
11736 window->replaceLastRegexCase = TRUE;
11737 @@ -3876,7 +3885,6 @@ void RefreshMenuToggleStates(WindowInfo
11738 #endif
11739 XmToggleButtonSetState(window->autoSaveItem, window->autoSave, False);
11740 XmToggleButtonSetState(window->overtypeModeItem, window->overstrike, False);
11741 - XmToggleButtonSetState(window->matchSyntaxBasedItem, window->matchSyntaxBased, False);
11742 XmToggleButtonSetState(window->readOnlyItem, IS_USER_LOCKED(window->lockReasons), False);
11743 XmToggleButtonSetState(window->transientItem, window->transient, False);
11745 @@ -4440,6 +4448,9 @@ static void cloneDocument(WindowInfo *wi
11746 if (window->highlightSyntax)
11747 StartHighlighting(window, False);
11749 + /* recycle the pattern match data */
11750 + window->stringMatchTable = orgWin->stringMatchTable;
11752 /* copy states of original document */
11753 window->filenameSet = orgWin->filenameSet;
11754 window->fileFormat = orgWin->fileFormat;
11755 @@ -4458,7 +4469,6 @@ static void cloneDocument(WindowInfo *wi
11756 window->wrapMode = orgWin->wrapMode;
11757 SetOverstrike(window, orgWin->overstrike);
11758 window->showMatchingStyle = orgWin->showMatchingStyle;
11759 - window->matchSyntaxBased = orgWin->matchSyntaxBased;
11760 #if 0
11761 window->showStats = orgWin->showStats;
11762 window->showISearchLine = orgWin->showISearchLine;
11763 diff --quilt old/source/built-ins.h new/source/built-ins.h
11764 --- old/source/built-ins.h
11765 +++ new/source/built-ins.h
11766 @@ -62,6 +62,7 @@ MS(call, call)
11767 MS(args, args)
11768 MS(n_args, nArgs)
11769 MS(highlight_calltip_line, highlightCTLine)
11770 +MS(get_matching, getMatching)
11772 MV(cursor, cursor)
11773 MV(line, line)
11774 @@ -88,7 +89,6 @@ MV(highlight_syntax, highlightSyntax)
11775 MV(make_backup_copy, makeBackupCopy)
11776 MV(incremental_backup, incBackup)
11777 MV(show_matching, showMatching)
11778 -MV(match_syntax_based, matchSyntaxBased)
11779 MV(overtype_mode, overTypeMode)
11780 MV(read_only, readOnly)
11781 MV(locked, locked)