runtime symbol lookup
[nedit-bw.git] / matching_patterns.patch
blobe9dc11e4e50c6a9265fe227e2619fb40f0acb6e7
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 | 6
56 source/Makefile.dependencies | 11
57 source/highlightData.c | 13
58 source/macro.c | 107
59 source/menu.c | 63
60 source/nedit.h | 6
61 source/patternMatch.c | 2202 ++++++++++++
62 source/patternMatch.h | 170
63 source/patternMatchData.c | 7780 +++++++++++++++++++++++++++++++++++++++++++
64 source/patternMatchData.h | 24
65 source/preferences.c | 170
66 source/preferences.h | 4
67 source/search.c | 231 -
68 source/smartIndent.c | 7
69 source/window.c | 18
70 16 files changed, 10773 insertions(+), 297 deletions(-)
72 diff --quilt old/doc/help.etx new/doc/help.etx
73 --- old/doc/help.etx
74 +++ new/doc/help.etx
75 @@ -866,8 +866,9 @@ Programming with NEdit
76 Though general in appearance, NEdit has many features intended specifically
77 for programmers. Major programming-related topics are listed in separate
78 sections under the heading: "Features for Programming": Syntax_Highlighting_,
79 - Tabs/Emulated_Tabs_, Finding_Declarations_(ctags)_, Calltips_, and
80 - Auto/Smart_Indent_. Minor topics related to programming are discussed below:
81 + Tabs/Emulated_Tabs_, Matching_Parentheses_, Finding_Declarations_(ctags)_,
82 + Calltips_, and Auto/Smart_Indent_. Minor topics related to programming are
83 + discussed below:
85 3>Language Modes
87 @@ -925,26 +926,6 @@ Programming with NEdit
88 a column on the current line just leave out the line number. (e.g. Enter
89 ",45" to go the column 45 on the current line.)
91 -3>Matching Parentheses
93 - To help you inspect nested parentheses, brackets, braces, quotes, and other
94 - characters, NEdit has both an automatic parenthesis matching mode, and a Goto
95 - Matching command. Automatic parenthesis matching is activated when you type,
96 - or move the insertion cursor after a parenthesis, bracket, or brace. It
97 - momentarily highlights either the opposite character ('Delimiter') or the
98 - entire expression ('Range') when the opposite character is visible in the
99 - window. To find a matching character anywhere in the file, select it or
100 - position the cursor after it, and choose Goto Matching from the Search menu.
101 - If the character matches itself, such as a quote or slash, select the first
102 - character of the pair. NEdit will match {, (, [, <, ", ', `, /, and \.
103 - Holding the Shift key while typing the accelerator key (Shift+Ctrl+M, by
104 - default), will select all of the text between the matching characters.
106 - When syntax highlighting is enabled, the matching routines can optionally
107 - make use of the syntax information for improved accuracy. In that case,
108 - a brace inside a highlighted string will not match a brace inside a comment,
109 - for instance.
111 3>Opening Included Files
113 The Open Selected command in the File menu understands the C preprocessor's
114 @@ -1222,6 +1203,39 @@ Syntax Highlighting
115 possible, but unlikely if you are only using the built-in patterns.
116 ----------------------------------------------------------------------
118 +Matching Parentheses
119 +--------------------
121 +3>Matching Parentheses (Patterns)
123 + To help you inspect nested parentheses (e.g. brackets, braces, quotes
124 + etc.) or nested constructs (e.g. "begin" .. "end"), NEdit has both an
125 + automatic parenthesis matching mode, and a Goto Matching command.
127 + A matching pattern can be a single character (like '(', ')'), a literal
128 + string (like '#ifdef', '#endif') or a regular expression (like
129 + '\</.*\>').
131 + Automatic parenthesis matching is activated when you type, or move the
132 + insertion cursor after a parenthesis, bracket, or brace. It momentarily
133 + highlights either the opposite pattern ('Delimiter') or the entire expression
134 + ('Range') when the opposite pattern is visible in the window. To find a
135 + matching pattern anywhere in the file, select it or position the cursor after
136 + it, and choose Goto Matching from the Search menu. If the pattern matches
137 + itself, such as a quote or slash, select the first pattern of the pair.
138 + Holding the Shift key while typing the accelerator key (Shift+Ctrl+M, by
139 + default), will select all of the text between the matching patterns.
141 + When syntax highlighting is enabled, the matching routines can optionally
142 + make use of the syntax information for improved accuracy. In that case,
143 + a brace inside a highlighted string will not match a brace inside a comment,
144 + for instance.
146 + Matching patterns are language dependent. Matching patterns can be
147 + configured by the user. If no matching patterns are available for the
148 + language that you want to use, you can create new patterns relatively quickly.
149 + The Help section "Matching_Patterns_" under "Customizing", has details.
151 Finding Declarations (ctags)
152 ----------------------------
154 @@ -2580,9 +2594,6 @@ Macro Subroutines
155 Contains the current preference for showing matching pairs,
156 such as "[]" and "{}" pairs. Can be "off", "delimiter", or "range".
158 -**$match_syntax_based**
159 - Whether pair matching should use syntax information, if available.
161 **$statistics_line**
162 Has a value of 1 if the statistics line is shown, otherwise 0.
164 @@ -2697,6 +2708,15 @@ Macro Subroutines
165 Returns the single character at the position
166 indicated by the first argument to the routine from the current window.
168 +**get_matching( position )**
169 + Find a matching pattern string related to the given position.
170 + Returns info about matching pattern within an array. The array has
171 + the following keys: **pos** (position of the first character of the
172 + matching pattern), **len** (length of the matching pattern), **direction**
173 + (direction where the matching pattern was found: ~0~ = forward;
174 + ~1~ = backward). If no matching pattern was found, then array element
175 + of **pos** holds ~-1~, **len** holds ~0~ and **direction** holds ~-1~.
177 **get_range( start, end )**
178 Returns the text between a starting and ending position from the current
179 window.
180 @@ -3406,9 +3426,6 @@ Action Routines
181 **set_show_matching( "off" | "delimiter" | "range" )**
182 Set show matching (...) mode for the current window.
184 -**set_match_syntax_based( [0 | 1] )**
185 - Set whether matching should be syntax based for the current window.
187 **set_statistics_line( [0 | 1] )**
188 Show or hide the statistics line for the current window.
189 A value of 0 turns it off and a value of 1 turns it on.
190 @@ -3940,10 +3957,6 @@ Preferences
191 matching delimiter, while Range highlights the whole range of text between
192 the matching delimiters.
194 - Optionally, the matching can make use of syntax information if syntax
195 - highlighting is enabled. Alternatively, the matching is purely character
196 - based. In general, syntax based matching results in fewer false matches.
198 **Overtype**
199 In overtype mode, new characters entered replace the characters in front of
200 the insertion cursor, rather than being inserted before them.
201 @@ -5049,6 +5062,185 @@ Smart Indent Macros
202 keystroke typed, so if you try to get too fancy, you may degrade performance.
203 ----------------------------------------------------------------------
205 +Matching Patterns
206 +-----------------
208 +3>Writing Matching Pattern Sets
210 + Matching Patterns Sets are groups of single characters (like '(', ')'),
211 + literal strings (like '#ifdef', '#endif') or a regular expressions (like
212 + '\</.*\>'), which match to each other.
214 + Examples: An open bracket '(' belongs a closing one ')'.
215 + Or: '#ifdef'(start), '#ifndef'(alternative start), '#ifndef' (another
216 + alternative start),'#elif' (optional), '#else' (optional), '#endif' (end)
217 + define a "#ifdef statement matching pattern".
219 + "Opposite pattern highlighting" or "Goto Matching" features are implemented
220 + in NEdit using this matching pattern sets (see Matching_Parentheses_ under
221 + the heading of Features for Programming).
223 + During definition of a new language mode a standard matching pattern set
224 + is assigned to this new language mode.
226 + To modify a matching pattern set, select "Matching Patterns ..." from
227 + "Show Matching (..)" sub-section of the "Default Settings" sub-menu
228 + of the "Preferences" menu.
230 + A matching pattern set is a collection of matching patterns.
232 + A matching pattern usually consists out of string patterns.
234 + The name of a matching pattern set needs to be defined within field "Matching
235 + Pattern Name".
237 +4>Attributes of matching pattern
239 + A matching pattern holds two types of attributes:
241 +* "Matching Pattern Type" and
242 +* "Global Attributes"
244 + The matching pattern type specifies the kind of the matching pattern
245 + entry:
247 +* "Individual" or
248 +* "Sub-pattern" or
249 +* "Context group"
251 + Each matching pattern can be defined as "Individual" or as "Sub-pattern".
252 + A "Sub-pattern" belongs to a context group. A context group is simply a
253 + collection of sub-patterns.
255 + During search for a corresponding pattern, an "Individual" matching pattern
256 + does not care about nesting of other matching patterns.
258 + If a matching pattern out of a "Context group" is searched, then all
259 + sub-pattern sets defined in this group are taken into account during the
260 + search.
262 + In fact, "Individual" matching pattern search is faster than "Context group" /
263 + "Sub-pattern" search. "Context group" / "Sub-pattern" search results in fewer
264 + false matches.
266 + To define a context group, set "Matching Pattern Type" to "Context group".
267 + Select out of "Sub-Pattern Name" pop-up field all sub-patterns, which
268 + should be placed into this group. **Note**: all "Sub-pattern" used by a context
269 + group must be defined **before** the context group itself.
271 + "Global Attributes" of a matching pattern are
273 +* "Skip content between start / end pattern"
274 +* "Flash matching pattern"
275 +* "Syntax based"
277 + If "Skip content between start / end pattern" is checked, then all text
278 + between the first / last string pattern of the related matching pattern is
279 + not scanned for other string patterns. This is useful for specifying comments.
281 + "Flash matching pattern" indicates, if the string patterns are flashed during
282 + typing. If not checked, then only the "Goto Matching" feature works for the
283 + related matching pattern. Note: if lots of "Flash matching pattern" are
284 + specified, then this may slow down the performance of NEdit: after each
285 + character typed all "Flash matching pattern" are scanned for being
286 + applicable ...
288 + "Syntax based" defines, if the matching pattern can make use of syntax
289 + information if syntax highlighting is enabled. Alternatively, the matching is
290 + purely character based. In general, syntax based matching results in fewer
291 + false matches.
293 +4>Content of matching pattern
295 + An "Individual" pattern or a "Sub-pattern" may consist out of only one string
296 + pattern (e.g. double quotes '"'). Such a pattern is called "mono pattern".
297 + You can imagine, that a match for a mono pattern is hard to find. A matching
298 + mono pattern search is always started in forward direction. If no match is
299 + found in forward direction, a backward search is started. If the "Global
300 + Attribute" "Syntax based" is selected for a mono pattern, then the character
301 + before / after the match is checked to have the same highlighting style than
302 + the pattern itself. This may help to determine the correct match for a mono
303 + pattern.
305 + Usually a matching pattern holds two string patterns (e.g. 'begin' and
306 + 'end'). One ('begin') is the start pattern. The other one ('end') is the
307 + end pattern. If the cursor is located behind the start pattern, then a
308 + corresponding end pattern is searched (in forward direction). If the
309 + cursor is located behind the end pattern, then a start pattern is search
310 + (in backward direction):
312 +! +--> start ---> end --+
313 +! +-----------<---------+
315 + Alternative start / end patterns can be defined. In this case one of the
316 + start / end patterns must be in front of the cursor to detect one of the
317 + related end / start patterns:
319 +! +-> start1 -+ +-> end1 -+
320 +! +-+-> start2 -+---+ +--+
321 +! + +-> start3 -+ +-> end2 -+ |
322 +! +---------------<-------------+
324 + At least also "middle" patterns can be defined (e.g. middle patterns
325 + 'elif' or 'else'). If the cursor is located behind a middle pattern then a
326 + next middle pattern or the end pattern is searched in forward direction:
328 +! +-----<-----+
329 +! +--> start -+-> middle -+-> end --+
330 +! +-----------<---------------------+
332 +4>String pattern
334 + A string pattern holds three attributes:
336 +* "String Pattern Type"
337 +* "Word Boundary"
338 +* "String Attributes"
340 + String Pattern Type specifies if the related string pattern is
341 + a "start", middle, or "end" pattern (see above).
343 + Word boundary defines, if before / after a string pattern a delimiter must be
344 + located ("Both" = pattern is framed by delimiters. "Left" = before pattern
345 + must be a delimiter. "Right" = after pattern must be a delimiter. "None" =
346 + there must be no delimiter before or after pattern).
348 + There are two "String Attributes":
350 +* "Case Sensitive"
351 +* "Regular Expression"
353 + If "Case Sensitive" is checked (= default), then the matching pattern search
354 + concerning this string pattern differs between upper / lower case of the
355 + characters. If "Case Sensitive" is not set, then the case of the checked
356 + characters is not considered.
358 + "Regular Expression" indicates, that string pattern is treated as
359 + regular expression (if "Regular Expression" is checked) or as literal
360 + string (if "Regular Expression" is not checked).
362 +4>Regular Expression String Pattern
364 + Syntax of regular expression is described by NEdit Help menu item
365 + Regular_Expressions_. Following deviations from this syntax are
366 + existing concerning string patterns:
368 +5>Capturing Parentheses
370 + Capturing Parentheses inside string patterns are of the form `(*n<regex>)',
371 + where n = 1 .. 9. Standard "capturing parentheses" of form `(<regex>)' are
372 + treated as "non-capturing parentheses" by the matching pattern feature.
373 + "n" defines the **global** backreference number, which can be used inside any string
374 + pattern of the same matching pattern (= set of string patterns). So
375 + matching patterns like "\<(*1[^/>])\>" (start string pattern) and "\</\1\>"
376 + (end string pattern) are possible. This matching pattern will match e.g.
377 + <body> .. </body> but will not match <body> .. </head>.
379 +5>Non-Capturing Parentheses
381 + As described above: parentheses constructs like (<regex>) are treated
382 + as `(?:<regex>)' (non-capturing parentheses) by the matching pattern feature.
384 NEdit Command Line
385 ------------------
387 @@ -6079,6 +6271,7 @@ Problems/Defects
388 .. Menu: Tabs/Emulated Tabs # tabs
389 .. Menu: Auto/Smart Indent # indent
390 .. Menu: Syntax Highlighting # syntax
391 +.. Menu: Matching Parentheses # pattern_matching
392 .. Menu: Finding Declarations (ctags) # tags
393 .. Menu: Calltips # calltips
395 @@ -6106,6 +6299,7 @@ Problems/Defects
396 .. Menu: Key Binding # binding
397 .. Menu: Highlighting Patterns # patterns
398 .. Menu: Smart Indent Macros # smart_indent
399 +.. Menu: Matching Patterns # matching_patterns
401 .. Menu: NEdit Command Line # command_line
402 .. Menu: Client/Server Mode # server
403 diff --quilt old/source/Makefile.common new/source/Makefile.common
404 --- old/source/Makefile.common
405 +++ new/source/Makefile.common
406 @@ -7,7 +7,8 @@ OBJS = nedit.o file.o menu.o window.o se
407 help.o preferences.o tags.o userCmds.o shell.o regularExp.o macro.o \
408 text.o textSel.o textDisp.o textBuf.o textDrag.o server.o highlight.o \
409 highlightData.o interpret.o parse.o smartIndent.o regexConvert.o \
410 - rbTree.o windowTitle.o calltips.o server_common.o rangeset.o
411 + rbTree.o windowTitle.o calltips.o server_common.o rangeset.o \
412 + patternMatch.o patternMatchData.o
414 XLTLIB = ../Xlt/libXlt.a
415 XMLLIB = ../Microline/XmL/libXmL.a
416 @@ -37,6 +38,9 @@ smartIndent.o: smartIndent.c
417 highlightData.o: highlightData.c
418 $(CC) $(CFLAGS) $(BIGGER_STRINGS) -c highlightData.c -o $@
420 +patternMatchData.o: patternMatchData.c
421 + $(CC) $(CFLAGS) $(BIGGER_STRINGS) -c patternMatchData.c -o $@
423 help_topic.h help_data.h: ../doc/help.etx
424 (cd ..; $(MAKE) docs)
426 diff --quilt old/source/Makefile.dependencies new/source/Makefile.dependencies
427 --- old/source/Makefile.dependencies
428 +++ new/source/Makefile.dependencies
429 @@ -87,3 +87,14 @@ windowTitle.o: windowTitle.c windowTitle
430 ../util/DialogF.h ../util/utils.h ../util/fileUtils.h \
431 ../util/clearcase.h
432 parse.c: parse.h textBuf.h nedit.h rbTree.h interpret.h ops.h
433 +patternMatch.o: patternMatch.c regularExp.h \
434 + textBuf.h search.h window.h preferences.h highlight.h\
435 + patternMatch.h patternMatchData.h
436 +patternMatchData.o: patternMatchData.c ../util/DialogF.h ../util/misc.h \
437 + ../util/managedList.h regularExp.h textBuf.h nedit.h window.h \
438 + preferences.h help.h file.h textP.h patternMatch.h patternMatchData.h
439 +macro.o: patternMatch.h regularExp.h
440 +menu.o: patternMatchData.h
441 +preferences.o: patternMatchData.h
442 +search.o: patternMatch.h
443 +window.o: patternMatchData.h
444 diff --quilt old/source/highlightData.c new/source/highlightData.c
445 --- old/source/highlightData.c
446 +++ new/source/highlightData.c
447 @@ -551,7 +551,7 @@ static char *DefaultPatternSets[] = {
448 Built-in Misc Vars:\"(?<!\\Y)\\$(?:active_pane|args|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\
449 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\
450 Built-in Special Vars:\"(?<!\\Y)\\$(?:[1-9]|list_dialog_button|n_args|read_status|search_end|shell_cmd_status|string_dialog_button|sub_sep)>\":::String1::\n\
451 - 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\
452 + 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\
453 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\
454 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\
455 Macro Hooks:\"<(?:(?:pre|post)_(?:open|save)|cursor_moved|modified|(?:losing_)?focus)_hook(?=\\s*\\()\":::Subroutine1::\n\
456 @@ -2346,8 +2346,9 @@ void EditHighlightPatterns(WindowInfo *w
457 XmNrightPosition, 99,
458 NULL);
460 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
461 HighlightDialog.lmPulldown = CreateLanguageModeMenu(lmForm, langModeCB,
462 - NULL);
463 + NULL, FALSE);
464 n = 0;
465 XtSetArg(args[n], XmNspacing, 0); n++;
466 XtSetArg(args[n], XmNmarginWidth, 0); n++;
467 @@ -2881,8 +2882,9 @@ void UpdateLanguageModeMenu(void)
468 return;
470 oldMenu = HighlightDialog.lmPulldown;
471 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
472 HighlightDialog.lmPulldown = CreateLanguageModeMenu(
473 - XtParent(XtParent(oldMenu)), langModeCB, NULL);
474 + XtParent(XtParent(oldMenu)), langModeCB, NULL, FALSE);
475 XtVaSetValues(XmOptionButtonGadget(HighlightDialog.lmOptMenu),
476 XmNsubMenuId, HighlightDialog.lmPulldown, NULL);
477 SetLangModeMenu(HighlightDialog.lmOptMenu, HighlightDialog.langModeName);
478 @@ -2941,6 +2943,9 @@ static void langModeCB(Widget w, XtPoint
480 SetLangModeMenu(HighlightDialog.lmOptMenu,
481 HighlightDialog.langModeName);
483 + freePatternSet(newPatSet);
485 return;
487 if (resp == 1)
488 @@ -3040,6 +3045,8 @@ static void restoreCB(Widget w, XtPointe
489 "patterns for language mode %s?", "Discard", "Cancel",
490 HighlightDialog.langModeName) == 2)
492 + freePatternSet(defaultPatSet);
494 return;
497 diff --quilt old/source/macro.c new/source/macro.c
498 --- old/source/macro.c
499 +++ new/source/macro.c
500 @@ -57,6 +57,8 @@ static const char CVSID[] = "$Id: macro.
501 #include "highlight.h"
502 #include "highlightData.h"
503 #include "rangeset.h"
504 +#include "patternMatch.h"
505 +#include "regularExp.h"
507 #include <stdio.h>
508 #include <stdlib.h>
509 @@ -312,8 +314,6 @@ static int incBackupMV(WindowInfo *windo
510 DataValue *result, char **errMsg);
511 static int showMatchingMV(WindowInfo *window, DataValue *argList, int nArgs,
512 DataValue *result, char **errMsg);
513 -static int matchSyntaxBasedMV(WindowInfo *window, DataValue *argList, int nArgs,
514 - DataValue *result, char **errMsg);
515 static int overTypeModeMV(WindowInfo *window, DataValue *argList, int nArgs,
516 DataValue *result, char **errMsg);
517 static int readOnlyMV(WindowInfo *window, DataValue *argList, int nArgs,
518 @@ -429,6 +429,10 @@ static int filenameDialogMS(WindowInfo*
519 static int callMS(WindowInfo *window, DataValue *argList,
520 int nArgs, DataValue *result, char **errMsg);
522 +/* Pattern Match Feature */
523 +static int getMatchingMS(WindowInfo *window, DataValue *argList, int nArgs,
524 + DataValue *result, char **errMsg);
526 /* Built-in subroutines and variables for the macro language */
527 static const BuiltInSubrName MacroSubrs[] = {
528 { "args", argsMS },
529 @@ -491,6 +495,7 @@ static const BuiltInSubrName MacroSubrs[
530 { "get_style_at_pos", getStyleAtPosMS },
531 { "filename_dialog", filenameDialogMS },
532 { "call", callMS },
533 + { "get_matching", getMatchingMS },
534 { NULL, NULL } /* sentinel */
537 @@ -520,7 +525,6 @@ static const BuiltInSubrName SpecialVars
538 { "$make_backup_copy", makeBackupCopyMV },
539 { "$incremental_backup", incBackupMV },
540 { "$show_matching", showMatchingMV },
541 - { "$match_syntax_based", matchSyntaxBasedMV },
542 { "$overtype_mode", overTypeModeMV },
543 { "$read_only", readOnlyMV },
544 { "$locked", lockedMV },
545 @@ -4530,16 +4534,6 @@ static int showMatchingMV(WindowInfo *wi
546 return True;
549 -static int matchSyntaxBasedMV(WindowInfo *window, DataValue *argList, int nArgs,
550 - DataValue *result, char **errMsg)
552 - result->tag = INT_TAG;
553 - result->val.n = window->matchSyntaxBased ? 1 : 0;
554 - return True;
559 static int overTypeModeMV(WindowInfo *window, DataValue *argList, int nArgs,
560 DataValue *result, char **errMsg)
562 @@ -5947,6 +5941,93 @@ static int getPatternAtPosMS(WindowInfo
563 HighlightStyleOfCode(window, patCode), bufferPos);
567 +** Pattern Match Feature:
568 +** Find a matching pattern string related to the given position.
570 +** Syntax:
571 +** get_matching(position)
573 +** Returns info about matching pattern within an array. The array has
574 +** the following keys: "pos" (position of the first character of the
575 +** matching pattern), "len" (length of the matching pattern), "direction"
576 +** (direction where the matching pattern was found: "0" = forward;
577 +** "1" = backward). If no matching pattern was found, then array element
578 +** of "pos" holds "-1", "len" holds "0" and "direction" holds "-1".
581 +static int getMatchingMS(WindowInfo *window, DataValue *argList, int nArgs,
582 + DataValue *result, char **errMsg)
584 + int startPos;
585 + int matchPos, matchLen;
586 + int direction;
587 + textBuffer *buf = window->buffer;
588 + DataValue dv;
590 + /*
591 + * Perform syntax & semantic check
592 + */
593 + if (nArgs != 1 )
594 + return wrongNArgsErr(errMsg);
596 + if (!readIntArg(argList[0], &startPos, errMsg))
597 + return False;
599 + startPos ++;
601 + /*
602 + * do the search; provide default values, if search fails
603 + */
604 + if (!FindMatchingString(window, MT_MACRO, &startPos, 0, buf->length,
605 + &matchPos, &matchLen, &direction))
607 + matchPos = -1;
608 + matchLen = 0;
609 + direction = -1;
612 + /*
613 + * initialize array holding info about matching string
614 + */
615 + result->tag = ARRAY_TAG;
616 + result->val.arrayPtr = ArrayNew();
618 + /*
619 + * the following array entries will be integers
620 + */
621 + dv.tag = INT_TAG;
623 + /*
624 + * insert match position
625 + */
626 + dv.val.n = matchPos;
627 + if (!ArrayInsert(result, PERM_ALLOC_STR("pos"), &dv))
629 + M_ARRAY_INSERT_FAILURE();
632 + /*
633 + * insert length of matching pattern
634 + */
635 + dv.val.n = matchLen;
636 + if (!ArrayInsert(result, PERM_ALLOC_STR("len"), &dv))
638 + M_ARRAY_INSERT_FAILURE();
641 + /*
642 + * insert direction where the matching pattern was found
643 + */
644 + dv.val.n = direction;
645 + if (!ArrayInsert(result, PERM_ALLOC_STR("direction"), &dv))
647 + M_ARRAY_INSERT_FAILURE();
650 + return True;
653 static int wrongNArgsErr(char **errMsg)
655 *errMsg = "Wrong number of arguments to function %s";
656 diff --quilt old/source/menu.c new/source/menu.c
657 --- old/source/menu.c
658 +++ new/source/menu.c
659 @@ -49,6 +49,7 @@ static const char CVSID[] = "$Id: menu.c
660 #include "macro.h"
661 #include "highlight.h"
662 #include "highlightData.h"
663 +#include "patternMatchData.h"
664 #include "interpret.h"
665 #include "smartIndent.h"
666 #include "windowTitle.h"
667 @@ -133,7 +134,6 @@ static void backlightCharsCB(Widget w, W
668 static void showMatchingOffCB(Widget w, WindowInfo *window, caddr_t callData);
669 static void showMatchingDelimitCB(Widget w, WindowInfo *window, caddr_t callData);
670 static void showMatchingRangeCB(Widget w, WindowInfo *window, caddr_t callData);
671 -static void matchSyntaxBasedCB(Widget w, WindowInfo *window, caddr_t callData);
672 static void statsCB(Widget w, WindowInfo *window, caddr_t callData);
673 static void autoIndentOffDefCB(Widget w, WindowInfo *window, caddr_t callData);
674 static void autoIndentDefCB(Widget w, WindowInfo *window, caddr_t callData);
675 @@ -160,9 +160,9 @@ static void tabsDefCB(Widget w, WindowIn
676 static void showMatchingOffDefCB(Widget w, WindowInfo *window, caddr_t callData);
677 static void showMatchingDelimitDefCB(Widget w, WindowInfo *window, caddr_t callData);
678 static void showMatchingRangeDefCB(Widget w, WindowInfo *window, caddr_t callData);
679 -static void matchSyntaxBasedDefCB(Widget w, WindowInfo *window, caddr_t callData);
680 static void highlightOffDefCB(Widget w, WindowInfo *window, caddr_t callData);
681 static void highlightDefCB(Widget w, WindowInfo *window, caddr_t callData);
682 +static void matchPatternsDefCB(Widget w, WindowInfo *window, caddr_t callData);
683 static void backlightCharsDefCB(Widget w, WindowInfo *window, caddr_t callData);
684 static void fontDefCB(Widget w, WindowInfo *window, caddr_t callData);
685 static void colorDefCB(Widget w, WindowInfo *window, caddr_t callData);
686 @@ -409,8 +409,6 @@ static void setIncrementalBackupAP(Widge
687 Cardinal *nArgs);
688 static void setShowMatchingAP(Widget w, XEvent *event, String *args,
689 Cardinal *nArgs);
690 -static void setMatchSyntaxBasedAP(Widget w, XEvent *event, String *args,
691 - Cardinal *nArgs);
692 static void setOvertypeModeAP(Widget w, XEvent *event, String *args,
693 Cardinal *nArgs);
694 static void setLockedAP(Widget w, XEvent *event, String *args,
695 @@ -584,7 +582,6 @@ static XtActionsRec Actions[] = {
696 #endif
697 {"set_incremental_backup", setIncrementalBackupAP},
698 {"set_show_matching", setShowMatchingAP},
699 - {"set_match_syntax_based", setMatchSyntaxBasedAP},
700 {"set_overtype_mode", setOvertypeModeAP},
701 {"set_locked", setLockedAP},
702 {"set_transient", setTransientAP},
703 @@ -1030,9 +1027,8 @@ Widget CreateMenuBar(Widget parent, Wind
704 "range", "Range", 'R', showMatchingRangeDefCB, window,
705 GetPrefShowMatching() == FLASH_RANGE, SHORT);
706 createMenuSeparator(subSubPane, "sep", SHORT);
707 - window->matchSyntaxBasedDefItem = createMenuToggle(subSubPane,
708 - "matchSyntax", "Syntax Based", 'S', matchSyntaxBasedDefCB, window,
709 - GetPrefMatchSyntaxBased(), SHORT);
710 + createMenuItem(subSubPane, "matchPatterns", "Matching Patterns...",
711 + 'M', matchPatternsDefCB, window, FULL);
713 /* Show Cursorline */
714 window->showCursorlineItem = createMenuToggle(subPane,
715 @@ -1154,10 +1150,6 @@ Widget CreateMenuBar(Widget parent, Wind
716 window->showMatchingRangeItem = createMenuRadioToggle(subPane, "range",
717 "Range", 'R', showMatchingRangeCB, window,
718 window->showMatchingStyle == FLASH_RANGE, SHORT);
719 - createMenuSeparator(subPane, "sep", SHORT);
720 - window->matchSyntaxBasedItem = createMenuToggle(subPane, "matchSyntax",
721 - "Syntax Based", 'S', matchSyntaxBasedCB, window,
722 - window->matchSyntaxBased, SHORT);
724 #ifndef SGI_CUSTOM
725 createMenuSeparator(menuPane, "sep2", SHORT);
726 @@ -1689,24 +1681,6 @@ static void showMatchingRangeCB(Widget w
727 ((XmAnyCallbackStruct *)callData)->event, params, 1);
730 -static void matchSyntaxBasedCB(Widget w, WindowInfo *window, caddr_t callData)
732 - Widget menu = MENU_WIDGET(w);
734 - window = WidgetToWindow(menu);
736 -#ifdef SGI_CUSTOM
737 - if (shortPrefAskDefault(window->shell, w, "Match Syntax Based")) {
738 - matchSyntaxBasedDefCB(w, window, callData);
739 - SaveNEditPrefs(window->shell, GetPrefShortMenus());
741 -#endif
742 - HidePointerOnKeyedEvent(WidgetToWindow(menu)->lastFocus,
743 - ((XmAnyCallbackStruct *)callData)->event);
744 - XtCallActionProc(WidgetToWindow(menu)->lastFocus, "set_match_syntax_based",
745 - ((XmAnyCallbackStruct *)callData)->event, NULL, 0);
748 static void fontCB(Widget w, WindowInfo *window, caddr_t callData)
750 ChooseFonts(WidgetToWindow(MENU_WIDGET(w)), True);
751 @@ -2034,18 +2008,14 @@ static void showMatchingRangeDefCB(Widge
755 -static void matchSyntaxBasedDefCB(Widget w, WindowInfo *window, caddr_t callData)
756 +static void matchPatternsDefCB(Widget w, WindowInfo *window, caddr_t callData)
758 - WindowInfo *win;
760 - int state = XmToggleButtonGetState(w);
761 + Widget menu = MENU_WIDGET(w);
762 + WindowInfo *activeWindow = WidgetToWindow(menu);
764 - /* Set the preference and make the other windows' menus agree */
765 - SetPrefMatchSyntaxBased(state);
766 - for (win=WindowList; win!=NULL; win=win->next) {
767 - if (IsTopDocument(win))
768 - XmToggleButtonSetState(win->matchSyntaxBasedDefItem, state, False);
770 + HidePointerOnKeyedEvent(activeWindow->lastFocus,
771 + ((XmAnyCallbackStruct *)callData)->event);
772 + EditMatchPatterns(activeWindow);
775 static void backlightCharsDefCB(Widget w, WindowInfo *window, caddr_t callData)
776 @@ -4288,19 +4258,6 @@ static void setShowMatchingAP(Widget w,
780 -static void setMatchSyntaxBasedAP(Widget w, XEvent *event, String *args,
781 - Cardinal *nArgs)
783 - WindowInfo *window = WidgetToWindow(w);
784 - Boolean newState;
786 - ACTION_BOOL_PARAM_OR_TOGGLE(newState, *nArgs, args, window->matchSyntaxBased, "set_match_syntax_based");
788 - if (IsTopDocument(window))
789 - XmToggleButtonSetState(window->matchSyntaxBasedItem, newState, False);
790 - window->matchSyntaxBased = newState;
793 static void setOvertypeModeAP(Widget w, XEvent *event, String *args,
794 Cardinal *nArgs)
796 diff --quilt old/source/nedit.h new/source/nedit.h
797 --- old/source/nedit.h
798 +++ new/source/nedit.h
799 @@ -366,7 +366,6 @@ typedef struct _WindowInfo {
800 Widget showMatchingOffItem;
801 Widget showMatchingDelimitItem;
802 Widget showMatchingRangeItem;
803 - Widget matchSyntaxBasedItem;
804 Widget overtypeModeItem;
805 Widget highlightItem;
806 Widget windowMenuPane;
807 @@ -392,7 +391,6 @@ typedef struct _WindowInfo {
808 Widget showMatchingOffDefItem;
809 Widget showMatchingDelimitDefItem;
810 Widget showMatchingRangeDefItem;
811 - Widget matchSyntaxBasedDefItem;
812 Widget highlightOffDefItem;
813 Widget highlightDefItem;
814 Widget backlightCharsItem;
815 @@ -512,7 +510,6 @@ typedef struct _WindowInfo {
816 char showMatchingStyle; /* How to show matching parens:
817 NO_FLASH, FLASH_DELIMIT, or
818 FLASH_RANGE */
819 - char matchSyntaxBased; /* Use syntax info to show matching */
820 Boolean showStats; /* is stats line supposed to be shown */
821 Boolean showISearchLine; /* is incr. search line to be shown */
822 Boolean showLineNumbers; /* is the line number display shown */
823 @@ -558,6 +555,9 @@ typedef struct _WindowInfo {
824 Bool findLastRegexCase; /* idem, for regex mode in find dialog */
825 Bool findLastLiteralCase; /* idem, for literal mode */
827 + /* Pattern Match Feature */
828 + void *stringMatchTable; /* match pattern info related to this window */
830 #ifdef REPLACE_SCOPE
831 int replaceScope; /* Current scope for replace dialog */
832 Widget replaceScopeWinToggle; /* Scope for replace = window */
833 diff --quilt /dev/null new/source/patternMatch.c
834 --- /dev/null
835 +++ new/source/patternMatch.c
836 @@ -0,0 +1,2202 @@
837 +static const char CVSID[] = "$Id: patternMatch.c,v 1.4 2003/10/27 21:59:14 uleh Exp $";
838 +/*******************************************************************************
839 +* *
840 +* patternMatch.c -- Nirvana Editor pattern matching functions *
841 +* *
842 +* Copyright (C) 2003-2004, Uwe Lehnert *
843 +* *
844 +* This is free software; you can redistribute it and/or modify it under the *
845 +* terms of the GNU General Public License as published by the Free Software *
846 +* Foundation; either version 2 of the License, or (at your option) any later *
847 +* version. In addition, you may distribute versions of this program linked to *
848 +* Motif or Open Motif. See README for details. *
849 +* *
850 +* This software is distributed in the hope that it will be useful, but WITHOUT *
851 +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
852 +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
853 +* for more details. *
854 +* *
855 +* You should have received a copy of the GNU General Public License along with *
856 +* software; if not, write to the Free Software Foundation, Inc., 59 Temple *
857 +* Place, Suite 330, Boston, MA 02111-1307 USA *
858 +* *
859 +* Nirvana Text Editor *
860 +* October 27, 2004 *
861 +* *
862 +* Written by Uwe Lehnert *
863 +* *
864 +*******************************************************************************/
866 +#ifdef HAVE_CONFIG_H
867 +#include "../config.h"
868 +#endif
870 +#include <stdlib.h>
871 +#include <stdio.h>
872 +#include <limits.h>
873 +#include <string.h>
874 +#include <ctype.h>
876 +#ifdef VMS
877 +#include "../util/VMSparam.h"
878 +#else
879 +#ifndef __MVS__
880 +#include <sys/param.h>
881 +#endif
882 +#endif /*VMS*/
884 +#include "regularExp.h"
885 +#include "textBuf.h"
886 +#include "search.h"
887 +#include "window.h"
888 +#include "preferences.h"
889 +#include "highlight.h"
891 +#include "patternMatch.h"
892 +#include "patternMatchData.h"
894 +#ifdef HAVE_DEBUG_H
895 +#include "../debug.h"
896 +#endif
898 +#define MAX_NESTED_PATTERNS 100
900 +#define IGNORE_HIGHLIGHT_CODE -1
902 +typedef struct _SearchRegionInfo {
903 + WindowInfo *sriWindow;
904 + char *sriText;
905 + char sriPrevChar;
906 + char sriSuccChar;
907 + int sriStartOfTextPos;
908 +} SearchRegionInfo;
910 +typedef struct _FoundStringInfo {
911 + char *fsiStartPtr;
912 + char *fsiEndPtr;
913 + int fsiLength;
914 + char fsiPrevChar;
915 + char fsiSuccChar;
916 + const char *fsiDelimiters;
917 +} FoundStringInfo;
919 +typedef struct _BackRefInfo {
920 + int briAvailable;
921 + int briCaseInsensitive;
922 + char *briStartPtr[MAX_GLOBAL_BACK_REF_ID];
923 + char *briEndPtr[MAX_GLOBAL_BACK_REF_ID];
924 +} BackRefInfo;
926 +typedef struct _MatchingElementInfo {
927 + MatchPatternTableElement *meiElement;
928 + PatternReference meiPatRef;
929 + int meiDirection;
930 + int meiHighLightCode;
931 + int meiAbsStartPos;
932 + int meiLength;
933 + BackRefInfo meiBackRefInfo;
934 +} MatchingElementInfo;
936 +typedef struct _PatternStackElement {
937 + PatternReference psePatRef;
938 + int pseHighLightCode;
939 + BackRefInfo pseBackRefInfo;
940 +} PatternStackElement;
943 + * Prototypes of local functions
944 + */
945 +void adaptPatternPositions(
946 + MatchingType matchingType,
947 + int direction,
948 + int *charPos,
949 + int startPatternLength,
950 + int *matchPos,
951 + int matchedPatternLength);
953 +static int findMatchingStringElement(
954 + StringMatchTable *smTable,
955 + SearchRegionInfo *searchRegion,
956 + MatchingElementInfo *matchInfo,
957 + int *charPos,
958 + const char *delimiters);
960 +static PatternElementMonoInfo determineMonoPatInfo(
961 + WindowInfo *window,
962 + int patHighLightCode,
963 + int leftPos,
964 + int rightPos,
965 + PatternElementKind *patElementKind);
967 +static void assignBackRefInfo(
968 + StringPattern *strPat,
969 + BackRefInfo *backRefInfo);
970 +static int doesBackRefInfoMatch(
971 + BackRefInfo *backRefInfo1,
972 + BackRefInfo *backRefInfo2);
973 +static int compareBackRef(
974 + char *startPtr1,
975 + char *endPtr1,
976 + char *startPtr2,
977 + char *endPtr2,
978 + int caseInsensitive);
980 +static int doesPatternElementMatch(
981 + PatternElement *patElement,
982 + FoundStringInfo *foundStringInfo,
983 + BackRefInfo *backRefInfo);
984 +static int doesMPTableElementMatch(
985 + MatchPatternTableElement *element,
986 + FoundStringInfo *foundStringInfo,
987 + PatternElementKind *patternElementKind,
988 + int *patternElementIdx,
989 + BackRefInfo *backRefInfo);
990 +static int getPatternInfo(
991 + MatchPatternTable *table,
992 + FoundStringInfo *foundStringInfo,
993 + PatternReference *patRef,
994 + BackRefInfo *backRefInfo);
996 +static int isPartOfPattern(
997 + MatchPatternTable *table,
998 + int parentElementIdx,
999 + int childElementIdx,
1000 + PatternElementKind patElementKind);
1001 +static int isPartOfPatternElementSet(
1002 + PatternElementSet *patElementSet,
1003 + int patternElementIdx);
1004 +static int isPartOfMiddlePatternElementSet(
1005 + PatternElementSet *patElementSet,
1006 + int patternElementIdx);
1007 +static void considerNextPatternReference(
1008 + MatchPatternTable *table,
1009 + PatternReference *startPatRef,
1010 + PatternReference nxtPatRef,
1011 + int groupIdx);
1013 +static int searchPatternForward(
1014 + MatchPatternTable *table,
1015 + regexp *compiledRE,
1016 + SearchRegionInfo *searchRegion,
1017 + const char *delimiters,
1018 + int beginPos,
1019 + int *matchEndPos,
1020 + PatternReference *patRef,
1021 + int *highLightCode,
1022 + BackRefInfo *backRefInfo);
1023 +static int searchPatternBackward(
1024 + MatchPatternTable *table,
1025 + regexp *compiledRE,
1026 + SearchRegionInfo *searchRegion,
1027 + const char *delimiters,
1028 + int beginPos,
1029 + PatternReference *patRef,
1030 + int *highLightCode,
1031 + int *matchedPatternLength,
1032 + BackRefInfo *backRefInfo);
1034 +static int parseStringElementForward(
1035 + MatchingElementInfo *matchInfo,
1036 + SearchRegionInfo *searchRegion,
1037 + int relCharPos,
1038 + int *matchPos,
1039 + int *matchedPatternLength,
1040 + const char *delimiters);
1041 +static int findRelatedForwardPattern(
1042 + StringMatchTable *table,
1043 + SearchRegionInfo *searchRegion,
1044 + const char *delimiters,
1045 + PatternReference beginPatRef,
1046 + int beginPatHighLightCode,
1047 + BackRefInfo *beginPatBackRefInfo,
1048 + int beginPos,
1049 + int *matchEndPos);
1051 +static int parseStringElementBackward(
1052 + MatchingElementInfo *matchInfo,
1053 + SearchRegionInfo *searchRegion,
1054 + int relCharPos,
1055 + int *matchPos,
1056 + int *matchedPatternLength,
1057 + const char *delimiters);
1058 +static int findRelatedStartPattern(
1059 + StringMatchTable *table,
1060 + SearchRegionInfo *searchRegion,
1061 + const char *delimiters,
1062 + PatternReference beginPatRef,
1063 + int beginPatHighLightCode,
1064 + BackRefInfo *beginPatBackRefInfo,
1065 + int beginPos,
1066 + int *matchedPatternLength);
1067 +static void considerStackPatReference(
1068 + PatternElementSet *patSet,
1069 + int stackElementIdx,
1070 + int *foundElementIdx);
1072 +static int getPatternLocatedAtPos(
1073 + regexp *usedPatRE,
1074 + MatchPatternTable *table,
1075 + SearchRegionInfo *searchRegion,
1076 + int *relBeginPos,
1077 + MatchingElementInfo *matchInfo,
1078 + const char *delimiters);
1079 +static int getMatchedElementInfo(
1080 + WindowInfo *window,
1081 + MatchPatternTable *table,
1082 + FoundStringInfo *foundStringInfo,
1083 + MatchingElementInfo *matchInfo);
1085 +static PatternElement *getPatternOfReference(
1086 + MatchPatternTable *table,
1087 + PatternReference patRef);
1089 +#ifdef DEBUG_FIND
1090 +static char *getPatternForDebug(
1091 + MatchPatternTable *table,
1092 + PatternReference patRef );
1093 +static char *patElemKindToString(
1094 + PatternElementKind patElemKind);
1095 +static void printFoundStringForDebug(
1096 + WindowInfo *window,
1097 + int absStartPos,
1098 + int length);
1099 +#endif
1102 +** Try to find a matching pattern string related to the given "charPos"
1103 +** inside the given range (defined by startLimit & endLimit).
1104 +** Determine the matching position & the match pattern length (depending
1105 +** on given matchingType), if a matching pattern was found.
1106 +** Returns true, if a matching pattern string was found.
1108 +int FindMatchingString(
1109 + WindowInfo *window,
1110 + MatchingType matchingType,
1111 + int *charPos,
1112 + int startLimit,
1113 + int endLimit,
1114 + int *matchPos,
1115 + int *matchedPatternLength,
1116 + int *direction)
1118 + StringMatchTable *smTable = (StringMatchTable *)window->stringMatchTable;
1119 + const char *delimiters;
1120 + SearchRegionInfo searchRegion;
1121 + MatchingElementInfo matchInfo;
1122 + int matchingPatternFound = FALSE;
1123 + int relCharPos;
1125 + if (smTable == NULL || smTable->smtAllPatRE == NULL)
1127 + /*
1128 + * No match pattern table available:
1129 + */
1130 + return FALSE;
1133 + /*
1134 + * Get delimiters related to window
1135 + */
1136 + delimiters = GetWindowDelimiters(window);
1137 + if (delimiters == NULL)
1138 + delimiters = GetPrefDelimiters();
1140 + /*
1141 + * Select the start pattern reg. exp. to use
1142 + */
1143 + if (matchingType == MT_FLASH_RANGE ||
1144 + matchingType == MT_FLASH_DELIMIT)
1146 + smTable->smtUsedPatRE = smTable->smtFlashPatRE;
1148 + else
1150 + smTable->smtUsedPatRE = smTable->smtAllPatRE;
1153 + /*
1154 + * Get a copy of the text buffer area to parse
1155 + */
1156 + searchRegion.sriWindow = window;
1157 + searchRegion.sriText = BufGetRange(window->buffer, startLimit, endLimit);
1158 + searchRegion.sriPrevChar = BufGetCharacter(window->buffer, startLimit - 1);
1159 + searchRegion.sriSuccChar = BufGetCharacter(window->buffer, endLimit);
1160 + searchRegion.sriStartOfTextPos = startLimit;
1162 + relCharPos = *charPos - startLimit;
1164 + /*
1165 + * Try to find a matching pattern string using string match table
1166 + * of window
1167 + */
1168 + if (findMatchingStringElement(
1169 + smTable,
1170 + &searchRegion,
1171 + &matchInfo,
1172 + &relCharPos,
1173 + delimiters ))
1175 +#ifdef DEBUG_FIND
1176 + printf("--- Start at : ");
1177 + printFoundStringForDebug(
1178 + window,
1179 + matchInfo.meiAbsStartPos,
1180 + matchInfo.meiLength);
1181 + printf(" ---\n");
1182 +#endif
1183 + if (matchInfo.meiDirection == SEARCH_FORWARD)
1185 + matchingPatternFound =
1186 + parseStringElementForward(
1187 + &matchInfo,
1188 + &searchRegion,
1189 + relCharPos,
1190 + matchPos,
1191 + matchedPatternLength,
1192 + delimiters );
1194 + else
1196 + matchingPatternFound =
1197 + parseStringElementBackward(
1198 + &matchInfo,
1199 + &searchRegion,
1200 + relCharPos,
1201 + matchPos,
1202 + matchedPatternLength,
1203 + delimiters );
1206 + if (matchingPatternFound)
1208 + /*
1209 + * Calc. abs. start char pos. (may have been changed if
1210 + * cursor was located inside a string pattern). Adapt
1211 + * pattern positions depending on matchingType.
1212 + */
1213 + *charPos = relCharPos + startLimit;
1214 + *direction = matchInfo.meiDirection;
1216 + adaptPatternPositions(
1217 + matchingType,
1218 + matchInfo.meiDirection,
1219 + charPos,
1220 + matchInfo.meiLength,
1221 + matchPos,
1222 + *matchedPatternLength);
1226 + XtFree(searchRegion.sriText);
1228 + return matchingPatternFound;
1232 +** Adapt match pattern position / start position depending on the
1233 +** given matching type.
1235 +void adaptPatternPositions(
1236 + MatchingType matchingType,
1237 + int direction,
1238 + int *charPos,
1239 + int startPatternLength,
1240 + int *matchPos,
1241 + int matchedPatternLength)
1243 + switch (matchingType)
1245 + case MT_FLASH_DELIMIT:
1246 + case MT_MACRO:
1247 + if (direction == SEARCH_FORWARD)
1249 + (*matchPos) -= matchedPatternLength - 1;
1251 + break;
1253 + case MT_FLASH_RANGE:
1254 + case MT_SELECT:
1255 + if (direction == SEARCH_FORWARD)
1257 + (*charPos) -= startPatternLength;
1259 + else
1261 + (*charPos) --;
1263 + break;
1265 + case MT_GOTO:
1266 + if (direction == SEARCH_FORWARD)
1268 + (*matchPos) ++;
1270 + else
1272 + (*matchPos) += matchedPatternLength;
1274 + break;
1279 +** Try to find a string pattern at given buffer position 'charPos'.
1280 +** A string pattern is found, if pattern is located before 'charPos' or
1281 +** 'charPos' is located within a pattern.
1282 +** If a string pattern is found, then search direction and string pattern
1283 +** reference / properties are determined.
1284 +** Returns true, if a string pattern was found.
1286 +static int findMatchingStringElement(
1287 + StringMatchTable *smTable,
1288 + SearchRegionInfo *searchRegion,
1289 + MatchingElementInfo *matchInfo,
1290 + int *charPos,
1291 + const char *delimiters)
1293 + if (getPatternLocatedAtPos(
1294 + smTable->smtUsedPatRE,
1295 + smTable->smtAllPatterns,
1296 + searchRegion,
1297 + charPos,
1298 + matchInfo,
1299 + delimiters))
1301 + /*
1302 + * Pattern found -> define search direction:
1303 + * - START & MIDDLE pattern: matching pattern is searched in
1304 + * forward direction
1305 + * - END pattern: matching pattern is searched in backward
1306 + * direction
1307 + */
1308 + if (matchInfo->meiPatRef.prKind == PEK_END)
1309 + matchInfo->meiDirection = SEARCH_BACKWARD;
1310 + else
1311 + matchInfo->meiDirection = SEARCH_FORWARD;
1313 + return TRUE;
1316 + return FALSE;
1320 +** Return mono pattern info depending on highlight codes
1321 +** of left / right side of string pattern. Update pattern
1322 +** kind if applicable.
1324 +static PatternElementMonoInfo determineMonoPatInfo(
1325 + WindowInfo *window,
1326 + int patHighLightCode,
1327 + int leftPos,
1328 + int rightPos,
1329 + PatternElementKind *patElementKind)
1331 + int leftSideHasSameHC;
1332 + int rightSideHasSameHC;
1334 + /*
1335 + * Determine, if left side holds same highlight code than
1336 + * found string pattern
1337 + */
1338 + if (leftPos >= 0)
1339 + leftSideHasSameHC =
1340 + (HighlightCodeOfPos(window, leftPos) == patHighLightCode);
1341 + else
1342 + leftSideHasSameHC = FALSE;
1344 + /*
1345 + * Determine, if right side holds same highlight code than
1346 + * found string pattern
1347 + */
1348 + if (rightPos < window->buffer->length)
1349 + rightSideHasSameHC =
1350 + (HighlightCodeOfPos(window, rightPos) == patHighLightCode);
1351 + else
1352 + rightSideHasSameHC = FALSE;
1354 + if ((rightSideHasSameHC && leftSideHasSameHC) ||
1355 + (!rightSideHasSameHC && !leftSideHasSameHC))
1357 + return PEMI_MONO_AMBIGUOUS_SYNTAX;
1359 + else if (leftSideHasSameHC)
1361 + *patElementKind = PEK_END;
1362 + return PEMI_MONO_DEFINITE_SYNTAX;
1364 + else
1366 + *patElementKind = PEK_START;
1367 + return PEMI_MONO_DEFINITE_SYNTAX;
1372 +** Get backref info out of found string pattern and
1373 +** put it into given backRefInfo.
1375 +static void assignBackRefInfo(
1376 + StringPattern *strPat,
1377 + BackRefInfo *backRefInfo)
1379 + int i;
1380 + int localId;
1381 + regexp *patRE = strPat->spTextRE;
1383 + backRefInfo->briAvailable = FALSE;
1384 + backRefInfo->briCaseInsensitive = strPat->spCaseInsensitive;
1386 + for (i=0; i<MAX_GLOBAL_BACK_REF_ID; i++)
1388 + localId = strPat->spGlobalToLocalBackRef[i];
1390 + if (localId != NO_LOCAL_BACK_REF_ID)
1392 + backRefInfo->briAvailable = TRUE;
1394 + backRefInfo->briStartPtr[i] = patRE->startp[localId];
1395 + backRefInfo->briEndPtr[i] = patRE->endp[localId];
1397 + else
1399 + backRefInfo->briStartPtr[i] = NULL;
1400 + backRefInfo->briEndPtr[i] = NULL;
1406 +** Check, if given backref infos match.
1407 +** Returns true, if backref infos match.
1409 +static int doesBackRefInfoMatch(
1410 + BackRefInfo *backRefInfo1,
1411 + BackRefInfo *backRefInfo2)
1413 + int i;
1415 + /*
1416 + * if min. one string pattern doesn't hold backref info, then nothing
1417 + * could be compared -> both string pattern are matching.
1418 + */
1419 + if (!backRefInfo1->briAvailable || !backRefInfo2->briAvailable)
1420 + return TRUE;
1422 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
1424 + if (!compareBackRef(
1425 + backRefInfo1->briStartPtr[i],
1426 + backRefInfo1->briEndPtr[i],
1427 + backRefInfo2->briStartPtr[i],
1428 + backRefInfo2->briEndPtr[i],
1429 + backRefInfo1->briCaseInsensitive || backRefInfo2->briCaseInsensitive))
1431 + return FALSE;
1435 + return TRUE;
1439 +** Compares two backref content.
1440 +** Returns true, if backref contents match.
1442 +static int compareBackRef(
1443 + char *startPtr1,
1444 + char *endPtr1,
1445 + char *startPtr2,
1446 + char *endPtr2,
1447 + int caseInsensitive)
1449 + char *s1;
1450 + char *s2;
1452 + if (startPtr1 == NULL && startPtr2 == NULL)
1453 + return TRUE;
1455 + if (startPtr1 == NULL || startPtr2 == NULL)
1456 + return FALSE;
1458 + if ((endPtr1 - startPtr1) != (endPtr2 - startPtr2))
1459 + return FALSE;
1461 + s1 = startPtr1;
1462 + s2 = startPtr2;
1464 + if (caseInsensitive)
1466 + while (s1 != endPtr1)
1468 + if (tolower((unsigned char)*s1++) != tolower((unsigned char)*s2++))
1469 + return FALSE;
1472 + else
1474 + while (s1 != endPtr1)
1476 + if (*s1++ != *s2++)
1477 + return FALSE;
1480 + return TRUE;
1484 +** Verify if given pattern element is located between given
1485 +** start / end pointer of "foundStringInfo". Assign backreference
1486 +** information, if pattern element matches.
1487 +** Returns true, if given pattern element matches.
1489 +static int doesPatternElementMatch(
1490 + PatternElement *patElement,
1491 + FoundStringInfo *foundStringInfo,
1492 + BackRefInfo *backRefInfo)
1494 + char *s;
1495 + char *p;
1496 + StringPattern *strPat;
1497 + int elementMatch;
1499 + switch (patElement->peType)
1501 + case PET_SINGLE:
1502 + strPat = &patElement->peVal.peuSingle;
1503 + break;
1504 + case PET_MULTIPLE:
1505 + strPat = &patElement->peVal.peuMulti.mpStringPattern;
1506 + break;
1507 + default:
1508 + return FALSE;
1511 + if (strPat->spRegularExpression)
1513 + /*
1514 + * check reg. expression:
1515 + */
1516 + elementMatch =
1517 + ExecRE(
1518 + strPat->spTextRE,
1519 + foundStringInfo->fsiStartPtr,
1520 + foundStringInfo->fsiEndPtr,
1521 + FALSE,
1522 + foundStringInfo->fsiPrevChar,
1523 + foundStringInfo->fsiSuccChar,
1524 + foundStringInfo->fsiDelimiters,
1525 + NULL,
1526 + NULL);
1528 + if (elementMatch)
1529 + assignBackRefInfo(strPat, backRefInfo);
1531 + return elementMatch;
1533 + else
1535 + backRefInfo->briAvailable = FALSE;
1537 + /*
1538 + * check literal string:
1539 + */
1540 + p = strPat->spText;
1542 + /*
1543 + * if length of found string is different from length of
1544 + * given string pattern, then there is no match.
1545 + */
1546 + if (strPat->spLength != foundStringInfo->fsiLength)
1547 + return FALSE;
1549 + s = foundStringInfo->fsiStartPtr;
1551 + if (strPat->spCaseInsensitive)
1553 + while (s != foundStringInfo->fsiEndPtr)
1555 + if (tolower((unsigned char)*s++) != *p++)
1556 + return FALSE;
1559 + else
1561 + while (s != foundStringInfo->fsiEndPtr)
1563 + if (*s++ != *p++)
1564 + return FALSE;
1569 + return TRUE;
1573 +** Verify if a pattern element of given MatchPatternTableElement is
1574 +** located between given start / end pointer of "foundStringInfo".
1575 +** Returns true, if so.
1577 +static int doesMPTableElementMatch(
1578 + MatchPatternTableElement *element,
1579 + FoundStringInfo *foundStringInfo,
1580 + PatternElementKind *patternElementKind,
1581 + int *patternElementIdx,
1582 + BackRefInfo *backRefInfo)
1584 + int i;
1586 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i ++)
1588 + if (doesPatternElementMatch(
1589 + element->mpteAll.pesPattern[i],
1590 + foundStringInfo,
1591 + backRefInfo))
1593 + *patternElementKind = element->mpteAll.pesPattern[i]->peKind;
1594 + *patternElementIdx = i;
1596 + return TRUE;
1600 + return FALSE;
1604 +** Determine the pattern element of given MatchPatternTable, which is
1605 +** located between given start / end pointer of "foundStringInfo".
1606 +** Setup related pattern element reference.
1607 +** Returns true, if a pattern element was found.
1609 +static int getPatternInfo(
1610 + MatchPatternTable *table,
1611 + FoundStringInfo *foundStringInfo,
1612 + PatternReference *patRef,
1613 + BackRefInfo *backRefInfo)
1615 + int i;
1617 + for (i=0; i<table->mptNumberOfElements; i++)
1619 + if (doesMPTableElementMatch(
1620 + table->mptElements[i],
1621 + foundStringInfo,
1622 + &patRef->prKind,
1623 + &patRef->prPatternIdx,
1624 + backRefInfo))
1626 + patRef->prElementIdx = i;
1628 + return TRUE;
1632 + /*
1633 + * Should never been reached !
1634 + */
1635 + patRef->prElementIdx = NO_ELEMENT_IDX;
1636 + patRef->prKind = PEK_UNKNOWN;
1637 + patRef->prPatternIdx = NO_PATTERN_IDX;
1639 + return FALSE;
1643 +** Check, if given child pattern element is part of given
1644 +** parent pattern element.
1645 +** Returns true, if child is part of parent.
1647 +static int isPartOfPattern(
1648 + MatchPatternTable *table,
1649 + int parentElementIdx,
1650 + int childElementIdx,
1651 + PatternElementKind patElementKind)
1653 + MatchPatternTableElement *parent = table->mptElements[parentElementIdx];
1654 + MatchPatternTableElement *child = table->mptElements[childElementIdx];
1656 + if (childElementIdx == parentElementIdx)
1657 + return TRUE;
1659 + if (patElementKind == PEK_START)
1661 + if (isPartOfPatternElementSet(&parent->mpteStart, childElementIdx))
1662 + return TRUE;
1664 + return( isPartOfPatternElementSet(&child->mpteStart, parentElementIdx) );
1666 + else if (patElementKind == PEK_END)
1668 + if (isPartOfPatternElementSet(&parent->mpteEnd, childElementIdx))
1669 + return TRUE;
1671 + return( isPartOfPatternElementSet(&child->mpteEnd, parentElementIdx) );
1673 + else
1675 + /*
1676 + * Given child pattern element is middle pattern: the given pattern element
1677 + * is part of parent pattern, if it's a reference of a middle pattern
1678 + */
1679 + if (isPartOfMiddlePatternElementSet(&parent->mpteMiddle, childElementIdx))
1680 + return TRUE;
1682 + return( isPartOfMiddlePatternElementSet(&child->mpteMiddle, parentElementIdx) );
1687 +** Check, if given pattern element is part of given pattern element set.
1688 +** Returns true, if so.
1690 +static int isPartOfPatternElementSet(
1691 + PatternElementSet *patElementSet,
1692 + int patternElementIdx)
1694 + PatternElement *patElement;
1695 + int i;
1697 + for (i=0; i<patElementSet->pesNumberOfPattern; i++)
1699 + if (patElementSet->pesPattern[i]->peType == PET_REFERENCE)
1701 + patElement = patElementSet->pesPattern[i];
1703 + if (patElement->peVal.peuRef.prElementIdx == patternElementIdx)
1705 + return TRUE;
1710 + return FALSE;
1714 +** Verify, if given pattern element is part of middle pattern set.
1715 +** That's the case, if an element of the pattern set is reference
1716 +** of a middle pattern, which fits to given pattern element.
1717 +** Returns true, if pattern element is part of middle pattern set.
1718 + */
1719 +static int isPartOfMiddlePatternElementSet(
1720 + PatternElementSet *patElementSet,
1721 + int patternElementIdx)
1723 + PatternElement *patElement;
1724 + int i;
1726 + for (i=0; i<patElementSet->pesNumberOfPattern; i++)
1728 + if (patElementSet->pesPattern[i]->peType == PET_REFERENCE)
1730 + patElement = patElementSet->pesPattern[i];
1732 + if (patElement->peVal.peuRef.prElementIdx == patternElementIdx &&
1733 + patElement->peKind == PEK_MIDDLE)
1735 + return TRUE;
1740 + return FALSE;
1744 +** Update start pattern reference depending on next pattern located
1745 +** after start pattern.
1747 +static void considerNextPatternReference(
1748 + MatchPatternTable *table,
1749 + PatternReference *startPatRef,
1750 + PatternReference nxtPatRef,
1751 + int groupIdx)
1753 + MatchPatternTableElement *tabElement;
1754 + PatternElement *startPat;
1755 + MultiPattern *multiStartPat;
1756 + PatternReference patRef;
1757 + int i;
1759 + /*
1760 + * startPatRef needs no adaption, if element index of start pattern
1761 + * and next pattern are equal (i.e. start and next pattern belong
1762 + * to same pattern element).
1763 + */
1764 + if (startPatRef->prElementIdx == nxtPatRef.prElementIdx)
1765 + return;
1767 + /*
1768 + * Verify, if start pattern belongs to multiple pattern elements
1769 + * (like "ELSE .. FI" & "ELSE .. ESAC").
1770 + */
1771 + startPat = getPatternOfReference( table, *startPatRef );
1773 + if (startPat->peType == PET_MULTIPLE)
1775 + /*
1776 + * Check, if next pattern fits to one of the references of
1777 + * the start multi pattern. If so: adapt start pattern reference.
1778 + */
1779 + multiStartPat = &startPat->peVal.peuMulti;
1781 + for (i=0; i<multiStartPat->mpNumberOfReferences; i ++)
1783 + patRef = multiStartPat->mpRefList[i];
1784 + tabElement = table->mptElements[patRef.prElementIdx];
1786 + if (nxtPatRef.prElementIdx == patRef.prElementIdx &&
1787 + tabElement->mpteGroup == groupIdx)
1789 + *startPatRef = patRef;
1790 + return;
1797 +** Search for a string pattern in forward direction, starting at
1798 +** given beginPos. Determine related pattern reference of a found
1799 +** string pattern.
1800 +** Returns true, if a next string pattern was found.
1802 +static int searchPatternForward(
1803 + MatchPatternTable *table,
1804 + regexp *compiledRE,
1805 + SearchRegionInfo *searchRegion,
1806 + const char *delimiters,
1807 + int beginPos,
1808 + int *matchEndPos,
1809 + PatternReference *patRef,
1810 + int *highLightCode,
1811 + BackRefInfo *backRefInfo)
1813 + FoundStringInfo foundStringInfo;
1814 + int matchStartPos;
1815 + int absMatchStartPos;
1816 + MatchPatternTableElement *matchedElement;
1818 + *matchEndPos = -1;
1820 + patRef->prElementIdx = NO_ELEMENT_IDX;
1821 + patRef->prKind = PEK_UNKNOWN;
1822 + patRef->prPatternIdx = NO_PATTERN_IDX;
1824 + *highLightCode = IGNORE_HIGHLIGHT_CODE;
1826 + if (ExecRE(
1827 + compiledRE,
1828 + searchRegion->sriText + beginPos,
1829 + NULL,
1830 + FALSE,
1831 + beginPos==0 ? searchRegion->sriPrevChar : searchRegion->sriText[beginPos-1],
1832 + searchRegion->sriSuccChar,
1833 + delimiters,
1834 + searchRegion->sriText,
1835 + NULL))
1837 + foundStringInfo.fsiStartPtr = compiledRE->startp[0];
1838 + foundStringInfo.fsiEndPtr = compiledRE->endp[0];
1839 + foundStringInfo.fsiLength =
1840 + foundStringInfo.fsiEndPtr - foundStringInfo.fsiStartPtr;
1842 + foundStringInfo.fsiPrevChar =
1843 + foundStringInfo.fsiStartPtr == searchRegion->sriText ?
1844 + searchRegion->sriPrevChar : *(foundStringInfo.fsiStartPtr - 1);
1846 + foundStringInfo.fsiSuccChar =
1847 + *(foundStringInfo.fsiEndPtr) == '\0' ?
1848 + searchRegion->sriSuccChar : *(foundStringInfo.fsiEndPtr);
1850 + foundStringInfo.fsiDelimiters = delimiters;
1852 + if (getPatternInfo(
1853 + table,
1854 + &foundStringInfo,
1855 + patRef,
1856 + backRefInfo))
1858 + /*
1859 + * Next string pattern was found in forward direction and
1860 + * a pattern reference could be assigned to: calculate
1861 + * relative & absolute match positions.
1862 + */
1863 + matchStartPos = foundStringInfo.fsiStartPtr - searchRegion->sriText;
1864 + *matchEndPos = foundStringInfo.fsiEndPtr - searchRegion->sriText;
1866 + absMatchStartPos = matchStartPos + searchRegion->sriStartOfTextPos;
1868 + matchedElement = table->mptElements[patRef->prElementIdx];
1870 + /*
1871 + * get highlight code of found string pattern, if applicable
1872 + */
1873 + if (!matchedElement->mpteIgnoreHighLightInfo)
1875 + *highLightCode =
1876 + HighlightCodeOfPos(searchRegion->sriWindow, absMatchStartPos);
1879 + /*
1880 + * setup mono pattern info of found string pattern
1881 + */
1882 + if (matchedElement->mpteIsMonoPattern)
1884 + if (matchedElement->mpteIgnoreHighLightInfo)
1886 + patRef->prMonoInfo = PEMI_MONO_NOT_SYNTAX_BASED;
1888 + else
1890 + /*
1891 + * determine mono pattern info depending on highLightCodes
1892 + * before / after found string pattern.
1893 + */
1894 + patRef->prMonoInfo =
1895 + determineMonoPatInfo(
1896 + searchRegion->sriWindow,
1897 + *highLightCode,
1898 + absMatchStartPos - 1,
1899 + *matchEndPos + searchRegion->sriStartOfTextPos,
1900 + &patRef->prKind);
1903 + else
1905 + patRef->prMonoInfo = PEMI_NOT_MONO;
1908 + return matchStartPos;
1910 + else
1912 + /*
1913 + * Found string can't be assigned to a pattern element
1914 + * (should never occur).
1915 + */
1916 + return -1;
1919 + else
1921 + /*
1922 + * No next string pattern is found in forward direction.
1923 + */
1924 + return -1;
1929 +** Search for a string pattern in backward direction, starting at
1930 +** given beginPos. Determine related pattern reference of a found
1931 +** string pattern.
1932 +** Returns true, if a next string pattern was found.
1934 +static int searchPatternBackward(
1935 + MatchPatternTable *table,
1936 + regexp *compiledRE,
1937 + SearchRegionInfo *searchRegion,
1938 + const char *delimiters,
1939 + int beginPos,
1940 + PatternReference *patRef,
1941 + int *highLightCode,
1942 + int *matchedPatternLength,
1943 + BackRefInfo *backRefInfo)
1945 + FoundStringInfo foundStringInfo;
1946 + int matchStartPos;
1947 + int absMatchStartPos;
1948 + MatchPatternTableElement *matchedElement;
1950 + patRef->prElementIdx = NO_ELEMENT_IDX;
1951 + patRef->prKind = PEK_UNKNOWN;
1952 + patRef->prPatternIdx = NO_PATTERN_IDX;
1954 + *highLightCode = IGNORE_HIGHLIGHT_CODE;
1956 + if (ExecRE(
1957 + compiledRE,
1958 + searchRegion->sriText,
1959 + searchRegion->sriText + beginPos,
1960 + TRUE,
1961 + searchRegion->sriPrevChar,
1962 + searchRegion->sriText[beginPos] == '\0' ?
1963 + searchRegion->sriSuccChar : searchRegion->sriText[beginPos + 1],
1964 + delimiters,
1965 + searchRegion->sriText,
1966 + NULL))
1968 + foundStringInfo.fsiStartPtr = compiledRE->startp[0];
1969 + foundStringInfo.fsiEndPtr = compiledRE->endp[0];
1970 + foundStringInfo.fsiLength =
1971 + foundStringInfo.fsiEndPtr - foundStringInfo.fsiStartPtr;
1973 + foundStringInfo.fsiPrevChar =
1974 + foundStringInfo.fsiStartPtr == searchRegion->sriText ?
1975 + searchRegion->sriPrevChar : *(foundStringInfo.fsiStartPtr - 1);
1977 + foundStringInfo.fsiSuccChar =
1978 + *(foundStringInfo.fsiEndPtr) == '\0' ?
1979 + searchRegion->sriSuccChar : *(foundStringInfo.fsiEndPtr);
1981 + foundStringInfo.fsiDelimiters = delimiters;
1983 + if (getPatternInfo(
1984 + table,
1985 + &foundStringInfo,
1986 + patRef,
1987 + backRefInfo))
1989 + /*
1990 + * Next string pattern was found in backward direction and
1991 + * a pattern reference could be assigned to: calculate
1992 + * relative & absolute match positions.
1993 + */
1994 + matchStartPos = foundStringInfo.fsiStartPtr - searchRegion->sriText;
1995 + *matchedPatternLength = foundStringInfo.fsiLength;
1997 + absMatchStartPos = matchStartPos + searchRegion->sriStartOfTextPos;
1999 + matchedElement = table->mptElements[patRef->prElementIdx];
2001 + /*
2002 + * get highlight code of found string pattern, if applicable
2003 + */
2004 + if (!matchedElement->mpteIgnoreHighLightInfo)
2006 + *highLightCode =
2007 + HighlightCodeOfPos(searchRegion->sriWindow, absMatchStartPos);
2010 + /*
2011 + * setup mono pattern info of found string pattern
2012 + */
2013 + if (matchedElement->mpteIsMonoPattern)
2015 + if (matchedElement->mpteIgnoreHighLightInfo)
2017 + patRef->prMonoInfo = PEMI_MONO_NOT_SYNTAX_BASED;
2019 + else
2021 + /*
2022 + * determine mono pattern info depending on highLightCodes
2023 + * before / after found string pattern.
2024 + */
2025 + patRef->prMonoInfo =
2026 + determineMonoPatInfo(
2027 + searchRegion->sriWindow,
2028 + *highLightCode,
2029 + absMatchStartPos - 1,
2030 + absMatchStartPos + *matchedPatternLength,
2031 + &patRef->prKind);
2034 + else
2036 + patRef->prMonoInfo = PEMI_NOT_MONO;
2039 + return matchStartPos;
2041 + else
2043 + /*
2044 + * Found string can't be assigned to a pattern element
2045 + * (should never occur).
2046 + */
2047 + return -1;
2050 + else
2052 + /*
2053 + * No next string pattern is found in backward direction.
2054 + */
2055 + return -1;
2060 +** Find matching pattern related to given pattern (stored in
2061 +** 'matchInfo') in forward direction by considering the rules stored in
2062 +** string match table of given window. Determine match position (= abs.
2063 +** pos. of last character of matching string) and length of matching
2064 +** string. If a mono matching pattern couldn't be found in forward
2065 +** direction, then try finding it in backward direction (if found in
2066 +** backward direction, then match position indicates the 1st char. of
2067 +** matching string).
2068 +** Returns true, if a matching pattern was found.
2070 +static int parseStringElementForward(
2071 + MatchingElementInfo *matchInfo,
2072 + SearchRegionInfo *searchRegion,
2073 + int relCharPos,
2074 + int *matchPos,
2075 + int *matchedPatternLength,
2076 + const char *delimiters)
2078 + StringMatchTable *smTable =
2079 + (StringMatchTable *)searchRegion->sriWindow->stringMatchTable;
2080 + MatchPatternTableElement *matchElement = matchInfo->meiElement;
2081 + int beginPos = relCharPos;
2082 + int endStartPos;
2083 + int startStartPos;
2084 + int endEndPos;
2085 + int matchingPatternFound = FALSE;
2087 + /*
2088 + * Find matching pattern within text buffer area to parse in
2089 + * forward direction.
2090 + */
2091 + endStartPos =
2092 + findRelatedForwardPattern(
2093 + smTable,
2094 + searchRegion,
2095 + delimiters,
2096 + matchInfo->meiPatRef,
2097 + matchInfo->meiHighLightCode,
2098 + &matchInfo->meiBackRefInfo,
2099 + beginPos,
2100 + &endEndPos);
2102 + if (endEndPos != -1)
2104 + *matchPos = endEndPos - 1 + searchRegion->sriStartOfTextPos;
2105 + *matchedPatternLength = endEndPos - endStartPos;
2107 + matchingPatternFound = TRUE;
2109 + else if (matchElement->mpteIsMonoPattern)
2111 + /*
2112 + * mono pattern: forward find fails -> try backward direction.
2113 + * Calc. relative position of 1st char. before found string pattern.
2114 + */
2115 + beginPos = beginPos - matchInfo->meiLength - 1;
2117 + if (beginPos > 0)
2119 + startStartPos =
2120 + findRelatedStartPattern(
2121 + smTable,
2122 + searchRegion,
2123 + delimiters,
2124 + matchInfo->meiPatRef,
2125 + matchInfo->meiHighLightCode,
2126 + &matchInfo->meiBackRefInfo,
2127 + beginPos,
2128 + matchedPatternLength);
2130 + if (startStartPos != -1)
2132 + matchInfo->meiDirection = SEARCH_BACKWARD;
2134 + *matchPos = startStartPos + searchRegion->sriStartOfTextPos;
2136 + matchingPatternFound = TRUE;
2141 + return matchingPatternFound;
2145 +** Find matching pattern related to given begin pattern reference
2146 +** in forward direction by considering the rules stored in given
2147 +** string match table. Determine match position (= relative
2148 +** pos. of last character of matching string).
2149 +** Returns -1, if no matching pattern was found. Else the relative
2150 +** position of 1st char. of matching string is returned.
2152 +static int findRelatedForwardPattern(
2153 + StringMatchTable *table,
2154 + SearchRegionInfo *searchRegion,
2155 + const char *delimiters,
2156 + PatternReference beginPatRef,
2157 + int beginPatHighLightCode,
2158 + BackRefInfo *beginPatBackRefInfo,
2159 + int beginPos,
2160 + int *matchEndPos)
2162 + MatchPatternTable *patTable = table->smtAllPatterns;
2163 + int startPos = beginPos;
2164 + int nxtPatStartPos = 0;
2165 + int nxtPatEndPos = 0;
2166 + PatternReference nxtPatRef;
2167 + int nxtPatHighLightCode;
2168 + BackRefInfo nxtPatBackRefInfo;
2169 + PatternStackElement stack[MAX_NESTED_PATTERNS];
2170 + int stackIdx = 0;
2171 + PatternReference startPatRef;
2172 + MatchPatternTableElement *currentElement;
2173 + int groupIdx;
2174 + regexp *groupPatRE;
2175 + regexp *currentPatRE;
2176 + int skipToEnd = FALSE;
2177 + int beginPatternIsMono;
2179 +#ifdef DEBUG_FIND
2180 + printf("Forward Start Pos: %d K: %s EI: %d PI: %d HC: %d <%s>\n",
2181 + startPos,
2182 + patElemKindToString(beginPatRef.prKind),
2183 + beginPatRef.prElementIdx,
2184 + beginPatRef.prPatternIdx,
2185 + beginPatHighLightCode,
2186 + getPatternForDebug(patTable, beginPatRef) );
2187 +#endif
2189 + /*
2190 + * put begin pattern info on stack
2191 + */
2192 + stack[stackIdx].psePatRef = beginPatRef;
2193 + stack[stackIdx].pseHighLightCode = beginPatHighLightCode;
2194 + stack[stackIdx].pseBackRefInfo = *beginPatBackRefInfo;
2195 + stackIdx ++;
2197 + currentElement = patTable->mptElements[beginPatRef.prElementIdx];
2199 + beginPatternIsMono = currentElement->mpteIsMonoPattern;
2201 + groupIdx = currentElement->mpteGroup;
2203 + /*
2204 + * no next pattern can be found, if there is no group assigned
2205 + * to begin pattern (should never occur)
2206 + */
2207 + if (groupIdx == NO_GROUP_IDX)
2209 + *matchEndPos = -1;
2211 + return -1;
2214 + /*
2215 + * Remember pattern (= keywords) regular expression of context
2216 + * group related to begin pattern. Use it for forward search.
2217 + */
2218 + groupPatRE = table->smtGroups[groupIdx]->mpgeKeywordRE;
2219 + currentPatRE = groupPatRE;
2221 + /*
2222 + * Use start / end pattern regular expression if skip to end is
2223 + * set for begin pattern.
2224 + */
2225 + if (currentElement->mpteSkipBtwnStartEnd)
2227 + currentPatRE = currentElement->mpteStartEndRE;
2228 + skipToEnd = TRUE;
2231 + while (stackIdx > 0 && nxtPatStartPos != -1)
2233 + /*
2234 + * Search for next string pattern in forward direction.
2235 + */
2236 + nxtPatStartPos =
2237 + searchPatternForward(
2238 + patTable,
2239 + currentPatRE,
2240 + searchRegion,
2241 + delimiters,
2242 + startPos,
2243 + &nxtPatEndPos,
2244 + &nxtPatRef,
2245 + &nxtPatHighLightCode,
2246 + &nxtPatBackRefInfo );
2248 + startPatRef = stack[stackIdx-1].psePatRef;
2250 + if (nxtPatStartPos == -1)
2252 + /*
2253 + * no next pattern found -> leave loop
2254 + */
2255 +#ifdef DEBUG_FIND
2256 + printf(" SI: %d [start K: %s EI: %d PI %d] Pos: %d --> no next pat. found\n",
2257 + stackIdx,
2258 + patElemKindToString(startPatRef.prKind),
2259 + startPatRef.prElementIdx,
2260 + startPatRef.prPatternIdx,
2261 + startPos);
2262 +#endif
2263 + break;
2266 + /*
2267 + * Update start pattern reference depending on next pattern
2268 + * located after start pattern.
2269 + */
2270 + considerNextPatternReference(
2271 + patTable,
2272 + &startPatRef,
2273 + nxtPatRef,
2274 + groupIdx );
2276 + /*
2277 + * If current found match pattern table element is a mono pattern and
2278 + * skip to start pattern is active, then the found pattern string is
2279 + * a END one in case of ambiguous or no syntax was detected.
2280 + */
2281 + if (skipToEnd &&
2282 + (nxtPatRef.prMonoInfo == PEMI_MONO_AMBIGUOUS_SYNTAX ||
2283 + nxtPatRef.prMonoInfo == PEMI_MONO_NOT_SYNTAX_BASED))
2285 + nxtPatRef.prKind = PEK_END;
2288 +#ifdef DEBUG_FIND
2289 + printf(" SI: %d [start K: %s EI: %d PI %d] Pos: %d-%d K: %s EI: %d PI: %d HC: %d f=<%s> ",
2290 + stackIdx,
2291 + patElemKindToString(startPatRef.prKind),
2292 + startPatRef.prElementIdx,
2293 + startPatRef.prPatternIdx,
2294 + nxtPatStartPos,
2295 + nxtPatEndPos,
2296 + patElemKindToString(nxtPatRef.prKind),
2297 + nxtPatRef.prElementIdx,
2298 + nxtPatRef.prPatternIdx,
2299 + nxtPatHighLightCode,
2300 + getPatternForDebug(patTable, nxtPatRef) );
2301 + printFoundStringForDebug(
2302 + searchRegion->sriWindow,
2303 + nxtPatStartPos + searchRegion->sriStartOfTextPos,
2304 + nxtPatEndPos - nxtPatStartPos);
2305 + printf("\n");
2306 +#endif
2308 + if (nxtPatRef.prKind == PEK_START)
2310 + if (stackIdx >= MAX_NESTED_PATTERNS)
2312 +#ifdef DEBUG_FIND
2313 + printf("FORWARD: MAX. NESTED PATTERN DEPTH REACHED !\n");
2314 +#endif
2315 + nxtPatStartPos = -1;
2316 + nxtPatEndPos = -1;
2318 + else if (!skipToEnd)
2320 + /*
2321 + * Put next pattern on stack, if contents between start /
2322 + * end shouldn't be skipped (if "skipToEnd" is set,
2323 + * a (usually illegal) start pattern to skip inside the
2324 + * skipped one is found (e.g. \* \* ..)
2325 + */
2326 + stack[stackIdx].psePatRef = nxtPatRef;
2327 + stack[stackIdx].pseHighLightCode = nxtPatHighLightCode;
2328 + stack[stackIdx].pseBackRefInfo = nxtPatBackRefInfo;
2329 + stackIdx ++;
2331 + currentElement = patTable->mptElements[nxtPatRef.prElementIdx];
2333 + /*
2334 + * Use start / end pattern regular expression if skip to
2335 + * end is set for found start pattern.
2336 + */
2337 + if (currentElement->mpteSkipBtwnStartEnd)
2339 + currentPatRE = currentElement->mpteStartEndRE;
2340 + skipToEnd = TRUE;
2343 + else if (beginPatternIsMono)
2345 + /*
2346 + * skip to end is set and a mono pattern start is reached:
2347 + * trigger backward search by returning "not found"
2348 + */
2349 +#ifdef DEBUG_FIND
2350 + printf(" ---> mono pattern (re-)start -> trigger backward search\n");
2351 +#endif
2352 + nxtPatStartPos = -1;
2353 + nxtPatEndPos = -1;
2355 +#ifdef DEBUG_FIND
2356 + else
2358 + printf(" ---> skip to end: illegal (re-)start pattern !\n");
2360 +#endif
2362 + else if (nxtPatRef.prKind == PEK_END)
2364 + /*
2365 + * ignore current found pattern, if it doesn't fit to the prev.
2366 + * opened one.
2367 + */
2368 + if (isPartOfPattern(
2369 + patTable,
2370 + nxtPatRef.prElementIdx,
2371 + startPatRef.prElementIdx,
2372 + PEK_END) &&
2373 + (stack[stackIdx - 1].pseHighLightCode == nxtPatHighLightCode ||
2374 + stack[stackIdx - 1].pseHighLightCode == IGNORE_HIGHLIGHT_CODE ||
2375 + nxtPatHighLightCode == IGNORE_HIGHLIGHT_CODE) &&
2376 + doesBackRefInfoMatch(
2377 + &stack[stackIdx - 1].pseBackRefInfo,
2378 + &nxtPatBackRefInfo))
2380 + /*
2381 + * use context group pattern again, if end pattern to skip
2382 + * to was found.
2383 + */
2384 + if (skipToEnd)
2386 + currentPatRE = groupPatRE;
2387 + skipToEnd = FALSE;
2390 + /*
2391 + * pop. related start pattern from stack.
2392 + */
2393 + stackIdx --;
2396 + else if (!skipToEnd)
2398 + /*
2399 + * middle pattern was found: ignore it, if found middle pattern
2400 + * doesn't belong to begin pattern.
2401 + */
2402 + if (stackIdx == 1 &&
2403 + isPartOfPattern(
2404 + patTable,
2405 + startPatRef.prElementIdx,
2406 + nxtPatRef.prElementIdx,
2407 + nxtPatRef.prKind) &&
2408 + (beginPatHighLightCode == nxtPatHighLightCode ||
2409 + beginPatHighLightCode == IGNORE_HIGHLIGHT_CODE ||
2410 + nxtPatHighLightCode == IGNORE_HIGHLIGHT_CODE) &&
2411 + doesBackRefInfoMatch(
2412 + beginPatBackRefInfo,
2413 + &nxtPatBackRefInfo))
2416 + stackIdx --;
2420 + startPos = nxtPatEndPos;
2423 + *matchEndPos = nxtPatEndPos;
2425 + return nxtPatStartPos;
2429 +** Find matching pattern related to given pattern (stored in
2430 +** 'matchInfo') in backward direction by considering the rules stored in
2431 +** string match table of given window. Determine match position (= abs.
2432 +** pos. of 1st character of matching string) and length of matching
2433 +** string.
2434 +** Returns true, if a matching pattern was found.
2436 +static int parseStringElementBackward(
2437 + MatchingElementInfo *matchInfo,
2438 + SearchRegionInfo *searchRegion,
2439 + int relCharPos,
2440 + int *matchPos,
2441 + int *matchedPatternLength,
2442 + const char *delimiters)
2444 + StringMatchTable *smTable =
2445 + (StringMatchTable *)searchRegion->sriWindow->stringMatchTable;
2446 + int beginPos;
2447 + int startStartPos;
2448 + int matchingPatternFound = FALSE;
2450 + /*
2451 + * determine begin of search in string buffer (= relative position
2452 + * of 1st char. before found string pattern.)
2453 + */
2454 + beginPos = relCharPos - matchInfo->meiLength - 1;
2456 + if (beginPos < 0)
2457 + return FALSE;
2459 + /*
2460 + * Find matching pattern within text buffer area to parse in
2461 + * backward direction.
2462 + */
2463 + startStartPos =
2464 + findRelatedStartPattern(
2465 + smTable,
2466 + searchRegion,
2467 + delimiters,
2468 + matchInfo->meiPatRef,
2469 + matchInfo->meiHighLightCode,
2470 + &matchInfo->meiBackRefInfo,
2471 + beginPos,
2472 + matchedPatternLength);
2474 + if (startStartPos != -1)
2476 + *matchPos = startStartPos + searchRegion->sriStartOfTextPos;
2477 + matchingPatternFound = TRUE;
2480 + return matchingPatternFound;
2484 +** Find matching pattern related to given begin pattern reference
2485 +** in backward direction by considering the rules stored in given
2486 +** string match table. Determine match position (= relative
2487 +** pos. of 1st character of matching string).
2488 +** Returns -1, if no matching pattern was found. Else the relative
2489 +** position of 1st char. of matching string is returned.
2491 +static int findRelatedStartPattern(
2492 + StringMatchTable *table,
2493 + SearchRegionInfo *searchRegion,
2494 + const char *delimiters,
2495 + PatternReference beginPatRef,
2496 + int beginPatHighLightCode,
2497 + BackRefInfo *beginPatBackRefInfo,
2498 + int beginPos,
2499 + int *matchedPatternLength)
2501 + MatchPatternTable *patTable = table->smtAllPatterns;
2502 + int startPos = beginPos;
2503 + int prevStartPos = 0;
2504 + PatternReference prevPatRef;
2505 + int prevPatHighLightCode;
2506 + BackRefInfo prevPatBackRefInfo;
2507 + PatternStackElement stack[MAX_NESTED_PATTERNS];
2508 + int stackIdx = 0;
2509 + MatchPatternTableElement *currentElement;
2510 + int groupIdx;
2511 + regexp *groupPatRE;
2512 + regexp *currentPatRE;
2513 + int skipToStart = FALSE;
2515 + /*
2516 + * put begin pattern info on stack
2517 + */
2518 + stack[stackIdx].psePatRef = beginPatRef;
2519 + stack[stackIdx].pseHighLightCode = beginPatHighLightCode;
2520 + stack[stackIdx].pseBackRefInfo = *beginPatBackRefInfo;
2521 + stackIdx ++;
2523 + currentElement = patTable->mptElements[beginPatRef.prElementIdx];
2525 +#ifdef DEBUG_FIND
2526 + printf("Backward Start Pos: %d K: %s EI: %d PI: %d HC: %d <%s>\n",
2527 + startPos,
2528 + patElemKindToString(beginPatRef.prKind),
2529 + beginPatRef.prElementIdx,
2530 + beginPatRef.prPatternIdx,
2531 + beginPatHighLightCode,
2532 + getPatternForDebug(patTable, beginPatRef) );
2533 +#endif
2535 + groupIdx = currentElement->mpteGroup;
2537 + /*
2538 + * no start pattern can be found, if there is no group assigned
2539 + * to begin pattern (should never occur)
2540 + */
2541 + if (groupIdx == NO_GROUP_IDX)
2543 + return -1;
2546 + /*
2547 + * Remember pattern (= keywords) regular expression of context
2548 + * group related to begin pattern. Use it for backward search.
2549 + */
2550 + groupPatRE = table->smtGroups[groupIdx]->mpgeKeywordRE;
2551 + currentPatRE = groupPatRE;
2553 + /*
2554 + * Use start / end pattern regular expression if skip to start is
2555 + * set for begin pattern.
2556 + */
2557 + if (currentElement->mpteSkipBtwnStartEnd)
2559 + currentPatRE = currentElement->mpteStartEndRE;
2560 + skipToStart = TRUE;
2563 + while (stackIdx > 0 && prevStartPos != -1)
2565 + /*
2566 + * Search for previous string pattern in backward direction.
2567 + */
2568 + prevStartPos =
2569 + searchPatternBackward(
2570 + patTable,
2571 + currentPatRE,
2572 + searchRegion,
2573 + delimiters,
2574 + startPos,
2575 + &prevPatRef,
2576 + &prevPatHighLightCode,
2577 + matchedPatternLength,
2578 + &prevPatBackRefInfo );
2580 + if (prevStartPos == -1)
2582 + /*
2583 + * no previous pattern found -> leave loop
2584 + */
2585 +#ifdef DEBUG_FIND
2586 + printf(" SI: %d [K: %s start EI: %d PI %d] Pos: %d --> no next pat. found\n",
2587 + stackIdx,
2588 + patElemKindToString(stack[stackIdx -1].psePatRef.prKind),
2589 + stack[stackIdx -1].psePatRef.prElementIdx,
2590 + stack[stackIdx -1].psePatRef.prPatternIdx,
2591 + startPos);
2592 +#endif
2593 + break;
2596 + /*
2597 + * Update previous pattern reference depending on last stack
2598 + * pattern, which is located in text puffer after previous
2599 + * start pattern.
2600 + */
2601 + considerNextPatternReference(
2602 + patTable,
2603 + &prevPatRef,
2604 + stack[stackIdx - 1].psePatRef,
2605 + groupIdx);
2607 + /*
2608 + * If current found match pattern table element is a mono pattern and
2609 + * skip to start pattern is active, then the found pattern string is
2610 + * a START one in case of ambiguous or no syntax was detected.
2611 + */
2612 + if (skipToStart &&
2613 + (prevPatRef.prMonoInfo == PEMI_MONO_AMBIGUOUS_SYNTAX ||
2614 + prevPatRef.prMonoInfo == PEMI_MONO_NOT_SYNTAX_BASED))
2616 + prevPatRef.prKind = PEK_START;
2619 +#ifdef DEBUG_FIND
2620 + printf(" SI: %d [K: %s start EI: %d PI %d] Pos: %d K: %s EI: %d PI: %d HC: %d f=<%s> ",
2621 + stackIdx,
2622 + patElemKindToString(stack[stackIdx -1].psePatRef.prKind),
2623 + stack[stackIdx -1].psePatRef.prElementIdx,
2624 + stack[stackIdx -1].psePatRef.prPatternIdx,
2625 + prevStartPos,
2626 + patElemKindToString(prevPatRef.prKind),
2627 + prevPatRef.prElementIdx,
2628 + prevPatRef.prPatternIdx,
2629 + prevPatHighLightCode,
2630 + getPatternForDebug(patTable, prevPatRef) );
2631 + printFoundStringForDebug(
2632 + searchRegion->sriWindow,
2633 + prevStartPos + searchRegion->sriStartOfTextPos,
2634 + *matchedPatternLength);
2635 + printf("\n");
2636 +#endif
2638 + if (prevPatRef.prKind == PEK_START)
2640 + /*
2641 + * If the end pattern of the previous pattern set is a reference,
2642 + * then the prev. element index is the one of the ref. (due to this
2643 + * string was found before and was stored on stack)
2644 + */
2645 + if (patTable->mptElements[prevPatRef.prElementIdx]->mpteGroup == groupIdx)
2647 + considerStackPatReference(
2648 + &patTable->mptElements[prevPatRef.prElementIdx]->mpteEnd,
2649 + stack[stackIdx - 1].psePatRef.prElementIdx,
2650 + &prevPatRef.prElementIdx);
2653 + /*
2654 + * Ignore current found pattern, if it doesn't fit to the prev.
2655 + * opened one.
2656 + */
2657 + if (stack[stackIdx - 1].psePatRef.prElementIdx == prevPatRef.prElementIdx &&
2658 + (stack[stackIdx - 1].pseHighLightCode == prevPatHighLightCode ||
2659 + stack[stackIdx - 1].pseHighLightCode == IGNORE_HIGHLIGHT_CODE ||
2660 + prevPatHighLightCode == IGNORE_HIGHLIGHT_CODE) &&
2661 + doesBackRefInfoMatch(
2662 + &stack[stackIdx - 1].pseBackRefInfo,
2663 + &prevPatBackRefInfo))
2665 + /*
2666 + * use context group pattern again, if start pattern
2667 + * to skip to was found.
2668 + */
2669 + if (skipToStart)
2671 + currentPatRE = groupPatRE;
2672 + skipToStart = FALSE;
2675 + /*
2676 + * pop. related end pattern from stack.
2677 + */
2678 + stackIdx --;
2681 + else if (prevPatRef.prKind == PEK_END)
2683 + if (stackIdx >= MAX_NESTED_PATTERNS)
2685 +#ifdef DEBUG_FIND
2686 + printf("BACKWARD: MAX. NESTED PATTERN DEPTH REACHED !\n");
2687 +#endif
2688 + prevStartPos = -1;
2690 + else if (!skipToStart)
2692 + /*
2693 + * Put prev. pattern on stack, if contents between start /
2694 + * end shouldn't be skipped (if "skipToStart" is set,
2695 + * a (usually illegal) end pattern to skip inside the
2696 + * skipped one is found (e.g. *\ *\ ..)
2697 + */
2698 + stack[stackIdx].psePatRef = prevPatRef;
2699 + stack[stackIdx].pseHighLightCode = prevPatHighLightCode;
2700 + stack[stackIdx].pseBackRefInfo = prevPatBackRefInfo;
2701 + stackIdx ++;
2703 + currentElement =
2704 + patTable->mptElements[prevPatRef.prElementIdx];
2706 + /*
2707 + * Use start / end pattern regular expression if skip to
2708 + * end is set for found end pattern.
2709 + */
2710 + if (currentElement->mpteSkipBtwnStartEnd)
2712 + currentPatRE = currentElement->mpteStartEndRE;
2713 + skipToStart = TRUE;
2717 + startPos = prevStartPos - 1;
2720 + return prevStartPos;
2724 +** Adapt found pattern element index depending on
2725 +** the info stored on (last) stack element and
2726 +** a given pattern set (belonging to the found pattern).
2728 +static void considerStackPatReference(
2729 + PatternElementSet *patSet,
2730 + int stackElementIdx,
2731 + int *foundElementIdx)
2733 + PatternElement *patElement;
2734 + int i;
2736 + /*
2737 + * If found pattern index already indicates, that found pattern
2738 + * belongs to pattern set stored on stack, then no adaption is needed
2739 + */
2740 + if (*foundElementIdx == stackElementIdx)
2741 + return;
2743 + /*
2744 + * Check all elements of given pattern element set:
2745 + */
2746 + for (i=0; i < patSet->pesNumberOfPattern; i++)
2748 + patElement = patSet->pesPattern[i];
2750 + /*
2751 + * If this set element is a reference and this reference fits
2752 + * to the element stored on stack, then adapt found element index:
2753 + * indicate, that found pattern belongs to pattern set stored on stack
2754 + */
2755 + if (patElement->peType == PET_REFERENCE &&
2756 + patElement->peVal.peuRef.prElementIdx == stackElementIdx)
2758 + *foundElementIdx = stackElementIdx;
2760 + return;
2766 +** Determines, if a string pattern is located at the given position
2767 +** "relBeginPos" in the given "searchRegion". A string pattern is
2768 +** found, if the pattern is located just before given position
2769 +** "relBeginPos" OR if "relBeginPos" is located within a string pattern.
2771 +** Returns true, if the given "pattern" is located at
2772 +** "relBeginPos". "matchInfo" holds all info needed about matched
2773 +** "start" string pattern.
2775 +static int getPatternLocatedAtPos(
2776 + regexp *usedPatRE,
2777 + MatchPatternTable *table,
2778 + SearchRegionInfo *searchRegion,
2779 + int *relBeginPos,
2780 + MatchingElementInfo *matchInfo,
2781 + const char *delimiters)
2783 + int searchStartPos = *relBeginPos;
2784 + PatternReference *patRef = &matchInfo->meiPatRef;
2785 + FoundStringInfo foundStringInfo;
2786 + int relMatchStartPos;
2787 + int relMatchEndPos;
2789 + patRef->prElementIdx = NO_ELEMENT_IDX;
2790 + patRef->prKind = PEK_UNKNOWN;
2791 + patRef->prPatternIdx = NO_PATTERN_IDX;
2793 + matchInfo->meiHighLightCode = IGNORE_HIGHLIGHT_CODE;
2794 + matchInfo->meiAbsStartPos = -1;
2795 + matchInfo->meiLength = 0;
2797 + /*
2798 + * No backward search possible, if we are at beginning of
2799 + * search region
2800 + */
2801 + if (searchStartPos == 0)
2802 + return FALSE;
2804 + /*
2805 + * Search in backward direction for 1st occurance of a string pattern
2806 + * starting one char before "searchStartPos".
2807 + */
2808 + if (ExecRE(
2809 + usedPatRE,
2810 + searchRegion->sriText,
2811 + searchRegion->sriText + searchStartPos - 1,
2812 + TRUE,
2813 + searchRegion->sriPrevChar,
2814 + searchRegion->sriText[searchStartPos],
2815 + delimiters,
2816 + searchRegion->sriText,
2817 + NULL))
2819 + /*
2820 + * String pattern was found:
2821 + */
2822 + foundStringInfo.fsiStartPtr = usedPatRE->startp[0];
2823 + foundStringInfo.fsiEndPtr = usedPatRE->endp[0];
2824 + foundStringInfo.fsiLength =
2825 + foundStringInfo.fsiEndPtr - foundStringInfo.fsiStartPtr;
2827 + relMatchEndPos = foundStringInfo.fsiEndPtr - searchRegion->sriText;
2828 + relMatchStartPos = foundStringInfo.fsiStartPtr - searchRegion->sriText;
2830 + /*
2831 + * Is found pattern located exactly one char before "relBeginPos" OR
2832 + * is "relBeginPos" located within found string pattern ?
2833 + * Note: "relMatchEndPos" indicates 1st pos. in "sriText"
2834 + * which does *not* belong to found string anymore.
2835 + */
2836 + if ((*relBeginPos == relMatchEndPos) ||
2837 + (*relBeginPos >= relMatchStartPos &&
2838 + *relBeginPos < relMatchEndPos))
2840 + *relBeginPos = relMatchEndPos;
2842 + /*
2843 + * Determine match element info related to found string.
2844 + */
2845 + matchInfo->meiAbsStartPos =
2846 + foundStringInfo.fsiStartPtr - searchRegion->sriText +
2847 + searchRegion->sriStartOfTextPos;
2848 + matchInfo->meiLength = foundStringInfo.fsiLength;
2850 + foundStringInfo.fsiPrevChar =
2851 + foundStringInfo.fsiStartPtr == searchRegion->sriText ?
2852 + searchRegion->sriPrevChar : *(foundStringInfo.fsiStartPtr - 1);
2854 + foundStringInfo.fsiSuccChar =
2855 + *(foundStringInfo.fsiEndPtr) == '\0' ?
2856 + searchRegion->sriSuccChar : *(foundStringInfo.fsiEndPtr);
2858 + foundStringInfo.fsiDelimiters = delimiters;
2860 + return(
2861 + getMatchedElementInfo(
2862 + searchRegion->sriWindow,
2863 + table,
2864 + &foundStringInfo,
2865 + matchInfo));
2869 + return FALSE;
2873 +** Get all needed info related to matched "start" string pattern
2874 +** (given by parameter "foundStringInfo").
2876 +** Returns true, if info was determined successfully.
2878 +static int getMatchedElementInfo(
2879 + WindowInfo *window,
2880 + MatchPatternTable *table,
2881 + FoundStringInfo *foundStringInfo,
2882 + MatchingElementInfo *matchInfo)
2884 + PatternReference *patRef = &matchInfo->meiPatRef;
2885 + int absMatchStartPos = matchInfo->meiAbsStartPos;
2886 + MatchPatternTableElement *matchedElement;
2888 + if (getPatternInfo(
2889 + table,
2890 + foundStringInfo,
2891 + patRef,
2892 + &matchInfo->meiBackRefInfo))
2894 + /*
2895 + * A pattern reference could be assigned to found string:
2896 + */
2897 + matchedElement = table->mptElements[patRef->prElementIdx];
2899 + matchInfo->meiElement = matchedElement;
2901 + /*
2902 + * get highlight code of found string pattern, if applicable
2903 + */
2904 + if (!matchedElement->mpteIgnoreHighLightInfo)
2906 + matchInfo->meiHighLightCode =
2907 + HighlightCodeOfPos(window, absMatchStartPos);
2910 + /*
2911 + * setup mono pattern info of found string pattern
2912 + */
2913 + if (matchedElement->mpteIsMonoPattern)
2915 + if (matchedElement->mpteIgnoreHighLightInfo)
2917 + patRef->prMonoInfo = PEMI_MONO_NOT_SYNTAX_BASED;
2919 + else
2921 + /*
2922 + * determine mono pattern info depending on highLightCodes
2923 + * before / after found string pattern.
2924 + */
2925 + patRef->prMonoInfo =
2926 + determineMonoPatInfo(
2927 + window,
2928 + matchInfo->meiHighLightCode,
2929 + absMatchStartPos - 1,
2930 + absMatchStartPos + matchInfo->meiLength,
2931 + &patRef->prKind);
2934 + else
2936 + patRef->prMonoInfo = PEMI_NOT_MONO;
2939 + return TRUE;
2941 + else
2943 + /*
2944 + * Found string can't be assigned to a pattern element
2945 + * (should never occur).
2946 + */
2947 + return FALSE;
2952 +** Returns string pattern of given pattern element.
2954 +StringPattern *GetStringPattern(
2955 + MatchPatternTable *table,
2956 + PatternElement *pattern )
2958 + switch (pattern->peType)
2960 + case PET_SINGLE:
2961 + return &pattern->peVal.peuSingle;
2962 + break;
2964 + case PET_MULTIPLE:
2965 + return &pattern->peVal.peuMulti.mpStringPattern;
2966 + break;
2968 + case PET_REFERENCE:
2969 + return GetStringPattern(
2970 + table,
2971 + getPatternOfReference(table, pattern->peVal.peuRef));
2972 + break;
2975 + /*
2976 + * never reached; just to make compiler happy
2977 + */
2978 + return NULL;
2982 +** Returns pattern element of given pattern reference.
2984 +static PatternElement *getPatternOfReference(
2985 + MatchPatternTable *table,
2986 + PatternReference patRef)
2988 + MatchPatternTableElement **element = table->mptElements;
2990 + return element[ patRef.prElementIdx ]->mpteAll.pesPattern[patRef.prPatternIdx];
2993 +#ifdef DEBUG_FIND
2994 +static char *getPatternForDebug(
2995 + MatchPatternTable *table,
2996 + PatternReference patRef )
2998 + if (patRef.prElementIdx < 0)
3000 + return "---";
3003 + return
3004 + GetStringPattern(
3005 + table,
3006 + getPatternOfReference(table, patRef))->spText;
3009 +static char *patElemKindToString(
3010 + PatternElementKind patElemKind)
3012 + if (patElemKind == PEK_START)
3013 + return "START";
3014 + else if (patElemKind == PEK_MIDDLE)
3015 + return "MIDDLE";
3016 + else if (patElemKind == PEK_END)
3017 + return "END";
3018 + else
3019 + return "UNKNOWN";
3022 +static void printFoundStringForDebug(
3023 + WindowInfo *window,
3024 + int absStartPos,
3025 + int length)
3027 + char *foundStr =
3028 + BufGetRange( window->buffer, absStartPos, absStartPos + length);
3030 + printf("%d (abs.) <%s>",
3031 + absStartPos,
3032 + foundStr);
3034 + XtFree(foundStr);
3036 +#endif
3039 diff --quilt /dev/null new/source/patternMatch.h
3040 --- /dev/null
3041 +++ new/source/patternMatch.h
3042 @@ -0,0 +1,170 @@
3043 +/* $Id: patternMatch.h,v 1.2 2003/10/11 16:45:25 uleh Exp $ */
3045 +#ifndef NEDIT_PATTERNMATCH_H_INCLUDED
3046 +#define NEDIT_PATTERNMATCH_H_INCLUDED
3048 +#include "regularExp.h"
3050 +#define NO_GROUP_IDX -1
3051 +#define NO_ELEMENT_IDX -1
3052 +#define NO_PATTERN_IDX -1
3054 +#define MAX_GLOBAL_BACK_REF_ID 9
3055 +#define NO_LOCAL_BACK_REF_ID -1
3057 +typedef enum {
3058 + PEK_UNKNOWN,
3059 + PEK_START,
3060 + PEK_END,
3061 + PEK_MIDDLE
3062 +} PatternElementKind;
3064 +typedef enum {
3065 + PEMI_NOT_MONO,
3066 + PEMI_MONO_NOT_SYNTAX_BASED,
3067 + PEMI_MONO_AMBIGUOUS_SYNTAX,
3068 + PEMI_MONO_DEFINITE_SYNTAX
3069 +} PatternElementMonoInfo;
3071 +typedef struct _PatternReference {
3072 + PatternElementKind prKind;
3073 + PatternElementMonoInfo prMonoInfo;
3074 + int prElementIdx;
3075 + int prPatternIdx;
3076 +} PatternReference;
3078 +typedef enum {
3079 + MPT_INDIVIDUAL,
3080 + MPT_SUB,
3081 + MPT_GROUP
3082 +} MatchPatternType;
3084 +typedef struct _MatchPatternSequenceElement {
3085 + char *mpseName;
3086 + MatchPatternType mpseType;
3087 + int mpseIndex;
3088 +} MatchPatternSequenceElement;
3090 +typedef struct _MatchPatternGroupElement {
3091 + char *mpgeName;
3092 + int mpgeNumberOfSubPatterns;
3093 + char **mpgeSubPatternIds;
3094 + regexp *mpgeKeywordRE;
3095 +} MatchPatternGroupElement;
3097 +typedef enum {
3098 + PWB_NONE,
3099 + PWB_LEFT,
3100 + PWB_RIGHT,
3101 + PWB_BOTH
3102 +} PatternWordBoundary;
3104 +typedef struct _StrPatBackRefElement{
3105 + int spbreLocalBackRefID;
3106 + char *spbreRegExpText;
3107 +} StrPatBackRefElement;
3109 +typedef struct _StringPattern {
3110 + char *spText;
3111 + int spLength;
3112 + PatternWordBoundary spWordBoundary;
3113 + int spCaseInsensitive;
3114 + int spRegularExpression;
3115 + regexp *spTextRE;
3116 + char *spOrigText;
3117 + int spBackRefParsed;
3118 + int spBackRefResolved;
3119 + StrPatBackRefElement spOwnGlobalBackRef[MAX_GLOBAL_BACK_REF_ID];
3120 + int spGlobalToLocalBackRef[MAX_GLOBAL_BACK_REF_ID];
3121 +} StringPattern;
3123 +typedef struct _MultiPattern {
3124 + StringPattern mpStringPattern;
3125 + int mpNumberOfReferences;
3126 + PatternReference *mpRefList;
3127 +} MultiPattern;
3129 +typedef enum {
3130 + PET_SINGLE,
3131 + PET_MULTIPLE,
3132 + PET_REFERENCE
3133 +} PatternElementType;
3135 +typedef struct _PatternElement {
3136 + int peIndex;
3137 + PatternElementKind peKind;
3138 + PatternElementType peType;
3139 + union {
3140 + StringPattern peuSingle;
3141 + MultiPattern peuMulti;
3142 + PatternReference peuRef;
3143 + } peVal;
3144 +} PatternElement;
3146 +typedef struct _PatternElementSet {
3147 + int pesNumberOfPattern;
3148 + PatternElement **pesPattern;
3149 +} PatternElementSet;
3151 +typedef struct _GlobalBackRefElement{
3152 + StringPattern *gbreDefByStrPat;
3153 + char *gbreRegExpText;
3154 +} GlobalBackRefElement;
3156 +typedef struct _MatchPatternTableElement {
3157 + char *mpteName;
3158 + int mpteIndex;
3159 + MatchPatternType mpteType;
3160 + int mpteGroup;
3161 + PatternElementSet mpteAll;
3162 + PatternElementSet mpteStart;
3163 + PatternElementSet mpteMiddle;
3164 + PatternElementSet mpteEnd;
3165 + int mpteFlash;
3166 + int mpteIsMonoPattern;
3167 + int mpteSkipBtwnStartEnd;
3168 + int mpteIgnoreHighLightInfo;
3169 + regexp *mpteStartEndRE;
3170 + GlobalBackRefElement mpteGlobalBackRef[MAX_GLOBAL_BACK_REF_ID];
3171 +} MatchPatternTableElement;
3173 +typedef struct _MatchPatternTable {
3174 + int mptNumberOfElements;
3175 + MatchPatternTableElement **mptElements;
3176 +} MatchPatternTable;
3178 +typedef struct _StringMatchTable {
3179 + char *smtLanguageMode;
3180 + MatchPatternTable *smtAllPatterns;
3181 + regexp *smtAllPatRE;
3182 + regexp *smtFlashPatRE;
3183 + regexp *smtUsedPatRE;
3184 + int smtNumberOfGroups;
3185 + MatchPatternGroupElement **smtGroups;
3186 + int smtNumberOfSeqElements;
3187 + MatchPatternSequenceElement **smtSequence;
3188 +} StringMatchTable;
3190 +typedef enum {
3191 + MT_FLASH_DELIMIT,
3192 + MT_FLASH_RANGE,
3193 + MT_SELECT,
3194 + MT_GOTO,
3195 + MT_MACRO
3196 +} MatchingType;
3198 +int FindMatchingString(
3199 + WindowInfo *window,
3200 + MatchingType matchingType,
3201 + int *charPos,
3202 + int startLimit,
3203 + int endLimit,
3204 + int *matchPos,
3205 + int *matchLength,
3206 + int *direction);
3208 +StringPattern *GetStringPattern(
3209 + MatchPatternTable *table,
3210 + PatternElement *pattern);
3212 +#endif /* NEDIT_PATTERNMATCH_H_INCLUDED */
3213 diff --quilt /dev/null new/source/patternMatchData.c
3214 --- /dev/null
3215 +++ new/source/patternMatchData.c
3216 @@ -0,0 +1,7780 @@
3217 +static const char CVSID[] = "$Id: patternMatchData.c,v 1.4 2004/10/27 21:57:12 uleh Exp $";
3218 +/*******************************************************************************
3219 +* *
3220 +* patternMatchData.c -- Maintain and allow user to edit a matching pattern list*
3221 +* used for pattern matching *
3222 +* *
3223 +* Copyright (C) 2003-2004, Uwe Lehnert *
3224 +* *
3225 +* This is free software; you can redistribute it and/or modify it under the *
3226 +* terms of the GNU General Public License as published by the Free Software *
3227 +* Foundation; either version 2 of the License, or (at your option) any later *
3228 +* version. In addition, you may distribute versions of this program linked to *
3229 +* Motif or Open Motif. See README for details. *
3230 +* *
3231 +* This software is distributed in the hope that it will be useful, but WITHOUT *
3232 +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
3233 +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
3234 +* for more details. *
3235 +* *
3236 +* You should have received a copy of the GNU General Public License along with *
3237 +* software; if not, write to the Free Software Foundation, Inc., 59 Temple *
3238 +* Place, Suite 330, Boston, MA 02111-1307 USA *
3239 +* *
3240 +* Nirvana Text Editor *
3241 +* October 27, 2004 *
3242 +* *
3243 +* Written by Uwe Lehnert *
3244 +* *
3245 +*******************************************************************************/
3246 +#ifdef HAVE_CONFIG_H
3247 +#include "../config.h"
3248 +#endif
3250 +#include <stdlib.h>
3251 +#include <stdio.h>
3252 +#include <limits.h>
3253 +#include <string.h>
3254 +#include <ctype.h>
3256 +#ifdef VMS
3257 +#include "../util/VMSparam.h"
3258 +#else
3259 +#ifndef __MVS__
3260 +#include <sys/param.h>
3261 +#endif
3262 +#endif /*VMS*/
3264 +#include <Xm/Xm.h>
3265 +#include <Xm/Form.h>
3266 +#include <Xm/Frame.h>
3267 +#include <Xm/Text.h>
3268 +#include <Xm/LabelG.h>
3269 +#include <Xm/PushB.h>
3270 +#include <Xm/PushBG.h>
3271 +#include <Xm/ToggleB.h>
3272 +#include <Xm/RowColumn.h>
3273 +#include <Xm/SeparatoG.h>
3275 +#include "../util/misc.h"
3276 +#include "../util/DialogF.h"
3277 +#include "../util/managedList.h"
3279 +#include "regularExp.h"
3280 +#include "textBuf.h"
3281 +#include "nedit.h"
3282 +#include "window.h"
3283 +#include "preferences.h"
3284 +#include "help.h"
3285 +#include "file.h"
3286 +#include "textP.h"
3288 +#include "patternMatch.h"
3289 +#include "patternMatchData.h"
3291 +#ifdef HAVE_DEBUG_H
3292 +#include "../debug.h"
3293 +#endif
3296 + * local synonyms
3297 + */
3298 +#define MAX_LOCAL_BACK_REF_ID 9
3299 +#define LOCAL_BACK_REF_ID_USED -2
3301 +#define MAX_NUMBER_MIDDLE_PATTERN 10
3302 +#define MAX_STRING_PATTERNS 30
3303 +#define MAX_NBR_MATCH_PATTERNS 50
3304 +#define MAX_NBR_MATCH_PATTERN_GROUPS 50
3305 +#define MAX_NBR_SEQ_ELEMENTS MAX_NBR_MATCH_PATTERNS + MAX_NBR_MATCH_PATTERN_GROUPS
3307 +#define MATCH_PAT_NAME_LBL_TXT "Matching Pattern Name"
3308 +#define STRING_PATTERNS_LBL_TXT "String Patterns"
3310 +#define BORDER 4
3311 +#define LIST_RIGHT 41
3312 +#define PLAIN_LM_STRING "PLAIN"
3314 +#define SPNM_NONE_SELECTED "none selected"
3316 +#define KEEP_LANGUAGE_MODE True
3317 +#define DISCARD_LANGUAGE_MODE False
3319 +#define STRING_PATTERN_DIALOG True
3320 +#define CONTEXT_GROUP_DIALOG False
3323 + * local data definitions
3324 + */
3325 +typedef struct _ErrorInfo {
3326 + char *eiDetail;
3327 + char *eiLanguageMode;
3328 + char *eiMPTabElementName;
3329 + char *eiStringPatText;
3330 + char *eiRegExpCompileMsg;
3331 + int eiBackRefNbr;
3332 +} ErrorInfo;
3334 +typedef struct _BackRefBracketInfo {
3335 + int brbiGlobalId;
3336 + char *brbiContentStart;
3337 + int brbiNestingLevel;
3338 +} BackRefBracketInfo;
3340 +typedef struct _RegExpStringInfo {
3341 + int resiNbrOfAddedMultiPat;
3342 + PatternReference **resiAddedMultiPat;
3343 + char *resiNoneWBRegExpString;
3344 + char *resiLeftWBRegExpString;
3345 + char *resiRightWBRegExpString;
3346 + char *resiBothWBRegExpString;
3347 + int resiLocalBackRefID;
3348 +} RegExpStringInfo;
3350 +typedef struct _ReadMatchPatternInfo {
3351 + int rmpiNbrOfElements;
3352 + MatchPatternTableElement *rmpiElement[MAX_NBR_MATCH_PATTERNS];
3353 + int rmpiNbrOfGroups;
3354 + MatchPatternGroupElement *rmpiGroup[MAX_NBR_MATCH_PATTERN_GROUPS];
3355 + int rmpiNbrOfSeqElements;
3356 + MatchPatternSequenceElement *rmpiSequence[MAX_NBR_SEQ_ELEMENTS];
3357 + regexp *rmpiAllPatRE;
3358 + regexp *rmpiFlashPatRE;
3359 +} ReadMatchPatternInfo;
3361 +typedef struct _DialogStringPatternElement {
3362 + char *dspeText;
3363 + PatternElementKind dspeKind;
3364 + PatternWordBoundary dspeWordBoundary;
3365 + int dspeCaseInsensitive;
3366 + int dspeRegularExpression;
3367 +} DialogStringPatternElement;
3369 +typedef struct _DialogStringPatterns {
3370 + int dspNumberOfPatterns;
3371 + DialogStringPatternElement *dspElements[MAX_STRING_PATTERNS];
3372 +} DialogStringPatterns;
3374 +typedef struct _DialogMatchPatternTableElement {
3375 + char *dmpteName;
3376 + MatchPatternType dmpteType;
3377 + DialogStringPatterns dmptePatterns;
3378 + int dmpteSkipBtwnStartEnd;
3379 + int dmpteIgnoreHighLightInfo;
3380 + int dmpteFlash;
3381 +} DialogMatchPatternTableElement;
3383 +typedef struct _DialogMatchPatternGroupElement {
3384 + char *dmpgeName;
3385 + int dmpgeNumberOfSubPatterns;
3386 + char *dmpgeSubPatternIds[MAX_NBR_MATCH_PATTERNS];
3387 +} DialogMatchPatternGroupElement;
3389 +typedef struct _DialogMatchPatternSequenceElement {
3390 + char *dmpseName;
3391 + MatchPatternType dmpseType;
3392 + int dmpseValid;
3393 + void *dmpsePtr;
3394 +} DialogMatchPatternSequenceElement;
3396 +typedef struct _DialogMatchPatternInfo {
3397 + int dmpiNbrOfSeqElements;
3398 + DialogMatchPatternSequenceElement *dmpiSequence[MAX_NBR_SEQ_ELEMENTS];
3399 +} DialogMatchPatternInfo;
3401 +typedef enum {
3402 + DMPTR_OK,
3403 + DMPTR_EMPTY,
3404 + DMPTR_INCOMPLETE
3405 +} DMPTranslationResult;
3407 +typedef struct _NameList {
3408 + int nlNumber;
3409 + char *nlId[MAX_NBR_SEQ_ELEMENTS + 1];
3410 +} NameList;
3413 + * prototypes of local functions
3414 + */
3415 +static void treatDuplicatedPattern(
3416 + MatchPatternTable *table,
3417 + PatternElement *prevPattern,
3418 + PatternReference prevPatRef,
3419 + PatternElement *lastPattern,
3420 + PatternReference lastPatRef);
3421 +static void treatDuplicatedPatternElements(
3422 + MatchPatternTable *table,
3423 + MatchPatternTableElement *prevElement,
3424 + int prevElementIdx,
3425 + PatternElement *lastPattern,
3426 + PatternReference lastPatRef);
3427 +static void treatDuplicatedMTElements(
3428 + MatchPatternTable *table,
3429 + MatchPatternTableElement *prevElement,
3430 + int prevElementIdx,
3431 + MatchPatternTableElement *lastElement,
3432 + int lastElementIdx);
3433 +static void treatDuplicatedMTEntries(
3434 + MatchPatternTableElement **element,
3435 + int nbrOfElements);
3437 +static int createStrPatRegExpOfElement(
3438 + ReadMatchPatternInfo *readPatInfo,
3439 + MatchPatternTableElement *element,
3440 + ErrorInfo *errInfo);
3441 +static int createStrPatRegExp(
3442 + StringPattern *strPat,
3443 + ErrorInfo *errInfo);
3444 +static void adaptCompileMsg(
3445 + char *compileMsg,
3446 + int *globalToLocalBackRef);
3447 +static int localToGlobalBackRef(
3448 + int *globalToLocalBackRef,
3449 + int localId);
3450 +static int createStartEndRegExp(
3451 + ReadMatchPatternInfo *readMatchPatternInfo,
3452 + MatchPatternTableElement *element,
3453 + ErrorInfo *errInfo);
3454 +static int createGroupRegExp(
3455 + ReadMatchPatternInfo *readPatInfo,
3456 + MatchPatternGroupElement *group,
3457 + ErrorInfo *errInfo);
3458 +static void setupRegExpStringBuffers(
3459 + ReadMatchPatternInfo *readMatchPatternInfo,
3460 + RegExpStringInfo *regExpStringInfo);
3461 +static void addSMTRegExpString(
3462 + char *result,
3463 + char *partToAdd,
3464 + const char *postfix);
3465 +static void composeStartEndRegExpString(
3466 + ReadMatchPatternInfo *readMatchPatternInfo,
3467 + MatchPatternTableElement *element,
3468 + char **regExpString);
3469 +static void addElementToRegExpString(
3470 + MatchPatternTableElement *element,
3471 + ReadMatchPatternInfo *readMatchPatternInfo,
3472 + RegExpStringInfo *regExpStringInfo);
3473 +static void addUniquePatternToRegExpString(
3474 + PatternElement *patElement,
3475 + PatternReference *patElementReference,
3476 + ReadMatchPatternInfo *readMatchPatternInfo,
3477 + RegExpStringInfo *regExpStringInfo);
3478 +static void addPatternToRegExpString(
3479 + StringPattern *pattern,
3480 + RegExpStringInfo *regExpStringInfo);
3481 +static char *adaptLocalBackRefs(
3482 + char *regExpText,
3483 + int *commonLocalId);
3484 +static void scanForLocalBackRefs(
3485 + char *regExpText,
3486 + int *localBackRefList);
3487 +static int isMultiPatternNotAdded(
3488 + RegExpStringInfo *regExpStringInfo,
3489 + PatternReference *toBeAddedPR);
3490 +static void catSMTRegExpStrings(
3491 + RegExpStringInfo *regExpStringInfo,
3492 + char **regExpString);
3493 +static void freeRegExpStringInfo(
3494 + RegExpStringInfo *regExpStringInfo);
3495 +static int totalKeywordOfTableLen(
3496 + ReadMatchPatternInfo *info,
3497 + int *nbrOfMultiPatterns);
3498 +static int totalMatchPatternTableElementLen(
3499 + ReadMatchPatternInfo *info,
3500 + MatchPatternTableElement *element,
3501 + int *nbrOfMultiPatterns);
3502 +static int patternElementLen(
3503 + ReadMatchPatternInfo *info,
3504 + PatternElement *patElement,
3505 + int *nbrOfMultiPatterns);
3507 +static void parseMatchingPatternSetError(
3508 + const char *stringStart,
3509 + const char *stoppedAt,
3510 + ErrorInfo *errInfo);
3511 +static void dialogMatchingPatternSetError(
3512 + char *title,
3513 + ErrorInfo *errInfo);
3515 +static char *createMatchPatternsString(
3516 + StringMatchTable *table,
3517 + char *indentStr);
3518 +static char *createPatternElementString(
3519 + MatchPatternTable *table,
3520 + PatternElement *pat);
3522 +static StringMatchTable *readDefaultStringMatchTable(const char *langModeName);
3523 +static int isDefaultMatchPatternTable(StringMatchTable *table);
3525 +static void freeReadMatchPatternInfo( ReadMatchPatternInfo *readPatInfo );
3526 +static void freeStringMatchTable( StringMatchTable *table );
3527 +static void freeMatchPatternTableElement( MatchPatternTableElement *element );
3528 +static void freePatternElement( PatternElement *element );
3529 +static void freeStringPattern( StringPattern *strPat );
3530 +static void freeMatchPatternGroupElement( MatchPatternGroupElement *group );
3531 +static void freeMatchPatternSequenceElement( MatchPatternSequenceElement *sequence );
3533 +static StringMatchTable *readMatchPatternSet(char **inPtr);
3534 +static StringMatchTable *readMatchPatternSetContent(
3535 + char **inPtr,
3536 + char *stringStart,
3537 + char *languageMode);
3538 +static int createRegExpOfPatterns(
3539 + ReadMatchPatternInfo *readPatInfo,
3540 + ErrorInfo *errInfo);
3541 +static int createRegExpOfAllPatterns(
3542 + ReadMatchPatternInfo *readPatInfo,
3543 + ErrorInfo *errInfo);
3544 +static int createRegExpOfStrPatterns(
3545 + ReadMatchPatternInfo *readPatInfo,
3546 + ErrorInfo *errInfo);
3547 +static StringMatchTable *createStringMatchTable(
3548 + ReadMatchPatternInfo *readPatInfo,
3549 + char *languageMode);
3550 +static int readMatchPatternEntry(
3551 + char **inPtr,
3552 + ErrorInfo *errInfo,
3553 + ReadMatchPatternInfo *info);
3554 +static void recordPatternSequence(
3555 + ReadMatchPatternInfo *info,
3556 + char *name,
3557 + MatchPatternType type,
3558 + int index);
3559 +static int assignIndividualGroup(
3560 + ReadMatchPatternInfo *info,
3561 + char **errMsg,
3562 + MatchPatternTableElement *element);
3563 +static MatchPatternTableElement *getPatternOfName(
3564 + ReadMatchPatternInfo *info,
3565 + char *subPatToSearch);
3566 +static MatchPatternGroupElement *readMatchPatternGroup(
3567 + char **inPtr,
3568 + ErrorInfo *errInfo,
3569 + char *name,
3570 + ReadMatchPatternInfo *info);
3571 +static int readPatternElement(
3572 + char **inPtr,
3573 + char **errMsg,
3574 + PatternElement **pattern);
3575 +static PatternElement *createPatternElement(
3576 + char *patternText,
3577 + PatternElementKind patternKind,
3578 + PatternWordBoundary wordBoundary,
3579 + int caseInsensitive,
3580 + int regularExpression);
3582 +static int createGlobalBackRefList(
3583 + ReadMatchPatternInfo *readPatInfo,
3584 + MatchPatternTableElement *element,
3585 + ErrorInfo *errInfo);
3586 +StringPattern *getReadStringPattern(
3587 + ReadMatchPatternInfo *readPatInfo,
3588 + PatternElement *pattern );
3589 +static PatternElement *getReadPatternOfReference(
3590 + ReadMatchPatternInfo *readPatInfo,
3591 + PatternReference *patRef);
3592 +static char *replaceCapturingParentheses(
3593 + const char *source);
3594 +static int parseGlobalBackRefs(
3595 + StringPattern *strPat,
3596 + GlobalBackRefElement *backRefList,
3597 + ErrorInfo *errInfo);
3598 +static int updateGlobalBackRefs(
3599 + StringPattern *strPat,
3600 + GlobalBackRefElement *backRefList,
3601 + ErrorInfo *errInfo);
3602 +static char *createBackRefRegExpText(
3603 + const char *start,
3604 + const char *end);
3605 +static int resolveGlobalBackRefs(
3606 + ReadMatchPatternInfo *readPatInfo,
3607 + MatchPatternTableElement *element,
3608 + ErrorInfo *errInfo);
3609 +static int resolveGlobalBackRefsOfStrPat(
3610 + StringPattern *strPat,
3611 + GlobalBackRefElement *backRefList,
3612 + ErrorInfo *errInfo);
3613 +static char *substituteGlobalBackRef(
3614 + StringPattern *strPat,
3615 + char *subsPtr,
3616 + int globalId,
3617 + int *localId,
3618 + GlobalBackRefElement *backRefList,
3619 + ErrorInfo *errInfo);
3620 +static char *replaceBackRefIdByRegExp(
3621 + StringPattern *strPat,
3622 + char *replaceStartPtr,
3623 + char *regExp);
3624 +static char *convertGlobalToLocalBackRef(
3625 + StringPattern *strPat,
3626 + char *convertPtr);
3628 +static MatchPatternTableElement *readMatchPatternTableElement(
3629 + char **inPtr,
3630 + char **errMsg,
3631 + char *name,
3632 + MatchPatternType type);
3633 +static int sortReadPatternElementSet(
3634 + PatternElementSet *allPat,
3635 + char **errMsg,
3636 + MatchPatternTableElement *result);
3637 +static void countPatternElementKind(
3638 + PatternElementSet *allPat,
3639 + MatchPatternTableElement *result);
3640 +static void sortPatternElementSet(
3641 + PatternElementSet *allPat,
3642 + MatchPatternTableElement *result);
3643 +static void copyPatternSet(
3644 + PatternElementSet *sourcePS,
3645 + PatternElementSet *destPS);
3647 +static int getMPSName(
3648 + char **inPtr,
3649 + ErrorInfo *errInfo,
3650 + char **name );
3651 +static int getMPSTypeAttribute(
3652 + char **inPtr,
3653 + ErrorInfo *errInfo,
3654 + MatchPatternType *type);
3655 +static int getMPSGlobalAttribute(
3656 + char **inPtr,
3657 + char **errMsg,
3658 + int *isMonoPattern,
3659 + int *comment,
3660 + int *flash,
3661 + int *ignoreHighLightInfo);
3662 +static int getMPSPatternAttribute(
3663 + char **inPtr,
3664 + char **errMsg,
3665 + PatternElementKind *patternKind,
3666 + PatternWordBoundary *wordBoundary,
3667 + int *caseInsensitive,
3668 + int *regularExpression);
3670 +static void copyStringMatchTableForDialog(
3671 + StringMatchTable *sourceTable,
3672 + DialogMatchPatternInfo *dialogTable );
3673 +static void *copyMatchPatternElementForDialog(
3674 + MatchPatternTable *table,
3675 + int sourceElementIdx);
3676 +static void copyPatternForDialog(
3677 + MatchPatternTable *table,
3678 + PatternElement *sourcePattern,
3679 + DialogStringPatternElement **dialogPattern );
3680 +static void *copyGroupElementForDialog(
3681 + MatchPatternGroupElement *sourceGroup);
3682 +static void copySequenceElementForDialog(
3683 + StringMatchTable *sourceTable,
3684 + MatchPatternSequenceElement *sourceSeqElement,
3685 + DialogMatchPatternSequenceElement **dialogSeqElement );
3686 +static DialogMatchPatternSequenceElement *copyDialogSequenceElement(
3687 + DialogMatchPatternSequenceElement *sourceSeq);
3688 +static void freeDialogMatchPatternElement(
3689 + DialogMatchPatternTableElement *dialogElement );
3690 +static void freeDialogStringPatternElement(
3691 + DialogStringPatternElement *element);
3692 +static void freeDialogGroupElement(
3693 + DialogMatchPatternGroupElement *dialogGroup );
3694 +static void freeDialogSequenceElement(
3695 + DialogMatchPatternSequenceElement *dialogSeq );
3697 +static void copyDialogStringPatternsFromTable(
3698 + DialogMatchPatternTableElement *tableElement,
3699 + DialogStringPatterns *destPatterns);
3700 +static void copyDialogStringPatterns(
3701 + DialogStringPatterns *sourcePatterns,
3702 + DialogStringPatterns *destPatterns);
3703 +static void freeDialogStringPatterns(
3704 + DialogStringPatterns *patterns);
3706 +static DialogStringPatternElement *copyDialogStringPatternElement(
3707 + DialogStringPatternElement *sourceElement);
3709 +static void copyDialogPatternNamesFromGroup(
3710 + DialogMatchPatternGroupElement *group,
3711 + DialogStringPatterns *destPatterns);
3712 +static DialogStringPatternElement *copyDialogPatternName(
3713 + char *sourcePatternId);
3714 +static void copyDialogPatternNamesToGroup(
3715 + DialogStringPatterns *sourceNames,
3716 + DialogMatchPatternGroupElement *destGroup);
3718 +static void setDialogType(int dialogShowsStringPattern);
3719 +static void setSensitiveWordBoundaryBox(int enable);
3721 +static void *getStringPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
3722 + void *cbArg);
3723 +static void setStringPatternDisplayedCB(void *item, void *cbArg);
3724 +static void freeStringPatternItemCB(void *item);
3726 +static void *getMatchPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
3727 + void *cbArg);
3728 +static void setMatchPatternDisplayedCB(void *item, void *cbArg);
3729 +static void freeMatchPatternItemCB(void *item);
3730 +static int deleteMatchPatternItemCB(int itemIndex, void *cbArg);
3732 +static void matchPatternLangModeCB(Widget w, XtPointer clientData, XtPointer callData);
3733 +static void pmLanguageModeDialogCB(Widget w, XtPointer clientData, XtPointer callData);
3735 +static void destroyCB(Widget w, XtPointer clientData, XtPointer callData);
3736 +static void okCB(Widget w, XtPointer clientData, XtPointer callData);
3737 +static void applyCB(Widget w, XtPointer clientData, XtPointer callData);
3738 +static void checkCB(Widget w, XtPointer clientData, XtPointer callData);
3739 +static void restoreCB(Widget w, XtPointer clientData, XtPointer callData);
3740 +static void deleteCB(Widget w, XtPointer clientData, XtPointer callData);
3741 +static void closeCB(Widget w, XtPointer clientData, XtPointer callData);
3742 +static void helpCB(Widget w, XtPointer clientData, XtPointer callData);
3744 +static void matchPatTypeCB(Widget w, XtPointer clientData, XtPointer callData);
3745 +static void strPatRegExpressionCB(Widget w, XtPointer clientData, XtPointer callData);
3746 +static void changeExistingSubPattern(char *warnTitle);
3747 +static void changeStringPatternToGroup(void);
3748 +static void changeGroupToStringPattern(char *warnTitle);
3750 +static Widget createSubPatternNameMenu(
3751 + Widget parent,
3752 + char *currentSubPatName,
3753 + int allSubPatterns);
3754 +static void setupSubPatternNameList(
3755 + char *currentSubPatName,
3756 + int allSubPatterns,
3757 + NameList *nameList);
3758 +static void createSubPatNameMenuEntry(
3759 + Widget menu,
3760 + char *subPatName);
3761 +static void setSubPatternNameMenu(
3762 + const char *subPatName);
3763 +static void updateSubPatternNameMenu(
3764 + char *currentSubPatName,
3765 + int allSubPatterns);
3766 +static char *getSelectedSubPatternName(void);
3767 +static int isSubPatternNameInCurStrPat(
3768 + char *subPatName);
3770 +static DialogMatchPatternSequenceElement *readMatchPatternFields(int silent);
3771 +static int isStartPatternElementAvailable(
3772 + DialogStringPatterns *dialogPatterns);
3773 +static DialogStringPatternElement *readStringPatternFrameFields(int silent);
3775 +static int matchPatternDialogEmpty(void);
3776 +static int stringPatternFrameEmpty(void);
3777 +static int stringPatternFieldsEmpty(
3778 + int strPatIsRelatedToGroup);
3780 +static int getAndUpdateStringMatchTable(void);
3781 +static void updateStringMatchTable(
3782 + StringMatchTable *newTable);
3784 +static StringMatchTable *getDialogStringMatchTable(
3785 + DMPTranslationResult *result);
3786 +static StringMatchTable *translateDialogStringMatchTable(
3787 + DialogMatchPatternInfo *dialogTable,
3788 + DMPTranslationResult *result);
3789 +static MatchPatternTableElement *translateDialogMatchPatternTableElement(
3790 + DialogMatchPatternTableElement *dialogElement);
3791 +static void translateDialogPatterns(
3792 + DialogStringPatterns *dialogPatterns,
3793 + MatchPatternTableElement *newElement);
3794 +static MatchPatternGroupElement *translateDialogMatchPatternGroupElement(
3795 + ReadMatchPatternInfo *info,
3796 + DialogMatchPatternGroupElement *dialogGroup);
3797 +static void sortDialogPatternElementSet(
3798 + PatternElementSet *allPat,
3799 + MatchPatternTableElement *result);
3801 +static int stringMatchTableDiffer(
3802 + StringMatchTable *oldTable,
3803 + StringMatchTable *newTable);
3805 +static int patternElementDiffer(
3806 + PatternElement *oldPE,
3807 + MatchPatternTable *oldTab,
3808 + PatternElement *newPE,
3809 + MatchPatternTable *newTab);
3811 +static DialogMatchPatternGroupElement *getDialogGroupUsingMatchPattern(
3812 + char *matchPatternName);
3813 +static void removeMatchPatternFromGroup(
3814 + char *matchPatternName,
3815 + DialogMatchPatternGroupElement *group);
3816 +static void removeMatchPatternFromAllGroups(
3817 + char *matchPatternName);
3818 +static void renameMatchPatternInGroup(
3819 + char *oldMatchPatternName,
3820 + char *newMatchPatternName,
3821 + DialogMatchPatternGroupElement *group);
3822 +static void renameMatchPatternInAllGroups(
3823 + char *oldMatchPatternName,
3824 + char *newMatchPatternName);
3826 +static void freeVariableDialogData(
3827 + int keepLanguageModeName);
3829 +static void initGlobalBackRefList(
3830 + GlobalBackRefElement *list);
3831 +static void initStrPatBackRefList(
3832 + StringPattern *strPat);
3834 +StringPattern *getUniqueStringPattern(
3835 + PatternElement *pattern );
3837 +static void initErrorInfo(
3838 + ErrorInfo *errInfo);
3839 +static void freeErrorInfo(
3840 + ErrorInfo *errInfo);
3842 +static void freeXtPtr(void **ptr);
3843 +static void freePtr(void **ptr);
3846 + * matching pattern dialog information
3847 + */
3848 +static struct {
3849 + Widget mpdShell;
3850 + Widget mpdLmOptMenu;
3851 + Widget mpdLmPulldown;
3852 + Widget mpdMatchPatternNamesListW;
3853 + Widget mpdMatchPatternNameLbl;
3854 + Widget mpdMatchPatternNameW;
3855 + Widget mptbIndividualW;
3856 + Widget mptbSubPatternW;
3857 + Widget mptbContextGroupW;
3858 + Widget mpdGlobalAttributesLbl;
3859 + Widget gabSkipBtwStartEndW;
3860 + Widget gabFlashW;
3861 + Widget gabSyntaxBasedW;
3862 + Widget mpdStringPatternsLbl;
3863 + Widget mpdStringPatternsListW;
3864 + Widget mpdStringPatternTypeLbl;
3865 + Widget sptStartW;
3866 + Widget sptMiddleW;
3867 + Widget sptEndW;
3868 + Widget mpdWordBoundaryLbl;
3869 + Widget wbbBothW;
3870 + Widget wbbLeftW;
3871 + Widget wbbRightW;
3872 + Widget wbbNoneW;
3873 + Widget mpdStringAttributesLbl;
3874 + Widget sabCaseSensitiveW;
3875 + Widget sabRegularExpressionW;
3876 + Widget mpdStringPatternLbl;
3877 + Widget mpdStringPatternW;
3878 + Widget mpdSubPatNamesLbl;
3879 + Widget mpdSubPatNamesOptMenu;
3880 + Widget mpdSubPatNamesPulldown;
3881 + char *mpdLangModeName;
3882 + DialogMatchPatternSequenceElement *currentDmptSeqElement;
3883 + DialogMatchPatternTableElement *currentDmptElement;
3884 + DialogMatchPatternGroupElement *currentDmptGroup;
3885 + DialogStringPatterns currentStringPatterns;
3886 + DialogMatchPatternInfo mpdTable;
3887 + int mpdStringPatternIsDisplayed;
3888 +} MatchPatternDialog =
3889 + {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3890 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3891 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3892 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3893 + NULL, NULL, NULL, NULL,
3894 + {0, {NULL}},
3895 + {0, {NULL}},
3896 + True
3897 + };
3900 + * Matching pattern sources loaded from the nedit resources file or set
3901 + * by the user
3902 + */
3903 +static int NbrMatchTables = 0;
3904 +static StringMatchTable *MatchTables[MAX_LANGUAGE_MODES];
3907 + * Syntax:
3908 + * LanguagePatternSet ::=
3909 + * LanguageName{PatternStatement..}
3911 + * PatternStatement ::=
3912 + * name:[s]:[c][f][m][p][u]:([s|m|e][w|l|r][i]:"pattern":)..)\n)|
3913 + * name:g:"sub-pattern name":..\n..
3915 + * TypeAttribute:
3916 + * s : sub-pattern (pattern is only matched, if part of a pattern group).
3917 + * g : pattern (context) group (i.e. a sequence of sub-patterns).
3918 + * default: individual pattern (pattern is matched individually).
3919 + * GlobalAttribute:
3920 + * c : the content between start and end pattern is skipped
3921 + * during parsing (e.g. pattern encloses a comment).
3922 + * f : flash matching pattern (if not set, then only jump
3923 + * to matching pattern is supported).
3924 + * m : mono pattern - set exist out of only one single pattern
3925 + * (start pattern = end pattern; e.g. quotes like ")
3926 + * p : ignore highlight info code of single patterns of this set
3927 + * ("plain").
3928 + * StringPatternKind:
3929 + * s : start string pattern.
3930 + * m : middle string pattern.
3931 + * e : end string pattern.
3932 + * WordBoundaryAttribute:
3933 + * w : pattern is word (i.e. before and after pattern
3934 + * there must be a delimiter).
3935 + * l : before pattern must be a delimiter (left side).
3936 + * r : after pattern must be a delimiter (right side).
3937 + * default: neither before nor after pattern must be a delimiter.
3938 + * StringAttribute:
3939 + * i : pattern is case insensitive (if not set: pattern is
3940 + * case sensitive).
3941 + * x : pattern is regular expression (if not set: pattern is
3942 + * literal string).
3944 + * \n : end of pattern
3945 + */
3947 +static char *DefaultStringMatchTable[] = {
3948 + "PLAIN{"
3949 + "Round braces::fp:s:\"(\":e:\")\":\n"
3950 + "Curly braces::fp:s:\"{\":e:\"}\":\n"
3951 + "Squared braces::fp:s:\"[\":e:\"]\":\n"
3952 + "Sharp braces::fp:s:\"<\":e:\">\":\n}",
3953 + "C++{"
3954 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
3955 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3956 + "Single Quotes:s:cmf:s:\"'\":\n"
3957 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3958 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3959 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3960 + "#ifdef statement:s:f:sx:\"#\\s*ifdef\":sx:\"#\\s*ifndef\":sx:\"#\\s*if\":mx:\"#\\s*elif\":mx:\"#\\s*else\":ex:\"#\\s*endif\":\n"
3961 + "#if group:g:Comment:Double Quotes:Single Quotes:#ifdef statement:\n"
3962 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
3963 + "C{"
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 + "#ifdef statement:s:f:sx:\"#\\s*ifdef\":sx:\"#\\s*ifndef\":sx:\"#\\s*if\":mx:\"#\\s*elif\":mx:\"#\\s*else\":ex:\"#\\s*endif\":\n"
3971 + "#if group:g:Comment:Double Quotes:Single Quotes:#ifdef statement:\n"
3972 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
3973 + "CSS{"
3974 + "comment:s:cf:s:\"/*\":e:\"*/\":\n"
3975 + "curly braces:s:f:s:\"{\":e:\"}\":\n"
3976 + "round braces:s:f:s:\"(\":e:\")\":\n"
3977 + "double quotes:s:cfm:s:\"\"\"\":\n"
3978 + "single quotes:s:cfm:s:\"'\":\n"
3979 + "braces:g:comment:single quotes:double quotes:curly braces:round braces:\n}",
3980 + "Csh{"
3981 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3982 + "Single Quotes:s:cmf:s:\"'\":\n"
3983 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3984 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3985 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3986 + "if statement:s:f:sw:\"if\":mw:\"else\":ew:\"endif\":\n"
3987 + "switch statement:s:f:sw:\"switch\":mw:\"case\":mw:\"default\":ew:\"endsw\":\n"
3988 + "foreach statement:s:f:sw:\"for\":ew:\"end\":\n"
3989 + "while statement:s:f:sw:\"while\":ew:\"end\":\n"
3990 + "statement group:g:Double Quotes:Single Quotes:if statement:switch statement:foreach statement:while statement:\n"
3991 + "Braces:g:Double Quotes:Single Quotes:Squared braces:Round braces:Curly braces:\n}",
3992 + "Java{"
3993 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
3994 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3995 + "Single Quotes:s:cmf:s:\"'\":\n"
3996 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3997 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3998 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3999 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
4000 + "JavaScript{"
4001 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
4002 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4003 + "Single Quotes:s:cmf:s:\"'\":\n"
4004 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4005 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4006 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4007 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
4008 + "Makefile{"
4009 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4010 + "Single Quotes:s:cmf:s:\"'\":\n"
4011 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4012 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4013 + "Braces:g:Double Quotes:Single Quotes:Curly braces:Round braces:\n}",
4014 + "NEdit Macro{"
4015 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4016 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4017 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4018 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4019 + "Braces:g:Double Quotes:Curly braces:Round braces:Squared braces:\n}",
4020 + "Pascal{"
4021 + "Single Quotes:s:cmf:s:\"'\":\n"
4022 + "Comment1:s:cf:s:\"(*\":e:\"*)\":\n"
4023 + "Comment2:s:cf:s:\"{\":e:\"}\":\n"
4024 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4025 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4026 + "Block:s:f:swi:\"begin\":ewi:\"end\":\n"
4027 + "Case:s:fp:swi:\"case\":ewi:\"end\":\n"
4028 + "Record:s:f:swi:\"record\":ewi:\"end\":\n"
4029 + "Statement:g:Comment1:Comment2:Single Quotes:Block:Case:Record:\n"
4030 + "Braces:g:Comment1:Comment2:Single Quotes:Round braces:Squared braces:\n}",
4031 + "Perl{"
4032 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
4033 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4034 + "Single Quotes:s:cmf:s:\"'\":\n"
4035 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4036 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4037 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4038 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
4039 + "SGML HTML{"
4040 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4041 + "Single Quotes:s:cmf:s:\"'\":\n"
4042 + "Sharp braces:s:f:s:\"<\":e:\">\":\n"
4043 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4044 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4045 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4046 + "Braces:g:Double Quotes:Single Quotes:Sharp braces:Curly braces:Round braces:Squared braces:\n}",
4047 + "Sh Ksh Bash{"
4048 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4049 + "Single Quotes:s:cmf:s:\"'\":\n"
4050 + "Back Quotes:s:cfm:s:\"`\":\n"
4051 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4052 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4053 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4054 + "if statement:s:f:sw:\"if\":mw:\"elif\":mw:\"else\":ew:\"fi\":\n"
4055 + "case statement:s:f:sw:\"case\":ew:\"esac\":\n"
4056 + "for statement:s:f:sw:\"for\":mw:\"do\":ew:\"done\":\n"
4057 + "while statement:s:f:sw:\"while\":mw:\"do\":ew:\"done\":\n"
4058 + "statement group:g:Double Quotes:Single Quotes:if statement:case statement:for statement:while statement:\n"
4059 + "Braces:g:Double Quotes:Single Quotes:Back Quotes:Squared braces:Round braces:Curly braces:\n}",
4060 + "XML{"
4061 + "round braces:s:f:s:\"(\":e:\")\":\n"
4062 + "comment:s:cf:s:\"<!--\":e:\"-->\":\n"
4063 + "cdata + ignore:s:cf:sx:\"\\<!\\[((?icdata)|(\\s*IGNORE\\s*))\\[\":ex:\"\\]\\]\\>\":\n"
4064 + "short element:s:cf:sx:\"(?n\\<[\\l_][^@$%/\"\"';!>\\s]*(?=[^>]*/\\>))\":ex:\"/\\>\":\n"
4065 + "element pair:s:f:sx:\"(?n\\<(*1[\\l|_][^@$%/\"\"';!>\\s]*)\\>)\":sx:\"(?n\\<(*1[\\l|_][^@$%/\"\"';!>\\s]*)(?=[^>]*[^/]\\>))\":eix:\"\\</\\1\\>\":\n"
4066 + "processing instruction:s:f:sx:\"\\<\\?\\S+\":ex:\"\\?\\>\":\n"
4067 + "double quotes:s:cmf:s:\"\"\"\":\n"
4068 + "single quotes:s:cmf:s:\"'\":\n"
4069 + "tags:g:comment:double quotes:single quotes:round braces:cdata + ignore:element pair:short element:processing instruction:\n}",
4070 + };
4072 +static char *StandardStringMatchTable =
4073 + "{Round braces::fp:s:\"(\":e:\")\":\n"
4074 + "Curly braces::fp:s:\"{\":e:\"}\":\n"
4075 + "Squared braces::fp:s:\"[\":e:\"]\":\n}";
4078 +** Return string match table related to given language mode name.
4079 +** Return NULL, if no table is found.
4081 +void *FindStringMatchTable(const char *langModeName)
4083 + const char *nameToSearch;
4084 + int i;
4086 + if (langModeName == NULL)
4087 + nameToSearch = PLAIN_LM_STRING;
4088 + else
4089 + nameToSearch = langModeName;
4091 + for (i=0; i<NbrMatchTables; i++)
4092 + if (!strcmp(nameToSearch, MatchTables[i]->smtLanguageMode))
4093 + return (void *)MatchTables[i];
4094 + return NULL;
4098 +** Change the language mode name of string match tables for language
4099 +** "oldName" to "newName" in both the stored tables, and the table
4100 +** currently being edited in the dialog.
4102 +void RenameStringMatchTable(const char *oldName, const char *newName)
4104 + int i;
4106 + for (i=0; i<NbrMatchTables; i++)
4108 + if (!strcmp(oldName, MatchTables[i]->smtLanguageMode))
4110 + XtFree(MatchTables[i]->smtLanguageMode);
4111 + MatchTables[i]->smtLanguageMode = XtNewString(newName);
4114 + if (MatchPatternDialog.mpdShell != NULL)
4116 + if (!strcmp(MatchPatternDialog.mpdLangModeName, oldName))
4118 + XtFree(MatchPatternDialog.mpdLangModeName);
4119 + MatchPatternDialog.mpdLangModeName = XtNewString(newName);
4125 +** Delete string match table related to given language mode name.
4127 +void DeleteStringMatchTable(const char *langModeName)
4129 + int i;
4131 + for (i=0; i<NbrMatchTables; i++)
4133 + if (!strcmp(langModeName, MatchTables[i]->smtLanguageMode))
4135 + /*
4136 + * free (delete) existing matching pattern
4137 + */
4138 + freeStringMatchTable(MatchTables[i]);
4139 + memmove(
4140 + &MatchTables[i],
4141 + &MatchTables[i+1],
4142 + (NbrMatchTables-1 - i) * sizeof(StringMatchTable *));
4143 + NbrMatchTables--;
4144 + break;
4150 +** Assign a standard string match table to a given new language mode.
4152 +void AssignStandardStringMatchTable(const char *langModeName)
4154 + char *list;
4155 + StringMatchTable *newTable;
4157 + /*
4158 + * assign standard table for new language mode
4159 + * add table to end
4160 + */
4161 + list = StandardStringMatchTable;
4162 + newTable =
4163 + readMatchPatternSetContent(&list, list, XtNewString(langModeName));
4165 + /*
4166 + * add table to end
4167 + */
4168 + MatchTables[NbrMatchTables++] = newTable;
4172 +** Returns True if there is a string match table, or potential table
4173 +** not yet committed in the match pattern dialog for a language mode,
4175 +int LMHasStringMatchTable(const char *languageMode)
4177 + StringMatchTable *table = FindStringMatchTable(languageMode);
4179 + if (table != NULL && table->smtNumberOfSeqElements != 0)
4180 + return True;
4181 + return MatchPatternDialog.mpdShell != NULL &&
4182 + !strcmp(MatchPatternDialog.mpdLangModeName, languageMode) &&
4183 + MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements != 0;
4187 +** Read a string representing string matching pattern sets and add them
4188 +** to the StringMatchTable list of loaded string match patterns.
4189 +** Returns true, if read of string was successful.
4191 +int LoadMatchPatternString(char *inString)
4193 + char *inPtr = inString;
4194 + StringMatchTable *table;
4195 + int i;
4197 + for (;;)
4199 + /*
4200 + * read each matching pattern set
4201 + */
4202 + table = readMatchPatternSet(&inPtr);
4204 + if (table != NULL)
4206 + /*
4207 + * add/change the pattern set in the list
4208 + */
4209 + for (i=0; i<NbrMatchTables; i++)
4211 + if (!strcmp(MatchTables[i]->smtLanguageMode, table->smtLanguageMode))
4213 + freeStringMatchTable(MatchTables[i]);
4214 + MatchTables[i] = table;
4215 + break;
4218 + if (i == NbrMatchTables)
4220 + MatchTables[NbrMatchTables++] = table;
4221 + if (NbrMatchTables > MAX_LANGUAGE_MODES)
4223 + return False;
4228 + /*
4229 + * find end of this pattern. if the string ends here, we're done
4230 + */
4231 + inPtr = strstr(inPtr, "\n");
4232 + if (inPtr == NULL)
4234 + return True;
4237 + /*
4238 + * skip newline, tabs & spaces in front of next pattern.
4239 + * if the string ends here, we're done
4240 + */
4241 + inPtr += strspn(inPtr, " \t\n");
4242 + if (*inPtr == '\0')
4244 + return True;
4250 +** Create a string in the correct format for the matchPatterns resource,
4251 +** containing all of the matching pattern information from the stored
4252 +** matching pattern sets for this NEdit session.
4254 +char *WriteMatchPatternString(void)
4256 + char *outStr, *str, *escapedStr;
4257 + textBuffer *outBuf;
4258 + int i, written = False;
4259 + StringMatchTable *table;
4261 + outBuf = BufCreate();
4263 + for (i=0; i<NbrMatchTables; i++)
4265 + table = MatchTables[i];
4267 + written = True;
4269 + BufInsert(outBuf, outBuf->length, table->smtLanguageMode);
4270 + BufInsert(outBuf, outBuf->length, ":");
4272 + if (isDefaultMatchPatternTable(table))
4274 + BufInsert(outBuf, outBuf->length, "Default\n\t");
4276 + else
4278 + BufInsert(outBuf, outBuf->length, "{\n");
4279 + BufInsert(outBuf, outBuf->length,
4280 + str = createMatchPatternsString(table, "\t\t"));
4281 + XtFree(str);
4282 + BufInsert(outBuf, outBuf->length, "\t}\n\t");
4286 + /*
4287 + * Get the output string, and lop off the trailing newline and tab
4288 + */
4289 + outStr = BufGetRange(outBuf, 0, outBuf->length - (written?2:0));
4290 + BufFree(outBuf);
4292 + /*
4293 + * Protect newlines and backslashes from translation by the resource
4294 + * reader
4295 + */
4296 + escapedStr = EscapeSensitiveChars(outStr);
4298 + XtFree(outStr);
4300 + return escapedStr;
4304 +** Check, if last pattern is a duplicate of a previous pattern.
4305 +** Convert last pattern to a reference, if so.
4307 +static void treatDuplicatedPattern(
4308 + MatchPatternTable *table,
4309 + PatternElement *prevPattern,
4310 + PatternReference prevPatRef,
4311 + PatternElement *lastPattern,
4312 + PatternReference lastPatRef)
4314 + StringPattern *prevStringPat;
4315 + StringPattern *lastStringPat;
4316 + StringPattern *stringPat;
4317 + PatternReference *oldList;
4318 + int nbrOfRef;
4320 + /*
4321 + * No duplicate check needed, if previous pattern is a reference,
4322 + * due to the related multi pattern element is checked before.
4323 + */
4324 + if (prevPattern->peType == PET_REFERENCE)
4325 + return;
4327 + prevStringPat = GetStringPattern(table, prevPattern);
4328 + lastStringPat = GetStringPattern(table, lastPattern);
4330 + if (!AllocatedStringsDiffer(prevStringPat->spText, lastStringPat->spText) &&
4331 + !AllocatedStringsDiffer(prevStringPat->spOrigText, lastStringPat->spOrigText) &&
4332 + prevStringPat->spWordBoundary == lastStringPat->spWordBoundary &&
4333 + prevStringPat->spCaseInsensitive == lastStringPat->spCaseInsensitive &&
4334 + prevStringPat->spRegularExpression == lastStringPat->spRegularExpression)
4336 + /*
4337 + * Patterns are identical: Is prevPattern already a multi pattern ?
4338 + */
4339 + if (prevPattern->peType == PET_MULTIPLE)
4341 + /*
4342 + * just add ref. to "lastPattern" to the ref. list
4343 + */
4344 + (prevPattern->peVal.peuMulti.mpNumberOfReferences) ++;
4345 + nbrOfRef = prevPattern->peVal.peuMulti.mpNumberOfReferences;
4346 + oldList = prevPattern->peVal.peuMulti.mpRefList;
4347 + prevPattern->peVal.peuMulti.mpRefList =
4348 + (PatternReference *)XtMalloc( nbrOfRef * sizeof(PatternReference) );
4349 + memcpy(
4350 + prevPattern->peVal.peuMulti.mpRefList,
4351 + oldList,
4352 + (nbrOfRef-1) * sizeof(PatternReference) );
4353 + prevPattern->peVal.peuMulti.mpRefList[nbrOfRef-1] = lastPatRef;
4354 + XtFree( (char *)oldList );
4356 + else
4358 + /*
4359 + * convert prev. single pattern to multi pattern
4360 + */
4361 + stringPat = &prevPattern->peVal.peuSingle;
4362 + prevPattern->peType = PET_MULTIPLE;
4363 + prevPattern->peVal.peuMulti.mpStringPattern = *stringPat;
4364 + prevPattern->peVal.peuMulti.mpNumberOfReferences = 1;
4365 + prevPattern->peVal.peuMulti.mpRefList =
4366 + (PatternReference *)XtMalloc( sizeof(PatternReference) );
4367 + prevPattern->peVal.peuMulti.mpRefList[0] = lastPatRef;
4370 + /*
4371 + * convert last single pattern to reference
4372 + */
4373 + freeStringPattern( &(lastPattern->peVal.peuSingle) );
4374 + lastPattern->peType = PET_REFERENCE;
4375 + lastPattern->peVal.peuRef = prevPatRef;
4380 +** Check, if last pattern is a duplicate of a pattern stored within a
4381 +** previous match pattern table element.
4382 +** Convert last pattern to a reference, if so.
4384 +static void treatDuplicatedPatternElements(
4385 + MatchPatternTable *table,
4386 + MatchPatternTableElement *prevElement,
4387 + int prevElementIdx,
4388 + PatternElement *lastPattern,
4389 + PatternReference lastPatRef)
4391 + int i;
4392 + PatternReference prevPatRef;
4394 + prevPatRef.prElementIdx = prevElementIdx;
4396 + for (i=0; i<prevElement->mpteAll.pesNumberOfPattern; i++)
4398 + prevPatRef.prPatternIdx = i;
4399 + treatDuplicatedPattern(
4400 + table,
4401 + prevElement->mpteAll.pesPattern[i],
4402 + prevPatRef,
4403 + lastPattern,
4404 + lastPatRef);
4409 +** Check, if a pattern of last match pattern table element is a
4410 +** duplicate of a pattern stored within a previous match pattern table
4411 +** element.
4412 +** Convert duplicated last patterns to references, if so.
4414 +static void treatDuplicatedMTElements(
4415 + MatchPatternTable *table,
4416 + MatchPatternTableElement *prevElement,
4417 + int prevElementIdx,
4418 + MatchPatternTableElement *lastElement,
4419 + int lastElementIdx)
4421 + int i;
4422 + PatternReference lastPatRef;
4424 + lastPatRef.prElementIdx = lastElementIdx;
4426 + for (i=0; i<lastElement->mpteAll.pesNumberOfPattern; i++)
4428 + lastPatRef.prPatternIdx = i;
4429 + treatDuplicatedPatternElements(
4430 + table,
4431 + prevElement,
4432 + prevElementIdx,
4433 + lastElement->mpteAll.pesPattern[i],
4434 + lastPatRef);
4439 +** Convert all duplicated patterns of given match pattern table to
4440 +** references.
4442 +static void treatDuplicatedMTEntries(
4443 + MatchPatternTableElement **element,
4444 + int nbrOfElements)
4446 + int i;
4447 + MatchPatternTableElement *lastElement;
4448 + int lastElementIdx;
4449 + MatchPatternTable table;
4451 + if (nbrOfElements < 2)
4452 + return;
4454 + lastElementIdx = nbrOfElements - 1;
4455 + lastElement = element[lastElementIdx];
4457 + table.mptElements = element;
4458 + table.mptNumberOfElements = nbrOfElements;
4460 + for (i=0; i<nbrOfElements-1; i ++)
4462 + treatDuplicatedMTElements( &table, element[i], i, lastElement, lastElementIdx );
4467 +** Compile regular expressions of all string patterns of given
4468 +** match pattern table element.
4469 +** Returns true, if compilation fails.
4471 +static int createStrPatRegExpOfElement(
4472 + ReadMatchPatternInfo *readPatInfo,
4473 + MatchPatternTableElement *element,
4474 + ErrorInfo *errInfo)
4476 + int i;
4477 + StringPattern *strPat;
4479 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
4481 + strPat = getReadStringPattern(readPatInfo, element->mpteAll.pesPattern[i]);
4483 + /*
4484 + * if current string pattern holds a regular expression, then
4485 + * compile it
4486 + */
4487 + if (strPat->spRegularExpression)
4489 + if (createStrPatRegExp(strPat, errInfo))
4491 + /*
4492 + * compilation was not successful
4493 + */
4494 + errInfo->eiMPTabElementName = XtNewString(element->mpteName);
4495 + return True;
4500 + return False;
4504 +** Compile regular expressions of given string pattern.
4505 +** Returns true, if compilation fails.
4507 +static int createStrPatRegExp(
4508 + StringPattern *strPat,
4509 + ErrorInfo *errInfo)
4511 + char *regExpString;
4512 + char *compileMsg;
4514 + /*
4515 + * compose regular expression for start string pattern.
4516 + */
4517 + if( strPat->spCaseInsensitive)
4519 + /*
4520 + * Add '(?i .. )' to given text for case insensitive search.
4521 + * Allocate buffer to hold 5 more char than text length
4522 + * (4 char '(?i)' + \0 char.
4523 + */
4524 + regExpString = XtMalloc(strPat->spLength + 5);
4525 + strcpy(regExpString, "(?i");
4526 + strcat(regExpString, strPat->spText);
4527 + strcat(regExpString, ")");
4529 + else
4531 + regExpString = strPat->spText;
4534 + /*
4535 + * compile regular expression & free allocated string buffer,
4536 + * if applicable.
4537 + */
4538 + strPat->spTextRE =
4539 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
4541 + if (strPat->spTextRE == NULL)
4543 + /*
4544 + * compilation was not successful: adapt error reason by
4545 + * converting local backrefs to global ones.
4546 + */
4547 + adaptCompileMsg(compileMsg, strPat->spGlobalToLocalBackRef);
4549 + errInfo->eiRegExpCompileMsg = compileMsg;
4550 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
4553 + if (strPat->spCaseInsensitive)
4554 + XtFree( regExpString );
4556 + return (strPat->spTextRE == NULL);
4560 +** adapt regular expression compilation message by converting local
4561 +** backrefs to global ones.
4563 +static void adaptCompileMsg(
4564 + char *compileMsg,
4565 + int *globalToLocalBackRef)
4567 + int localId;
4568 + int globalId;
4569 + char *s = compileMsg;
4571 + while (*s != '\0')
4573 + if (*s == '\\')
4575 + if (isdigit((unsigned char)*(s+1)))
4577 + /*
4578 + * \n (n=1..9) found: substitute local by global back ref.
4579 + */
4580 + s ++;
4582 + localId =
4583 + (int)((unsigned char)*s - (unsigned char)'0');
4585 + globalId = localToGlobalBackRef(globalToLocalBackRef, localId);
4587 + *s = (char)((int)('0') + globalId);
4589 + else if (*(s+1) != '\0')
4590 + s ++;
4592 + s ++;
4597 +** translate given local backref to global backref by using
4598 +** given globalToLocalBackRef list.
4600 +static int localToGlobalBackRef(
4601 + int *globalToLocalBackRef,
4602 + int localId)
4604 + int i;
4606 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
4608 + if (globalToLocalBackRef[i] == localId)
4609 + return i+1;
4612 + return 0;
4616 +** Create a regular expression holding keywords of given start & end
4617 +** pattern set.
4618 +** Returns true, if creation of regular expression has failed.
4620 +static int createStartEndRegExp(
4621 + ReadMatchPatternInfo *readMatchPatternInfo,
4622 + MatchPatternTableElement *element,
4623 + ErrorInfo *errInfo)
4625 + char *regExpString;
4626 + char *compileMsg;
4628 + /*
4629 + * compose regular expression for start / end pattern.
4630 + */
4631 + composeStartEndRegExpString(
4632 + readMatchPatternInfo,
4633 + element,
4634 + &regExpString);
4636 + /*
4637 + * compile regular expression & free allocated string buffer.
4638 + */
4639 + element->mpteStartEndRE =
4640 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
4642 + XtFree( regExpString );
4644 + if( element->mpteStartEndRE == NULL)
4646 + errInfo->eiRegExpCompileMsg = compileMsg;
4647 + errInfo->eiDetail = "Error compiling start / end reg. exp.";
4650 + return (element->mpteStartEndRE == NULL);
4654 +** Create a regular expression holding keywords of given group element.
4655 +** Returns true, if creation of regular expression has failed.
4657 +static int createGroupRegExp(
4658 + ReadMatchPatternInfo *readPatInfo,
4659 + MatchPatternGroupElement *group,
4660 + ErrorInfo *errInfo)
4662 + int i;
4663 + MatchPatternTableElement *element;
4664 + RegExpStringInfo regExpStringInfo;
4665 + char *regExpString;
4666 + regexp *keywordRE;
4667 + char *compileMsg;
4669 + /*
4670 + * Allocate buffers for keyword regular expression of this group.
4671 + */
4672 + setupRegExpStringBuffers(
4673 + readPatInfo,
4674 + &regExpStringInfo);
4676 + for (i=0; i<group->mpgeNumberOfSubPatterns; i++)
4678 + element = getPatternOfName(readPatInfo, group->mpgeSubPatternIds[i]);
4679 + /*
4680 + * Add the keywords of the sub pattern to the keyword regular
4681 + * expression string buffer of new group.
4682 + */
4683 + addElementToRegExpString(
4684 + element,
4685 + readPatInfo,
4686 + &regExpStringInfo);
4689 + /*
4690 + * Assemble and compile the resulting keyword regular expression string.
4691 + */
4692 + catSMTRegExpStrings(
4693 + &regExpStringInfo,
4694 + &regExpString);
4696 + keywordRE = CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
4698 + XtFree( regExpString );
4700 + if (keywordRE == NULL)
4702 + errInfo->eiMPTabElementName = XtNewString(group->mpgeName);
4703 + errInfo->eiRegExpCompileMsg = compileMsg;
4704 + errInfo->eiDetail = "Group: Compile reg. exp. error";
4707 + group->mpgeKeywordRE = keywordRE;
4709 + return (keywordRE == NULL);
4713 +** Allocate memory for regular expression strings to be
4714 +** created out of read match pattern info.
4716 +static void setupRegExpStringBuffers(
4717 + ReadMatchPatternInfo *readMatchPatternInfo,
4718 + RegExpStringInfo *regExpStringInfo)
4720 + int totalLen;
4721 + int nbrOfMultiPatterns;
4722 + int sizeOfPatRefs;
4724 + /*
4725 + * determine total length of pattern characters to determine
4726 + * the size of a string buffer for the regular expression to
4727 + * compose. Count number of total multi patterns, too.
4728 + */
4729 + totalLen =
4730 + totalKeywordOfTableLen( readMatchPatternInfo, &nbrOfMultiPatterns );
4732 + /*
4733 + * allocate memory to store added multi pattern references (to avoid
4734 + * duplicated keywords strings later on).
4735 + */
4736 + sizeOfPatRefs = sizeof(PatternReference *) * nbrOfMultiPatterns;
4738 + regExpStringInfo->resiAddedMultiPat =
4739 + (PatternReference **)XtMalloc( sizeOfPatRefs );
4741 + regExpStringInfo->resiNbrOfAddedMultiPat = 0;
4743 + /*
4744 + * init. ID of capturing local backrefs
4745 + */
4746 + regExpStringInfo->resiLocalBackRefID = 1;
4748 + /*
4749 + * allocate & init. string buffers for regular expression:
4750 + * 3 times the size + x of all pattern characters (due to
4751 + * a.) each char may need to be escaped
4752 + * b.) '<(?:', ')>', ')' and '|' need to be added.
4753 + */
4754 + regExpStringInfo->resiNoneWBRegExpString = XtMalloc( 3 * totalLen );
4755 + regExpStringInfo->resiLeftWBRegExpString = XtMalloc( 3 * totalLen + 5 );
4756 + regExpStringInfo->resiRightWBRegExpString = XtMalloc( 3 * totalLen + 5 );
4757 + regExpStringInfo->resiBothWBRegExpString = XtMalloc( 3 * totalLen + 6 );
4759 + strcpy( regExpStringInfo->resiNoneWBRegExpString, "" );
4760 + strcpy( regExpStringInfo->resiLeftWBRegExpString, "" );
4761 + strcpy( regExpStringInfo->resiRightWBRegExpString, "" );
4762 + strcpy( regExpStringInfo->resiBothWBRegExpString, "" );
4766 +** Concatenate given 'partToAdd' string to result string, separated
4767 +** by an OR ('|'). Add 'postfix' at end of result string.
4769 +static void addSMTRegExpString(
4770 + char *result,
4771 + char *partToAdd,
4772 + const char *postfix)
4774 + if (strlen(partToAdd) != 0)
4776 + if (strlen(result) != 0)
4778 + strcat( result, "|" );
4781 + strcat( result, partToAdd );
4783 + strcat( result, postfix );
4789 +** Return a string representing given string match table.
4791 +static char *createMatchPatternsString(
4792 + StringMatchTable *table,
4793 + char *indentStr)
4795 + char *outStr, *str;
4796 + textBuffer *outBuf;
4797 + int i, j;
4798 + MatchPatternSequenceElement *seq;
4799 + MatchPatternTableElement *element;
4800 + MatchPatternGroupElement *group;
4802 + outBuf = BufCreate();
4804 + for (i=0; i<table->smtNumberOfSeqElements; i++)
4806 + seq = table->smtSequence[i];
4808 + BufInsert(outBuf, outBuf->length, indentStr);
4809 + BufInsert(outBuf, outBuf->length, seq->mpseName);
4810 + BufInsert(outBuf, outBuf->length, ":");
4812 + if (seq->mpseType == MPT_GROUP)
4814 + BufInsert(outBuf, outBuf->length, "g:");
4816 + group = table->smtGroups[seq->mpseIndex];
4818 + for (j=0; j < group->mpgeNumberOfSubPatterns; j ++)
4820 + BufInsert(outBuf, outBuf->length, group->mpgeSubPatternIds[j]);
4821 + BufInsert(outBuf, outBuf->length, ":");
4824 + else
4826 + if (seq->mpseType == MPT_SUB)
4828 + BufInsert(outBuf, outBuf->length, "s");
4830 + BufInsert(outBuf, outBuf->length, ":");
4832 + element = table->smtAllPatterns->mptElements[seq->mpseIndex];
4834 + /*
4835 + * write global attributes
4836 + */
4837 + if (element->mpteSkipBtwnStartEnd)
4838 + BufInsert(outBuf, outBuf->length, "c");
4839 + if (element->mpteFlash)
4840 + BufInsert(outBuf, outBuf->length, "f");
4841 + if (element->mpteIsMonoPattern)
4842 + BufInsert(outBuf, outBuf->length, "m");
4843 + if (element->mpteIgnoreHighLightInfo)
4844 + BufInsert(outBuf, outBuf->length, "p");
4845 + BufInsert(outBuf, outBuf->length, ":");
4847 + /*
4848 + * write string patterns
4849 + */
4850 + for (j=0; j < element->mpteAll.pesNumberOfPattern; j ++)
4852 + BufInsert(
4853 + outBuf,
4854 + outBuf->length,
4855 + str =
4856 + createPatternElementString(
4857 + table->smtAllPatterns,
4858 + element->mpteAll.pesPattern[j]));
4859 + XtFree(str);
4863 + BufInsert(outBuf, outBuf->length, "\n");
4866 + outStr = BufGetAll(outBuf);
4867 + BufFree(outBuf);
4869 + return outStr;
4873 +** Return a string representing given pattern element.
4875 +static char *createPatternElementString(
4876 + MatchPatternTable *table,
4877 + PatternElement *pat)
4879 + char *outStr, *str;
4880 + textBuffer *outBuf;
4881 + StringPattern *strPat;
4883 + outBuf = BufCreate();
4885 + strPat = GetStringPattern(table, pat);
4887 + /*
4888 + * write string pattern kind
4889 + */
4890 + if (pat->peKind == PEK_START)
4891 + BufInsert(outBuf, outBuf->length, "s");
4892 + else if (pat->peKind == PEK_MIDDLE)
4893 + BufInsert(outBuf, outBuf->length, "m");
4894 + else if (pat->peKind == PEK_END)
4895 + BufInsert(outBuf, outBuf->length, "e");
4897 + /*
4898 + * write word boundary
4899 + */
4900 + if (strPat->spWordBoundary == PWB_BOTH)
4901 + BufInsert(outBuf, outBuf->length, "w");
4902 + else if (strPat->spWordBoundary == PWB_LEFT)
4903 + BufInsert(outBuf, outBuf->length, "l");
4904 + else if (strPat->spWordBoundary == PWB_RIGHT)
4905 + BufInsert(outBuf, outBuf->length, "r");
4907 + /*
4908 + * write case insensitive flag
4909 + */
4910 + if (strPat->spCaseInsensitive)
4911 + BufInsert(outBuf, outBuf->length, "i");
4913 + /*
4914 + * write regular expression flag
4915 + */
4916 + if (strPat->spRegularExpression)
4917 + BufInsert(outBuf, outBuf->length, "x");
4919 + BufInsert(outBuf, outBuf->length, ":");
4921 + /*
4922 + * write pattern string
4923 + */
4924 + if( strPat->spOrigText != NULL)
4925 + BufInsert(
4926 + outBuf,
4927 + outBuf->length,
4928 + str = MakeQuotedString(strPat->spOrigText));
4929 + else
4930 + BufInsert(
4931 + outBuf,
4932 + outBuf->length,
4933 + str = MakeQuotedString(strPat->spText));
4934 + XtFree(str);
4936 + BufInsert(outBuf, outBuf->length, ":");
4938 + outStr = BufGetAll(outBuf);
4939 + BufFree(outBuf);
4941 + return outStr;
4945 +** Given a language mode name, determine if there is a default (built-in)
4946 +** string match table available for that language mode, and if so, read it and
4947 +** return a new allocated copy of it. The returned pattern set should be
4948 +** freed by the caller with freeStringMatchTable().
4950 +static StringMatchTable *readDefaultStringMatchTable(const char *langModeName)
4952 + int i, modeNameLen;
4953 + char *list;
4955 + modeNameLen = strlen(langModeName);
4957 + for (i=0; i<(int)XtNumber(DefaultStringMatchTable); i++)
4959 + if (!strncmp(langModeName, DefaultStringMatchTable[i], modeNameLen) &&
4960 + DefaultStringMatchTable[i][modeNameLen] == '{')
4962 + list = DefaultStringMatchTable[i];
4963 + return readMatchPatternSet(&list);
4967 + list = StandardStringMatchTable;
4968 + return readMatchPatternSetContent(&list, list, XtNewString(langModeName));
4972 +** Return true, if table exactly matches one of the default matching
4973 +** pattern tables.
4975 +static int isDefaultMatchPatternTable(StringMatchTable *table)
4977 + StringMatchTable *defaultTable;
4978 + int retVal;
4980 + defaultTable = readDefaultStringMatchTable(table->smtLanguageMode);
4982 + if (defaultTable == NULL)
4983 + return False;
4985 + retVal = !stringMatchTableDiffer(table, defaultTable);
4987 + freeStringMatchTable(defaultTable);
4989 + return retVal;
4993 +** Read in a string match pattern table character string,
4994 +** and advance *inPtr beyond it.
4995 +** Returns NULL and outputs an error to stderr on failure.
4997 +static StringMatchTable *readMatchPatternSet(char **inPtr)
4999 + char *languageMode;
5000 + StringMatchTable *table = NULL;
5001 + char *stringStart = *inPtr;
5002 + ErrorInfo errInfo;
5004 + initErrorInfo(&errInfo);
5006 + /*
5007 + * remove leading whitespace
5008 + */
5009 + *inPtr += strspn(*inPtr, " \t\n");
5011 + /*
5012 + * read language mode field
5013 + */
5014 + languageMode = ReadSymbolicField(inPtr);
5016 + /*
5017 + * look for initial brace
5018 + */
5019 + if (**inPtr == ':')
5021 + (*inPtr) ++;
5022 + /*
5023 + * look for "Default" keyword, and if it's there, return the default
5024 + * pattern set
5025 + */
5026 + if (!strncmp(*inPtr, "Default", 7))
5028 + *inPtr += 7;
5029 + table = readDefaultStringMatchTable(languageMode);
5030 + XtFree(languageMode);
5032 + return table;
5036 + table = readMatchPatternSetContent(inPtr, stringStart, languageMode);
5038 + if (table == NULL)
5039 + XtFree(languageMode);
5041 + return table;
5045 +** Read in a content string ("{..}") of match pattern table,
5046 +** and advance *inPtr beyond it.
5047 +** Returns NULL and outputs an error to stderr on failure.
5049 +static StringMatchTable *readMatchPatternSetContent(
5050 + char **inPtr,
5051 + char *stringStart,
5052 + char *languageMode)
5054 + ReadMatchPatternInfo readPatInfo;
5055 + StringMatchTable *table = NULL;
5056 + ErrorInfo errInfo;
5057 + int successful = True;
5058 + int endOfPatternSet = False;
5060 + initErrorInfo(&errInfo);
5062 + /*
5063 + * look for initial brace
5064 + */
5065 + if (**inPtr != '{')
5067 + errInfo.eiLanguageMode = XtNewString(languageMode);
5068 + errInfo.eiDetail = "pattern list must begin with \"{\"";
5069 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo );
5071 + return NULL;
5074 + (*inPtr)++;
5076 + readPatInfo.rmpiNbrOfElements = 0;
5077 + readPatInfo.rmpiNbrOfGroups = 0;
5078 + readPatInfo.rmpiNbrOfSeqElements = 0;
5079 + readPatInfo.rmpiAllPatRE = NULL;
5080 + readPatInfo.rmpiFlashPatRE = NULL;
5082 + /*
5083 + * parse each pattern in the list
5084 + */
5085 + while (successful && !endOfPatternSet)
5087 + *inPtr += strspn(*inPtr, " \t\n");
5088 + if (**inPtr == '\0')
5090 + errInfo.eiLanguageMode = XtNewString(languageMode);
5091 + errInfo.eiDetail = "end of pattern list not found";
5092 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo);
5093 + successful = False;
5095 + else if (**inPtr == '}')
5097 + (*inPtr)++;
5098 + endOfPatternSet = True;
5100 + else
5102 + if (!readMatchPatternEntry(inPtr, &errInfo, &readPatInfo))
5104 + errInfo.eiLanguageMode = XtNewString(languageMode);
5105 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo);
5106 + successful = False;
5111 + if (successful)
5113 + /*
5114 + * compile regular expressions of read patterns
5115 + */
5116 + if (createRegExpOfPatterns(&readPatInfo, &errInfo))
5118 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo);
5119 + successful = False;
5123 + if (successful)
5125 + return createStringMatchTable(&readPatInfo, languageMode);
5127 + else
5129 + /*
5130 + * free memory of already read patterns
5131 + */
5132 + freeReadMatchPatternInfo(&readPatInfo);
5134 + return NULL;
5137 + return table;
5141 +** Create a reg. exp. of all patterns contained
5142 +** in given read match pattern info.
5144 +static int createRegExpOfPatterns(
5145 + ReadMatchPatternInfo *readPatInfo,
5146 + ErrorInfo *errInfo)
5148 + if (createRegExpOfStrPatterns(readPatInfo, errInfo))
5149 + return True;
5151 + if (createRegExpOfAllPatterns(readPatInfo, errInfo))
5152 + return True;
5154 + return False;
5158 +** Create a "total pattern reg. exp." of all patterns / flash patterns
5159 +** contained in given read match pattern info.
5160 +** Returns true, if create of reg. exp. has failed.
5162 +static int createRegExpOfAllPatterns(
5163 + ReadMatchPatternInfo *readPatInfo,
5164 + ErrorInfo *errInfo)
5166 + int i;
5167 + RegExpStringInfo allPatRegExpSI;
5168 + RegExpStringInfo flashPatRegExpSI;
5169 + MatchPatternTableElement *element;
5170 + char *regExpString;
5171 + char *compileMsg;
5173 + /*
5174 + * Allocate buffers for keyword regular expressions.
5175 + */
5176 + setupRegExpStringBuffers(readPatInfo, &allPatRegExpSI);
5177 + setupRegExpStringBuffers(readPatInfo, &flashPatRegExpSI);
5179 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5181 + element = readPatInfo->rmpiElement[i];
5183 + /*
5184 + * Add the keywords of the matching pattern to the keyword
5185 + * regular expression string buffer of all patterns.
5186 + */
5187 + addElementToRegExpString(
5188 + element,
5189 + readPatInfo,
5190 + &allPatRegExpSI);
5192 + /*
5193 + * If flash attribute is set, then add the keywords of the
5194 + * matching pattern also to the keyword regular expression
5195 + * string buffer of flash patterns.
5196 + */
5197 + if (element->mpteFlash)
5199 + addElementToRegExpString(
5200 + element,
5201 + readPatInfo,
5202 + &flashPatRegExpSI);
5206 + /*
5207 + * Assemble and compile the resulting all keywords reg. exp. string.
5208 + */
5209 + catSMTRegExpStrings(
5210 + &allPatRegExpSI,
5211 + &regExpString);
5213 + readPatInfo->rmpiAllPatRE =
5214 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
5216 + XtFree( regExpString );
5218 + if (readPatInfo->rmpiAllPatRE == NULL)
5220 + errInfo->eiRegExpCompileMsg = compileMsg;
5221 + errInfo->eiDetail = "All patterns: compile reg. exp. error";
5222 + return True;
5225 + /*
5226 + * Assemble and compile the resulting flash keywords reg. exp. string.
5227 + */
5228 + catSMTRegExpStrings(
5229 + &flashPatRegExpSI,
5230 + &regExpString);
5232 + readPatInfo->rmpiFlashPatRE =
5233 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
5235 + XtFree( regExpString );
5237 + if (readPatInfo->rmpiFlashPatRE == NULL)
5239 + errInfo->eiRegExpCompileMsg = compileMsg;
5240 + errInfo->eiDetail = "Flash patterns: compile reg. exp. error";
5241 + return True;
5244 + /*
5245 + * Pattern reg. exp. successful created:
5246 + */
5247 + return False;
5251 +** Create reg. exp. of single patterns contained in given
5252 +** read match pattern info.
5253 +** Returns true, if create of reg. exp. has failed.
5255 +static int createRegExpOfStrPatterns(
5256 + ReadMatchPatternInfo *readPatInfo,
5257 + ErrorInfo *errInfo)
5259 + int i;
5260 + MatchPatternTableElement *element;
5261 + MatchPatternGroupElement *group;
5263 + /*
5264 + * create global backref list of all elements of read info
5265 + */
5266 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5268 + element = readPatInfo->rmpiElement[i];
5270 + if (!createGlobalBackRefList(readPatInfo, element, errInfo))
5271 + return True;
5274 + /*
5275 + * resolve global backrefs of all elements of read info
5276 + */
5277 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5279 + element = readPatInfo->rmpiElement[i];
5281 + if (!resolveGlobalBackRefs(readPatInfo, element, errInfo))
5282 + return True;
5285 + /*
5286 + * compile reg. exp. of all elements of read info
5287 + */
5288 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5290 + element = readPatInfo->rmpiElement[i];
5292 + if (createStrPatRegExpOfElement(readPatInfo, element, errInfo))
5293 + return True;
5295 + /*
5296 + * create start / end reg. exp. if applicable.
5297 + */
5298 + if (element->mpteSkipBtwnStartEnd)
5300 + if (createStartEndRegExp(readPatInfo, element, errInfo))
5301 + return True;
5305 + /*
5306 + * compile reg. exp. of all groups of read info
5307 + */
5308 + for (i=0; i < readPatInfo->rmpiNbrOfGroups; i ++)
5310 + group = readPatInfo->rmpiGroup[i];
5312 + if (createGroupRegExp(readPatInfo, group, errInfo))
5314 + return True;
5318 + return False;
5322 +** Create a string match table out of read match pattern info.
5324 +static StringMatchTable *createStringMatchTable(
5325 + ReadMatchPatternInfo *readPatInfo,
5326 + char *languageMode)
5328 + StringMatchTable *table;
5329 + MatchPatternTable *patTable;
5330 + int sizeOfElements;
5332 + table = (StringMatchTable *)XtMalloc(sizeof(StringMatchTable));
5333 + table->smtLanguageMode = languageMode;
5335 + /*
5336 + * allocate a more appropriately sized list to return matching patterns
5337 + */
5338 + patTable = (MatchPatternTable *)XtMalloc(sizeof(MatchPatternTable));
5339 + patTable->mptNumberOfElements = readPatInfo->rmpiNbrOfElements;
5341 + if (readPatInfo->rmpiNbrOfElements > 0)
5343 + sizeOfElements =
5344 + sizeof(MatchPatternTableElement *) * readPatInfo->rmpiNbrOfElements;
5345 + patTable->mptElements =
5346 + (MatchPatternTableElement **)XtMalloc(sizeOfElements);
5347 + memcpy(patTable->mptElements, readPatInfo->rmpiElement, sizeOfElements);
5349 + else
5351 + patTable->mptElements = NULL;
5354 + table->smtAllPatterns = patTable;
5356 + table->smtAllPatRE = readPatInfo->rmpiAllPatRE;
5357 + table->smtFlashPatRE = readPatInfo->rmpiFlashPatRE;
5358 + table->smtUsedPatRE = NULL;
5360 + /*
5361 + * allocate a more appropriately sized list to return matching pattern groups
5362 + */
5363 + table->smtNumberOfGroups = readPatInfo->rmpiNbrOfGroups;
5364 + if (readPatInfo->rmpiNbrOfGroups > 0)
5366 + sizeOfElements =
5367 + sizeof(MatchPatternGroupElement *) * readPatInfo->rmpiNbrOfGroups;
5368 + table->smtGroups =
5369 + (MatchPatternGroupElement **)XtMalloc(sizeOfElements);
5370 + memcpy(table->smtGroups, readPatInfo->rmpiGroup, sizeOfElements);
5372 + else
5374 + table->smtGroups = NULL;
5376 + /*
5377 + * allocate a more appropriately sized list to return matching pattern sequence
5378 + */
5379 + table->smtNumberOfSeqElements = readPatInfo->rmpiNbrOfSeqElements;
5380 + if (readPatInfo->rmpiNbrOfSeqElements > 0)
5382 + sizeOfElements =
5383 + sizeof(MatchPatternSequenceElement *) * readPatInfo->rmpiNbrOfSeqElements;
5384 + table->smtSequence =
5385 + (MatchPatternSequenceElement **)XtMalloc(sizeOfElements);
5386 + memcpy(table->smtSequence, readPatInfo->rmpiSequence, sizeOfElements);
5388 + else
5390 + table->smtSequence = NULL;
5393 + return table;
5397 +** Read one match pattern entry of a match pattern string.
5398 +** Returns true, if read was successful.
5400 +static int readMatchPatternEntry(
5401 + char **inPtr,
5402 + ErrorInfo *errInfo,
5403 + ReadMatchPatternInfo *info)
5405 + char *name;
5406 + MatchPatternType type;
5407 + MatchPatternGroupElement *readGroup;
5408 + MatchPatternTableElement *readElement;
5410 + if (!getMPSName( inPtr, errInfo, &name ))
5412 + return False;
5415 + if (!getMPSTypeAttribute( inPtr, errInfo, &type ))
5417 + errInfo->eiMPTabElementName = XtNewString(name);
5418 + return False;
5421 + if (type == MPT_GROUP)
5423 + if (info->rmpiNbrOfGroups >= MAX_NBR_MATCH_PATTERN_GROUPS)
5425 + errInfo->eiMPTabElementName = XtNewString(name);
5426 + errInfo->eiDetail = "max number of match pattern groups exceeded";
5427 + return False;
5430 + readGroup = readMatchPatternGroup( inPtr, errInfo, name, info );
5432 + if (readGroup == NULL)
5434 + errInfo->eiMPTabElementName = XtNewString(name);
5435 + XtFree( name );
5437 + else
5439 + info->rmpiGroup[info->rmpiNbrOfGroups ++] = readGroup;
5441 + recordPatternSequence( info, name, type, info->rmpiNbrOfGroups-1 );
5444 + return (readGroup != NULL);
5446 + else
5448 + if (info->rmpiNbrOfElements >= MAX_NBR_MATCH_PATTERNS)
5450 + errInfo->eiMPTabElementName = XtNewString(name);
5451 + errInfo->eiDetail = "max number of match patterns exceeded";
5452 + XtFree( name );
5453 + return False;
5456 + readElement =
5457 + readMatchPatternTableElement( inPtr, &errInfo->eiDetail, name, type );
5459 + if (readElement == NULL)
5461 + errInfo->eiMPTabElementName = XtNewString(name);
5462 + XtFree( name );
5464 + else
5466 + readElement->mpteIndex = info->rmpiNbrOfElements;
5468 + info->rmpiElement[info->rmpiNbrOfElements ++] = readElement;
5470 + if (type == MPT_INDIVIDUAL)
5472 + if (!assignIndividualGroup( info, &errInfo->eiDetail, readElement ))
5474 + errInfo->eiMPTabElementName = XtNewString(name);
5475 + return False;
5479 + treatDuplicatedMTEntries(
5480 + info->rmpiElement, info->rmpiNbrOfElements );
5482 + recordPatternSequence( info, name, type, info->rmpiNbrOfElements-1 );
5485 + return (readElement != NULL);
5490 +** Record match pattern sequence for display of match pattern dialog.
5492 +static void recordPatternSequence(
5493 + ReadMatchPatternInfo *info,
5494 + char *name,
5495 + MatchPatternType type,
5496 + int index)
5498 + MatchPatternSequenceElement *sequence;
5500 + sequence =
5501 + (MatchPatternSequenceElement *)XtMalloc( sizeof(MatchPatternSequenceElement) );
5503 + sequence->mpseName = XtNewString(name);
5504 + sequence->mpseType = type;
5505 + sequence->mpseIndex = index;
5507 + info->rmpiSequence[info->rmpiNbrOfSeqElements ++] = sequence;
5511 +** Assign a new group to an individual match pattern.
5512 +** Returns true, if assignment was successful.
5514 +static int assignIndividualGroup(
5515 + ReadMatchPatternInfo *info,
5516 + char **errMsg,
5517 + MatchPatternTableElement *element)
5519 + MatchPatternGroupElement *group = NULL;
5521 + if (info->rmpiNbrOfGroups >= MAX_NBR_MATCH_PATTERN_GROUPS)
5523 + *errMsg = "max. number of matching pattern groups exceeded\n";
5524 + return False;
5527 + /*
5528 + * Assign the index of new group to the individual matching pattern
5529 + */
5530 + element->mpteGroup = info->rmpiNbrOfGroups;
5532 + /*
5533 + * Allocate memory for the matching pattern group and copy the
5534 + * info into this group element.
5535 + */
5536 + group =
5537 + (MatchPatternGroupElement *)XtMalloc( sizeof(MatchPatternGroupElement) );
5539 + group->mpgeName = NULL;
5540 + group->mpgeKeywordRE = NULL;
5542 + /*
5543 + * remember name of match pattern table element, which is
5544 + * represented by this group.
5545 + */
5546 + group->mpgeNumberOfSubPatterns = 1;
5547 + group->mpgeSubPatternIds = (char **)XtMalloc( sizeof(char *) );
5548 + group->mpgeSubPatternIds[0] = XtNewString(element->mpteName);
5550 + info->rmpiGroup[info->rmpiNbrOfGroups ++] = group;
5552 + return True;
5556 +** Get the match pattern table element of given 'patToSearch'
5557 +** name.
5558 +** Returns NULL, if no element was found.
5560 +static MatchPatternTableElement *getPatternOfName(
5561 + ReadMatchPatternInfo *info,
5562 + char *patToSearch)
5564 + int i;
5565 + MatchPatternTableElement *element;
5567 + for (i=0; i<info->rmpiNbrOfElements; i ++)
5569 + element = info->rmpiElement[i];
5571 + if (strcmp( element->mpteName, patToSearch ) == 0)
5573 + /*
5574 + * Related sub-pattern found:
5575 + */
5576 + return element;
5580 + /*
5581 + * No sub-pattern found:
5582 + */
5583 + return NULL;
5587 +** Read match pattern group of given match pattern string.
5588 +** Returns NULL, if read fails.
5590 +static MatchPatternGroupElement *readMatchPatternGroup(
5591 + char **inPtr,
5592 + ErrorInfo *errInfo,
5593 + char *name,
5594 + ReadMatchPatternInfo *info)
5596 + int i;
5597 + int error = False;
5598 + char *patNameInPtr;
5599 + char *subPatName;
5600 + MatchPatternTableElement *subPatElement;
5601 + int numberOfRelatedSubPattern = 0;
5602 + char *relatedSubPatternId[MAX_NBR_MATCH_PATTERNS];
5603 + int sizeOfIds;
5604 + MatchPatternGroupElement *group = NULL;
5606 + /*
5607 + * Read sub-matching patterns of this group.
5608 + */
5609 + while (**inPtr != '\n' && !error)
5611 + /*
5612 + * Read next pattern name from inPtr.
5613 + */
5614 + patNameInPtr = *inPtr;
5615 + subPatName = ReadSymbolicField(inPtr);
5617 + if (subPatName == NULL)
5619 + errInfo->eiDetail = "Sub-Matching Pattern Name expected";
5620 + error = True;
5622 + else
5624 + /*
5625 + * Get matching pattern related to sub-matching pattern name.
5626 + */
5627 + subPatElement =
5628 + getPatternOfName( info, subPatName );
5630 + if (subPatElement == NULL)
5632 + errInfo->eiStringPatText = XtNewString(subPatName);
5633 + errInfo->eiDetail = "Sub-Matching Pattern not defined before";
5634 + error = True;
5636 + else if (numberOfRelatedSubPattern >= MAX_NBR_MATCH_PATTERNS)
5638 + errInfo->eiDetail = "Group holds too many Sub-Matching Patterns";
5639 + error = True;
5641 + else if (subPatElement->mpteType != MPT_SUB)
5643 + errInfo->eiStringPatText = XtNewString(subPatName);
5644 + errInfo->eiDetail = "Not a Sub-Matching Pattern";
5645 + error = True;
5647 + else
5649 + /*
5650 + * Remember sub-matching pattern ID
5651 + */
5652 + relatedSubPatternId[numberOfRelatedSubPattern ++] = subPatName;
5654 + /*
5655 + * Assign the index of this group to the sub-matching pattern
5656 + * if no group index was assigned before.
5657 + */
5658 + if (subPatElement->mpteGroup == NO_GROUP_IDX)
5660 + subPatElement->mpteGroup = info->rmpiNbrOfGroups;
5664 + /*
5665 + * Skip to the start of the next matching pattern name.
5666 + */
5667 + if (!error && !SkipDelimiter(inPtr, &errInfo->eiDetail))
5669 + error = True;
5674 + if (error)
5676 + for (i=0; i < numberOfRelatedSubPattern; i++)
5678 + XtFree( relatedSubPatternId[i] );
5681 + return NULL;
5683 + else
5685 + /*
5686 + * Allocate memory for the matching pattern group and copy the
5687 + * info into this group element.
5688 + */
5689 + group =
5690 + (MatchPatternGroupElement *)XtMalloc( sizeof(MatchPatternGroupElement) );
5692 + group->mpgeName = name;
5693 + group->mpgeKeywordRE = NULL;
5695 + /*
5696 + * Allocate memory for the sub-matching pattern IDs & copy
5697 + * related sub-matching pattern into the group element.
5698 + */
5699 + sizeOfIds = sizeof(char *) * numberOfRelatedSubPattern;
5700 + group->mpgeSubPatternIds = (char **)XtMalloc( sizeOfIds );
5702 + memcpy(group->mpgeSubPatternIds, relatedSubPatternId, sizeOfIds);
5704 + group->mpgeNumberOfSubPatterns = numberOfRelatedSubPattern;
5706 + return group;
5711 +** Read one match pattern element from given match pattern string.
5712 +** Returns true, if read was successful.
5714 +static int readPatternElement(
5715 + char **inPtr,
5716 + char **errMsg,
5717 + PatternElement **pattern)
5719 + PatternElementKind patternKind;
5720 + PatternWordBoundary wordBoundary;
5721 + int caseInsensitive;
5722 + int regularExpression;
5723 + char *string;
5725 + if (!getMPSPatternAttribute(
5726 + inPtr,
5727 + errMsg,
5728 + &patternKind,
5729 + &wordBoundary,
5730 + &caseInsensitive,
5731 + &regularExpression ))
5733 + return False;
5736 + if (!ReadQuotedString(inPtr, errMsg, &string))
5738 + return False;
5741 + if (!SkipDelimiter(inPtr, errMsg))
5743 + XtFree( string );
5744 + return False;
5747 + *pattern =
5748 + createPatternElement(
5749 + string,
5750 + patternKind,
5751 + wordBoundary,
5752 + caseInsensitive,
5753 + regularExpression);
5755 + return True;
5759 +** Create a pattern element.
5761 +static PatternElement *createPatternElement(
5762 + char *patternText,
5763 + PatternElementKind patternKind,
5764 + PatternWordBoundary wordBoundary,
5765 + int caseInsensitive,
5766 + int regularExpression)
5768 + PatternElement *pattern;
5769 + char *s;
5771 + /*
5772 + * Convert pattern text to lower case, if case insensitive
5773 + * attribute is set.
5774 + */
5775 + if (caseInsensitive)
5777 + for (s = patternText; *s != '\0'; s ++)
5779 + *s = tolower(*s);
5783 + /*
5784 + * Allocate memory for the new pattern element and init. / copy
5785 + * related info into this pattern element.
5786 + */
5787 + pattern = (PatternElement *)XtMalloc( sizeof(PatternElement) );
5789 + initStrPatBackRefList(&pattern->peVal.peuSingle);
5791 + pattern->peKind = patternKind;
5792 + pattern->peIndex = NO_PATTERN_IDX;
5793 + pattern->peType = PET_SINGLE;
5795 + pattern->peVal.peuSingle.spLength = strlen(patternText);
5796 + pattern->peVal.peuSingle.spBackRefParsed = False;
5797 + pattern->peVal.peuSingle.spBackRefResolved = False;
5799 + pattern->peVal.peuSingle.spCaseInsensitive = caseInsensitive;
5800 + pattern->peVal.peuSingle.spRegularExpression = regularExpression;
5801 + pattern->peVal.peuSingle.spTextRE = NULL;
5803 + /*
5804 + * Store original string of regular expression patterns due to
5805 + * it may be later adapted (e.g. due to global backrefs etc.).
5806 + */
5807 + if (regularExpression)
5809 + pattern->peVal.peuSingle.spOrigText = patternText;
5810 + pattern->peVal.peuSingle.spText = NULL;
5811 + pattern->peVal.peuSingle.spWordBoundary = PWB_NONE;
5813 + else
5815 + pattern->peVal.peuSingle.spOrigText = NULL;
5816 + pattern->peVal.peuSingle.spText = patternText;
5817 + pattern->peVal.peuSingle.spWordBoundary = wordBoundary;
5820 + return pattern;
5824 +** Create a list holding all global backref definitions of given
5825 +** match pattern table element. The list is stored in this given
5826 +** element.
5827 +** Returns true, if list was successfully created.
5829 +static int createGlobalBackRefList(
5830 + ReadMatchPatternInfo *readPatInfo,
5831 + MatchPatternTableElement *element,
5832 + ErrorInfo *errInfo)
5834 + int i;
5835 + StringPattern *strPat;
5837 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
5839 + strPat = getReadStringPattern(readPatInfo, element->mpteAll.pesPattern[i]);
5841 + if (strPat->spRegularExpression)
5843 + if (strPat->spBackRefParsed)
5845 + /*
5846 + * Global backrefs or this string pattern already parsed:
5847 + * just merge string pattern list with elements one.
5848 + */
5849 + if (!updateGlobalBackRefs(
5850 + strPat,
5851 + element->mpteGlobalBackRef,
5852 + errInfo))
5854 + return False;
5857 + else
5859 + /*
5860 + * parse string pattern for global backrefs and
5861 + * merge string pattern list with elements one.
5862 + */
5863 + if (!parseGlobalBackRefs(
5864 + strPat,
5865 + element->mpteGlobalBackRef,
5866 + errInfo))
5868 + return False;
5874 + return True;
5878 +** Returns read string pattern of given pattern element.
5880 +StringPattern *getReadStringPattern(
5881 + ReadMatchPatternInfo *readPatInfo,
5882 + PatternElement *pattern )
5884 + switch (pattern->peType)
5886 + case PET_SINGLE:
5887 + return &pattern->peVal.peuSingle;
5888 + break;
5890 + case PET_MULTIPLE:
5891 + return &pattern->peVal.peuMulti.mpStringPattern;
5892 + break;
5894 + case PET_REFERENCE:
5895 + return getReadStringPattern(
5896 + readPatInfo,
5897 + getReadPatternOfReference(readPatInfo, &pattern->peVal.peuRef));
5898 + break;
5901 + /*
5902 + * never reached; just to make compiler happy
5903 + */
5904 + return NULL;
5908 +** Returns read pattern element of given pattern reference.
5910 +static PatternElement *getReadPatternOfReference(
5911 + ReadMatchPatternInfo *readPatInfo,
5912 + PatternReference *patRef)
5914 + MatchPatternTableElement **element = readPatInfo->rmpiElement;
5916 + return element[ patRef->prElementIdx ]->mpteAll.pesPattern[patRef->prPatternIdx];
5920 +** Allocate a new copy of given string and substitute each capturing
5921 +** parentheses inside given string by a non-capturing one.
5922 +** Returns resulting string.
5924 +static char *replaceCapturingParentheses(
5925 + const char *source)
5927 + char *destination;
5928 + const char *s;
5929 + char *d;
5930 + int nbrOfOpenBraces = 0;
5932 + s = source;
5934 + /*
5935 + * count number of open braces
5936 + */
5937 + while (*s != '\0')
5939 + if (*s++ == '(')
5940 + nbrOfOpenBraces ++;
5943 + /*
5944 + * allocate memory for substitued reg. exp. text
5945 + */
5946 + destination = XtMalloc(strlen(source) + 2*nbrOfOpenBraces);
5948 + /*
5949 + * substitute each capturing open brace by a non-capturing one
5950 + */
5951 + s = source;
5952 + d = destination;
5954 + while (*s != '\0')
5956 + if (*s == '\\')
5958 + *d++ = *s++;
5960 + if (*s != '\0')
5961 + *d++ = *s++;
5963 + else if (*s == '(')
5965 + *d++ = *s++;
5967 + if (*s != '?' && *s != '*')
5969 + *d++ = '?';
5970 + *d++ = ':';
5973 + else
5975 + *d++ = *s++;
5979 + *d = '\0';
5981 + return destination;
5985 +** Parse given string pattern for global backrefs definitions
5986 +** (syntax: "(*n", where n=1..9). Add found global backrefs to
5987 +** given backRefList.
5988 +** Returns false, if parse fails.
5990 +static int parseGlobalBackRefs(
5991 + StringPattern *strPat,
5992 + GlobalBackRefElement *backRefList,
5993 + ErrorInfo *errInfo)
5995 + char *s;
5996 + char *backRefContent;
5997 + int nestingLevel = 0;
5998 + int stackIdx = -1;
5999 + BackRefBracketInfo backRefInfo[MAX_GLOBAL_BACK_REF_ID+1];
6000 + StrPatBackRefElement *curStrPatBRE;
6002 + strPat->spText = replaceCapturingParentheses(strPat->spOrigText);
6003 + strPat->spLength = strlen(strPat->spText);
6004 + strPat->spBackRefParsed = True;
6006 + s = strPat->spText;
6008 + while (*s != '\0')
6010 + if (*s == '\\')
6012 + /*
6013 + * Ignore escaped characters
6014 + */
6015 + if (*(s+1) != '\0')
6016 + s ++;
6018 + else if (*s == '(')
6020 + if (*(s+1) == '*')
6022 + if (isdigit((unsigned char)*(s+2)))
6024 + /*
6025 + * Global backref. definition start found:
6026 + */
6027 + stackIdx ++;
6029 + backRefInfo[stackIdx].brbiGlobalId =
6030 + (int)((unsigned char)*(s+2) - (unsigned char)'0') - 1;
6032 + if(backRefInfo[stackIdx].brbiGlobalId < 0)
6034 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6035 + errInfo->eiDetail = "Backref '0' not allowed";
6036 + return False;
6039 + backRefInfo[stackIdx].brbiContentStart = s+3;
6040 + backRefInfo[stackIdx].brbiNestingLevel = nestingLevel;
6041 + s ++;
6043 + s ++;
6045 + nestingLevel ++;
6047 + else if (*s == ')')
6049 + nestingLevel --;
6050 + if (stackIdx != -1 &&
6051 + backRefInfo[stackIdx].brbiNestingLevel == nestingLevel)
6053 + /*
6054 + * Global backref. definition end found: add it to
6055 + * backref. list of string pattern.
6056 + */
6057 + curStrPatBRE =
6058 + &strPat->spOwnGlobalBackRef[backRefInfo[stackIdx].brbiGlobalId];
6060 + backRefContent =
6061 + createBackRefRegExpText(
6062 + backRefInfo[stackIdx].brbiContentStart,
6063 + s);
6065 + if (curStrPatBRE->spbreRegExpText != NULL)
6067 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6068 + errInfo->eiBackRefNbr = backRefInfo[stackIdx].brbiGlobalId + 1;
6069 + errInfo->eiDetail = "already defined before";
6070 + XtFree(backRefContent);
6071 + return False;
6073 + else
6075 + curStrPatBRE->spbreRegExpText = backRefContent;
6078 + stackIdx --;
6081 + s ++;
6084 + /*
6085 + * Merge global backref. list of string pattern with given backRefList.
6086 + */
6087 + return updateGlobalBackRefs(
6088 + strPat,
6089 + backRefList,
6090 + errInfo);
6094 +** Merge global backref. list of given string pattern with given backRefList.
6095 +** Returns false, if merge fails.
6097 +static int updateGlobalBackRefs(
6098 + StringPattern *strPat,
6099 + GlobalBackRefElement *backRefList,
6100 + ErrorInfo *errInfo)
6102 + int i;
6103 + StrPatBackRefElement *curStrPatBRE;
6104 + GlobalBackRefElement *curGlobalBRE;
6106 + for (i=0;i < MAX_GLOBAL_BACK_REF_ID; i ++)
6108 + curStrPatBRE = &strPat->spOwnGlobalBackRef[i];
6110 + if (curStrPatBRE->spbreRegExpText != NULL)
6112 + curGlobalBRE = &backRefList[i];
6114 + if (curGlobalBRE->gbreDefByStrPat != NULL)
6116 + if (strcmp(curGlobalBRE->gbreRegExpText, curStrPatBRE->spbreRegExpText) != 0)
6118 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6119 + errInfo->eiBackRefNbr = i+1;
6120 + errInfo->eiDetail = "already defined before";
6122 + return False;
6125 + else
6127 + curGlobalBRE->gbreDefByStrPat = strPat;
6128 + curGlobalBRE->gbreRegExpText = curStrPatBRE->spbreRegExpText;
6133 + return True;
6137 +** Allocate and return a new string holding content of
6138 +** global backref. definition.
6140 +static char *createBackRefRegExpText(
6141 + const char *start,
6142 + const char *end)
6144 + int len = end - start;
6145 + char *regExpText = XtMalloc( len+1 );
6147 + memcpy( regExpText, start, len );
6149 + regExpText[len] = '\0';
6151 + return regExpText;
6155 +** Resolve all global backrefs of given match pattern table element.
6156 +** Returns false, if resolve fails.
6158 +static int resolveGlobalBackRefs(
6159 + ReadMatchPatternInfo *readPatInfo,
6160 + MatchPatternTableElement *element,
6161 + ErrorInfo *errInfo)
6163 + int i;
6164 + StringPattern *strPat;
6166 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
6168 + strPat = getReadStringPattern(readPatInfo, element->mpteAll.pesPattern[i]);
6170 + if (strPat->spRegularExpression && !strPat->spBackRefResolved)
6172 + if (!resolveGlobalBackRefsOfStrPat(strPat, element->mpteGlobalBackRef, errInfo))
6173 + return False;
6175 + strPat->spBackRefResolved = True;
6179 + return True;
6183 +** Resolve global backrefs of given string pattern.
6184 +** Returns false, if resolve fails.
6186 +static int resolveGlobalBackRefsOfStrPat(
6187 + StringPattern *strPat,
6188 + GlobalBackRefElement *backRefList,
6189 + ErrorInfo *errInfo)
6191 + char *s;
6192 + int globalId;
6193 + int localId = 1;
6195 + s = strPat->spText;
6197 + while (*s != '\0')
6199 + if (*s == '\\')
6201 + if (isdigit((unsigned char)*(s+1)))
6203 + /*
6204 + * \n (n=1..9) found: substitute global backref.
6205 + */
6206 + globalId =
6207 + (int)((unsigned char)*(s+1) - (unsigned char)'0') - 1;
6209 + if(globalId < 0)
6211 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6212 + errInfo->eiDetail = "backref '\\0' not allowed";
6213 + return False;
6216 + s = substituteGlobalBackRef(strPat, s, globalId, &localId, backRefList, errInfo);
6218 + if (s == NULL)
6219 + return False;
6221 + else if (*(s+1) != '\0')
6222 + s ++;
6224 + else if (*s == '(')
6226 + if (*(s+1) == '*')
6228 + if (isdigit((unsigned char)*(s+2)))
6230 + /*
6231 + * "(*n" (n=1..9) found: substitute global backref. definition.
6232 + */
6233 + globalId =
6234 + (int)((unsigned char)*(s+2) - (unsigned char)'0') - 1;
6236 + strPat->spOwnGlobalBackRef[globalId].spbreLocalBackRefID = localId;
6237 + strPat->spGlobalToLocalBackRef[globalId] = localId;
6239 + localId ++;
6241 + s = convertGlobalToLocalBackRef(strPat, s);
6243 + else
6245 + s ++;
6249 + s ++;
6252 + return True;
6256 +** Substitute global backref (\n, n=1..9) located at given "subsPtr"
6257 +** by its definition or by a local backref.
6258 +** Returns
6259 +** - NULL, if substitute fails or
6260 +** - substituted string pointer, where scan shall continue with.
6262 +static char *substituteGlobalBackRef(
6263 + StringPattern *strPat,
6264 + char *subsPtr,
6265 + int globalId,
6266 + int *localId,
6267 + GlobalBackRefElement *backRefList,
6268 + ErrorInfo *errInfo)
6270 + StrPatBackRefElement *strPatBackRef = &strPat->spOwnGlobalBackRef[globalId];
6271 + char *s;
6273 + if (strPatBackRef->spbreRegExpText == NULL)
6275 + /*
6276 + * given global backref definition is not located in given
6277 + * string pattern -> replace backref ID by backref reg. exp.
6278 + */
6279 + if (backRefList[globalId].gbreRegExpText == NULL)
6281 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6282 + errInfo->eiBackRefNbr = globalId + 1;
6283 + errInfo->eiDetail = "not defined within any string pattern";
6284 + return NULL;
6287 + if (strPat->spGlobalToLocalBackRef[globalId] == NO_LOCAL_BACK_REF_ID)
6289 + /*
6290 + * 1st occurence of global backref ID in this pattern ->
6291 + * replace global backref ID by backref reg. exp.
6292 + */
6293 + s = replaceBackRefIdByRegExp(strPat, subsPtr, backRefList[globalId].gbreRegExpText);
6295 + strPat->spGlobalToLocalBackRef[globalId] = *localId;
6296 + (*localId) ++;
6298 + else
6300 + /*
6301 + * next occurence of global backref ID in this pattern ->
6302 + * replace global backref ID by local one
6303 + */
6304 + s = subsPtr + 1;
6305 + *s = (char)((int)('0') + strPat->spGlobalToLocalBackRef[globalId]);
6308 + else
6310 + /*
6311 + * given global backref definition is located in given string pattern
6312 + */
6313 + if (strPatBackRef->spbreLocalBackRefID == NO_LOCAL_BACK_REF_ID)
6315 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6316 + errInfo->eiBackRefNbr = globalId + 1;
6317 + errInfo->eiDetail = "not defined before";
6318 + return NULL;
6321 + /*
6322 + * replace global backref ID by local one
6323 + */
6324 + s = subsPtr + 1;
6325 + *s = (char)((int)('0') + strPatBackRef->spbreLocalBackRefID);
6328 + return s;
6332 +** Replace global backref ID ("\n", n=1..9), located at given
6333 +** replaceStartPtr, by its definition (given by regExp parameter).
6334 +** Returns string pointer, where scan shall continue with
6336 +static char *replaceBackRefIdByRegExp(
6337 + StringPattern *strPat,
6338 + char *replaceStartPtr,
6339 + char *regExp)
6341 + char *oldText = strPat->spText;
6342 + char *newText;
6343 + char *n;
6344 + char *continueScanPtr;
6345 + int oldLen = strlen(oldText);
6346 + int regExpLen = strlen(regExp);
6347 + int replacePos = replaceStartPtr - oldText;
6348 + int remainingLen = oldLen-replacePos-2;
6350 + /*
6351 + * replace "\n" - located at replaceStartPtr - by "(regExp)"
6352 + */
6353 + newText = XtMalloc(oldLen + regExpLen + 3);
6355 + memcpy(newText, oldText, replacePos);
6356 + n = newText + replacePos;
6357 + *n = '(';
6358 + continueScanPtr = n;
6359 + n ++;
6360 + memcpy(n, regExp, regExpLen);
6361 + n += regExpLen;
6362 + *n = ')';
6363 + n ++;
6364 + memcpy(n, replaceStartPtr+2, remainingLen);
6365 + *(n + remainingLen) = '\0';
6367 + XtFree(oldText);
6369 + strPat->spText = newText;
6370 + strPat->spLength = strlen(newText);
6372 + return continueScanPtr;
6376 +** Convert global backref definition ("(*n", n=1..9), located at given
6377 +** convertPtr, by capturing parentheses "(".
6378 +** Returns string pointer, where scan shall continue with
6380 +static char *convertGlobalToLocalBackRef(
6381 + StringPattern *strPat,
6382 + char *convertPtr)
6384 + char *oldText = strPat->spText;
6385 + char *newText;
6386 + int oldLen = strlen(oldText);
6387 + int convertPos = convertPtr - oldText;
6389 + /*
6390 + * replace "(*n" - located at convertPtr - by "("
6391 + */
6392 + newText = XtMalloc(oldLen - 1);
6394 + memcpy(newText, oldText, convertPos+1);
6395 + memcpy(newText+convertPos+1, convertPtr+3, oldLen-convertPos-3);
6397 + *(newText + oldLen - 2) = '\0';
6399 + XtFree(oldText);
6401 + strPat->spText = newText;
6402 + strPat->spLength = strlen(newText);
6404 + return newText + convertPos;
6408 +** Read a match pattern table element from given input string.
6409 +** Return NULL, if read fails.
6411 +static MatchPatternTableElement *readMatchPatternTableElement(
6412 + char **inPtr,
6413 + char **errMsg,
6414 + char *name,
6415 + MatchPatternType type)
6417 + int error = False;
6418 + PatternElement *pattern;
6419 + PatternElement *allPat[MAX_STRING_PATTERNS];
6420 + int nbrOfPat = 0;
6421 + int sizeOfPat;
6422 + MatchPatternTableElement *result;
6423 + int isMonoPattern;
6424 + int skipBtwStartEnd;
6425 + int flash;
6426 + int ignoreHighLightInfo;
6427 + int i;
6429 + if (!getMPSGlobalAttribute(
6430 + inPtr,
6431 + errMsg,
6432 + &isMonoPattern,
6433 + &skipBtwStartEnd,
6434 + &flash,
6435 + &ignoreHighLightInfo ))
6437 + return NULL;
6440 + /*
6441 + * read all patterns
6442 + */
6443 + while (**inPtr != '\n' && !error)
6445 + if (!readPatternElement( inPtr, errMsg, &pattern ))
6447 + error = True;
6449 + else if (nbrOfPat >= MAX_STRING_PATTERNS)
6451 + *errMsg = "max. number of string patterns exceeded";
6452 + error = True;
6454 + else
6456 + pattern->peIndex = nbrOfPat;
6458 + allPat[nbrOfPat ++] = pattern;
6462 + if (error)
6464 + for (i=0; i < nbrOfPat; i ++)
6465 + freePatternElement( allPat[i] );
6467 + return NULL;
6470 + if (nbrOfPat == 0)
6472 + *errMsg = "min. one string pattern needed";
6473 + return NULL;
6476 + /*
6477 + * allocate & init. MatchPatternTableElement
6478 + */
6479 + result =
6480 + (MatchPatternTableElement *)XtMalloc(sizeof(MatchPatternTableElement));
6482 + result->mpteName = name;
6483 + result->mpteIndex = NO_ELEMENT_IDX;
6484 + result->mpteType = type;
6485 + result->mpteGroup = NO_GROUP_IDX;
6487 + sizeOfPat = sizeof(PatternElement *) * nbrOfPat;
6488 + result->mpteAll.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6490 + memcpy(result->mpteAll.pesPattern, allPat, sizeOfPat);
6492 + result->mpteAll.pesNumberOfPattern = nbrOfPat;
6494 + result->mpteIsMonoPattern = isMonoPattern;
6495 + result->mpteSkipBtwnStartEnd = skipBtwStartEnd;
6496 + result->mpteFlash = flash;
6497 + result->mpteIgnoreHighLightInfo = ignoreHighLightInfo;
6499 + result->mpteStartEndRE = NULL;
6501 + initGlobalBackRefList( result->mpteGlobalBackRef );
6503 + /*
6504 + * sort start / end / middle pattern
6505 + */
6506 + error = !sortReadPatternElementSet( &result->mpteAll, errMsg, result );
6508 + if (error)
6510 + freeMatchPatternTableElement( result );
6511 + return NULL;
6513 + else
6515 + return result;
6520 + * Sort read pattern element set into start, middle & end arrays.
6521 + * Validate "monopattern" attribute.
6522 + * Returns true, if validation was successful.
6523 + */
6524 +static int sortReadPatternElementSet(
6525 + PatternElementSet *allPat,
6526 + char **errMsg,
6527 + MatchPatternTableElement *result)
6529 + int sizeOfPat;
6530 + int isMonoPattern = result->mpteIsMonoPattern;
6532 + /*
6533 + * count number of start, middle & end pattern elements.
6534 + */
6535 + countPatternElementKind( allPat, result );
6537 + /*
6538 + * validate and allocate pattern elements.
6539 + */
6540 + if (result->mpteStart.pesNumberOfPattern != 0)
6542 + sizeOfPat = sizeof(PatternElement *) * result->mpteStart.pesNumberOfPattern;
6543 + result->mpteStart.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6545 + else
6547 + *errMsg = "min. one start pattern needed";
6548 + return False;
6551 + if (isMonoPattern &&
6552 + (result->mpteMiddle.pesNumberOfPattern != 0 ||
6553 + result->mpteEnd.pesNumberOfPattern !=0))
6555 + *errMsg = "mono pattern: only start pattern(s) allowed due to attribute [m]";
6556 + return False;
6559 + if (result->mpteMiddle.pesNumberOfPattern != 0)
6561 + sizeOfPat = sizeof(PatternElement *) * result->mpteMiddle.pesNumberOfPattern;
6562 + result->mpteMiddle.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6565 + if (result->mpteEnd.pesNumberOfPattern != 0)
6567 + sizeOfPat = sizeof(PatternElement *) * result->mpteEnd.pesNumberOfPattern;
6568 + result->mpteEnd.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6570 + else
6572 + if (!isMonoPattern)
6574 + *errMsg = "min. one end pattern needed";
6575 + return False;
6579 + /*
6580 + * sort pattern elements into start, middle & end arrays.
6581 + */
6582 + sortPatternElementSet( allPat, result );
6584 + if (isMonoPattern)
6586 + copyPatternSet( &result->mpteStart, &result->mpteEnd );
6589 + return True;
6593 + * Count number of start, middle & end patterns stored in "allPat".
6594 + */
6595 +static void countPatternElementKind(
6596 + PatternElementSet *allPat,
6597 + MatchPatternTableElement *result)
6599 + int i;
6601 + result->mpteStart.pesNumberOfPattern = 0;
6602 + result->mpteEnd.pesNumberOfPattern = 0;
6603 + result->mpteMiddle.pesNumberOfPattern = 0;
6605 + result->mpteStart.pesPattern = NULL;
6606 + result->mpteEnd.pesPattern = NULL;
6607 + result->mpteMiddle.pesPattern = NULL;
6609 + for (i=0; i < allPat->pesNumberOfPattern; i ++)
6611 + switch (allPat->pesPattern[i]->peKind)
6613 + case PEK_START:
6614 + result->mpteStart.pesNumberOfPattern ++;
6615 + break;
6616 + case PEK_MIDDLE:
6617 + result->mpteMiddle.pesNumberOfPattern ++;
6618 + break;
6619 + case PEK_END:
6620 + result->mpteEnd.pesNumberOfPattern ++;
6621 + break;
6622 + default:;
6628 + * Sort start, middle & end pattern elements into related arrays.
6629 + */
6630 +static void sortPatternElementSet(
6631 + PatternElementSet *allPat,
6632 + MatchPatternTableElement *result)
6634 + int i;
6635 + int s,m,e;
6637 + for (i=0, s=0, m=0, e=0; i < allPat->pesNumberOfPattern; i ++)
6639 + switch (allPat->pesPattern[i]->peKind)
6641 + case PEK_START:
6642 + result->mpteStart.pesPattern[s ++] = allPat->pesPattern[i];
6643 + break;
6644 + case PEK_MIDDLE:
6645 + result->mpteMiddle.pesPattern[m ++] = allPat->pesPattern[i];
6646 + break;
6647 + case PEK_END:
6648 + result->mpteEnd.pesPattern[e ++] = allPat->pesPattern[i];
6649 + break;
6650 + default:;
6655 +static void copyPatternSet(
6656 + PatternElementSet *sourcePS,
6657 + PatternElementSet *destPS)
6659 + int sizeOfPat;
6661 + destPS->pesNumberOfPattern = sourcePS->pesNumberOfPattern;
6663 + sizeOfPat = sizeof(PatternElement *) * destPS->pesNumberOfPattern;
6664 + destPS->pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6666 + memcpy(destPS->pesPattern, sourcePS->pesPattern, sizeOfPat);
6670 +** Free the allocated memory contained in a ReadMatchPatternInfo data structure
6672 +static void freeReadMatchPatternInfo( ReadMatchPatternInfo *readPatInfo )
6674 + int i;
6676 + for (i=0; i<readPatInfo->rmpiNbrOfElements; i++)
6677 + freeMatchPatternTableElement(readPatInfo->rmpiElement[i]);
6679 + for (i=0; i<readPatInfo->rmpiNbrOfGroups; i++)
6680 + freeMatchPatternGroupElement(readPatInfo->rmpiGroup[i]);
6682 + for (i=0; i<readPatInfo->rmpiNbrOfSeqElements; i++)
6683 + freeMatchPatternSequenceElement(readPatInfo->rmpiSequence[i]);
6685 + freePtr((void **)&readPatInfo->rmpiAllPatRE);
6687 + freePtr((void **)&readPatInfo->rmpiFlashPatRE);
6691 +** Free the allocated memory contained in a StringMatchTable data structure
6693 +static void freeStringMatchTable( StringMatchTable *table )
6695 + MatchPatternTable *patTable;
6696 + int i;
6698 + if (table == NULL)
6699 + return;
6701 + XtFree(table->smtLanguageMode);
6703 + /*
6704 + * Free all matching patterns
6705 + */
6706 + patTable = table->smtAllPatterns;
6708 + for (i=0; i<patTable->mptNumberOfElements; i++)
6709 + freeMatchPatternTableElement(patTable->mptElements[i]);
6711 + XtFree((char *)patTable);
6713 + /*
6714 + * Free matching pattern group elements
6715 + */
6716 + for (i=0; i<table->smtNumberOfGroups; i++)
6717 + freeMatchPatternGroupElement(table->smtGroups[i]);
6719 + /*
6720 + * Free matching pattern sequence elements
6721 + */
6722 + for (i=0; i<table->smtNumberOfSeqElements; i++)
6723 + freeMatchPatternSequenceElement(table->smtSequence[i]);
6725 + /*
6726 + * Free keyword reg. expressions
6727 + */
6728 + freePtr((void **)&table->smtAllPatRE);
6730 + freePtr((void **)&table->smtFlashPatRE);
6732 + XtFree((char *)table);
6736 +** Free the allocated memory contained in a MatchPatternTableElement data structure
6738 +static void freeMatchPatternTableElement( MatchPatternTableElement *element )
6740 + int i;
6742 + XtFree(element->mpteName);
6744 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
6746 + freePatternElement(element->mpteAll.pesPattern[i]);
6749 + freePtr((void **)&element->mpteStartEndRE);
6751 + freeXtPtr((void **)&element->mpteStart.pesPattern);
6753 + freeXtPtr((void **)&element->mpteMiddle.pesPattern);
6755 + freeXtPtr((void **)&element->mpteEnd.pesPattern);
6757 + XtFree((char *)element);
6761 +** Free the allocated memory contained in a PatternElement data structure
6763 +static void freePatternElement( PatternElement *element )
6765 + if (element->peType == PET_SINGLE)
6766 + freeStringPattern( &(element->peVal.peuSingle) );
6767 + else if (element->peType == PET_MULTIPLE)
6769 + freeStringPattern( &(element->peVal.peuMulti.mpStringPattern) );
6770 + XtFree( (char *)element->peVal.peuMulti.mpRefList );
6773 + XtFree( (char *)element );
6777 +** Free the allocated memory contained in a StringPattern data structure
6779 +static void freeStringPattern( StringPattern *strPat )
6781 + int i;
6783 + freeXtPtr((void **)&strPat->spText);
6784 + freeXtPtr((void **)&strPat->spOrigText);
6786 + freePtr((void **)&strPat->spTextRE);
6788 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
6789 + freeXtPtr((void **)&strPat->spOwnGlobalBackRef[i].spbreRegExpText);
6793 +** Free the allocated memory contained in a MatchPatternGroupElement data structure
6795 +static void freeMatchPatternGroupElement( MatchPatternGroupElement *group )
6797 + int i;
6799 + freeXtPtr((void **)&group->mpgeName);
6801 + freePtr((void **)&group->mpgeKeywordRE);
6803 + if (group->mpgeSubPatternIds != NULL)
6805 + for (i=0; i < group->mpgeNumberOfSubPatterns; i++)
6807 + XtFree(group->mpgeSubPatternIds[i]);
6809 + XtFree((char *)group->mpgeSubPatternIds);
6812 + XtFree((char *)group);
6816 +** Free the allocated memory contained in a MatchPatternSequenceElement data structure
6818 +static void freeMatchPatternSequenceElement( MatchPatternSequenceElement *sequence )
6820 + XtFree( sequence->mpseName );
6822 + XtFree( (char *)sequence );
6827 +** Format a matching pattern set parse error.
6829 +static void parseMatchingPatternSetError(
6830 + const char *stringStart,
6831 + const char *stoppedAt,
6832 + ErrorInfo *errInfo)
6834 + char *message = "";
6835 + int msgLen;
6836 + char *errorInForm = "matching pattern of \"%s\"";
6837 + char *errorIn;
6839 + if (errInfo->eiLanguageMode == NULL)
6841 + errorIn = "matching pattern";
6843 + else
6845 + errorIn = XtMalloc(strlen(errorInForm) + strlen(errInfo->eiLanguageMode)+1);
6846 + sprintf(errorIn, "matching pattern of \"%s\"", errInfo->eiLanguageMode);
6849 + if (errInfo->eiRegExpCompileMsg != NULL)
6851 + /*
6852 + * Error message of form:
6853 + * "MP \"eiMPTabElementName\", SP \"eiStringPatText\": eiRegExpCompileMsg" or
6854 + * "MP \"eiMPTabElementName\" - eiDetail: eiRegExpCompileMsg"
6855 + */
6857 + msgLen = strlen(errInfo->eiRegExpCompileMsg) + 1;
6859 + if (errInfo->eiMPTabElementName != NULL)
6860 + msgLen += strlen(errInfo->eiMPTabElementName) + 10;
6862 + if (errInfo->eiDetail != NULL)
6864 + msgLen += strlen(errInfo->eiDetail + 2);
6866 + else
6868 + if (errInfo->eiStringPatText != NULL)
6869 + msgLen += strlen(errInfo->eiStringPatText) + 9;
6872 + message = XtMalloc(msgLen);
6874 + strcpy(message, "");
6876 + if (errInfo->eiMPTabElementName != NULL)
6877 + sprintf( message, "MP \"%s\"", errInfo->eiMPTabElementName);
6879 + if (errInfo->eiDetail == NULL)
6881 + if (errInfo->eiStringPatText != NULL)
6882 + sprintf( message, "%s, SP \"%s\"", message, errInfo->eiStringPatText);
6884 + else
6886 + if (strlen(message) != 0)
6887 + strcat(message, " - ");
6889 + strcat(message, errInfo->eiDetail);
6892 + if (strlen(message) != 0)
6893 + strcat(message, ": ");
6895 + strcat(message, errInfo->eiRegExpCompileMsg);
6897 + else if (errInfo->eiDetail != NULL)
6899 + /*
6900 + * Error message of form:
6901 + * "MP \"eiMPTabElementName\", SP \"eiStringPatText\": Backref %d eiDetail
6902 + */
6903 + msgLen = strlen(errInfo->eiDetail) + 1;
6905 + if (errInfo->eiMPTabElementName != NULL)
6906 + msgLen += strlen(errInfo->eiMPTabElementName) + 7;
6907 + if (errInfo->eiStringPatText != NULL)
6908 + msgLen += strlen(errInfo->eiStringPatText) + 9;
6909 + if (errInfo->eiBackRefNbr != 0)
6910 + msgLen += 15;
6912 + message = XtMalloc(msgLen);
6914 + strcpy(message, "");
6916 + if (errInfo->eiMPTabElementName != NULL)
6917 + sprintf( message, "MP \"%s\"", errInfo->eiMPTabElementName);
6918 + if (errInfo->eiStringPatText != NULL)
6919 + sprintf( message, "%s, SP \"%s\"", message, errInfo->eiStringPatText);
6921 + if (strlen(message) != 0)
6922 + strcat(message, ": ");
6924 + if (errInfo->eiBackRefNbr != 0)
6925 + sprintf( message, "%s Backref %d ", message, errInfo->eiBackRefNbr);
6927 + strcat(message, errInfo->eiDetail);
6930 + ParseError(NULL, stringStart, stoppedAt, errorIn, message);
6932 + if (errInfo->eiRegExpCompileMsg != NULL || errInfo->eiDetail != NULL)
6934 + XtFree(message);
6937 + if (errInfo->eiLanguageMode != NULL)
6939 + XtFree(errorIn);
6942 + freeErrorInfo(errInfo);
6943 + initErrorInfo(errInfo);
6947 + * Pop-up a warning dialog showing a matching pattern set error.
6948 + */
6949 +static void dialogMatchingPatternSetError(
6950 + char *title,
6951 + ErrorInfo *errInfo)
6953 + char *message;
6954 + int msgLen = 1;
6956 + /*
6957 + * Error message of form:
6958 + * "Name : \"eiMPTabElementName\"\n
6959 + * "String: \"eiStringPatText\"\n
6960 + * eiDetail\n
6961 + * eiRegExpCompileMsg\n"
6962 + */
6964 + if (errInfo->eiMPTabElementName != NULL)
6965 + msgLen += strlen(errInfo->eiMPTabElementName) + 15;
6966 + if (errInfo->eiStringPatText != NULL)
6967 + msgLen += strlen(errInfo->eiStringPatText) + 15;
6968 + if (errInfo->eiDetail != NULL)
6969 + msgLen += strlen(errInfo->eiDetail) + 15;
6970 + if (errInfo->eiBackRefNbr != 0)
6971 + msgLen += 15;
6972 + if (errInfo->eiRegExpCompileMsg != NULL)
6973 + msgLen += strlen(errInfo->eiRegExpCompileMsg) + 15;
6975 + message = XtMalloc(msgLen);
6977 + strcpy(message, "");
6979 + if (errInfo->eiMPTabElementName != NULL)
6980 + sprintf( message, "%sName : \"%s\"\n", message, errInfo->eiMPTabElementName);
6981 + if (errInfo->eiStringPatText != NULL)
6982 + sprintf( message, "%sPattern: \"%s\"\n", message, errInfo->eiStringPatText);
6983 + if (errInfo->eiBackRefNbr != 0)
6984 + sprintf( message, "%sBackref %d ", message, errInfo->eiBackRefNbr);
6985 + if (errInfo->eiDetail != NULL)
6986 + sprintf( message, "%s%s\n", message, errInfo->eiDetail);
6987 + if (errInfo->eiRegExpCompileMsg != NULL)
6988 + sprintf( message, "%s%s\n", message, errInfo->eiRegExpCompileMsg);
6990 + DialogF(
6991 + DF_WARN, MatchPatternDialog.mpdShell, 1,
6992 + title,
6993 + "%s(language mode '%s')",
6994 + "OK",
6995 + message,
6996 + errInfo->eiLanguageMode);
6998 + XtFree(message);
7000 + freeErrorInfo(errInfo);
7001 + initErrorInfo(errInfo);
7005 +** Get matching pattern set name.
7006 +** Syntax:
7007 +** patternName ::= "name:"
7008 +** Returns true, if get was successful.
7010 +static int getMPSName(
7011 + char **inPtr,
7012 + ErrorInfo *errInfo,
7013 + char **name )
7015 + char *dummy;
7016 + char *field = ReadSymbolicField(inPtr);
7018 + if (field == NULL)
7020 + errInfo->eiDetail = "matching pattern name missing";
7021 + return False;
7024 + if (!SkipDelimiter(inPtr, &dummy))
7026 + errInfo->eiMPTabElementName = XtNewString(field);
7027 + errInfo->eiDetail = "':' missing after matching pattern name";
7028 + XtFree( field );
7029 + return False;
7032 + *name = field;
7034 + return True;
7038 +** Get matching pattern set type attribute.
7039 +** TypeAttribute ::=
7040 +** [s|g]:
7042 +** s : sub-pattern (pattern is only matched, if part of a pattern group).
7043 +** g : pattern (context) group (i.e. a sequence of sub-patterns).
7044 +** default: individual pattern (pattern is not part of a group and is
7045 +** matched individually.
7046 +** Returns true, if get was successful.
7048 +static int getMPSTypeAttribute(
7049 + char **inPtr,
7050 + ErrorInfo *errInfo,
7051 + MatchPatternType *type)
7053 + char *field = ReadSymbolicField(inPtr);
7054 + int successful = True;
7056 + *type = MPT_INDIVIDUAL;
7058 + if (field != NULL)
7060 + switch (*field)
7062 + case 'g':
7063 + *type = MPT_GROUP;
7064 + break;
7065 + case 's':
7066 + *type = MPT_SUB;
7067 + break;
7068 + default:
7069 + errInfo->eiDetail = "unknown matching pattern type attribute";
7070 + successful = False;
7074 + if (successful)
7076 + if (!SkipDelimiter(inPtr, &errInfo->eiDetail))
7078 + successful = False;
7082 + freeXtPtr((void **)&field);
7084 + return successful;
7088 +** Syntax:
7090 +** GlobalAttribute ::=
7091 +** [c][f][m][p][u]:
7093 +** c : the content between start and end pattern is skipped
7094 +** during parsing (e.g. pattern encloses a comment).
7095 +** f : flash matching pattern (if not set, then only jump
7096 +** to matching pattern is supported).
7097 +** m : mono pattern - set exist out of only one single pattern
7098 +** (start pattern = end pattern; e.g. quotes like ")
7099 +** p : ignore highlight info code of single patterns of this set
7100 +** ("plain").
7102 +** Returns TRUE, if global attribute was successful read.
7104 +static int getMPSGlobalAttribute(
7105 + char **inPtr,
7106 + char **errMsg,
7107 + int *isMonoPattern,
7108 + int *comment,
7109 + int *flash,
7110 + int *ignoreHighLightInfo)
7112 + char *field = ReadSymbolicField(inPtr);
7113 + char *attribute;
7114 + int successful = True;
7116 + *isMonoPattern = False;
7117 + *comment = False;
7118 + *flash = False;
7119 + *ignoreHighLightInfo = False;
7121 + if (field != NULL)
7123 + attribute = field;
7124 + while (*attribute != '\0' && successful)
7126 + switch (*attribute)
7128 + case 'c':
7129 + *comment = True;
7130 + break;
7131 + case 'f':
7132 + *flash = True;
7133 + break;
7134 + case 'm':
7135 + *isMonoPattern = True;
7136 + break;
7137 + case 'p':
7138 + *ignoreHighLightInfo = True;
7139 + break;
7140 + default:
7141 + *errMsg = "unknown global attribute";
7142 + successful = False;
7144 + attribute ++;
7148 + if (successful)
7150 + if (!SkipDelimiter(inPtr, errMsg))
7152 + successful = False;
7156 + freeXtPtr((void **)&field);
7158 + return successful;
7162 +** Get matching pattern set attribute.
7164 +** Syntax:
7166 +** patternAttribute ::=
7167 +** [s|m|e][w|l|r][i]:
7169 +** StringPatternKind:
7170 +** s : start string pattern.
7171 +** m : middle string pattern.
7172 +** e : end string pattern.
7173 +** WordBoundaryAttribute:
7174 +** w : pattern is word (i.e. before and after pattern
7175 +** there must be a delimiter).
7176 +** l : before pattern must be a delimiter (left side).
7177 +** r : after pattern must be a delimiter (right side).
7178 +** default: neither before nor after pattern must be a delimiter.
7179 +** StringAttribute:
7180 +** i : pattern is case insensitive (if not set: pattern is
7181 +** case sensitive).
7182 +** x : pattern is regular expression (if not set: pattern is
7183 +** literal string).
7185 +** Returns TRUE, if pattern attribute was successful read.
7187 +static int getMPSPatternAttribute(
7188 + char **inPtr,
7189 + char **errMsg,
7190 + PatternElementKind *patternKind,
7191 + PatternWordBoundary *wordBoundary,
7192 + int *caseInsensitive,
7193 + int *regularExpression)
7195 + char *field = ReadSymbolicField(inPtr);
7196 + char *attribute;
7197 + int successful = True;
7199 + *patternKind = PEK_UNKNOWN;
7200 + *wordBoundary = PWB_NONE;
7201 + *caseInsensitive = False;
7202 + *regularExpression = False;
7204 + if (field != NULL)
7206 + attribute = field;
7207 + while (*attribute != '\0' && successful)
7209 + switch (*attribute)
7211 + case 'e':
7212 + *patternKind = PEK_END;
7213 + break;
7214 + case 'i':
7215 + *caseInsensitive = True;
7216 + break;
7217 + case 'l':
7218 + *wordBoundary = PWB_LEFT;
7219 + break;
7220 + case 'm':
7221 + *patternKind = PEK_MIDDLE;
7222 + break;
7223 + case 'r':
7224 + *wordBoundary = PWB_RIGHT;
7225 + break;
7226 + case 's':
7227 + *patternKind = PEK_START;
7228 + break;
7229 + case 'w':
7230 + *wordBoundary = PWB_BOTH;
7231 + break;
7232 + case 'x':
7233 + *regularExpression = True;
7234 + break;
7235 + default:
7236 + *errMsg = "unknown string pattern attribute";
7237 + successful = False;
7239 + attribute ++;
7243 + if (successful)
7245 + if (!SkipDelimiter(inPtr, errMsg))
7247 + successful = False;
7251 + freeXtPtr((void **)&field);
7253 + return successful;
7257 +** Returns the (to be reserved) reg. ex. length of an pattern element.
7258 +** Update total number of multi patterns, too.
7260 +static int patternElementLen(
7261 + ReadMatchPatternInfo *info,
7262 + PatternElement *patElement,
7263 + int *nbrOfMultiPatterns)
7265 + PatternElement *referredElement;
7266 + StringPattern *strPat = NULL;
7267 + int patElementLen;
7269 + switch (patElement->peType)
7271 + case PET_SINGLE:
7272 + strPat = &patElement->peVal.peuSingle;
7273 + break;
7275 + case PET_MULTIPLE:
7276 + strPat = &patElement->peVal.peuMulti.mpStringPattern;
7278 + (*nbrOfMultiPatterns) ++;
7280 + break;
7282 + case PET_REFERENCE:
7283 + referredElement =
7284 + info->rmpiElement[patElement->peVal.peuRef.prElementIdx]->
7285 + mpteAll.pesPattern[patElement->peVal.peuRef.prPatternIdx];
7287 + strPat = &referredElement->peVal.peuMulti.mpStringPattern;
7288 + break;
7291 + /*
7292 + * reserve additional 4 characters ("(?i)") for case insensitive search
7293 + */
7294 + if (strPat->spCaseInsensitive)
7295 + patElementLen = strPat->spLength + 4;
7296 + else
7297 + patElementLen = strPat->spLength;
7299 + /*
7300 + * reserve additional 4 characters ("(?:)") for regular expression
7301 + */
7302 + if (strPat->spRegularExpression)
7303 + patElementLen += 4;
7305 + return patElementLen;
7309 +** Returns the (to be reserved) total reg. ex. length of given
7310 +** MatchPatternTableElement. Update total number of multi patterns, too.
7312 +static int totalMatchPatternTableElementLen(
7313 + ReadMatchPatternInfo *info,
7314 + MatchPatternTableElement *element,
7315 + int *nbrOfMultiPatterns)
7317 + int i;
7318 + int totalLen = 0;
7320 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i ++)
7322 + totalLen +=
7323 + patternElementLen(
7324 + info,
7325 + element->mpteAll.pesPattern[i],
7326 + nbrOfMultiPatterns );
7329 + return totalLen;
7333 +** Returns the (to be reserved) total reg. ex. length of given
7334 +** read match pattern info. Counts total number of multi patterns, too.
7336 +static int totalKeywordOfTableLen(
7337 + ReadMatchPatternInfo *info,
7338 + int *nbrOfMultiPatterns)
7340 + int i;
7341 + int totalLen = 0;
7343 + *nbrOfMultiPatterns = 0;
7345 + for (i=0; i<info->rmpiNbrOfElements; i ++)
7347 + totalLen +=
7348 + totalMatchPatternTableElementLen(
7349 + info,
7350 + info->rmpiElement[i],
7351 + nbrOfMultiPatterns);
7354 + return totalLen;
7358 +** Add given StringPattern to given reg. ex. strings
7360 +static void addPatternToRegExpString(
7361 + StringPattern *pattern,
7362 + RegExpStringInfo *regExpStringInfo)
7364 + char *r = NULL, *s;
7365 + char *adaptedRegExpText = NULL;
7366 + int prevLen = 0;
7368 + /*
7369 + * Select the buffer, where the pattern needs to be added
7370 + * to (depending on its word boundary). Prepare the buffer
7371 + * by evtl. adding a prefix, if related buffer is empty.
7372 + */
7373 + switch (pattern->spWordBoundary)
7375 + case PWB_NONE:
7376 + prevLen = strlen( regExpStringInfo->resiNoneWBRegExpString );
7378 + r = regExpStringInfo->resiNoneWBRegExpString + strlen( regExpStringInfo->resiNoneWBRegExpString );
7379 + break;
7380 + case PWB_LEFT:
7381 + prevLen = strlen( regExpStringInfo->resiLeftWBRegExpString );
7382 + if (prevLen == 0)
7384 + strcpy( regExpStringInfo->resiLeftWBRegExpString, "<(?:" );
7386 + r = regExpStringInfo->resiLeftWBRegExpString + strlen( regExpStringInfo->resiLeftWBRegExpString );
7387 + break;
7388 + case PWB_RIGHT:
7389 + prevLen = strlen( regExpStringInfo->resiRightWBRegExpString );
7390 + if (prevLen == 0)
7392 + strcpy( regExpStringInfo->resiRightWBRegExpString, "(?:" );
7394 + r = regExpStringInfo->resiRightWBRegExpString + strlen( regExpStringInfo->resiRightWBRegExpString );
7395 + break;
7396 + case PWB_BOTH:
7397 + prevLen = strlen( regExpStringInfo->resiBothWBRegExpString );
7398 + if (prevLen == 0)
7400 + strcpy( regExpStringInfo->resiBothWBRegExpString, "<(?:" );
7402 + r = regExpStringInfo->resiBothWBRegExpString + strlen( regExpStringInfo->resiBothWBRegExpString );
7403 + break;
7406 + /*
7407 + * add an "or" if there is already a pattern in the buffer
7408 + */
7409 + if (prevLen != 0)
7411 + *r++ = '|';
7414 + /*
7415 + * add "(?i" to order case insensitive search
7416 + */
7417 + if (pattern->spCaseInsensitive)
7419 + *r++ = '(';
7420 + *r++ = '?';
7421 + *r++ = 'i';
7424 + /*
7425 + * add "(?:" to group this regular expression
7426 + */
7427 + if (pattern->spRegularExpression)
7429 + *r++ = '(';
7430 + *r++ = '?';
7431 + *r++ = ':';
7433 + adaptedRegExpText =
7434 + adaptLocalBackRefs(
7435 + pattern->spText,
7436 + &regExpStringInfo->resiLocalBackRefID);
7438 + s = adaptedRegExpText;
7440 + else
7442 + s = pattern->spText;
7445 + /*
7446 + * add the pattern characters - evtl. escaped, if special
7447 + * regular expression symbols & pattern is no reg. exp. -
7448 + * to the buffer:
7449 + */
7451 + while (*s != '\0')
7453 + if (!pattern->spRegularExpression)
7455 + switch (*s)
7457 + case '(':
7458 + case ')':
7459 + case '-':
7460 + case '[':
7461 + case ']':
7462 + case '<':
7463 + case '>':
7464 + case '{':
7465 + case '}':
7466 + case '.':
7467 + case '\\':
7468 + case '|':
7469 + case '^':
7470 + case '$':
7471 + case '*':
7472 + case '+':
7473 + case '?':
7474 + case '&':
7475 + *r++ = '\\';
7476 + break;
7477 + };
7480 + *r++ = *s++;
7483 + /*
7484 + * close "reg. exp. group" bracket
7485 + */
7486 + if (pattern->spRegularExpression)
7488 + *r++ = ')';
7490 + XtFree(adaptedRegExpText);
7493 + /*
7494 + * close case insensitive search bracket
7495 + */
7496 + if (pattern->spCaseInsensitive)
7498 + *r++ = ')';
7501 + /*
7502 + * terminate added string
7503 + */
7504 + *r = '\0';
7508 +** Adapt local backrefs inside given regExpText by common local IDs.
7509 +** Returns new allocated reg. exp. string holding common local backrefs.
7511 +static char *adaptLocalBackRefs(
7512 + char *regExpText,
7513 + int *commonLocalId)
7515 + int id;
7516 + int ownLocalId = 0;
7517 + char *s = regExpText;
7518 + char *newRegExpText = XtMalloc(strlen(regExpText)*3);
7519 + char *n = newRegExpText;
7520 + int localBackRefList[MAX_LOCAL_BACK_REF_ID];
7522 + /*
7523 + * put all local backrefs into "localBackRefList".
7524 + */
7525 + scanForLocalBackRefs(regExpText, localBackRefList);
7527 + while (*s != '\0')
7529 + *n++ = *s;
7531 + if (*s == '\\')
7533 + s++;
7535 + if (isdigit((unsigned char)*s))
7537 + /*
7538 + * \n (n=1..9) found: replace local backref.
7539 + * by "common local ID"
7540 + */
7541 + id =
7542 + (int)((unsigned char)*s - (unsigned char)'0') - 1;
7544 + if (localBackRefList[id] != NO_LOCAL_BACK_REF_ID &&
7545 + localBackRefList[id] != LOCAL_BACK_REF_ID_USED)
7547 + *n++ = (char)((int)('0') + localBackRefList[id]);
7549 + else
7551 + *n++ = '0';
7554 + s ++;
7556 + else if (*s != '\0')
7558 + /*
7559 + * copy escaped character
7560 + */
7561 + *n++ = *s++;
7564 + else if (*s == '(')
7566 + s ++;
7568 + if (*s == '?')
7570 + /*
7571 + * non capturing parentheses found -> just copy it
7572 + */
7573 + *n++ = *s++;
7575 + else
7577 + /*
7578 + * capturing parentheses found:
7579 + */
7580 + if (localBackRefList[ownLocalId] == LOCAL_BACK_REF_ID_USED)
7582 + /*
7583 + * backref used within given reg. exp. text:
7584 + * remember common local id for replacement later on
7585 + */
7586 + localBackRefList[ownLocalId] = *commonLocalId;
7587 + (*commonLocalId) ++;
7588 + ownLocalId ++;
7590 + else
7592 + /*
7593 + * backref not used within given reg. exp. text:
7594 + * replace capturing parentheses by non capturing one
7595 + */
7596 + *n++ = '?';
7597 + *n++ = ':';
7601 + else
7603 + s ++;
7607 + /*
7608 + * terminate adapted string
7609 + */
7610 + *n = '\0';
7612 + return newRegExpText;
7616 +** Get all local backrefs of given regExpText and put them into
7617 +** given localBackRefList.
7619 +static void scanForLocalBackRefs(
7620 + char *regExpText,
7621 + int *localBackRefList)
7623 + int i;
7624 + int localId;
7625 + char *s = regExpText;
7627 + for (i=0; i<MAX_LOCAL_BACK_REF_ID; i++)
7629 + localBackRefList[i] = NO_LOCAL_BACK_REF_ID;
7632 + while (*s != '\0')
7634 + if (*s == '\\')
7636 + if (isdigit((unsigned char)*(s+1)))
7638 + /*
7639 + * \n (n=1..9) found: flag usage in local backref list
7640 + */
7641 + localId =
7642 + (int)((unsigned char)*(s+1) - (unsigned char)'0') - 1;
7644 + localBackRefList[localId] = LOCAL_BACK_REF_ID_USED;
7646 + s ++;
7648 + else if (*(s+1) != '\0')
7649 + s ++;
7651 + s ++;
7656 +** Returns true, if string of given multi pattern reference was
7657 +** not added to regExpStringInfo.
7659 +static int isMultiPatternNotAdded(
7660 + RegExpStringInfo *regExpStringInfo,
7661 + PatternReference *toBeAddedPR)
7663 + int i;
7664 + PatternReference *addedPR;
7665 + PatternReference *newPR;
7667 + for (i=0; i < regExpStringInfo->resiNbrOfAddedMultiPat; i++)
7669 + addedPR = regExpStringInfo->resiAddedMultiPat[i];
7671 + if (addedPR->prElementIdx == toBeAddedPR->prElementIdx &&
7672 + addedPR->prPatternIdx == toBeAddedPR->prPatternIdx)
7674 + return False;
7678 + newPR = (PatternReference *)XtMalloc(sizeof(PatternReference));
7680 + *newPR = *toBeAddedPR;
7682 + regExpStringInfo->resiAddedMultiPat[regExpStringInfo->resiNbrOfAddedMultiPat ++] = newPR;
7684 + return True;
7688 +** add given PatternElement to given reg. exp. strings
7690 +static void addUniquePatternToRegExpString(
7691 + PatternElement *patElement,
7692 + PatternReference *patElementReference,
7693 + ReadMatchPatternInfo *readMatchPatternInfo,
7694 + RegExpStringInfo *regExpStringInfo)
7696 + PatternElement *referredElement;
7697 + PatternReference referredPatReference;
7699 + switch (patElement->peType)
7701 + case PET_SINGLE:
7702 + addPatternToRegExpString(
7703 + &(patElement->peVal.peuSingle),
7704 + regExpStringInfo);
7705 + break;
7707 + case PET_MULTIPLE:
7708 + /*
7709 + * add element to reg. exp. string only, if it was
7710 + * not added before.
7711 + */
7712 + if (isMultiPatternNotAdded(regExpStringInfo, patElementReference))
7714 + addPatternToRegExpString(
7715 + &(patElement->peVal.peuMulti.mpStringPattern),
7716 + regExpStringInfo);
7718 + break;
7720 + case PET_REFERENCE:
7721 + /*
7722 + * add referred element to reg. exp. string only, if related
7723 + * multi pattern was not added before.
7724 + */
7725 + referredPatReference = patElement->peVal.peuRef;
7727 + referredElement =
7728 + readMatchPatternInfo->rmpiElement[referredPatReference.prElementIdx]->
7729 + mpteAll.pesPattern[referredPatReference.prPatternIdx];
7731 + if (isMultiPatternNotAdded(regExpStringInfo, &referredPatReference))
7733 + addPatternToRegExpString(
7734 + &(referredElement->peVal.peuMulti.mpStringPattern),
7735 + regExpStringInfo);
7737 + break;
7742 +** add given MatchPatternTableElement to given reg. ex. strings
7744 +static void addElementToRegExpString(
7745 + MatchPatternTableElement *element,
7746 + ReadMatchPatternInfo *readMatchPatternInfo,
7747 + RegExpStringInfo *regExpStringInfo)
7749 + int i;
7750 + PatternReference elementRef;
7752 + elementRef.prElementIdx = element->mpteIndex;
7754 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i ++)
7756 + elementRef.prPatternIdx = i;
7758 + addUniquePatternToRegExpString(
7759 + element->mpteAll.pesPattern[i],
7760 + &elementRef,
7761 + readMatchPatternInfo,
7762 + regExpStringInfo);
7767 +** Concatenate strings stored by regExpStringInfo.
7768 +** Free given regExpStringInfo afterwards.
7769 +** Returns resulting string.
7771 +static void catSMTRegExpStrings(
7772 + RegExpStringInfo *regExpStringInfo,
7773 + char **regExpString)
7775 + int resultingLen;
7777 + /*
7778 + * allocate & init. a buffer for the resulting regular expression
7779 + */
7780 + resultingLen =
7781 + strlen( regExpStringInfo->resiNoneWBRegExpString ) +
7782 + strlen( regExpStringInfo->resiLeftWBRegExpString ) +
7783 + strlen( regExpStringInfo->resiRightWBRegExpString ) +
7784 + strlen( regExpStringInfo->resiBothWBRegExpString ) + 5;
7786 + *regExpString = XtMalloc( resultingLen );
7788 + strcpy( *regExpString, "" );
7790 + /*
7791 + * add the single parts to the resulting regular expression
7792 + * (= cat of parts separated by an "or")
7793 + */
7794 + addSMTRegExpString( *regExpString, regExpStringInfo->resiNoneWBRegExpString, "" );
7795 + addSMTRegExpString( *regExpString, regExpStringInfo->resiLeftWBRegExpString, ")" );
7796 + addSMTRegExpString( *regExpString, regExpStringInfo->resiRightWBRegExpString, ")>" );
7797 + addSMTRegExpString( *regExpString, regExpStringInfo->resiBothWBRegExpString, ")>" );
7799 + /*
7800 + * free buffers
7801 + */
7802 + freeRegExpStringInfo( regExpStringInfo );
7806 +** Free the allocated memory contained in a RegExpStringInfo data structure
7808 +static void freeRegExpStringInfo(
7809 + RegExpStringInfo *regExpStringInfo)
7811 + int i;
7813 + XtFree( regExpStringInfo->resiNoneWBRegExpString );
7814 + XtFree( regExpStringInfo->resiLeftWBRegExpString );
7815 + XtFree( regExpStringInfo->resiRightWBRegExpString );
7816 + XtFree( regExpStringInfo->resiBothWBRegExpString );
7818 + for (i=0; i < regExpStringInfo->resiNbrOfAddedMultiPat; i ++)
7819 + XtFree( (char *)regExpStringInfo->resiAddedMultiPat[i] );
7821 + XtFree( (char *)regExpStringInfo->resiAddedMultiPat);
7825 +** Compose regular expression for start / end pattern.
7827 +static void composeStartEndRegExpString(
7828 + ReadMatchPatternInfo *readMatchPatternInfo,
7829 + MatchPatternTableElement *element,
7830 + char **regExpString)
7832 + int i;
7833 + RegExpStringInfo regExpStringInfo;
7834 + PatternReference elementRef;
7835 + PatternElementSet startPat = element->mpteStart;
7836 + PatternElementSet endPat = element->mpteEnd;
7838 + /*
7839 + * Allocate buffers for keyword regular expression.
7840 + */
7841 + setupRegExpStringBuffers(
7842 + readMatchPatternInfo,
7843 + &regExpStringInfo);
7845 + /*
7846 + * Treat start / end element of MatchPatternTableElement
7847 + */
7849 + elementRef.prElementIdx = element->mpteIndex;
7851 + for (i=0; i < startPat.pesNumberOfPattern; i ++)
7853 + elementRef.prPatternIdx = startPat.pesPattern[i]->peIndex;
7855 + addUniquePatternToRegExpString(
7856 + startPat.pesPattern[i],
7857 + &elementRef,
7858 + readMatchPatternInfo,
7859 + &regExpStringInfo);
7862 + for (i=0; i < endPat.pesNumberOfPattern; i ++)
7864 + elementRef.prPatternIdx = endPat.pesPattern[i]->peIndex;
7866 + addUniquePatternToRegExpString(
7867 + endPat.pesPattern[i],
7868 + &elementRef,
7869 + readMatchPatternInfo,
7870 + &regExpStringInfo);
7873 + /*
7874 + * Assemble the resulting regular expression
7875 + */
7876 + catSMTRegExpStrings(
7877 + &regExpStringInfo,
7878 + regExpString);
7881 +static void copyStringMatchTableForDialog(
7882 + StringMatchTable *sourceTable,
7883 + DialogMatchPatternInfo *dialogTable )
7885 + int i;
7887 + /*
7888 + * if no source table exist (yet), then set nbr. of elements / groups to 0
7889 + */
7890 + if (sourceTable == NULL)
7892 + dialogTable->dmpiNbrOfSeqElements = 0;
7894 + return;
7897 + /*
7898 + * copy matching pattern sequence
7899 + */
7900 + dialogTable->dmpiNbrOfSeqElements = sourceTable->smtNumberOfSeqElements;
7902 + for (i=0; i < sourceTable->smtNumberOfSeqElements; i ++)
7904 + copySequenceElementForDialog(
7905 + sourceTable,
7906 + sourceTable->smtSequence[i],
7907 + &dialogTable->dmpiSequence[i] );
7911 +static void *copyMatchPatternElementForDialog(
7912 + MatchPatternTable *table,
7913 + int sourceElementIdx)
7915 + int i;
7916 + int patIdx = 0;
7917 + MatchPatternTableElement *sourceElement;
7918 + DialogMatchPatternTableElement *destination;
7920 + sourceElement = table->mptElements[sourceElementIdx];
7922 + destination =
7923 + (DialogMatchPatternTableElement *)XtMalloc( sizeof(DialogMatchPatternTableElement) );
7925 + destination->dmpteName = XtNewString(sourceElement->mpteName);
7926 + destination->dmpteType = sourceElement->mpteType;
7927 + destination->dmpteSkipBtwnStartEnd = sourceElement->mpteSkipBtwnStartEnd;
7928 + destination->dmpteIgnoreHighLightInfo = sourceElement->mpteIgnoreHighLightInfo;
7929 + destination->dmpteFlash = sourceElement->mpteFlash;
7931 + for (i=0; i<sourceElement->mpteAll.pesNumberOfPattern; i++)
7933 + copyPatternForDialog(
7934 + table,
7935 + sourceElement->mpteAll.pesPattern[i],
7936 + &destination->dmptePatterns.dspElements[patIdx ++]);
7939 + destination->dmptePatterns.dspNumberOfPatterns = patIdx;
7941 + return (void *)destination;
7944 +static void copyPatternForDialog(
7945 + MatchPatternTable *table,
7946 + PatternElement *sourcePattern,
7947 + DialogStringPatternElement **dialogPattern )
7949 + DialogStringPatternElement *newPat;
7950 + StringPattern *strSourcePat = GetStringPattern( table, sourcePattern );
7952 + newPat = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
7953 + *dialogPattern = newPat;
7955 + if( strSourcePat->spOrigText != NULL)
7956 + newPat->dspeText = XtNewString(strSourcePat->spOrigText);
7957 + else
7958 + newPat->dspeText = XtNewString(strSourcePat->spText);
7960 + newPat->dspeKind = sourcePattern->peKind;
7961 + newPat->dspeWordBoundary = strSourcePat->spWordBoundary;
7962 + newPat->dspeCaseInsensitive = strSourcePat->spCaseInsensitive;
7963 + newPat->dspeRegularExpression = strSourcePat->spRegularExpression;
7966 +static void *copyGroupElementForDialog(
7967 + MatchPatternGroupElement *sourceGroup)
7969 + int i;
7970 + DialogMatchPatternGroupElement *destination;
7972 + destination =
7973 + (DialogMatchPatternGroupElement *)XtMalloc( sizeof(DialogMatchPatternGroupElement) );
7975 + destination->dmpgeName = XtNewString(sourceGroup->mpgeName);
7976 + destination->dmpgeNumberOfSubPatterns = sourceGroup->mpgeNumberOfSubPatterns;
7978 + for ( i=0; i<destination->dmpgeNumberOfSubPatterns; i ++)
7980 + destination->dmpgeSubPatternIds[i] =
7981 + XtNewString(sourceGroup->mpgeSubPatternIds[i]);
7984 + return destination;
7987 +static void copySequenceElementForDialog(
7988 + StringMatchTable *sourceTable,
7989 + MatchPatternSequenceElement *sourceSeqElement,
7990 + DialogMatchPatternSequenceElement **dialogSeqElement )
7992 + DialogMatchPatternSequenceElement *destSeqElement;
7994 + destSeqElement =
7995 + (DialogMatchPatternSequenceElement *)XtMalloc( sizeof(DialogMatchPatternSequenceElement) );
7997 + *dialogSeqElement = destSeqElement;
7999 + destSeqElement->dmpseName = XtNewString(sourceSeqElement->mpseName);
8000 + destSeqElement->dmpseType = sourceSeqElement->mpseType;
8001 + destSeqElement->dmpseValid = True;
8003 + if (destSeqElement->dmpseType == MPT_GROUP)
8005 + destSeqElement->dmpsePtr =
8006 + copyGroupElementForDialog(
8007 + sourceTable->smtGroups[sourceSeqElement->mpseIndex]);
8009 + else
8011 + destSeqElement->dmpsePtr =
8012 + copyMatchPatternElementForDialog(
8013 + sourceTable->smtAllPatterns,
8014 + sourceSeqElement->mpseIndex);
8018 +static DialogMatchPatternSequenceElement *copyDialogSequenceElement(
8019 + DialogMatchPatternSequenceElement *sourceSeq)
8021 + DialogMatchPatternSequenceElement *destSeq;
8023 + destSeq =
8024 + (DialogMatchPatternSequenceElement *)XtMalloc(sizeof(DialogMatchPatternSequenceElement));
8026 + destSeq->dmpseName = XtNewString(sourceSeq->dmpseName);
8027 + destSeq->dmpseType = sourceSeq->dmpseType;
8028 + destSeq->dmpseValid = True;
8030 + destSeq->dmpsePtr = sourceSeq->dmpsePtr;
8032 + return destSeq;
8035 +static void freeDialogMatchPatternElement(
8036 + DialogMatchPatternTableElement *dialogElement )
8038 + int i;
8040 + for (i=0; i<dialogElement->dmptePatterns.dspNumberOfPatterns; i ++)
8042 + freeDialogStringPatternElement(
8043 + dialogElement->dmptePatterns.dspElements[i]);
8046 + freeXtPtr((void **)&dialogElement->dmpteName);
8048 + freeXtPtr((void **)&dialogElement);
8051 +static void freeDialogStringPatternElement(
8052 + DialogStringPatternElement *element)
8054 + freeXtPtr((void **)&element->dspeText);
8056 + freeXtPtr((void **)&element);
8059 +static void freeDialogGroupElement(
8060 + DialogMatchPatternGroupElement *dialogGroup )
8062 + int i;
8064 + for (i=0; i<dialogGroup->dmpgeNumberOfSubPatterns; i ++)
8066 + freeXtPtr((void **)&dialogGroup->dmpgeSubPatternIds[i]);
8069 + freeXtPtr((void **)&dialogGroup->dmpgeName);
8071 + freeXtPtr((void **)&dialogGroup);
8074 +static void freeDialogSequenceElement(
8075 + DialogMatchPatternSequenceElement *dialogSeq )
8077 + freeXtPtr((void **)&dialogSeq->dmpseName);
8079 + if (dialogSeq->dmpseType == MPT_GROUP)
8081 + freeDialogGroupElement(
8082 + (DialogMatchPatternGroupElement *)dialogSeq->dmpsePtr );
8084 + else
8086 + freeDialogMatchPatternElement(
8087 + (DialogMatchPatternTableElement *)dialogSeq->dmpsePtr );
8090 + freeXtPtr((void **)&dialogSeq);
8093 +static void copyDialogStringPatternsFromTable(
8094 + DialogMatchPatternTableElement *tableElement,
8095 + DialogStringPatterns *destPatterns)
8097 + int i;
8099 + destPatterns->dspNumberOfPatterns =
8100 + tableElement->dmptePatterns.dspNumberOfPatterns;
8102 + for (i=0; i<destPatterns->dspNumberOfPatterns; i++)
8104 + destPatterns->dspElements[i] =
8105 + copyDialogStringPatternElement(
8106 + tableElement->dmptePatterns.dspElements[i] );
8110 +static void copyDialogStringPatterns(
8111 + DialogStringPatterns *sourcePatterns,
8112 + DialogStringPatterns *destPatterns)
8114 + int i;
8116 + destPatterns->dspNumberOfPatterns =
8117 + sourcePatterns->dspNumberOfPatterns;
8119 + for (i=0; i<destPatterns->dspNumberOfPatterns; i++)
8121 + destPatterns->dspElements[i] =
8122 + copyDialogStringPatternElement(
8123 + sourcePatterns->dspElements[i] );
8127 +static void freeDialogStringPatterns(
8128 + DialogStringPatterns *patterns)
8130 + int i;
8132 + for (i=0; i<patterns->dspNumberOfPatterns; i++)
8134 + freeDialogStringPatternElement(patterns->dspElements[i]);
8137 + patterns->dspNumberOfPatterns = 0;
8140 +static DialogStringPatternElement *copyDialogStringPatternElement(
8141 + DialogStringPatternElement *sourceElement)
8143 + DialogStringPatternElement *newPatElement;
8145 + newPatElement = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
8147 + newPatElement->dspeText = XtNewString(sourceElement->dspeText);
8148 + newPatElement->dspeKind = sourceElement->dspeKind;
8149 + newPatElement->dspeWordBoundary = sourceElement->dspeWordBoundary;
8150 + newPatElement->dspeCaseInsensitive = sourceElement->dspeCaseInsensitive;
8151 + newPatElement->dspeRegularExpression = sourceElement->dspeRegularExpression;
8153 + return newPatElement;
8156 +static void copyDialogPatternNamesFromGroup(
8157 + DialogMatchPatternGroupElement *group,
8158 + DialogStringPatterns *destPatterns)
8160 + int i;
8162 + destPatterns->dspNumberOfPatterns =
8163 + group->dmpgeNumberOfSubPatterns;
8165 + for (i=0; i<destPatterns->dspNumberOfPatterns; i++)
8167 + destPatterns->dspElements[i] =
8168 + copyDialogPatternName(
8169 + group->dmpgeSubPatternIds[i] );
8173 +static DialogStringPatternElement *copyDialogPatternName(
8174 + char *sourcePatternId)
8176 + DialogStringPatternElement *newPatElement;
8178 + newPatElement = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
8180 + newPatElement->dspeText = XtNewString(sourcePatternId);
8181 + newPatElement->dspeKind = PEK_START;
8182 + newPatElement->dspeWordBoundary = PWB_NONE;
8183 + newPatElement->dspeCaseInsensitive = False;
8184 + newPatElement->dspeRegularExpression = False;
8186 + return newPatElement;
8189 +static void copyDialogPatternNamesToGroup(
8190 + DialogStringPatterns *sourceNames,
8191 + DialogMatchPatternGroupElement *destGroup)
8193 + int i;
8195 + destGroup->dmpgeNumberOfSubPatterns =
8196 + sourceNames->dspNumberOfPatterns;
8198 + for (i=0; i<destGroup->dmpgeNumberOfSubPatterns; i++)
8200 + destGroup->dmpgeSubPatternIds[i] =
8201 + XtNewString(
8202 + sourceNames->dspElements[i]->dspeText);
8208 +** Present a dialog for editing matching pattern information
8210 +void EditMatchPatterns(WindowInfo *window)
8212 + Widget form, lmOptMenu;
8213 + Widget lmForm;
8214 + Widget okBtn, applyBtn, checkBtn, deleteBtn, closeBtn, helpBtn;
8215 + Widget restoreBtn, lmBtn;
8216 + Widget matchPatternsForm, matchPatternsFrame, matchPatternsLbl;
8217 + Widget matchPatternTypeBox, matchPatternTypeLbl;
8218 + Widget globalAttributesBox;
8219 + Widget stringPatternsFrame, stringPatternsForm;
8220 + Widget stringPatternTypeBox;
8221 + Widget wordBoundaryBox;
8222 + Widget stringAttributesBox;
8223 + StringMatchTable *table;
8224 + XmString s1;
8225 + int n;
8226 + Arg args[20];
8228 + /*
8229 + * if the dialog is already displayed, just pop it to the top and return
8230 + */
8231 + if (MatchPatternDialog.mpdShell != NULL)
8233 + RaiseDialogWindow(MatchPatternDialog.mpdShell);
8234 + return;
8237 + /*
8238 + * decide on an initial language mode
8239 + */
8240 + MatchPatternDialog.mpdLangModeName =
8241 + XtNewString(
8242 + window->languageMode == PLAIN_LANGUAGE_MODE ?
8243 + PLAIN_LM_STRING : LanguageModeName(window->languageMode));
8245 + /*
8246 + * find the associated matching pattern table to edit
8247 + */
8248 + table = (StringMatchTable *)FindStringMatchTable(MatchPatternDialog.mpdLangModeName);
8250 + /*
8251 + * copy the list of patterns to one that the user can freely edit
8252 + */
8253 + copyStringMatchTableForDialog( table, &MatchPatternDialog.mpdTable );
8255 + /*
8256 + * init. status information of dialog
8257 + */
8258 + MatchPatternDialog.currentDmptSeqElement = NULL;
8259 + MatchPatternDialog.currentDmptElement = NULL;
8260 + MatchPatternDialog.currentDmptGroup = NULL;
8262 + MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns = 0;
8263 + MatchPatternDialog.mpdStringPatternIsDisplayed = True;
8265 + /*
8266 + * Create a form widget in an application shell
8267 + */
8268 + n = 0;
8269 + XtSetArg(args[n], XmNdeleteResponse, XmDO_NOTHING); n++;
8270 + XtSetArg(args[n], XmNiconName, "Matching Patterns"); n++;
8271 + XtSetArg(args[n], XmNtitle, "Matching (Parenthesis) Patterns"); n++;
8272 + MatchPatternDialog.mpdShell = CreateShellWithBestVis(APP_NAME, APP_CLASS,
8273 + applicationShellWidgetClass, TheDisplay, args, n);
8274 + AddSmallIcon(MatchPatternDialog.mpdShell);
8275 + form = XtVaCreateManagedWidget("editMatchPatterns", xmFormWidgetClass,
8276 + MatchPatternDialog.mpdShell, XmNautoUnmanage, False,
8277 + XmNresizePolicy, XmRESIZE_NONE, NULL);
8278 + XtAddCallback(form, XmNdestroyCallback, destroyCB, NULL);
8279 + AddMotifCloseCallback(MatchPatternDialog.mpdShell, closeCB, NULL);
8281 + lmForm = XtVaCreateManagedWidget("lmForm", xmFormWidgetClass,
8282 + form,
8283 + XmNleftAttachment, XmATTACH_POSITION,
8284 + XmNleftPosition, 1,
8285 + XmNtopAttachment, XmATTACH_POSITION,
8286 + XmNtopPosition, 1,
8287 + XmNrightAttachment, XmATTACH_POSITION,
8288 + XmNrightPosition, 99, NULL);
8290 + MatchPatternDialog.mpdLmPulldown =
8291 + CreateLanguageModeMenu(lmForm, matchPatternLangModeCB, NULL, True);
8293 + n = 0;
8294 + XtSetArg(args[n], XmNspacing, 0); n++;
8295 + XtSetArg(args[n], XmNmarginWidth, 0); n++;
8296 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
8297 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8298 + XtSetArg(args[n], XmNleftPosition, 50); n++;
8299 + XtSetArg(args[n], XmNsubMenuId, MatchPatternDialog.mpdLmPulldown); n++;
8300 + lmOptMenu = XmCreateOptionMenu(lmForm, "langModeOptMenu", args, n);
8301 + XtManageChild(lmOptMenu);
8302 + MatchPatternDialog.mpdLmOptMenu = lmOptMenu;
8304 + XtVaCreateManagedWidget("lmLbl", xmLabelGadgetClass, lmForm,
8305 + XmNlabelString, s1=XmStringCreateSimple("Language Mode:"),
8306 + XmNmnemonic, 'M',
8307 + XmNuserData, XtParent(MatchPatternDialog.mpdLmOptMenu),
8308 + XmNalignment, XmALIGNMENT_END,
8309 + XmNrightAttachment, XmATTACH_POSITION,
8310 + XmNrightPosition, 50,
8311 + XmNtopAttachment, XmATTACH_FORM,
8312 + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
8313 + XmNbottomWidget, lmOptMenu, NULL);
8314 + XmStringFree(s1);
8316 + lmBtn = XtVaCreateManagedWidget("lmBtn", xmPushButtonWidgetClass, lmForm,
8317 + XmNlabelString, s1=MKSTRING("Add / Modify\nLanguage Mode..."),
8318 + XmNmnemonic, 'A',
8319 + XmNrightAttachment, XmATTACH_FORM,
8320 + XmNtopAttachment, XmATTACH_FORM, NULL);
8321 + XtAddCallback(lmBtn, XmNactivateCallback, pmLanguageModeDialogCB, NULL);
8322 + XmStringFree(s1);
8324 + okBtn = XtVaCreateManagedWidget("ok", xmPushButtonWidgetClass, form,
8325 + XmNlabelString, s1=XmStringCreateSimple("OK"),
8326 + XmNleftAttachment, XmATTACH_POSITION,
8327 + XmNleftPosition, 1,
8328 + XmNrightAttachment, XmATTACH_POSITION,
8329 + XmNrightPosition, 13,
8330 + XmNbottomAttachment, XmATTACH_FORM,
8331 + XmNbottomOffset, BORDER, NULL);
8332 + XtAddCallback(okBtn, XmNactivateCallback, okCB, NULL);
8333 + XmStringFree(s1);
8335 + applyBtn = XtVaCreateManagedWidget("apply", xmPushButtonWidgetClass, form,
8336 + XmNlabelString, s1=XmStringCreateSimple("Apply"),
8337 + XmNmnemonic, 'y',
8338 + XmNleftAttachment, XmATTACH_POSITION,
8339 + XmNleftPosition, 13,
8340 + XmNrightAttachment, XmATTACH_POSITION,
8341 + XmNrightPosition, 26,
8342 + XmNbottomAttachment, XmATTACH_FORM,
8343 + XmNbottomOffset, BORDER, NULL);
8344 + XtAddCallback(applyBtn, XmNactivateCallback, applyCB, NULL);
8345 + XmStringFree(s1);
8347 + checkBtn = XtVaCreateManagedWidget("check", xmPushButtonWidgetClass, form,
8348 + XmNlabelString, s1=XmStringCreateSimple("Check"),
8349 + XmNmnemonic, 'k',
8350 + XmNleftAttachment, XmATTACH_POSITION,
8351 + XmNleftPosition, 26,
8352 + XmNrightAttachment, XmATTACH_POSITION,
8353 + XmNrightPosition, 39,
8354 + XmNbottomAttachment, XmATTACH_FORM,
8355 + XmNbottomOffset, BORDER, NULL);
8356 + XtAddCallback(checkBtn, XmNactivateCallback, checkCB, NULL);
8357 + XmStringFree(s1);
8359 + deleteBtn = XtVaCreateManagedWidget("delete", xmPushButtonWidgetClass, form,
8360 + XmNlabelString, s1=XmStringCreateSimple("Delete"),
8361 + XmNmnemonic, 'D',
8362 + XmNleftAttachment, XmATTACH_POSITION,
8363 + XmNleftPosition, 39,
8364 + XmNrightAttachment, XmATTACH_POSITION,
8365 + XmNrightPosition, 52,
8366 + XmNbottomAttachment, XmATTACH_FORM,
8367 + XmNbottomOffset, BORDER, NULL);
8368 + XtAddCallback(deleteBtn, XmNactivateCallback, deleteCB, NULL);
8369 + XmStringFree(s1);
8371 + restoreBtn = XtVaCreateManagedWidget("restore", xmPushButtonWidgetClass, form,
8372 + XmNlabelString, s1=XmStringCreateSimple("Restore Defaults"),
8373 + XmNmnemonic, 'f',
8374 + XmNleftAttachment, XmATTACH_POSITION,
8375 + XmNleftPosition, 52,
8376 + XmNrightAttachment, XmATTACH_POSITION,
8377 + XmNrightPosition, 73,
8378 + XmNbottomAttachment, XmATTACH_FORM,
8379 + XmNbottomOffset, BORDER, NULL);
8380 + XtAddCallback(restoreBtn, XmNactivateCallback, restoreCB, NULL);
8381 + XmStringFree(s1);
8383 + closeBtn = XtVaCreateManagedWidget("close", xmPushButtonWidgetClass,
8384 + form,
8385 + XmNlabelString, s1=XmStringCreateSimple("Close"),
8386 + XmNleftAttachment, XmATTACH_POSITION,
8387 + XmNleftPosition, 73,
8388 + XmNrightAttachment, XmATTACH_POSITION,
8389 + XmNrightPosition, 86,
8390 + XmNbottomAttachment, XmATTACH_FORM,
8391 + XmNbottomOffset, BORDER, NULL);
8392 + XtAddCallback(closeBtn, XmNactivateCallback, closeCB, NULL);
8393 + XmStringFree(s1);
8395 + helpBtn = XtVaCreateManagedWidget("help", xmPushButtonWidgetClass,
8396 + form,
8397 + XmNlabelString, s1=XmStringCreateSimple("Help"),
8398 + XmNmnemonic, 'H',
8399 + XmNleftAttachment, XmATTACH_POSITION,
8400 + XmNleftPosition, 86,
8401 + XmNrightAttachment, XmATTACH_POSITION,
8402 + XmNrightPosition, 99,
8403 + XmNbottomAttachment, XmATTACH_FORM,
8404 + XmNbottomOffset, BORDER, NULL);
8405 + XtAddCallback(helpBtn, XmNactivateCallback, helpCB, NULL);
8406 + XmStringFree(s1);
8408 + stringPatternsFrame = XtVaCreateManagedWidget("stringPatternsFrame", xmFrameWidgetClass,
8409 + form,
8410 + XmNleftAttachment, XmATTACH_POSITION,
8411 + XmNleftPosition, 1,
8412 + XmNrightAttachment, XmATTACH_POSITION,
8413 + XmNrightPosition, 99,
8414 + XmNbottomAttachment, XmATTACH_WIDGET,
8415 + XmNbottomWidget, okBtn,
8416 + XmNbottomOffset, BORDER, NULL);
8417 + stringPatternsForm = XtVaCreateManagedWidget("stringPatternsForm", xmFormWidgetClass,
8418 + stringPatternsFrame, NULL);
8419 + MatchPatternDialog.mpdStringPatternsLbl = XtVaCreateManagedWidget("mpdStringPatternsLbl", xmLabelGadgetClass,
8420 + stringPatternsFrame,
8421 + XmNlabelString, s1=XmStringCreateSimple(STRING_PATTERNS_LBL_TXT),
8422 + XmNmarginHeight, 0,
8423 + XmNchildType, XmFRAME_TITLE_CHILD, NULL);
8424 + XmStringFree(s1);
8426 + n = 0;
8427 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
8428 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8429 + XtSetArg(args[n], XmNleftPosition, 1); n++;
8430 + XtSetArg(args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
8431 + XtSetArg(args[n], XmNrightPosition, LIST_RIGHT-1); n++;
8432 + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
8433 + XtSetArg(args[n], XmNbottomOffset, BORDER); n++;
8434 + MatchPatternDialog.mpdStringPatternsListW =
8435 + CreateManagedList(stringPatternsForm, "stringPatternsList", args,
8436 + n, (void **)MatchPatternDialog.currentStringPatterns.dspElements,
8437 + &MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns,
8438 + MAX_STRING_PATTERNS, 18,
8439 + getStringPatternDisplayedCB, NULL,
8440 + setStringPatternDisplayedCB, NULL,
8441 + freeStringPatternItemCB);
8442 + XtVaSetValues(MatchPatternDialog.mpdStringPatternsLbl, XmNuserData, MatchPatternDialog.mpdStringPatternsListW, NULL);
8444 + MatchPatternDialog.mpdStringPatternTypeLbl = XtVaCreateManagedWidget("mpdStringPatternTypeLbl", xmLabelGadgetClass,
8445 + stringPatternsForm,
8446 + XmNlabelString, s1=XmStringCreateSimple("String Pattern Type:"),
8447 + XmNmarginHeight, 0,
8448 + XmNalignment, XmALIGNMENT_BEGINNING,
8449 + XmNleftAttachment, XmATTACH_POSITION,
8450 + XmNleftPosition, LIST_RIGHT,
8451 + XmNtopAttachment, XmATTACH_FORM, NULL);
8452 + XmStringFree(s1);
8454 + stringPatternTypeBox = XtVaCreateManagedWidget("stringPatternTypeBox", xmRowColumnWidgetClass,
8455 + stringPatternsForm,
8456 + XmNorientation, XmHORIZONTAL,
8457 + XmNpacking, XmPACK_TIGHT,
8458 + XmNradioBehavior, True,
8459 + XmNleftAttachment, XmATTACH_POSITION,
8460 + XmNleftPosition, LIST_RIGHT,
8461 + XmNtopAttachment, XmATTACH_WIDGET,
8462 + XmNtopWidget, MatchPatternDialog.mpdStringPatternTypeLbl, NULL);
8463 + MatchPatternDialog.sptStartW = XtVaCreateManagedWidget("sptStartW",
8464 + xmToggleButtonWidgetClass, stringPatternTypeBox,
8465 + XmNset, True,
8466 + XmNmarginHeight, 0,
8467 + XmNlabelString, s1=XmStringCreateSimple(
8468 + "Start"),
8469 + NULL);
8470 + XmStringFree(s1);
8471 + MatchPatternDialog.sptMiddleW = XtVaCreateManagedWidget("sptMiddleW",
8472 + xmToggleButtonWidgetClass, stringPatternTypeBox,
8473 + XmNmarginHeight, 0,
8474 + XmNlabelString, s1=XmStringCreateSimple(
8475 + "Middle"),
8476 + NULL);
8477 + XmStringFree(s1);
8478 + MatchPatternDialog.sptEndW = XtVaCreateManagedWidget("sptEndW",
8479 + xmToggleButtonWidgetClass, stringPatternTypeBox,
8480 + XmNmarginHeight, 0,
8481 + XmNlabelString, s1=XmStringCreateSimple(
8482 + "End"),
8483 + NULL);
8484 + XmStringFree(s1);
8486 + MatchPatternDialog.mpdWordBoundaryLbl = XtVaCreateManagedWidget("mpdWordBoundaryLbl", xmLabelGadgetClass,
8487 + stringPatternsForm,
8488 + XmNlabelString, s1=XmStringCreateSimple("Word boundary:"),
8489 + XmNmarginHeight, 0,
8490 + XmNalignment, XmALIGNMENT_BEGINNING,
8491 + XmNleftAttachment, XmATTACH_POSITION,
8492 + XmNleftPosition, LIST_RIGHT,
8493 + XmNtopAttachment, XmATTACH_WIDGET,
8494 + XmNtopWidget, stringPatternTypeBox,
8495 + NULL);
8496 + XmStringFree(s1);
8498 + wordBoundaryBox = XtVaCreateManagedWidget("wordBoundaryBox", xmRowColumnWidgetClass,
8499 + stringPatternsForm,
8500 + XmNorientation, XmHORIZONTAL,
8501 + XmNpacking, XmPACK_TIGHT,
8502 + XmNradioBehavior, True,
8503 + XmNleftAttachment, XmATTACH_POSITION,
8504 + XmNleftPosition, LIST_RIGHT,
8505 + XmNtopAttachment, XmATTACH_WIDGET,
8506 + XmNtopWidget, MatchPatternDialog.mpdWordBoundaryLbl, NULL);
8507 + MatchPatternDialog.wbbBothW = XtVaCreateManagedWidget("wbbBothW",
8508 + xmToggleButtonWidgetClass, wordBoundaryBox,
8509 + XmNset, True,
8510 + XmNmarginHeight, 0,
8511 + XmNlabelString, s1=XmStringCreateSimple(
8512 + "Both (pattern is word)"),
8513 + NULL);
8514 + XmStringFree(s1);
8515 + MatchPatternDialog.wbbLeftW = XtVaCreateManagedWidget("wbbLeftW",
8516 + xmToggleButtonWidgetClass, wordBoundaryBox,
8517 + XmNmarginHeight, 0,
8518 + XmNlabelString, s1=XmStringCreateSimple(
8519 + "Left"),
8520 + NULL);
8521 + XmStringFree(s1);
8522 + MatchPatternDialog.wbbRightW = XtVaCreateManagedWidget("wbbRightW",
8523 + xmToggleButtonWidgetClass, wordBoundaryBox,
8524 + XmNmarginHeight, 0,
8525 + XmNlabelString, s1=XmStringCreateSimple(
8526 + "Right"),
8527 + NULL);
8528 + XmStringFree(s1);
8529 + MatchPatternDialog.wbbNoneW = XtVaCreateManagedWidget("wbbNoneW",
8530 + xmToggleButtonWidgetClass, wordBoundaryBox,
8531 + XmNmarginHeight, 0,
8532 + XmNlabelString, s1=XmStringCreateSimple(
8533 + "None"),
8534 + NULL);
8535 + XmStringFree(s1);
8537 + MatchPatternDialog.mpdStringAttributesLbl = XtVaCreateManagedWidget("mpdStringAttributesLbl", xmLabelGadgetClass,
8538 + stringPatternsForm,
8539 + XmNlabelString, s1=XmStringCreateSimple("String Attributes:"),
8540 + XmNmarginHeight, 0,
8541 + XmNalignment, XmALIGNMENT_BEGINNING,
8542 + XmNleftAttachment, XmATTACH_POSITION,
8543 + XmNleftPosition, LIST_RIGHT,
8544 + XmNtopAttachment, XmATTACH_WIDGET,
8545 + XmNtopWidget, wordBoundaryBox, NULL);
8546 + XmStringFree(s1);
8548 + stringAttributesBox = XtVaCreateManagedWidget("stringAttributesBox", xmRowColumnWidgetClass,
8549 + stringPatternsForm,
8550 + XmNorientation, XmHORIZONTAL,
8551 + XmNpacking, XmPACK_TIGHT,
8552 + XmNleftAttachment, XmATTACH_POSITION,
8553 + XmNleftPosition, LIST_RIGHT,
8554 + XmNtopAttachment, XmATTACH_WIDGET,
8555 + XmNtopWidget, MatchPatternDialog.mpdStringAttributesLbl, NULL);
8556 + MatchPatternDialog.sabRegularExpressionW = XtVaCreateManagedWidget("sabRegularExpressionW",
8557 + xmToggleButtonWidgetClass, stringAttributesBox,
8558 + XmNset, False,
8559 + XmNmarginHeight, 0,
8560 + XmNlabelString, s1=XmStringCreateSimple(
8561 + "Regular Expression"),
8562 + NULL);
8563 + XmStringFree(s1);
8564 + XtAddCallback(MatchPatternDialog.sabRegularExpressionW, XmNvalueChangedCallback,
8565 + strPatRegExpressionCB, NULL);
8566 + MatchPatternDialog.sabCaseSensitiveW = XtVaCreateManagedWidget("sabCaseSensitiveW",
8567 + xmToggleButtonWidgetClass, stringAttributesBox,
8568 + XmNset, True,
8569 + XmNmarginHeight, 0,
8570 + XmNlabelString, s1=XmStringCreateSimple(
8571 + "Case Sensitive"),
8572 + NULL);
8573 + XmStringFree(s1);
8575 + MatchPatternDialog.mpdStringPatternLbl = XtVaCreateManagedWidget("mpdStringPatternLbl", xmLabelGadgetClass,
8576 + stringPatternsForm,
8577 + XmNlabelString, s1=XmStringCreateSimple("String Pattern"),
8578 + XmNmnemonic, 'S',
8579 + XmNalignment, XmALIGNMENT_BEGINNING,
8580 + XmNleftAttachment, XmATTACH_POSITION,
8581 + XmNleftPosition, LIST_RIGHT,
8582 + XmNtopAttachment, XmATTACH_WIDGET,
8583 + XmNtopWidget, stringAttributesBox,
8584 + XmNtopOffset, BORDER,
8585 + NULL);
8586 + XmStringFree(s1);
8588 + MatchPatternDialog.mpdStringPatternW = XtVaCreateManagedWidget("mpdStringPatternW", xmTextWidgetClass,
8589 + stringPatternsForm,
8590 + XmNleftAttachment, XmATTACH_POSITION,
8591 + XmNleftPosition, LIST_RIGHT,
8592 + XmNtopAttachment, XmATTACH_WIDGET,
8593 + XmNtopWidget, MatchPatternDialog.mpdStringPatternLbl,
8594 + XmNrightAttachment, XmATTACH_FORM,
8595 + XmNrightOffset, BORDER,
8596 + NULL);
8597 + RemapDeleteKey(MatchPatternDialog.mpdStringPatternW);
8598 + XtVaSetValues(MatchPatternDialog.mpdStringPatternLbl, XmNuserData, MatchPatternDialog.mpdStringPatternW, NULL);
8600 + MatchPatternDialog.mpdSubPatNamesLbl = XtVaCreateManagedWidget("mpdSubPatNamesLbl", xmLabelGadgetClass,
8601 + stringPatternsForm,
8602 + XmNlabelString, s1=XmStringCreateSimple("Sub-Pattern Name"),
8603 + XmNmnemonic, 't',
8604 + XmNalignment, XmALIGNMENT_BEGINNING,
8605 + XmNleftAttachment, XmATTACH_POSITION,
8606 + XmNleftPosition, LIST_RIGHT,
8607 + XmNtopAttachment, XmATTACH_WIDGET,
8608 + XmNtopWidget, MatchPatternDialog.mpdStringPatternW,
8609 + XmNtopOffset, BORDER,
8610 + NULL);
8611 + XmStringFree(s1);
8613 + MatchPatternDialog.mpdSubPatNamesPulldown =
8614 + createSubPatternNameMenu(stringPatternsForm, NULL, False);
8616 + n = 0;
8617 + XtSetArg(args[n], XmNspacing, 0); n++;
8618 + XtSetArg(args[n], XmNmarginWidth, 0); n++;
8619 + XtSetArg(args[n], XmNresizeWidth, True); n++;
8620 + XtSetArg(args[n], XmNresizeHeight, True); n++;
8621 + XtSetArg(args[n], XmNnavigationType, XmTAB_GROUP); n++;
8622 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
8623 + XtSetArg(args[n], XmNtopWidget, MatchPatternDialog.mpdSubPatNamesLbl); n++;
8624 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8625 + XtSetArg(args[n], XmNleftPosition, LIST_RIGHT); n++;
8626 + XtSetArg(args[n], XmNsubMenuId, MatchPatternDialog.mpdSubPatNamesPulldown); n++;
8627 + MatchPatternDialog.mpdSubPatNamesOptMenu =
8628 + XmCreateOptionMenu(stringPatternsForm, "subPatNamesOptMenu", args, n);
8629 + XtManageChild(MatchPatternDialog.mpdSubPatNamesOptMenu);
8631 + XtVaSetValues(
8632 + MatchPatternDialog.mpdSubPatNamesLbl,
8633 + XmNuserData, XtParent(MatchPatternDialog.mpdSubPatNamesOptMenu),
8634 + NULL);
8636 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesLbl, False);
8637 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesOptMenu, False);
8639 + matchPatternsFrame = XtVaCreateManagedWidget("matchPatternsFrame", xmFrameWidgetClass,
8640 + form,
8641 + XmNleftAttachment, XmATTACH_POSITION,
8642 + XmNleftPosition, 1,
8643 + XmNtopAttachment, XmATTACH_WIDGET,
8644 + XmNtopWidget, lmForm,
8645 + XmNrightAttachment, XmATTACH_POSITION,
8646 + XmNrightPosition, 99,
8647 + XmNbottomAttachment, XmATTACH_WIDGET,
8648 + XmNbottomWidget, stringPatternsFrame,
8649 + XmNbottomOffset, BORDER, NULL);
8650 + matchPatternsForm = XtVaCreateManagedWidget("matchPatternsForm", xmFormWidgetClass,
8651 + matchPatternsFrame, NULL);
8652 + matchPatternsLbl = XtVaCreateManagedWidget("matchPatternsLbl", xmLabelGadgetClass,
8653 + matchPatternsFrame,
8654 + XmNlabelString, s1=XmStringCreateSimple("Matching Patterns"),
8655 + XmNmnemonic, 'P',
8656 + XmNmarginHeight, 0,
8657 + XmNchildType, XmFRAME_TITLE_CHILD, NULL);
8658 + XmStringFree(s1);
8660 + matchPatternTypeLbl = XtVaCreateManagedWidget("matchPatternTypeLbl", xmLabelGadgetClass,
8661 + matchPatternsForm,
8662 + XmNlabelString, s1=XmStringCreateSimple("Matching Pattern Type:"),
8663 + XmNmarginHeight, 0,
8664 + XmNalignment, XmALIGNMENT_BEGINNING,
8665 + XmNleftAttachment, XmATTACH_POSITION,
8666 + XmNleftPosition, LIST_RIGHT,
8667 + XmNtopAttachment, XmATTACH_FORM, NULL);
8668 + XmStringFree(s1);
8670 + matchPatternTypeBox = XtVaCreateManagedWidget("matchPatternTypeBox", xmRowColumnWidgetClass,
8671 + matchPatternsForm,
8672 + XmNpacking, XmPACK_COLUMN,
8673 + XmNradioBehavior, True,
8674 + XmNleftAttachment, XmATTACH_POSITION,
8675 + XmNleftPosition, LIST_RIGHT,
8676 + XmNtopAttachment, XmATTACH_WIDGET,
8677 + XmNtopWidget, matchPatternTypeLbl, NULL);
8678 + MatchPatternDialog.mptbIndividualW = XtVaCreateManagedWidget("mptbIndividualW",
8679 + xmToggleButtonWidgetClass, matchPatternTypeBox,
8680 + XmNset, True,
8681 + XmNmarginHeight, 0,
8682 + XmNlabelString, s1=XmStringCreateSimple(
8683 + "Individual"),
8684 + XmNmnemonic, 'I', NULL);
8685 + XmStringFree(s1);
8686 + XtAddCallback(MatchPatternDialog.mptbIndividualW, XmNvalueChangedCallback,
8687 + matchPatTypeCB, NULL);
8688 + MatchPatternDialog.mptbSubPatternW = XtVaCreateManagedWidget("mptbSubPatternW",
8689 + xmToggleButtonWidgetClass, matchPatternTypeBox,
8690 + XmNmarginHeight, 0,
8691 + XmNlabelString, s1=XmStringCreateSimple(
8692 + "Sub-pattern (belongs to context group)"),
8693 + XmNmnemonic, 'u', NULL);
8694 + XmStringFree(s1);
8695 + XtAddCallback(MatchPatternDialog.mptbSubPatternW, XmNvalueChangedCallback,
8696 + matchPatTypeCB, NULL);
8697 + MatchPatternDialog.mptbContextGroupW = XtVaCreateManagedWidget("mptbContextGroupW",
8698 + xmToggleButtonWidgetClass, matchPatternTypeBox,
8699 + XmNmarginHeight, 0,
8700 + XmNlabelString, s1=XmStringCreateSimple(
8701 + "Context group"),
8702 + XmNmnemonic, 'g', NULL);
8703 + XmStringFree(s1);
8704 + XtAddCallback(MatchPatternDialog.mptbContextGroupW, XmNvalueChangedCallback,
8705 + matchPatTypeCB, NULL);
8707 + MatchPatternDialog.mpdGlobalAttributesLbl = XtVaCreateManagedWidget("mpdGlobalAttributesLbl",
8708 + xmLabelGadgetClass, matchPatternsForm,
8709 + XmNlabelString, s1=XmStringCreateSimple("Global Attributes:"),
8710 + XmNmarginHeight, 0,
8711 + XmNalignment, XmALIGNMENT_BEGINNING,
8712 + XmNleftAttachment, XmATTACH_POSITION,
8713 + XmNleftPosition, LIST_RIGHT,
8714 + XmNtopAttachment, XmATTACH_WIDGET,
8715 + XmNtopOffset, BORDER,
8716 + XmNtopWidget, matchPatternTypeBox, NULL);
8717 + XmStringFree(s1);
8719 + globalAttributesBox = XtVaCreateManagedWidget("globalAttributesBox", xmRowColumnWidgetClass,
8720 + matchPatternsForm,
8721 + XmNpacking, XmPACK_COLUMN,
8722 + XmNleftAttachment, XmATTACH_POSITION,
8723 + XmNleftPosition, LIST_RIGHT,
8724 + XmNtopAttachment, XmATTACH_WIDGET,
8725 + XmNtopWidget, MatchPatternDialog.mpdGlobalAttributesLbl, NULL);
8726 + MatchPatternDialog.gabSkipBtwStartEndW = XtVaCreateManagedWidget("gabSkipBtwStartEndW",
8727 + xmToggleButtonWidgetClass, globalAttributesBox,
8728 + XmNmarginHeight, 0,
8729 + XmNlabelString, s1=XmStringCreateSimple(
8730 + "Skip content between start / end pattern"),
8731 + XmNmnemonic, 'c', NULL);
8732 + XmStringFree(s1);
8733 + MatchPatternDialog.gabFlashW = XtVaCreateManagedWidget("gabFlashW",
8734 + xmToggleButtonWidgetClass, globalAttributesBox,
8735 + XmNset, True,
8736 + XmNmarginHeight, 0,
8737 + XmNlabelString, s1=XmStringCreateSimple(
8738 + "Flash matching pattern"),
8739 + XmNmnemonic, 'l', NULL);
8740 + XmStringFree(s1);
8741 + MatchPatternDialog.gabSyntaxBasedW = XtVaCreateManagedWidget("gabSyntaxBasedW",
8742 + xmToggleButtonWidgetClass, globalAttributesBox,
8743 + XmNset, True,
8744 + XmNmarginHeight, 0,
8745 + XmNlabelString, s1=XmStringCreateSimple(
8746 + "Syntax based"),
8747 + XmNmnemonic, 'b', NULL);
8748 + XmStringFree(s1);
8750 + MatchPatternDialog.mpdMatchPatternNameLbl = XtVaCreateManagedWidget("mpdMatchPatternNameLbl", xmLabelGadgetClass,
8751 + matchPatternsForm,
8752 + XmNlabelString, s1=XmStringCreateSimple(MATCH_PAT_NAME_LBL_TXT),
8753 + XmNmnemonic, 'N',
8754 + XmNalignment, XmALIGNMENT_BEGINNING,
8755 + XmNleftAttachment, XmATTACH_POSITION,
8756 + XmNleftPosition, LIST_RIGHT,
8757 + XmNtopAttachment, XmATTACH_WIDGET,
8758 + XmNtopWidget, globalAttributesBox,
8759 + XmNtopOffset, BORDER, NULL);
8760 + XmStringFree(s1);
8762 + MatchPatternDialog.mpdMatchPatternNameW = XtVaCreateManagedWidget("mpdMatchPatternNameW", xmTextWidgetClass,
8763 + matchPatternsForm,
8764 + XmNleftAttachment, XmATTACH_POSITION,
8765 + XmNleftPosition, LIST_RIGHT,
8766 + XmNtopAttachment, XmATTACH_WIDGET,
8767 + XmNtopWidget, MatchPatternDialog.mpdMatchPatternNameLbl,
8768 + XmNrightAttachment, XmATTACH_FORM,
8769 + XmNrightOffset, BORDER,
8770 + XmNbottomAttachment, XmATTACH_FORM,
8771 + XmNbottomOffset, BORDER,
8772 + NULL);
8773 + RemapDeleteKey(MatchPatternDialog.mpdMatchPatternNameW);
8774 + XtVaSetValues(MatchPatternDialog.mpdMatchPatternNameLbl, XmNuserData, MatchPatternDialog.mpdMatchPatternNameW, NULL);
8776 + n = 0;
8777 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
8778 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8779 + XtSetArg(args[n], XmNleftPosition, 1); n++;
8780 + XtSetArg(args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
8781 + XtSetArg(args[n], XmNrightPosition, LIST_RIGHT-1); n++;
8782 + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
8784 + XtSetArg(args[n], XmNbottomOffset, BORDER); n++;
8785 + MatchPatternDialog.mpdMatchPatternNamesListW =
8786 + CreateManagedList(
8787 + matchPatternsForm, "mpdMatchPatternNamesListW",
8788 + args, n,
8789 + (void **)MatchPatternDialog.mpdTable.dmpiSequence, &MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements,
8790 + MAX_NBR_MATCH_PATTERNS, 18,
8791 + getMatchPatternDisplayedCB, NULL,
8792 + setMatchPatternDisplayedCB, NULL,
8793 + freeMatchPatternItemCB);
8794 + AddDeleteConfirmCB(MatchPatternDialog.mpdMatchPatternNamesListW, deleteMatchPatternItemCB, NULL);
8796 + XtVaSetValues(matchPatternsLbl, XmNuserData, MatchPatternDialog.mpdMatchPatternNamesListW, NULL);
8798 + /*
8799 + * set initial default button
8800 + */
8801 + XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
8802 + XtVaSetValues(form, XmNcancelButton, closeBtn, NULL);
8804 + /*
8805 + * handle mnemonic selection of buttons and focus to dialog
8806 + */
8807 + AddDialogMnemonicHandler(form, False);
8809 + /*
8810 + * fill in the dialog information for the selected language mode
8811 + */
8812 + SetLangModeMenu(MatchPatternDialog.mpdLmOptMenu, MatchPatternDialog.mpdLangModeName);
8814 + /*
8815 + * realize all of the widgets in the new dialog
8816 + */
8817 + RealizeWithoutForcingPosition(MatchPatternDialog.mpdShell);
8821 +** Modify match pattern dialog depending on showing a string pattern
8822 +** or a context group.
8824 +static void setDialogType(int dialogShowsStringPattern)
8826 + char *matchPatternNameText;
8827 + char *strPatCxtGrpListText;
8828 + XmString s1;
8829 + int regularExpression =
8830 + XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
8832 + /*
8833 + * check, if dialog mode needs to be switched
8834 + */
8835 + if (MatchPatternDialog.mpdStringPatternIsDisplayed == dialogShowsStringPattern)
8837 + return;
8840 + if (dialogShowsStringPattern)
8842 + matchPatternNameText = MATCH_PAT_NAME_LBL_TXT;
8843 + strPatCxtGrpListText = STRING_PATTERNS_LBL_TXT;
8845 + else
8847 + matchPatternNameText = "Context Group Name";
8848 + strPatCxtGrpListText = "Related Sub-Patterns";
8851 + XtSetSensitive(MatchPatternDialog.mpdGlobalAttributesLbl, dialogShowsStringPattern);
8852 + XtSetSensitive(MatchPatternDialog.gabSkipBtwStartEndW, dialogShowsStringPattern);
8853 + XtSetSensitive(MatchPatternDialog.gabFlashW, dialogShowsStringPattern);
8854 + XtSetSensitive(MatchPatternDialog.gabSyntaxBasedW, dialogShowsStringPattern);
8856 + XtSetSensitive(MatchPatternDialog.mpdStringPatternTypeLbl, dialogShowsStringPattern);
8857 + XtSetSensitive(MatchPatternDialog.sptStartW, dialogShowsStringPattern);
8858 + XtSetSensitive(MatchPatternDialog.sptMiddleW, dialogShowsStringPattern);
8859 + XtSetSensitive(MatchPatternDialog.sptEndW, dialogShowsStringPattern);
8861 + setSensitiveWordBoundaryBox( dialogShowsStringPattern && !regularExpression );
8863 + XtSetSensitive(MatchPatternDialog.mpdStringAttributesLbl, dialogShowsStringPattern);
8864 + XtSetSensitive(MatchPatternDialog.sabCaseSensitiveW, dialogShowsStringPattern);
8865 + XtSetSensitive(MatchPatternDialog.sabRegularExpressionW, dialogShowsStringPattern);
8867 + XtSetSensitive(MatchPatternDialog.mpdStringPatternLbl, dialogShowsStringPattern);
8868 + XtSetSensitive(MatchPatternDialog.mpdStringPatternW, dialogShowsStringPattern);
8870 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesLbl, !dialogShowsStringPattern);
8871 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesOptMenu, !dialogShowsStringPattern);
8873 + XtVaSetValues(
8874 + MatchPatternDialog.mpdMatchPatternNameLbl,
8875 + XmNlabelString, s1=XmStringCreateSimple(matchPatternNameText),
8876 + NULL);
8877 + XmStringFree(s1);
8879 + XtVaSetValues(
8880 + MatchPatternDialog.mpdStringPatternsLbl,
8881 + XmNlabelString, s1=XmStringCreateSimple(strPatCxtGrpListText),
8882 + NULL);
8883 + XmStringFree(s1);
8885 + MatchPatternDialog.mpdStringPatternIsDisplayed = dialogShowsStringPattern;
8888 +static void setSensitiveWordBoundaryBox(int enable)
8890 + XtSetSensitive(MatchPatternDialog.mpdWordBoundaryLbl, enable);
8891 + XtSetSensitive(MatchPatternDialog.wbbBothW , enable);
8892 + XtSetSensitive(MatchPatternDialog.wbbLeftW , enable);
8893 + XtSetSensitive(MatchPatternDialog.wbbRightW, enable);
8894 + XtSetSensitive(MatchPatternDialog.wbbNoneW , enable);
8897 +static void matchPatternLangModeCB(Widget w, XtPointer clientData, XtPointer callData)
8899 + char *modeName;
8900 + StringMatchTable *oldTable, *newTable;
8901 + StringMatchTable emptyTable = {"", NULL, NULL, NULL, NULL, 0, NULL, 0, NULL};
8902 + StringMatchTable *table;
8903 + DMPTranslationResult translResult;
8904 + int resp;
8906 + /*
8907 + * Get the newly selected mode name. If it's the same, do nothing
8908 + */
8909 + XtVaGetValues(w, XmNuserData, &modeName, NULL);
8910 + if (!strcmp(modeName, MatchPatternDialog.mpdLangModeName))
8911 + return;
8913 + /*
8914 + * Look up the original version of the patterns being edited
8915 + */
8916 + oldTable = (StringMatchTable *)FindStringMatchTable(MatchPatternDialog.mpdLangModeName);
8917 + if (oldTable == NULL)
8918 + oldTable = &emptyTable;
8920 + /*
8921 + * Get the current information displayed by the dialog. If it's bad,
8922 + * give the user the chance to throw it out or go back and fix it. If
8923 + * it has changed, give the user the chance to apply discard or cancel.
8924 + */
8925 + newTable = getDialogStringMatchTable(&translResult);
8927 + if (translResult == DMPTR_EMPTY)
8929 + newTable = &emptyTable;
8932 + if (newTable == NULL)
8934 + if (DialogF(
8935 + DF_WARN, MatchPatternDialog.mpdShell, 2,
8936 + "Incomplete Matching Patterns for Language Mode",
8937 + "Discard incomplete entry for language mode '%s'?",
8938 + "Keep", "Discard",
8939 + MatchPatternDialog.mpdLangModeName) == 1)
8941 + SetLangModeMenu(
8942 + MatchPatternDialog.mpdLmOptMenu,
8943 + MatchPatternDialog.mpdLangModeName);
8945 + return;
8948 + else if (stringMatchTableDiffer(oldTable, newTable))
8950 + if (newTable == &emptyTable)
8951 + newTable = NULL;
8953 + resp =
8954 + DialogF(
8955 + DF_WARN, MatchPatternDialog.mpdShell, 3,
8956 + "Change Language Mode",
8957 + "Apply changes for language mode '%s'?",
8958 + "Apply Changes", "Discard Changes", "Cancel",
8959 + MatchPatternDialog.mpdLangModeName);
8961 + if (resp == 3)
8963 + SetLangModeMenu(
8964 + MatchPatternDialog.mpdLmOptMenu,
8965 + MatchPatternDialog.mpdLangModeName);
8967 + freeStringMatchTable( newTable );
8969 + return;
8971 + else if (resp == 1)
8973 + updateStringMatchTable( newTable );
8975 + /*
8976 + * Don't free the new table due to it's stored in MatchTables now
8977 + */
8978 + newTable = NULL;
8982 + if (newTable != NULL && newTable != &emptyTable)
8983 + freeStringMatchTable(newTable);
8985 + /*
8986 + * Free the old dialog information
8987 + */
8988 + freeVariableDialogData(DISCARD_LANGUAGE_MODE);
8990 + /*
8991 + * Fill the dialog with the new language mode information
8992 + */
8993 + MatchPatternDialog.mpdLangModeName = XtNewString(modeName);
8995 + /*
8996 + * Find the associated matching pattern table to edit
8997 + */
8998 + table = (StringMatchTable *)FindStringMatchTable(MatchPatternDialog.mpdLangModeName);
9000 + /*
9001 + * Copy the list of patterns to one that the user can freely edit
9002 + */
9003 + copyStringMatchTableForDialog( table, &MatchPatternDialog.mpdTable );
9005 + /*
9006 + * Update dialog fields
9007 + */
9008 + ChangeManagedListData(MatchPatternDialog.mpdMatchPatternNamesListW);
9009 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9012 +static void pmLanguageModeDialogCB(Widget w, XtPointer clientData, XtPointer callData)
9014 + EditLanguageModes();
9018 +** If a matching pattern dialog is up, ask to have the option menu for
9019 +** chosing language mode updated (via a call to CreateLanguageModeMenu)
9021 +void UpdateLanguageModeMenuMatchPattern(void)
9023 + Widget oldMenu;
9025 + if (MatchPatternDialog.mpdShell == NULL)
9026 + return;
9028 + oldMenu = MatchPatternDialog.mpdLmPulldown;
9029 + /*
9030 + * don't include "PLAIN" (4th parameter) in LM menu
9031 + */
9032 + MatchPatternDialog.mpdLmPulldown = CreateLanguageModeMenu(
9033 + XtParent(XtParent(oldMenu)), matchPatternLangModeCB, NULL, False);
9034 + XtVaSetValues(XmOptionButtonGadget(MatchPatternDialog.mpdLmOptMenu),
9035 + XmNsubMenuId, MatchPatternDialog.mpdLmPulldown, NULL);
9036 + SetLangModeMenu(MatchPatternDialog.mpdLmOptMenu, MatchPatternDialog.mpdLangModeName);
9038 + XtDestroyWidget(oldMenu);
9041 +static void *getMatchPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
9042 + void *cbArg)
9044 + DialogMatchPatternSequenceElement *newSeq;
9046 + /*
9047 + * If the dialog is currently displaying the "new" entry and the
9048 + * fields are empty, that's just fine
9049 + */
9050 + if (oldItem == NULL && matchPatternDialogEmpty())
9051 + return NULL;
9053 + /*
9054 + * Read string patterns / sub-pattern names area first
9055 + */
9056 + UpdateManagedList(MatchPatternDialog.mpdStringPatternsListW, True);
9058 + /*
9059 + * If there are no problems reading the data, just return it
9060 + */
9061 + newSeq = readMatchPatternFields(True);
9062 + if (newSeq != NULL)
9063 + return (void *)newSeq;
9065 + /*
9066 + * If there are problems, and the user didn't ask for the fields to be
9067 + * read, give more warning
9068 + */
9069 + if (!explicitRequest)
9071 + if (DialogF(
9072 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9073 + "Discard Matching Pattern Entry",
9074 + "Discard incomplete entry\nfor current matching pattern?",
9075 + "Keep", "Discard") == 2)
9077 + return oldItem == NULL
9078 + ? NULL
9079 + : (void *)copyDialogSequenceElement(
9080 + (DialogMatchPatternSequenceElement *)oldItem);
9084 + /*
9085 + * read data again without "silent" mode to display warning
9086 + */
9087 + newSeq = readMatchPatternFields(False);
9088 + *abort = True;
9090 + return NULL;
9093 +static void setMatchPatternDisplayedCB(void *item, void *cbArg)
9095 + DialogMatchPatternSequenceElement *seqElement;
9096 + DialogMatchPatternTableElement *element;
9097 + DialogMatchPatternGroupElement *group;
9098 + int isGroup;
9100 + seqElement = (DialogMatchPatternSequenceElement *)item;
9102 + MatchPatternDialog.currentDmptSeqElement = seqElement;
9104 + if (item == NULL)
9106 + MatchPatternDialog.currentDmptElement = NULL;
9107 + MatchPatternDialog.currentDmptGroup = NULL;
9109 + XmTextSetString(MatchPatternDialog.mpdMatchPatternNameW, "");
9110 + RadioButtonChangeState(MatchPatternDialog.mptbIndividualW, True, True);
9111 + RadioButtonChangeState(MatchPatternDialog.gabSkipBtwStartEndW, False, False);
9112 + RadioButtonChangeState(MatchPatternDialog.gabFlashW, True, False);
9113 + RadioButtonChangeState(MatchPatternDialog.gabSyntaxBasedW, True, False);
9115 + freeDialogStringPatterns(
9116 + &MatchPatternDialog.currentStringPatterns);
9118 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9120 + setDialogType( STRING_PATTERN_DIALOG );
9122 + else
9124 + isGroup = (seqElement->dmpseType == MPT_GROUP);
9126 + XmTextSetString(MatchPatternDialog.mpdMatchPatternNameW, seqElement->dmpseName);
9128 + if (seqElement->dmpseType == MPT_INDIVIDUAL)
9129 + RadioButtonChangeState(MatchPatternDialog.mptbIndividualW, True, True);
9130 + else if (seqElement->dmpseType == MPT_SUB)
9131 + RadioButtonChangeState(MatchPatternDialog.mptbSubPatternW, True, True);
9132 + else
9133 + RadioButtonChangeState(MatchPatternDialog.mptbContextGroupW, True, True);
9135 + freeDialogStringPatterns(
9136 + &MatchPatternDialog.currentStringPatterns);
9138 + if (isGroup)
9140 + group = (DialogMatchPatternGroupElement *)seqElement->dmpsePtr;
9141 + MatchPatternDialog.currentDmptElement = NULL;
9142 + MatchPatternDialog.currentDmptGroup = group;
9144 + copyDialogPatternNamesFromGroup(
9145 + group,
9146 + &MatchPatternDialog.currentStringPatterns);
9148 + else
9150 + element = (DialogMatchPatternTableElement *)seqElement->dmpsePtr;
9151 + MatchPatternDialog.currentDmptElement = element;
9152 + MatchPatternDialog.currentDmptGroup = NULL;
9154 + RadioButtonChangeState(
9155 + MatchPatternDialog.gabSkipBtwStartEndW,
9156 + element->dmpteSkipBtwnStartEnd,
9157 + False);
9158 + RadioButtonChangeState(
9159 + MatchPatternDialog.gabFlashW,
9160 + element->dmpteFlash,
9161 + False);
9162 + RadioButtonChangeState(
9163 + MatchPatternDialog.gabSyntaxBasedW,
9164 + !element->dmpteIgnoreHighLightInfo,
9165 + False);
9167 + copyDialogStringPatternsFromTable(
9168 + element,
9169 + &MatchPatternDialog.currentStringPatterns);
9172 + setDialogType( !isGroup );
9174 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9178 +static void freeMatchPatternItemCB(void *item)
9180 + freeDialogSequenceElement((DialogMatchPatternSequenceElement *)item);
9184 +** Use "delete confirm" to delete matching pattern name from
9185 +** any group of this matching pattern set, in case of sub-pattern.
9186 +** Always confirm the delete.
9188 +static int deleteMatchPatternItemCB(int itemIndex, void *cbArg)
9190 + DialogMatchPatternSequenceElement *seqElement;
9192 + seqElement = MatchPatternDialog.mpdTable.dmpiSequence[itemIndex];
9194 + if (seqElement->dmpseType == MPT_SUB)
9196 + removeMatchPatternFromAllGroups( seqElement->dmpseName );
9199 + return True;
9202 +static void *getStringPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
9203 + void *cbArg)
9205 + DialogStringPatternElement *newPat;
9206 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
9208 + /*
9209 + * If the string pattern frame is currently displaying the "new" entry and the
9210 + * fields are empty, that's just fine
9211 + */
9212 + if (oldItem == NULL && stringPatternFieldsEmpty(isRelatedToGroup))
9213 + return NULL;
9215 + /*
9216 + * If there are no problems reading the data, just return it
9217 + */
9218 + newPat = readStringPatternFrameFields(True);
9219 + if (newPat != NULL)
9220 + return (void *)newPat;
9222 + /*
9223 + * If there are problems, and the user didn't ask for the fields to be
9224 + * read, give more warning
9225 + */
9227 + if (!explicitRequest)
9229 + if (DialogF(
9230 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9231 + "Discard String Pattern Entry",
9232 + "Discard incomplete entry\nfor current string pattern?",
9233 + "Keep", "Discard") == 2)
9235 + return oldItem == NULL
9236 + ? NULL
9237 + : (void *)copyDialogStringPatternElement(
9238 + (DialogStringPatternElement *)oldItem);
9242 + /*
9243 + * read data again without "silent" mode to display warning
9244 + */
9245 + newPat = readStringPatternFrameFields(False);
9246 + *abort = True;
9248 + return NULL;
9251 +static void setStringPatternDisplayedCB(void *item, void *cbArg)
9253 + DialogStringPatternElement *element = (DialogStringPatternElement *)item;
9254 + PatternElementKind peKind;
9255 + PatternWordBoundary wordBoundary;
9256 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
9258 + if (item == NULL)
9260 + if (isRelatedToGroup)
9262 + updateSubPatternNameMenu(NULL, False);
9264 + else
9266 + XmTextSetString(MatchPatternDialog.mpdStringPatternW, "");
9268 + setSensitiveWordBoundaryBox( True );
9270 + RadioButtonChangeState(MatchPatternDialog.wbbBothW, True, True);
9272 + /*
9273 + * type of "new" string pattern:
9274 + * preset "start", if no string pattern exists at all;
9275 + * else select "end"
9276 + */
9277 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0)
9278 + RadioButtonChangeState(MatchPatternDialog.sptStartW, True, True);
9279 + else
9280 + RadioButtonChangeState(MatchPatternDialog.sptEndW, True, True);
9282 + RadioButtonChangeState(MatchPatternDialog.sabCaseSensitiveW, True, False);
9283 + RadioButtonChangeState(MatchPatternDialog.sabRegularExpressionW, False, False);
9286 + else
9288 + if (isRelatedToGroup)
9290 + updateSubPatternNameMenu(element->dspeText, False);
9292 + else
9294 + XmTextSetString(MatchPatternDialog.mpdStringPatternW, element->dspeText);
9296 + peKind = element->dspeKind;
9297 + wordBoundary = element->dspeWordBoundary;
9299 + if (peKind == PEK_START)
9300 + RadioButtonChangeState(MatchPatternDialog.sptStartW, True, True);
9301 + else if (peKind == PEK_MIDDLE)
9302 + RadioButtonChangeState(MatchPatternDialog.sptMiddleW, True, True);
9303 + else
9304 + RadioButtonChangeState(MatchPatternDialog.sptEndW, True, True);
9306 + if (wordBoundary == PWB_BOTH)
9307 + RadioButtonChangeState(MatchPatternDialog.wbbBothW, True, True);
9308 + else if (wordBoundary == PWB_LEFT)
9309 + RadioButtonChangeState(MatchPatternDialog.wbbLeftW, True, True);
9310 + else if (wordBoundary == PWB_RIGHT)
9311 + RadioButtonChangeState(MatchPatternDialog.wbbRightW, True, True);
9312 + else
9313 + RadioButtonChangeState(MatchPatternDialog.wbbNoneW, True, True);
9315 + RadioButtonChangeState(
9316 + MatchPatternDialog.sabCaseSensitiveW,
9317 + !element->dspeCaseInsensitive,
9318 + False);
9320 + RadioButtonChangeState(
9321 + MatchPatternDialog.sabRegularExpressionW,
9322 + element->dspeRegularExpression,
9323 + False);
9325 + setSensitiveWordBoundaryBox( !element->dspeRegularExpression );
9330 +static void freeStringPatternItemCB(void *item)
9332 + DialogStringPatternElement *patElement;
9334 + patElement = (DialogStringPatternElement *)item;
9336 + freeDialogStringPatternElement(patElement);
9339 +static void destroyCB(Widget w, XtPointer clientData, XtPointer callData)
9341 + freeVariableDialogData(DISCARD_LANGUAGE_MODE);
9343 + MatchPatternDialog.mpdShell = NULL;
9346 +static void okCB(Widget w, XtPointer clientData, XtPointer callData)
9348 + /*
9349 + * change the matching pattern
9350 + */
9351 + if (!getAndUpdateStringMatchTable())
9352 + return;
9354 + /*
9355 + * pop down and destroy the dialog
9356 + */
9357 + XtDestroyWidget(MatchPatternDialog.mpdShell);
9360 +static void applyCB(Widget w, XtPointer clientData, XtPointer callData)
9362 + /*
9363 + * change the matching pattern
9364 + */
9365 + getAndUpdateStringMatchTable();
9368 +static void checkCB(Widget w, XtPointer clientData, XtPointer callData)
9370 + StringMatchTable *newTable;
9371 + DMPTranslationResult translResult;
9373 + /*
9374 + * Get the current information displayed by the dialog.
9375 + * If a new table is available, then the test is passed successfully.
9376 + */
9377 + newTable = getDialogStringMatchTable(&translResult);
9379 + if (newTable != NULL)
9381 + DialogF(
9382 + DF_INF, MatchPatternDialog.mpdShell, 1,
9383 + "Matching Patterns Checked",
9384 + "Matching Patterns checked without error",
9385 + "OK");
9387 + freeStringMatchTable(newTable);
9391 +static void restoreCB(Widget w, XtPointer clientData, XtPointer callData)
9393 + StringMatchTable *defaultTable;
9395 + defaultTable = readDefaultStringMatchTable(MatchPatternDialog.mpdLangModeName);
9397 + if (defaultTable == NULL)
9399 + DialogF(
9400 + DF_WARN, MatchPatternDialog.mpdShell, 1,
9401 + "No Default Matching Pattern",
9402 + "There is no default matching pattern set\nfor language mode %s",
9403 + "OK",
9404 + MatchPatternDialog.mpdLangModeName);
9406 + return;
9409 + if (DialogF(
9410 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9411 + "Discard Changes",
9412 + "Are you sure you want to discard\n"
9413 + "all changes to matching patterns\n"
9414 + "for language mode %s?",
9415 + "Discard", "Cancel",
9416 + MatchPatternDialog.mpdLangModeName) == 2)
9418 + freeStringMatchTable(defaultTable);
9420 + return;
9423 + /*
9424 + * if a stored version of the matching pattern set exists, replace it.
9425 + * if it doesn't, add a new one.
9426 + */
9427 + updateStringMatchTable( defaultTable );
9429 + /*
9430 + * free the old dialog information
9431 + */
9432 + freeVariableDialogData(KEEP_LANGUAGE_MODE);
9434 + /*
9435 + * update the dialog
9436 + */
9437 + copyStringMatchTableForDialog( defaultTable, &MatchPatternDialog.mpdTable );
9439 + ChangeManagedListData(MatchPatternDialog.mpdMatchPatternNamesListW);
9440 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9443 +static void deleteCB(Widget w, XtPointer clientData, XtPointer callData)
9445 + if (DialogF(
9446 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9447 + "Delete Matching Patterns",
9448 + "Are you sure you want to delete\n"
9449 + "all matching patterns for\n"
9450 + "language mode %s?",
9451 + "Yes, Delete", "Cancel",
9452 + MatchPatternDialog.mpdLangModeName) == 2)
9454 + return;
9457 + /*
9458 + * if a stored version of the matching pattern exists, delete it from the list
9459 + */
9460 + DeleteStringMatchTable(MatchPatternDialog.mpdLangModeName);
9462 + /*
9463 + * free the old dialog information
9464 + */
9465 + freeVariableDialogData(KEEP_LANGUAGE_MODE);
9467 + /*
9468 + * clear out the dialog
9469 + */
9470 + ChangeManagedListData(MatchPatternDialog.mpdMatchPatternNamesListW);
9471 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9474 +static void closeCB(Widget w, XtPointer clientData, XtPointer callData)
9476 + /*
9477 + * pop down and destroy the dialog
9478 + */
9479 + XtDestroyWidget(MatchPatternDialog.mpdShell);
9482 +static void helpCB(Widget w, XtPointer clientData, XtPointer callData)
9485 + Help(HELP_MATCHING_PATTERNS);
9489 +static void strPatRegExpressionCB(Widget w, XtPointer clientData, XtPointer callData)
9491 + int regularExpression =
9492 + XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
9494 + setSensitiveWordBoundaryBox( !regularExpression );
9496 + if (regularExpression)
9497 + RadioButtonChangeState(MatchPatternDialog.sabCaseSensitiveW, True, False);
9500 +static void matchPatTypeCB(Widget w, XtPointer clientData, XtPointer callData)
9502 + if (MatchPatternDialog.currentDmptSeqElement != NULL)
9504 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW))
9506 + if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_SUB)
9508 + changeExistingSubPattern("Change to Context Group");
9511 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW) &&
9512 + MatchPatternDialog.currentDmptSeqElement->dmpseType != MPT_GROUP)
9514 + changeStringPatternToGroup();
9517 + else if (XmToggleButtonGetState(MatchPatternDialog.mptbIndividualW))
9519 + if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_SUB)
9521 + changeExistingSubPattern("Change to Individual Matching Pattern");
9523 + else if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_GROUP)
9525 + changeGroupToStringPattern("Change to Individual Matching Pattern");
9528 + else if (XmToggleButtonGetState(MatchPatternDialog.mptbSubPatternW))
9530 + if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_GROUP)
9532 + changeGroupToStringPattern("Change to Sub-Matching Pattern");
9537 + /*
9538 + * if context group button is (still) selected, then update labels etc.
9539 + */
9540 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW))
9542 + setDialogType(CONTEXT_GROUP_DIALOG);
9544 + else
9546 + setDialogType(STRING_PATTERN_DIALOG);
9549 + /*
9550 + * if a "new" entry is selected in matching patterns names list, then provide a
9551 + * list of all sub-pattern names
9552 + */
9553 + if (MatchPatternDialog.currentDmptSeqElement == NULL)
9555 + updateSubPatternNameMenu(NULL, True);
9559 +static void changeExistingSubPattern(
9560 + char *warnTitle)
9562 + DialogMatchPatternGroupElement *group;
9563 + int resp;
9565 + group =
9566 + getDialogGroupUsingMatchPattern(
9567 + MatchPatternDialog.currentDmptElement->dmpteName );
9569 + while ( group != NULL )
9571 + resp =
9572 + DialogF(
9573 + DF_WARN, MatchPatternDialog.mpdShell, 3,
9574 + warnTitle,
9575 + "Sub-pattern '%s' is used at least\n"
9576 + "by context group '%s'.\n\n"
9577 + "Remove this sub-pattern from this resp. all context group(s) ?",
9578 + "No, Keep", "Yes, Remove", "Yes, Remove All",
9579 + MatchPatternDialog.currentDmptElement->dmpteName,
9580 + group->dmpgeName);
9582 + if (resp == 1)
9584 + RadioButtonChangeState(MatchPatternDialog.mptbSubPatternW, True, True);
9586 + return;
9588 + else if (resp == 2)
9590 + removeMatchPatternFromGroup(
9591 + MatchPatternDialog.currentDmptElement->dmpteName,
9592 + group);
9594 + /*
9595 + * look for evtl. next context group holding this matching pattern
9596 + */
9597 + group =
9598 + getDialogGroupUsingMatchPattern(
9599 + MatchPatternDialog.currentDmptElement->dmpteName );
9601 + else
9603 + /*
9604 + * remove this matching pattern form all context groups
9605 + */
9606 + removeMatchPatternFromAllGroups(
9607 + MatchPatternDialog.currentDmptElement->dmpteName);
9609 + return;
9614 +static void changeStringPatternToGroup(void)
9616 + int resp;
9617 + int isSubPattern;
9619 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns != 0)
9621 + resp =
9622 + DialogF(
9623 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9624 + "Change to Context Group",
9625 + "All string patterns of '%s'\n"
9626 + "need to be discarded.\n\n"
9627 + "Discard related string patterns ?",
9628 + "No, Keep", "Yes, Discard",
9629 + MatchPatternDialog.currentDmptElement->dmpteName);
9631 + if (resp == 1)
9633 + isSubPattern = (MatchPatternDialog.currentDmptElement->dmpteType == MPT_SUB);
9635 + if (isSubPattern)
9636 + RadioButtonChangeState(MatchPatternDialog.mptbSubPatternW, True, True);
9637 + else
9638 + RadioButtonChangeState(MatchPatternDialog.mptbIndividualW, True, True);
9640 + return;
9643 + /*
9644 + * remove string patterns & update dialog fields
9645 + */
9646 + freeDialogStringPatterns(&MatchPatternDialog.currentStringPatterns);
9648 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9651 + /*
9652 + * invalidate this sub-/individual pattern
9653 + */
9654 + MatchPatternDialog.currentDmptSeqElement->dmpseValid = False;
9656 + /*
9657 + * update sub-pattern menu due to change to context group
9658 + */
9659 + updateSubPatternNameMenu(NULL, True);
9662 +static void changeGroupToStringPattern(
9663 + char *warnTitle)
9665 + int resp;
9667 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0)
9668 + return;
9670 + resp =
9671 + DialogF(
9672 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9673 + warnTitle,
9674 + "Content of context group '%s'\n"
9675 + "needs to be discarded.\n\n"
9676 + "Discard content ?",
9677 + "No, Keep", "Yes, Discard",
9678 + MatchPatternDialog.currentDmptGroup->dmpgeName);
9680 + if (resp == 1)
9682 + RadioButtonChangeState(MatchPatternDialog.mptbContextGroupW, True, True);
9684 + else
9686 + /*
9687 + * remove string patterns & update dialog fields
9688 + */
9689 + freeDialogStringPatterns(&MatchPatternDialog.currentStringPatterns);
9691 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9696 +** Create a pulldown menu pane with the names of the sub-patterns of
9697 +** the current matching pattern set.
9699 +static Widget createSubPatternNameMenu(
9700 + Widget parent,
9701 + char *currentSubPatName,
9702 + int allSubPatterns)
9704 + NameList nameList;
9705 + Widget menu;
9706 + int i;
9708 + setupSubPatternNameList(currentSubPatName, allSubPatterns, &nameList);
9710 + menu = CreatePulldownMenu(parent, "subPatternNames", NULL, 0);
9712 + for (i=0; i<nameList.nlNumber; i++)
9714 + createSubPatNameMenuEntry(menu, nameList.nlId[i]);
9717 + return menu;
9720 +static void setupSubPatternNameList(
9721 + char *currentSubPatName,
9722 + int allSubPatterns,
9723 + NameList *nameList)
9725 + int n = 0;
9726 + int i;
9727 + DialogMatchPatternSequenceElement *seq;
9728 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
9730 + if (isRelatedToGroup || allSubPatterns)
9732 + /*
9733 + * add "none selected" (default) item
9734 + */
9735 + nameList->nlId[n ++] = SPNM_NONE_SELECTED;
9737 + /*
9738 + * add one item for each (not assigned) sub-pattern name
9739 + */
9740 + for (i=0; i<MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i++)
9742 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
9744 + if (seq->dmpseType == MPT_SUB &&
9745 + seq->dmpseValid &&
9746 + (allSubPatterns ||
9747 + (!isSubPatternNameInCurStrPat(seq->dmpseName) ||
9748 + (currentSubPatName != NULL &&
9749 + (strcmp(seq->dmpseName, currentSubPatName) == 0))) ))
9751 + nameList->nlId[n ++] = seq->dmpseName;
9755 + else
9757 + nameList->nlId[n ++] = "none available ";
9760 + nameList->nlNumber = n;
9764 +** Create a menu entry with the names of one sub-pattern.
9765 +** XmNuserData of this item contains the sub-pattern name.
9767 +static void createSubPatNameMenuEntry(
9768 + Widget menu,
9769 + char *subPatName)
9771 + Widget btn;
9772 + XmString s1;
9774 + btn = XtVaCreateManagedWidget("subPattern", xmPushButtonGadgetClass,
9775 + menu,
9776 + XmNlabelString, s1=XmStringCreateSimple(subPatName),
9777 + XmNmarginHeight, 0,
9778 + XmNuserData, (void *)subPatName, NULL);
9779 + XmStringFree(s1);
9783 +** Set the sub-patterns menu to show a particular sub-pattern name
9785 +static void setSubPatternNameMenu(
9786 + const char *subPatName)
9788 + int i;
9789 + Cardinal nItems;
9790 + WidgetList items;
9791 + Widget pulldown, selectedItem;
9792 + char *itemName;
9794 + XtVaGetValues(MatchPatternDialog.mpdSubPatNamesOptMenu, XmNsubMenuId, &pulldown, NULL);
9795 + XtVaGetValues(pulldown, XmNchildren, &items, XmNnumChildren, &nItems, NULL);
9797 + if (nItems == 0)
9798 + return;
9800 + selectedItem = items[0];
9802 + /*
9803 + * if no subPatName is given, then select first item of option menu
9804 + */
9805 + if (subPatName != NULL)
9807 + for (i=0; i<(int)nItems; i++)
9809 + if (items[i] != NULL && !items[i]->core.being_destroyed)
9811 + XtVaGetValues(items[i], XmNuserData, &itemName, NULL);
9812 + if (!strcmp(itemName, subPatName))
9814 + selectedItem = items[i];
9815 + break;
9821 + XtVaSetValues(MatchPatternDialog.mpdSubPatNamesOptMenu, XmNmenuHistory, selectedItem, NULL);
9825 +** Update sub-pattern names menu, e.g. when a new sub-pattern is defined
9827 +static void updateSubPatternNameMenu(
9828 + char *currentSubPatName,
9829 + int allSubPatterns)
9831 + NameList nameList;
9832 + WidgetList items;
9833 + Cardinal nItems;
9834 + int n;
9835 + XmString st1;
9837 + setupSubPatternNameList(currentSubPatName, allSubPatterns, &nameList);
9839 + /*
9840 + * Go thru all of the items in the sub-pattern names menu
9841 + * and rename them to match the current sub-patterns.
9842 + * Delete any extras.
9843 + */
9844 + XtVaGetValues(
9845 + MatchPatternDialog.mpdSubPatNamesPulldown,
9846 + XmNchildren, &items,
9847 + XmNnumChildren, &nItems,
9848 + NULL);
9850 + for (n=0; n<(int)nItems; n++)
9852 + if (n >= nameList.nlNumber)
9854 + /*
9855 + * unmanaging before destroying stops parent from displaying
9856 + */
9857 + XtUnmanageChild(items[n]);
9858 + XtDestroyWidget(items[n]);
9860 + else
9862 + if (items[n] == NULL || items[n]->core.being_destroyed)
9864 + /*
9865 + * create a new entry (widget) if this one is not existing or
9866 + * if it is marked as to be destroyed
9867 + */
9868 + createSubPatNameMenuEntry(
9869 + MatchPatternDialog.mpdSubPatNamesPulldown, nameList.nlId[n]);
9871 + else
9873 + XtVaSetValues(
9874 + items[n],
9875 + XmNlabelString, st1=XmStringCreateSimple(nameList.nlId[n]),
9876 + XmNuserData, (void *)nameList.nlId[n],
9877 + NULL);
9879 + XmStringFree(st1);
9884 + /*
9885 + * add new items for remaining sub-patterns names
9886 + */
9887 + for (n=(int)nItems; n<nameList.nlNumber; n++)
9889 + createSubPatNameMenuEntry(
9890 + MatchPatternDialog.mpdSubPatNamesPulldown, nameList.nlId[n]);
9893 + /*
9894 + * select entry shown in sub-pattern name option menu
9895 + */
9896 + setSubPatternNameMenu(currentSubPatName);
9899 +static char *getSelectedSubPatternName(void)
9901 + Widget selectedItem;
9902 + char *itemName;
9904 + XtVaGetValues(MatchPatternDialog.mpdSubPatNamesOptMenu, XmNmenuHistory, &selectedItem, NULL);
9905 + XtVaGetValues(selectedItem, XmNuserData, &itemName, NULL);
9907 + return itemName;
9910 +static int isSubPatternNameInCurStrPat(
9911 + char *subPatName)
9913 + int i;
9914 + DialogStringPatterns *curPatNames = &MatchPatternDialog.currentStringPatterns;
9916 + for (i=0; i<curPatNames->dspNumberOfPatterns; i++)
9918 + if (strcmp(curPatNames->dspElements[i]->dspeText, subPatName) == 0)
9919 + return True;
9922 + return False;
9926 +** Read the matching pattern fields of the matching pattern dialog and produce an
9927 +** allocated DialogMatchPatternSequenceElement structure reflecting the contents.
9928 +** Pop up dialogs telling the user what's wrong (Passing "silent" as True,
9929 +** suppresses these dialogs).
9930 +** Returns NULL on error.
9932 +static DialogMatchPatternSequenceElement *readMatchPatternFields(int silent)
9934 + int isGroup;
9935 + char *name;
9936 + char *nameLabel;
9937 + char *nameTitle;
9938 + char *contentTitle;
9939 + char *contentWarningText;
9940 + DialogMatchPatternSequenceElement *newSeq;
9941 + DialogMatchPatternTableElement *newElement;
9942 + DialogMatchPatternGroupElement *newGroup;
9944 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW))
9946 + nameLabel = "context group name";
9947 + nameTitle = "Context Group Name";
9948 + contentTitle = "Context Group Content";
9949 + contentWarningText = "Please assign min. 1\nsub-pattern";
9950 + isGroup = True;
9952 + else
9954 + nameLabel = "matching pattern name";
9955 + nameTitle = "Matching Pattern Name";
9956 + contentTitle = "Matching Pattern Content";
9957 + contentWarningText = "Please specify min. 1\nstring pattern";
9958 + isGroup = False;
9961 + name =
9962 + ReadSymbolicFieldTextWidget(
9963 + MatchPatternDialog.mpdMatchPatternNameW,
9964 + nameLabel,
9965 + silent);
9967 + if (name == NULL)
9969 + return NULL;
9971 + else if (*name == '\0')
9973 + if (!silent)
9975 + DialogF(
9976 + DF_WARN, MatchPatternDialog.mpdShell, 1,
9977 + nameTitle,
9978 + "Please specify a valid name",
9979 + "OK");
9980 + XmProcessTraversal(MatchPatternDialog.mpdMatchPatternNameW, XmTRAVERSE_CURRENT);
9982 + XtFree(name);
9983 + return NULL;
9986 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0)
9988 + if (!silent)
9990 + DialogF(
9991 + DF_WARN, MatchPatternDialog.mpdShell, 1,
9992 + contentTitle,
9993 + contentWarningText,
9994 + "OK");
9996 + XtFree(name);
9997 + return NULL;
9999 + else
10001 + if (!isGroup &&
10002 + !isStartPatternElementAvailable(&MatchPatternDialog.currentStringPatterns))
10004 + if (!silent)
10006 + DialogF(
10007 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10008 + contentTitle,
10009 + "Please specify min. 1 string pattern\nof type 'start'",
10010 + "OK");
10012 + XtFree(name);
10013 + return NULL;
10017 + if (MatchPatternDialog.currentDmptElement != NULL &&
10018 + MatchPatternDialog.currentDmptElement->dmpteType == MPT_SUB &&
10019 + strcmp(MatchPatternDialog.currentDmptElement->dmpteName, name) != 0)
10021 + renameMatchPatternInAllGroups(
10022 + MatchPatternDialog.currentDmptElement->dmpteName,
10023 + name);
10026 + newSeq =
10027 + (DialogMatchPatternSequenceElement *)XtMalloc(sizeof(DialogMatchPatternSequenceElement));
10029 + newSeq->dmpseName = name;
10030 + newSeq->dmpseValid = True;
10032 + if (isGroup)
10034 + newSeq->dmpseType = MPT_GROUP;
10036 + newGroup =
10037 + (DialogMatchPatternGroupElement *)XtMalloc(sizeof(DialogMatchPatternGroupElement));
10039 + newGroup->dmpgeName = XtNewString(name);
10041 + copyDialogPatternNamesToGroup(
10042 + &MatchPatternDialog.currentStringPatterns,
10043 + newGroup);
10045 + newSeq->dmpsePtr = (void *)newGroup;
10047 + else
10049 + if (XmToggleButtonGetState(MatchPatternDialog.mptbIndividualW))
10050 + newSeq->dmpseType = MPT_INDIVIDUAL;
10051 + else
10052 + newSeq->dmpseType = MPT_SUB;
10054 + newElement =
10055 + (DialogMatchPatternTableElement *)XtMalloc(sizeof(DialogMatchPatternTableElement));
10057 + newElement->dmpteName = XtNewString(name);
10058 + newElement->dmpteType = newSeq->dmpseType;
10060 + newElement->dmpteSkipBtwnStartEnd =
10061 + XmToggleButtonGetState(MatchPatternDialog.gabSkipBtwStartEndW);
10063 + newElement->dmpteFlash =
10064 + XmToggleButtonGetState(MatchPatternDialog.gabFlashW);
10066 + newElement->dmpteIgnoreHighLightInfo =
10067 + !XmToggleButtonGetState(MatchPatternDialog.gabSyntaxBasedW);
10069 + copyDialogStringPatterns(
10070 + &MatchPatternDialog.currentStringPatterns,
10071 + &newElement->dmptePatterns);
10073 + newSeq->dmpsePtr = (void *)newElement;
10076 + return newSeq;
10080 +** Check, if min. 1 string pattern of type 'start' is
10081 +** available within dialog.
10082 +** Returns True, if min. 1 start string pattern is
10083 +** populated in dialog.
10085 +static int isStartPatternElementAvailable(
10086 + DialogStringPatterns *dialogPatterns)
10088 + int i;
10090 + for (i=0; i < dialogPatterns->dspNumberOfPatterns; i++)
10092 + if (dialogPatterns->dspElements[i]->dspeKind == PEK_START)
10093 + return True;
10096 + return False;
10100 +** Read the string pattern fields of the string pattern frame and produce an
10101 +** allocated DialogStringPatternElement structure reflecting the contents.
10102 +** Pop up dialogs telling the user what's wrong (Passing "silent" as True,
10103 +** suppresses these dialogs).
10104 +** Returns NULL on error.
10106 +static DialogStringPatternElement *readStringPatternFrameFields(int silent)
10108 + char *stringPatText;
10109 + DialogStringPatternElement *newPatElement;
10110 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
10112 + if (isRelatedToGroup)
10114 + stringPatText = getSelectedSubPatternName();
10115 + if (strcmp(stringPatText, SPNM_NONE_SELECTED) == 0)
10117 + return NULL;
10120 + stringPatText = XtNewString(stringPatText);
10122 + else
10124 + stringPatText =
10125 + XmTextGetString(MatchPatternDialog.mpdStringPatternW);
10127 + if (stringPatText == NULL)
10129 + return NULL;
10131 + else if (*stringPatText == '\0')
10133 + if (!silent)
10135 + DialogF(
10136 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10137 + "String Pattern",
10138 + "Please specify string\npattern content",
10139 + "OK");
10140 + XmProcessTraversal(MatchPatternDialog.mpdStringPatternW, XmTRAVERSE_CURRENT);
10142 + XtFree(stringPatText);
10143 + return NULL;
10147 + newPatElement = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
10149 + newPatElement->dspeText = stringPatText;
10151 + if (isRelatedToGroup)
10153 + newPatElement->dspeKind = PEK_START;
10154 + newPatElement->dspeWordBoundary = PWB_NONE;
10155 + newPatElement->dspeCaseInsensitive = False;
10156 + newPatElement->dspeRegularExpression = False;
10158 + else
10160 + newPatElement->dspeRegularExpression =
10161 + XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
10163 + if (XmToggleButtonGetState(MatchPatternDialog.sptStartW))
10164 + newPatElement->dspeKind = PEK_START;
10165 + else if (XmToggleButtonGetState(MatchPatternDialog.sptMiddleW))
10166 + newPatElement->dspeKind = PEK_MIDDLE;
10167 + else
10168 + newPatElement->dspeKind = PEK_END;
10170 + if (newPatElement->dspeRegularExpression)
10171 + newPatElement->dspeWordBoundary = PWB_NONE;
10172 + else if (XmToggleButtonGetState(MatchPatternDialog.wbbBothW))
10173 + newPatElement->dspeWordBoundary = PWB_BOTH;
10174 + else if (XmToggleButtonGetState(MatchPatternDialog.wbbLeftW))
10175 + newPatElement->dspeWordBoundary = PWB_LEFT;
10176 + else if (XmToggleButtonGetState(MatchPatternDialog.wbbRightW))
10177 + newPatElement->dspeWordBoundary = PWB_RIGHT;
10178 + else
10179 + newPatElement->dspeWordBoundary = PWB_NONE;
10181 + newPatElement->dspeCaseInsensitive =
10182 + !XmToggleButtonGetState(MatchPatternDialog.sabCaseSensitiveW);
10185 + return newPatElement;
10189 +** Returns true if the pattern fields of the matching pattern dialog are set to
10190 +** the default ("New" pattern) state.
10192 +static int matchPatternDialogEmpty(void)
10194 + return
10195 + TextWidgetIsBlank(MatchPatternDialog.mpdMatchPatternNameW) &&
10196 + XmToggleButtonGetState(MatchPatternDialog.mptbIndividualW) &&
10197 + XmToggleButtonGetState(MatchPatternDialog.gabFlashW) &&
10198 + XmToggleButtonGetState(MatchPatternDialog.gabSyntaxBasedW) &&
10199 + stringPatternFrameEmpty();
10203 +** Returns true if the string pattern frame of the matching pattern dialog is set to
10204 +** the default state.
10206 +static int stringPatternFrameEmpty(void)
10208 + return
10209 + stringPatternFieldsEmpty(False) &&
10210 + MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0;
10214 +** Returns true if the string pattern fields of the string pattern frame are set to
10215 +** the default state.
10217 +static int stringPatternFieldsEmpty(
10218 + int strPatIsRelatedToGroup)
10220 + if (strPatIsRelatedToGroup)
10222 + return(
10223 + strcmp( getSelectedSubPatternName(), SPNM_NONE_SELECTED ) == 0);
10225 + else
10227 + return
10228 + TextWidgetIsBlank(MatchPatternDialog.mpdStringPatternW) &&
10229 + XmToggleButtonGetState(MatchPatternDialog.wbbBothW) &&
10230 + XmToggleButtonGetState(MatchPatternDialog.sabCaseSensitiveW) &&
10231 + !XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
10236 +** Get the current content of the matching pattern dialog.
10237 +** If the matching pattern is o.k., then update & apply it
10238 +** to any window which is currently using the matching pattern.
10239 +** If it's bad, then only report it.
10241 +static int getAndUpdateStringMatchTable(void)
10243 + StringMatchTable *newTable;
10244 + DMPTranslationResult translResult;
10246 + /*
10247 + * Get the current information displayed by the dialog. If it's bad,
10248 + * report it to the user & return.
10249 + */
10250 + newTable = getDialogStringMatchTable(&translResult);
10252 + if (newTable == NULL && translResult != DMPTR_EMPTY)
10254 + DialogF(
10255 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10256 + "Incomplete Matching Patterns for Language Mode",
10257 + "Incomplete matching patterns for language mode '%s'.\n"
10258 + "Please complete them first",
10259 + "OK",
10260 + MatchPatternDialog.mpdLangModeName);
10262 + return False;
10265 + /*
10266 + * change the matching pattern
10267 + */
10268 + updateStringMatchTable( newTable );
10270 + return True;
10274 +** Update the matching pattern set being edited in the matching pattern dialog
10275 +** with the information that the dialog is currently displaying, and
10276 +** apply changes to any window which is currently using the matching pattern.
10278 +static void updateStringMatchTable(
10279 + StringMatchTable *newTable)
10281 + WindowInfo *window;
10282 + int i;
10284 + /*
10285 + * Find the matching pattern being modified
10286 + */
10287 + for (i=0; i<NbrMatchTables; i++)
10289 + if (!strcmp(MatchPatternDialog.mpdLangModeName, MatchTables[i]->smtLanguageMode))
10291 + /*
10292 + * replace existing matching pattern
10293 + */
10294 + freeStringMatchTable(MatchTables[i]);
10295 + MatchTables[i] = newTable;
10296 + break;
10300 + if (i == NbrMatchTables)
10302 + /*
10303 + * new match table for language mode -> add it to end
10304 + */
10305 + MatchTables[NbrMatchTables++] = newTable;
10308 + /*
10309 + * Find windows that are currently using this matching pattern set and
10310 + * update this windows
10311 + */
10312 + for (window=WindowList; window!=NULL; window=window->next)
10314 + if ((window->languageMode == PLAIN_LANGUAGE_MODE &&
10315 + !strcmp(PLAIN_LM_STRING, newTable->smtLanguageMode)) ||
10316 + (window->languageMode != PLAIN_LANGUAGE_MODE &&
10317 + !strcmp(LanguageModeName(window->languageMode), newTable->smtLanguageMode)))
10319 + window->stringMatchTable = newTable;
10323 + /*
10324 + * Note that preferences have been changed
10325 + */
10326 + MarkPrefsChanged();
10329 +static StringMatchTable *getDialogStringMatchTable(
10330 + DMPTranslationResult *result)
10332 + int matchPatListIdx =
10333 + ManagedListSelectedIndex(MatchPatternDialog.mpdMatchPatternNamesListW);
10334 + int stringPatListIdx =
10335 + ManagedListSelectedIndex(MatchPatternDialog.mpdStringPatternsListW);
10337 + /*
10338 + * Get the current content of the matching pattern dialog fields
10339 + */
10340 + if (!UpdateManagedList(MatchPatternDialog.mpdStringPatternsListW, True))
10342 + *result = DMPTR_INCOMPLETE;
10344 + return NULL;
10347 + if (!UpdateManagedList(MatchPatternDialog.mpdMatchPatternNamesListW, True))
10349 + *result = DMPTR_INCOMPLETE;
10351 + return NULL;
10354 + SelectManagedListItem(MatchPatternDialog.mpdMatchPatternNamesListW, matchPatListIdx);
10355 + SelectManagedListItem(MatchPatternDialog.mpdStringPatternsListW, stringPatListIdx);
10357 + /*
10358 + * Translate dialog match table to string match table
10359 + */
10360 + return translateDialogStringMatchTable(&MatchPatternDialog.mpdTable, result);
10363 +static StringMatchTable *translateDialogStringMatchTable(
10364 + DialogMatchPatternInfo *dialogTable,
10365 + DMPTranslationResult *result)
10367 + ReadMatchPatternInfo readPatInfo;
10368 + DialogMatchPatternSequenceElement *seq;
10369 + MatchPatternTableElement *newPatElement;
10370 + MatchPatternGroupElement *newGroupElement;
10371 + char *errMsg;
10372 + ErrorInfo errInfo;
10373 + int i;
10375 + initErrorInfo(&errInfo);
10377 + readPatInfo.rmpiNbrOfElements = 0;
10378 + readPatInfo.rmpiNbrOfGroups = 0;
10379 + readPatInfo.rmpiNbrOfSeqElements = 0;
10380 + readPatInfo.rmpiAllPatRE = NULL;
10381 + readPatInfo.rmpiFlashPatRE = NULL;
10383 + /*
10384 + * if no dialog patterns are defined, return "empty" table
10385 + */
10386 + if (dialogTable->dmpiNbrOfSeqElements == 0)
10388 + *result = DMPTR_EMPTY;
10390 + return createStringMatchTable(
10391 + &readPatInfo,
10392 + XtNewString(MatchPatternDialog.mpdLangModeName));
10395 + /*
10396 + * translate dialog matching pattern elements
10397 + */
10398 + for (i=0; i < dialogTable->dmpiNbrOfSeqElements; i++)
10400 + seq = dialogTable->dmpiSequence[i];
10402 + if (seq->dmpseType == MPT_GROUP)
10404 + newGroupElement =
10405 + translateDialogMatchPatternGroupElement(
10406 + &readPatInfo,
10407 + (DialogMatchPatternGroupElement *)seq->dmpsePtr);
10409 + if (newGroupElement == NULL)
10411 + freeReadMatchPatternInfo(&readPatInfo);
10413 + *result = DMPTR_INCOMPLETE;
10415 + return NULL;
10418 + readPatInfo.rmpiGroup[readPatInfo.rmpiNbrOfGroups ++] =
10419 + newGroupElement;
10421 + recordPatternSequence(
10422 + &readPatInfo,
10423 + seq->dmpseName,
10424 + seq->dmpseType,
10425 + readPatInfo.rmpiNbrOfGroups-1 );
10427 + else
10429 + newPatElement =
10430 + translateDialogMatchPatternTableElement(
10431 + (DialogMatchPatternTableElement *)seq->dmpsePtr);
10433 + newPatElement->mpteIndex = readPatInfo.rmpiNbrOfElements;
10435 + readPatInfo.rmpiElement[readPatInfo.rmpiNbrOfElements ++] =
10436 + newPatElement;
10438 + if (newPatElement->mpteType == MPT_INDIVIDUAL)
10440 + if (!assignIndividualGroup(&readPatInfo, &errMsg, newPatElement))
10442 + DialogF(
10443 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10444 + "Assign reg. exp.",
10445 + "%s\n(Pattern: '%s')",
10446 + "OK",
10447 + errMsg,
10448 + newPatElement->mpteName);
10450 + freeReadMatchPatternInfo(&readPatInfo);
10452 + *result = DMPTR_INCOMPLETE;
10454 + return NULL;
10458 + treatDuplicatedMTEntries(readPatInfo.rmpiElement, readPatInfo.rmpiNbrOfElements);
10460 + recordPatternSequence(
10461 + &readPatInfo,
10462 + seq->dmpseName,
10463 + seq->dmpseType,
10464 + newPatElement->mpteIndex );
10468 + /*
10469 + * compile reg. expressions of "read" patterns
10470 + */
10471 + if (createRegExpOfPatterns( &readPatInfo, &errInfo ))
10473 + errInfo.eiLanguageMode = XtNewString(MatchPatternDialog.mpdLangModeName);
10474 + dialogMatchingPatternSetError(
10475 + "Assign all patterns reg. exp.",
10476 + &errInfo);
10478 + freeReadMatchPatternInfo(&readPatInfo);
10480 + *result = DMPTR_INCOMPLETE;
10482 + return NULL;
10485 + *result = DMPTR_OK;
10487 + return createStringMatchTable(
10488 + &readPatInfo,
10489 + XtNewString(MatchPatternDialog.mpdLangModeName));
10492 +static MatchPatternTableElement *translateDialogMatchPatternTableElement(
10493 + DialogMatchPatternTableElement *dialogElement)
10495 + MatchPatternTableElement *newElement;
10497 + newElement =
10498 + (MatchPatternTableElement *)XtMalloc(sizeof(MatchPatternTableElement));
10500 + newElement->mpteName = XtNewString(dialogElement->dmpteName);
10501 + newElement->mpteIndex = NO_ELEMENT_IDX;
10502 + newElement->mpteType = dialogElement->dmpteType;
10503 + newElement->mpteGroup = NO_GROUP_IDX;
10505 + translateDialogPatterns(&dialogElement->dmptePatterns, newElement);
10507 + newElement->mpteSkipBtwnStartEnd = dialogElement->dmpteSkipBtwnStartEnd;
10508 + newElement->mpteFlash = dialogElement->dmpteFlash;
10509 + newElement->mpteIgnoreHighLightInfo = dialogElement->dmpteIgnoreHighLightInfo;
10510 + newElement->mpteStartEndRE = NULL;
10512 + initGlobalBackRefList( newElement->mpteGlobalBackRef );
10514 + return newElement;
10517 +static void translateDialogPatterns(
10518 + DialogStringPatterns *dialogPatterns,
10519 + MatchPatternTableElement *newElement)
10521 + int sizeOfPat;
10522 + int i;
10524 + /*
10525 + * allocate memory for patterns
10526 + */
10527 + newElement->mpteAll.pesNumberOfPattern = dialogPatterns->dspNumberOfPatterns;
10529 + sizeOfPat =
10530 + sizeof(PatternElement *) * dialogPatterns->dspNumberOfPatterns;
10532 + newElement->mpteAll.pesPattern = (PatternElement **)XtMalloc(sizeOfPat);
10534 + /*
10535 + * assign dialog patterns to patterns of MatchPatternTableElement
10536 + */
10537 + for (i=0; i < dialogPatterns->dspNumberOfPatterns; i++)
10539 + newElement->mpteAll.pesPattern[i] =
10540 + createPatternElement(
10541 + XtNewString(dialogPatterns->dspElements[i]->dspeText),
10542 + dialogPatterns->dspElements[i]->dspeKind,
10543 + dialogPatterns->dspElements[i]->dspeWordBoundary,
10544 + dialogPatterns->dspElements[i]->dspeCaseInsensitive,
10545 + dialogPatterns->dspElements[i]->dspeRegularExpression);
10547 + newElement->mpteAll.pesPattern[i]->peIndex = i;
10550 + /*
10551 + * sort pattern elements into start, middle & end arrays
10552 + */
10553 + sortDialogPatternElementSet( &newElement->mpteAll, newElement );
10555 + /*
10556 + * determine mono pattern
10557 + */
10558 + if (newElement->mpteEnd.pesNumberOfPattern == 0)
10560 + newElement->mpteIsMonoPattern = True;
10562 + copyPatternSet( &newElement->mpteStart, &newElement->mpteEnd );
10564 + else
10566 + newElement->mpteIsMonoPattern = False;
10571 + * Sort dialog pattern element set into start, middle & end arrays.
10572 + */
10573 +static void sortDialogPatternElementSet(
10574 + PatternElementSet *allPat,
10575 + MatchPatternTableElement *result)
10577 + int sizeOfPat;
10579 + /*
10580 + * count number of start, middle & end pattern elements
10581 + */
10582 + countPatternElementKind( allPat, result );
10584 + /*
10585 + * allocate pattern elements
10586 + */
10587 + sizeOfPat = sizeof(PatternElement *) * result->mpteStart.pesNumberOfPattern;
10588 + result->mpteStart.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
10590 + if (result->mpteMiddle.pesNumberOfPattern != 0)
10592 + sizeOfPat = sizeof(PatternElement *) * result->mpteMiddle.pesNumberOfPattern;
10593 + result->mpteMiddle.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
10596 + if (result->mpteEnd.pesNumberOfPattern != 0)
10598 + sizeOfPat = sizeof(PatternElement *) * result->mpteEnd.pesNumberOfPattern;
10599 + result->mpteEnd.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
10602 + /*
10603 + * sort pattern elements into start, middle & end arrays
10604 + */
10605 + sortPatternElementSet( allPat, result );
10608 +static MatchPatternGroupElement *translateDialogMatchPatternGroupElement(
10609 + ReadMatchPatternInfo *info,
10610 + DialogMatchPatternGroupElement *dialogGroup)
10612 + int i;
10613 + int error = False;
10614 + MatchPatternTableElement *subPatElement;
10615 + int sizeOfIds;
10616 + MatchPatternGroupElement *group;
10618 + /*
10619 + * Allocate memory for the matching pattern group. Copy name & number of
10620 + * sub patterns.
10621 + */
10622 + group =
10623 + (MatchPatternGroupElement *)XtMalloc( sizeof(MatchPatternGroupElement) );
10625 + group->mpgeName = XtNewString(dialogGroup->dmpgeName);
10626 + group->mpgeNumberOfSubPatterns = dialogGroup->dmpgeNumberOfSubPatterns;
10627 + group->mpgeKeywordRE = NULL;
10629 + /*
10630 + * Allocate memory for the sub-matching pattern IDs
10631 + */
10632 + sizeOfIds = sizeof(char *) * group->mpgeNumberOfSubPatterns;
10633 + group->mpgeSubPatternIds = (char **)XtMalloc( sizeOfIds );
10635 + for (i=0; i < group->mpgeNumberOfSubPatterns; i ++)
10637 + /*
10638 + * Remember sub-matching pattern ID
10639 + */
10640 + group->mpgeSubPatternIds[i] = XtNewString(dialogGroup->dmpgeSubPatternIds[i]);
10642 + /*
10643 + * Assign the index of this group to the sub-matching pattern
10644 + * if no group index was assigned before.
10645 + */
10646 + subPatElement =
10647 + getPatternOfName( info, dialogGroup->dmpgeSubPatternIds[i]);
10649 + if (subPatElement == NULL)
10651 + DialogF(
10652 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10653 + "Group Compilation",
10654 + "Group '%s':\nsub-matching pattern '%s' not defined before",
10655 + "OK",
10656 + group->mpgeName,
10657 + dialogGroup->dmpgeSubPatternIds[i]);
10659 + error = True;
10661 + else
10663 + if (subPatElement->mpteGroup == NO_GROUP_IDX)
10665 + subPatElement->mpteGroup = info->rmpiNbrOfGroups;
10670 + if (error)
10672 + freeMatchPatternGroupElement(group);
10674 + return NULL;
10677 + return group;
10680 +static int stringMatchTableDiffer(
10681 + StringMatchTable *oldTable,
10682 + StringMatchTable *newTable)
10684 + int i, j;
10685 + MatchPatternTable *oldPatTab = oldTable->smtAllPatterns;
10686 + MatchPatternTable *newPatTab = newTable->smtAllPatterns;
10687 + MatchPatternTableElement *oldPat;
10688 + MatchPatternTableElement *newPat;
10689 + MatchPatternGroupElement *oldGroup;
10690 + MatchPatternGroupElement *newGroup;
10691 + MatchPatternSequenceElement *oldSeq;
10692 + MatchPatternSequenceElement *newSeq;
10694 + if (oldTable->smtNumberOfSeqElements != newTable->smtNumberOfSeqElements)
10695 + return True;
10697 + for (i=0; i < oldTable->smtNumberOfSeqElements; i++)
10699 + oldSeq = oldTable->smtSequence[i];
10700 + newSeq = newTable->smtSequence[i];
10702 + if (AllocatedStringsDiffer(oldSeq->mpseName, newSeq->mpseName))
10703 + return True;
10704 + if (oldSeq->mpseType != newSeq->mpseType)
10705 + return True;
10707 + if (oldSeq->mpseType == MPT_GROUP)
10709 + oldGroup = oldTable->smtGroups[oldSeq->mpseIndex];
10710 + newGroup = newTable->smtGroups[newSeq->mpseIndex];
10712 + if (AllocatedStringsDiffer(oldGroup->mpgeName, newGroup->mpgeName))
10713 + return True;
10715 + if (oldGroup->mpgeNumberOfSubPatterns != newGroup->mpgeNumberOfSubPatterns)
10716 + return True;
10718 + for (j=0; j < oldGroup->mpgeNumberOfSubPatterns; j++)
10720 + if (AllocatedStringsDiffer(
10721 + oldGroup->mpgeSubPatternIds[j],
10722 + newGroup->mpgeSubPatternIds[j]))
10723 + return True;
10726 + else
10728 + oldPat = oldPatTab->mptElements[oldSeq->mpseIndex];
10729 + newPat = newPatTab->mptElements[newSeq->mpseIndex];
10731 + if (AllocatedStringsDiffer(oldPat->mpteName, newPat->mpteName))
10732 + return True;
10734 + if (oldPat->mpteType != newPat->mpteType)
10735 + return True;
10737 + if (oldPat->mpteGroup != newPat->mpteGroup)
10738 + return True;
10740 + if (oldPat->mpteAll.pesNumberOfPattern != newPat->mpteAll.pesNumberOfPattern)
10741 + return True;
10743 + for (j=0; j < oldPat->mpteAll.pesNumberOfPattern; j ++)
10745 + if (patternElementDiffer(
10746 + oldPat->mpteAll.pesPattern[j], oldPatTab,
10747 + newPat->mpteAll.pesPattern[j], newPatTab ) )
10748 + return True;
10751 + if (oldPat->mpteIsMonoPattern != newPat->mpteIsMonoPattern)
10752 + return True;
10754 + if (oldPat->mpteSkipBtwnStartEnd != newPat->mpteSkipBtwnStartEnd)
10755 + return True;
10757 + if (oldPat->mpteIgnoreHighLightInfo != newPat->mpteIgnoreHighLightInfo)
10758 + return True;
10760 + if (oldPat->mpteFlash != newPat->mpteFlash)
10761 + return True;
10765 + return False;
10768 +static int patternElementDiffer(
10769 + PatternElement *oldPE,
10770 + MatchPatternTable *oldTab,
10771 + PatternElement *newPE,
10772 + MatchPatternTable *newTab)
10774 + StringPattern *oldSP;
10775 + StringPattern *newSP;
10777 + oldSP = GetStringPattern(oldTab, oldPE);
10778 + newSP = GetStringPattern(newTab, newPE);
10780 + if (AllocatedStringsDiffer(oldSP->spText, newSP->spText))
10781 + return True;
10782 + if (AllocatedStringsDiffer(oldSP->spOrigText, newSP->spOrigText))
10783 + return True;
10784 + if (oldPE->peKind != newPE->peKind)
10785 + return True;
10786 + if (oldSP->spWordBoundary != newSP->spWordBoundary)
10787 + return True;
10788 + if (oldSP->spCaseInsensitive != newSP->spCaseInsensitive)
10789 + return True;
10790 + if (oldSP->spRegularExpression != newSP->spRegularExpression)
10791 + return True;
10793 + return False;
10796 +static DialogMatchPatternGroupElement *getDialogGroupUsingMatchPattern(
10797 + char *matchPatternName)
10799 + DialogMatchPatternSequenceElement *seq;
10800 + DialogMatchPatternGroupElement *group;
10801 + int i, j;
10803 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10805 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
10807 + if (seq->dmpseType == MPT_GROUP)
10809 + group = (DialogMatchPatternGroupElement *)seq->dmpsePtr;
10811 + for (j=0; j < group->dmpgeNumberOfSubPatterns; j ++)
10813 + if (strcmp(group->dmpgeSubPatternIds[j], matchPatternName) == 0)
10814 + return group;
10819 + return NULL;
10822 +static void removeMatchPatternFromGroup(
10823 + char *matchPatternName,
10824 + DialogMatchPatternGroupElement *group)
10826 + int i;
10828 + for (i=0; i < group->dmpgeNumberOfSubPatterns; i ++)
10830 + if (strcmp(group->dmpgeSubPatternIds[i], matchPatternName) == 0)
10832 + /*
10833 + * remove existing matching pattern name from sub-pattern list
10834 + */
10835 + freeXtPtr((void **)&group->dmpgeSubPatternIds[i]);
10836 + memmove(
10837 + &group->dmpgeSubPatternIds[i],
10838 + &group->dmpgeSubPatternIds[i+1],
10839 + (group->dmpgeNumberOfSubPatterns-1 - i) * sizeof(char *));
10840 + group->dmpgeNumberOfSubPatterns --;
10842 + return;
10847 +static void removeMatchPatternFromAllGroups(
10848 + char *matchPatternName)
10850 + DialogMatchPatternSequenceElement *seq;
10851 + DialogMatchPatternGroupElement *group;
10852 + int i;
10854 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10856 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
10858 + if (seq->dmpseType == MPT_GROUP)
10860 + group = (DialogMatchPatternGroupElement *)seq->dmpsePtr;
10862 + removeMatchPatternFromGroup(matchPatternName, group);
10867 +static void renameMatchPatternInGroup(
10868 + char *oldMatchPatternName,
10869 + char *newMatchPatternName,
10870 + DialogMatchPatternGroupElement *group)
10872 + int i;
10874 + for (i=0; i < group->dmpgeNumberOfSubPatterns; i ++)
10876 + if (strcmp(group->dmpgeSubPatternIds[i], oldMatchPatternName) == 0)
10878 + /*
10879 + * rename existing matching pattern name in sub-pattern list
10880 + */
10881 + freeXtPtr((void **)&group->dmpgeSubPatternIds[i]);
10883 + group->dmpgeSubPatternIds[i] =
10884 + XtNewString(newMatchPatternName);
10886 + return;
10891 +static void renameMatchPatternInAllGroups(
10892 + char *oldMatchPatternName,
10893 + char *newMatchPatternName)
10895 + DialogMatchPatternSequenceElement *seq;
10896 + DialogMatchPatternGroupElement *group;
10897 + int i;
10899 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10901 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
10903 + if (seq->dmpseType == MPT_GROUP)
10905 + group = (DialogMatchPatternGroupElement *)seq->dmpsePtr;
10907 + renameMatchPatternInGroup(
10908 + oldMatchPatternName,
10909 + newMatchPatternName,
10910 + group);
10915 +static void freeVariableDialogData(
10916 + int keepLanguageModeName)
10918 + int i;
10920 + if (!keepLanguageModeName)
10921 + freeXtPtr((void **)&MatchPatternDialog.mpdLangModeName);
10923 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10925 + freeDialogSequenceElement(
10926 + MatchPatternDialog.mpdTable.dmpiSequence[i] );
10929 + MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements = 0;
10931 + freeDialogStringPatterns(
10932 + &MatchPatternDialog.currentStringPatterns);
10935 +static void initGlobalBackRefList(
10936 + GlobalBackRefElement *list)
10938 + int i;
10940 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
10942 + list[i].gbreDefByStrPat = NULL;
10943 + list[i].gbreRegExpText = NULL;
10947 +static void initStrPatBackRefList(
10948 + StringPattern *strPat)
10950 + int i;
10952 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
10954 + strPat->spOwnGlobalBackRef[i].spbreRegExpText = NULL;
10955 + strPat->spOwnGlobalBackRef[i].spbreLocalBackRefID = NO_LOCAL_BACK_REF_ID;
10957 + strPat->spGlobalToLocalBackRef[i] = NO_LOCAL_BACK_REF_ID;
10961 +static void initErrorInfo(
10962 + ErrorInfo *errInfo)
10964 + errInfo->eiDetail = NULL;
10965 + errInfo->eiLanguageMode = NULL;
10966 + errInfo->eiMPTabElementName = NULL;
10967 + errInfo->eiStringPatText = NULL;
10968 + errInfo->eiRegExpCompileMsg = NULL;
10969 + errInfo->eiBackRefNbr = 0;
10972 +static void freeErrorInfo(
10973 + ErrorInfo *errInfo)
10975 + freeXtPtr((void **)&errInfo->eiLanguageMode);
10976 + freeXtPtr((void **)&errInfo->eiMPTabElementName);
10977 + freeXtPtr((void **)&errInfo->eiStringPatText);
10980 +static void freeXtPtr(void **ptr)
10982 + if (*ptr != NULL)
10984 + XtFree((char *)*ptr);
10985 + *ptr = NULL;
10989 +static void freePtr(void **ptr)
10991 + if (*ptr != NULL)
10993 + free((char *)*ptr);
10994 + *ptr = NULL;
10997 diff --quilt /dev/null new/source/patternMatchData.h
10998 --- /dev/null
10999 +++ new/source/patternMatchData.h
11000 @@ -0,0 +1,24 @@
11001 +/* $Id: patternMatchData.h,v 1.3 2003/12/12 16:45:25 uleh Exp $ */
11003 +#ifndef NEDIT_PATTERNMATCHDATA_H_INCLUDED
11004 +#define NEDIT_PATTERNMATCHDATA_H_INCLUDED
11006 +void *FindStringMatchTable(const char *langModeName);
11008 +void RenameStringMatchTable(const char *oldName, const char *newName);
11010 +void DeleteStringMatchTable(const char *langModeName);
11012 +void AssignStandardStringMatchTable(const char *langModeName);
11014 +int LMHasStringMatchTable(const char *languageMode);
11016 +int LoadMatchPatternString(char *inString);
11018 +char *WriteMatchPatternString(void);
11020 +void EditMatchPatterns(WindowInfo *window);
11022 +void UpdateLanguageModeMenuMatchPattern(void);
11024 +#endif /* NEDIT_PATTERNMATCHDATA_H_INCLUDED */
11025 diff --quilt old/source/preferences.c new/source/preferences.c
11026 --- old/source/preferences.c
11027 +++ new/source/preferences.c
11028 @@ -47,6 +47,10 @@ static const char CVSID[] = "$Id: prefer
11029 #include "windowTitle.h"
11030 #include "server.h"
11031 #include "tags.h"
11033 +/* Pattern Match Feature */
11034 +#include "patternMatchData.h"
11036 #include "../util/prefFile.h"
11037 #include "../util/misc.h"
11038 #include "../util/DialogF.h"
11039 @@ -280,7 +284,6 @@ static struct prefData {
11040 int emTabDist; /* non-zero tab dist. if emulated tabs are on */
11041 int insertTabs; /* whether to use tabs for padding */
11042 int showMatchingStyle; /* how to flash matching parenthesis */
11043 - int matchSyntaxBased; /* use syntax info to match parenthesis */
11044 int highlightSyntax; /* whether to highlight syntax by default */
11045 int smartTags; /* look for tag in current window first */
11046 int alwaysCheckRelativeTagsSpecs; /* for every new opened file of session */
11047 @@ -350,6 +353,7 @@ static struct {
11048 char *smartIndent;
11049 char *smartIndentCommon;
11050 char *shell;
11051 + char *matchPattern;
11052 } TempStringPrefs;
11054 /* preference descriptions for SavePreferences and RestorePreferences. */
11055 @@ -855,6 +859,72 @@ static PrefDescripRec PrefDescrip[] = {
11056 Matlab:Default", &TempStringPrefs.smartIndent, NULL, True},
11057 {"smartIndentInitCommon", "SmartIndentInitCommon", PREF_ALLOC_STRING,
11058 "Default", &TempStringPrefs.smartIndentCommon, NULL, True},
11059 +/* Pattern Match Feature: matchPatterns resource added */
11060 +#ifdef VMS
11061 +/* The VAX compiler can't compile Java-Script's definition in highlightData.c */
11062 + {"matchPatterns", "MatchPatterns", PREF_ALLOC_STRING,
11063 + "PLAIN:Default\n\
11064 + Ada:Default\n\
11065 + Awk:Default\n\
11066 + C++:Default\n\
11067 + C:Default\n\
11068 + CSS:Default\n\
11069 + Csh:Default\n\
11070 + Fortran:Default\n\
11071 + Java:Default\n\
11072 + LaTeX:Default\n\
11073 + Lex:Default\n\
11074 + Makefile:Default\n\
11075 + Matlab:Default\n\
11076 + NEdit Macro:Default\n\
11077 + Pascal:Default\n\
11078 + Perl:Default\n\
11079 + PostScript:Default\n\
11080 + Python:Default\n\
11081 + Regex:Default\n\
11082 + SGML HTML:Default\n\
11083 + SQL:Default\n\
11084 + Sh Ksh Bash:Default\n\
11085 + Tcl:Default\n\
11086 + VHDL:Default\n\
11087 + Verilog:Default\n\
11088 + XML:Default\n\
11089 + X Resources:Default\n\
11090 + Yacc:Default\n",
11091 + &TempStringPrefs.matchPattern, NULL, True},
11092 +#else
11093 + {"matchPatterns", "MatchPatterns", PREF_ALLOC_STRING,
11094 + "PLAIN:Default\n\
11095 + Ada:Default\n\
11096 + Awk:Default\n\
11097 + C++:Default\n\
11098 + C:Default\n\
11099 + CSS:Default\n\
11100 + Csh:Default\n\
11101 + Fortran:Default\n\
11102 + Java:Default\n\
11103 + JavaScript:Default\n\
11104 + LaTeX:Default\n\
11105 + Lex:Default\n\
11106 + Makefile:Default\n\
11107 + Matlab:Default\n\
11108 + NEdit Macro:Default\n\
11109 + Pascal:Default\n\
11110 + Perl:Default\n\
11111 + PostScript:Default\n\
11112 + Python:Default\n\
11113 + Regex:Default\n\
11114 + SGML HTML:Default\n\
11115 + SQL:Default\n\
11116 + Sh Ksh Bash:Default\n\
11117 + Tcl:Default\n\
11118 + VHDL:Default\n\
11119 + Verilog:Default\n\
11120 + XML:Default\n\
11121 + X Resources:Default\n\
11122 + Yacc:Default\n",
11123 + &TempStringPrefs.matchPattern, NULL, True},
11124 +#endif
11125 {"autoWrap", "AutoWrap", PREF_ENUM, "Continuous",
11126 &PrefData.wrapStyle, AutoWrapTypes, True},
11127 {"wrapMargin", "WrapMargin", PREF_INT, "0",
11128 @@ -871,8 +941,6 @@ static PrefDescripRec PrefDescrip[] = {
11129 &PrefData.saveOldVersion, NULL, True},
11130 {"showMatching", "ShowMatching", PREF_ENUM, "Delimiter",
11131 &PrefData.showMatchingStyle, ShowMatchingTypes, True},
11132 - {"matchSyntaxBased", "MatchSyntaxBased", PREF_BOOLEAN, "True",
11133 - &PrefData.matchSyntaxBased, NULL, True},
11134 {"highlightSyntax", "HighlightSyntax", PREF_BOOLEAN, "True",
11135 &PrefData.highlightSyntax, NULL, True},
11136 {"backlightChars", "BacklightChars", PREF_BOOLEAN, "False",
11137 @@ -1245,6 +1313,7 @@ static void lmApplyCB(Widget w, XtPointe
11138 static void lmCloseCB(Widget w, XtPointer clientData, XtPointer callData);
11139 static int lmDeleteConfirmCB(int itemIndex, void *cbArg);
11140 static int updateLMList(void);
11141 +static int isOldLanguageMode(const char *lmDialogName, const char *oldModeName);
11142 static languageModeRec *copyLanguageModeRec(languageModeRec *lm);
11143 static void *lmGetDisplayedCB(void *oldItem, int explicitRequest, int *abort,
11144 void *cbArg);
11145 @@ -1427,6 +1496,11 @@ static void translatePrefFormats(int con
11146 XtFree(TempStringPrefs.smartIndentCommon);
11147 TempStringPrefs.smartIndentCommon = NULL;
11149 + if (TempStringPrefs.matchPattern != NULL) {
11150 + LoadMatchPatternString(TempStringPrefs.matchPattern);
11151 + XtFree(TempStringPrefs.matchPattern);
11152 + TempStringPrefs.matchPattern = NULL;
11155 /* translate the font names into fontLists suitable for the text widget */
11156 font = XLoadQueryFont(TheDisplay, PrefData.fontString);
11157 @@ -1506,6 +1580,7 @@ void SaveNEditPrefs(Widget parent, int q
11158 TempStringPrefs.styles = WriteStylesString();
11159 TempStringPrefs.smartIndent = WriteSmartIndentString();
11160 TempStringPrefs.smartIndentCommon = WriteSmartIndentCommonString();
11161 + TempStringPrefs.matchPattern = WriteMatchPatternString();
11162 strcpy(PrefData.fileVersion, PREF_FILE_VERSION);
11164 if (!SavePreferences(XtDisplay(parent), prefFileName, HeaderText,
11165 @@ -1525,6 +1600,7 @@ void SaveNEditPrefs(Widget parent, int q
11166 XtFree(TempStringPrefs.styles);
11167 XtFree(TempStringPrefs.smartIndent);
11168 XtFree(TempStringPrefs.smartIndentCommon);
11169 + XtFree(TempStringPrefs.matchPattern);
11171 PrefsHaveChanged = False;
11173 @@ -1921,16 +1997,6 @@ int GetPrefShowMatching(void)
11174 return PrefData.showMatchingStyle;
11177 -void SetPrefMatchSyntaxBased(int state)
11179 - setIntPref(&PrefData.matchSyntaxBased, state);
11182 -int GetPrefMatchSyntaxBased(void)
11184 - return PrefData.matchSyntaxBased;
11187 void SetPrefHighlightSyntax(Boolean state)
11189 setIntPref(&PrefData.highlightSyntax, state);
11190 @@ -3480,6 +3546,21 @@ static int lmDeleteConfirmCB(int itemInd
11191 return False;
11194 + /* Pattern Match Feature: don't allow deletion if data will be lost */
11195 + if (LMHasStringMatchTable(LMDialog.languageModeList[itemIndex]->name))
11197 + DialogF(DF_WARN, LMDialog.shell, 1, "Matching Patterns exist",
11198 + "This language mode has matching patterns\n"
11199 + "defined. Please delete the patterns first,\n"
11200 + "in Preferences -> Default Settings ->\n"
11201 + "Show Matching (..) -> Matching Patterns ..,\n"
11202 + "before proceeding here.", "Dismiss");
11203 + return False;
11206 + /* delete "empty" string match table related to language mode to be deleted */
11207 + DeleteStringMatchTable(LMDialog.languageModeList[itemIndex]->name);
11209 return True;
11212 @@ -3500,15 +3581,15 @@ static int updateLMList(void)
11213 return False;
11215 /* Fix up language mode indices in all open windows (which may change
11216 - if the currently selected mode is deleted or has changed position),
11217 - and update word delimiters */
11218 + if the currently selected mode is renamed, deleted or has changed
11219 + position), and update word delimiters */
11220 for (window=WindowList; window!=NULL; window=window->next) {
11221 if (window->languageMode != PLAIN_LANGUAGE_MODE) {
11222 oldLanguageMode = window->languageMode;
11223 oldModeName = LanguageModes[window->languageMode]->name;
11224 window->languageMode = PLAIN_LANGUAGE_MODE;
11225 for (i=0; i<LMDialog.nLanguageModes; i++) {
11226 - if (!strcmp(oldModeName, LMDialog.languageModeList[i]->name)) {
11227 + if (isOldLanguageMode(LMDialog.languageModeList[i]->name, oldModeName)) {
11228 newDelimiters = LMDialog.languageModeList[i]->delimiters;
11229 if (newDelimiters == NULL)
11230 newDelimiters = GetPrefDelimiters();
11231 @@ -3538,6 +3619,7 @@ static int updateLMList(void)
11232 *strchr(LMDialog.languageModeList[i]->name, ':') = '\0';
11233 RenameHighlightPattern(LMDialog.languageModeList[i]->name, newName);
11234 RenameSmartIndentMacros(LMDialog.languageModeList[i]->name, newName);
11235 + RenameStringMatchTable(LMDialog.languageModeList[i]->name, newName);
11236 memmove(LMDialog.languageModeList[i]->name, newName,
11237 strlen(newName) + 1);
11238 ChangeManagedListData(LMDialog.managedListW);
11239 @@ -3555,13 +3637,24 @@ static int updateLMList(void)
11240 user menu items */
11241 UpdateUserMenuInfo();
11243 + /* Pattern Match Feature: assign standard string match table to new
11244 + language modes */
11245 + for (i=0; i<NLanguageModes; i++) {
11246 + if (FindStringMatchTable(LanguageModeName(i)) == NULL)
11247 + AssignStandardStringMatchTable(LanguageModeName(i));
11250 /* Update the menus in the window menu bars and load any needed
11251 - calltips files */
11252 + calltips files and reassign string match tables */
11253 for (window=WindowList; window!=NULL; window=window->next) {
11254 updateLanguageModeSubmenu(window);
11255 if (window->languageMode != PLAIN_LANGUAGE_MODE &&
11256 LanguageModes[window->languageMode]->defTipsFile != NULL)
11257 AddTagsFile(LanguageModes[window->languageMode]->defTipsFile, TIP);
11259 + window->stringMatchTable =
11260 + FindStringMatchTable(LanguageModeName(window->languageMode));
11262 /* cache user menus: Rebuild all user menus of this window */
11263 RebuildAllMenus(window);
11265 @@ -3570,12 +3663,32 @@ static int updateLMList(void)
11266 UpdateLanguageModeMenu();
11267 /* The same for the smart indent macro dialog */
11268 UpdateLangModeMenuSmartIndent();
11269 + /* The same for the match pattern dialog */
11270 + UpdateLanguageModeMenuMatchPattern();
11271 /* Note that preferences have been changed */
11272 MarkPrefsChanged();
11274 return True;
11278 +** Returns true, if the given old language mode name matches the
11279 +** given (new) language mode dialog name.
11281 +static int isOldLanguageMode(const char *lmDialogName, const char *oldModeName)
11283 + char *c = strchr(lmDialogName, ':');
11284 + int isOldMode = !strcmp(oldModeName, lmDialogName);
11286 + if (!isOldMode && c != NULL) {
11287 + *c = '\0';
11288 + isOldMode = !strcmp(lmDialogName, oldModeName);
11289 + *c = ':';
11292 + return isOldMode;
11295 static void *lmGetDisplayedCB(void *oldItem, int explicitRequest, int *abort,
11296 void *cbArg)
11298 @@ -4569,6 +4682,10 @@ static void reapplyLanguageMode(WindowIn
11299 DeleteTagsFile( LanguageModes[oldMode]->defTipsFile, TIP, False );
11302 + /* Pattern Match Feature: Assign the match pattern related to
11303 + the language mode */
11304 + window->stringMatchTable = FindStringMatchTable(LanguageModeName(mode));
11306 /* Set delimiters for all text widgets */
11307 if (mode == PLAIN_LANGUAGE_MODE || LanguageModes[mode]->delimiters == NULL)
11308 delimiters = GetPrefDelimiters();
11309 @@ -5186,14 +5303,31 @@ char *ReadSymbolicFieldTextWidget(Widget
11311 ** Create a pulldown menu pane with the names of the current language modes.
11312 ** XmNuserData for each item contains the language mode name.
11313 +** Pattern Match Feature: if "includePlain" is set, then 1st menu entry
11314 +** holds "PLAIN".
11316 -Widget CreateLanguageModeMenu(Widget parent, XtCallbackProc cbProc, void *cbArg)
11317 +Widget CreateLanguageModeMenu(
11318 + Widget parent,
11319 + XtCallbackProc cbProc,
11320 + void *cbArg,
11321 + int includePlain)
11323 Widget menu, btn;
11324 int i;
11325 XmString s1;
11327 menu = CreatePulldownMenu(parent, "languageModes", NULL, 0);
11329 + if (includePlain) {
11330 + btn = XtVaCreateManagedWidget("languageMode", xmPushButtonGadgetClass,
11331 + menu,
11332 + XmNlabelString, s1=XmStringCreateSimple("PLAIN"),
11333 + XmNmarginHeight, 0,
11334 + XmNuserData, (void *)"PLAIN", NULL);
11335 + XmStringFree(s1);
11336 + XtAddCallback(btn, XmNactivateCallback, cbProc, cbArg);
11339 for (i=0; i<NLanguageModes; i++) {
11340 btn = XtVaCreateManagedWidget("languageMode", xmPushButtonGadgetClass,
11341 menu,
11342 diff --quilt old/source/preferences.h new/source/preferences.h
11343 --- old/source/preferences.h
11344 +++ new/source/preferences.h
11345 @@ -111,8 +111,6 @@ void SetPrefInsertTabs(int state);
11346 int GetPrefInsertTabs(void);
11347 void SetPrefShowMatching(int state);
11348 int GetPrefShowMatching(void);
11349 -void SetPrefMatchSyntaxBased(int state);
11350 -int GetPrefMatchSyntaxBased(void);
11351 void SetPrefHighlightSyntax(Boolean state);
11352 Boolean GetPrefHighlightSyntax(void);
11353 void SetPrefBacklightChars(int state);
11354 @@ -192,7 +190,7 @@ int FindLanguageMode(const char *languag
11355 void UnloadLanguageModeTipsFile(WindowInfo *window);
11356 void DetermineLanguageMode(WindowInfo *window, int forceNewDefaults);
11357 Widget CreateLanguageModeMenu(Widget parent, XtCallbackProc cbProc,
11358 - void *cbArg);
11359 + void *cbArg, int includePlain);
11360 void SetLangModeMenu(Widget optMenu, const char *modeName);
11361 void CreateLanguageModeSubMenu(WindowInfo* window, const Widget parent,
11362 const char* name, const char* label, const char mnemonic);
11363 diff --quilt old/source/search.c new/source/search.c
11364 --- old/source/search.c
11365 +++ new/source/search.c
11366 @@ -85,6 +85,7 @@ static const char CVSID[] = "$Id: search
11367 #include "../debug.h"
11368 #endif
11370 +#include "patternMatch.h"
11372 int NHist = 0;
11374 @@ -173,6 +174,7 @@ static void checkMultiReplaceListForDoom
11375 WindowInfo* doomedWindow);
11376 static void removeDoomedWindowFromList(WindowInfo* window, int index);
11377 static void unmanageReplaceDialogs(const WindowInfo *window);
11378 +static int getPosForMatchingCharacter(WindowInfo *window);
11379 static void flashTimeoutProc(XtPointer clientData, XtIntervalId *id);
11380 static void eraseFlash(WindowInfo *window);
11381 static int getReplaceDlogInfo(WindowInfo *window, int *direction,
11382 @@ -213,9 +215,6 @@ static void resetReplaceTabGroup(WindowI
11383 static int searchMatchesSelection(WindowInfo *window, const char *searchString,
11384 int searchType, int *left, int *right, int *searchExtentBW,
11385 int *searchExtentFW);
11386 -static int findMatchingChar(WindowInfo *window, char toMatch,
11387 - void *toMatchStyle, int charPos, int startLimit, int endLimit,
11388 - int *matchPos);
11389 static Boolean replaceUsingRE(const char* searchStr, const char* replaceStr,
11390 const char* sourceStr, int beginPos, char* destStr, int maxDestLen,
11391 int prevChar, const char* delimiters, int defaultFlags);
11392 @@ -253,24 +252,6 @@ typedef struct _charMatchTable {
11393 char direction;
11394 } charMatchTable;
11396 -#define N_MATCH_CHARS 13
11397 -#define N_FLASH_CHARS 6
11398 -static charMatchTable MatchingChars[N_MATCH_CHARS] = {
11399 - {'{', '}', SEARCH_FORWARD},
11400 - {'}', '{', SEARCH_BACKWARD},
11401 - {'(', ')', SEARCH_FORWARD},
11402 - {')', '(', SEARCH_BACKWARD},
11403 - {'[', ']', SEARCH_FORWARD},
11404 - {']', '[', SEARCH_BACKWARD},
11405 - {'<', '>', SEARCH_FORWARD},
11406 - {'>', '<', SEARCH_BACKWARD},
11407 - {'/', '/', SEARCH_FORWARD},
11408 - {'"', '"', SEARCH_FORWARD},
11409 - {'\'', '\'', SEARCH_FORWARD},
11410 - {'`', '`', SEARCH_FORWARD},
11411 - {'\\', '\\', SEARCH_FORWARD},
11415 ** Definitions for the search method strings, used as arguments for
11416 ** macro search subroutines and search action routines
11417 @@ -3342,18 +3323,18 @@ static void iSearchTextKeyEH(Widget w, W
11421 -** Check the character before the insertion cursor of textW and flash
11422 -** matching parenthesis, brackets, or braces, by temporarily highlighting
11423 -** the matching character (a timer procedure is scheduled for removing the
11424 -** highlights)
11425 +** Check the characters before the insertion cursor of textW and flash
11426 +** matching patterns (parenthesis e.g. brackets, braces ..) by temporarily
11427 +** highlighting matching characters (a timer procedure is scheduled for
11428 +** removing the highlights)
11430 void FlashMatching(WindowInfo *window, Widget textW)
11432 - char c;
11433 - void *style;
11434 - int pos, matchIndex;
11435 - int startPos, endPos, searchPos, matchPos;
11436 + int pos;
11437 + int direction;
11438 + int startPos, endPos, matchPos, matchLen;
11439 int constrain;
11440 + MatchingType matchingType;
11442 /* if a marker is already drawn, erase it and cancel the timeout */
11443 if (window->flashTimeoutID != 0) {
11444 @@ -3371,48 +3352,43 @@ void FlashMatching(WindowInfo *window, W
11445 if (window->buffer->primary.selected)
11446 return;
11448 - /* get the character to match and the position to start from */
11449 - pos = TextGetCursorPos(textW) - 1;
11450 + /* get the position to start from */
11451 + pos = TextGetCursorPos(textW);
11452 if (pos < 0)
11453 return;
11454 - c = BufGetCharacter(window->buffer, pos);
11455 - style = GetHighlightInfo(window, pos);
11457 - /* is the character one we want to flash? */
11458 - for (matchIndex = 0; matchIndex<N_FLASH_CHARS; matchIndex++) {
11459 - if (MatchingChars[matchIndex].c == c)
11460 - break;
11462 - if (matchIndex == N_FLASH_CHARS)
11463 - return;
11465 /* constrain the search to visible text only when in single-pane mode
11466 AND using delimiter flashing (otherwise search the whole buffer) */
11467 constrain = ((window->nPanes == 0) &&
11468 (window->showMatchingStyle == FLASH_DELIMIT));
11470 - if (MatchingChars[matchIndex].direction == SEARCH_BACKWARD) {
11471 startPos = constrain ? TextFirstVisiblePos(textW) : 0;
11472 - endPos = pos;
11473 - searchPos = endPos;
11474 - } else {
11475 - startPos = pos;
11476 endPos = constrain ? TextLastVisiblePos(textW) :
11477 window->buffer->length;
11478 - searchPos = startPos;
11480 + /* cursor pos. must be between start / end pos. */
11481 + if (pos < startPos || pos > endPos)
11482 + return;
11484 + /* Pattern Match Feature: determine matching type
11485 + (here: flash delimiter or range) */
11486 + if (window->showMatchingStyle == FLASH_DELIMIT) {
11487 + matchingType = MT_FLASH_DELIMIT;
11488 + } else {
11489 + matchingType = MT_FLASH_RANGE;
11492 - /* do the search */
11493 - if (!findMatchingChar(window, c, style, searchPos, startPos, endPos,
11494 - &matchPos))
11495 + /* Pattern Match Feature: do the search */
11496 + if (!FindMatchingString(window, matchingType, &pos, startPos, endPos,
11497 + &matchPos, &matchLen, &direction))
11498 return;
11500 if (window->showMatchingStyle == FLASH_DELIMIT) {
11501 - /* Highlight either the matching character ... */
11502 - BufHighlight(window->buffer, matchPos, matchPos+1);
11503 + /* Highlight either the matching characters ... */
11504 + BufHighlight(window->buffer, matchPos, matchPos + matchLen);
11505 } else {
11506 /* ... or the whole range. */
11507 - if (MatchingChars[matchIndex].direction == SEARCH_BACKWARD) {
11508 + if (direction == SEARCH_BACKWARD) {
11509 BufHighlight(window->buffer, matchPos, pos+1);
11510 } else {
11511 BufHighlight(window->buffer, matchPos+1, pos);
11512 @@ -3426,38 +3402,46 @@ void FlashMatching(WindowInfo *window, W
11513 window->flashPos = matchPos;
11516 -void SelectToMatchingCharacter(WindowInfo *window)
11518 +** Pattern Match Feature:
11519 +** get position of the character to match from the selection, or
11520 +** the character before the insert point if nothing is selected.
11523 +static int getPosForMatchingCharacter(WindowInfo *window)
11525 + int pos;
11526 int selStart, selEnd;
11527 - int startPos, endPos, matchPos;
11528 textBuffer *buf = window->buffer;
11530 - /* get the character to match and its position from the selection, or
11531 - the character before the insert point if nothing is selected.
11532 - Give up if too many characters are selected */
11533 - if (!GetSimpleSelection(buf, &selStart, &selEnd)) {
11534 - selEnd = TextGetCursorPos(window->lastFocus);
11535 - if (window->overstrike)
11536 - selEnd += 1;
11537 - selStart = selEnd - 1;
11538 - if (selStart < 0) {
11539 - XBell(TheDisplay, 0);
11540 - return;
11542 + if (GetSimpleSelection(buf, &selStart, &selEnd)) {
11543 + pos = selEnd;
11545 - if ((selEnd - selStart) != 1) {
11546 - XBell(TheDisplay, 0);
11547 - return;
11548 + else {
11549 + pos = TextGetCursorPos(window->lastFocus);
11553 + return pos;
11556 +void SelectToMatchingCharacter(WindowInfo *window)
11558 + int pos;
11559 + int startPos, endPos, matchPos, matchLen;
11560 + int direction;
11561 + textBuffer *buf = window->buffer;
11563 + /* Pattern Match Feature: get position of the character to match */
11564 + pos = getPosForMatchingCharacter(window);
11566 /* Search for it in the buffer */
11567 - if (!findMatchingChar(window, BufGetCharacter(buf, selStart),
11568 - GetHighlightInfo(window, selStart), selStart, 0, buf->length, &matchPos)) {
11569 + if (!FindMatchingString(window, MT_SELECT, &pos, 0,
11570 + buf->length, &matchPos, &matchLen, &direction)) {
11571 XBell(TheDisplay, 0);
11572 return;
11574 - startPos = (matchPos > selStart) ? selStart : matchPos;
11575 - endPos = (matchPos > selStart) ? matchPos : selStart;
11576 + startPos = (matchPos > pos) ? pos : matchPos;
11577 + endPos = (matchPos > pos) ? matchPos : pos;
11579 /* temporarily shut off autoShowInsertPos before setting the cursor
11580 position so MakeSelectionVisible gets a chance to place the cursor
11581 @@ -3473,32 +3457,17 @@ void SelectToMatchingCharacter(WindowInf
11583 void GotoMatchingCharacter(WindowInfo *window)
11585 - int selStart, selEnd;
11586 - int matchPos;
11587 + int pos;
11588 + int matchPos, matchLen;
11589 + int direction;
11590 textBuffer *buf = window->buffer;
11592 - /* get the character to match and its position from the selection, or
11593 - the character before the insert point if nothing is selected.
11594 - Give up if too many characters are selected */
11595 - if (!GetSimpleSelection(buf, &selStart, &selEnd)) {
11596 - selEnd = TextGetCursorPos(window->lastFocus);
11597 - if (window->overstrike)
11598 - selEnd += 1;
11599 - selStart = selEnd - 1;
11600 - if (selStart < 0) {
11601 - XBell(TheDisplay, 0);
11602 - return;
11605 - if ((selEnd - selStart) != 1) {
11606 - XBell(TheDisplay, 0);
11607 - return;
11609 + /* Pattern Match Feature: get position of the character to match */
11610 + pos = getPosForMatchingCharacter(window);
11612 /* Search for it in the buffer */
11613 - if (!findMatchingChar(window, BufGetCharacter(buf, selStart),
11614 - GetHighlightInfo(window, selStart), selStart, 0,
11615 - buf->length, &matchPos)) {
11616 + if (!FindMatchingString(window, MT_GOTO, &pos, 0,
11617 + buf->length, &matchPos, &matchLen, &direction)) {
11618 XBell(TheDisplay, 0);
11619 return;
11621 @@ -3509,77 +3478,11 @@ void GotoMatchingCharacter(WindowInfo *w
11622 be automatically scrolled on screen and MakeSelectionVisible would do
11623 nothing) */
11624 XtVaSetValues(window->lastFocus, textNautoShowInsertPos, False, NULL);
11625 - TextSetCursorPos(window->lastFocus, matchPos+1);
11626 + TextSetCursorPos(window->lastFocus, matchPos);
11627 MakeSelectionVisible(window, window->lastFocus);
11628 XtVaSetValues(window->lastFocus, textNautoShowInsertPos, True, NULL);
11631 -static int findMatchingChar(WindowInfo *window, char toMatch,
11632 - void* styleToMatch, int charPos, int startLimit, int endLimit,
11633 - int *matchPos)
11635 - int nestDepth, matchIndex, direction, beginPos, pos;
11636 - char matchChar, c;
11637 - void *style = NULL;
11638 - textBuffer *buf = window->buffer;
11639 - int matchSyntaxBased = window->matchSyntaxBased;
11641 - /* If we don't match syntax based, fake a matching style. */
11642 - if (!matchSyntaxBased) style = styleToMatch;
11644 - /* Look up the matching character and match direction */
11645 - for (matchIndex = 0; matchIndex<N_MATCH_CHARS; matchIndex++) {
11646 - if (MatchingChars[matchIndex].c == toMatch)
11647 - break;
11649 - if (matchIndex == N_MATCH_CHARS)
11650 - return FALSE;
11651 - matchChar = MatchingChars[matchIndex].match;
11652 - direction = MatchingChars[matchIndex].direction;
11654 - /* find it in the buffer */
11655 - beginPos = (direction==SEARCH_FORWARD) ? charPos+1 : charPos-1;
11656 - nestDepth = 1;
11657 - if (direction == SEARCH_FORWARD) {
11658 - for (pos=beginPos; pos<endLimit; pos++) {
11659 - c=BufGetCharacter(buf, pos);
11660 - if (c == matchChar) {
11661 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11662 - if (style == styleToMatch) {
11663 - nestDepth--;
11664 - if (nestDepth == 0) {
11665 - *matchPos = pos;
11666 - return TRUE;
11669 - } else if (c == toMatch) {
11670 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11671 - if (style == styleToMatch)
11672 - nestDepth++;
11675 - } else { /* SEARCH_BACKWARD */
11676 - for (pos=beginPos; pos>=startLimit; pos--) {
11677 - c=BufGetCharacter(buf, pos);
11678 - if (c == matchChar) {
11679 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11680 - if (style == styleToMatch) {
11681 - nestDepth--;
11682 - if (nestDepth == 0) {
11683 - *matchPos = pos;
11684 - return TRUE;
11687 - } else if (c == toMatch) {
11688 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11689 - if (style == styleToMatch)
11690 - nestDepth++;
11694 - return FALSE;
11698 ** Xt timer procedure for erasing the matching parenthesis marker.
11700 diff --quilt old/source/smartIndent.c new/source/smartIndent.c
11701 --- old/source/smartIndent.c
11702 +++ new/source/smartIndent.c
11703 @@ -983,9 +983,9 @@ void EditSmartIndentMacros(WindowInfo *w
11704 XmNtopPosition, 1,
11705 XmNrightAttachment, XmATTACH_POSITION,
11706 XmNrightPosition, 99, NULL);
11708 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
11709 SmartIndentDialog.lmPulldown = CreateLanguageModeMenu(lmForm, langModeCB,
11710 - NULL);
11711 + NULL, FALSE);
11712 n = 0;
11713 XtSetArg(args[n], XmNspacing, 0); n++;
11714 XtSetArg(args[n], XmNmarginWidth, 0); n++;
11715 @@ -2155,8 +2155,9 @@ void UpdateLangModeMenuSmartIndent(void)
11716 return;
11718 oldMenu = SmartIndentDialog.lmPulldown;
11719 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
11720 SmartIndentDialog.lmPulldown = CreateLanguageModeMenu(
11721 - XtParent(XtParent(oldMenu)), langModeCB, NULL);
11722 + XtParent(XtParent(oldMenu)), langModeCB, NULL, FALSE);
11723 XtVaSetValues(XmOptionButtonGadget(SmartIndentDialog.lmOptMenu),
11724 XmNsubMenuId, SmartIndentDialog.lmPulldown, NULL);
11725 SetLangModeMenu(SmartIndentDialog.lmOptMenu, SmartIndentDialog.langModeName);
11726 diff --quilt old/source/window.c new/source/window.c
11727 --- old/source/window.c
11728 +++ new/source/window.c
11729 @@ -55,6 +55,7 @@ static const char CVSID[] = "$Id: window
11730 #include "windowTitle.h"
11731 #include "interpret.h"
11732 #include "rangeset.h"
11733 +#include "patternMatchData.h"
11734 #include "../util/clearcase.h"
11735 #include "../util/misc.h"
11736 #include "../util/fileUtils.h"
11737 @@ -277,7 +278,6 @@ WindowInfo *CreateWindow(const char *nam
11738 window->showWrapMargin = GetPrefShowWrapMargin();
11739 window->overstrike = False;
11740 window->showMatchingStyle = GetPrefShowMatching();
11741 - window->matchSyntaxBased = GetPrefMatchSyntaxBased();
11742 window->showStats = GetPrefStatsLine();
11743 window->showISearchLine = GetPrefISearchLine();
11744 window->showLineNumbers = GetPrefLineNums();
11745 @@ -316,6 +316,10 @@ WindowInfo *CreateWindow(const char *nam
11746 window->macroCmdData = NULL;
11747 window->smartIndentData = NULL;
11748 window->languageMode = PLAIN_LANGUAGE_MODE;
11750 + /* Pattern Match Feature: assign "PLAIN" string match table*/
11751 + window->stringMatchTable = FindStringMatchTable(NULL);
11753 window->iSearchHistIndex = 0;
11754 window->iSearchStartPos = -1;
11755 window->replaceLastRegexCase = TRUE;
11756 @@ -3450,7 +3454,6 @@ WindowInfo* CreateDocument(WindowInfo* s
11757 window->showWrapMargin = GetPrefShowWrapMargin();
11758 window->overstrike = False;
11759 window->showMatchingStyle = GetPrefShowMatching();
11760 - window->matchSyntaxBased = GetPrefMatchSyntaxBased();
11761 window->highlightSyntax = GetPrefHighlightSyntax();
11762 window->backlightCharTypes = NULL;
11763 window->backlightChars = GetPrefBacklightChars();
11764 @@ -3485,6 +3488,12 @@ WindowInfo* CreateDocument(WindowInfo* s
11765 window->macroCmdData = NULL;
11766 window->smartIndentData = NULL;
11767 window->languageMode = PLAIN_LANGUAGE_MODE;
11769 + /*
11770 + * Pattern Match Feature:
11771 + */
11772 + window->stringMatchTable = FindStringMatchTable(NULL);
11774 window->iSearchHistIndex = 0;
11775 window->iSearchStartPos = -1;
11776 window->replaceLastRegexCase = TRUE;
11777 @@ -3882,7 +3891,6 @@ void RefreshMenuToggleStates(WindowInfo
11778 #endif
11779 XmToggleButtonSetState(window->autoSaveItem, window->autoSave, False);
11780 XmToggleButtonSetState(window->overtypeModeItem, window->overstrike, False);
11781 - XmToggleButtonSetState(window->matchSyntaxBasedItem, window->matchSyntaxBased, False);
11782 XmToggleButtonSetState(window->readOnlyItem, IS_USER_LOCKED(window->lockReasons), False);
11783 XmToggleButtonSetState(window->transientItem, window->transient, False);
11785 @@ -4446,6 +4454,9 @@ static void cloneDocument(WindowInfo *wi
11786 if (window->highlightSyntax)
11787 StartHighlighting(window, False);
11789 + /* recycle the pattern match data */
11790 + window->stringMatchTable = orgWin->stringMatchTable;
11792 /* copy states of original document */
11793 window->filenameSet = orgWin->filenameSet;
11794 window->fileFormat = orgWin->fileFormat;
11795 @@ -4464,7 +4475,6 @@ static void cloneDocument(WindowInfo *wi
11796 window->wrapMode = orgWin->wrapMode;
11797 SetOverstrike(window, orgWin->overstrike);
11798 window->showMatchingStyle = orgWin->showMatchingStyle;
11799 - window->matchSyntaxBased = orgWin->matchSyntaxBased;
11800 #if 0
11801 window->showStats = orgWin->showStats;
11802 window->showISearchLine = orgWin->showISearchLine;