Allow '>' and '@' to appear in menu items
[nedit-bw.git] / matching_patterns.patch
blobf889e2404465e0b76d6d979ba6b80e7fa14923f6
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/built-ins.h | 2
58 source/highlightData.c | 13
59 source/macro.c | 99
60 source/menu.c | 63
61 source/nedit.h | 6
62 source/patternMatch.c | 2202 ++++++++++++
63 source/patternMatch.h | 170
64 source/patternMatchData.c | 7780 +++++++++++++++++++++++++++++++++++++++++++
65 source/patternMatchData.h | 24
66 source/preferences.c | 170
67 source/preferences.h | 4
68 source/search.c | 231 -
69 source/smartIndent.c | 7
70 source/window.c | 18
71 17 files changed, 10769 insertions(+), 295 deletions(-)
73 diff --quilt old/doc/help.etx new/doc/help.etx
74 --- old/doc/help.etx
75 +++ new/doc/help.etx
76 @@ -866,8 +866,9 @@ Programming with NEdit
77 Though general in appearance, NEdit has many features intended specifically
78 for programmers. Major programming-related topics are listed in separate
79 sections under the heading: "Features for Programming": Syntax_Highlighting_,
80 - Tabs/Emulated_Tabs_, Finding_Declarations_(ctags)_, Calltips_, and
81 - Auto/Smart_Indent_. Minor topics related to programming are discussed below:
82 + Tabs/Emulated_Tabs_, Matching_Parentheses_, Finding_Declarations_(ctags)_,
83 + Calltips_, and Auto/Smart_Indent_. Minor topics related to programming are
84 + discussed below:
86 3>Language Modes
88 @@ -925,26 +926,6 @@ Programming with NEdit
89 a column on the current line just leave out the line number. (e.g. Enter
90 ",45" to go the column 45 on the current line.)
92 -3>Matching Parentheses
94 - To help you inspect nested parentheses, brackets, braces, quotes, and other
95 - characters, NEdit has both an automatic parenthesis matching mode, and a Goto
96 - Matching command. Automatic parenthesis matching is activated when you type,
97 - or move the insertion cursor after a parenthesis, bracket, or brace. It
98 - momentarily highlights either the opposite character ('Delimiter') or the
99 - entire expression ('Range') when the opposite character is visible in the
100 - window. To find a matching character anywhere in the file, select it or
101 - position the cursor after it, and choose Goto Matching from the Search menu.
102 - If the character matches itself, such as a quote or slash, select the first
103 - character of the pair. NEdit will match {, (, [, <, ", ', `, /, and \.
104 - Holding the Shift key while typing the accelerator key (Shift+Ctrl+M, by
105 - default), will select all of the text between the matching characters.
107 - When syntax highlighting is enabled, the matching routines can optionally
108 - make use of the syntax information for improved accuracy. In that case,
109 - a brace inside a highlighted string will not match a brace inside a comment,
110 - for instance.
112 3>Opening Included Files
114 The Open Selected command in the File menu understands the C preprocessor's
115 @@ -1222,6 +1203,39 @@ Syntax Highlighting
116 possible, but unlikely if you are only using the built-in patterns.
117 ----------------------------------------------------------------------
119 +Matching Parentheses
120 +--------------------
122 +3>Matching Parentheses (Patterns)
124 + To help you inspect nested parentheses (e.g. brackets, braces, quotes
125 + etc.) or nested constructs (e.g. "begin" .. "end"), NEdit has both an
126 + automatic parenthesis matching mode, and a Goto Matching command.
128 + A matching pattern can be a single character (like '(', ')'), a literal
129 + string (like '#ifdef', '#endif') or a regular expression (like
130 + '\</.*\>').
132 + Automatic parenthesis matching is activated when you type, or move the
133 + insertion cursor after a parenthesis, bracket, or brace. It momentarily
134 + highlights either the opposite pattern ('Delimiter') or the entire expression
135 + ('Range') when the opposite pattern is visible in the window. To find a
136 + matching pattern anywhere in the file, select it or position the cursor after
137 + it, and choose Goto Matching from the Search menu. If the pattern matches
138 + itself, such as a quote or slash, select the first pattern of the pair.
139 + Holding the Shift key while typing the accelerator key (Shift+Ctrl+M, by
140 + default), will select all of the text between the matching patterns.
142 + When syntax highlighting is enabled, the matching routines can optionally
143 + make use of the syntax information for improved accuracy. In that case,
144 + a brace inside a highlighted string will not match a brace inside a comment,
145 + for instance.
147 + Matching patterns are language dependent. Matching patterns can be
148 + configured by the user. If no matching patterns are available for the
149 + language that you want to use, you can create new patterns relatively quickly.
150 + The Help section "Matching_Patterns_" under "Customizing", has details.
152 Finding Declarations (ctags)
153 ----------------------------
155 @@ -2580,9 +2594,6 @@ Macro Subroutines
156 Contains the current preference for showing matching pairs,
157 such as "[]" and "{}" pairs. Can be "off", "delimiter", or "range".
159 -**$match_syntax_based**
160 - Whether pair matching should use syntax information, if available.
162 **$statistics_line**
163 Has a value of 1 if the statistics line is shown, otherwise 0.
165 @@ -2697,6 +2708,15 @@ Macro Subroutines
166 Returns the single character at the position
167 indicated by the first argument to the routine from the current window.
169 +**get_matching( position )**
170 + Find a matching pattern string related to the given position.
171 + Returns info about matching pattern within an array. The array has
172 + the following keys: **pos** (position of the first character of the
173 + matching pattern), **len** (length of the matching pattern), **direction**
174 + (direction where the matching pattern was found: ~0~ = forward;
175 + ~1~ = backward). If no matching pattern was found, then array element
176 + of **pos** holds ~-1~, **len** holds ~0~ and **direction** holds ~-1~.
178 **get_range( start, end )**
179 Returns the text between a starting and ending position from the current
180 window.
181 @@ -3406,9 +3426,6 @@ Action Routines
182 **set_show_matching( "off" | "delimiter" | "range" )**
183 Set show matching (...) mode for the current window.
185 -**set_match_syntax_based( [0 | 1] )**
186 - Set whether matching should be syntax based for the current window.
188 **set_statistics_line( [0 | 1] )**
189 Show or hide the statistics line for the current window.
190 A value of 0 turns it off and a value of 1 turns it on.
191 @@ -3940,10 +3957,6 @@ Preferences
192 matching delimiter, while Range highlights the whole range of text between
193 the matching delimiters.
195 - Optionally, the matching can make use of syntax information if syntax
196 - highlighting is enabled. Alternatively, the matching is purely character
197 - based. In general, syntax based matching results in fewer false matches.
199 **Overtype**
200 In overtype mode, new characters entered replace the characters in front of
201 the insertion cursor, rather than being inserted before them.
202 @@ -5049,6 +5062,185 @@ Smart Indent Macros
203 keystroke typed, so if you try to get too fancy, you may degrade performance.
204 ----------------------------------------------------------------------
206 +Matching Patterns
207 +-----------------
209 +3>Writing Matching Pattern Sets
211 + Matching Patterns Sets are groups of single characters (like '(', ')'),
212 + literal strings (like '#ifdef', '#endif') or a regular expressions (like
213 + '\</.*\>'), which match to each other.
215 + Examples: An open bracket '(' belongs a closing one ')'.
216 + Or: '#ifdef'(start), '#ifndef'(alternative start), '#ifndef' (another
217 + alternative start),'#elif' (optional), '#else' (optional), '#endif' (end)
218 + define a "#ifdef statement matching pattern".
220 + "Opposite pattern highlighting" or "Goto Matching" features are implemented
221 + in NEdit using this matching pattern sets (see Matching_Parentheses_ under
222 + the heading of Features for Programming).
224 + During definition of a new language mode a standard matching pattern set
225 + is assigned to this new language mode.
227 + To modify a matching pattern set, select "Matching Patterns ..." from
228 + "Show Matching (..)" sub-section of the "Default Settings" sub-menu
229 + of the "Preferences" menu.
231 + A matching pattern set is a collection of matching patterns.
233 + A matching pattern usually consists out of string patterns.
235 + The name of a matching pattern set needs to be defined within field "Matching
236 + Pattern Name".
238 +4>Attributes of matching pattern
240 + A matching pattern holds two types of attributes:
242 +* "Matching Pattern Type" and
243 +* "Global Attributes"
245 + The matching pattern type specifies the kind of the matching pattern
246 + entry:
248 +* "Individual" or
249 +* "Sub-pattern" or
250 +* "Context group"
252 + Each matching pattern can be defined as "Individual" or as "Sub-pattern".
253 + A "Sub-pattern" belongs to a context group. A context group is simply a
254 + collection of sub-patterns.
256 + During search for a corresponding pattern, an "Individual" matching pattern
257 + does not care about nesting of other matching patterns.
259 + If a matching pattern out of a "Context group" is searched, then all
260 + sub-pattern sets defined in this group are taken into account during the
261 + search.
263 + In fact, "Individual" matching pattern search is faster than "Context group" /
264 + "Sub-pattern" search. "Context group" / "Sub-pattern" search results in fewer
265 + false matches.
267 + To define a context group, set "Matching Pattern Type" to "Context group".
268 + Select out of "Sub-Pattern Name" pop-up field all sub-patterns, which
269 + should be placed into this group. **Note**: all "Sub-pattern" used by a context
270 + group must be defined **before** the context group itself.
272 + "Global Attributes" of a matching pattern are
274 +* "Skip content between start / end pattern"
275 +* "Flash matching pattern"
276 +* "Syntax based"
278 + If "Skip content between start / end pattern" is checked, then all text
279 + between the first / last string pattern of the related matching pattern is
280 + not scanned for other string patterns. This is useful for specifying comments.
282 + "Flash matching pattern" indicates, if the string patterns are flashed during
283 + typing. If not checked, then only the "Goto Matching" feature works for the
284 + related matching pattern. Note: if lots of "Flash matching pattern" are
285 + specified, then this may slow down the performance of NEdit: after each
286 + character typed all "Flash matching pattern" are scanned for being
287 + applicable ...
289 + "Syntax based" defines, if the matching pattern can make use of syntax
290 + information if syntax highlighting is enabled. Alternatively, the matching is
291 + purely character based. In general, syntax based matching results in fewer
292 + false matches.
294 +4>Content of matching pattern
296 + An "Individual" pattern or a "Sub-pattern" may consist out of only one string
297 + pattern (e.g. double quotes '"'). Such a pattern is called "mono pattern".
298 + You can imagine, that a match for a mono pattern is hard to find. A matching
299 + mono pattern search is always started in forward direction. If no match is
300 + found in forward direction, a backward search is started. If the "Global
301 + Attribute" "Syntax based" is selected for a mono pattern, then the character
302 + before / after the match is checked to have the same highlighting style than
303 + the pattern itself. This may help to determine the correct match for a mono
304 + pattern.
306 + Usually a matching pattern holds two string patterns (e.g. 'begin' and
307 + 'end'). One ('begin') is the start pattern. The other one ('end') is the
308 + end pattern. If the cursor is located behind the start pattern, then a
309 + corresponding end pattern is searched (in forward direction). If the
310 + cursor is located behind the end pattern, then a start pattern is search
311 + (in backward direction):
313 +! +--> start ---> end --+
314 +! +-----------<---------+
316 + Alternative start / end patterns can be defined. In this case one of the
317 + start / end patterns must be in front of the cursor to detect one of the
318 + related end / start patterns:
320 +! +-> start1 -+ +-> end1 -+
321 +! +-+-> start2 -+---+ +--+
322 +! + +-> start3 -+ +-> end2 -+ |
323 +! +---------------<-------------+
325 + At least also "middle" patterns can be defined (e.g. middle patterns
326 + 'elif' or 'else'). If the cursor is located behind a middle pattern then a
327 + next middle pattern or the end pattern is searched in forward direction:
329 +! +-----<-----+
330 +! +--> start -+-> middle -+-> end --+
331 +! +-----------<---------------------+
333 +4>String pattern
335 + A string pattern holds three attributes:
337 +* "String Pattern Type"
338 +* "Word Boundary"
339 +* "String Attributes"
341 + String Pattern Type specifies if the related string pattern is
342 + a "start", middle, or "end" pattern (see above).
344 + Word boundary defines, if before / after a string pattern a delimiter must be
345 + located ("Both" = pattern is framed by delimiters. "Left" = before pattern
346 + must be a delimiter. "Right" = after pattern must be a delimiter. "None" =
347 + there must be no delimiter before or after pattern).
349 + There are two "String Attributes":
351 +* "Case Sensitive"
352 +* "Regular Expression"
354 + If "Case Sensitive" is checked (= default), then the matching pattern search
355 + concerning this string pattern differs between upper / lower case of the
356 + characters. If "Case Sensitive" is not set, then the case of the checked
357 + characters is not considered.
359 + "Regular Expression" indicates, that string pattern is treated as
360 + regular expression (if "Regular Expression" is checked) or as literal
361 + string (if "Regular Expression" is not checked).
363 +4>Regular Expression String Pattern
365 + Syntax of regular expression is described by NEdit Help menu item
366 + Regular_Expressions_. Following deviations from this syntax are
367 + existing concerning string patterns:
369 +5>Capturing Parentheses
371 + Capturing Parentheses inside string patterns are of the form `(*n<regex>)',
372 + where n = 1 .. 9. Standard "capturing parentheses" of form `(<regex>)' are
373 + treated as "non-capturing parentheses" by the matching pattern feature.
374 + "n" defines the **global** backreference number, which can be used inside any string
375 + pattern of the same matching pattern (= set of string patterns). So
376 + matching patterns like "\<(*1[^/>])\>" (start string pattern) and "\</\1\>"
377 + (end string pattern) are possible. This matching pattern will match e.g.
378 + <body> .. </body> but will not match <body> .. </head>.
380 +5>Non-Capturing Parentheses
382 + As described above: parentheses constructs like (<regex>) are treated
383 + as `(?:<regex>)' (non-capturing parentheses) by the matching pattern feature.
385 NEdit Command Line
386 ------------------
388 @@ -6079,6 +6271,7 @@ Problems/Defects
389 .. Menu: Tabs/Emulated Tabs # tabs
390 .. Menu: Auto/Smart Indent # indent
391 .. Menu: Syntax Highlighting # syntax
392 +.. Menu: Matching Parentheses # pattern_matching
393 .. Menu: Finding Declarations (ctags) # tags
394 .. Menu: Calltips # calltips
396 @@ -6106,6 +6299,7 @@ Problems/Defects
397 .. Menu: Key Binding # binding
398 .. Menu: Highlighting Patterns # patterns
399 .. Menu: Smart Indent Macros # smart_indent
400 +.. Menu: Matching Patterns # matching_patterns
402 .. Menu: NEdit Command Line # command_line
403 .. Menu: Client/Server Mode # server
404 diff --quilt old/source/Makefile.common new/source/Makefile.common
405 --- old/source/Makefile.common
406 +++ new/source/Makefile.common
407 @@ -7,7 +7,8 @@ OBJS = nedit.o file.o menu.o window.o se
408 help.o preferences.o tags.o userCmds.o shell.o regularExp.o macro.o \
409 text.o textSel.o textDisp.o textBuf.o textDrag.o server.o highlight.o \
410 highlightData.o interpret.o parse.o smartIndent.o regexConvert.o \
411 - rbTree.o windowTitle.o calltips.o server_common.o rangeset.o
412 + rbTree.o windowTitle.o calltips.o server_common.o rangeset.o \
413 + patternMatch.o patternMatchData.o
415 XLTLIB = ../Xlt/libXlt.a
416 XMLLIB = ../Microline/XmL/libXmL.a
417 @@ -37,6 +38,9 @@ smartIndent.o: smartIndent.c
418 highlightData.o: highlightData.c
419 $(CC) $(CFLAGS) $(BIGGER_STRINGS) -c highlightData.c -o $@
421 +patternMatchData.o: patternMatchData.c
422 + $(CC) $(CFLAGS) $(BIGGER_STRINGS) -c patternMatchData.c -o $@
424 clean:
425 rm -f $(OBJS) nedit nc nc.o parse.c parse_noyacc.c linkdate.o
427 diff --quilt old/source/Makefile.dependencies new/source/Makefile.dependencies
428 --- old/source/Makefile.dependencies
429 +++ new/source/Makefile.dependencies
430 @@ -85,3 +85,14 @@ windowTitle.o: windowTitle.c windowTitle
431 ../util/DialogF.h ../util/utils.h ../util/fileUtils.h \
432 ../util/clearcase.h
433 parse.c: parse.h textBuf.h nedit.h rbTree.h interpret.h ops.h
434 +patternMatch.o: patternMatch.c regularExp.h \
435 + textBuf.h search.h window.h preferences.h highlight.h\
436 + patternMatch.h patternMatchData.h
437 +patternMatchData.o: patternMatchData.c ../util/DialogF.h ../util/misc.h \
438 + ../util/managedList.h regularExp.h textBuf.h nedit.h window.h \
439 + preferences.h help.h file.h textP.h patternMatch.h patternMatchData.h
440 +macro.o: patternMatch.h regularExp.h
441 +menu.o: patternMatchData.h
442 +preferences.o: patternMatchData.h
443 +search.o: patternMatch.h
444 +window.o: patternMatchData.h
445 diff --quilt old/source/highlightData.c new/source/highlightData.c
446 --- old/source/highlightData.c
447 +++ new/source/highlightData.c
448 @@ -551,7 +551,7 @@ static char *DefaultPatternSets[] = {
449 Built-in Misc Vars:\"(?<!\\Y)\\$(?:active_pane|calltip_ID|column|cursor|display_width|empty_array|file_name|file_path|language_mode|line|locked|max_font_width|min_font_width|modified|n_display_lines|n_panes|rangeset_list|read_only|selection_(?:start|end|left|right)|server_name|text_length|top_line|transient|VERSION|NEDIT_HOME)>\":::Identifier::\n\
450 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\
451 Built-in Special Vars:\"(?<!\\Y)\\$(?:args|[1-9]|list_dialog_button|n_args|read_status|search_end|shell_cmd_status|string_dialog_button|sub_sep)>\":::String1::\n\
452 - 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\
453 + 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\
454 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\
455 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\
456 Macro Hooks:\"<(?:(?:pre|post)_(?:open|save)|cursor_moved|modified|(?:losing_)?focus)_hook(?=\\s*\\()\":::Subroutine1::\n\
457 @@ -2346,8 +2346,9 @@ void EditHighlightPatterns(WindowInfo *w
458 XmNrightPosition, 99,
459 NULL);
461 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
462 HighlightDialog.lmPulldown = CreateLanguageModeMenu(lmForm, langModeCB,
463 - NULL);
464 + NULL, FALSE);
465 n = 0;
466 XtSetArg(args[n], XmNspacing, 0); n++;
467 XtSetArg(args[n], XmNmarginWidth, 0); n++;
468 @@ -2881,8 +2882,9 @@ void UpdateLanguageModeMenu(void)
469 return;
471 oldMenu = HighlightDialog.lmPulldown;
472 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
473 HighlightDialog.lmPulldown = CreateLanguageModeMenu(
474 - XtParent(XtParent(oldMenu)), langModeCB, NULL);
475 + XtParent(XtParent(oldMenu)), langModeCB, NULL, FALSE);
476 XtVaSetValues(XmOptionButtonGadget(HighlightDialog.lmOptMenu),
477 XmNsubMenuId, HighlightDialog.lmPulldown, NULL);
478 SetLangModeMenu(HighlightDialog.lmOptMenu, HighlightDialog.langModeName);
479 @@ -2941,6 +2943,9 @@ static void langModeCB(Widget w, XtPoint
481 SetLangModeMenu(HighlightDialog.lmOptMenu,
482 HighlightDialog.langModeName);
484 + freePatternSet(newPatSet);
486 return;
488 if (resp == 1)
489 @@ -3040,6 +3045,8 @@ static void restoreCB(Widget w, XtPointe
490 "patterns for language mode %s?", "Discard", "Cancel",
491 HighlightDialog.langModeName) == 2)
493 + freePatternSet(defaultPatSet);
495 return;
498 diff --quilt old/source/macro.c new/source/macro.c
499 --- old/source/macro.c
500 +++ new/source/macro.c
501 @@ -57,6 +57,8 @@ static const char CVSID[] = "$Id: macro.
502 #include "highlight.h"
503 #include "highlightData.h"
504 #include "rangeset.h"
505 +#include "patternMatch.h"
506 +#include "regularExp.h"
508 #include <stdio.h>
509 #include <stdlib.h>
510 @@ -4216,16 +4218,6 @@ static int showMatchingMV(WindowInfo *wi
511 return True;
514 -static int matchSyntaxBasedMV(WindowInfo *window, DataValue *argList, int nArgs,
515 - DataValue *result, char **errMsg)
517 - result->tag = INT_TAG;
518 - result->val.n = window->matchSyntaxBased ? 1 : 0;
519 - return True;
524 static int overTypeModeMV(WindowInfo *window, DataValue *argList, int nArgs,
525 DataValue *result, char **errMsg)
527 @@ -5633,6 +5625,93 @@ static int getPatternAtPosMS(WindowInfo
528 HighlightStyleOfCode(window, patCode), bufferPos);
532 +** Pattern Match Feature:
533 +** Find a matching pattern string related to the given position.
535 +** Syntax:
536 +** get_matching(position)
538 +** Returns info about matching pattern within an array. The array has
539 +** the following keys: "pos" (position of the first character of the
540 +** matching pattern), "len" (length of the matching pattern), "direction"
541 +** (direction where the matching pattern was found: "0" = forward;
542 +** "1" = backward). If no matching pattern was found, then array element
543 +** of "pos" holds "-1", "len" holds "0" and "direction" holds "-1".
546 +static int getMatchingMS(WindowInfo *window, DataValue *argList, int nArgs,
547 + DataValue *result, char **errMsg)
549 + int startPos;
550 + int matchPos, matchLen;
551 + int direction;
552 + textBuffer *buf = window->buffer;
553 + DataValue dv;
555 + /*
556 + * Perform syntax & semantic check
557 + */
558 + if (nArgs != 1 )
559 + return wrongNArgsErr(errMsg);
561 + if (!readIntArg(argList[0], &startPos, errMsg))
562 + return False;
564 + startPos ++;
566 + /*
567 + * do the search; provide default values, if search fails
568 + */
569 + if (!FindMatchingString(window, MT_MACRO, &startPos, 0, buf->length,
570 + &matchPos, &matchLen, &direction))
572 + matchPos = -1;
573 + matchLen = 0;
574 + direction = -1;
577 + /*
578 + * initialize array holding info about matching string
579 + */
580 + result->tag = ARRAY_TAG;
581 + result->val.arrayPtr = ArrayNew();
583 + /*
584 + * the following array entries will be integers
585 + */
586 + dv.tag = INT_TAG;
588 + /*
589 + * insert match position
590 + */
591 + dv.val.n = matchPos;
592 + if (!ArrayInsert(result, PERM_ALLOC_STR("pos"), &dv))
594 + M_ARRAY_INSERT_FAILURE();
597 + /*
598 + * insert length of matching pattern
599 + */
600 + dv.val.n = matchLen;
601 + if (!ArrayInsert(result, PERM_ALLOC_STR("len"), &dv))
603 + M_ARRAY_INSERT_FAILURE();
606 + /*
607 + * insert direction where the matching pattern was found
608 + */
609 + dv.val.n = direction;
610 + if (!ArrayInsert(result, PERM_ALLOC_STR("direction"), &dv))
612 + M_ARRAY_INSERT_FAILURE();
615 + return True;
618 static int wrongNArgsErr(char **errMsg)
620 *errMsg = "Wrong number of arguments to function %s";
621 diff --quilt old/source/menu.c new/source/menu.c
622 --- old/source/menu.c
623 +++ new/source/menu.c
624 @@ -49,6 +49,7 @@ static const char CVSID[] = "$Id: menu.c
625 #include "macro.h"
626 #include "highlight.h"
627 #include "highlightData.h"
628 +#include "patternMatchData.h"
629 #include "interpret.h"
630 #include "smartIndent.h"
631 #include "windowTitle.h"
632 @@ -133,7 +134,6 @@ static void backlightCharsCB(Widget w, W
633 static void showMatchingOffCB(Widget w, WindowInfo *window, caddr_t callData);
634 static void showMatchingDelimitCB(Widget w, WindowInfo *window, caddr_t callData);
635 static void showMatchingRangeCB(Widget w, WindowInfo *window, caddr_t callData);
636 -static void matchSyntaxBasedCB(Widget w, WindowInfo *window, caddr_t callData);
637 static void statsCB(Widget w, WindowInfo *window, caddr_t callData);
638 static void autoIndentOffDefCB(Widget w, WindowInfo *window, caddr_t callData);
639 static void autoIndentDefCB(Widget w, WindowInfo *window, caddr_t callData);
640 @@ -160,9 +160,9 @@ static void tabsDefCB(Widget w, WindowIn
641 static void showMatchingOffDefCB(Widget w, WindowInfo *window, caddr_t callData);
642 static void showMatchingDelimitDefCB(Widget w, WindowInfo *window, caddr_t callData);
643 static void showMatchingRangeDefCB(Widget w, WindowInfo *window, caddr_t callData);
644 -static void matchSyntaxBasedDefCB(Widget w, WindowInfo *window, caddr_t callData);
645 static void highlightOffDefCB(Widget w, WindowInfo *window, caddr_t callData);
646 static void highlightDefCB(Widget w, WindowInfo *window, caddr_t callData);
647 +static void matchPatternsDefCB(Widget w, WindowInfo *window, caddr_t callData);
648 static void backlightCharsDefCB(Widget w, WindowInfo *window, caddr_t callData);
649 static void fontDefCB(Widget w, WindowInfo *window, caddr_t callData);
650 static void colorDefCB(Widget w, WindowInfo *window, caddr_t callData);
651 @@ -409,8 +409,6 @@ static void setIncrementalBackupAP(Widge
652 Cardinal *nArgs);
653 static void setShowMatchingAP(Widget w, XEvent *event, String *args,
654 Cardinal *nArgs);
655 -static void setMatchSyntaxBasedAP(Widget w, XEvent *event, String *args,
656 - Cardinal *nArgs);
657 static void setOvertypeModeAP(Widget w, XEvent *event, String *args,
658 Cardinal *nArgs);
659 static void setLockedAP(Widget w, XEvent *event, String *args,
660 @@ -584,7 +582,6 @@ static XtActionsRec Actions[] = {
661 #endif
662 {"set_incremental_backup", setIncrementalBackupAP},
663 {"set_show_matching", setShowMatchingAP},
664 - {"set_match_syntax_based", setMatchSyntaxBasedAP},
665 {"set_overtype_mode", setOvertypeModeAP},
666 {"set_locked", setLockedAP},
667 {"set_transient", setTransientAP},
668 @@ -1030,9 +1027,8 @@ Widget CreateMenuBar(Widget parent, Wind
669 "range", "Range", 'R', showMatchingRangeDefCB, window,
670 GetPrefShowMatching() == FLASH_RANGE, SHORT);
671 createMenuSeparator(subSubPane, "sep", SHORT);
672 - window->matchSyntaxBasedDefItem = createMenuToggle(subSubPane,
673 - "matchSyntax", "Syntax Based", 'S', matchSyntaxBasedDefCB, window,
674 - GetPrefMatchSyntaxBased(), SHORT);
675 + createMenuItem(subSubPane, "matchPatterns", "Matching Patterns...",
676 + 'M', matchPatternsDefCB, window, FULL);
678 /* Show Cursorline */
679 window->showCursorlineItem = createMenuToggle(subPane,
680 @@ -1154,10 +1150,6 @@ Widget CreateMenuBar(Widget parent, Wind
681 window->showMatchingRangeItem = createMenuRadioToggle(subPane, "range",
682 "Range", 'R', showMatchingRangeCB, window,
683 window->showMatchingStyle == FLASH_RANGE, SHORT);
684 - createMenuSeparator(subPane, "sep", SHORT);
685 - window->matchSyntaxBasedItem = createMenuToggle(subPane, "matchSyntax",
686 - "Syntax Based", 'S', matchSyntaxBasedCB, window,
687 - window->matchSyntaxBased, SHORT);
689 #ifndef SGI_CUSTOM
690 createMenuSeparator(menuPane, "sep2", SHORT);
691 @@ -1689,24 +1681,6 @@ static void showMatchingRangeCB(Widget w
692 ((XmAnyCallbackStruct *)callData)->event, params, 1);
695 -static void matchSyntaxBasedCB(Widget w, WindowInfo *window, caddr_t callData)
697 - Widget menu = MENU_WIDGET(w);
699 - window = WidgetToWindow(menu);
701 -#ifdef SGI_CUSTOM
702 - if (shortPrefAskDefault(window->shell, w, "Match Syntax Based")) {
703 - matchSyntaxBasedDefCB(w, window, callData);
704 - SaveNEditPrefs(window->shell, GetPrefShortMenus());
706 -#endif
707 - HidePointerOnKeyedEvent(WidgetToWindow(menu)->lastFocus,
708 - ((XmAnyCallbackStruct *)callData)->event);
709 - XtCallActionProc(WidgetToWindow(menu)->lastFocus, "set_match_syntax_based",
710 - ((XmAnyCallbackStruct *)callData)->event, NULL, 0);
713 static void fontCB(Widget w, WindowInfo *window, caddr_t callData)
715 ChooseFonts(WidgetToWindow(MENU_WIDGET(w)), True);
716 @@ -2034,18 +2008,14 @@ static void showMatchingRangeDefCB(Widge
720 -static void matchSyntaxBasedDefCB(Widget w, WindowInfo *window, caddr_t callData)
721 +static void matchPatternsDefCB(Widget w, WindowInfo *window, caddr_t callData)
723 - WindowInfo *win;
725 - int state = XmToggleButtonGetState(w);
726 + Widget menu = MENU_WIDGET(w);
727 + WindowInfo *activeWindow = WidgetToWindow(menu);
729 - /* Set the preference and make the other windows' menus agree */
730 - SetPrefMatchSyntaxBased(state);
731 - for (win=WindowList; win!=NULL; win=win->next) {
732 - if (IsTopDocument(win))
733 - XmToggleButtonSetState(win->matchSyntaxBasedDefItem, state, False);
735 + HidePointerOnKeyedEvent(activeWindow->lastFocus,
736 + ((XmAnyCallbackStruct *)callData)->event);
737 + EditMatchPatterns(activeWindow);
740 static void backlightCharsDefCB(Widget w, WindowInfo *window, caddr_t callData)
741 @@ -4288,19 +4258,6 @@ static void setShowMatchingAP(Widget w,
745 -static void setMatchSyntaxBasedAP(Widget w, XEvent *event, String *args,
746 - Cardinal *nArgs)
748 - WindowInfo *window = WidgetToWindow(w);
749 - Boolean newState;
751 - ACTION_BOOL_PARAM_OR_TOGGLE(newState, *nArgs, args, window->matchSyntaxBased, "set_match_syntax_based");
753 - if (IsTopDocument(window))
754 - XmToggleButtonSetState(window->matchSyntaxBasedItem, newState, False);
755 - window->matchSyntaxBased = newState;
758 static void setOvertypeModeAP(Widget w, XEvent *event, String *args,
759 Cardinal *nArgs)
761 diff --quilt old/source/nedit.h new/source/nedit.h
762 --- old/source/nedit.h
763 +++ new/source/nedit.h
764 @@ -366,7 +366,6 @@ typedef struct _WindowInfo {
765 Widget showMatchingOffItem;
766 Widget showMatchingDelimitItem;
767 Widget showMatchingRangeItem;
768 - Widget matchSyntaxBasedItem;
769 Widget overtypeModeItem;
770 Widget highlightItem;
771 Widget windowMenuPane;
772 @@ -392,7 +391,6 @@ typedef struct _WindowInfo {
773 Widget showMatchingOffDefItem;
774 Widget showMatchingDelimitDefItem;
775 Widget showMatchingRangeDefItem;
776 - Widget matchSyntaxBasedDefItem;
777 Widget highlightOffDefItem;
778 Widget highlightDefItem;
779 Widget backlightCharsItem;
780 @@ -512,7 +510,6 @@ typedef struct _WindowInfo {
781 char showMatchingStyle; /* How to show matching parens:
782 NO_FLASH, FLASH_DELIMIT, or
783 FLASH_RANGE */
784 - char matchSyntaxBased; /* Use syntax info to show matching */
785 Boolean showStats; /* is stats line supposed to be shown */
786 Boolean showISearchLine; /* is incr. search line to be shown */
787 Boolean showLineNumbers; /* is the line number display shown */
788 @@ -558,6 +555,9 @@ typedef struct _WindowInfo {
789 Bool findLastRegexCase; /* idem, for regex mode in find dialog */
790 Bool findLastLiteralCase; /* idem, for literal mode */
792 + /* Pattern Match Feature */
793 + void *stringMatchTable; /* match pattern info related to this window */
795 #ifdef REPLACE_SCOPE
796 int replaceScope; /* Current scope for replace dialog */
797 Widget replaceScopeWinToggle; /* Scope for replace = window */
798 diff --quilt /dev/null new/source/patternMatch.c
799 --- /dev/null
800 +++ new/source/patternMatch.c
801 @@ -0,0 +1,2202 @@
802 +static const char CVSID[] = "$Id: patternMatch.c,v 1.4 2003/10/27 21:59:14 uleh Exp $";
803 +/*******************************************************************************
804 +* *
805 +* patternMatch.c -- Nirvana Editor pattern matching functions *
806 +* *
807 +* Copyright (C) 2003-2004, Uwe Lehnert *
808 +* *
809 +* This is free software; you can redistribute it and/or modify it under the *
810 +* terms of the GNU General Public License as published by the Free Software *
811 +* Foundation; either version 2 of the License, or (at your option) any later *
812 +* version. In addition, you may distribute versions of this program linked to *
813 +* Motif or Open Motif. See README for details. *
814 +* *
815 +* This software is distributed in the hope that it will be useful, but WITHOUT *
816 +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
817 +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
818 +* for more details. *
819 +* *
820 +* You should have received a copy of the GNU General Public License along with *
821 +* software; if not, write to the Free Software Foundation, Inc., 59 Temple *
822 +* Place, Suite 330, Boston, MA 02111-1307 USA *
823 +* *
824 +* Nirvana Text Editor *
825 +* October 27, 2004 *
826 +* *
827 +* Written by Uwe Lehnert *
828 +* *
829 +*******************************************************************************/
831 +#ifdef HAVE_CONFIG_H
832 +#include "../config.h"
833 +#endif
835 +#include <stdlib.h>
836 +#include <stdio.h>
837 +#include <limits.h>
838 +#include <string.h>
839 +#include <ctype.h>
841 +#ifdef VMS
842 +#include "../util/VMSparam.h"
843 +#else
844 +#ifndef __MVS__
845 +#include <sys/param.h>
846 +#endif
847 +#endif /*VMS*/
849 +#include "regularExp.h"
850 +#include "textBuf.h"
851 +#include "search.h"
852 +#include "window.h"
853 +#include "preferences.h"
854 +#include "highlight.h"
856 +#include "patternMatch.h"
857 +#include "patternMatchData.h"
859 +#ifdef HAVE_DEBUG_H
860 +#include "../debug.h"
861 +#endif
863 +#define MAX_NESTED_PATTERNS 100
865 +#define IGNORE_HIGHLIGHT_CODE -1
867 +typedef struct _SearchRegionInfo {
868 + WindowInfo *sriWindow;
869 + char *sriText;
870 + char sriPrevChar;
871 + char sriSuccChar;
872 + int sriStartOfTextPos;
873 +} SearchRegionInfo;
875 +typedef struct _FoundStringInfo {
876 + char *fsiStartPtr;
877 + char *fsiEndPtr;
878 + int fsiLength;
879 + char fsiPrevChar;
880 + char fsiSuccChar;
881 + const char *fsiDelimiters;
882 +} FoundStringInfo;
884 +typedef struct _BackRefInfo {
885 + int briAvailable;
886 + int briCaseInsensitive;
887 + char *briStartPtr[MAX_GLOBAL_BACK_REF_ID];
888 + char *briEndPtr[MAX_GLOBAL_BACK_REF_ID];
889 +} BackRefInfo;
891 +typedef struct _MatchingElementInfo {
892 + MatchPatternTableElement *meiElement;
893 + PatternReference meiPatRef;
894 + int meiDirection;
895 + int meiHighLightCode;
896 + int meiAbsStartPos;
897 + int meiLength;
898 + BackRefInfo meiBackRefInfo;
899 +} MatchingElementInfo;
901 +typedef struct _PatternStackElement {
902 + PatternReference psePatRef;
903 + int pseHighLightCode;
904 + BackRefInfo pseBackRefInfo;
905 +} PatternStackElement;
908 + * Prototypes of local functions
909 + */
910 +void adaptPatternPositions(
911 + MatchingType matchingType,
912 + int direction,
913 + int *charPos,
914 + int startPatternLength,
915 + int *matchPos,
916 + int matchedPatternLength);
918 +static int findMatchingStringElement(
919 + StringMatchTable *smTable,
920 + SearchRegionInfo *searchRegion,
921 + MatchingElementInfo *matchInfo,
922 + int *charPos,
923 + const char *delimiters);
925 +static PatternElementMonoInfo determineMonoPatInfo(
926 + WindowInfo *window,
927 + int patHighLightCode,
928 + int leftPos,
929 + int rightPos,
930 + PatternElementKind *patElementKind);
932 +static void assignBackRefInfo(
933 + StringPattern *strPat,
934 + BackRefInfo *backRefInfo);
935 +static int doesBackRefInfoMatch(
936 + BackRefInfo *backRefInfo1,
937 + BackRefInfo *backRefInfo2);
938 +static int compareBackRef(
939 + char *startPtr1,
940 + char *endPtr1,
941 + char *startPtr2,
942 + char *endPtr2,
943 + int caseInsensitive);
945 +static int doesPatternElementMatch(
946 + PatternElement *patElement,
947 + FoundStringInfo *foundStringInfo,
948 + BackRefInfo *backRefInfo);
949 +static int doesMPTableElementMatch(
950 + MatchPatternTableElement *element,
951 + FoundStringInfo *foundStringInfo,
952 + PatternElementKind *patternElementKind,
953 + int *patternElementIdx,
954 + BackRefInfo *backRefInfo);
955 +static int getPatternInfo(
956 + MatchPatternTable *table,
957 + FoundStringInfo *foundStringInfo,
958 + PatternReference *patRef,
959 + BackRefInfo *backRefInfo);
961 +static int isPartOfPattern(
962 + MatchPatternTable *table,
963 + int parentElementIdx,
964 + int childElementIdx,
965 + PatternElementKind patElementKind);
966 +static int isPartOfPatternElementSet(
967 + PatternElementSet *patElementSet,
968 + int patternElementIdx);
969 +static int isPartOfMiddlePatternElementSet(
970 + PatternElementSet *patElementSet,
971 + int patternElementIdx);
972 +static void considerNextPatternReference(
973 + MatchPatternTable *table,
974 + PatternReference *startPatRef,
975 + PatternReference nxtPatRef,
976 + int groupIdx);
978 +static int searchPatternForward(
979 + MatchPatternTable *table,
980 + regexp *compiledRE,
981 + SearchRegionInfo *searchRegion,
982 + const char *delimiters,
983 + int beginPos,
984 + int *matchEndPos,
985 + PatternReference *patRef,
986 + int *highLightCode,
987 + BackRefInfo *backRefInfo);
988 +static int searchPatternBackward(
989 + MatchPatternTable *table,
990 + regexp *compiledRE,
991 + SearchRegionInfo *searchRegion,
992 + const char *delimiters,
993 + int beginPos,
994 + PatternReference *patRef,
995 + int *highLightCode,
996 + int *matchedPatternLength,
997 + BackRefInfo *backRefInfo);
999 +static int parseStringElementForward(
1000 + MatchingElementInfo *matchInfo,
1001 + SearchRegionInfo *searchRegion,
1002 + int relCharPos,
1003 + int *matchPos,
1004 + int *matchedPatternLength,
1005 + const char *delimiters);
1006 +static int findRelatedForwardPattern(
1007 + StringMatchTable *table,
1008 + SearchRegionInfo *searchRegion,
1009 + const char *delimiters,
1010 + PatternReference beginPatRef,
1011 + int beginPatHighLightCode,
1012 + BackRefInfo *beginPatBackRefInfo,
1013 + int beginPos,
1014 + int *matchEndPos);
1016 +static int parseStringElementBackward(
1017 + MatchingElementInfo *matchInfo,
1018 + SearchRegionInfo *searchRegion,
1019 + int relCharPos,
1020 + int *matchPos,
1021 + int *matchedPatternLength,
1022 + const char *delimiters);
1023 +static int findRelatedStartPattern(
1024 + StringMatchTable *table,
1025 + SearchRegionInfo *searchRegion,
1026 + const char *delimiters,
1027 + PatternReference beginPatRef,
1028 + int beginPatHighLightCode,
1029 + BackRefInfo *beginPatBackRefInfo,
1030 + int beginPos,
1031 + int *matchedPatternLength);
1032 +static void considerStackPatReference(
1033 + PatternElementSet *patSet,
1034 + int stackElementIdx,
1035 + int *foundElementIdx);
1037 +static int getPatternLocatedAtPos(
1038 + regexp *usedPatRE,
1039 + MatchPatternTable *table,
1040 + SearchRegionInfo *searchRegion,
1041 + int *relBeginPos,
1042 + MatchingElementInfo *matchInfo,
1043 + const char *delimiters);
1044 +static int getMatchedElementInfo(
1045 + WindowInfo *window,
1046 + MatchPatternTable *table,
1047 + FoundStringInfo *foundStringInfo,
1048 + MatchingElementInfo *matchInfo);
1050 +static PatternElement *getPatternOfReference(
1051 + MatchPatternTable *table,
1052 + PatternReference patRef);
1054 +#ifdef DEBUG_FIND
1055 +static char *getPatternForDebug(
1056 + MatchPatternTable *table,
1057 + PatternReference patRef );
1058 +static char *patElemKindToString(
1059 + PatternElementKind patElemKind);
1060 +static void printFoundStringForDebug(
1061 + WindowInfo *window,
1062 + int absStartPos,
1063 + int length);
1064 +#endif
1067 +** Try to find a matching pattern string related to the given "charPos"
1068 +** inside the given range (defined by startLimit & endLimit).
1069 +** Determine the matching position & the match pattern length (depending
1070 +** on given matchingType), if a matching pattern was found.
1071 +** Returns true, if a matching pattern string was found.
1073 +int FindMatchingString(
1074 + WindowInfo *window,
1075 + MatchingType matchingType,
1076 + int *charPos,
1077 + int startLimit,
1078 + int endLimit,
1079 + int *matchPos,
1080 + int *matchedPatternLength,
1081 + int *direction)
1083 + StringMatchTable *smTable = (StringMatchTable *)window->stringMatchTable;
1084 + const char *delimiters;
1085 + SearchRegionInfo searchRegion;
1086 + MatchingElementInfo matchInfo;
1087 + int matchingPatternFound = FALSE;
1088 + int relCharPos;
1090 + if (smTable == NULL || smTable->smtAllPatRE == NULL)
1092 + /*
1093 + * No match pattern table available:
1094 + */
1095 + return FALSE;
1098 + /*
1099 + * Get delimiters related to window
1100 + */
1101 + delimiters = GetWindowDelimiters(window);
1102 + if (delimiters == NULL)
1103 + delimiters = GetPrefDelimiters();
1105 + /*
1106 + * Select the start pattern reg. exp. to use
1107 + */
1108 + if (matchingType == MT_FLASH_RANGE ||
1109 + matchingType == MT_FLASH_DELIMIT)
1111 + smTable->smtUsedPatRE = smTable->smtFlashPatRE;
1113 + else
1115 + smTable->smtUsedPatRE = smTable->smtAllPatRE;
1118 + /*
1119 + * Get a copy of the text buffer area to parse
1120 + */
1121 + searchRegion.sriWindow = window;
1122 + searchRegion.sriText = BufGetRange(window->buffer, startLimit, endLimit);
1123 + searchRegion.sriPrevChar = BufGetCharacter(window->buffer, startLimit - 1);
1124 + searchRegion.sriSuccChar = BufGetCharacter(window->buffer, endLimit);
1125 + searchRegion.sriStartOfTextPos = startLimit;
1127 + relCharPos = *charPos - startLimit;
1129 + /*
1130 + * Try to find a matching pattern string using string match table
1131 + * of window
1132 + */
1133 + if (findMatchingStringElement(
1134 + smTable,
1135 + &searchRegion,
1136 + &matchInfo,
1137 + &relCharPos,
1138 + delimiters ))
1140 +#ifdef DEBUG_FIND
1141 + printf("--- Start at : ");
1142 + printFoundStringForDebug(
1143 + window,
1144 + matchInfo.meiAbsStartPos,
1145 + matchInfo.meiLength);
1146 + printf(" ---\n");
1147 +#endif
1148 + if (matchInfo.meiDirection == SEARCH_FORWARD)
1150 + matchingPatternFound =
1151 + parseStringElementForward(
1152 + &matchInfo,
1153 + &searchRegion,
1154 + relCharPos,
1155 + matchPos,
1156 + matchedPatternLength,
1157 + delimiters );
1159 + else
1161 + matchingPatternFound =
1162 + parseStringElementBackward(
1163 + &matchInfo,
1164 + &searchRegion,
1165 + relCharPos,
1166 + matchPos,
1167 + matchedPatternLength,
1168 + delimiters );
1171 + if (matchingPatternFound)
1173 + /*
1174 + * Calc. abs. start char pos. (may have been changed if
1175 + * cursor was located inside a string pattern). Adapt
1176 + * pattern positions depending on matchingType.
1177 + */
1178 + *charPos = relCharPos + startLimit;
1179 + *direction = matchInfo.meiDirection;
1181 + adaptPatternPositions(
1182 + matchingType,
1183 + matchInfo.meiDirection,
1184 + charPos,
1185 + matchInfo.meiLength,
1186 + matchPos,
1187 + *matchedPatternLength);
1191 + XtFree(searchRegion.sriText);
1193 + return matchingPatternFound;
1197 +** Adapt match pattern position / start position depending on the
1198 +** given matching type.
1200 +void adaptPatternPositions(
1201 + MatchingType matchingType,
1202 + int direction,
1203 + int *charPos,
1204 + int startPatternLength,
1205 + int *matchPos,
1206 + int matchedPatternLength)
1208 + switch (matchingType)
1210 + case MT_FLASH_DELIMIT:
1211 + case MT_MACRO:
1212 + if (direction == SEARCH_FORWARD)
1214 + (*matchPos) -= matchedPatternLength - 1;
1216 + break;
1218 + case MT_FLASH_RANGE:
1219 + case MT_SELECT:
1220 + if (direction == SEARCH_FORWARD)
1222 + (*charPos) -= startPatternLength;
1224 + else
1226 + (*charPos) --;
1228 + break;
1230 + case MT_GOTO:
1231 + if (direction == SEARCH_FORWARD)
1233 + (*matchPos) ++;
1235 + else
1237 + (*matchPos) += matchedPatternLength;
1239 + break;
1244 +** Try to find a string pattern at given buffer position 'charPos'.
1245 +** A string pattern is found, if pattern is located before 'charPos' or
1246 +** 'charPos' is located within a pattern.
1247 +** If a string pattern is found, then search direction and string pattern
1248 +** reference / properties are determined.
1249 +** Returns true, if a string pattern was found.
1251 +static int findMatchingStringElement(
1252 + StringMatchTable *smTable,
1253 + SearchRegionInfo *searchRegion,
1254 + MatchingElementInfo *matchInfo,
1255 + int *charPos,
1256 + const char *delimiters)
1258 + if (getPatternLocatedAtPos(
1259 + smTable->smtUsedPatRE,
1260 + smTable->smtAllPatterns,
1261 + searchRegion,
1262 + charPos,
1263 + matchInfo,
1264 + delimiters))
1266 + /*
1267 + * Pattern found -> define search direction:
1268 + * - START & MIDDLE pattern: matching pattern is searched in
1269 + * forward direction
1270 + * - END pattern: matching pattern is searched in backward
1271 + * direction
1272 + */
1273 + if (matchInfo->meiPatRef.prKind == PEK_END)
1274 + matchInfo->meiDirection = SEARCH_BACKWARD;
1275 + else
1276 + matchInfo->meiDirection = SEARCH_FORWARD;
1278 + return TRUE;
1281 + return FALSE;
1285 +** Return mono pattern info depending on highlight codes
1286 +** of left / right side of string pattern. Update pattern
1287 +** kind if applicable.
1289 +static PatternElementMonoInfo determineMonoPatInfo(
1290 + WindowInfo *window,
1291 + int patHighLightCode,
1292 + int leftPos,
1293 + int rightPos,
1294 + PatternElementKind *patElementKind)
1296 + int leftSideHasSameHC;
1297 + int rightSideHasSameHC;
1299 + /*
1300 + * Determine, if left side holds same highlight code than
1301 + * found string pattern
1302 + */
1303 + if (leftPos >= 0)
1304 + leftSideHasSameHC =
1305 + (HighlightCodeOfPos(window, leftPos) == patHighLightCode);
1306 + else
1307 + leftSideHasSameHC = FALSE;
1309 + /*
1310 + * Determine, if right side holds same highlight code than
1311 + * found string pattern
1312 + */
1313 + if (rightPos < window->buffer->length)
1314 + rightSideHasSameHC =
1315 + (HighlightCodeOfPos(window, rightPos) == patHighLightCode);
1316 + else
1317 + rightSideHasSameHC = FALSE;
1319 + if ((rightSideHasSameHC && leftSideHasSameHC) ||
1320 + (!rightSideHasSameHC && !leftSideHasSameHC))
1322 + return PEMI_MONO_AMBIGUOUS_SYNTAX;
1324 + else if (leftSideHasSameHC)
1326 + *patElementKind = PEK_END;
1327 + return PEMI_MONO_DEFINITE_SYNTAX;
1329 + else
1331 + *patElementKind = PEK_START;
1332 + return PEMI_MONO_DEFINITE_SYNTAX;
1337 +** Get backref info out of found string pattern and
1338 +** put it into given backRefInfo.
1340 +static void assignBackRefInfo(
1341 + StringPattern *strPat,
1342 + BackRefInfo *backRefInfo)
1344 + int i;
1345 + int localId;
1346 + regexp *patRE = strPat->spTextRE;
1348 + backRefInfo->briAvailable = FALSE;
1349 + backRefInfo->briCaseInsensitive = strPat->spCaseInsensitive;
1351 + for (i=0; i<MAX_GLOBAL_BACK_REF_ID; i++)
1353 + localId = strPat->spGlobalToLocalBackRef[i];
1355 + if (localId != NO_LOCAL_BACK_REF_ID)
1357 + backRefInfo->briAvailable = TRUE;
1359 + backRefInfo->briStartPtr[i] = patRE->startp[localId];
1360 + backRefInfo->briEndPtr[i] = patRE->endp[localId];
1362 + else
1364 + backRefInfo->briStartPtr[i] = NULL;
1365 + backRefInfo->briEndPtr[i] = NULL;
1371 +** Check, if given backref infos match.
1372 +** Returns true, if backref infos match.
1374 +static int doesBackRefInfoMatch(
1375 + BackRefInfo *backRefInfo1,
1376 + BackRefInfo *backRefInfo2)
1378 + int i;
1380 + /*
1381 + * if min. one string pattern doesn't hold backref info, then nothing
1382 + * could be compared -> both string pattern are matching.
1383 + */
1384 + if (!backRefInfo1->briAvailable || !backRefInfo2->briAvailable)
1385 + return TRUE;
1387 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
1389 + if (!compareBackRef(
1390 + backRefInfo1->briStartPtr[i],
1391 + backRefInfo1->briEndPtr[i],
1392 + backRefInfo2->briStartPtr[i],
1393 + backRefInfo2->briEndPtr[i],
1394 + backRefInfo1->briCaseInsensitive || backRefInfo2->briCaseInsensitive))
1396 + return FALSE;
1400 + return TRUE;
1404 +** Compares two backref content.
1405 +** Returns true, if backref contents match.
1407 +static int compareBackRef(
1408 + char *startPtr1,
1409 + char *endPtr1,
1410 + char *startPtr2,
1411 + char *endPtr2,
1412 + int caseInsensitive)
1414 + char *s1;
1415 + char *s2;
1417 + if (startPtr1 == NULL && startPtr2 == NULL)
1418 + return TRUE;
1420 + if (startPtr1 == NULL || startPtr2 == NULL)
1421 + return FALSE;
1423 + if ((endPtr1 - startPtr1) != (endPtr2 - startPtr2))
1424 + return FALSE;
1426 + s1 = startPtr1;
1427 + s2 = startPtr2;
1429 + if (caseInsensitive)
1431 + while (s1 != endPtr1)
1433 + if (tolower((unsigned char)*s1++) != tolower((unsigned char)*s2++))
1434 + return FALSE;
1437 + else
1439 + while (s1 != endPtr1)
1441 + if (*s1++ != *s2++)
1442 + return FALSE;
1445 + return TRUE;
1449 +** Verify if given pattern element is located between given
1450 +** start / end pointer of "foundStringInfo". Assign backreference
1451 +** information, if pattern element matches.
1452 +** Returns true, if given pattern element matches.
1454 +static int doesPatternElementMatch(
1455 + PatternElement *patElement,
1456 + FoundStringInfo *foundStringInfo,
1457 + BackRefInfo *backRefInfo)
1459 + char *s;
1460 + char *p;
1461 + StringPattern *strPat;
1462 + int elementMatch;
1464 + switch (patElement->peType)
1466 + case PET_SINGLE:
1467 + strPat = &patElement->peVal.peuSingle;
1468 + break;
1469 + case PET_MULTIPLE:
1470 + strPat = &patElement->peVal.peuMulti.mpStringPattern;
1471 + break;
1472 + default:
1473 + return FALSE;
1476 + if (strPat->spRegularExpression)
1478 + /*
1479 + * check reg. expression:
1480 + */
1481 + elementMatch =
1482 + ExecRE(
1483 + strPat->spTextRE,
1484 + foundStringInfo->fsiStartPtr,
1485 + foundStringInfo->fsiEndPtr,
1486 + FALSE,
1487 + foundStringInfo->fsiPrevChar,
1488 + foundStringInfo->fsiSuccChar,
1489 + foundStringInfo->fsiDelimiters,
1490 + NULL,
1491 + NULL);
1493 + if (elementMatch)
1494 + assignBackRefInfo(strPat, backRefInfo);
1496 + return elementMatch;
1498 + else
1500 + backRefInfo->briAvailable = FALSE;
1502 + /*
1503 + * check literal string:
1504 + */
1505 + p = strPat->spText;
1507 + /*
1508 + * if length of found string is different from length of
1509 + * given string pattern, then there is no match.
1510 + */
1511 + if (strPat->spLength != foundStringInfo->fsiLength)
1512 + return FALSE;
1514 + s = foundStringInfo->fsiStartPtr;
1516 + if (strPat->spCaseInsensitive)
1518 + while (s != foundStringInfo->fsiEndPtr)
1520 + if (tolower((unsigned char)*s++) != *p++)
1521 + return FALSE;
1524 + else
1526 + while (s != foundStringInfo->fsiEndPtr)
1528 + if (*s++ != *p++)
1529 + return FALSE;
1534 + return TRUE;
1538 +** Verify if a pattern element of given MatchPatternTableElement is
1539 +** located between given start / end pointer of "foundStringInfo".
1540 +** Returns true, if so.
1542 +static int doesMPTableElementMatch(
1543 + MatchPatternTableElement *element,
1544 + FoundStringInfo *foundStringInfo,
1545 + PatternElementKind *patternElementKind,
1546 + int *patternElementIdx,
1547 + BackRefInfo *backRefInfo)
1549 + int i;
1551 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i ++)
1553 + if (doesPatternElementMatch(
1554 + element->mpteAll.pesPattern[i],
1555 + foundStringInfo,
1556 + backRefInfo))
1558 + *patternElementKind = element->mpteAll.pesPattern[i]->peKind;
1559 + *patternElementIdx = i;
1561 + return TRUE;
1565 + return FALSE;
1569 +** Determine the pattern element of given MatchPatternTable, which is
1570 +** located between given start / end pointer of "foundStringInfo".
1571 +** Setup related pattern element reference.
1572 +** Returns true, if a pattern element was found.
1574 +static int getPatternInfo(
1575 + MatchPatternTable *table,
1576 + FoundStringInfo *foundStringInfo,
1577 + PatternReference *patRef,
1578 + BackRefInfo *backRefInfo)
1580 + int i;
1582 + for (i=0; i<table->mptNumberOfElements; i++)
1584 + if (doesMPTableElementMatch(
1585 + table->mptElements[i],
1586 + foundStringInfo,
1587 + &patRef->prKind,
1588 + &patRef->prPatternIdx,
1589 + backRefInfo))
1591 + patRef->prElementIdx = i;
1593 + return TRUE;
1597 + /*
1598 + * Should never been reached !
1599 + */
1600 + patRef->prElementIdx = NO_ELEMENT_IDX;
1601 + patRef->prKind = PEK_UNKNOWN;
1602 + patRef->prPatternIdx = NO_PATTERN_IDX;
1604 + return FALSE;
1608 +** Check, if given child pattern element is part of given
1609 +** parent pattern element.
1610 +** Returns true, if child is part of parent.
1612 +static int isPartOfPattern(
1613 + MatchPatternTable *table,
1614 + int parentElementIdx,
1615 + int childElementIdx,
1616 + PatternElementKind patElementKind)
1618 + MatchPatternTableElement *parent = table->mptElements[parentElementIdx];
1619 + MatchPatternTableElement *child = table->mptElements[childElementIdx];
1621 + if (childElementIdx == parentElementIdx)
1622 + return TRUE;
1624 + if (patElementKind == PEK_START)
1626 + if (isPartOfPatternElementSet(&parent->mpteStart, childElementIdx))
1627 + return TRUE;
1629 + return( isPartOfPatternElementSet(&child->mpteStart, parentElementIdx) );
1631 + else if (patElementKind == PEK_END)
1633 + if (isPartOfPatternElementSet(&parent->mpteEnd, childElementIdx))
1634 + return TRUE;
1636 + return( isPartOfPatternElementSet(&child->mpteEnd, parentElementIdx) );
1638 + else
1640 + /*
1641 + * Given child pattern element is middle pattern: the given pattern element
1642 + * is part of parent pattern, if it's a reference of a middle pattern
1643 + */
1644 + if (isPartOfMiddlePatternElementSet(&parent->mpteMiddle, childElementIdx))
1645 + return TRUE;
1647 + return( isPartOfMiddlePatternElementSet(&child->mpteMiddle, parentElementIdx) );
1652 +** Check, if given pattern element is part of given pattern element set.
1653 +** Returns true, if so.
1655 +static int isPartOfPatternElementSet(
1656 + PatternElementSet *patElementSet,
1657 + int patternElementIdx)
1659 + PatternElement *patElement;
1660 + int i;
1662 + for (i=0; i<patElementSet->pesNumberOfPattern; i++)
1664 + if (patElementSet->pesPattern[i]->peType == PET_REFERENCE)
1666 + patElement = patElementSet->pesPattern[i];
1668 + if (patElement->peVal.peuRef.prElementIdx == patternElementIdx)
1670 + return TRUE;
1675 + return FALSE;
1679 +** Verify, if given pattern element is part of middle pattern set.
1680 +** That's the case, if an element of the pattern set is reference
1681 +** of a middle pattern, which fits to given pattern element.
1682 +** Returns true, if pattern element is part of middle pattern set.
1683 + */
1684 +static int isPartOfMiddlePatternElementSet(
1685 + PatternElementSet *patElementSet,
1686 + int patternElementIdx)
1688 + PatternElement *patElement;
1689 + int i;
1691 + for (i=0; i<patElementSet->pesNumberOfPattern; i++)
1693 + if (patElementSet->pesPattern[i]->peType == PET_REFERENCE)
1695 + patElement = patElementSet->pesPattern[i];
1697 + if (patElement->peVal.peuRef.prElementIdx == patternElementIdx &&
1698 + patElement->peKind == PEK_MIDDLE)
1700 + return TRUE;
1705 + return FALSE;
1709 +** Update start pattern reference depending on next pattern located
1710 +** after start pattern.
1712 +static void considerNextPatternReference(
1713 + MatchPatternTable *table,
1714 + PatternReference *startPatRef,
1715 + PatternReference nxtPatRef,
1716 + int groupIdx)
1718 + MatchPatternTableElement *tabElement;
1719 + PatternElement *startPat;
1720 + MultiPattern *multiStartPat;
1721 + PatternReference patRef;
1722 + int i;
1724 + /*
1725 + * startPatRef needs no adaption, if element index of start pattern
1726 + * and next pattern are equal (i.e. start and next pattern belong
1727 + * to same pattern element).
1728 + */
1729 + if (startPatRef->prElementIdx == nxtPatRef.prElementIdx)
1730 + return;
1732 + /*
1733 + * Verify, if start pattern belongs to multiple pattern elements
1734 + * (like "ELSE .. FI" & "ELSE .. ESAC").
1735 + */
1736 + startPat = getPatternOfReference( table, *startPatRef );
1738 + if (startPat->peType == PET_MULTIPLE)
1740 + /*
1741 + * Check, if next pattern fits to one of the references of
1742 + * the start multi pattern. If so: adapt start pattern reference.
1743 + */
1744 + multiStartPat = &startPat->peVal.peuMulti;
1746 + for (i=0; i<multiStartPat->mpNumberOfReferences; i ++)
1748 + patRef = multiStartPat->mpRefList[i];
1749 + tabElement = table->mptElements[patRef.prElementIdx];
1751 + if (nxtPatRef.prElementIdx == patRef.prElementIdx &&
1752 + tabElement->mpteGroup == groupIdx)
1754 + *startPatRef = patRef;
1755 + return;
1762 +** Search for a string pattern in forward direction, starting at
1763 +** given beginPos. Determine related pattern reference of a found
1764 +** string pattern.
1765 +** Returns true, if a next string pattern was found.
1767 +static int searchPatternForward(
1768 + MatchPatternTable *table,
1769 + regexp *compiledRE,
1770 + SearchRegionInfo *searchRegion,
1771 + const char *delimiters,
1772 + int beginPos,
1773 + int *matchEndPos,
1774 + PatternReference *patRef,
1775 + int *highLightCode,
1776 + BackRefInfo *backRefInfo)
1778 + FoundStringInfo foundStringInfo;
1779 + int matchStartPos;
1780 + int absMatchStartPos;
1781 + MatchPatternTableElement *matchedElement;
1783 + *matchEndPos = -1;
1785 + patRef->prElementIdx = NO_ELEMENT_IDX;
1786 + patRef->prKind = PEK_UNKNOWN;
1787 + patRef->prPatternIdx = NO_PATTERN_IDX;
1789 + *highLightCode = IGNORE_HIGHLIGHT_CODE;
1791 + if (ExecRE(
1792 + compiledRE,
1793 + searchRegion->sriText + beginPos,
1794 + NULL,
1795 + FALSE,
1796 + beginPos==0 ? searchRegion->sriPrevChar : searchRegion->sriText[beginPos-1],
1797 + searchRegion->sriSuccChar,
1798 + delimiters,
1799 + searchRegion->sriText,
1800 + NULL))
1802 + foundStringInfo.fsiStartPtr = compiledRE->startp[0];
1803 + foundStringInfo.fsiEndPtr = compiledRE->endp[0];
1804 + foundStringInfo.fsiLength =
1805 + foundStringInfo.fsiEndPtr - foundStringInfo.fsiStartPtr;
1807 + foundStringInfo.fsiPrevChar =
1808 + foundStringInfo.fsiStartPtr == searchRegion->sriText ?
1809 + searchRegion->sriPrevChar : *(foundStringInfo.fsiStartPtr - 1);
1811 + foundStringInfo.fsiSuccChar =
1812 + *(foundStringInfo.fsiEndPtr) == '\0' ?
1813 + searchRegion->sriSuccChar : *(foundStringInfo.fsiEndPtr);
1815 + foundStringInfo.fsiDelimiters = delimiters;
1817 + if (getPatternInfo(
1818 + table,
1819 + &foundStringInfo,
1820 + patRef,
1821 + backRefInfo))
1823 + /*
1824 + * Next string pattern was found in forward direction and
1825 + * a pattern reference could be assigned to: calculate
1826 + * relative & absolute match positions.
1827 + */
1828 + matchStartPos = foundStringInfo.fsiStartPtr - searchRegion->sriText;
1829 + *matchEndPos = foundStringInfo.fsiEndPtr - searchRegion->sriText;
1831 + absMatchStartPos = matchStartPos + searchRegion->sriStartOfTextPos;
1833 + matchedElement = table->mptElements[patRef->prElementIdx];
1835 + /*
1836 + * get highlight code of found string pattern, if applicable
1837 + */
1838 + if (!matchedElement->mpteIgnoreHighLightInfo)
1840 + *highLightCode =
1841 + HighlightCodeOfPos(searchRegion->sriWindow, absMatchStartPos);
1844 + /*
1845 + * setup mono pattern info of found string pattern
1846 + */
1847 + if (matchedElement->mpteIsMonoPattern)
1849 + if (matchedElement->mpteIgnoreHighLightInfo)
1851 + patRef->prMonoInfo = PEMI_MONO_NOT_SYNTAX_BASED;
1853 + else
1855 + /*
1856 + * determine mono pattern info depending on highLightCodes
1857 + * before / after found string pattern.
1858 + */
1859 + patRef->prMonoInfo =
1860 + determineMonoPatInfo(
1861 + searchRegion->sriWindow,
1862 + *highLightCode,
1863 + absMatchStartPos - 1,
1864 + *matchEndPos + searchRegion->sriStartOfTextPos,
1865 + &patRef->prKind);
1868 + else
1870 + patRef->prMonoInfo = PEMI_NOT_MONO;
1873 + return matchStartPos;
1875 + else
1877 + /*
1878 + * Found string can't be assigned to a pattern element
1879 + * (should never occur).
1880 + */
1881 + return -1;
1884 + else
1886 + /*
1887 + * No next string pattern is found in forward direction.
1888 + */
1889 + return -1;
1894 +** Search for a string pattern in backward direction, starting at
1895 +** given beginPos. Determine related pattern reference of a found
1896 +** string pattern.
1897 +** Returns true, if a next string pattern was found.
1899 +static int searchPatternBackward(
1900 + MatchPatternTable *table,
1901 + regexp *compiledRE,
1902 + SearchRegionInfo *searchRegion,
1903 + const char *delimiters,
1904 + int beginPos,
1905 + PatternReference *patRef,
1906 + int *highLightCode,
1907 + int *matchedPatternLength,
1908 + BackRefInfo *backRefInfo)
1910 + FoundStringInfo foundStringInfo;
1911 + int matchStartPos;
1912 + int absMatchStartPos;
1913 + MatchPatternTableElement *matchedElement;
1915 + patRef->prElementIdx = NO_ELEMENT_IDX;
1916 + patRef->prKind = PEK_UNKNOWN;
1917 + patRef->prPatternIdx = NO_PATTERN_IDX;
1919 + *highLightCode = IGNORE_HIGHLIGHT_CODE;
1921 + if (ExecRE(
1922 + compiledRE,
1923 + searchRegion->sriText,
1924 + searchRegion->sriText + beginPos,
1925 + TRUE,
1926 + searchRegion->sriPrevChar,
1927 + searchRegion->sriText[beginPos] == '\0' ?
1928 + searchRegion->sriSuccChar : searchRegion->sriText[beginPos + 1],
1929 + delimiters,
1930 + searchRegion->sriText,
1931 + NULL))
1933 + foundStringInfo.fsiStartPtr = compiledRE->startp[0];
1934 + foundStringInfo.fsiEndPtr = compiledRE->endp[0];
1935 + foundStringInfo.fsiLength =
1936 + foundStringInfo.fsiEndPtr - foundStringInfo.fsiStartPtr;
1938 + foundStringInfo.fsiPrevChar =
1939 + foundStringInfo.fsiStartPtr == searchRegion->sriText ?
1940 + searchRegion->sriPrevChar : *(foundStringInfo.fsiStartPtr - 1);
1942 + foundStringInfo.fsiSuccChar =
1943 + *(foundStringInfo.fsiEndPtr) == '\0' ?
1944 + searchRegion->sriSuccChar : *(foundStringInfo.fsiEndPtr);
1946 + foundStringInfo.fsiDelimiters = delimiters;
1948 + if (getPatternInfo(
1949 + table,
1950 + &foundStringInfo,
1951 + patRef,
1952 + backRefInfo))
1954 + /*
1955 + * Next string pattern was found in backward direction and
1956 + * a pattern reference could be assigned to: calculate
1957 + * relative & absolute match positions.
1958 + */
1959 + matchStartPos = foundStringInfo.fsiStartPtr - searchRegion->sriText;
1960 + *matchedPatternLength = foundStringInfo.fsiLength;
1962 + absMatchStartPos = matchStartPos + searchRegion->sriStartOfTextPos;
1964 + matchedElement = table->mptElements[patRef->prElementIdx];
1966 + /*
1967 + * get highlight code of found string pattern, if applicable
1968 + */
1969 + if (!matchedElement->mpteIgnoreHighLightInfo)
1971 + *highLightCode =
1972 + HighlightCodeOfPos(searchRegion->sriWindow, absMatchStartPos);
1975 + /*
1976 + * setup mono pattern info of found string pattern
1977 + */
1978 + if (matchedElement->mpteIsMonoPattern)
1980 + if (matchedElement->mpteIgnoreHighLightInfo)
1982 + patRef->prMonoInfo = PEMI_MONO_NOT_SYNTAX_BASED;
1984 + else
1986 + /*
1987 + * determine mono pattern info depending on highLightCodes
1988 + * before / after found string pattern.
1989 + */
1990 + patRef->prMonoInfo =
1991 + determineMonoPatInfo(
1992 + searchRegion->sriWindow,
1993 + *highLightCode,
1994 + absMatchStartPos - 1,
1995 + absMatchStartPos + *matchedPatternLength,
1996 + &patRef->prKind);
1999 + else
2001 + patRef->prMonoInfo = PEMI_NOT_MONO;
2004 + return matchStartPos;
2006 + else
2008 + /*
2009 + * Found string can't be assigned to a pattern element
2010 + * (should never occur).
2011 + */
2012 + return -1;
2015 + else
2017 + /*
2018 + * No next string pattern is found in backward direction.
2019 + */
2020 + return -1;
2025 +** Find matching pattern related to given pattern (stored in
2026 +** 'matchInfo') in forward direction by considering the rules stored in
2027 +** string match table of given window. Determine match position (= abs.
2028 +** pos. of last character of matching string) and length of matching
2029 +** string. If a mono matching pattern couldn't be found in forward
2030 +** direction, then try finding it in backward direction (if found in
2031 +** backward direction, then match position indicates the 1st char. of
2032 +** matching string).
2033 +** Returns true, if a matching pattern was found.
2035 +static int parseStringElementForward(
2036 + MatchingElementInfo *matchInfo,
2037 + SearchRegionInfo *searchRegion,
2038 + int relCharPos,
2039 + int *matchPos,
2040 + int *matchedPatternLength,
2041 + const char *delimiters)
2043 + StringMatchTable *smTable =
2044 + (StringMatchTable *)searchRegion->sriWindow->stringMatchTable;
2045 + MatchPatternTableElement *matchElement = matchInfo->meiElement;
2046 + int beginPos = relCharPos;
2047 + int endStartPos;
2048 + int startStartPos;
2049 + int endEndPos;
2050 + int matchingPatternFound = FALSE;
2052 + /*
2053 + * Find matching pattern within text buffer area to parse in
2054 + * forward direction.
2055 + */
2056 + endStartPos =
2057 + findRelatedForwardPattern(
2058 + smTable,
2059 + searchRegion,
2060 + delimiters,
2061 + matchInfo->meiPatRef,
2062 + matchInfo->meiHighLightCode,
2063 + &matchInfo->meiBackRefInfo,
2064 + beginPos,
2065 + &endEndPos);
2067 + if (endEndPos != -1)
2069 + *matchPos = endEndPos - 1 + searchRegion->sriStartOfTextPos;
2070 + *matchedPatternLength = endEndPos - endStartPos;
2072 + matchingPatternFound = TRUE;
2074 + else if (matchElement->mpteIsMonoPattern)
2076 + /*
2077 + * mono pattern: forward find fails -> try backward direction.
2078 + * Calc. relative position of 1st char. before found string pattern.
2079 + */
2080 + beginPos = beginPos - matchInfo->meiLength - 1;
2082 + if (beginPos > 0)
2084 + startStartPos =
2085 + findRelatedStartPattern(
2086 + smTable,
2087 + searchRegion,
2088 + delimiters,
2089 + matchInfo->meiPatRef,
2090 + matchInfo->meiHighLightCode,
2091 + &matchInfo->meiBackRefInfo,
2092 + beginPos,
2093 + matchedPatternLength);
2095 + if (startStartPos != -1)
2097 + matchInfo->meiDirection = SEARCH_BACKWARD;
2099 + *matchPos = startStartPos + searchRegion->sriStartOfTextPos;
2101 + matchingPatternFound = TRUE;
2106 + return matchingPatternFound;
2110 +** Find matching pattern related to given begin pattern reference
2111 +** in forward direction by considering the rules stored in given
2112 +** string match table. Determine match position (= relative
2113 +** pos. of last character of matching string).
2114 +** Returns -1, if no matching pattern was found. Else the relative
2115 +** position of 1st char. of matching string is returned.
2117 +static int findRelatedForwardPattern(
2118 + StringMatchTable *table,
2119 + SearchRegionInfo *searchRegion,
2120 + const char *delimiters,
2121 + PatternReference beginPatRef,
2122 + int beginPatHighLightCode,
2123 + BackRefInfo *beginPatBackRefInfo,
2124 + int beginPos,
2125 + int *matchEndPos)
2127 + MatchPatternTable *patTable = table->smtAllPatterns;
2128 + int startPos = beginPos;
2129 + int nxtPatStartPos = 0;
2130 + int nxtPatEndPos = 0;
2131 + PatternReference nxtPatRef;
2132 + int nxtPatHighLightCode;
2133 + BackRefInfo nxtPatBackRefInfo;
2134 + PatternStackElement stack[MAX_NESTED_PATTERNS];
2135 + int stackIdx = 0;
2136 + PatternReference startPatRef;
2137 + MatchPatternTableElement *currentElement;
2138 + int groupIdx;
2139 + regexp *groupPatRE;
2140 + regexp *currentPatRE;
2141 + int skipToEnd = FALSE;
2142 + int beginPatternIsMono;
2144 +#ifdef DEBUG_FIND
2145 + printf("Forward Start Pos: %d K: %s EI: %d PI: %d HC: %d <%s>\n",
2146 + startPos,
2147 + patElemKindToString(beginPatRef.prKind),
2148 + beginPatRef.prElementIdx,
2149 + beginPatRef.prPatternIdx,
2150 + beginPatHighLightCode,
2151 + getPatternForDebug(patTable, beginPatRef) );
2152 +#endif
2154 + /*
2155 + * put begin pattern info on stack
2156 + */
2157 + stack[stackIdx].psePatRef = beginPatRef;
2158 + stack[stackIdx].pseHighLightCode = beginPatHighLightCode;
2159 + stack[stackIdx].pseBackRefInfo = *beginPatBackRefInfo;
2160 + stackIdx ++;
2162 + currentElement = patTable->mptElements[beginPatRef.prElementIdx];
2164 + beginPatternIsMono = currentElement->mpteIsMonoPattern;
2166 + groupIdx = currentElement->mpteGroup;
2168 + /*
2169 + * no next pattern can be found, if there is no group assigned
2170 + * to begin pattern (should never occur)
2171 + */
2172 + if (groupIdx == NO_GROUP_IDX)
2174 + *matchEndPos = -1;
2176 + return -1;
2179 + /*
2180 + * Remember pattern (= keywords) regular expression of context
2181 + * group related to begin pattern. Use it for forward search.
2182 + */
2183 + groupPatRE = table->smtGroups[groupIdx]->mpgeKeywordRE;
2184 + currentPatRE = groupPatRE;
2186 + /*
2187 + * Use start / end pattern regular expression if skip to end is
2188 + * set for begin pattern.
2189 + */
2190 + if (currentElement->mpteSkipBtwnStartEnd)
2192 + currentPatRE = currentElement->mpteStartEndRE;
2193 + skipToEnd = TRUE;
2196 + while (stackIdx > 0 && nxtPatStartPos != -1)
2198 + /*
2199 + * Search for next string pattern in forward direction.
2200 + */
2201 + nxtPatStartPos =
2202 + searchPatternForward(
2203 + patTable,
2204 + currentPatRE,
2205 + searchRegion,
2206 + delimiters,
2207 + startPos,
2208 + &nxtPatEndPos,
2209 + &nxtPatRef,
2210 + &nxtPatHighLightCode,
2211 + &nxtPatBackRefInfo );
2213 + startPatRef = stack[stackIdx-1].psePatRef;
2215 + if (nxtPatStartPos == -1)
2217 + /*
2218 + * no next pattern found -> leave loop
2219 + */
2220 +#ifdef DEBUG_FIND
2221 + printf(" SI: %d [start K: %s EI: %d PI %d] Pos: %d --> no next pat. found\n",
2222 + stackIdx,
2223 + patElemKindToString(startPatRef.prKind),
2224 + startPatRef.prElementIdx,
2225 + startPatRef.prPatternIdx,
2226 + startPos);
2227 +#endif
2228 + break;
2231 + /*
2232 + * Update start pattern reference depending on next pattern
2233 + * located after start pattern.
2234 + */
2235 + considerNextPatternReference(
2236 + patTable,
2237 + &startPatRef,
2238 + nxtPatRef,
2239 + groupIdx );
2241 + /*
2242 + * If current found match pattern table element is a mono pattern and
2243 + * skip to start pattern is active, then the found pattern string is
2244 + * a END one in case of ambiguous or no syntax was detected.
2245 + */
2246 + if (skipToEnd &&
2247 + (nxtPatRef.prMonoInfo == PEMI_MONO_AMBIGUOUS_SYNTAX ||
2248 + nxtPatRef.prMonoInfo == PEMI_MONO_NOT_SYNTAX_BASED))
2250 + nxtPatRef.prKind = PEK_END;
2253 +#ifdef DEBUG_FIND
2254 + printf(" SI: %d [start K: %s EI: %d PI %d] Pos: %d-%d K: %s EI: %d PI: %d HC: %d f=<%s> ",
2255 + stackIdx,
2256 + patElemKindToString(startPatRef.prKind),
2257 + startPatRef.prElementIdx,
2258 + startPatRef.prPatternIdx,
2259 + nxtPatStartPos,
2260 + nxtPatEndPos,
2261 + patElemKindToString(nxtPatRef.prKind),
2262 + nxtPatRef.prElementIdx,
2263 + nxtPatRef.prPatternIdx,
2264 + nxtPatHighLightCode,
2265 + getPatternForDebug(patTable, nxtPatRef) );
2266 + printFoundStringForDebug(
2267 + searchRegion->sriWindow,
2268 + nxtPatStartPos + searchRegion->sriStartOfTextPos,
2269 + nxtPatEndPos - nxtPatStartPos);
2270 + printf("\n");
2271 +#endif
2273 + if (nxtPatRef.prKind == PEK_START)
2275 + if (stackIdx >= MAX_NESTED_PATTERNS)
2277 +#ifdef DEBUG_FIND
2278 + printf("FORWARD: MAX. NESTED PATTERN DEPTH REACHED !\n");
2279 +#endif
2280 + nxtPatStartPos = -1;
2281 + nxtPatEndPos = -1;
2283 + else if (!skipToEnd)
2285 + /*
2286 + * Put next pattern on stack, if contents between start /
2287 + * end shouldn't be skipped (if "skipToEnd" is set,
2288 + * a (usually illegal) start pattern to skip inside the
2289 + * skipped one is found (e.g. \* \* ..)
2290 + */
2291 + stack[stackIdx].psePatRef = nxtPatRef;
2292 + stack[stackIdx].pseHighLightCode = nxtPatHighLightCode;
2293 + stack[stackIdx].pseBackRefInfo = nxtPatBackRefInfo;
2294 + stackIdx ++;
2296 + currentElement = patTable->mptElements[nxtPatRef.prElementIdx];
2298 + /*
2299 + * Use start / end pattern regular expression if skip to
2300 + * end is set for found start pattern.
2301 + */
2302 + if (currentElement->mpteSkipBtwnStartEnd)
2304 + currentPatRE = currentElement->mpteStartEndRE;
2305 + skipToEnd = TRUE;
2308 + else if (beginPatternIsMono)
2310 + /*
2311 + * skip to end is set and a mono pattern start is reached:
2312 + * trigger backward search by returning "not found"
2313 + */
2314 +#ifdef DEBUG_FIND
2315 + printf(" ---> mono pattern (re-)start -> trigger backward search\n");
2316 +#endif
2317 + nxtPatStartPos = -1;
2318 + nxtPatEndPos = -1;
2320 +#ifdef DEBUG_FIND
2321 + else
2323 + printf(" ---> skip to end: illegal (re-)start pattern !\n");
2325 +#endif
2327 + else if (nxtPatRef.prKind == PEK_END)
2329 + /*
2330 + * ignore current found pattern, if it doesn't fit to the prev.
2331 + * opened one.
2332 + */
2333 + if (isPartOfPattern(
2334 + patTable,
2335 + nxtPatRef.prElementIdx,
2336 + startPatRef.prElementIdx,
2337 + PEK_END) &&
2338 + (stack[stackIdx - 1].pseHighLightCode == nxtPatHighLightCode ||
2339 + stack[stackIdx - 1].pseHighLightCode == IGNORE_HIGHLIGHT_CODE ||
2340 + nxtPatHighLightCode == IGNORE_HIGHLIGHT_CODE) &&
2341 + doesBackRefInfoMatch(
2342 + &stack[stackIdx - 1].pseBackRefInfo,
2343 + &nxtPatBackRefInfo))
2345 + /*
2346 + * use context group pattern again, if end pattern to skip
2347 + * to was found.
2348 + */
2349 + if (skipToEnd)
2351 + currentPatRE = groupPatRE;
2352 + skipToEnd = FALSE;
2355 + /*
2356 + * pop. related start pattern from stack.
2357 + */
2358 + stackIdx --;
2361 + else if (!skipToEnd)
2363 + /*
2364 + * middle pattern was found: ignore it, if found middle pattern
2365 + * doesn't belong to begin pattern.
2366 + */
2367 + if (stackIdx == 1 &&
2368 + isPartOfPattern(
2369 + patTable,
2370 + startPatRef.prElementIdx,
2371 + nxtPatRef.prElementIdx,
2372 + nxtPatRef.prKind) &&
2373 + (beginPatHighLightCode == nxtPatHighLightCode ||
2374 + beginPatHighLightCode == IGNORE_HIGHLIGHT_CODE ||
2375 + nxtPatHighLightCode == IGNORE_HIGHLIGHT_CODE) &&
2376 + doesBackRefInfoMatch(
2377 + beginPatBackRefInfo,
2378 + &nxtPatBackRefInfo))
2381 + stackIdx --;
2385 + startPos = nxtPatEndPos;
2388 + *matchEndPos = nxtPatEndPos;
2390 + return nxtPatStartPos;
2394 +** Find matching pattern related to given pattern (stored in
2395 +** 'matchInfo') in backward direction by considering the rules stored in
2396 +** string match table of given window. Determine match position (= abs.
2397 +** pos. of 1st character of matching string) and length of matching
2398 +** string.
2399 +** Returns true, if a matching pattern was found.
2401 +static int parseStringElementBackward(
2402 + MatchingElementInfo *matchInfo,
2403 + SearchRegionInfo *searchRegion,
2404 + int relCharPos,
2405 + int *matchPos,
2406 + int *matchedPatternLength,
2407 + const char *delimiters)
2409 + StringMatchTable *smTable =
2410 + (StringMatchTable *)searchRegion->sriWindow->stringMatchTable;
2411 + int beginPos;
2412 + int startStartPos;
2413 + int matchingPatternFound = FALSE;
2415 + /*
2416 + * determine begin of search in string buffer (= relative position
2417 + * of 1st char. before found string pattern.)
2418 + */
2419 + beginPos = relCharPos - matchInfo->meiLength - 1;
2421 + if (beginPos < 0)
2422 + return FALSE;
2424 + /*
2425 + * Find matching pattern within text buffer area to parse in
2426 + * backward direction.
2427 + */
2428 + startStartPos =
2429 + findRelatedStartPattern(
2430 + smTable,
2431 + searchRegion,
2432 + delimiters,
2433 + matchInfo->meiPatRef,
2434 + matchInfo->meiHighLightCode,
2435 + &matchInfo->meiBackRefInfo,
2436 + beginPos,
2437 + matchedPatternLength);
2439 + if (startStartPos != -1)
2441 + *matchPos = startStartPos + searchRegion->sriStartOfTextPos;
2442 + matchingPatternFound = TRUE;
2445 + return matchingPatternFound;
2449 +** Find matching pattern related to given begin pattern reference
2450 +** in backward direction by considering the rules stored in given
2451 +** string match table. Determine match position (= relative
2452 +** pos. of 1st character of matching string).
2453 +** Returns -1, if no matching pattern was found. Else the relative
2454 +** position of 1st char. of matching string is returned.
2456 +static int findRelatedStartPattern(
2457 + StringMatchTable *table,
2458 + SearchRegionInfo *searchRegion,
2459 + const char *delimiters,
2460 + PatternReference beginPatRef,
2461 + int beginPatHighLightCode,
2462 + BackRefInfo *beginPatBackRefInfo,
2463 + int beginPos,
2464 + int *matchedPatternLength)
2466 + MatchPatternTable *patTable = table->smtAllPatterns;
2467 + int startPos = beginPos;
2468 + int prevStartPos = 0;
2469 + PatternReference prevPatRef;
2470 + int prevPatHighLightCode;
2471 + BackRefInfo prevPatBackRefInfo;
2472 + PatternStackElement stack[MAX_NESTED_PATTERNS];
2473 + int stackIdx = 0;
2474 + MatchPatternTableElement *currentElement;
2475 + int groupIdx;
2476 + regexp *groupPatRE;
2477 + regexp *currentPatRE;
2478 + int skipToStart = FALSE;
2480 + /*
2481 + * put begin pattern info on stack
2482 + */
2483 + stack[stackIdx].psePatRef = beginPatRef;
2484 + stack[stackIdx].pseHighLightCode = beginPatHighLightCode;
2485 + stack[stackIdx].pseBackRefInfo = *beginPatBackRefInfo;
2486 + stackIdx ++;
2488 + currentElement = patTable->mptElements[beginPatRef.prElementIdx];
2490 +#ifdef DEBUG_FIND
2491 + printf("Backward Start Pos: %d K: %s EI: %d PI: %d HC: %d <%s>\n",
2492 + startPos,
2493 + patElemKindToString(beginPatRef.prKind),
2494 + beginPatRef.prElementIdx,
2495 + beginPatRef.prPatternIdx,
2496 + beginPatHighLightCode,
2497 + getPatternForDebug(patTable, beginPatRef) );
2498 +#endif
2500 + groupIdx = currentElement->mpteGroup;
2502 + /*
2503 + * no start pattern can be found, if there is no group assigned
2504 + * to begin pattern (should never occur)
2505 + */
2506 + if (groupIdx == NO_GROUP_IDX)
2508 + return -1;
2511 + /*
2512 + * Remember pattern (= keywords) regular expression of context
2513 + * group related to begin pattern. Use it for backward search.
2514 + */
2515 + groupPatRE = table->smtGroups[groupIdx]->mpgeKeywordRE;
2516 + currentPatRE = groupPatRE;
2518 + /*
2519 + * Use start / end pattern regular expression if skip to start is
2520 + * set for begin pattern.
2521 + */
2522 + if (currentElement->mpteSkipBtwnStartEnd)
2524 + currentPatRE = currentElement->mpteStartEndRE;
2525 + skipToStart = TRUE;
2528 + while (stackIdx > 0 && prevStartPos != -1)
2530 + /*
2531 + * Search for previous string pattern in backward direction.
2532 + */
2533 + prevStartPos =
2534 + searchPatternBackward(
2535 + patTable,
2536 + currentPatRE,
2537 + searchRegion,
2538 + delimiters,
2539 + startPos,
2540 + &prevPatRef,
2541 + &prevPatHighLightCode,
2542 + matchedPatternLength,
2543 + &prevPatBackRefInfo );
2545 + if (prevStartPos == -1)
2547 + /*
2548 + * no previous pattern found -> leave loop
2549 + */
2550 +#ifdef DEBUG_FIND
2551 + printf(" SI: %d [K: %s start EI: %d PI %d] Pos: %d --> no next pat. found\n",
2552 + stackIdx,
2553 + patElemKindToString(stack[stackIdx -1].psePatRef.prKind),
2554 + stack[stackIdx -1].psePatRef.prElementIdx,
2555 + stack[stackIdx -1].psePatRef.prPatternIdx,
2556 + startPos);
2557 +#endif
2558 + break;
2561 + /*
2562 + * Update previous pattern reference depending on last stack
2563 + * pattern, which is located in text puffer after previous
2564 + * start pattern.
2565 + */
2566 + considerNextPatternReference(
2567 + patTable,
2568 + &prevPatRef,
2569 + stack[stackIdx - 1].psePatRef,
2570 + groupIdx);
2572 + /*
2573 + * If current found match pattern table element is a mono pattern and
2574 + * skip to start pattern is active, then the found pattern string is
2575 + * a START one in case of ambiguous or no syntax was detected.
2576 + */
2577 + if (skipToStart &&
2578 + (prevPatRef.prMonoInfo == PEMI_MONO_AMBIGUOUS_SYNTAX ||
2579 + prevPatRef.prMonoInfo == PEMI_MONO_NOT_SYNTAX_BASED))
2581 + prevPatRef.prKind = PEK_START;
2584 +#ifdef DEBUG_FIND
2585 + printf(" SI: %d [K: %s start EI: %d PI %d] Pos: %d K: %s EI: %d PI: %d HC: %d f=<%s> ",
2586 + stackIdx,
2587 + patElemKindToString(stack[stackIdx -1].psePatRef.prKind),
2588 + stack[stackIdx -1].psePatRef.prElementIdx,
2589 + stack[stackIdx -1].psePatRef.prPatternIdx,
2590 + prevStartPos,
2591 + patElemKindToString(prevPatRef.prKind),
2592 + prevPatRef.prElementIdx,
2593 + prevPatRef.prPatternIdx,
2594 + prevPatHighLightCode,
2595 + getPatternForDebug(patTable, prevPatRef) );
2596 + printFoundStringForDebug(
2597 + searchRegion->sriWindow,
2598 + prevStartPos + searchRegion->sriStartOfTextPos,
2599 + *matchedPatternLength);
2600 + printf("\n");
2601 +#endif
2603 + if (prevPatRef.prKind == PEK_START)
2605 + /*
2606 + * If the end pattern of the previous pattern set is a reference,
2607 + * then the prev. element index is the one of the ref. (due to this
2608 + * string was found before and was stored on stack)
2609 + */
2610 + if (patTable->mptElements[prevPatRef.prElementIdx]->mpteGroup == groupIdx)
2612 + considerStackPatReference(
2613 + &patTable->mptElements[prevPatRef.prElementIdx]->mpteEnd,
2614 + stack[stackIdx - 1].psePatRef.prElementIdx,
2615 + &prevPatRef.prElementIdx);
2618 + /*
2619 + * Ignore current found pattern, if it doesn't fit to the prev.
2620 + * opened one.
2621 + */
2622 + if (stack[stackIdx - 1].psePatRef.prElementIdx == prevPatRef.prElementIdx &&
2623 + (stack[stackIdx - 1].pseHighLightCode == prevPatHighLightCode ||
2624 + stack[stackIdx - 1].pseHighLightCode == IGNORE_HIGHLIGHT_CODE ||
2625 + prevPatHighLightCode == IGNORE_HIGHLIGHT_CODE) &&
2626 + doesBackRefInfoMatch(
2627 + &stack[stackIdx - 1].pseBackRefInfo,
2628 + &prevPatBackRefInfo))
2630 + /*
2631 + * use context group pattern again, if start pattern
2632 + * to skip to was found.
2633 + */
2634 + if (skipToStart)
2636 + currentPatRE = groupPatRE;
2637 + skipToStart = FALSE;
2640 + /*
2641 + * pop. related end pattern from stack.
2642 + */
2643 + stackIdx --;
2646 + else if (prevPatRef.prKind == PEK_END)
2648 + if (stackIdx >= MAX_NESTED_PATTERNS)
2650 +#ifdef DEBUG_FIND
2651 + printf("BACKWARD: MAX. NESTED PATTERN DEPTH REACHED !\n");
2652 +#endif
2653 + prevStartPos = -1;
2655 + else if (!skipToStart)
2657 + /*
2658 + * Put prev. pattern on stack, if contents between start /
2659 + * end shouldn't be skipped (if "skipToStart" is set,
2660 + * a (usually illegal) end pattern to skip inside the
2661 + * skipped one is found (e.g. *\ *\ ..)
2662 + */
2663 + stack[stackIdx].psePatRef = prevPatRef;
2664 + stack[stackIdx].pseHighLightCode = prevPatHighLightCode;
2665 + stack[stackIdx].pseBackRefInfo = prevPatBackRefInfo;
2666 + stackIdx ++;
2668 + currentElement =
2669 + patTable->mptElements[prevPatRef.prElementIdx];
2671 + /*
2672 + * Use start / end pattern regular expression if skip to
2673 + * end is set for found end pattern.
2674 + */
2675 + if (currentElement->mpteSkipBtwnStartEnd)
2677 + currentPatRE = currentElement->mpteStartEndRE;
2678 + skipToStart = TRUE;
2682 + startPos = prevStartPos - 1;
2685 + return prevStartPos;
2689 +** Adapt found pattern element index depending on
2690 +** the info stored on (last) stack element and
2691 +** a given pattern set (belonging to the found pattern).
2693 +static void considerStackPatReference(
2694 + PatternElementSet *patSet,
2695 + int stackElementIdx,
2696 + int *foundElementIdx)
2698 + PatternElement *patElement;
2699 + int i;
2701 + /*
2702 + * If found pattern index already indicates, that found pattern
2703 + * belongs to pattern set stored on stack, then no adaption is needed
2704 + */
2705 + if (*foundElementIdx == stackElementIdx)
2706 + return;
2708 + /*
2709 + * Check all elements of given pattern element set:
2710 + */
2711 + for (i=0; i < patSet->pesNumberOfPattern; i++)
2713 + patElement = patSet->pesPattern[i];
2715 + /*
2716 + * If this set element is a reference and this reference fits
2717 + * to the element stored on stack, then adapt found element index:
2718 + * indicate, that found pattern belongs to pattern set stored on stack
2719 + */
2720 + if (patElement->peType == PET_REFERENCE &&
2721 + patElement->peVal.peuRef.prElementIdx == stackElementIdx)
2723 + *foundElementIdx = stackElementIdx;
2725 + return;
2731 +** Determines, if a string pattern is located at the given position
2732 +** "relBeginPos" in the given "searchRegion". A string pattern is
2733 +** found, if the pattern is located just before given position
2734 +** "relBeginPos" OR if "relBeginPos" is located within a string pattern.
2736 +** Returns true, if the given "pattern" is located at
2737 +** "relBeginPos". "matchInfo" holds all info needed about matched
2738 +** "start" string pattern.
2740 +static int getPatternLocatedAtPos(
2741 + regexp *usedPatRE,
2742 + MatchPatternTable *table,
2743 + SearchRegionInfo *searchRegion,
2744 + int *relBeginPos,
2745 + MatchingElementInfo *matchInfo,
2746 + const char *delimiters)
2748 + int searchStartPos = *relBeginPos;
2749 + PatternReference *patRef = &matchInfo->meiPatRef;
2750 + FoundStringInfo foundStringInfo;
2751 + int relMatchStartPos;
2752 + int relMatchEndPos;
2754 + patRef->prElementIdx = NO_ELEMENT_IDX;
2755 + patRef->prKind = PEK_UNKNOWN;
2756 + patRef->prPatternIdx = NO_PATTERN_IDX;
2758 + matchInfo->meiHighLightCode = IGNORE_HIGHLIGHT_CODE;
2759 + matchInfo->meiAbsStartPos = -1;
2760 + matchInfo->meiLength = 0;
2762 + /*
2763 + * No backward search possible, if we are at beginning of
2764 + * search region
2765 + */
2766 + if (searchStartPos == 0)
2767 + return FALSE;
2769 + /*
2770 + * Search in backward direction for 1st occurance of a string pattern
2771 + * starting one char before "searchStartPos".
2772 + */
2773 + if (ExecRE(
2774 + usedPatRE,
2775 + searchRegion->sriText,
2776 + searchRegion->sriText + searchStartPos - 1,
2777 + TRUE,
2778 + searchRegion->sriPrevChar,
2779 + searchRegion->sriText[searchStartPos],
2780 + delimiters,
2781 + searchRegion->sriText,
2782 + NULL))
2784 + /*
2785 + * String pattern was found:
2786 + */
2787 + foundStringInfo.fsiStartPtr = usedPatRE->startp[0];
2788 + foundStringInfo.fsiEndPtr = usedPatRE->endp[0];
2789 + foundStringInfo.fsiLength =
2790 + foundStringInfo.fsiEndPtr - foundStringInfo.fsiStartPtr;
2792 + relMatchEndPos = foundStringInfo.fsiEndPtr - searchRegion->sriText;
2793 + relMatchStartPos = foundStringInfo.fsiStartPtr - searchRegion->sriText;
2795 + /*
2796 + * Is found pattern located exactly one char before "relBeginPos" OR
2797 + * is "relBeginPos" located within found string pattern ?
2798 + * Note: "relMatchEndPos" indicates 1st pos. in "sriText"
2799 + * which does *not* belong to found string anymore.
2800 + */
2801 + if ((*relBeginPos == relMatchEndPos) ||
2802 + (*relBeginPos >= relMatchStartPos &&
2803 + *relBeginPos < relMatchEndPos))
2805 + *relBeginPos = relMatchEndPos;
2807 + /*
2808 + * Determine match element info related to found string.
2809 + */
2810 + matchInfo->meiAbsStartPos =
2811 + foundStringInfo.fsiStartPtr - searchRegion->sriText +
2812 + searchRegion->sriStartOfTextPos;
2813 + matchInfo->meiLength = foundStringInfo.fsiLength;
2815 + foundStringInfo.fsiPrevChar =
2816 + foundStringInfo.fsiStartPtr == searchRegion->sriText ?
2817 + searchRegion->sriPrevChar : *(foundStringInfo.fsiStartPtr - 1);
2819 + foundStringInfo.fsiSuccChar =
2820 + *(foundStringInfo.fsiEndPtr) == '\0' ?
2821 + searchRegion->sriSuccChar : *(foundStringInfo.fsiEndPtr);
2823 + foundStringInfo.fsiDelimiters = delimiters;
2825 + return(
2826 + getMatchedElementInfo(
2827 + searchRegion->sriWindow,
2828 + table,
2829 + &foundStringInfo,
2830 + matchInfo));
2834 + return FALSE;
2838 +** Get all needed info related to matched "start" string pattern
2839 +** (given by parameter "foundStringInfo").
2841 +** Returns true, if info was determined successfully.
2843 +static int getMatchedElementInfo(
2844 + WindowInfo *window,
2845 + MatchPatternTable *table,
2846 + FoundStringInfo *foundStringInfo,
2847 + MatchingElementInfo *matchInfo)
2849 + PatternReference *patRef = &matchInfo->meiPatRef;
2850 + int absMatchStartPos = matchInfo->meiAbsStartPos;
2851 + MatchPatternTableElement *matchedElement;
2853 + if (getPatternInfo(
2854 + table,
2855 + foundStringInfo,
2856 + patRef,
2857 + &matchInfo->meiBackRefInfo))
2859 + /*
2860 + * A pattern reference could be assigned to found string:
2861 + */
2862 + matchedElement = table->mptElements[patRef->prElementIdx];
2864 + matchInfo->meiElement = matchedElement;
2866 + /*
2867 + * get highlight code of found string pattern, if applicable
2868 + */
2869 + if (!matchedElement->mpteIgnoreHighLightInfo)
2871 + matchInfo->meiHighLightCode =
2872 + HighlightCodeOfPos(window, absMatchStartPos);
2875 + /*
2876 + * setup mono pattern info of found string pattern
2877 + */
2878 + if (matchedElement->mpteIsMonoPattern)
2880 + if (matchedElement->mpteIgnoreHighLightInfo)
2882 + patRef->prMonoInfo = PEMI_MONO_NOT_SYNTAX_BASED;
2884 + else
2886 + /*
2887 + * determine mono pattern info depending on highLightCodes
2888 + * before / after found string pattern.
2889 + */
2890 + patRef->prMonoInfo =
2891 + determineMonoPatInfo(
2892 + window,
2893 + matchInfo->meiHighLightCode,
2894 + absMatchStartPos - 1,
2895 + absMatchStartPos + matchInfo->meiLength,
2896 + &patRef->prKind);
2899 + else
2901 + patRef->prMonoInfo = PEMI_NOT_MONO;
2904 + return TRUE;
2906 + else
2908 + /*
2909 + * Found string can't be assigned to a pattern element
2910 + * (should never occur).
2911 + */
2912 + return FALSE;
2917 +** Returns string pattern of given pattern element.
2919 +StringPattern *GetStringPattern(
2920 + MatchPatternTable *table,
2921 + PatternElement *pattern )
2923 + switch (pattern->peType)
2925 + case PET_SINGLE:
2926 + return &pattern->peVal.peuSingle;
2927 + break;
2929 + case PET_MULTIPLE:
2930 + return &pattern->peVal.peuMulti.mpStringPattern;
2931 + break;
2933 + case PET_REFERENCE:
2934 + return GetStringPattern(
2935 + table,
2936 + getPatternOfReference(table, pattern->peVal.peuRef));
2937 + break;
2940 + /*
2941 + * never reached; just to make compiler happy
2942 + */
2943 + return NULL;
2947 +** Returns pattern element of given pattern reference.
2949 +static PatternElement *getPatternOfReference(
2950 + MatchPatternTable *table,
2951 + PatternReference patRef)
2953 + MatchPatternTableElement **element = table->mptElements;
2955 + return element[ patRef.prElementIdx ]->mpteAll.pesPattern[patRef.prPatternIdx];
2958 +#ifdef DEBUG_FIND
2959 +static char *getPatternForDebug(
2960 + MatchPatternTable *table,
2961 + PatternReference patRef )
2963 + if (patRef.prElementIdx < 0)
2965 + return "---";
2968 + return
2969 + GetStringPattern(
2970 + table,
2971 + getPatternOfReference(table, patRef))->spText;
2974 +static char *patElemKindToString(
2975 + PatternElementKind patElemKind)
2977 + if (patElemKind == PEK_START)
2978 + return "START";
2979 + else if (patElemKind == PEK_MIDDLE)
2980 + return "MIDDLE";
2981 + else if (patElemKind == PEK_END)
2982 + return "END";
2983 + else
2984 + return "UNKNOWN";
2987 +static void printFoundStringForDebug(
2988 + WindowInfo *window,
2989 + int absStartPos,
2990 + int length)
2992 + char *foundStr =
2993 + BufGetRange( window->buffer, absStartPos, absStartPos + length);
2995 + printf("%d (abs.) <%s>",
2996 + absStartPos,
2997 + foundStr);
2999 + XtFree(foundStr);
3001 +#endif
3004 diff --quilt /dev/null new/source/patternMatch.h
3005 --- /dev/null
3006 +++ new/source/patternMatch.h
3007 @@ -0,0 +1,170 @@
3008 +/* $Id: patternMatch.h,v 1.2 2003/10/11 16:45:25 uleh Exp $ */
3010 +#ifndef NEDIT_PATTERNMATCH_H_INCLUDED
3011 +#define NEDIT_PATTERNMATCH_H_INCLUDED
3013 +#include "regularExp.h"
3015 +#define NO_GROUP_IDX -1
3016 +#define NO_ELEMENT_IDX -1
3017 +#define NO_PATTERN_IDX -1
3019 +#define MAX_GLOBAL_BACK_REF_ID 9
3020 +#define NO_LOCAL_BACK_REF_ID -1
3022 +typedef enum {
3023 + PEK_UNKNOWN,
3024 + PEK_START,
3025 + PEK_END,
3026 + PEK_MIDDLE
3027 +} PatternElementKind;
3029 +typedef enum {
3030 + PEMI_NOT_MONO,
3031 + PEMI_MONO_NOT_SYNTAX_BASED,
3032 + PEMI_MONO_AMBIGUOUS_SYNTAX,
3033 + PEMI_MONO_DEFINITE_SYNTAX
3034 +} PatternElementMonoInfo;
3036 +typedef struct _PatternReference {
3037 + PatternElementKind prKind;
3038 + PatternElementMonoInfo prMonoInfo;
3039 + int prElementIdx;
3040 + int prPatternIdx;
3041 +} PatternReference;
3043 +typedef enum {
3044 + MPT_INDIVIDUAL,
3045 + MPT_SUB,
3046 + MPT_GROUP
3047 +} MatchPatternType;
3049 +typedef struct _MatchPatternSequenceElement {
3050 + char *mpseName;
3051 + MatchPatternType mpseType;
3052 + int mpseIndex;
3053 +} MatchPatternSequenceElement;
3055 +typedef struct _MatchPatternGroupElement {
3056 + char *mpgeName;
3057 + int mpgeNumberOfSubPatterns;
3058 + char **mpgeSubPatternIds;
3059 + regexp *mpgeKeywordRE;
3060 +} MatchPatternGroupElement;
3062 +typedef enum {
3063 + PWB_NONE,
3064 + PWB_LEFT,
3065 + PWB_RIGHT,
3066 + PWB_BOTH
3067 +} PatternWordBoundary;
3069 +typedef struct _StrPatBackRefElement{
3070 + int spbreLocalBackRefID;
3071 + char *spbreRegExpText;
3072 +} StrPatBackRefElement;
3074 +typedef struct _StringPattern {
3075 + char *spText;
3076 + int spLength;
3077 + PatternWordBoundary spWordBoundary;
3078 + int spCaseInsensitive;
3079 + int spRegularExpression;
3080 + regexp *spTextRE;
3081 + char *spOrigText;
3082 + int spBackRefParsed;
3083 + int spBackRefResolved;
3084 + StrPatBackRefElement spOwnGlobalBackRef[MAX_GLOBAL_BACK_REF_ID];
3085 + int spGlobalToLocalBackRef[MAX_GLOBAL_BACK_REF_ID];
3086 +} StringPattern;
3088 +typedef struct _MultiPattern {
3089 + StringPattern mpStringPattern;
3090 + int mpNumberOfReferences;
3091 + PatternReference *mpRefList;
3092 +} MultiPattern;
3094 +typedef enum {
3095 + PET_SINGLE,
3096 + PET_MULTIPLE,
3097 + PET_REFERENCE
3098 +} PatternElementType;
3100 +typedef struct _PatternElement {
3101 + int peIndex;
3102 + PatternElementKind peKind;
3103 + PatternElementType peType;
3104 + union {
3105 + StringPattern peuSingle;
3106 + MultiPattern peuMulti;
3107 + PatternReference peuRef;
3108 + } peVal;
3109 +} PatternElement;
3111 +typedef struct _PatternElementSet {
3112 + int pesNumberOfPattern;
3113 + PatternElement **pesPattern;
3114 +} PatternElementSet;
3116 +typedef struct _GlobalBackRefElement{
3117 + StringPattern *gbreDefByStrPat;
3118 + char *gbreRegExpText;
3119 +} GlobalBackRefElement;
3121 +typedef struct _MatchPatternTableElement {
3122 + char *mpteName;
3123 + int mpteIndex;
3124 + MatchPatternType mpteType;
3125 + int mpteGroup;
3126 + PatternElementSet mpteAll;
3127 + PatternElementSet mpteStart;
3128 + PatternElementSet mpteMiddle;
3129 + PatternElementSet mpteEnd;
3130 + int mpteFlash;
3131 + int mpteIsMonoPattern;
3132 + int mpteSkipBtwnStartEnd;
3133 + int mpteIgnoreHighLightInfo;
3134 + regexp *mpteStartEndRE;
3135 + GlobalBackRefElement mpteGlobalBackRef[MAX_GLOBAL_BACK_REF_ID];
3136 +} MatchPatternTableElement;
3138 +typedef struct _MatchPatternTable {
3139 + int mptNumberOfElements;
3140 + MatchPatternTableElement **mptElements;
3141 +} MatchPatternTable;
3143 +typedef struct _StringMatchTable {
3144 + char *smtLanguageMode;
3145 + MatchPatternTable *smtAllPatterns;
3146 + regexp *smtAllPatRE;
3147 + regexp *smtFlashPatRE;
3148 + regexp *smtUsedPatRE;
3149 + int smtNumberOfGroups;
3150 + MatchPatternGroupElement **smtGroups;
3151 + int smtNumberOfSeqElements;
3152 + MatchPatternSequenceElement **smtSequence;
3153 +} StringMatchTable;
3155 +typedef enum {
3156 + MT_FLASH_DELIMIT,
3157 + MT_FLASH_RANGE,
3158 + MT_SELECT,
3159 + MT_GOTO,
3160 + MT_MACRO
3161 +} MatchingType;
3163 +int FindMatchingString(
3164 + WindowInfo *window,
3165 + MatchingType matchingType,
3166 + int *charPos,
3167 + int startLimit,
3168 + int endLimit,
3169 + int *matchPos,
3170 + int *matchLength,
3171 + int *direction);
3173 +StringPattern *GetStringPattern(
3174 + MatchPatternTable *table,
3175 + PatternElement *pattern);
3177 +#endif /* NEDIT_PATTERNMATCH_H_INCLUDED */
3178 diff --quilt /dev/null new/source/patternMatchData.c
3179 --- /dev/null
3180 +++ new/source/patternMatchData.c
3181 @@ -0,0 +1,7780 @@
3182 +static const char CVSID[] = "$Id: patternMatchData.c,v 1.4 2004/10/27 21:57:12 uleh Exp $";
3183 +/*******************************************************************************
3184 +* *
3185 +* patternMatchData.c -- Maintain and allow user to edit a matching pattern list*
3186 +* used for pattern matching *
3187 +* *
3188 +* Copyright (C) 2003-2004, Uwe Lehnert *
3189 +* *
3190 +* This is free software; you can redistribute it and/or modify it under the *
3191 +* terms of the GNU General Public License as published by the Free Software *
3192 +* Foundation; either version 2 of the License, or (at your option) any later *
3193 +* version. In addition, you may distribute versions of this program linked to *
3194 +* Motif or Open Motif. See README for details. *
3195 +* *
3196 +* This software is distributed in the hope that it will be useful, but WITHOUT *
3197 +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
3198 +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
3199 +* for more details. *
3200 +* *
3201 +* You should have received a copy of the GNU General Public License along with *
3202 +* software; if not, write to the Free Software Foundation, Inc., 59 Temple *
3203 +* Place, Suite 330, Boston, MA 02111-1307 USA *
3204 +* *
3205 +* Nirvana Text Editor *
3206 +* October 27, 2004 *
3207 +* *
3208 +* Written by Uwe Lehnert *
3209 +* *
3210 +*******************************************************************************/
3211 +#ifdef HAVE_CONFIG_H
3212 +#include "../config.h"
3213 +#endif
3215 +#include <stdlib.h>
3216 +#include <stdio.h>
3217 +#include <limits.h>
3218 +#include <string.h>
3219 +#include <ctype.h>
3221 +#ifdef VMS
3222 +#include "../util/VMSparam.h"
3223 +#else
3224 +#ifndef __MVS__
3225 +#include <sys/param.h>
3226 +#endif
3227 +#endif /*VMS*/
3229 +#include <Xm/Xm.h>
3230 +#include <Xm/Form.h>
3231 +#include <Xm/Frame.h>
3232 +#include <Xm/Text.h>
3233 +#include <Xm/LabelG.h>
3234 +#include <Xm/PushB.h>
3235 +#include <Xm/PushBG.h>
3236 +#include <Xm/ToggleB.h>
3237 +#include <Xm/RowColumn.h>
3238 +#include <Xm/SeparatoG.h>
3240 +#include "../util/misc.h"
3241 +#include "../util/DialogF.h"
3242 +#include "../util/managedList.h"
3244 +#include "regularExp.h"
3245 +#include "textBuf.h"
3246 +#include "nedit.h"
3247 +#include "window.h"
3248 +#include "preferences.h"
3249 +#include "help.h"
3250 +#include "file.h"
3251 +#include "textP.h"
3253 +#include "patternMatch.h"
3254 +#include "patternMatchData.h"
3256 +#ifdef HAVE_DEBUG_H
3257 +#include "../debug.h"
3258 +#endif
3261 + * local synonyms
3262 + */
3263 +#define MAX_LOCAL_BACK_REF_ID 9
3264 +#define LOCAL_BACK_REF_ID_USED -2
3266 +#define MAX_NUMBER_MIDDLE_PATTERN 10
3267 +#define MAX_STRING_PATTERNS 30
3268 +#define MAX_NBR_MATCH_PATTERNS 50
3269 +#define MAX_NBR_MATCH_PATTERN_GROUPS 50
3270 +#define MAX_NBR_SEQ_ELEMENTS MAX_NBR_MATCH_PATTERNS + MAX_NBR_MATCH_PATTERN_GROUPS
3272 +#define MATCH_PAT_NAME_LBL_TXT "Matching Pattern Name"
3273 +#define STRING_PATTERNS_LBL_TXT "String Patterns"
3275 +#define BORDER 4
3276 +#define LIST_RIGHT 41
3277 +#define PLAIN_LM_STRING "PLAIN"
3279 +#define SPNM_NONE_SELECTED "none selected"
3281 +#define KEEP_LANGUAGE_MODE True
3282 +#define DISCARD_LANGUAGE_MODE False
3284 +#define STRING_PATTERN_DIALOG True
3285 +#define CONTEXT_GROUP_DIALOG False
3288 + * local data definitions
3289 + */
3290 +typedef struct _ErrorInfo {
3291 + char *eiDetail;
3292 + char *eiLanguageMode;
3293 + char *eiMPTabElementName;
3294 + char *eiStringPatText;
3295 + char *eiRegExpCompileMsg;
3296 + int eiBackRefNbr;
3297 +} ErrorInfo;
3299 +typedef struct _BackRefBracketInfo {
3300 + int brbiGlobalId;
3301 + char *brbiContentStart;
3302 + int brbiNestingLevel;
3303 +} BackRefBracketInfo;
3305 +typedef struct _RegExpStringInfo {
3306 + int resiNbrOfAddedMultiPat;
3307 + PatternReference **resiAddedMultiPat;
3308 + char *resiNoneWBRegExpString;
3309 + char *resiLeftWBRegExpString;
3310 + char *resiRightWBRegExpString;
3311 + char *resiBothWBRegExpString;
3312 + int resiLocalBackRefID;
3313 +} RegExpStringInfo;
3315 +typedef struct _ReadMatchPatternInfo {
3316 + int rmpiNbrOfElements;
3317 + MatchPatternTableElement *rmpiElement[MAX_NBR_MATCH_PATTERNS];
3318 + int rmpiNbrOfGroups;
3319 + MatchPatternGroupElement *rmpiGroup[MAX_NBR_MATCH_PATTERN_GROUPS];
3320 + int rmpiNbrOfSeqElements;
3321 + MatchPatternSequenceElement *rmpiSequence[MAX_NBR_SEQ_ELEMENTS];
3322 + regexp *rmpiAllPatRE;
3323 + regexp *rmpiFlashPatRE;
3324 +} ReadMatchPatternInfo;
3326 +typedef struct _DialogStringPatternElement {
3327 + char *dspeText;
3328 + PatternElementKind dspeKind;
3329 + PatternWordBoundary dspeWordBoundary;
3330 + int dspeCaseInsensitive;
3331 + int dspeRegularExpression;
3332 +} DialogStringPatternElement;
3334 +typedef struct _DialogStringPatterns {
3335 + int dspNumberOfPatterns;
3336 + DialogStringPatternElement *dspElements[MAX_STRING_PATTERNS];
3337 +} DialogStringPatterns;
3339 +typedef struct _DialogMatchPatternTableElement {
3340 + char *dmpteName;
3341 + MatchPatternType dmpteType;
3342 + DialogStringPatterns dmptePatterns;
3343 + int dmpteSkipBtwnStartEnd;
3344 + int dmpteIgnoreHighLightInfo;
3345 + int dmpteFlash;
3346 +} DialogMatchPatternTableElement;
3348 +typedef struct _DialogMatchPatternGroupElement {
3349 + char *dmpgeName;
3350 + int dmpgeNumberOfSubPatterns;
3351 + char *dmpgeSubPatternIds[MAX_NBR_MATCH_PATTERNS];
3352 +} DialogMatchPatternGroupElement;
3354 +typedef struct _DialogMatchPatternSequenceElement {
3355 + char *dmpseName;
3356 + MatchPatternType dmpseType;
3357 + int dmpseValid;
3358 + void *dmpsePtr;
3359 +} DialogMatchPatternSequenceElement;
3361 +typedef struct _DialogMatchPatternInfo {
3362 + int dmpiNbrOfSeqElements;
3363 + DialogMatchPatternSequenceElement *dmpiSequence[MAX_NBR_SEQ_ELEMENTS];
3364 +} DialogMatchPatternInfo;
3366 +typedef enum {
3367 + DMPTR_OK,
3368 + DMPTR_EMPTY,
3369 + DMPTR_INCOMPLETE
3370 +} DMPTranslationResult;
3372 +typedef struct _NameList {
3373 + int nlNumber;
3374 + char *nlId[MAX_NBR_SEQ_ELEMENTS + 1];
3375 +} NameList;
3378 + * prototypes of local functions
3379 + */
3380 +static void treatDuplicatedPattern(
3381 + MatchPatternTable *table,
3382 + PatternElement *prevPattern,
3383 + PatternReference prevPatRef,
3384 + PatternElement *lastPattern,
3385 + PatternReference lastPatRef);
3386 +static void treatDuplicatedPatternElements(
3387 + MatchPatternTable *table,
3388 + MatchPatternTableElement *prevElement,
3389 + int prevElementIdx,
3390 + PatternElement *lastPattern,
3391 + PatternReference lastPatRef);
3392 +static void treatDuplicatedMTElements(
3393 + MatchPatternTable *table,
3394 + MatchPatternTableElement *prevElement,
3395 + int prevElementIdx,
3396 + MatchPatternTableElement *lastElement,
3397 + int lastElementIdx);
3398 +static void treatDuplicatedMTEntries(
3399 + MatchPatternTableElement **element,
3400 + int nbrOfElements);
3402 +static int createStrPatRegExpOfElement(
3403 + ReadMatchPatternInfo *readPatInfo,
3404 + MatchPatternTableElement *element,
3405 + ErrorInfo *errInfo);
3406 +static int createStrPatRegExp(
3407 + StringPattern *strPat,
3408 + ErrorInfo *errInfo);
3409 +static void adaptCompileMsg(
3410 + char *compileMsg,
3411 + int *globalToLocalBackRef);
3412 +static int localToGlobalBackRef(
3413 + int *globalToLocalBackRef,
3414 + int localId);
3415 +static int createStartEndRegExp(
3416 + ReadMatchPatternInfo *readMatchPatternInfo,
3417 + MatchPatternTableElement *element,
3418 + ErrorInfo *errInfo);
3419 +static int createGroupRegExp(
3420 + ReadMatchPatternInfo *readPatInfo,
3421 + MatchPatternGroupElement *group,
3422 + ErrorInfo *errInfo);
3423 +static void setupRegExpStringBuffers(
3424 + ReadMatchPatternInfo *readMatchPatternInfo,
3425 + RegExpStringInfo *regExpStringInfo);
3426 +static void addSMTRegExpString(
3427 + char *result,
3428 + char *partToAdd,
3429 + const char *postfix);
3430 +static void composeStartEndRegExpString(
3431 + ReadMatchPatternInfo *readMatchPatternInfo,
3432 + MatchPatternTableElement *element,
3433 + char **regExpString);
3434 +static void addElementToRegExpString(
3435 + MatchPatternTableElement *element,
3436 + ReadMatchPatternInfo *readMatchPatternInfo,
3437 + RegExpStringInfo *regExpStringInfo);
3438 +static void addUniquePatternToRegExpString(
3439 + PatternElement *patElement,
3440 + PatternReference *patElementReference,
3441 + ReadMatchPatternInfo *readMatchPatternInfo,
3442 + RegExpStringInfo *regExpStringInfo);
3443 +static void addPatternToRegExpString(
3444 + StringPattern *pattern,
3445 + RegExpStringInfo *regExpStringInfo);
3446 +static char *adaptLocalBackRefs(
3447 + char *regExpText,
3448 + int *commonLocalId);
3449 +static void scanForLocalBackRefs(
3450 + char *regExpText,
3451 + int *localBackRefList);
3452 +static int isMultiPatternNotAdded(
3453 + RegExpStringInfo *regExpStringInfo,
3454 + PatternReference *toBeAddedPR);
3455 +static void catSMTRegExpStrings(
3456 + RegExpStringInfo *regExpStringInfo,
3457 + char **regExpString);
3458 +static void freeRegExpStringInfo(
3459 + RegExpStringInfo *regExpStringInfo);
3460 +static int totalKeywordOfTableLen(
3461 + ReadMatchPatternInfo *info,
3462 + int *nbrOfMultiPatterns);
3463 +static int totalMatchPatternTableElementLen(
3464 + ReadMatchPatternInfo *info,
3465 + MatchPatternTableElement *element,
3466 + int *nbrOfMultiPatterns);
3467 +static int patternElementLen(
3468 + ReadMatchPatternInfo *info,
3469 + PatternElement *patElement,
3470 + int *nbrOfMultiPatterns);
3472 +static void parseMatchingPatternSetError(
3473 + const char *stringStart,
3474 + const char *stoppedAt,
3475 + ErrorInfo *errInfo);
3476 +static void dialogMatchingPatternSetError(
3477 + char *title,
3478 + ErrorInfo *errInfo);
3480 +static char *createMatchPatternsString(
3481 + StringMatchTable *table,
3482 + char *indentStr);
3483 +static char *createPatternElementString(
3484 + MatchPatternTable *table,
3485 + PatternElement *pat);
3487 +static StringMatchTable *readDefaultStringMatchTable(const char *langModeName);
3488 +static int isDefaultMatchPatternTable(StringMatchTable *table);
3490 +static void freeReadMatchPatternInfo( ReadMatchPatternInfo *readPatInfo );
3491 +static void freeStringMatchTable( StringMatchTable *table );
3492 +static void freeMatchPatternTableElement( MatchPatternTableElement *element );
3493 +static void freePatternElement( PatternElement *element );
3494 +static void freeStringPattern( StringPattern *strPat );
3495 +static void freeMatchPatternGroupElement( MatchPatternGroupElement *group );
3496 +static void freeMatchPatternSequenceElement( MatchPatternSequenceElement *sequence );
3498 +static StringMatchTable *readMatchPatternSet(char **inPtr);
3499 +static StringMatchTable *readMatchPatternSetContent(
3500 + char **inPtr,
3501 + char *stringStart,
3502 + char *languageMode);
3503 +static int createRegExpOfPatterns(
3504 + ReadMatchPatternInfo *readPatInfo,
3505 + ErrorInfo *errInfo);
3506 +static int createRegExpOfAllPatterns(
3507 + ReadMatchPatternInfo *readPatInfo,
3508 + ErrorInfo *errInfo);
3509 +static int createRegExpOfStrPatterns(
3510 + ReadMatchPatternInfo *readPatInfo,
3511 + ErrorInfo *errInfo);
3512 +static StringMatchTable *createStringMatchTable(
3513 + ReadMatchPatternInfo *readPatInfo,
3514 + char *languageMode);
3515 +static int readMatchPatternEntry(
3516 + char **inPtr,
3517 + ErrorInfo *errInfo,
3518 + ReadMatchPatternInfo *info);
3519 +static void recordPatternSequence(
3520 + ReadMatchPatternInfo *info,
3521 + char *name,
3522 + MatchPatternType type,
3523 + int index);
3524 +static int assignIndividualGroup(
3525 + ReadMatchPatternInfo *info,
3526 + char **errMsg,
3527 + MatchPatternTableElement *element);
3528 +static MatchPatternTableElement *getPatternOfName(
3529 + ReadMatchPatternInfo *info,
3530 + char *subPatToSearch);
3531 +static MatchPatternGroupElement *readMatchPatternGroup(
3532 + char **inPtr,
3533 + ErrorInfo *errInfo,
3534 + char *name,
3535 + ReadMatchPatternInfo *info);
3536 +static int readPatternElement(
3537 + char **inPtr,
3538 + char **errMsg,
3539 + PatternElement **pattern);
3540 +static PatternElement *createPatternElement(
3541 + char *patternText,
3542 + PatternElementKind patternKind,
3543 + PatternWordBoundary wordBoundary,
3544 + int caseInsensitive,
3545 + int regularExpression);
3547 +static int createGlobalBackRefList(
3548 + ReadMatchPatternInfo *readPatInfo,
3549 + MatchPatternTableElement *element,
3550 + ErrorInfo *errInfo);
3551 +StringPattern *getReadStringPattern(
3552 + ReadMatchPatternInfo *readPatInfo,
3553 + PatternElement *pattern );
3554 +static PatternElement *getReadPatternOfReference(
3555 + ReadMatchPatternInfo *readPatInfo,
3556 + PatternReference *patRef);
3557 +static char *replaceCapturingParentheses(
3558 + const char *source);
3559 +static int parseGlobalBackRefs(
3560 + StringPattern *strPat,
3561 + GlobalBackRefElement *backRefList,
3562 + ErrorInfo *errInfo);
3563 +static int updateGlobalBackRefs(
3564 + StringPattern *strPat,
3565 + GlobalBackRefElement *backRefList,
3566 + ErrorInfo *errInfo);
3567 +static char *createBackRefRegExpText(
3568 + const char *start,
3569 + const char *end);
3570 +static int resolveGlobalBackRefs(
3571 + ReadMatchPatternInfo *readPatInfo,
3572 + MatchPatternTableElement *element,
3573 + ErrorInfo *errInfo);
3574 +static int resolveGlobalBackRefsOfStrPat(
3575 + StringPattern *strPat,
3576 + GlobalBackRefElement *backRefList,
3577 + ErrorInfo *errInfo);
3578 +static char *substituteGlobalBackRef(
3579 + StringPattern *strPat,
3580 + char *subsPtr,
3581 + int globalId,
3582 + int *localId,
3583 + GlobalBackRefElement *backRefList,
3584 + ErrorInfo *errInfo);
3585 +static char *replaceBackRefIdByRegExp(
3586 + StringPattern *strPat,
3587 + char *replaceStartPtr,
3588 + char *regExp);
3589 +static char *convertGlobalToLocalBackRef(
3590 + StringPattern *strPat,
3591 + char *convertPtr);
3593 +static MatchPatternTableElement *readMatchPatternTableElement(
3594 + char **inPtr,
3595 + char **errMsg,
3596 + char *name,
3597 + MatchPatternType type);
3598 +static int sortReadPatternElementSet(
3599 + PatternElementSet *allPat,
3600 + char **errMsg,
3601 + MatchPatternTableElement *result);
3602 +static void countPatternElementKind(
3603 + PatternElementSet *allPat,
3604 + MatchPatternTableElement *result);
3605 +static void sortPatternElementSet(
3606 + PatternElementSet *allPat,
3607 + MatchPatternTableElement *result);
3608 +static void copyPatternSet(
3609 + PatternElementSet *sourcePS,
3610 + PatternElementSet *destPS);
3612 +static int getMPSName(
3613 + char **inPtr,
3614 + ErrorInfo *errInfo,
3615 + char **name );
3616 +static int getMPSTypeAttribute(
3617 + char **inPtr,
3618 + ErrorInfo *errInfo,
3619 + MatchPatternType *type);
3620 +static int getMPSGlobalAttribute(
3621 + char **inPtr,
3622 + char **errMsg,
3623 + int *isMonoPattern,
3624 + int *comment,
3625 + int *flash,
3626 + int *ignoreHighLightInfo);
3627 +static int getMPSPatternAttribute(
3628 + char **inPtr,
3629 + char **errMsg,
3630 + PatternElementKind *patternKind,
3631 + PatternWordBoundary *wordBoundary,
3632 + int *caseInsensitive,
3633 + int *regularExpression);
3635 +static void copyStringMatchTableForDialog(
3636 + StringMatchTable *sourceTable,
3637 + DialogMatchPatternInfo *dialogTable );
3638 +static void *copyMatchPatternElementForDialog(
3639 + MatchPatternTable *table,
3640 + int sourceElementIdx);
3641 +static void copyPatternForDialog(
3642 + MatchPatternTable *table,
3643 + PatternElement *sourcePattern,
3644 + DialogStringPatternElement **dialogPattern );
3645 +static void *copyGroupElementForDialog(
3646 + MatchPatternGroupElement *sourceGroup);
3647 +static void copySequenceElementForDialog(
3648 + StringMatchTable *sourceTable,
3649 + MatchPatternSequenceElement *sourceSeqElement,
3650 + DialogMatchPatternSequenceElement **dialogSeqElement );
3651 +static DialogMatchPatternSequenceElement *copyDialogSequenceElement(
3652 + DialogMatchPatternSequenceElement *sourceSeq);
3653 +static void freeDialogMatchPatternElement(
3654 + DialogMatchPatternTableElement *dialogElement );
3655 +static void freeDialogStringPatternElement(
3656 + DialogStringPatternElement *element);
3657 +static void freeDialogGroupElement(
3658 + DialogMatchPatternGroupElement *dialogGroup );
3659 +static void freeDialogSequenceElement(
3660 + DialogMatchPatternSequenceElement *dialogSeq );
3662 +static void copyDialogStringPatternsFromTable(
3663 + DialogMatchPatternTableElement *tableElement,
3664 + DialogStringPatterns *destPatterns);
3665 +static void copyDialogStringPatterns(
3666 + DialogStringPatterns *sourcePatterns,
3667 + DialogStringPatterns *destPatterns);
3668 +static void freeDialogStringPatterns(
3669 + DialogStringPatterns *patterns);
3671 +static DialogStringPatternElement *copyDialogStringPatternElement(
3672 + DialogStringPatternElement *sourceElement);
3674 +static void copyDialogPatternNamesFromGroup(
3675 + DialogMatchPatternGroupElement *group,
3676 + DialogStringPatterns *destPatterns);
3677 +static DialogStringPatternElement *copyDialogPatternName(
3678 + char *sourcePatternId);
3679 +static void copyDialogPatternNamesToGroup(
3680 + DialogStringPatterns *sourceNames,
3681 + DialogMatchPatternGroupElement *destGroup);
3683 +static void setDialogType(int dialogShowsStringPattern);
3684 +static void setSensitiveWordBoundaryBox(int enable);
3686 +static void *getStringPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
3687 + void *cbArg);
3688 +static void setStringPatternDisplayedCB(void *item, void *cbArg);
3689 +static void freeStringPatternItemCB(void *item);
3691 +static void *getMatchPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
3692 + void *cbArg);
3693 +static void setMatchPatternDisplayedCB(void *item, void *cbArg);
3694 +static void freeMatchPatternItemCB(void *item);
3695 +static int deleteMatchPatternItemCB(int itemIndex, void *cbArg);
3697 +static void matchPatternLangModeCB(Widget w, XtPointer clientData, XtPointer callData);
3698 +static void pmLanguageModeDialogCB(Widget w, XtPointer clientData, XtPointer callData);
3700 +static void destroyCB(Widget w, XtPointer clientData, XtPointer callData);
3701 +static void okCB(Widget w, XtPointer clientData, XtPointer callData);
3702 +static void applyCB(Widget w, XtPointer clientData, XtPointer callData);
3703 +static void checkCB(Widget w, XtPointer clientData, XtPointer callData);
3704 +static void restoreCB(Widget w, XtPointer clientData, XtPointer callData);
3705 +static void deleteCB(Widget w, XtPointer clientData, XtPointer callData);
3706 +static void closeCB(Widget w, XtPointer clientData, XtPointer callData);
3707 +static void helpCB(Widget w, XtPointer clientData, XtPointer callData);
3709 +static void matchPatTypeCB(Widget w, XtPointer clientData, XtPointer callData);
3710 +static void strPatRegExpressionCB(Widget w, XtPointer clientData, XtPointer callData);
3711 +static void changeExistingSubPattern(char *warnTitle);
3712 +static void changeStringPatternToGroup(void);
3713 +static void changeGroupToStringPattern(char *warnTitle);
3715 +static Widget createSubPatternNameMenu(
3716 + Widget parent,
3717 + char *currentSubPatName,
3718 + int allSubPatterns);
3719 +static void setupSubPatternNameList(
3720 + char *currentSubPatName,
3721 + int allSubPatterns,
3722 + NameList *nameList);
3723 +static void createSubPatNameMenuEntry(
3724 + Widget menu,
3725 + char *subPatName);
3726 +static void setSubPatternNameMenu(
3727 + const char *subPatName);
3728 +static void updateSubPatternNameMenu(
3729 + char *currentSubPatName,
3730 + int allSubPatterns);
3731 +static char *getSelectedSubPatternName(void);
3732 +static int isSubPatternNameInCurStrPat(
3733 + char *subPatName);
3735 +static DialogMatchPatternSequenceElement *readMatchPatternFields(int silent);
3736 +static int isStartPatternElementAvailable(
3737 + DialogStringPatterns *dialogPatterns);
3738 +static DialogStringPatternElement *readStringPatternFrameFields(int silent);
3740 +static int matchPatternDialogEmpty(void);
3741 +static int stringPatternFrameEmpty(void);
3742 +static int stringPatternFieldsEmpty(
3743 + int strPatIsRelatedToGroup);
3745 +static int getAndUpdateStringMatchTable(void);
3746 +static void updateStringMatchTable(
3747 + StringMatchTable *newTable);
3749 +static StringMatchTable *getDialogStringMatchTable(
3750 + DMPTranslationResult *result);
3751 +static StringMatchTable *translateDialogStringMatchTable(
3752 + DialogMatchPatternInfo *dialogTable,
3753 + DMPTranslationResult *result);
3754 +static MatchPatternTableElement *translateDialogMatchPatternTableElement(
3755 + DialogMatchPatternTableElement *dialogElement);
3756 +static void translateDialogPatterns(
3757 + DialogStringPatterns *dialogPatterns,
3758 + MatchPatternTableElement *newElement);
3759 +static MatchPatternGroupElement *translateDialogMatchPatternGroupElement(
3760 + ReadMatchPatternInfo *info,
3761 + DialogMatchPatternGroupElement *dialogGroup);
3762 +static void sortDialogPatternElementSet(
3763 + PatternElementSet *allPat,
3764 + MatchPatternTableElement *result);
3766 +static int stringMatchTableDiffer(
3767 + StringMatchTable *oldTable,
3768 + StringMatchTable *newTable);
3770 +static int patternElementDiffer(
3771 + PatternElement *oldPE,
3772 + MatchPatternTable *oldTab,
3773 + PatternElement *newPE,
3774 + MatchPatternTable *newTab);
3776 +static DialogMatchPatternGroupElement *getDialogGroupUsingMatchPattern(
3777 + char *matchPatternName);
3778 +static void removeMatchPatternFromGroup(
3779 + char *matchPatternName,
3780 + DialogMatchPatternGroupElement *group);
3781 +static void removeMatchPatternFromAllGroups(
3782 + char *matchPatternName);
3783 +static void renameMatchPatternInGroup(
3784 + char *oldMatchPatternName,
3785 + char *newMatchPatternName,
3786 + DialogMatchPatternGroupElement *group);
3787 +static void renameMatchPatternInAllGroups(
3788 + char *oldMatchPatternName,
3789 + char *newMatchPatternName);
3791 +static void freeVariableDialogData(
3792 + int keepLanguageModeName);
3794 +static void initGlobalBackRefList(
3795 + GlobalBackRefElement *list);
3796 +static void initStrPatBackRefList(
3797 + StringPattern *strPat);
3799 +StringPattern *getUniqueStringPattern(
3800 + PatternElement *pattern );
3802 +static void initErrorInfo(
3803 + ErrorInfo *errInfo);
3804 +static void freeErrorInfo(
3805 + ErrorInfo *errInfo);
3807 +static void freeXtPtr(void **ptr);
3808 +static void freePtr(void **ptr);
3811 + * matching pattern dialog information
3812 + */
3813 +static struct {
3814 + Widget mpdShell;
3815 + Widget mpdLmOptMenu;
3816 + Widget mpdLmPulldown;
3817 + Widget mpdMatchPatternNamesListW;
3818 + Widget mpdMatchPatternNameLbl;
3819 + Widget mpdMatchPatternNameW;
3820 + Widget mptbIndividualW;
3821 + Widget mptbSubPatternW;
3822 + Widget mptbContextGroupW;
3823 + Widget mpdGlobalAttributesLbl;
3824 + Widget gabSkipBtwStartEndW;
3825 + Widget gabFlashW;
3826 + Widget gabSyntaxBasedW;
3827 + Widget mpdStringPatternsLbl;
3828 + Widget mpdStringPatternsListW;
3829 + Widget mpdStringPatternTypeLbl;
3830 + Widget sptStartW;
3831 + Widget sptMiddleW;
3832 + Widget sptEndW;
3833 + Widget mpdWordBoundaryLbl;
3834 + Widget wbbBothW;
3835 + Widget wbbLeftW;
3836 + Widget wbbRightW;
3837 + Widget wbbNoneW;
3838 + Widget mpdStringAttributesLbl;
3839 + Widget sabCaseSensitiveW;
3840 + Widget sabRegularExpressionW;
3841 + Widget mpdStringPatternLbl;
3842 + Widget mpdStringPatternW;
3843 + Widget mpdSubPatNamesLbl;
3844 + Widget mpdSubPatNamesOptMenu;
3845 + Widget mpdSubPatNamesPulldown;
3846 + char *mpdLangModeName;
3847 + DialogMatchPatternSequenceElement *currentDmptSeqElement;
3848 + DialogMatchPatternTableElement *currentDmptElement;
3849 + DialogMatchPatternGroupElement *currentDmptGroup;
3850 + DialogStringPatterns currentStringPatterns;
3851 + DialogMatchPatternInfo mpdTable;
3852 + int mpdStringPatternIsDisplayed;
3853 +} MatchPatternDialog =
3854 + {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3855 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3856 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3857 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3858 + NULL, NULL, NULL, NULL,
3859 + {0, {NULL}},
3860 + {0, {NULL}},
3861 + True
3862 + };
3865 + * Matching pattern sources loaded from the nedit resources file or set
3866 + * by the user
3867 + */
3868 +static int NbrMatchTables = 0;
3869 +static StringMatchTable *MatchTables[MAX_LANGUAGE_MODES];
3872 + * Syntax:
3873 + * LanguagePatternSet ::=
3874 + * LanguageName{PatternStatement..}
3876 + * PatternStatement ::=
3877 + * name:[s]:[c][f][m][p][u]:([s|m|e][w|l|r][i]:"pattern":)..)\n)|
3878 + * name:g:"sub-pattern name":..\n..
3880 + * TypeAttribute:
3881 + * s : sub-pattern (pattern is only matched, if part of a pattern group).
3882 + * g : pattern (context) group (i.e. a sequence of sub-patterns).
3883 + * default: individual pattern (pattern is matched individually).
3884 + * GlobalAttribute:
3885 + * c : the content between start and end pattern is skipped
3886 + * during parsing (e.g. pattern encloses a comment).
3887 + * f : flash matching pattern (if not set, then only jump
3888 + * to matching pattern is supported).
3889 + * m : mono pattern - set exist out of only one single pattern
3890 + * (start pattern = end pattern; e.g. quotes like ")
3891 + * p : ignore highlight info code of single patterns of this set
3892 + * ("plain").
3893 + * StringPatternKind:
3894 + * s : start string pattern.
3895 + * m : middle string pattern.
3896 + * e : end string pattern.
3897 + * WordBoundaryAttribute:
3898 + * w : pattern is word (i.e. before and after pattern
3899 + * there must be a delimiter).
3900 + * l : before pattern must be a delimiter (left side).
3901 + * r : after pattern must be a delimiter (right side).
3902 + * default: neither before nor after pattern must be a delimiter.
3903 + * StringAttribute:
3904 + * i : pattern is case insensitive (if not set: pattern is
3905 + * case sensitive).
3906 + * x : pattern is regular expression (if not set: pattern is
3907 + * literal string).
3909 + * \n : end of pattern
3910 + */
3912 +static char *DefaultStringMatchTable[] = {
3913 + "PLAIN{"
3914 + "Round braces::fp:s:\"(\":e:\")\":\n"
3915 + "Curly braces::fp:s:\"{\":e:\"}\":\n"
3916 + "Squared braces::fp:s:\"[\":e:\"]\":\n"
3917 + "Sharp braces::fp:s:\"<\":e:\">\":\n}",
3918 + "C++{"
3919 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
3920 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3921 + "Single Quotes:s:cmf:s:\"'\":\n"
3922 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3923 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3924 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3925 + "#ifdef statement:s:f:sx:\"#\\s*ifdef\":sx:\"#\\s*ifndef\":sx:\"#\\s*if\":mx:\"#\\s*elif\":mx:\"#\\s*else\":ex:\"#\\s*endif\":\n"
3926 + "#if group:g:Comment:Double Quotes:Single Quotes:#ifdef statement:\n"
3927 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
3928 + "C{"
3929 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
3930 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3931 + "Single Quotes:s:cmf:s:\"'\":\n"
3932 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3933 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3934 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3935 + "#ifdef statement:s:f:sx:\"#\\s*ifdef\":sx:\"#\\s*ifndef\":sx:\"#\\s*if\":mx:\"#\\s*elif\":mx:\"#\\s*else\":ex:\"#\\s*endif\":\n"
3936 + "#if group:g:Comment:Double Quotes:Single Quotes:#ifdef statement:\n"
3937 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
3938 + "CSS{"
3939 + "comment:s:cf:s:\"/*\":e:\"*/\":\n"
3940 + "curly braces:s:f:s:\"{\":e:\"}\":\n"
3941 + "round braces:s:f:s:\"(\":e:\")\":\n"
3942 + "double quotes:s:cfm:s:\"\"\"\":\n"
3943 + "single quotes:s:cfm:s:\"'\":\n"
3944 + "braces:g:comment:single quotes:double quotes:curly braces:round braces:\n}",
3945 + "Csh{"
3946 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3947 + "Single Quotes:s:cmf:s:\"'\":\n"
3948 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3949 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3950 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3951 + "if statement:s:f:sw:\"if\":mw:\"else\":ew:\"endif\":\n"
3952 + "switch statement:s:f:sw:\"switch\":mw:\"case\":mw:\"default\":ew:\"endsw\":\n"
3953 + "foreach statement:s:f:sw:\"for\":ew:\"end\":\n"
3954 + "while statement:s:f:sw:\"while\":ew:\"end\":\n"
3955 + "statement group:g:Double Quotes:Single Quotes:if statement:switch statement:foreach statement:while statement:\n"
3956 + "Braces:g:Double Quotes:Single Quotes:Squared braces:Round braces:Curly braces:\n}",
3957 + "Java{"
3958 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
3959 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3960 + "Single Quotes:s:cmf:s:\"'\":\n"
3961 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3962 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3963 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3964 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
3965 + "JavaScript{"
3966 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
3967 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3968 + "Single Quotes:s:cmf:s:\"'\":\n"
3969 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3970 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3971 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3972 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
3973 + "Makefile{"
3974 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3975 + "Single Quotes:s:cmf:s:\"'\":\n"
3976 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3977 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3978 + "Braces:g:Double Quotes:Single Quotes:Curly braces:Round braces:\n}",
3979 + "NEdit Macro{"
3980 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3981 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3982 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3983 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3984 + "Braces:g:Double Quotes:Curly braces:Round braces:Squared braces:\n}",
3985 + "Pascal{"
3986 + "Single Quotes:s:cmf:s:\"'\":\n"
3987 + "Comment1:s:cf:s:\"(*\":e:\"*)\":\n"
3988 + "Comment2:s:cf:s:\"{\":e:\"}\":\n"
3989 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3990 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3991 + "Block:s:f:swi:\"begin\":ewi:\"end\":\n"
3992 + "Case:s:fp:swi:\"case\":ewi:\"end\":\n"
3993 + "Record:s:f:swi:\"record\":ewi:\"end\":\n"
3994 + "Statement:g:Comment1:Comment2:Single Quotes:Block:Case:Record:\n"
3995 + "Braces:g:Comment1:Comment2:Single Quotes:Round braces:Squared braces:\n}",
3996 + "Perl{"
3997 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
3998 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3999 + "Single Quotes:s:cmf:s:\"'\":\n"
4000 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4001 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4002 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4003 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
4004 + "SGML HTML{"
4005 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4006 + "Single Quotes:s:cmf:s:\"'\":\n"
4007 + "Sharp braces:s:f:s:\"<\":e:\">\":\n"
4008 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4009 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4010 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4011 + "Braces:g:Double Quotes:Single Quotes:Sharp braces:Curly braces:Round braces:Squared braces:\n}",
4012 + "Sh Ksh Bash{"
4013 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4014 + "Single Quotes:s:cmf:s:\"'\":\n"
4015 + "Back Quotes:s:cfm: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 + "if statement:s:f:sw:\"if\":mw:\"elif\":mw:\"else\":ew:\"fi\":\n"
4020 + "case statement:s:f:sw:\"case\":ew:\"esac\":\n"
4021 + "for statement:s:f:sw:\"for\":mw:\"do\":ew:\"done\":\n"
4022 + "while statement:s:f:sw:\"while\":mw:\"do\":ew:\"done\":\n"
4023 + "statement group:g:Double Quotes:Single Quotes:if statement:case statement:for statement:while statement:\n"
4024 + "Braces:g:Double Quotes:Single Quotes:Back Quotes:Squared braces:Round braces:Curly braces:\n}",
4025 + "XML{"
4026 + "round braces:s:f:s:\"(\":e:\")\":\n"
4027 + "comment:s:cf:s:\"<!--\":e:\"-->\":\n"
4028 + "cdata + ignore:s:cf:sx:\"\\<!\\[((?icdata)|(\\s*IGNORE\\s*))\\[\":ex:\"\\]\\]\\>\":\n"
4029 + "short element:s:cf:sx:\"(?n\\<[\\l_][^@$%/\"\"';!>\\s]*(?=[^>]*/\\>))\":ex:\"/\\>\":\n"
4030 + "element pair:s:f:sx:\"(?n\\<(*1[\\l|_][^@$%/\"\"';!>\\s]*)\\>)\":sx:\"(?n\\<(*1[\\l|_][^@$%/\"\"';!>\\s]*)(?=[^>]*[^/]\\>))\":eix:\"\\</\\1\\>\":\n"
4031 + "processing instruction:s:f:sx:\"\\<\\?\\S+\":ex:\"\\?\\>\":\n"
4032 + "double quotes:s:cmf:s:\"\"\"\":\n"
4033 + "single quotes:s:cmf:s:\"'\":\n"
4034 + "tags:g:comment:double quotes:single quotes:round braces:cdata + ignore:element pair:short element:processing instruction:\n}",
4035 + };
4037 +static char *StandardStringMatchTable =
4038 + "{Round braces::fp:s:\"(\":e:\")\":\n"
4039 + "Curly braces::fp:s:\"{\":e:\"}\":\n"
4040 + "Squared braces::fp:s:\"[\":e:\"]\":\n}";
4043 +** Return string match table related to given language mode name.
4044 +** Return NULL, if no table is found.
4046 +void *FindStringMatchTable(const char *langModeName)
4048 + const char *nameToSearch;
4049 + int i;
4051 + if (langModeName == NULL)
4052 + nameToSearch = PLAIN_LM_STRING;
4053 + else
4054 + nameToSearch = langModeName;
4056 + for (i=0; i<NbrMatchTables; i++)
4057 + if (!strcmp(nameToSearch, MatchTables[i]->smtLanguageMode))
4058 + return (void *)MatchTables[i];
4059 + return NULL;
4063 +** Change the language mode name of string match tables for language
4064 +** "oldName" to "newName" in both the stored tables, and the table
4065 +** currently being edited in the dialog.
4067 +void RenameStringMatchTable(const char *oldName, const char *newName)
4069 + int i;
4071 + for (i=0; i<NbrMatchTables; i++)
4073 + if (!strcmp(oldName, MatchTables[i]->smtLanguageMode))
4075 + XtFree(MatchTables[i]->smtLanguageMode);
4076 + MatchTables[i]->smtLanguageMode = XtNewString(newName);
4079 + if (MatchPatternDialog.mpdShell != NULL)
4081 + if (!strcmp(MatchPatternDialog.mpdLangModeName, oldName))
4083 + XtFree(MatchPatternDialog.mpdLangModeName);
4084 + MatchPatternDialog.mpdLangModeName = XtNewString(newName);
4090 +** Delete string match table related to given language mode name.
4092 +void DeleteStringMatchTable(const char *langModeName)
4094 + int i;
4096 + for (i=0; i<NbrMatchTables; i++)
4098 + if (!strcmp(langModeName, MatchTables[i]->smtLanguageMode))
4100 + /*
4101 + * free (delete) existing matching pattern
4102 + */
4103 + freeStringMatchTable(MatchTables[i]);
4104 + memmove(
4105 + &MatchTables[i],
4106 + &MatchTables[i+1],
4107 + (NbrMatchTables-1 - i) * sizeof(StringMatchTable *));
4108 + NbrMatchTables--;
4109 + break;
4115 +** Assign a standard string match table to a given new language mode.
4117 +void AssignStandardStringMatchTable(const char *langModeName)
4119 + char *list;
4120 + StringMatchTable *newTable;
4122 + /*
4123 + * assign standard table for new language mode
4124 + * add table to end
4125 + */
4126 + list = StandardStringMatchTable;
4127 + newTable =
4128 + readMatchPatternSetContent(&list, list, XtNewString(langModeName));
4130 + /*
4131 + * add table to end
4132 + */
4133 + MatchTables[NbrMatchTables++] = newTable;
4137 +** Returns True if there is a string match table, or potential table
4138 +** not yet committed in the match pattern dialog for a language mode,
4140 +int LMHasStringMatchTable(const char *languageMode)
4142 + StringMatchTable *table = FindStringMatchTable(languageMode);
4144 + if (table != NULL && table->smtNumberOfSeqElements != 0)
4145 + return True;
4146 + return MatchPatternDialog.mpdShell != NULL &&
4147 + !strcmp(MatchPatternDialog.mpdLangModeName, languageMode) &&
4148 + MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements != 0;
4152 +** Read a string representing string matching pattern sets and add them
4153 +** to the StringMatchTable list of loaded string match patterns.
4154 +** Returns true, if read of string was successful.
4156 +int LoadMatchPatternString(char *inString)
4158 + char *inPtr = inString;
4159 + StringMatchTable *table;
4160 + int i;
4162 + for (;;)
4164 + /*
4165 + * read each matching pattern set
4166 + */
4167 + table = readMatchPatternSet(&inPtr);
4169 + if (table != NULL)
4171 + /*
4172 + * add/change the pattern set in the list
4173 + */
4174 + for (i=0; i<NbrMatchTables; i++)
4176 + if (!strcmp(MatchTables[i]->smtLanguageMode, table->smtLanguageMode))
4178 + freeStringMatchTable(MatchTables[i]);
4179 + MatchTables[i] = table;
4180 + break;
4183 + if (i == NbrMatchTables)
4185 + MatchTables[NbrMatchTables++] = table;
4186 + if (NbrMatchTables > MAX_LANGUAGE_MODES)
4188 + return False;
4193 + /*
4194 + * find end of this pattern. if the string ends here, we're done
4195 + */
4196 + inPtr = strstr(inPtr, "\n");
4197 + if (inPtr == NULL)
4199 + return True;
4202 + /*
4203 + * skip newline, tabs & spaces in front of next pattern.
4204 + * if the string ends here, we're done
4205 + */
4206 + inPtr += strspn(inPtr, " \t\n");
4207 + if (*inPtr == '\0')
4209 + return True;
4215 +** Create a string in the correct format for the matchPatterns resource,
4216 +** containing all of the matching pattern information from the stored
4217 +** matching pattern sets for this NEdit session.
4219 +char *WriteMatchPatternString(void)
4221 + char *outStr, *str, *escapedStr;
4222 + textBuffer *outBuf;
4223 + int i, written = False;
4224 + StringMatchTable *table;
4226 + outBuf = BufCreate();
4228 + for (i=0; i<NbrMatchTables; i++)
4230 + table = MatchTables[i];
4232 + written = True;
4234 + BufInsert(outBuf, outBuf->length, table->smtLanguageMode);
4235 + BufInsert(outBuf, outBuf->length, ":");
4237 + if (isDefaultMatchPatternTable(table))
4239 + BufInsert(outBuf, outBuf->length, "Default\n\t");
4241 + else
4243 + BufInsert(outBuf, outBuf->length, "{\n");
4244 + BufInsert(outBuf, outBuf->length,
4245 + str = createMatchPatternsString(table, "\t\t"));
4246 + XtFree(str);
4247 + BufInsert(outBuf, outBuf->length, "\t}\n\t");
4251 + /*
4252 + * Get the output string, and lop off the trailing newline and tab
4253 + */
4254 + outStr = BufGetRange(outBuf, 0, outBuf->length - (written?2:0));
4255 + BufFree(outBuf);
4257 + /*
4258 + * Protect newlines and backslashes from translation by the resource
4259 + * reader
4260 + */
4261 + escapedStr = EscapeSensitiveChars(outStr);
4263 + XtFree(outStr);
4265 + return escapedStr;
4269 +** Check, if last pattern is a duplicate of a previous pattern.
4270 +** Convert last pattern to a reference, if so.
4272 +static void treatDuplicatedPattern(
4273 + MatchPatternTable *table,
4274 + PatternElement *prevPattern,
4275 + PatternReference prevPatRef,
4276 + PatternElement *lastPattern,
4277 + PatternReference lastPatRef)
4279 + StringPattern *prevStringPat;
4280 + StringPattern *lastStringPat;
4281 + StringPattern *stringPat;
4282 + PatternReference *oldList;
4283 + int nbrOfRef;
4285 + /*
4286 + * No duplicate check needed, if previous pattern is a reference,
4287 + * due to the related multi pattern element is checked before.
4288 + */
4289 + if (prevPattern->peType == PET_REFERENCE)
4290 + return;
4292 + prevStringPat = GetStringPattern(table, prevPattern);
4293 + lastStringPat = GetStringPattern(table, lastPattern);
4295 + if (!AllocatedStringsDiffer(prevStringPat->spText, lastStringPat->spText) &&
4296 + !AllocatedStringsDiffer(prevStringPat->spOrigText, lastStringPat->spOrigText) &&
4297 + prevStringPat->spWordBoundary == lastStringPat->spWordBoundary &&
4298 + prevStringPat->spCaseInsensitive == lastStringPat->spCaseInsensitive &&
4299 + prevStringPat->spRegularExpression == lastStringPat->spRegularExpression)
4301 + /*
4302 + * Patterns are identical: Is prevPattern already a multi pattern ?
4303 + */
4304 + if (prevPattern->peType == PET_MULTIPLE)
4306 + /*
4307 + * just add ref. to "lastPattern" to the ref. list
4308 + */
4309 + (prevPattern->peVal.peuMulti.mpNumberOfReferences) ++;
4310 + nbrOfRef = prevPattern->peVal.peuMulti.mpNumberOfReferences;
4311 + oldList = prevPattern->peVal.peuMulti.mpRefList;
4312 + prevPattern->peVal.peuMulti.mpRefList =
4313 + (PatternReference *)XtMalloc( nbrOfRef * sizeof(PatternReference) );
4314 + memcpy(
4315 + prevPattern->peVal.peuMulti.mpRefList,
4316 + oldList,
4317 + (nbrOfRef-1) * sizeof(PatternReference) );
4318 + prevPattern->peVal.peuMulti.mpRefList[nbrOfRef-1] = lastPatRef;
4319 + XtFree( (char *)oldList );
4321 + else
4323 + /*
4324 + * convert prev. single pattern to multi pattern
4325 + */
4326 + stringPat = &prevPattern->peVal.peuSingle;
4327 + prevPattern->peType = PET_MULTIPLE;
4328 + prevPattern->peVal.peuMulti.mpStringPattern = *stringPat;
4329 + prevPattern->peVal.peuMulti.mpNumberOfReferences = 1;
4330 + prevPattern->peVal.peuMulti.mpRefList =
4331 + (PatternReference *)XtMalloc( sizeof(PatternReference) );
4332 + prevPattern->peVal.peuMulti.mpRefList[0] = lastPatRef;
4335 + /*
4336 + * convert last single pattern to reference
4337 + */
4338 + freeStringPattern( &(lastPattern->peVal.peuSingle) );
4339 + lastPattern->peType = PET_REFERENCE;
4340 + lastPattern->peVal.peuRef = prevPatRef;
4345 +** Check, if last pattern is a duplicate of a pattern stored within a
4346 +** previous match pattern table element.
4347 +** Convert last pattern to a reference, if so.
4349 +static void treatDuplicatedPatternElements(
4350 + MatchPatternTable *table,
4351 + MatchPatternTableElement *prevElement,
4352 + int prevElementIdx,
4353 + PatternElement *lastPattern,
4354 + PatternReference lastPatRef)
4356 + int i;
4357 + PatternReference prevPatRef;
4359 + prevPatRef.prElementIdx = prevElementIdx;
4361 + for (i=0; i<prevElement->mpteAll.pesNumberOfPattern; i++)
4363 + prevPatRef.prPatternIdx = i;
4364 + treatDuplicatedPattern(
4365 + table,
4366 + prevElement->mpteAll.pesPattern[i],
4367 + prevPatRef,
4368 + lastPattern,
4369 + lastPatRef);
4374 +** Check, if a pattern of last match pattern table element is a
4375 +** duplicate of a pattern stored within a previous match pattern table
4376 +** element.
4377 +** Convert duplicated last patterns to references, if so.
4379 +static void treatDuplicatedMTElements(
4380 + MatchPatternTable *table,
4381 + MatchPatternTableElement *prevElement,
4382 + int prevElementIdx,
4383 + MatchPatternTableElement *lastElement,
4384 + int lastElementIdx)
4386 + int i;
4387 + PatternReference lastPatRef;
4389 + lastPatRef.prElementIdx = lastElementIdx;
4391 + for (i=0; i<lastElement->mpteAll.pesNumberOfPattern; i++)
4393 + lastPatRef.prPatternIdx = i;
4394 + treatDuplicatedPatternElements(
4395 + table,
4396 + prevElement,
4397 + prevElementIdx,
4398 + lastElement->mpteAll.pesPattern[i],
4399 + lastPatRef);
4404 +** Convert all duplicated patterns of given match pattern table to
4405 +** references.
4407 +static void treatDuplicatedMTEntries(
4408 + MatchPatternTableElement **element,
4409 + int nbrOfElements)
4411 + int i;
4412 + MatchPatternTableElement *lastElement;
4413 + int lastElementIdx;
4414 + MatchPatternTable table;
4416 + if (nbrOfElements < 2)
4417 + return;
4419 + lastElementIdx = nbrOfElements - 1;
4420 + lastElement = element[lastElementIdx];
4422 + table.mptElements = element;
4423 + table.mptNumberOfElements = nbrOfElements;
4425 + for (i=0; i<nbrOfElements-1; i ++)
4427 + treatDuplicatedMTElements( &table, element[i], i, lastElement, lastElementIdx );
4432 +** Compile regular expressions of all string patterns of given
4433 +** match pattern table element.
4434 +** Returns true, if compilation fails.
4436 +static int createStrPatRegExpOfElement(
4437 + ReadMatchPatternInfo *readPatInfo,
4438 + MatchPatternTableElement *element,
4439 + ErrorInfo *errInfo)
4441 + int i;
4442 + StringPattern *strPat;
4444 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
4446 + strPat = getReadStringPattern(readPatInfo, element->mpteAll.pesPattern[i]);
4448 + /*
4449 + * if current string pattern holds a regular expression, then
4450 + * compile it
4451 + */
4452 + if (strPat->spRegularExpression)
4454 + if (createStrPatRegExp(strPat, errInfo))
4456 + /*
4457 + * compilation was not successful
4458 + */
4459 + errInfo->eiMPTabElementName = XtNewString(element->mpteName);
4460 + return True;
4465 + return False;
4469 +** Compile regular expressions of given string pattern.
4470 +** Returns true, if compilation fails.
4472 +static int createStrPatRegExp(
4473 + StringPattern *strPat,
4474 + ErrorInfo *errInfo)
4476 + char *regExpString;
4477 + char *compileMsg;
4479 + /*
4480 + * compose regular expression for start string pattern.
4481 + */
4482 + if( strPat->spCaseInsensitive)
4484 + /*
4485 + * Add '(?i .. )' to given text for case insensitive search.
4486 + * Allocate buffer to hold 5 more char than text length
4487 + * (4 char '(?i)' + \0 char.
4488 + */
4489 + regExpString = XtMalloc(strPat->spLength + 5);
4490 + strcpy(regExpString, "(?i");
4491 + strcat(regExpString, strPat->spText);
4492 + strcat(regExpString, ")");
4494 + else
4496 + regExpString = strPat->spText;
4499 + /*
4500 + * compile regular expression & free allocated string buffer,
4501 + * if applicable.
4502 + */
4503 + strPat->spTextRE =
4504 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
4506 + if (strPat->spTextRE == NULL)
4508 + /*
4509 + * compilation was not successful: adapt error reason by
4510 + * converting local backrefs to global ones.
4511 + */
4512 + adaptCompileMsg(compileMsg, strPat->spGlobalToLocalBackRef);
4514 + errInfo->eiRegExpCompileMsg = compileMsg;
4515 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
4518 + if (strPat->spCaseInsensitive)
4519 + XtFree( regExpString );
4521 + return (strPat->spTextRE == NULL);
4525 +** adapt regular expression compilation message by converting local
4526 +** backrefs to global ones.
4528 +static void adaptCompileMsg(
4529 + char *compileMsg,
4530 + int *globalToLocalBackRef)
4532 + int localId;
4533 + int globalId;
4534 + char *s = compileMsg;
4536 + while (*s != '\0')
4538 + if (*s == '\\')
4540 + if (isdigit((unsigned char)*(s+1)))
4542 + /*
4543 + * \n (n=1..9) found: substitute local by global back ref.
4544 + */
4545 + s ++;
4547 + localId =
4548 + (int)((unsigned char)*s - (unsigned char)'0');
4550 + globalId = localToGlobalBackRef(globalToLocalBackRef, localId);
4552 + *s = (char)((int)('0') + globalId);
4554 + else if (*(s+1) != '\0')
4555 + s ++;
4557 + s ++;
4562 +** translate given local backref to global backref by using
4563 +** given globalToLocalBackRef list.
4565 +static int localToGlobalBackRef(
4566 + int *globalToLocalBackRef,
4567 + int localId)
4569 + int i;
4571 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
4573 + if (globalToLocalBackRef[i] == localId)
4574 + return i+1;
4577 + return 0;
4581 +** Create a regular expression holding keywords of given start & end
4582 +** pattern set.
4583 +** Returns true, if creation of regular expression has failed.
4585 +static int createStartEndRegExp(
4586 + ReadMatchPatternInfo *readMatchPatternInfo,
4587 + MatchPatternTableElement *element,
4588 + ErrorInfo *errInfo)
4590 + char *regExpString;
4591 + char *compileMsg;
4593 + /*
4594 + * compose regular expression for start / end pattern.
4595 + */
4596 + composeStartEndRegExpString(
4597 + readMatchPatternInfo,
4598 + element,
4599 + &regExpString);
4601 + /*
4602 + * compile regular expression & free allocated string buffer.
4603 + */
4604 + element->mpteStartEndRE =
4605 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
4607 + XtFree( regExpString );
4609 + if( element->mpteStartEndRE == NULL)
4611 + errInfo->eiRegExpCompileMsg = compileMsg;
4612 + errInfo->eiDetail = "Error compiling start / end reg. exp.";
4615 + return (element->mpteStartEndRE == NULL);
4619 +** Create a regular expression holding keywords of given group element.
4620 +** Returns true, if creation of regular expression has failed.
4622 +static int createGroupRegExp(
4623 + ReadMatchPatternInfo *readPatInfo,
4624 + MatchPatternGroupElement *group,
4625 + ErrorInfo *errInfo)
4627 + int i;
4628 + MatchPatternTableElement *element;
4629 + RegExpStringInfo regExpStringInfo;
4630 + char *regExpString;
4631 + regexp *keywordRE;
4632 + char *compileMsg;
4634 + /*
4635 + * Allocate buffers for keyword regular expression of this group.
4636 + */
4637 + setupRegExpStringBuffers(
4638 + readPatInfo,
4639 + &regExpStringInfo);
4641 + for (i=0; i<group->mpgeNumberOfSubPatterns; i++)
4643 + element = getPatternOfName(readPatInfo, group->mpgeSubPatternIds[i]);
4644 + /*
4645 + * Add the keywords of the sub pattern to the keyword regular
4646 + * expression string buffer of new group.
4647 + */
4648 + addElementToRegExpString(
4649 + element,
4650 + readPatInfo,
4651 + &regExpStringInfo);
4654 + /*
4655 + * Assemble and compile the resulting keyword regular expression string.
4656 + */
4657 + catSMTRegExpStrings(
4658 + &regExpStringInfo,
4659 + &regExpString);
4661 + keywordRE = CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
4663 + XtFree( regExpString );
4665 + if (keywordRE == NULL)
4667 + errInfo->eiMPTabElementName = XtNewString(group->mpgeName);
4668 + errInfo->eiRegExpCompileMsg = compileMsg;
4669 + errInfo->eiDetail = "Group: Compile reg. exp. error";
4672 + group->mpgeKeywordRE = keywordRE;
4674 + return (keywordRE == NULL);
4678 +** Allocate memory for regular expression strings to be
4679 +** created out of read match pattern info.
4681 +static void setupRegExpStringBuffers(
4682 + ReadMatchPatternInfo *readMatchPatternInfo,
4683 + RegExpStringInfo *regExpStringInfo)
4685 + int totalLen;
4686 + int nbrOfMultiPatterns;
4687 + int sizeOfPatRefs;
4689 + /*
4690 + * determine total length of pattern characters to determine
4691 + * the size of a string buffer for the regular expression to
4692 + * compose. Count number of total multi patterns, too.
4693 + */
4694 + totalLen =
4695 + totalKeywordOfTableLen( readMatchPatternInfo, &nbrOfMultiPatterns );
4697 + /*
4698 + * allocate memory to store added multi pattern references (to avoid
4699 + * duplicated keywords strings later on).
4700 + */
4701 + sizeOfPatRefs = sizeof(PatternReference *) * nbrOfMultiPatterns;
4703 + regExpStringInfo->resiAddedMultiPat =
4704 + (PatternReference **)XtMalloc( sizeOfPatRefs );
4706 + regExpStringInfo->resiNbrOfAddedMultiPat = 0;
4708 + /*
4709 + * init. ID of capturing local backrefs
4710 + */
4711 + regExpStringInfo->resiLocalBackRefID = 1;
4713 + /*
4714 + * allocate & init. string buffers for regular expression:
4715 + * 3 times the size + x of all pattern characters (due to
4716 + * a.) each char may need to be escaped
4717 + * b.) '<(?:', ')>', ')' and '|' need to be added.
4718 + */
4719 + regExpStringInfo->resiNoneWBRegExpString = XtMalloc( 3 * totalLen );
4720 + regExpStringInfo->resiLeftWBRegExpString = XtMalloc( 3 * totalLen + 5 );
4721 + regExpStringInfo->resiRightWBRegExpString = XtMalloc( 3 * totalLen + 5 );
4722 + regExpStringInfo->resiBothWBRegExpString = XtMalloc( 3 * totalLen + 6 );
4724 + strcpy( regExpStringInfo->resiNoneWBRegExpString, "" );
4725 + strcpy( regExpStringInfo->resiLeftWBRegExpString, "" );
4726 + strcpy( regExpStringInfo->resiRightWBRegExpString, "" );
4727 + strcpy( regExpStringInfo->resiBothWBRegExpString, "" );
4731 +** Concatenate given 'partToAdd' string to result string, separated
4732 +** by an OR ('|'). Add 'postfix' at end of result string.
4734 +static void addSMTRegExpString(
4735 + char *result,
4736 + char *partToAdd,
4737 + const char *postfix)
4739 + if (strlen(partToAdd) != 0)
4741 + if (strlen(result) != 0)
4743 + strcat( result, "|" );
4746 + strcat( result, partToAdd );
4748 + strcat( result, postfix );
4754 +** Return a string representing given string match table.
4756 +static char *createMatchPatternsString(
4757 + StringMatchTable *table,
4758 + char *indentStr)
4760 + char *outStr, *str;
4761 + textBuffer *outBuf;
4762 + int i, j;
4763 + MatchPatternSequenceElement *seq;
4764 + MatchPatternTableElement *element;
4765 + MatchPatternGroupElement *group;
4767 + outBuf = BufCreate();
4769 + for (i=0; i<table->smtNumberOfSeqElements; i++)
4771 + seq = table->smtSequence[i];
4773 + BufInsert(outBuf, outBuf->length, indentStr);
4774 + BufInsert(outBuf, outBuf->length, seq->mpseName);
4775 + BufInsert(outBuf, outBuf->length, ":");
4777 + if (seq->mpseType == MPT_GROUP)
4779 + BufInsert(outBuf, outBuf->length, "g:");
4781 + group = table->smtGroups[seq->mpseIndex];
4783 + for (j=0; j < group->mpgeNumberOfSubPatterns; j ++)
4785 + BufInsert(outBuf, outBuf->length, group->mpgeSubPatternIds[j]);
4786 + BufInsert(outBuf, outBuf->length, ":");
4789 + else
4791 + if (seq->mpseType == MPT_SUB)
4793 + BufInsert(outBuf, outBuf->length, "s");
4795 + BufInsert(outBuf, outBuf->length, ":");
4797 + element = table->smtAllPatterns->mptElements[seq->mpseIndex];
4799 + /*
4800 + * write global attributes
4801 + */
4802 + if (element->mpteSkipBtwnStartEnd)
4803 + BufInsert(outBuf, outBuf->length, "c");
4804 + if (element->mpteFlash)
4805 + BufInsert(outBuf, outBuf->length, "f");
4806 + if (element->mpteIsMonoPattern)
4807 + BufInsert(outBuf, outBuf->length, "m");
4808 + if (element->mpteIgnoreHighLightInfo)
4809 + BufInsert(outBuf, outBuf->length, "p");
4810 + BufInsert(outBuf, outBuf->length, ":");
4812 + /*
4813 + * write string patterns
4814 + */
4815 + for (j=0; j < element->mpteAll.pesNumberOfPattern; j ++)
4817 + BufInsert(
4818 + outBuf,
4819 + outBuf->length,
4820 + str =
4821 + createPatternElementString(
4822 + table->smtAllPatterns,
4823 + element->mpteAll.pesPattern[j]));
4824 + XtFree(str);
4828 + BufInsert(outBuf, outBuf->length, "\n");
4831 + outStr = BufGetAll(outBuf);
4832 + BufFree(outBuf);
4834 + return outStr;
4838 +** Return a string representing given pattern element.
4840 +static char *createPatternElementString(
4841 + MatchPatternTable *table,
4842 + PatternElement *pat)
4844 + char *outStr, *str;
4845 + textBuffer *outBuf;
4846 + StringPattern *strPat;
4848 + outBuf = BufCreate();
4850 + strPat = GetStringPattern(table, pat);
4852 + /*
4853 + * write string pattern kind
4854 + */
4855 + if (pat->peKind == PEK_START)
4856 + BufInsert(outBuf, outBuf->length, "s");
4857 + else if (pat->peKind == PEK_MIDDLE)
4858 + BufInsert(outBuf, outBuf->length, "m");
4859 + else if (pat->peKind == PEK_END)
4860 + BufInsert(outBuf, outBuf->length, "e");
4862 + /*
4863 + * write word boundary
4864 + */
4865 + if (strPat->spWordBoundary == PWB_BOTH)
4866 + BufInsert(outBuf, outBuf->length, "w");
4867 + else if (strPat->spWordBoundary == PWB_LEFT)
4868 + BufInsert(outBuf, outBuf->length, "l");
4869 + else if (strPat->spWordBoundary == PWB_RIGHT)
4870 + BufInsert(outBuf, outBuf->length, "r");
4872 + /*
4873 + * write case insensitive flag
4874 + */
4875 + if (strPat->spCaseInsensitive)
4876 + BufInsert(outBuf, outBuf->length, "i");
4878 + /*
4879 + * write regular expression flag
4880 + */
4881 + if (strPat->spRegularExpression)
4882 + BufInsert(outBuf, outBuf->length, "x");
4884 + BufInsert(outBuf, outBuf->length, ":");
4886 + /*
4887 + * write pattern string
4888 + */
4889 + if( strPat->spOrigText != NULL)
4890 + BufInsert(
4891 + outBuf,
4892 + outBuf->length,
4893 + str = MakeQuotedString(strPat->spOrigText));
4894 + else
4895 + BufInsert(
4896 + outBuf,
4897 + outBuf->length,
4898 + str = MakeQuotedString(strPat->spText));
4899 + XtFree(str);
4901 + BufInsert(outBuf, outBuf->length, ":");
4903 + outStr = BufGetAll(outBuf);
4904 + BufFree(outBuf);
4906 + return outStr;
4910 +** Given a language mode name, determine if there is a default (built-in)
4911 +** string match table available for that language mode, and if so, read it and
4912 +** return a new allocated copy of it. The returned pattern set should be
4913 +** freed by the caller with freeStringMatchTable().
4915 +static StringMatchTable *readDefaultStringMatchTable(const char *langModeName)
4917 + int i, modeNameLen;
4918 + char *list;
4920 + modeNameLen = strlen(langModeName);
4922 + for (i=0; i<(int)XtNumber(DefaultStringMatchTable); i++)
4924 + if (!strncmp(langModeName, DefaultStringMatchTable[i], modeNameLen) &&
4925 + DefaultStringMatchTable[i][modeNameLen] == '{')
4927 + list = DefaultStringMatchTable[i];
4928 + return readMatchPatternSet(&list);
4932 + list = StandardStringMatchTable;
4933 + return readMatchPatternSetContent(&list, list, XtNewString(langModeName));
4937 +** Return true, if table exactly matches one of the default matching
4938 +** pattern tables.
4940 +static int isDefaultMatchPatternTable(StringMatchTable *table)
4942 + StringMatchTable *defaultTable;
4943 + int retVal;
4945 + defaultTable = readDefaultStringMatchTable(table->smtLanguageMode);
4947 + if (defaultTable == NULL)
4948 + return False;
4950 + retVal = !stringMatchTableDiffer(table, defaultTable);
4952 + freeStringMatchTable(defaultTable);
4954 + return retVal;
4958 +** Read in a string match pattern table character string,
4959 +** and advance *inPtr beyond it.
4960 +** Returns NULL and outputs an error to stderr on failure.
4962 +static StringMatchTable *readMatchPatternSet(char **inPtr)
4964 + char *languageMode;
4965 + StringMatchTable *table = NULL;
4966 + char *stringStart = *inPtr;
4967 + ErrorInfo errInfo;
4969 + initErrorInfo(&errInfo);
4971 + /*
4972 + * remove leading whitespace
4973 + */
4974 + *inPtr += strspn(*inPtr, " \t\n");
4976 + /*
4977 + * read language mode field
4978 + */
4979 + languageMode = ReadSymbolicField(inPtr);
4981 + /*
4982 + * look for initial brace
4983 + */
4984 + if (**inPtr == ':')
4986 + (*inPtr) ++;
4987 + /*
4988 + * look for "Default" keyword, and if it's there, return the default
4989 + * pattern set
4990 + */
4991 + if (!strncmp(*inPtr, "Default", 7))
4993 + *inPtr += 7;
4994 + table = readDefaultStringMatchTable(languageMode);
4995 + XtFree(languageMode);
4997 + return table;
5001 + table = readMatchPatternSetContent(inPtr, stringStart, languageMode);
5003 + if (table == NULL)
5004 + XtFree(languageMode);
5006 + return table;
5010 +** Read in a content string ("{..}") of match pattern table,
5011 +** and advance *inPtr beyond it.
5012 +** Returns NULL and outputs an error to stderr on failure.
5014 +static StringMatchTable *readMatchPatternSetContent(
5015 + char **inPtr,
5016 + char *stringStart,
5017 + char *languageMode)
5019 + ReadMatchPatternInfo readPatInfo;
5020 + StringMatchTable *table = NULL;
5021 + ErrorInfo errInfo;
5022 + int successful = True;
5023 + int endOfPatternSet = False;
5025 + initErrorInfo(&errInfo);
5027 + /*
5028 + * look for initial brace
5029 + */
5030 + if (**inPtr != '{')
5032 + errInfo.eiLanguageMode = XtNewString(languageMode);
5033 + errInfo.eiDetail = "pattern list must begin with \"{\"";
5034 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo );
5036 + return NULL;
5039 + (*inPtr)++;
5041 + readPatInfo.rmpiNbrOfElements = 0;
5042 + readPatInfo.rmpiNbrOfGroups = 0;
5043 + readPatInfo.rmpiNbrOfSeqElements = 0;
5044 + readPatInfo.rmpiAllPatRE = NULL;
5045 + readPatInfo.rmpiFlashPatRE = NULL;
5047 + /*
5048 + * parse each pattern in the list
5049 + */
5050 + while (successful && !endOfPatternSet)
5052 + *inPtr += strspn(*inPtr, " \t\n");
5053 + if (**inPtr == '\0')
5055 + errInfo.eiLanguageMode = XtNewString(languageMode);
5056 + errInfo.eiDetail = "end of pattern list not found";
5057 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo);
5058 + successful = False;
5060 + else if (**inPtr == '}')
5062 + (*inPtr)++;
5063 + endOfPatternSet = True;
5065 + else
5067 + if (!readMatchPatternEntry(inPtr, &errInfo, &readPatInfo))
5069 + errInfo.eiLanguageMode = XtNewString(languageMode);
5070 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo);
5071 + successful = False;
5076 + if (successful)
5078 + /*
5079 + * compile regular expressions of read patterns
5080 + */
5081 + if (createRegExpOfPatterns(&readPatInfo, &errInfo))
5083 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo);
5084 + successful = False;
5088 + if (successful)
5090 + return createStringMatchTable(&readPatInfo, languageMode);
5092 + else
5094 + /*
5095 + * free memory of already read patterns
5096 + */
5097 + freeReadMatchPatternInfo(&readPatInfo);
5099 + return NULL;
5102 + return table;
5106 +** Create a reg. exp. of all patterns contained
5107 +** in given read match pattern info.
5109 +static int createRegExpOfPatterns(
5110 + ReadMatchPatternInfo *readPatInfo,
5111 + ErrorInfo *errInfo)
5113 + if (createRegExpOfStrPatterns(readPatInfo, errInfo))
5114 + return True;
5116 + if (createRegExpOfAllPatterns(readPatInfo, errInfo))
5117 + return True;
5119 + return False;
5123 +** Create a "total pattern reg. exp." of all patterns / flash patterns
5124 +** contained in given read match pattern info.
5125 +** Returns true, if create of reg. exp. has failed.
5127 +static int createRegExpOfAllPatterns(
5128 + ReadMatchPatternInfo *readPatInfo,
5129 + ErrorInfo *errInfo)
5131 + int i;
5132 + RegExpStringInfo allPatRegExpSI;
5133 + RegExpStringInfo flashPatRegExpSI;
5134 + MatchPatternTableElement *element;
5135 + char *regExpString;
5136 + char *compileMsg;
5138 + /*
5139 + * Allocate buffers for keyword regular expressions.
5140 + */
5141 + setupRegExpStringBuffers(readPatInfo, &allPatRegExpSI);
5142 + setupRegExpStringBuffers(readPatInfo, &flashPatRegExpSI);
5144 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5146 + element = readPatInfo->rmpiElement[i];
5148 + /*
5149 + * Add the keywords of the matching pattern to the keyword
5150 + * regular expression string buffer of all patterns.
5151 + */
5152 + addElementToRegExpString(
5153 + element,
5154 + readPatInfo,
5155 + &allPatRegExpSI);
5157 + /*
5158 + * If flash attribute is set, then add the keywords of the
5159 + * matching pattern also to the keyword regular expression
5160 + * string buffer of flash patterns.
5161 + */
5162 + if (element->mpteFlash)
5164 + addElementToRegExpString(
5165 + element,
5166 + readPatInfo,
5167 + &flashPatRegExpSI);
5171 + /*
5172 + * Assemble and compile the resulting all keywords reg. exp. string.
5173 + */
5174 + catSMTRegExpStrings(
5175 + &allPatRegExpSI,
5176 + &regExpString);
5178 + readPatInfo->rmpiAllPatRE =
5179 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
5181 + XtFree( regExpString );
5183 + if (readPatInfo->rmpiAllPatRE == NULL)
5185 + errInfo->eiRegExpCompileMsg = compileMsg;
5186 + errInfo->eiDetail = "All patterns: compile reg. exp. error";
5187 + return True;
5190 + /*
5191 + * Assemble and compile the resulting flash keywords reg. exp. string.
5192 + */
5193 + catSMTRegExpStrings(
5194 + &flashPatRegExpSI,
5195 + &regExpString);
5197 + readPatInfo->rmpiFlashPatRE =
5198 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
5200 + XtFree( regExpString );
5202 + if (readPatInfo->rmpiFlashPatRE == NULL)
5204 + errInfo->eiRegExpCompileMsg = compileMsg;
5205 + errInfo->eiDetail = "Flash patterns: compile reg. exp. error";
5206 + return True;
5209 + /*
5210 + * Pattern reg. exp. successful created:
5211 + */
5212 + return False;
5216 +** Create reg. exp. of single patterns contained in given
5217 +** read match pattern info.
5218 +** Returns true, if create of reg. exp. has failed.
5220 +static int createRegExpOfStrPatterns(
5221 + ReadMatchPatternInfo *readPatInfo,
5222 + ErrorInfo *errInfo)
5224 + int i;
5225 + MatchPatternTableElement *element;
5226 + MatchPatternGroupElement *group;
5228 + /*
5229 + * create global backref list of all elements of read info
5230 + */
5231 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5233 + element = readPatInfo->rmpiElement[i];
5235 + if (!createGlobalBackRefList(readPatInfo, element, errInfo))
5236 + return True;
5239 + /*
5240 + * resolve global backrefs of all elements of read info
5241 + */
5242 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5244 + element = readPatInfo->rmpiElement[i];
5246 + if (!resolveGlobalBackRefs(readPatInfo, element, errInfo))
5247 + return True;
5250 + /*
5251 + * compile reg. exp. of all elements of read info
5252 + */
5253 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5255 + element = readPatInfo->rmpiElement[i];
5257 + if (createStrPatRegExpOfElement(readPatInfo, element, errInfo))
5258 + return True;
5260 + /*
5261 + * create start / end reg. exp. if applicable.
5262 + */
5263 + if (element->mpteSkipBtwnStartEnd)
5265 + if (createStartEndRegExp(readPatInfo, element, errInfo))
5266 + return True;
5270 + /*
5271 + * compile reg. exp. of all groups of read info
5272 + */
5273 + for (i=0; i < readPatInfo->rmpiNbrOfGroups; i ++)
5275 + group = readPatInfo->rmpiGroup[i];
5277 + if (createGroupRegExp(readPatInfo, group, errInfo))
5279 + return True;
5283 + return False;
5287 +** Create a string match table out of read match pattern info.
5289 +static StringMatchTable *createStringMatchTable(
5290 + ReadMatchPatternInfo *readPatInfo,
5291 + char *languageMode)
5293 + StringMatchTable *table;
5294 + MatchPatternTable *patTable;
5295 + int sizeOfElements;
5297 + table = (StringMatchTable *)XtMalloc(sizeof(StringMatchTable));
5298 + table->smtLanguageMode = languageMode;
5300 + /*
5301 + * allocate a more appropriately sized list to return matching patterns
5302 + */
5303 + patTable = (MatchPatternTable *)XtMalloc(sizeof(MatchPatternTable));
5304 + patTable->mptNumberOfElements = readPatInfo->rmpiNbrOfElements;
5306 + if (readPatInfo->rmpiNbrOfElements > 0)
5308 + sizeOfElements =
5309 + sizeof(MatchPatternTableElement *) * readPatInfo->rmpiNbrOfElements;
5310 + patTable->mptElements =
5311 + (MatchPatternTableElement **)XtMalloc(sizeOfElements);
5312 + memcpy(patTable->mptElements, readPatInfo->rmpiElement, sizeOfElements);
5314 + else
5316 + patTable->mptElements = NULL;
5319 + table->smtAllPatterns = patTable;
5321 + table->smtAllPatRE = readPatInfo->rmpiAllPatRE;
5322 + table->smtFlashPatRE = readPatInfo->rmpiFlashPatRE;
5323 + table->smtUsedPatRE = NULL;
5325 + /*
5326 + * allocate a more appropriately sized list to return matching pattern groups
5327 + */
5328 + table->smtNumberOfGroups = readPatInfo->rmpiNbrOfGroups;
5329 + if (readPatInfo->rmpiNbrOfGroups > 0)
5331 + sizeOfElements =
5332 + sizeof(MatchPatternGroupElement *) * readPatInfo->rmpiNbrOfGroups;
5333 + table->smtGroups =
5334 + (MatchPatternGroupElement **)XtMalloc(sizeOfElements);
5335 + memcpy(table->smtGroups, readPatInfo->rmpiGroup, sizeOfElements);
5337 + else
5339 + table->smtGroups = NULL;
5341 + /*
5342 + * allocate a more appropriately sized list to return matching pattern sequence
5343 + */
5344 + table->smtNumberOfSeqElements = readPatInfo->rmpiNbrOfSeqElements;
5345 + if (readPatInfo->rmpiNbrOfSeqElements > 0)
5347 + sizeOfElements =
5348 + sizeof(MatchPatternSequenceElement *) * readPatInfo->rmpiNbrOfSeqElements;
5349 + table->smtSequence =
5350 + (MatchPatternSequenceElement **)XtMalloc(sizeOfElements);
5351 + memcpy(table->smtSequence, readPatInfo->rmpiSequence, sizeOfElements);
5353 + else
5355 + table->smtSequence = NULL;
5358 + return table;
5362 +** Read one match pattern entry of a match pattern string.
5363 +** Returns true, if read was successful.
5365 +static int readMatchPatternEntry(
5366 + char **inPtr,
5367 + ErrorInfo *errInfo,
5368 + ReadMatchPatternInfo *info)
5370 + char *name;
5371 + MatchPatternType type;
5372 + MatchPatternGroupElement *readGroup;
5373 + MatchPatternTableElement *readElement;
5375 + if (!getMPSName( inPtr, errInfo, &name ))
5377 + return False;
5380 + if (!getMPSTypeAttribute( inPtr, errInfo, &type ))
5382 + errInfo->eiMPTabElementName = XtNewString(name);
5383 + return False;
5386 + if (type == MPT_GROUP)
5388 + if (info->rmpiNbrOfGroups >= MAX_NBR_MATCH_PATTERN_GROUPS)
5390 + errInfo->eiMPTabElementName = XtNewString(name);
5391 + errInfo->eiDetail = "max number of match pattern groups exceeded";
5392 + return False;
5395 + readGroup = readMatchPatternGroup( inPtr, errInfo, name, info );
5397 + if (readGroup == NULL)
5399 + errInfo->eiMPTabElementName = XtNewString(name);
5400 + XtFree( name );
5402 + else
5404 + info->rmpiGroup[info->rmpiNbrOfGroups ++] = readGroup;
5406 + recordPatternSequence( info, name, type, info->rmpiNbrOfGroups-1 );
5409 + return (readGroup != NULL);
5411 + else
5413 + if (info->rmpiNbrOfElements >= MAX_NBR_MATCH_PATTERNS)
5415 + errInfo->eiMPTabElementName = XtNewString(name);
5416 + errInfo->eiDetail = "max number of match patterns exceeded";
5417 + XtFree( name );
5418 + return False;
5421 + readElement =
5422 + readMatchPatternTableElement( inPtr, &errInfo->eiDetail, name, type );
5424 + if (readElement == NULL)
5426 + errInfo->eiMPTabElementName = XtNewString(name);
5427 + XtFree( name );
5429 + else
5431 + readElement->mpteIndex = info->rmpiNbrOfElements;
5433 + info->rmpiElement[info->rmpiNbrOfElements ++] = readElement;
5435 + if (type == MPT_INDIVIDUAL)
5437 + if (!assignIndividualGroup( info, &errInfo->eiDetail, readElement ))
5439 + errInfo->eiMPTabElementName = XtNewString(name);
5440 + return False;
5444 + treatDuplicatedMTEntries(
5445 + info->rmpiElement, info->rmpiNbrOfElements );
5447 + recordPatternSequence( info, name, type, info->rmpiNbrOfElements-1 );
5450 + return (readElement != NULL);
5455 +** Record match pattern sequence for display of match pattern dialog.
5457 +static void recordPatternSequence(
5458 + ReadMatchPatternInfo *info,
5459 + char *name,
5460 + MatchPatternType type,
5461 + int index)
5463 + MatchPatternSequenceElement *sequence;
5465 + sequence =
5466 + (MatchPatternSequenceElement *)XtMalloc( sizeof(MatchPatternSequenceElement) );
5468 + sequence->mpseName = XtNewString(name);
5469 + sequence->mpseType = type;
5470 + sequence->mpseIndex = index;
5472 + info->rmpiSequence[info->rmpiNbrOfSeqElements ++] = sequence;
5476 +** Assign a new group to an individual match pattern.
5477 +** Returns true, if assignment was successful.
5479 +static int assignIndividualGroup(
5480 + ReadMatchPatternInfo *info,
5481 + char **errMsg,
5482 + MatchPatternTableElement *element)
5484 + MatchPatternGroupElement *group = NULL;
5486 + if (info->rmpiNbrOfGroups >= MAX_NBR_MATCH_PATTERN_GROUPS)
5488 + *errMsg = "max. number of matching pattern groups exceeded\n";
5489 + return False;
5492 + /*
5493 + * Assign the index of new group to the individual matching pattern
5494 + */
5495 + element->mpteGroup = info->rmpiNbrOfGroups;
5497 + /*
5498 + * Allocate memory for the matching pattern group and copy the
5499 + * info into this group element.
5500 + */
5501 + group =
5502 + (MatchPatternGroupElement *)XtMalloc( sizeof(MatchPatternGroupElement) );
5504 + group->mpgeName = NULL;
5505 + group->mpgeKeywordRE = NULL;
5507 + /*
5508 + * remember name of match pattern table element, which is
5509 + * represented by this group.
5510 + */
5511 + group->mpgeNumberOfSubPatterns = 1;
5512 + group->mpgeSubPatternIds = (char **)XtMalloc( sizeof(char *) );
5513 + group->mpgeSubPatternIds[0] = XtNewString(element->mpteName);
5515 + info->rmpiGroup[info->rmpiNbrOfGroups ++] = group;
5517 + return True;
5521 +** Get the match pattern table element of given 'patToSearch'
5522 +** name.
5523 +** Returns NULL, if no element was found.
5525 +static MatchPatternTableElement *getPatternOfName(
5526 + ReadMatchPatternInfo *info,
5527 + char *patToSearch)
5529 + int i;
5530 + MatchPatternTableElement *element;
5532 + for (i=0; i<info->rmpiNbrOfElements; i ++)
5534 + element = info->rmpiElement[i];
5536 + if (strcmp( element->mpteName, patToSearch ) == 0)
5538 + /*
5539 + * Related sub-pattern found:
5540 + */
5541 + return element;
5545 + /*
5546 + * No sub-pattern found:
5547 + */
5548 + return NULL;
5552 +** Read match pattern group of given match pattern string.
5553 +** Returns NULL, if read fails.
5555 +static MatchPatternGroupElement *readMatchPatternGroup(
5556 + char **inPtr,
5557 + ErrorInfo *errInfo,
5558 + char *name,
5559 + ReadMatchPatternInfo *info)
5561 + int i;
5562 + int error = False;
5563 + char *patNameInPtr;
5564 + char *subPatName;
5565 + MatchPatternTableElement *subPatElement;
5566 + int numberOfRelatedSubPattern = 0;
5567 + char *relatedSubPatternId[MAX_NBR_MATCH_PATTERNS];
5568 + int sizeOfIds;
5569 + MatchPatternGroupElement *group = NULL;
5571 + /*
5572 + * Read sub-matching patterns of this group.
5573 + */
5574 + while (**inPtr != '\n' && !error)
5576 + /*
5577 + * Read next pattern name from inPtr.
5578 + */
5579 + patNameInPtr = *inPtr;
5580 + subPatName = ReadSymbolicField(inPtr);
5582 + if (subPatName == NULL)
5584 + errInfo->eiDetail = "Sub-Matching Pattern Name expected";
5585 + error = True;
5587 + else
5589 + /*
5590 + * Get matching pattern related to sub-matching pattern name.
5591 + */
5592 + subPatElement =
5593 + getPatternOfName( info, subPatName );
5595 + if (subPatElement == NULL)
5597 + errInfo->eiStringPatText = XtNewString(subPatName);
5598 + errInfo->eiDetail = "Sub-Matching Pattern not defined before";
5599 + error = True;
5601 + else if (numberOfRelatedSubPattern >= MAX_NBR_MATCH_PATTERNS)
5603 + errInfo->eiDetail = "Group holds too many Sub-Matching Patterns";
5604 + error = True;
5606 + else if (subPatElement->mpteType != MPT_SUB)
5608 + errInfo->eiStringPatText = XtNewString(subPatName);
5609 + errInfo->eiDetail = "Not a Sub-Matching Pattern";
5610 + error = True;
5612 + else
5614 + /*
5615 + * Remember sub-matching pattern ID
5616 + */
5617 + relatedSubPatternId[numberOfRelatedSubPattern ++] = subPatName;
5619 + /*
5620 + * Assign the index of this group to the sub-matching pattern
5621 + * if no group index was assigned before.
5622 + */
5623 + if (subPatElement->mpteGroup == NO_GROUP_IDX)
5625 + subPatElement->mpteGroup = info->rmpiNbrOfGroups;
5629 + /*
5630 + * Skip to the start of the next matching pattern name.
5631 + */
5632 + if (!error && !SkipDelimiter(inPtr, &errInfo->eiDetail))
5634 + error = True;
5639 + if (error)
5641 + for (i=0; i < numberOfRelatedSubPattern; i++)
5643 + XtFree( relatedSubPatternId[i] );
5646 + return NULL;
5648 + else
5650 + /*
5651 + * Allocate memory for the matching pattern group and copy the
5652 + * info into this group element.
5653 + */
5654 + group =
5655 + (MatchPatternGroupElement *)XtMalloc( sizeof(MatchPatternGroupElement) );
5657 + group->mpgeName = name;
5658 + group->mpgeKeywordRE = NULL;
5660 + /*
5661 + * Allocate memory for the sub-matching pattern IDs & copy
5662 + * related sub-matching pattern into the group element.
5663 + */
5664 + sizeOfIds = sizeof(char *) * numberOfRelatedSubPattern;
5665 + group->mpgeSubPatternIds = (char **)XtMalloc( sizeOfIds );
5667 + memcpy(group->mpgeSubPatternIds, relatedSubPatternId, sizeOfIds);
5669 + group->mpgeNumberOfSubPatterns = numberOfRelatedSubPattern;
5671 + return group;
5676 +** Read one match pattern element from given match pattern string.
5677 +** Returns true, if read was successful.
5679 +static int readPatternElement(
5680 + char **inPtr,
5681 + char **errMsg,
5682 + PatternElement **pattern)
5684 + PatternElementKind patternKind;
5685 + PatternWordBoundary wordBoundary;
5686 + int caseInsensitive;
5687 + int regularExpression;
5688 + char *string;
5690 + if (!getMPSPatternAttribute(
5691 + inPtr,
5692 + errMsg,
5693 + &patternKind,
5694 + &wordBoundary,
5695 + &caseInsensitive,
5696 + &regularExpression ))
5698 + return False;
5701 + if (!ReadQuotedString(inPtr, errMsg, &string))
5703 + return False;
5706 + if (!SkipDelimiter(inPtr, errMsg))
5708 + XtFree( string );
5709 + return False;
5712 + *pattern =
5713 + createPatternElement(
5714 + string,
5715 + patternKind,
5716 + wordBoundary,
5717 + caseInsensitive,
5718 + regularExpression);
5720 + return True;
5724 +** Create a pattern element.
5726 +static PatternElement *createPatternElement(
5727 + char *patternText,
5728 + PatternElementKind patternKind,
5729 + PatternWordBoundary wordBoundary,
5730 + int caseInsensitive,
5731 + int regularExpression)
5733 + PatternElement *pattern;
5734 + char *s;
5736 + /*
5737 + * Convert pattern text to lower case, if case insensitive
5738 + * attribute is set.
5739 + */
5740 + if (caseInsensitive)
5742 + for (s = patternText; *s != '\0'; s ++)
5744 + *s = tolower(*s);
5748 + /*
5749 + * Allocate memory for the new pattern element and init. / copy
5750 + * related info into this pattern element.
5751 + */
5752 + pattern = (PatternElement *)XtMalloc( sizeof(PatternElement) );
5754 + initStrPatBackRefList(&pattern->peVal.peuSingle);
5756 + pattern->peKind = patternKind;
5757 + pattern->peIndex = NO_PATTERN_IDX;
5758 + pattern->peType = PET_SINGLE;
5760 + pattern->peVal.peuSingle.spLength = strlen(patternText);
5761 + pattern->peVal.peuSingle.spBackRefParsed = False;
5762 + pattern->peVal.peuSingle.spBackRefResolved = False;
5764 + pattern->peVal.peuSingle.spCaseInsensitive = caseInsensitive;
5765 + pattern->peVal.peuSingle.spRegularExpression = regularExpression;
5766 + pattern->peVal.peuSingle.spTextRE = NULL;
5768 + /*
5769 + * Store original string of regular expression patterns due to
5770 + * it may be later adapted (e.g. due to global backrefs etc.).
5771 + */
5772 + if (regularExpression)
5774 + pattern->peVal.peuSingle.spOrigText = patternText;
5775 + pattern->peVal.peuSingle.spText = NULL;
5776 + pattern->peVal.peuSingle.spWordBoundary = PWB_NONE;
5778 + else
5780 + pattern->peVal.peuSingle.spOrigText = NULL;
5781 + pattern->peVal.peuSingle.spText = patternText;
5782 + pattern->peVal.peuSingle.spWordBoundary = wordBoundary;
5785 + return pattern;
5789 +** Create a list holding all global backref definitions of given
5790 +** match pattern table element. The list is stored in this given
5791 +** element.
5792 +** Returns true, if list was successfully created.
5794 +static int createGlobalBackRefList(
5795 + ReadMatchPatternInfo *readPatInfo,
5796 + MatchPatternTableElement *element,
5797 + ErrorInfo *errInfo)
5799 + int i;
5800 + StringPattern *strPat;
5802 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
5804 + strPat = getReadStringPattern(readPatInfo, element->mpteAll.pesPattern[i]);
5806 + if (strPat->spRegularExpression)
5808 + if (strPat->spBackRefParsed)
5810 + /*
5811 + * Global backrefs or this string pattern already parsed:
5812 + * just merge string pattern list with elements one.
5813 + */
5814 + if (!updateGlobalBackRefs(
5815 + strPat,
5816 + element->mpteGlobalBackRef,
5817 + errInfo))
5819 + return False;
5822 + else
5824 + /*
5825 + * parse string pattern for global backrefs and
5826 + * merge string pattern list with elements one.
5827 + */
5828 + if (!parseGlobalBackRefs(
5829 + strPat,
5830 + element->mpteGlobalBackRef,
5831 + errInfo))
5833 + return False;
5839 + return True;
5843 +** Returns read string pattern of given pattern element.
5845 +StringPattern *getReadStringPattern(
5846 + ReadMatchPatternInfo *readPatInfo,
5847 + PatternElement *pattern )
5849 + switch (pattern->peType)
5851 + case PET_SINGLE:
5852 + return &pattern->peVal.peuSingle;
5853 + break;
5855 + case PET_MULTIPLE:
5856 + return &pattern->peVal.peuMulti.mpStringPattern;
5857 + break;
5859 + case PET_REFERENCE:
5860 + return getReadStringPattern(
5861 + readPatInfo,
5862 + getReadPatternOfReference(readPatInfo, &pattern->peVal.peuRef));
5863 + break;
5866 + /*
5867 + * never reached; just to make compiler happy
5868 + */
5869 + return NULL;
5873 +** Returns read pattern element of given pattern reference.
5875 +static PatternElement *getReadPatternOfReference(
5876 + ReadMatchPatternInfo *readPatInfo,
5877 + PatternReference *patRef)
5879 + MatchPatternTableElement **element = readPatInfo->rmpiElement;
5881 + return element[ patRef->prElementIdx ]->mpteAll.pesPattern[patRef->prPatternIdx];
5885 +** Allocate a new copy of given string and substitute each capturing
5886 +** parentheses inside given string by a non-capturing one.
5887 +** Returns resulting string.
5889 +static char *replaceCapturingParentheses(
5890 + const char *source)
5892 + char *destination;
5893 + const char *s;
5894 + char *d;
5895 + int nbrOfOpenBraces = 0;
5897 + s = source;
5899 + /*
5900 + * count number of open braces
5901 + */
5902 + while (*s != '\0')
5904 + if (*s++ == '(')
5905 + nbrOfOpenBraces ++;
5908 + /*
5909 + * allocate memory for substitued reg. exp. text
5910 + */
5911 + destination = XtMalloc(strlen(source) + 2*nbrOfOpenBraces);
5913 + /*
5914 + * substitute each capturing open brace by a non-capturing one
5915 + */
5916 + s = source;
5917 + d = destination;
5919 + while (*s != '\0')
5921 + if (*s == '\\')
5923 + *d++ = *s++;
5925 + if (*s != '\0')
5926 + *d++ = *s++;
5928 + else if (*s == '(')
5930 + *d++ = *s++;
5932 + if (*s != '?' && *s != '*')
5934 + *d++ = '?';
5935 + *d++ = ':';
5938 + else
5940 + *d++ = *s++;
5944 + *d = '\0';
5946 + return destination;
5950 +** Parse given string pattern for global backrefs definitions
5951 +** (syntax: "(*n", where n=1..9). Add found global backrefs to
5952 +** given backRefList.
5953 +** Returns false, if parse fails.
5955 +static int parseGlobalBackRefs(
5956 + StringPattern *strPat,
5957 + GlobalBackRefElement *backRefList,
5958 + ErrorInfo *errInfo)
5960 + char *s;
5961 + char *backRefContent;
5962 + int nestingLevel = 0;
5963 + int stackIdx = -1;
5964 + BackRefBracketInfo backRefInfo[MAX_GLOBAL_BACK_REF_ID+1];
5965 + StrPatBackRefElement *curStrPatBRE;
5967 + strPat->spText = replaceCapturingParentheses(strPat->spOrigText);
5968 + strPat->spLength = strlen(strPat->spText);
5969 + strPat->spBackRefParsed = True;
5971 + s = strPat->spText;
5973 + while (*s != '\0')
5975 + if (*s == '\\')
5977 + /*
5978 + * Ignore escaped characters
5979 + */
5980 + if (*(s+1) != '\0')
5981 + s ++;
5983 + else if (*s == '(')
5985 + if (*(s+1) == '*')
5987 + if (isdigit((unsigned char)*(s+2)))
5989 + /*
5990 + * Global backref. definition start found:
5991 + */
5992 + stackIdx ++;
5994 + backRefInfo[stackIdx].brbiGlobalId =
5995 + (int)((unsigned char)*(s+2) - (unsigned char)'0') - 1;
5997 + if(backRefInfo[stackIdx].brbiGlobalId < 0)
5999 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6000 + errInfo->eiDetail = "Backref '0' not allowed";
6001 + return False;
6004 + backRefInfo[stackIdx].brbiContentStart = s+3;
6005 + backRefInfo[stackIdx].brbiNestingLevel = nestingLevel;
6006 + s ++;
6008 + s ++;
6010 + nestingLevel ++;
6012 + else if (*s == ')')
6014 + nestingLevel --;
6015 + if (stackIdx != -1 &&
6016 + backRefInfo[stackIdx].brbiNestingLevel == nestingLevel)
6018 + /*
6019 + * Global backref. definition end found: add it to
6020 + * backref. list of string pattern.
6021 + */
6022 + curStrPatBRE =
6023 + &strPat->spOwnGlobalBackRef[backRefInfo[stackIdx].brbiGlobalId];
6025 + backRefContent =
6026 + createBackRefRegExpText(
6027 + backRefInfo[stackIdx].brbiContentStart,
6028 + s);
6030 + if (curStrPatBRE->spbreRegExpText != NULL)
6032 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6033 + errInfo->eiBackRefNbr = backRefInfo[stackIdx].brbiGlobalId + 1;
6034 + errInfo->eiDetail = "already defined before";
6035 + XtFree(backRefContent);
6036 + return False;
6038 + else
6040 + curStrPatBRE->spbreRegExpText = backRefContent;
6043 + stackIdx --;
6046 + s ++;
6049 + /*
6050 + * Merge global backref. list of string pattern with given backRefList.
6051 + */
6052 + return updateGlobalBackRefs(
6053 + strPat,
6054 + backRefList,
6055 + errInfo);
6059 +** Merge global backref. list of given string pattern with given backRefList.
6060 +** Returns false, if merge fails.
6062 +static int updateGlobalBackRefs(
6063 + StringPattern *strPat,
6064 + GlobalBackRefElement *backRefList,
6065 + ErrorInfo *errInfo)
6067 + int i;
6068 + StrPatBackRefElement *curStrPatBRE;
6069 + GlobalBackRefElement *curGlobalBRE;
6071 + for (i=0;i < MAX_GLOBAL_BACK_REF_ID; i ++)
6073 + curStrPatBRE = &strPat->spOwnGlobalBackRef[i];
6075 + if (curStrPatBRE->spbreRegExpText != NULL)
6077 + curGlobalBRE = &backRefList[i];
6079 + if (curGlobalBRE->gbreDefByStrPat != NULL)
6081 + if (strcmp(curGlobalBRE->gbreRegExpText, curStrPatBRE->spbreRegExpText) != 0)
6083 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6084 + errInfo->eiBackRefNbr = i+1;
6085 + errInfo->eiDetail = "already defined before";
6087 + return False;
6090 + else
6092 + curGlobalBRE->gbreDefByStrPat = strPat;
6093 + curGlobalBRE->gbreRegExpText = curStrPatBRE->spbreRegExpText;
6098 + return True;
6102 +** Allocate and return a new string holding content of
6103 +** global backref. definition.
6105 +static char *createBackRefRegExpText(
6106 + const char *start,
6107 + const char *end)
6109 + int len = end - start;
6110 + char *regExpText = XtMalloc( len+1 );
6112 + memcpy( regExpText, start, len );
6114 + regExpText[len] = '\0';
6116 + return regExpText;
6120 +** Resolve all global backrefs of given match pattern table element.
6121 +** Returns false, if resolve fails.
6123 +static int resolveGlobalBackRefs(
6124 + ReadMatchPatternInfo *readPatInfo,
6125 + MatchPatternTableElement *element,
6126 + ErrorInfo *errInfo)
6128 + int i;
6129 + StringPattern *strPat;
6131 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
6133 + strPat = getReadStringPattern(readPatInfo, element->mpteAll.pesPattern[i]);
6135 + if (strPat->spRegularExpression && !strPat->spBackRefResolved)
6137 + if (!resolveGlobalBackRefsOfStrPat(strPat, element->mpteGlobalBackRef, errInfo))
6138 + return False;
6140 + strPat->spBackRefResolved = True;
6144 + return True;
6148 +** Resolve global backrefs of given string pattern.
6149 +** Returns false, if resolve fails.
6151 +static int resolveGlobalBackRefsOfStrPat(
6152 + StringPattern *strPat,
6153 + GlobalBackRefElement *backRefList,
6154 + ErrorInfo *errInfo)
6156 + char *s;
6157 + int globalId;
6158 + int localId = 1;
6160 + s = strPat->spText;
6162 + while (*s != '\0')
6164 + if (*s == '\\')
6166 + if (isdigit((unsigned char)*(s+1)))
6168 + /*
6169 + * \n (n=1..9) found: substitute global backref.
6170 + */
6171 + globalId =
6172 + (int)((unsigned char)*(s+1) - (unsigned char)'0') - 1;
6174 + if(globalId < 0)
6176 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6177 + errInfo->eiDetail = "backref '\\0' not allowed";
6178 + return False;
6181 + s = substituteGlobalBackRef(strPat, s, globalId, &localId, backRefList, errInfo);
6183 + if (s == NULL)
6184 + return False;
6186 + else if (*(s+1) != '\0')
6187 + s ++;
6189 + else if (*s == '(')
6191 + if (*(s+1) == '*')
6193 + if (isdigit((unsigned char)*(s+2)))
6195 + /*
6196 + * "(*n" (n=1..9) found: substitute global backref. definition.
6197 + */
6198 + globalId =
6199 + (int)((unsigned char)*(s+2) - (unsigned char)'0') - 1;
6201 + strPat->spOwnGlobalBackRef[globalId].spbreLocalBackRefID = localId;
6202 + strPat->spGlobalToLocalBackRef[globalId] = localId;
6204 + localId ++;
6206 + s = convertGlobalToLocalBackRef(strPat, s);
6208 + else
6210 + s ++;
6214 + s ++;
6217 + return True;
6221 +** Substitute global backref (\n, n=1..9) located at given "subsPtr"
6222 +** by its definition or by a local backref.
6223 +** Returns
6224 +** - NULL, if substitute fails or
6225 +** - substituted string pointer, where scan shall continue with.
6227 +static char *substituteGlobalBackRef(
6228 + StringPattern *strPat,
6229 + char *subsPtr,
6230 + int globalId,
6231 + int *localId,
6232 + GlobalBackRefElement *backRefList,
6233 + ErrorInfo *errInfo)
6235 + StrPatBackRefElement *strPatBackRef = &strPat->spOwnGlobalBackRef[globalId];
6236 + char *s;
6238 + if (strPatBackRef->spbreRegExpText == NULL)
6240 + /*
6241 + * given global backref definition is not located in given
6242 + * string pattern -> replace backref ID by backref reg. exp.
6243 + */
6244 + if (backRefList[globalId].gbreRegExpText == NULL)
6246 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6247 + errInfo->eiBackRefNbr = globalId + 1;
6248 + errInfo->eiDetail = "not defined within any string pattern";
6249 + return NULL;
6252 + if (strPat->spGlobalToLocalBackRef[globalId] == NO_LOCAL_BACK_REF_ID)
6254 + /*
6255 + * 1st occurence of global backref ID in this pattern ->
6256 + * replace global backref ID by backref reg. exp.
6257 + */
6258 + s = replaceBackRefIdByRegExp(strPat, subsPtr, backRefList[globalId].gbreRegExpText);
6260 + strPat->spGlobalToLocalBackRef[globalId] = *localId;
6261 + (*localId) ++;
6263 + else
6265 + /*
6266 + * next occurence of global backref ID in this pattern ->
6267 + * replace global backref ID by local one
6268 + */
6269 + s = subsPtr + 1;
6270 + *s = (char)((int)('0') + strPat->spGlobalToLocalBackRef[globalId]);
6273 + else
6275 + /*
6276 + * given global backref definition is located in given string pattern
6277 + */
6278 + if (strPatBackRef->spbreLocalBackRefID == NO_LOCAL_BACK_REF_ID)
6280 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6281 + errInfo->eiBackRefNbr = globalId + 1;
6282 + errInfo->eiDetail = "not defined before";
6283 + return NULL;
6286 + /*
6287 + * replace global backref ID by local one
6288 + */
6289 + s = subsPtr + 1;
6290 + *s = (char)((int)('0') + strPatBackRef->spbreLocalBackRefID);
6293 + return s;
6297 +** Replace global backref ID ("\n", n=1..9), located at given
6298 +** replaceStartPtr, by its definition (given by regExp parameter).
6299 +** Returns string pointer, where scan shall continue with
6301 +static char *replaceBackRefIdByRegExp(
6302 + StringPattern *strPat,
6303 + char *replaceStartPtr,
6304 + char *regExp)
6306 + char *oldText = strPat->spText;
6307 + char *newText;
6308 + char *n;
6309 + char *continueScanPtr;
6310 + int oldLen = strlen(oldText);
6311 + int regExpLen = strlen(regExp);
6312 + int replacePos = replaceStartPtr - oldText;
6313 + int remainingLen = oldLen-replacePos-2;
6315 + /*
6316 + * replace "\n" - located at replaceStartPtr - by "(regExp)"
6317 + */
6318 + newText = XtMalloc(oldLen + regExpLen + 3);
6320 + memcpy(newText, oldText, replacePos);
6321 + n = newText + replacePos;
6322 + *n = '(';
6323 + continueScanPtr = n;
6324 + n ++;
6325 + memcpy(n, regExp, regExpLen);
6326 + n += regExpLen;
6327 + *n = ')';
6328 + n ++;
6329 + memcpy(n, replaceStartPtr+2, remainingLen);
6330 + *(n + remainingLen) = '\0';
6332 + XtFree(oldText);
6334 + strPat->spText = newText;
6335 + strPat->spLength = strlen(newText);
6337 + return continueScanPtr;
6341 +** Convert global backref definition ("(*n", n=1..9), located at given
6342 +** convertPtr, by capturing parentheses "(".
6343 +** Returns string pointer, where scan shall continue with
6345 +static char *convertGlobalToLocalBackRef(
6346 + StringPattern *strPat,
6347 + char *convertPtr)
6349 + char *oldText = strPat->spText;
6350 + char *newText;
6351 + int oldLen = strlen(oldText);
6352 + int convertPos = convertPtr - oldText;
6354 + /*
6355 + * replace "(*n" - located at convertPtr - by "("
6356 + */
6357 + newText = XtMalloc(oldLen - 1);
6359 + memcpy(newText, oldText, convertPos+1);
6360 + memcpy(newText+convertPos+1, convertPtr+3, oldLen-convertPos-3);
6362 + *(newText + oldLen - 2) = '\0';
6364 + XtFree(oldText);
6366 + strPat->spText = newText;
6367 + strPat->spLength = strlen(newText);
6369 + return newText + convertPos;
6373 +** Read a match pattern table element from given input string.
6374 +** Return NULL, if read fails.
6376 +static MatchPatternTableElement *readMatchPatternTableElement(
6377 + char **inPtr,
6378 + char **errMsg,
6379 + char *name,
6380 + MatchPatternType type)
6382 + int error = False;
6383 + PatternElement *pattern;
6384 + PatternElement *allPat[MAX_STRING_PATTERNS];
6385 + int nbrOfPat = 0;
6386 + int sizeOfPat;
6387 + MatchPatternTableElement *result;
6388 + int isMonoPattern;
6389 + int skipBtwStartEnd;
6390 + int flash;
6391 + int ignoreHighLightInfo;
6392 + int i;
6394 + if (!getMPSGlobalAttribute(
6395 + inPtr,
6396 + errMsg,
6397 + &isMonoPattern,
6398 + &skipBtwStartEnd,
6399 + &flash,
6400 + &ignoreHighLightInfo ))
6402 + return NULL;
6405 + /*
6406 + * read all patterns
6407 + */
6408 + while (**inPtr != '\n' && !error)
6410 + if (!readPatternElement( inPtr, errMsg, &pattern ))
6412 + error = True;
6414 + else if (nbrOfPat >= MAX_STRING_PATTERNS)
6416 + *errMsg = "max. number of string patterns exceeded";
6417 + error = True;
6419 + else
6421 + pattern->peIndex = nbrOfPat;
6423 + allPat[nbrOfPat ++] = pattern;
6427 + if (error)
6429 + for (i=0; i < nbrOfPat; i ++)
6430 + freePatternElement( allPat[i] );
6432 + return NULL;
6435 + if (nbrOfPat == 0)
6437 + *errMsg = "min. one string pattern needed";
6438 + return NULL;
6441 + /*
6442 + * allocate & init. MatchPatternTableElement
6443 + */
6444 + result =
6445 + (MatchPatternTableElement *)XtMalloc(sizeof(MatchPatternTableElement));
6447 + result->mpteName = name;
6448 + result->mpteIndex = NO_ELEMENT_IDX;
6449 + result->mpteType = type;
6450 + result->mpteGroup = NO_GROUP_IDX;
6452 + sizeOfPat = sizeof(PatternElement *) * nbrOfPat;
6453 + result->mpteAll.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6455 + memcpy(result->mpteAll.pesPattern, allPat, sizeOfPat);
6457 + result->mpteAll.pesNumberOfPattern = nbrOfPat;
6459 + result->mpteIsMonoPattern = isMonoPattern;
6460 + result->mpteSkipBtwnStartEnd = skipBtwStartEnd;
6461 + result->mpteFlash = flash;
6462 + result->mpteIgnoreHighLightInfo = ignoreHighLightInfo;
6464 + result->mpteStartEndRE = NULL;
6466 + initGlobalBackRefList( result->mpteGlobalBackRef );
6468 + /*
6469 + * sort start / end / middle pattern
6470 + */
6471 + error = !sortReadPatternElementSet( &result->mpteAll, errMsg, result );
6473 + if (error)
6475 + freeMatchPatternTableElement( result );
6476 + return NULL;
6478 + else
6480 + return result;
6485 + * Sort read pattern element set into start, middle & end arrays.
6486 + * Validate "monopattern" attribute.
6487 + * Returns true, if validation was successful.
6488 + */
6489 +static int sortReadPatternElementSet(
6490 + PatternElementSet *allPat,
6491 + char **errMsg,
6492 + MatchPatternTableElement *result)
6494 + int sizeOfPat;
6495 + int isMonoPattern = result->mpteIsMonoPattern;
6497 + /*
6498 + * count number of start, middle & end pattern elements.
6499 + */
6500 + countPatternElementKind( allPat, result );
6502 + /*
6503 + * validate and allocate pattern elements.
6504 + */
6505 + if (result->mpteStart.pesNumberOfPattern != 0)
6507 + sizeOfPat = sizeof(PatternElement *) * result->mpteStart.pesNumberOfPattern;
6508 + result->mpteStart.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6510 + else
6512 + *errMsg = "min. one start pattern needed";
6513 + return False;
6516 + if (isMonoPattern &&
6517 + (result->mpteMiddle.pesNumberOfPattern != 0 ||
6518 + result->mpteEnd.pesNumberOfPattern !=0))
6520 + *errMsg = "mono pattern: only start pattern(s) allowed due to attribute [m]";
6521 + return False;
6524 + if (result->mpteMiddle.pesNumberOfPattern != 0)
6526 + sizeOfPat = sizeof(PatternElement *) * result->mpteMiddle.pesNumberOfPattern;
6527 + result->mpteMiddle.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6530 + if (result->mpteEnd.pesNumberOfPattern != 0)
6532 + sizeOfPat = sizeof(PatternElement *) * result->mpteEnd.pesNumberOfPattern;
6533 + result->mpteEnd.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6535 + else
6537 + if (!isMonoPattern)
6539 + *errMsg = "min. one end pattern needed";
6540 + return False;
6544 + /*
6545 + * sort pattern elements into start, middle & end arrays.
6546 + */
6547 + sortPatternElementSet( allPat, result );
6549 + if (isMonoPattern)
6551 + copyPatternSet( &result->mpteStart, &result->mpteEnd );
6554 + return True;
6558 + * Count number of start, middle & end patterns stored in "allPat".
6559 + */
6560 +static void countPatternElementKind(
6561 + PatternElementSet *allPat,
6562 + MatchPatternTableElement *result)
6564 + int i;
6566 + result->mpteStart.pesNumberOfPattern = 0;
6567 + result->mpteEnd.pesNumberOfPattern = 0;
6568 + result->mpteMiddle.pesNumberOfPattern = 0;
6570 + result->mpteStart.pesPattern = NULL;
6571 + result->mpteEnd.pesPattern = NULL;
6572 + result->mpteMiddle.pesPattern = NULL;
6574 + for (i=0; i < allPat->pesNumberOfPattern; i ++)
6576 + switch (allPat->pesPattern[i]->peKind)
6578 + case PEK_START:
6579 + result->mpteStart.pesNumberOfPattern ++;
6580 + break;
6581 + case PEK_MIDDLE:
6582 + result->mpteMiddle.pesNumberOfPattern ++;
6583 + break;
6584 + case PEK_END:
6585 + result->mpteEnd.pesNumberOfPattern ++;
6586 + break;
6587 + default:;
6593 + * Sort start, middle & end pattern elements into related arrays.
6594 + */
6595 +static void sortPatternElementSet(
6596 + PatternElementSet *allPat,
6597 + MatchPatternTableElement *result)
6599 + int i;
6600 + int s,m,e;
6602 + for (i=0, s=0, m=0, e=0; i < allPat->pesNumberOfPattern; i ++)
6604 + switch (allPat->pesPattern[i]->peKind)
6606 + case PEK_START:
6607 + result->mpteStart.pesPattern[s ++] = allPat->pesPattern[i];
6608 + break;
6609 + case PEK_MIDDLE:
6610 + result->mpteMiddle.pesPattern[m ++] = allPat->pesPattern[i];
6611 + break;
6612 + case PEK_END:
6613 + result->mpteEnd.pesPattern[e ++] = allPat->pesPattern[i];
6614 + break;
6615 + default:;
6620 +static void copyPatternSet(
6621 + PatternElementSet *sourcePS,
6622 + PatternElementSet *destPS)
6624 + int sizeOfPat;
6626 + destPS->pesNumberOfPattern = sourcePS->pesNumberOfPattern;
6628 + sizeOfPat = sizeof(PatternElement *) * destPS->pesNumberOfPattern;
6629 + destPS->pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6631 + memcpy(destPS->pesPattern, sourcePS->pesPattern, sizeOfPat);
6635 +** Free the allocated memory contained in a ReadMatchPatternInfo data structure
6637 +static void freeReadMatchPatternInfo( ReadMatchPatternInfo *readPatInfo )
6639 + int i;
6641 + for (i=0; i<readPatInfo->rmpiNbrOfElements; i++)
6642 + freeMatchPatternTableElement(readPatInfo->rmpiElement[i]);
6644 + for (i=0; i<readPatInfo->rmpiNbrOfGroups; i++)
6645 + freeMatchPatternGroupElement(readPatInfo->rmpiGroup[i]);
6647 + for (i=0; i<readPatInfo->rmpiNbrOfSeqElements; i++)
6648 + freeMatchPatternSequenceElement(readPatInfo->rmpiSequence[i]);
6650 + freePtr((void **)&readPatInfo->rmpiAllPatRE);
6652 + freePtr((void **)&readPatInfo->rmpiFlashPatRE);
6656 +** Free the allocated memory contained in a StringMatchTable data structure
6658 +static void freeStringMatchTable( StringMatchTable *table )
6660 + MatchPatternTable *patTable;
6661 + int i;
6663 + if (table == NULL)
6664 + return;
6666 + XtFree(table->smtLanguageMode);
6668 + /*
6669 + * Free all matching patterns
6670 + */
6671 + patTable = table->smtAllPatterns;
6673 + for (i=0; i<patTable->mptNumberOfElements; i++)
6674 + freeMatchPatternTableElement(patTable->mptElements[i]);
6676 + XtFree((char *)patTable);
6678 + /*
6679 + * Free matching pattern group elements
6680 + */
6681 + for (i=0; i<table->smtNumberOfGroups; i++)
6682 + freeMatchPatternGroupElement(table->smtGroups[i]);
6684 + /*
6685 + * Free matching pattern sequence elements
6686 + */
6687 + for (i=0; i<table->smtNumberOfSeqElements; i++)
6688 + freeMatchPatternSequenceElement(table->smtSequence[i]);
6690 + /*
6691 + * Free keyword reg. expressions
6692 + */
6693 + freePtr((void **)&table->smtAllPatRE);
6695 + freePtr((void **)&table->smtFlashPatRE);
6697 + XtFree((char *)table);
6701 +** Free the allocated memory contained in a MatchPatternTableElement data structure
6703 +static void freeMatchPatternTableElement( MatchPatternTableElement *element )
6705 + int i;
6707 + XtFree(element->mpteName);
6709 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
6711 + freePatternElement(element->mpteAll.pesPattern[i]);
6714 + freePtr((void **)&element->mpteStartEndRE);
6716 + freeXtPtr((void **)&element->mpteStart.pesPattern);
6718 + freeXtPtr((void **)&element->mpteMiddle.pesPattern);
6720 + freeXtPtr((void **)&element->mpteEnd.pesPattern);
6722 + XtFree((char *)element);
6726 +** Free the allocated memory contained in a PatternElement data structure
6728 +static void freePatternElement( PatternElement *element )
6730 + if (element->peType == PET_SINGLE)
6731 + freeStringPattern( &(element->peVal.peuSingle) );
6732 + else if (element->peType == PET_MULTIPLE)
6734 + freeStringPattern( &(element->peVal.peuMulti.mpStringPattern) );
6735 + XtFree( (char *)element->peVal.peuMulti.mpRefList );
6738 + XtFree( (char *)element );
6742 +** Free the allocated memory contained in a StringPattern data structure
6744 +static void freeStringPattern( StringPattern *strPat )
6746 + int i;
6748 + freeXtPtr((void **)&strPat->spText);
6749 + freeXtPtr((void **)&strPat->spOrigText);
6751 + freePtr((void **)&strPat->spTextRE);
6753 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
6754 + freeXtPtr((void **)&strPat->spOwnGlobalBackRef[i].spbreRegExpText);
6758 +** Free the allocated memory contained in a MatchPatternGroupElement data structure
6760 +static void freeMatchPatternGroupElement( MatchPatternGroupElement *group )
6762 + int i;
6764 + freeXtPtr((void **)&group->mpgeName);
6766 + freePtr((void **)&group->mpgeKeywordRE);
6768 + if (group->mpgeSubPatternIds != NULL)
6770 + for (i=0; i < group->mpgeNumberOfSubPatterns; i++)
6772 + XtFree(group->mpgeSubPatternIds[i]);
6774 + XtFree((char *)group->mpgeSubPatternIds);
6777 + XtFree((char *)group);
6781 +** Free the allocated memory contained in a MatchPatternSequenceElement data structure
6783 +static void freeMatchPatternSequenceElement( MatchPatternSequenceElement *sequence )
6785 + XtFree( sequence->mpseName );
6787 + XtFree( (char *)sequence );
6792 +** Format a matching pattern set parse error.
6794 +static void parseMatchingPatternSetError(
6795 + const char *stringStart,
6796 + const char *stoppedAt,
6797 + ErrorInfo *errInfo)
6799 + char *message = "";
6800 + int msgLen;
6801 + char *errorInForm = "matching pattern of \"%s\"";
6802 + char *errorIn;
6804 + if (errInfo->eiLanguageMode == NULL)
6806 + errorIn = "matching pattern";
6808 + else
6810 + errorIn = XtMalloc(strlen(errorInForm) + strlen(errInfo->eiLanguageMode)+1);
6811 + sprintf(errorIn, "matching pattern of \"%s\"", errInfo->eiLanguageMode);
6814 + if (errInfo->eiRegExpCompileMsg != NULL)
6816 + /*
6817 + * Error message of form:
6818 + * "MP \"eiMPTabElementName\", SP \"eiStringPatText\": eiRegExpCompileMsg" or
6819 + * "MP \"eiMPTabElementName\" - eiDetail: eiRegExpCompileMsg"
6820 + */
6822 + msgLen = strlen(errInfo->eiRegExpCompileMsg) + 1;
6824 + if (errInfo->eiMPTabElementName != NULL)
6825 + msgLen += strlen(errInfo->eiMPTabElementName) + 10;
6827 + if (errInfo->eiDetail != NULL)
6829 + msgLen += strlen(errInfo->eiDetail + 2);
6831 + else
6833 + if (errInfo->eiStringPatText != NULL)
6834 + msgLen += strlen(errInfo->eiStringPatText) + 9;
6837 + message = XtMalloc(msgLen);
6839 + strcpy(message, "");
6841 + if (errInfo->eiMPTabElementName != NULL)
6842 + sprintf( message, "MP \"%s\"", errInfo->eiMPTabElementName);
6844 + if (errInfo->eiDetail == NULL)
6846 + if (errInfo->eiStringPatText != NULL)
6847 + sprintf( message, "%s, SP \"%s\"", message, errInfo->eiStringPatText);
6849 + else
6851 + if (strlen(message) != 0)
6852 + strcat(message, " - ");
6854 + strcat(message, errInfo->eiDetail);
6857 + if (strlen(message) != 0)
6858 + strcat(message, ": ");
6860 + strcat(message, errInfo->eiRegExpCompileMsg);
6862 + else if (errInfo->eiDetail != NULL)
6864 + /*
6865 + * Error message of form:
6866 + * "MP \"eiMPTabElementName\", SP \"eiStringPatText\": Backref %d eiDetail
6867 + */
6868 + msgLen = strlen(errInfo->eiDetail) + 1;
6870 + if (errInfo->eiMPTabElementName != NULL)
6871 + msgLen += strlen(errInfo->eiMPTabElementName) + 7;
6872 + if (errInfo->eiStringPatText != NULL)
6873 + msgLen += strlen(errInfo->eiStringPatText) + 9;
6874 + if (errInfo->eiBackRefNbr != 0)
6875 + msgLen += 15;
6877 + message = XtMalloc(msgLen);
6879 + strcpy(message, "");
6881 + if (errInfo->eiMPTabElementName != NULL)
6882 + sprintf( message, "MP \"%s\"", errInfo->eiMPTabElementName);
6883 + if (errInfo->eiStringPatText != NULL)
6884 + sprintf( message, "%s, SP \"%s\"", message, errInfo->eiStringPatText);
6886 + if (strlen(message) != 0)
6887 + strcat(message, ": ");
6889 + if (errInfo->eiBackRefNbr != 0)
6890 + sprintf( message, "%s Backref %d ", message, errInfo->eiBackRefNbr);
6892 + strcat(message, errInfo->eiDetail);
6895 + ParseError(NULL, stringStart, stoppedAt, errorIn, message);
6897 + if (errInfo->eiRegExpCompileMsg != NULL || errInfo->eiDetail != NULL)
6899 + XtFree(message);
6902 + if (errInfo->eiLanguageMode != NULL)
6904 + XtFree(errorIn);
6907 + freeErrorInfo(errInfo);
6908 + initErrorInfo(errInfo);
6912 + * Pop-up a warning dialog showing a matching pattern set error.
6913 + */
6914 +static void dialogMatchingPatternSetError(
6915 + char *title,
6916 + ErrorInfo *errInfo)
6918 + char *message;
6919 + int msgLen = 1;
6921 + /*
6922 + * Error message of form:
6923 + * "Name : \"eiMPTabElementName\"\n
6924 + * "String: \"eiStringPatText\"\n
6925 + * eiDetail\n
6926 + * eiRegExpCompileMsg\n"
6927 + */
6929 + if (errInfo->eiMPTabElementName != NULL)
6930 + msgLen += strlen(errInfo->eiMPTabElementName) + 15;
6931 + if (errInfo->eiStringPatText != NULL)
6932 + msgLen += strlen(errInfo->eiStringPatText) + 15;
6933 + if (errInfo->eiDetail != NULL)
6934 + msgLen += strlen(errInfo->eiDetail) + 15;
6935 + if (errInfo->eiBackRefNbr != 0)
6936 + msgLen += 15;
6937 + if (errInfo->eiRegExpCompileMsg != NULL)
6938 + msgLen += strlen(errInfo->eiRegExpCompileMsg) + 15;
6940 + message = XtMalloc(msgLen);
6942 + strcpy(message, "");
6944 + if (errInfo->eiMPTabElementName != NULL)
6945 + sprintf( message, "%sName : \"%s\"\n", message, errInfo->eiMPTabElementName);
6946 + if (errInfo->eiStringPatText != NULL)
6947 + sprintf( message, "%sPattern: \"%s\"\n", message, errInfo->eiStringPatText);
6948 + if (errInfo->eiBackRefNbr != 0)
6949 + sprintf( message, "%sBackref %d ", message, errInfo->eiBackRefNbr);
6950 + if (errInfo->eiDetail != NULL)
6951 + sprintf( message, "%s%s\n", message, errInfo->eiDetail);
6952 + if (errInfo->eiRegExpCompileMsg != NULL)
6953 + sprintf( message, "%s%s\n", message, errInfo->eiRegExpCompileMsg);
6955 + DialogF(
6956 + DF_WARN, MatchPatternDialog.mpdShell, 1,
6957 + title,
6958 + "%s(language mode '%s')",
6959 + "OK",
6960 + message,
6961 + errInfo->eiLanguageMode);
6963 + XtFree(message);
6965 + freeErrorInfo(errInfo);
6966 + initErrorInfo(errInfo);
6970 +** Get matching pattern set name.
6971 +** Syntax:
6972 +** patternName ::= "name:"
6973 +** Returns true, if get was successful.
6975 +static int getMPSName(
6976 + char **inPtr,
6977 + ErrorInfo *errInfo,
6978 + char **name )
6980 + char *dummy;
6981 + char *field = ReadSymbolicField(inPtr);
6983 + if (field == NULL)
6985 + errInfo->eiDetail = "matching pattern name missing";
6986 + return False;
6989 + if (!SkipDelimiter(inPtr, &dummy))
6991 + errInfo->eiMPTabElementName = XtNewString(field);
6992 + errInfo->eiDetail = "':' missing after matching pattern name";
6993 + XtFree( field );
6994 + return False;
6997 + *name = field;
6999 + return True;
7003 +** Get matching pattern set type attribute.
7004 +** TypeAttribute ::=
7005 +** [s|g]:
7007 +** s : sub-pattern (pattern is only matched, if part of a pattern group).
7008 +** g : pattern (context) group (i.e. a sequence of sub-patterns).
7009 +** default: individual pattern (pattern is not part of a group and is
7010 +** matched individually.
7011 +** Returns true, if get was successful.
7013 +static int getMPSTypeAttribute(
7014 + char **inPtr,
7015 + ErrorInfo *errInfo,
7016 + MatchPatternType *type)
7018 + char *field = ReadSymbolicField(inPtr);
7019 + int successful = True;
7021 + *type = MPT_INDIVIDUAL;
7023 + if (field != NULL)
7025 + switch (*field)
7027 + case 'g':
7028 + *type = MPT_GROUP;
7029 + break;
7030 + case 's':
7031 + *type = MPT_SUB;
7032 + break;
7033 + default:
7034 + errInfo->eiDetail = "unknown matching pattern type attribute";
7035 + successful = False;
7039 + if (successful)
7041 + if (!SkipDelimiter(inPtr, &errInfo->eiDetail))
7043 + successful = False;
7047 + freeXtPtr((void **)&field);
7049 + return successful;
7053 +** Syntax:
7055 +** GlobalAttribute ::=
7056 +** [c][f][m][p][u]:
7058 +** c : the content between start and end pattern is skipped
7059 +** during parsing (e.g. pattern encloses a comment).
7060 +** f : flash matching pattern (if not set, then only jump
7061 +** to matching pattern is supported).
7062 +** m : mono pattern - set exist out of only one single pattern
7063 +** (start pattern = end pattern; e.g. quotes like ")
7064 +** p : ignore highlight info code of single patterns of this set
7065 +** ("plain").
7067 +** Returns TRUE, if global attribute was successful read.
7069 +static int getMPSGlobalAttribute(
7070 + char **inPtr,
7071 + char **errMsg,
7072 + int *isMonoPattern,
7073 + int *comment,
7074 + int *flash,
7075 + int *ignoreHighLightInfo)
7077 + char *field = ReadSymbolicField(inPtr);
7078 + char *attribute;
7079 + int successful = True;
7081 + *isMonoPattern = False;
7082 + *comment = False;
7083 + *flash = False;
7084 + *ignoreHighLightInfo = False;
7086 + if (field != NULL)
7088 + attribute = field;
7089 + while (*attribute != '\0' && successful)
7091 + switch (*attribute)
7093 + case 'c':
7094 + *comment = True;
7095 + break;
7096 + case 'f':
7097 + *flash = True;
7098 + break;
7099 + case 'm':
7100 + *isMonoPattern = True;
7101 + break;
7102 + case 'p':
7103 + *ignoreHighLightInfo = True;
7104 + break;
7105 + default:
7106 + *errMsg = "unknown global attribute";
7107 + successful = False;
7109 + attribute ++;
7113 + if (successful)
7115 + if (!SkipDelimiter(inPtr, errMsg))
7117 + successful = False;
7121 + freeXtPtr((void **)&field);
7123 + return successful;
7127 +** Get matching pattern set attribute.
7129 +** Syntax:
7131 +** patternAttribute ::=
7132 +** [s|m|e][w|l|r][i]:
7134 +** StringPatternKind:
7135 +** s : start string pattern.
7136 +** m : middle string pattern.
7137 +** e : end string pattern.
7138 +** WordBoundaryAttribute:
7139 +** w : pattern is word (i.e. before and after pattern
7140 +** there must be a delimiter).
7141 +** l : before pattern must be a delimiter (left side).
7142 +** r : after pattern must be a delimiter (right side).
7143 +** default: neither before nor after pattern must be a delimiter.
7144 +** StringAttribute:
7145 +** i : pattern is case insensitive (if not set: pattern is
7146 +** case sensitive).
7147 +** x : pattern is regular expression (if not set: pattern is
7148 +** literal string).
7150 +** Returns TRUE, if pattern attribute was successful read.
7152 +static int getMPSPatternAttribute(
7153 + char **inPtr,
7154 + char **errMsg,
7155 + PatternElementKind *patternKind,
7156 + PatternWordBoundary *wordBoundary,
7157 + int *caseInsensitive,
7158 + int *regularExpression)
7160 + char *field = ReadSymbolicField(inPtr);
7161 + char *attribute;
7162 + int successful = True;
7164 + *patternKind = PEK_UNKNOWN;
7165 + *wordBoundary = PWB_NONE;
7166 + *caseInsensitive = False;
7167 + *regularExpression = False;
7169 + if (field != NULL)
7171 + attribute = field;
7172 + while (*attribute != '\0' && successful)
7174 + switch (*attribute)
7176 + case 'e':
7177 + *patternKind = PEK_END;
7178 + break;
7179 + case 'i':
7180 + *caseInsensitive = True;
7181 + break;
7182 + case 'l':
7183 + *wordBoundary = PWB_LEFT;
7184 + break;
7185 + case 'm':
7186 + *patternKind = PEK_MIDDLE;
7187 + break;
7188 + case 'r':
7189 + *wordBoundary = PWB_RIGHT;
7190 + break;
7191 + case 's':
7192 + *patternKind = PEK_START;
7193 + break;
7194 + case 'w':
7195 + *wordBoundary = PWB_BOTH;
7196 + break;
7197 + case 'x':
7198 + *regularExpression = True;
7199 + break;
7200 + default:
7201 + *errMsg = "unknown string pattern attribute";
7202 + successful = False;
7204 + attribute ++;
7208 + if (successful)
7210 + if (!SkipDelimiter(inPtr, errMsg))
7212 + successful = False;
7216 + freeXtPtr((void **)&field);
7218 + return successful;
7222 +** Returns the (to be reserved) reg. ex. length of an pattern element.
7223 +** Update total number of multi patterns, too.
7225 +static int patternElementLen(
7226 + ReadMatchPatternInfo *info,
7227 + PatternElement *patElement,
7228 + int *nbrOfMultiPatterns)
7230 + PatternElement *referredElement;
7231 + StringPattern *strPat = NULL;
7232 + int patElementLen;
7234 + switch (patElement->peType)
7236 + case PET_SINGLE:
7237 + strPat = &patElement->peVal.peuSingle;
7238 + break;
7240 + case PET_MULTIPLE:
7241 + strPat = &patElement->peVal.peuMulti.mpStringPattern;
7243 + (*nbrOfMultiPatterns) ++;
7245 + break;
7247 + case PET_REFERENCE:
7248 + referredElement =
7249 + info->rmpiElement[patElement->peVal.peuRef.prElementIdx]->
7250 + mpteAll.pesPattern[patElement->peVal.peuRef.prPatternIdx];
7252 + strPat = &referredElement->peVal.peuMulti.mpStringPattern;
7253 + break;
7256 + /*
7257 + * reserve additional 4 characters ("(?i)") for case insensitive search
7258 + */
7259 + if (strPat->spCaseInsensitive)
7260 + patElementLen = strPat->spLength + 4;
7261 + else
7262 + patElementLen = strPat->spLength;
7264 + /*
7265 + * reserve additional 4 characters ("(?:)") for regular expression
7266 + */
7267 + if (strPat->spRegularExpression)
7268 + patElementLen += 4;
7270 + return patElementLen;
7274 +** Returns the (to be reserved) total reg. ex. length of given
7275 +** MatchPatternTableElement. Update total number of multi patterns, too.
7277 +static int totalMatchPatternTableElementLen(
7278 + ReadMatchPatternInfo *info,
7279 + MatchPatternTableElement *element,
7280 + int *nbrOfMultiPatterns)
7282 + int i;
7283 + int totalLen = 0;
7285 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i ++)
7287 + totalLen +=
7288 + patternElementLen(
7289 + info,
7290 + element->mpteAll.pesPattern[i],
7291 + nbrOfMultiPatterns );
7294 + return totalLen;
7298 +** Returns the (to be reserved) total reg. ex. length of given
7299 +** read match pattern info. Counts total number of multi patterns, too.
7301 +static int totalKeywordOfTableLen(
7302 + ReadMatchPatternInfo *info,
7303 + int *nbrOfMultiPatterns)
7305 + int i;
7306 + int totalLen = 0;
7308 + *nbrOfMultiPatterns = 0;
7310 + for (i=0; i<info->rmpiNbrOfElements; i ++)
7312 + totalLen +=
7313 + totalMatchPatternTableElementLen(
7314 + info,
7315 + info->rmpiElement[i],
7316 + nbrOfMultiPatterns);
7319 + return totalLen;
7323 +** Add given StringPattern to given reg. ex. strings
7325 +static void addPatternToRegExpString(
7326 + StringPattern *pattern,
7327 + RegExpStringInfo *regExpStringInfo)
7329 + char *r = NULL, *s;
7330 + char *adaptedRegExpText = NULL;
7331 + int prevLen = 0;
7333 + /*
7334 + * Select the buffer, where the pattern needs to be added
7335 + * to (depending on its word boundary). Prepare the buffer
7336 + * by evtl. adding a prefix, if related buffer is empty.
7337 + */
7338 + switch (pattern->spWordBoundary)
7340 + case PWB_NONE:
7341 + prevLen = strlen( regExpStringInfo->resiNoneWBRegExpString );
7343 + r = regExpStringInfo->resiNoneWBRegExpString + strlen( regExpStringInfo->resiNoneWBRegExpString );
7344 + break;
7345 + case PWB_LEFT:
7346 + prevLen = strlen( regExpStringInfo->resiLeftWBRegExpString );
7347 + if (prevLen == 0)
7349 + strcpy( regExpStringInfo->resiLeftWBRegExpString, "<(?:" );
7351 + r = regExpStringInfo->resiLeftWBRegExpString + strlen( regExpStringInfo->resiLeftWBRegExpString );
7352 + break;
7353 + case PWB_RIGHT:
7354 + prevLen = strlen( regExpStringInfo->resiRightWBRegExpString );
7355 + if (prevLen == 0)
7357 + strcpy( regExpStringInfo->resiRightWBRegExpString, "(?:" );
7359 + r = regExpStringInfo->resiRightWBRegExpString + strlen( regExpStringInfo->resiRightWBRegExpString );
7360 + break;
7361 + case PWB_BOTH:
7362 + prevLen = strlen( regExpStringInfo->resiBothWBRegExpString );
7363 + if (prevLen == 0)
7365 + strcpy( regExpStringInfo->resiBothWBRegExpString, "<(?:" );
7367 + r = regExpStringInfo->resiBothWBRegExpString + strlen( regExpStringInfo->resiBothWBRegExpString );
7368 + break;
7371 + /*
7372 + * add an "or" if there is already a pattern in the buffer
7373 + */
7374 + if (prevLen != 0)
7376 + *r++ = '|';
7379 + /*
7380 + * add "(?i" to order case insensitive search
7381 + */
7382 + if (pattern->spCaseInsensitive)
7384 + *r++ = '(';
7385 + *r++ = '?';
7386 + *r++ = 'i';
7389 + /*
7390 + * add "(?:" to group this regular expression
7391 + */
7392 + if (pattern->spRegularExpression)
7394 + *r++ = '(';
7395 + *r++ = '?';
7396 + *r++ = ':';
7398 + adaptedRegExpText =
7399 + adaptLocalBackRefs(
7400 + pattern->spText,
7401 + &regExpStringInfo->resiLocalBackRefID);
7403 + s = adaptedRegExpText;
7405 + else
7407 + s = pattern->spText;
7410 + /*
7411 + * add the pattern characters - evtl. escaped, if special
7412 + * regular expression symbols & pattern is no reg. exp. -
7413 + * to the buffer:
7414 + */
7416 + while (*s != '\0')
7418 + if (!pattern->spRegularExpression)
7420 + switch (*s)
7422 + case '(':
7423 + case ')':
7424 + case '-':
7425 + case '[':
7426 + case ']':
7427 + case '<':
7428 + case '>':
7429 + case '{':
7430 + case '}':
7431 + case '.':
7432 + case '\\':
7433 + case '|':
7434 + case '^':
7435 + case '$':
7436 + case '*':
7437 + case '+':
7438 + case '?':
7439 + case '&':
7440 + *r++ = '\\';
7441 + break;
7442 + };
7445 + *r++ = *s++;
7448 + /*
7449 + * close "reg. exp. group" bracket
7450 + */
7451 + if (pattern->spRegularExpression)
7453 + *r++ = ')';
7455 + XtFree(adaptedRegExpText);
7458 + /*
7459 + * close case insensitive search bracket
7460 + */
7461 + if (pattern->spCaseInsensitive)
7463 + *r++ = ')';
7466 + /*
7467 + * terminate added string
7468 + */
7469 + *r = '\0';
7473 +** Adapt local backrefs inside given regExpText by common local IDs.
7474 +** Returns new allocated reg. exp. string holding common local backrefs.
7476 +static char *adaptLocalBackRefs(
7477 + char *regExpText,
7478 + int *commonLocalId)
7480 + int id;
7481 + int ownLocalId = 0;
7482 + char *s = regExpText;
7483 + char *newRegExpText = XtMalloc(strlen(regExpText)*3);
7484 + char *n = newRegExpText;
7485 + int localBackRefList[MAX_LOCAL_BACK_REF_ID];
7487 + /*
7488 + * put all local backrefs into "localBackRefList".
7489 + */
7490 + scanForLocalBackRefs(regExpText, localBackRefList);
7492 + while (*s != '\0')
7494 + *n++ = *s;
7496 + if (*s == '\\')
7498 + s++;
7500 + if (isdigit((unsigned char)*s))
7502 + /*
7503 + * \n (n=1..9) found: replace local backref.
7504 + * by "common local ID"
7505 + */
7506 + id =
7507 + (int)((unsigned char)*s - (unsigned char)'0') - 1;
7509 + if (localBackRefList[id] != NO_LOCAL_BACK_REF_ID &&
7510 + localBackRefList[id] != LOCAL_BACK_REF_ID_USED)
7512 + *n++ = (char)((int)('0') + localBackRefList[id]);
7514 + else
7516 + *n++ = '0';
7519 + s ++;
7521 + else if (*s != '\0')
7523 + /*
7524 + * copy escaped character
7525 + */
7526 + *n++ = *s++;
7529 + else if (*s == '(')
7531 + s ++;
7533 + if (*s == '?')
7535 + /*
7536 + * non capturing parentheses found -> just copy it
7537 + */
7538 + *n++ = *s++;
7540 + else
7542 + /*
7543 + * capturing parentheses found:
7544 + */
7545 + if (localBackRefList[ownLocalId] == LOCAL_BACK_REF_ID_USED)
7547 + /*
7548 + * backref used within given reg. exp. text:
7549 + * remember common local id for replacement later on
7550 + */
7551 + localBackRefList[ownLocalId] = *commonLocalId;
7552 + (*commonLocalId) ++;
7553 + ownLocalId ++;
7555 + else
7557 + /*
7558 + * backref not used within given reg. exp. text:
7559 + * replace capturing parentheses by non capturing one
7560 + */
7561 + *n++ = '?';
7562 + *n++ = ':';
7566 + else
7568 + s ++;
7572 + /*
7573 + * terminate adapted string
7574 + */
7575 + *n = '\0';
7577 + return newRegExpText;
7581 +** Get all local backrefs of given regExpText and put them into
7582 +** given localBackRefList.
7584 +static void scanForLocalBackRefs(
7585 + char *regExpText,
7586 + int *localBackRefList)
7588 + int i;
7589 + int localId;
7590 + char *s = regExpText;
7592 + for (i=0; i<MAX_LOCAL_BACK_REF_ID; i++)
7594 + localBackRefList[i] = NO_LOCAL_BACK_REF_ID;
7597 + while (*s != '\0')
7599 + if (*s == '\\')
7601 + if (isdigit((unsigned char)*(s+1)))
7603 + /*
7604 + * \n (n=1..9) found: flag usage in local backref list
7605 + */
7606 + localId =
7607 + (int)((unsigned char)*(s+1) - (unsigned char)'0') - 1;
7609 + localBackRefList[localId] = LOCAL_BACK_REF_ID_USED;
7611 + s ++;
7613 + else if (*(s+1) != '\0')
7614 + s ++;
7616 + s ++;
7621 +** Returns true, if string of given multi pattern reference was
7622 +** not added to regExpStringInfo.
7624 +static int isMultiPatternNotAdded(
7625 + RegExpStringInfo *regExpStringInfo,
7626 + PatternReference *toBeAddedPR)
7628 + int i;
7629 + PatternReference *addedPR;
7630 + PatternReference *newPR;
7632 + for (i=0; i < regExpStringInfo->resiNbrOfAddedMultiPat; i++)
7634 + addedPR = regExpStringInfo->resiAddedMultiPat[i];
7636 + if (addedPR->prElementIdx == toBeAddedPR->prElementIdx &&
7637 + addedPR->prPatternIdx == toBeAddedPR->prPatternIdx)
7639 + return False;
7643 + newPR = (PatternReference *)XtMalloc(sizeof(PatternReference));
7645 + *newPR = *toBeAddedPR;
7647 + regExpStringInfo->resiAddedMultiPat[regExpStringInfo->resiNbrOfAddedMultiPat ++] = newPR;
7649 + return True;
7653 +** add given PatternElement to given reg. exp. strings
7655 +static void addUniquePatternToRegExpString(
7656 + PatternElement *patElement,
7657 + PatternReference *patElementReference,
7658 + ReadMatchPatternInfo *readMatchPatternInfo,
7659 + RegExpStringInfo *regExpStringInfo)
7661 + PatternElement *referredElement;
7662 + PatternReference referredPatReference;
7664 + switch (patElement->peType)
7666 + case PET_SINGLE:
7667 + addPatternToRegExpString(
7668 + &(patElement->peVal.peuSingle),
7669 + regExpStringInfo);
7670 + break;
7672 + case PET_MULTIPLE:
7673 + /*
7674 + * add element to reg. exp. string only, if it was
7675 + * not added before.
7676 + */
7677 + if (isMultiPatternNotAdded(regExpStringInfo, patElementReference))
7679 + addPatternToRegExpString(
7680 + &(patElement->peVal.peuMulti.mpStringPattern),
7681 + regExpStringInfo);
7683 + break;
7685 + case PET_REFERENCE:
7686 + /*
7687 + * add referred element to reg. exp. string only, if related
7688 + * multi pattern was not added before.
7689 + */
7690 + referredPatReference = patElement->peVal.peuRef;
7692 + referredElement =
7693 + readMatchPatternInfo->rmpiElement[referredPatReference.prElementIdx]->
7694 + mpteAll.pesPattern[referredPatReference.prPatternIdx];
7696 + if (isMultiPatternNotAdded(regExpStringInfo, &referredPatReference))
7698 + addPatternToRegExpString(
7699 + &(referredElement->peVal.peuMulti.mpStringPattern),
7700 + regExpStringInfo);
7702 + break;
7707 +** add given MatchPatternTableElement to given reg. ex. strings
7709 +static void addElementToRegExpString(
7710 + MatchPatternTableElement *element,
7711 + ReadMatchPatternInfo *readMatchPatternInfo,
7712 + RegExpStringInfo *regExpStringInfo)
7714 + int i;
7715 + PatternReference elementRef;
7717 + elementRef.prElementIdx = element->mpteIndex;
7719 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i ++)
7721 + elementRef.prPatternIdx = i;
7723 + addUniquePatternToRegExpString(
7724 + element->mpteAll.pesPattern[i],
7725 + &elementRef,
7726 + readMatchPatternInfo,
7727 + regExpStringInfo);
7732 +** Concatenate strings stored by regExpStringInfo.
7733 +** Free given regExpStringInfo afterwards.
7734 +** Returns resulting string.
7736 +static void catSMTRegExpStrings(
7737 + RegExpStringInfo *regExpStringInfo,
7738 + char **regExpString)
7740 + int resultingLen;
7742 + /*
7743 + * allocate & init. a buffer for the resulting regular expression
7744 + */
7745 + resultingLen =
7746 + strlen( regExpStringInfo->resiNoneWBRegExpString ) +
7747 + strlen( regExpStringInfo->resiLeftWBRegExpString ) +
7748 + strlen( regExpStringInfo->resiRightWBRegExpString ) +
7749 + strlen( regExpStringInfo->resiBothWBRegExpString ) + 5;
7751 + *regExpString = XtMalloc( resultingLen );
7753 + strcpy( *regExpString, "" );
7755 + /*
7756 + * add the single parts to the resulting regular expression
7757 + * (= cat of parts separated by an "or")
7758 + */
7759 + addSMTRegExpString( *regExpString, regExpStringInfo->resiNoneWBRegExpString, "" );
7760 + addSMTRegExpString( *regExpString, regExpStringInfo->resiLeftWBRegExpString, ")" );
7761 + addSMTRegExpString( *regExpString, regExpStringInfo->resiRightWBRegExpString, ")>" );
7762 + addSMTRegExpString( *regExpString, regExpStringInfo->resiBothWBRegExpString, ")>" );
7764 + /*
7765 + * free buffers
7766 + */
7767 + freeRegExpStringInfo( regExpStringInfo );
7771 +** Free the allocated memory contained in a RegExpStringInfo data structure
7773 +static void freeRegExpStringInfo(
7774 + RegExpStringInfo *regExpStringInfo)
7776 + int i;
7778 + XtFree( regExpStringInfo->resiNoneWBRegExpString );
7779 + XtFree( regExpStringInfo->resiLeftWBRegExpString );
7780 + XtFree( regExpStringInfo->resiRightWBRegExpString );
7781 + XtFree( regExpStringInfo->resiBothWBRegExpString );
7783 + for (i=0; i < regExpStringInfo->resiNbrOfAddedMultiPat; i ++)
7784 + XtFree( (char *)regExpStringInfo->resiAddedMultiPat[i] );
7786 + XtFree( (char *)regExpStringInfo->resiAddedMultiPat);
7790 +** Compose regular expression for start / end pattern.
7792 +static void composeStartEndRegExpString(
7793 + ReadMatchPatternInfo *readMatchPatternInfo,
7794 + MatchPatternTableElement *element,
7795 + char **regExpString)
7797 + int i;
7798 + RegExpStringInfo regExpStringInfo;
7799 + PatternReference elementRef;
7800 + PatternElementSet startPat = element->mpteStart;
7801 + PatternElementSet endPat = element->mpteEnd;
7803 + /*
7804 + * Allocate buffers for keyword regular expression.
7805 + */
7806 + setupRegExpStringBuffers(
7807 + readMatchPatternInfo,
7808 + &regExpStringInfo);
7810 + /*
7811 + * Treat start / end element of MatchPatternTableElement
7812 + */
7814 + elementRef.prElementIdx = element->mpteIndex;
7816 + for (i=0; i < startPat.pesNumberOfPattern; i ++)
7818 + elementRef.prPatternIdx = startPat.pesPattern[i]->peIndex;
7820 + addUniquePatternToRegExpString(
7821 + startPat.pesPattern[i],
7822 + &elementRef,
7823 + readMatchPatternInfo,
7824 + &regExpStringInfo);
7827 + for (i=0; i < endPat.pesNumberOfPattern; i ++)
7829 + elementRef.prPatternIdx = endPat.pesPattern[i]->peIndex;
7831 + addUniquePatternToRegExpString(
7832 + endPat.pesPattern[i],
7833 + &elementRef,
7834 + readMatchPatternInfo,
7835 + &regExpStringInfo);
7838 + /*
7839 + * Assemble the resulting regular expression
7840 + */
7841 + catSMTRegExpStrings(
7842 + &regExpStringInfo,
7843 + regExpString);
7846 +static void copyStringMatchTableForDialog(
7847 + StringMatchTable *sourceTable,
7848 + DialogMatchPatternInfo *dialogTable )
7850 + int i;
7852 + /*
7853 + * if no source table exist (yet), then set nbr. of elements / groups to 0
7854 + */
7855 + if (sourceTable == NULL)
7857 + dialogTable->dmpiNbrOfSeqElements = 0;
7859 + return;
7862 + /*
7863 + * copy matching pattern sequence
7864 + */
7865 + dialogTable->dmpiNbrOfSeqElements = sourceTable->smtNumberOfSeqElements;
7867 + for (i=0; i < sourceTable->smtNumberOfSeqElements; i ++)
7869 + copySequenceElementForDialog(
7870 + sourceTable,
7871 + sourceTable->smtSequence[i],
7872 + &dialogTable->dmpiSequence[i] );
7876 +static void *copyMatchPatternElementForDialog(
7877 + MatchPatternTable *table,
7878 + int sourceElementIdx)
7880 + int i;
7881 + int patIdx = 0;
7882 + MatchPatternTableElement *sourceElement;
7883 + DialogMatchPatternTableElement *destination;
7885 + sourceElement = table->mptElements[sourceElementIdx];
7887 + destination =
7888 + (DialogMatchPatternTableElement *)XtMalloc( sizeof(DialogMatchPatternTableElement) );
7890 + destination->dmpteName = XtNewString(sourceElement->mpteName);
7891 + destination->dmpteType = sourceElement->mpteType;
7892 + destination->dmpteSkipBtwnStartEnd = sourceElement->mpteSkipBtwnStartEnd;
7893 + destination->dmpteIgnoreHighLightInfo = sourceElement->mpteIgnoreHighLightInfo;
7894 + destination->dmpteFlash = sourceElement->mpteFlash;
7896 + for (i=0; i<sourceElement->mpteAll.pesNumberOfPattern; i++)
7898 + copyPatternForDialog(
7899 + table,
7900 + sourceElement->mpteAll.pesPattern[i],
7901 + &destination->dmptePatterns.dspElements[patIdx ++]);
7904 + destination->dmptePatterns.dspNumberOfPatterns = patIdx;
7906 + return (void *)destination;
7909 +static void copyPatternForDialog(
7910 + MatchPatternTable *table,
7911 + PatternElement *sourcePattern,
7912 + DialogStringPatternElement **dialogPattern )
7914 + DialogStringPatternElement *newPat;
7915 + StringPattern *strSourcePat = GetStringPattern( table, sourcePattern );
7917 + newPat = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
7918 + *dialogPattern = newPat;
7920 + if( strSourcePat->spOrigText != NULL)
7921 + newPat->dspeText = XtNewString(strSourcePat->spOrigText);
7922 + else
7923 + newPat->dspeText = XtNewString(strSourcePat->spText);
7925 + newPat->dspeKind = sourcePattern->peKind;
7926 + newPat->dspeWordBoundary = strSourcePat->spWordBoundary;
7927 + newPat->dspeCaseInsensitive = strSourcePat->spCaseInsensitive;
7928 + newPat->dspeRegularExpression = strSourcePat->spRegularExpression;
7931 +static void *copyGroupElementForDialog(
7932 + MatchPatternGroupElement *sourceGroup)
7934 + int i;
7935 + DialogMatchPatternGroupElement *destination;
7937 + destination =
7938 + (DialogMatchPatternGroupElement *)XtMalloc( sizeof(DialogMatchPatternGroupElement) );
7940 + destination->dmpgeName = XtNewString(sourceGroup->mpgeName);
7941 + destination->dmpgeNumberOfSubPatterns = sourceGroup->mpgeNumberOfSubPatterns;
7943 + for ( i=0; i<destination->dmpgeNumberOfSubPatterns; i ++)
7945 + destination->dmpgeSubPatternIds[i] =
7946 + XtNewString(sourceGroup->mpgeSubPatternIds[i]);
7949 + return destination;
7952 +static void copySequenceElementForDialog(
7953 + StringMatchTable *sourceTable,
7954 + MatchPatternSequenceElement *sourceSeqElement,
7955 + DialogMatchPatternSequenceElement **dialogSeqElement )
7957 + DialogMatchPatternSequenceElement *destSeqElement;
7959 + destSeqElement =
7960 + (DialogMatchPatternSequenceElement *)XtMalloc( sizeof(DialogMatchPatternSequenceElement) );
7962 + *dialogSeqElement = destSeqElement;
7964 + destSeqElement->dmpseName = XtNewString(sourceSeqElement->mpseName);
7965 + destSeqElement->dmpseType = sourceSeqElement->mpseType;
7966 + destSeqElement->dmpseValid = True;
7968 + if (destSeqElement->dmpseType == MPT_GROUP)
7970 + destSeqElement->dmpsePtr =
7971 + copyGroupElementForDialog(
7972 + sourceTable->smtGroups[sourceSeqElement->mpseIndex]);
7974 + else
7976 + destSeqElement->dmpsePtr =
7977 + copyMatchPatternElementForDialog(
7978 + sourceTable->smtAllPatterns,
7979 + sourceSeqElement->mpseIndex);
7983 +static DialogMatchPatternSequenceElement *copyDialogSequenceElement(
7984 + DialogMatchPatternSequenceElement *sourceSeq)
7986 + DialogMatchPatternSequenceElement *destSeq;
7988 + destSeq =
7989 + (DialogMatchPatternSequenceElement *)XtMalloc(sizeof(DialogMatchPatternSequenceElement));
7991 + destSeq->dmpseName = XtNewString(sourceSeq->dmpseName);
7992 + destSeq->dmpseType = sourceSeq->dmpseType;
7993 + destSeq->dmpseValid = True;
7995 + destSeq->dmpsePtr = sourceSeq->dmpsePtr;
7997 + return destSeq;
8000 +static void freeDialogMatchPatternElement(
8001 + DialogMatchPatternTableElement *dialogElement )
8003 + int i;
8005 + for (i=0; i<dialogElement->dmptePatterns.dspNumberOfPatterns; i ++)
8007 + freeDialogStringPatternElement(
8008 + dialogElement->dmptePatterns.dspElements[i]);
8011 + freeXtPtr((void **)&dialogElement->dmpteName);
8013 + freeXtPtr((void **)&dialogElement);
8016 +static void freeDialogStringPatternElement(
8017 + DialogStringPatternElement *element)
8019 + freeXtPtr((void **)&element->dspeText);
8021 + freeXtPtr((void **)&element);
8024 +static void freeDialogGroupElement(
8025 + DialogMatchPatternGroupElement *dialogGroup )
8027 + int i;
8029 + for (i=0; i<dialogGroup->dmpgeNumberOfSubPatterns; i ++)
8031 + freeXtPtr((void **)&dialogGroup->dmpgeSubPatternIds[i]);
8034 + freeXtPtr((void **)&dialogGroup->dmpgeName);
8036 + freeXtPtr((void **)&dialogGroup);
8039 +static void freeDialogSequenceElement(
8040 + DialogMatchPatternSequenceElement *dialogSeq )
8042 + freeXtPtr((void **)&dialogSeq->dmpseName);
8044 + if (dialogSeq->dmpseType == MPT_GROUP)
8046 + freeDialogGroupElement(
8047 + (DialogMatchPatternGroupElement *)dialogSeq->dmpsePtr );
8049 + else
8051 + freeDialogMatchPatternElement(
8052 + (DialogMatchPatternTableElement *)dialogSeq->dmpsePtr );
8055 + freeXtPtr((void **)&dialogSeq);
8058 +static void copyDialogStringPatternsFromTable(
8059 + DialogMatchPatternTableElement *tableElement,
8060 + DialogStringPatterns *destPatterns)
8062 + int i;
8064 + destPatterns->dspNumberOfPatterns =
8065 + tableElement->dmptePatterns.dspNumberOfPatterns;
8067 + for (i=0; i<destPatterns->dspNumberOfPatterns; i++)
8069 + destPatterns->dspElements[i] =
8070 + copyDialogStringPatternElement(
8071 + tableElement->dmptePatterns.dspElements[i] );
8075 +static void copyDialogStringPatterns(
8076 + DialogStringPatterns *sourcePatterns,
8077 + DialogStringPatterns *destPatterns)
8079 + int i;
8081 + destPatterns->dspNumberOfPatterns =
8082 + sourcePatterns->dspNumberOfPatterns;
8084 + for (i=0; i<destPatterns->dspNumberOfPatterns; i++)
8086 + destPatterns->dspElements[i] =
8087 + copyDialogStringPatternElement(
8088 + sourcePatterns->dspElements[i] );
8092 +static void freeDialogStringPatterns(
8093 + DialogStringPatterns *patterns)
8095 + int i;
8097 + for (i=0; i<patterns->dspNumberOfPatterns; i++)
8099 + freeDialogStringPatternElement(patterns->dspElements[i]);
8102 + patterns->dspNumberOfPatterns = 0;
8105 +static DialogStringPatternElement *copyDialogStringPatternElement(
8106 + DialogStringPatternElement *sourceElement)
8108 + DialogStringPatternElement *newPatElement;
8110 + newPatElement = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
8112 + newPatElement->dspeText = XtNewString(sourceElement->dspeText);
8113 + newPatElement->dspeKind = sourceElement->dspeKind;
8114 + newPatElement->dspeWordBoundary = sourceElement->dspeWordBoundary;
8115 + newPatElement->dspeCaseInsensitive = sourceElement->dspeCaseInsensitive;
8116 + newPatElement->dspeRegularExpression = sourceElement->dspeRegularExpression;
8118 + return newPatElement;
8121 +static void copyDialogPatternNamesFromGroup(
8122 + DialogMatchPatternGroupElement *group,
8123 + DialogStringPatterns *destPatterns)
8125 + int i;
8127 + destPatterns->dspNumberOfPatterns =
8128 + group->dmpgeNumberOfSubPatterns;
8130 + for (i=0; i<destPatterns->dspNumberOfPatterns; i++)
8132 + destPatterns->dspElements[i] =
8133 + copyDialogPatternName(
8134 + group->dmpgeSubPatternIds[i] );
8138 +static DialogStringPatternElement *copyDialogPatternName(
8139 + char *sourcePatternId)
8141 + DialogStringPatternElement *newPatElement;
8143 + newPatElement = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
8145 + newPatElement->dspeText = XtNewString(sourcePatternId);
8146 + newPatElement->dspeKind = PEK_START;
8147 + newPatElement->dspeWordBoundary = PWB_NONE;
8148 + newPatElement->dspeCaseInsensitive = False;
8149 + newPatElement->dspeRegularExpression = False;
8151 + return newPatElement;
8154 +static void copyDialogPatternNamesToGroup(
8155 + DialogStringPatterns *sourceNames,
8156 + DialogMatchPatternGroupElement *destGroup)
8158 + int i;
8160 + destGroup->dmpgeNumberOfSubPatterns =
8161 + sourceNames->dspNumberOfPatterns;
8163 + for (i=0; i<destGroup->dmpgeNumberOfSubPatterns; i++)
8165 + destGroup->dmpgeSubPatternIds[i] =
8166 + XtNewString(
8167 + sourceNames->dspElements[i]->dspeText);
8173 +** Present a dialog for editing matching pattern information
8175 +void EditMatchPatterns(WindowInfo *window)
8177 + Widget form, lmOptMenu;
8178 + Widget lmForm;
8179 + Widget okBtn, applyBtn, checkBtn, deleteBtn, closeBtn, helpBtn;
8180 + Widget restoreBtn, lmBtn;
8181 + Widget matchPatternsForm, matchPatternsFrame, matchPatternsLbl;
8182 + Widget matchPatternTypeBox, matchPatternTypeLbl;
8183 + Widget globalAttributesBox;
8184 + Widget stringPatternsFrame, stringPatternsForm;
8185 + Widget stringPatternTypeBox;
8186 + Widget wordBoundaryBox;
8187 + Widget stringAttributesBox;
8188 + StringMatchTable *table;
8189 + XmString s1;
8190 + int n;
8191 + Arg args[20];
8193 + /*
8194 + * if the dialog is already displayed, just pop it to the top and return
8195 + */
8196 + if (MatchPatternDialog.mpdShell != NULL)
8198 + RaiseDialogWindow(MatchPatternDialog.mpdShell);
8199 + return;
8202 + /*
8203 + * decide on an initial language mode
8204 + */
8205 + MatchPatternDialog.mpdLangModeName =
8206 + XtNewString(
8207 + window->languageMode == PLAIN_LANGUAGE_MODE ?
8208 + PLAIN_LM_STRING : LanguageModeName(window->languageMode));
8210 + /*
8211 + * find the associated matching pattern table to edit
8212 + */
8213 + table = (StringMatchTable *)FindStringMatchTable(MatchPatternDialog.mpdLangModeName);
8215 + /*
8216 + * copy the list of patterns to one that the user can freely edit
8217 + */
8218 + copyStringMatchTableForDialog( table, &MatchPatternDialog.mpdTable );
8220 + /*
8221 + * init. status information of dialog
8222 + */
8223 + MatchPatternDialog.currentDmptSeqElement = NULL;
8224 + MatchPatternDialog.currentDmptElement = NULL;
8225 + MatchPatternDialog.currentDmptGroup = NULL;
8227 + MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns = 0;
8228 + MatchPatternDialog.mpdStringPatternIsDisplayed = True;
8230 + /*
8231 + * Create a form widget in an application shell
8232 + */
8233 + n = 0;
8234 + XtSetArg(args[n], XmNdeleteResponse, XmDO_NOTHING); n++;
8235 + XtSetArg(args[n], XmNiconName, "Matching Patterns"); n++;
8236 + XtSetArg(args[n], XmNtitle, "Matching (Parenthesis) Patterns"); n++;
8237 + MatchPatternDialog.mpdShell = CreateShellWithBestVis(APP_NAME, APP_CLASS,
8238 + applicationShellWidgetClass, TheDisplay, args, n);
8239 + AddSmallIcon(MatchPatternDialog.mpdShell);
8240 + form = XtVaCreateManagedWidget("editMatchPatterns", xmFormWidgetClass,
8241 + MatchPatternDialog.mpdShell, XmNautoUnmanage, False,
8242 + XmNresizePolicy, XmRESIZE_NONE, NULL);
8243 + XtAddCallback(form, XmNdestroyCallback, destroyCB, NULL);
8244 + AddMotifCloseCallback(MatchPatternDialog.mpdShell, closeCB, NULL);
8246 + lmForm = XtVaCreateManagedWidget("lmForm", xmFormWidgetClass,
8247 + form,
8248 + XmNleftAttachment, XmATTACH_POSITION,
8249 + XmNleftPosition, 1,
8250 + XmNtopAttachment, XmATTACH_POSITION,
8251 + XmNtopPosition, 1,
8252 + XmNrightAttachment, XmATTACH_POSITION,
8253 + XmNrightPosition, 99, NULL);
8255 + MatchPatternDialog.mpdLmPulldown =
8256 + CreateLanguageModeMenu(lmForm, matchPatternLangModeCB, NULL, True);
8258 + n = 0;
8259 + XtSetArg(args[n], XmNspacing, 0); n++;
8260 + XtSetArg(args[n], XmNmarginWidth, 0); n++;
8261 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
8262 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8263 + XtSetArg(args[n], XmNleftPosition, 50); n++;
8264 + XtSetArg(args[n], XmNsubMenuId, MatchPatternDialog.mpdLmPulldown); n++;
8265 + lmOptMenu = XmCreateOptionMenu(lmForm, "langModeOptMenu", args, n);
8266 + XtManageChild(lmOptMenu);
8267 + MatchPatternDialog.mpdLmOptMenu = lmOptMenu;
8269 + XtVaCreateManagedWidget("lmLbl", xmLabelGadgetClass, lmForm,
8270 + XmNlabelString, s1=XmStringCreateSimple("Language Mode:"),
8271 + XmNmnemonic, 'M',
8272 + XmNuserData, XtParent(MatchPatternDialog.mpdLmOptMenu),
8273 + XmNalignment, XmALIGNMENT_END,
8274 + XmNrightAttachment, XmATTACH_POSITION,
8275 + XmNrightPosition, 50,
8276 + XmNtopAttachment, XmATTACH_FORM,
8277 + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
8278 + XmNbottomWidget, lmOptMenu, NULL);
8279 + XmStringFree(s1);
8281 + lmBtn = XtVaCreateManagedWidget("lmBtn", xmPushButtonWidgetClass, lmForm,
8282 + XmNlabelString, s1=MKSTRING("Add / Modify\nLanguage Mode..."),
8283 + XmNmnemonic, 'A',
8284 + XmNrightAttachment, XmATTACH_FORM,
8285 + XmNtopAttachment, XmATTACH_FORM, NULL);
8286 + XtAddCallback(lmBtn, XmNactivateCallback, pmLanguageModeDialogCB, NULL);
8287 + XmStringFree(s1);
8289 + okBtn = XtVaCreateManagedWidget("ok", xmPushButtonWidgetClass, form,
8290 + XmNlabelString, s1=XmStringCreateSimple("OK"),
8291 + XmNleftAttachment, XmATTACH_POSITION,
8292 + XmNleftPosition, 1,
8293 + XmNrightAttachment, XmATTACH_POSITION,
8294 + XmNrightPosition, 13,
8295 + XmNbottomAttachment, XmATTACH_FORM,
8296 + XmNbottomOffset, BORDER, NULL);
8297 + XtAddCallback(okBtn, XmNactivateCallback, okCB, NULL);
8298 + XmStringFree(s1);
8300 + applyBtn = XtVaCreateManagedWidget("apply", xmPushButtonWidgetClass, form,
8301 + XmNlabelString, s1=XmStringCreateSimple("Apply"),
8302 + XmNmnemonic, 'y',
8303 + XmNleftAttachment, XmATTACH_POSITION,
8304 + XmNleftPosition, 13,
8305 + XmNrightAttachment, XmATTACH_POSITION,
8306 + XmNrightPosition, 26,
8307 + XmNbottomAttachment, XmATTACH_FORM,
8308 + XmNbottomOffset, BORDER, NULL);
8309 + XtAddCallback(applyBtn, XmNactivateCallback, applyCB, NULL);
8310 + XmStringFree(s1);
8312 + checkBtn = XtVaCreateManagedWidget("check", xmPushButtonWidgetClass, form,
8313 + XmNlabelString, s1=XmStringCreateSimple("Check"),
8314 + XmNmnemonic, 'k',
8315 + XmNleftAttachment, XmATTACH_POSITION,
8316 + XmNleftPosition, 26,
8317 + XmNrightAttachment, XmATTACH_POSITION,
8318 + XmNrightPosition, 39,
8319 + XmNbottomAttachment, XmATTACH_FORM,
8320 + XmNbottomOffset, BORDER, NULL);
8321 + XtAddCallback(checkBtn, XmNactivateCallback, checkCB, NULL);
8322 + XmStringFree(s1);
8324 + deleteBtn = XtVaCreateManagedWidget("delete", xmPushButtonWidgetClass, form,
8325 + XmNlabelString, s1=XmStringCreateSimple("Delete"),
8326 + XmNmnemonic, 'D',
8327 + XmNleftAttachment, XmATTACH_POSITION,
8328 + XmNleftPosition, 39,
8329 + XmNrightAttachment, XmATTACH_POSITION,
8330 + XmNrightPosition, 52,
8331 + XmNbottomAttachment, XmATTACH_FORM,
8332 + XmNbottomOffset, BORDER, NULL);
8333 + XtAddCallback(deleteBtn, XmNactivateCallback, deleteCB, NULL);
8334 + XmStringFree(s1);
8336 + restoreBtn = XtVaCreateManagedWidget("restore", xmPushButtonWidgetClass, form,
8337 + XmNlabelString, s1=XmStringCreateSimple("Restore Defaults"),
8338 + XmNmnemonic, 'f',
8339 + XmNleftAttachment, XmATTACH_POSITION,
8340 + XmNleftPosition, 52,
8341 + XmNrightAttachment, XmATTACH_POSITION,
8342 + XmNrightPosition, 73,
8343 + XmNbottomAttachment, XmATTACH_FORM,
8344 + XmNbottomOffset, BORDER, NULL);
8345 + XtAddCallback(restoreBtn, XmNactivateCallback, restoreCB, NULL);
8346 + XmStringFree(s1);
8348 + closeBtn = XtVaCreateManagedWidget("close", xmPushButtonWidgetClass,
8349 + form,
8350 + XmNlabelString, s1=XmStringCreateSimple("Close"),
8351 + XmNleftAttachment, XmATTACH_POSITION,
8352 + XmNleftPosition, 73,
8353 + XmNrightAttachment, XmATTACH_POSITION,
8354 + XmNrightPosition, 86,
8355 + XmNbottomAttachment, XmATTACH_FORM,
8356 + XmNbottomOffset, BORDER, NULL);
8357 + XtAddCallback(closeBtn, XmNactivateCallback, closeCB, NULL);
8358 + XmStringFree(s1);
8360 + helpBtn = XtVaCreateManagedWidget("help", xmPushButtonWidgetClass,
8361 + form,
8362 + XmNlabelString, s1=XmStringCreateSimple("Help"),
8363 + XmNmnemonic, 'H',
8364 + XmNleftAttachment, XmATTACH_POSITION,
8365 + XmNleftPosition, 86,
8366 + XmNrightAttachment, XmATTACH_POSITION,
8367 + XmNrightPosition, 99,
8368 + XmNbottomAttachment, XmATTACH_FORM,
8369 + XmNbottomOffset, BORDER, NULL);
8370 + XtAddCallback(helpBtn, XmNactivateCallback, helpCB, NULL);
8371 + XmStringFree(s1);
8373 + stringPatternsFrame = XtVaCreateManagedWidget("stringPatternsFrame", xmFrameWidgetClass,
8374 + form,
8375 + XmNleftAttachment, XmATTACH_POSITION,
8376 + XmNleftPosition, 1,
8377 + XmNrightAttachment, XmATTACH_POSITION,
8378 + XmNrightPosition, 99,
8379 + XmNbottomAttachment, XmATTACH_WIDGET,
8380 + XmNbottomWidget, okBtn,
8381 + XmNbottomOffset, BORDER, NULL);
8382 + stringPatternsForm = XtVaCreateManagedWidget("stringPatternsForm", xmFormWidgetClass,
8383 + stringPatternsFrame, NULL);
8384 + MatchPatternDialog.mpdStringPatternsLbl = XtVaCreateManagedWidget("mpdStringPatternsLbl", xmLabelGadgetClass,
8385 + stringPatternsFrame,
8386 + XmNlabelString, s1=XmStringCreateSimple(STRING_PATTERNS_LBL_TXT),
8387 + XmNmarginHeight, 0,
8388 + XmNchildType, XmFRAME_TITLE_CHILD, NULL);
8389 + XmStringFree(s1);
8391 + n = 0;
8392 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
8393 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8394 + XtSetArg(args[n], XmNleftPosition, 1); n++;
8395 + XtSetArg(args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
8396 + XtSetArg(args[n], XmNrightPosition, LIST_RIGHT-1); n++;
8397 + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
8398 + XtSetArg(args[n], XmNbottomOffset, BORDER); n++;
8399 + MatchPatternDialog.mpdStringPatternsListW =
8400 + CreateManagedList(stringPatternsForm, "stringPatternsList", args,
8401 + n, (void **)MatchPatternDialog.currentStringPatterns.dspElements,
8402 + &MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns,
8403 + MAX_STRING_PATTERNS, 18,
8404 + getStringPatternDisplayedCB, NULL,
8405 + setStringPatternDisplayedCB, NULL,
8406 + freeStringPatternItemCB);
8407 + XtVaSetValues(MatchPatternDialog.mpdStringPatternsLbl, XmNuserData, MatchPatternDialog.mpdStringPatternsListW, NULL);
8409 + MatchPatternDialog.mpdStringPatternTypeLbl = XtVaCreateManagedWidget("mpdStringPatternTypeLbl", xmLabelGadgetClass,
8410 + stringPatternsForm,
8411 + XmNlabelString, s1=XmStringCreateSimple("String Pattern Type:"),
8412 + XmNmarginHeight, 0,
8413 + XmNalignment, XmALIGNMENT_BEGINNING,
8414 + XmNleftAttachment, XmATTACH_POSITION,
8415 + XmNleftPosition, LIST_RIGHT,
8416 + XmNtopAttachment, XmATTACH_FORM, NULL);
8417 + XmStringFree(s1);
8419 + stringPatternTypeBox = XtVaCreateManagedWidget("stringPatternTypeBox", xmRowColumnWidgetClass,
8420 + stringPatternsForm,
8421 + XmNorientation, XmHORIZONTAL,
8422 + XmNpacking, XmPACK_TIGHT,
8423 + XmNradioBehavior, True,
8424 + XmNleftAttachment, XmATTACH_POSITION,
8425 + XmNleftPosition, LIST_RIGHT,
8426 + XmNtopAttachment, XmATTACH_WIDGET,
8427 + XmNtopWidget, MatchPatternDialog.mpdStringPatternTypeLbl, NULL);
8428 + MatchPatternDialog.sptStartW = XtVaCreateManagedWidget("sptStartW",
8429 + xmToggleButtonWidgetClass, stringPatternTypeBox,
8430 + XmNset, True,
8431 + XmNmarginHeight, 0,
8432 + XmNlabelString, s1=XmStringCreateSimple(
8433 + "Start"),
8434 + NULL);
8435 + XmStringFree(s1);
8436 + MatchPatternDialog.sptMiddleW = XtVaCreateManagedWidget("sptMiddleW",
8437 + xmToggleButtonWidgetClass, stringPatternTypeBox,
8438 + XmNmarginHeight, 0,
8439 + XmNlabelString, s1=XmStringCreateSimple(
8440 + "Middle"),
8441 + NULL);
8442 + XmStringFree(s1);
8443 + MatchPatternDialog.sptEndW = XtVaCreateManagedWidget("sptEndW",
8444 + xmToggleButtonWidgetClass, stringPatternTypeBox,
8445 + XmNmarginHeight, 0,
8446 + XmNlabelString, s1=XmStringCreateSimple(
8447 + "End"),
8448 + NULL);
8449 + XmStringFree(s1);
8451 + MatchPatternDialog.mpdWordBoundaryLbl = XtVaCreateManagedWidget("mpdWordBoundaryLbl", xmLabelGadgetClass,
8452 + stringPatternsForm,
8453 + XmNlabelString, s1=XmStringCreateSimple("Word boundary:"),
8454 + XmNmarginHeight, 0,
8455 + XmNalignment, XmALIGNMENT_BEGINNING,
8456 + XmNleftAttachment, XmATTACH_POSITION,
8457 + XmNleftPosition, LIST_RIGHT,
8458 + XmNtopAttachment, XmATTACH_WIDGET,
8459 + XmNtopWidget, stringPatternTypeBox,
8460 + NULL);
8461 + XmStringFree(s1);
8463 + wordBoundaryBox = XtVaCreateManagedWidget("wordBoundaryBox", xmRowColumnWidgetClass,
8464 + stringPatternsForm,
8465 + XmNorientation, XmHORIZONTAL,
8466 + XmNpacking, XmPACK_TIGHT,
8467 + XmNradioBehavior, True,
8468 + XmNleftAttachment, XmATTACH_POSITION,
8469 + XmNleftPosition, LIST_RIGHT,
8470 + XmNtopAttachment, XmATTACH_WIDGET,
8471 + XmNtopWidget, MatchPatternDialog.mpdWordBoundaryLbl, NULL);
8472 + MatchPatternDialog.wbbBothW = XtVaCreateManagedWidget("wbbBothW",
8473 + xmToggleButtonWidgetClass, wordBoundaryBox,
8474 + XmNset, True,
8475 + XmNmarginHeight, 0,
8476 + XmNlabelString, s1=XmStringCreateSimple(
8477 + "Both (pattern is word)"),
8478 + NULL);
8479 + XmStringFree(s1);
8480 + MatchPatternDialog.wbbLeftW = XtVaCreateManagedWidget("wbbLeftW",
8481 + xmToggleButtonWidgetClass, wordBoundaryBox,
8482 + XmNmarginHeight, 0,
8483 + XmNlabelString, s1=XmStringCreateSimple(
8484 + "Left"),
8485 + NULL);
8486 + XmStringFree(s1);
8487 + MatchPatternDialog.wbbRightW = XtVaCreateManagedWidget("wbbRightW",
8488 + xmToggleButtonWidgetClass, wordBoundaryBox,
8489 + XmNmarginHeight, 0,
8490 + XmNlabelString, s1=XmStringCreateSimple(
8491 + "Right"),
8492 + NULL);
8493 + XmStringFree(s1);
8494 + MatchPatternDialog.wbbNoneW = XtVaCreateManagedWidget("wbbNoneW",
8495 + xmToggleButtonWidgetClass, wordBoundaryBox,
8496 + XmNmarginHeight, 0,
8497 + XmNlabelString, s1=XmStringCreateSimple(
8498 + "None"),
8499 + NULL);
8500 + XmStringFree(s1);
8502 + MatchPatternDialog.mpdStringAttributesLbl = XtVaCreateManagedWidget("mpdStringAttributesLbl", xmLabelGadgetClass,
8503 + stringPatternsForm,
8504 + XmNlabelString, s1=XmStringCreateSimple("String Attributes:"),
8505 + XmNmarginHeight, 0,
8506 + XmNalignment, XmALIGNMENT_BEGINNING,
8507 + XmNleftAttachment, XmATTACH_POSITION,
8508 + XmNleftPosition, LIST_RIGHT,
8509 + XmNtopAttachment, XmATTACH_WIDGET,
8510 + XmNtopWidget, wordBoundaryBox, NULL);
8511 + XmStringFree(s1);
8513 + stringAttributesBox = XtVaCreateManagedWidget("stringAttributesBox", xmRowColumnWidgetClass,
8514 + stringPatternsForm,
8515 + XmNorientation, XmHORIZONTAL,
8516 + XmNpacking, XmPACK_TIGHT,
8517 + XmNleftAttachment, XmATTACH_POSITION,
8518 + XmNleftPosition, LIST_RIGHT,
8519 + XmNtopAttachment, XmATTACH_WIDGET,
8520 + XmNtopWidget, MatchPatternDialog.mpdStringAttributesLbl, NULL);
8521 + MatchPatternDialog.sabRegularExpressionW = XtVaCreateManagedWidget("sabRegularExpressionW",
8522 + xmToggleButtonWidgetClass, stringAttributesBox,
8523 + XmNset, False,
8524 + XmNmarginHeight, 0,
8525 + XmNlabelString, s1=XmStringCreateSimple(
8526 + "Regular Expression"),
8527 + NULL);
8528 + XmStringFree(s1);
8529 + XtAddCallback(MatchPatternDialog.sabRegularExpressionW, XmNvalueChangedCallback,
8530 + strPatRegExpressionCB, NULL);
8531 + MatchPatternDialog.sabCaseSensitiveW = XtVaCreateManagedWidget("sabCaseSensitiveW",
8532 + xmToggleButtonWidgetClass, stringAttributesBox,
8533 + XmNset, True,
8534 + XmNmarginHeight, 0,
8535 + XmNlabelString, s1=XmStringCreateSimple(
8536 + "Case Sensitive"),
8537 + NULL);
8538 + XmStringFree(s1);
8540 + MatchPatternDialog.mpdStringPatternLbl = XtVaCreateManagedWidget("mpdStringPatternLbl", xmLabelGadgetClass,
8541 + stringPatternsForm,
8542 + XmNlabelString, s1=XmStringCreateSimple("String Pattern"),
8543 + XmNmnemonic, 'S',
8544 + XmNalignment, XmALIGNMENT_BEGINNING,
8545 + XmNleftAttachment, XmATTACH_POSITION,
8546 + XmNleftPosition, LIST_RIGHT,
8547 + XmNtopAttachment, XmATTACH_WIDGET,
8548 + XmNtopWidget, stringAttributesBox,
8549 + XmNtopOffset, BORDER,
8550 + NULL);
8551 + XmStringFree(s1);
8553 + MatchPatternDialog.mpdStringPatternW = XtVaCreateManagedWidget("mpdStringPatternW", xmTextWidgetClass,
8554 + stringPatternsForm,
8555 + XmNleftAttachment, XmATTACH_POSITION,
8556 + XmNleftPosition, LIST_RIGHT,
8557 + XmNtopAttachment, XmATTACH_WIDGET,
8558 + XmNtopWidget, MatchPatternDialog.mpdStringPatternLbl,
8559 + XmNrightAttachment, XmATTACH_FORM,
8560 + XmNrightOffset, BORDER,
8561 + NULL);
8562 + RemapDeleteKey(MatchPatternDialog.mpdStringPatternW);
8563 + XtVaSetValues(MatchPatternDialog.mpdStringPatternLbl, XmNuserData, MatchPatternDialog.mpdStringPatternW, NULL);
8565 + MatchPatternDialog.mpdSubPatNamesLbl = XtVaCreateManagedWidget("mpdSubPatNamesLbl", xmLabelGadgetClass,
8566 + stringPatternsForm,
8567 + XmNlabelString, s1=XmStringCreateSimple("Sub-Pattern Name"),
8568 + XmNmnemonic, 't',
8569 + XmNalignment, XmALIGNMENT_BEGINNING,
8570 + XmNleftAttachment, XmATTACH_POSITION,
8571 + XmNleftPosition, LIST_RIGHT,
8572 + XmNtopAttachment, XmATTACH_WIDGET,
8573 + XmNtopWidget, MatchPatternDialog.mpdStringPatternW,
8574 + XmNtopOffset, BORDER,
8575 + NULL);
8576 + XmStringFree(s1);
8578 + MatchPatternDialog.mpdSubPatNamesPulldown =
8579 + createSubPatternNameMenu(stringPatternsForm, NULL, False);
8581 + n = 0;
8582 + XtSetArg(args[n], XmNspacing, 0); n++;
8583 + XtSetArg(args[n], XmNmarginWidth, 0); n++;
8584 + XtSetArg(args[n], XmNresizeWidth, True); n++;
8585 + XtSetArg(args[n], XmNresizeHeight, True); n++;
8586 + XtSetArg(args[n], XmNnavigationType, XmTAB_GROUP); n++;
8587 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
8588 + XtSetArg(args[n], XmNtopWidget, MatchPatternDialog.mpdSubPatNamesLbl); n++;
8589 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8590 + XtSetArg(args[n], XmNleftPosition, LIST_RIGHT); n++;
8591 + XtSetArg(args[n], XmNsubMenuId, MatchPatternDialog.mpdSubPatNamesPulldown); n++;
8592 + MatchPatternDialog.mpdSubPatNamesOptMenu =
8593 + XmCreateOptionMenu(stringPatternsForm, "subPatNamesOptMenu", args, n);
8594 + XtManageChild(MatchPatternDialog.mpdSubPatNamesOptMenu);
8596 + XtVaSetValues(
8597 + MatchPatternDialog.mpdSubPatNamesLbl,
8598 + XmNuserData, XtParent(MatchPatternDialog.mpdSubPatNamesOptMenu),
8599 + NULL);
8601 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesLbl, False);
8602 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesOptMenu, False);
8604 + matchPatternsFrame = XtVaCreateManagedWidget("matchPatternsFrame", xmFrameWidgetClass,
8605 + form,
8606 + XmNleftAttachment, XmATTACH_POSITION,
8607 + XmNleftPosition, 1,
8608 + XmNtopAttachment, XmATTACH_WIDGET,
8609 + XmNtopWidget, lmForm,
8610 + XmNrightAttachment, XmATTACH_POSITION,
8611 + XmNrightPosition, 99,
8612 + XmNbottomAttachment, XmATTACH_WIDGET,
8613 + XmNbottomWidget, stringPatternsFrame,
8614 + XmNbottomOffset, BORDER, NULL);
8615 + matchPatternsForm = XtVaCreateManagedWidget("matchPatternsForm", xmFormWidgetClass,
8616 + matchPatternsFrame, NULL);
8617 + matchPatternsLbl = XtVaCreateManagedWidget("matchPatternsLbl", xmLabelGadgetClass,
8618 + matchPatternsFrame,
8619 + XmNlabelString, s1=XmStringCreateSimple("Matching Patterns"),
8620 + XmNmnemonic, 'P',
8621 + XmNmarginHeight, 0,
8622 + XmNchildType, XmFRAME_TITLE_CHILD, NULL);
8623 + XmStringFree(s1);
8625 + matchPatternTypeLbl = XtVaCreateManagedWidget("matchPatternTypeLbl", xmLabelGadgetClass,
8626 + matchPatternsForm,
8627 + XmNlabelString, s1=XmStringCreateSimple("Matching Pattern Type:"),
8628 + XmNmarginHeight, 0,
8629 + XmNalignment, XmALIGNMENT_BEGINNING,
8630 + XmNleftAttachment, XmATTACH_POSITION,
8631 + XmNleftPosition, LIST_RIGHT,
8632 + XmNtopAttachment, XmATTACH_FORM, NULL);
8633 + XmStringFree(s1);
8635 + matchPatternTypeBox = XtVaCreateManagedWidget("matchPatternTypeBox", xmRowColumnWidgetClass,
8636 + matchPatternsForm,
8637 + XmNpacking, XmPACK_COLUMN,
8638 + XmNradioBehavior, True,
8639 + XmNleftAttachment, XmATTACH_POSITION,
8640 + XmNleftPosition, LIST_RIGHT,
8641 + XmNtopAttachment, XmATTACH_WIDGET,
8642 + XmNtopWidget, matchPatternTypeLbl, NULL);
8643 + MatchPatternDialog.mptbIndividualW = XtVaCreateManagedWidget("mptbIndividualW",
8644 + xmToggleButtonWidgetClass, matchPatternTypeBox,
8645 + XmNset, True,
8646 + XmNmarginHeight, 0,
8647 + XmNlabelString, s1=XmStringCreateSimple(
8648 + "Individual"),
8649 + XmNmnemonic, 'I', NULL);
8650 + XmStringFree(s1);
8651 + XtAddCallback(MatchPatternDialog.mptbIndividualW, XmNvalueChangedCallback,
8652 + matchPatTypeCB, NULL);
8653 + MatchPatternDialog.mptbSubPatternW = XtVaCreateManagedWidget("mptbSubPatternW",
8654 + xmToggleButtonWidgetClass, matchPatternTypeBox,
8655 + XmNmarginHeight, 0,
8656 + XmNlabelString, s1=XmStringCreateSimple(
8657 + "Sub-pattern (belongs to context group)"),
8658 + XmNmnemonic, 'u', NULL);
8659 + XmStringFree(s1);
8660 + XtAddCallback(MatchPatternDialog.mptbSubPatternW, XmNvalueChangedCallback,
8661 + matchPatTypeCB, NULL);
8662 + MatchPatternDialog.mptbContextGroupW = XtVaCreateManagedWidget("mptbContextGroupW",
8663 + xmToggleButtonWidgetClass, matchPatternTypeBox,
8664 + XmNmarginHeight, 0,
8665 + XmNlabelString, s1=XmStringCreateSimple(
8666 + "Context group"),
8667 + XmNmnemonic, 'g', NULL);
8668 + XmStringFree(s1);
8669 + XtAddCallback(MatchPatternDialog.mptbContextGroupW, XmNvalueChangedCallback,
8670 + matchPatTypeCB, NULL);
8672 + MatchPatternDialog.mpdGlobalAttributesLbl = XtVaCreateManagedWidget("mpdGlobalAttributesLbl",
8673 + xmLabelGadgetClass, matchPatternsForm,
8674 + XmNlabelString, s1=XmStringCreateSimple("Global Attributes:"),
8675 + XmNmarginHeight, 0,
8676 + XmNalignment, XmALIGNMENT_BEGINNING,
8677 + XmNleftAttachment, XmATTACH_POSITION,
8678 + XmNleftPosition, LIST_RIGHT,
8679 + XmNtopAttachment, XmATTACH_WIDGET,
8680 + XmNtopOffset, BORDER,
8681 + XmNtopWidget, matchPatternTypeBox, NULL);
8682 + XmStringFree(s1);
8684 + globalAttributesBox = XtVaCreateManagedWidget("globalAttributesBox", xmRowColumnWidgetClass,
8685 + matchPatternsForm,
8686 + XmNpacking, XmPACK_COLUMN,
8687 + XmNleftAttachment, XmATTACH_POSITION,
8688 + XmNleftPosition, LIST_RIGHT,
8689 + XmNtopAttachment, XmATTACH_WIDGET,
8690 + XmNtopWidget, MatchPatternDialog.mpdGlobalAttributesLbl, NULL);
8691 + MatchPatternDialog.gabSkipBtwStartEndW = XtVaCreateManagedWidget("gabSkipBtwStartEndW",
8692 + xmToggleButtonWidgetClass, globalAttributesBox,
8693 + XmNmarginHeight, 0,
8694 + XmNlabelString, s1=XmStringCreateSimple(
8695 + "Skip content between start / end pattern"),
8696 + XmNmnemonic, 'c', NULL);
8697 + XmStringFree(s1);
8698 + MatchPatternDialog.gabFlashW = XtVaCreateManagedWidget("gabFlashW",
8699 + xmToggleButtonWidgetClass, globalAttributesBox,
8700 + XmNset, True,
8701 + XmNmarginHeight, 0,
8702 + XmNlabelString, s1=XmStringCreateSimple(
8703 + "Flash matching pattern"),
8704 + XmNmnemonic, 'l', NULL);
8705 + XmStringFree(s1);
8706 + MatchPatternDialog.gabSyntaxBasedW = XtVaCreateManagedWidget("gabSyntaxBasedW",
8707 + xmToggleButtonWidgetClass, globalAttributesBox,
8708 + XmNset, True,
8709 + XmNmarginHeight, 0,
8710 + XmNlabelString, s1=XmStringCreateSimple(
8711 + "Syntax based"),
8712 + XmNmnemonic, 'b', NULL);
8713 + XmStringFree(s1);
8715 + MatchPatternDialog.mpdMatchPatternNameLbl = XtVaCreateManagedWidget("mpdMatchPatternNameLbl", xmLabelGadgetClass,
8716 + matchPatternsForm,
8717 + XmNlabelString, s1=XmStringCreateSimple(MATCH_PAT_NAME_LBL_TXT),
8718 + XmNmnemonic, 'N',
8719 + XmNalignment, XmALIGNMENT_BEGINNING,
8720 + XmNleftAttachment, XmATTACH_POSITION,
8721 + XmNleftPosition, LIST_RIGHT,
8722 + XmNtopAttachment, XmATTACH_WIDGET,
8723 + XmNtopWidget, globalAttributesBox,
8724 + XmNtopOffset, BORDER, NULL);
8725 + XmStringFree(s1);
8727 + MatchPatternDialog.mpdMatchPatternNameW = XtVaCreateManagedWidget("mpdMatchPatternNameW", xmTextWidgetClass,
8728 + matchPatternsForm,
8729 + XmNleftAttachment, XmATTACH_POSITION,
8730 + XmNleftPosition, LIST_RIGHT,
8731 + XmNtopAttachment, XmATTACH_WIDGET,
8732 + XmNtopWidget, MatchPatternDialog.mpdMatchPatternNameLbl,
8733 + XmNrightAttachment, XmATTACH_FORM,
8734 + XmNrightOffset, BORDER,
8735 + XmNbottomAttachment, XmATTACH_FORM,
8736 + XmNbottomOffset, BORDER,
8737 + NULL);
8738 + RemapDeleteKey(MatchPatternDialog.mpdMatchPatternNameW);
8739 + XtVaSetValues(MatchPatternDialog.mpdMatchPatternNameLbl, XmNuserData, MatchPatternDialog.mpdMatchPatternNameW, NULL);
8741 + n = 0;
8742 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
8743 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8744 + XtSetArg(args[n], XmNleftPosition, 1); n++;
8745 + XtSetArg(args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
8746 + XtSetArg(args[n], XmNrightPosition, LIST_RIGHT-1); n++;
8747 + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
8749 + XtSetArg(args[n], XmNbottomOffset, BORDER); n++;
8750 + MatchPatternDialog.mpdMatchPatternNamesListW =
8751 + CreateManagedList(
8752 + matchPatternsForm, "mpdMatchPatternNamesListW",
8753 + args, n,
8754 + (void **)MatchPatternDialog.mpdTable.dmpiSequence, &MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements,
8755 + MAX_NBR_MATCH_PATTERNS, 18,
8756 + getMatchPatternDisplayedCB, NULL,
8757 + setMatchPatternDisplayedCB, NULL,
8758 + freeMatchPatternItemCB);
8759 + AddDeleteConfirmCB(MatchPatternDialog.mpdMatchPatternNamesListW, deleteMatchPatternItemCB, NULL);
8761 + XtVaSetValues(matchPatternsLbl, XmNuserData, MatchPatternDialog.mpdMatchPatternNamesListW, NULL);
8763 + /*
8764 + * set initial default button
8765 + */
8766 + XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
8767 + XtVaSetValues(form, XmNcancelButton, closeBtn, NULL);
8769 + /*
8770 + * handle mnemonic selection of buttons and focus to dialog
8771 + */
8772 + AddDialogMnemonicHandler(form, False);
8774 + /*
8775 + * fill in the dialog information for the selected language mode
8776 + */
8777 + SetLangModeMenu(MatchPatternDialog.mpdLmOptMenu, MatchPatternDialog.mpdLangModeName);
8779 + /*
8780 + * realize all of the widgets in the new dialog
8781 + */
8782 + RealizeWithoutForcingPosition(MatchPatternDialog.mpdShell);
8786 +** Modify match pattern dialog depending on showing a string pattern
8787 +** or a context group.
8789 +static void setDialogType(int dialogShowsStringPattern)
8791 + char *matchPatternNameText;
8792 + char *strPatCxtGrpListText;
8793 + XmString s1;
8794 + int regularExpression =
8795 + XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
8797 + /*
8798 + * check, if dialog mode needs to be switched
8799 + */
8800 + if (MatchPatternDialog.mpdStringPatternIsDisplayed == dialogShowsStringPattern)
8802 + return;
8805 + if (dialogShowsStringPattern)
8807 + matchPatternNameText = MATCH_PAT_NAME_LBL_TXT;
8808 + strPatCxtGrpListText = STRING_PATTERNS_LBL_TXT;
8810 + else
8812 + matchPatternNameText = "Context Group Name";
8813 + strPatCxtGrpListText = "Related Sub-Patterns";
8816 + XtSetSensitive(MatchPatternDialog.mpdGlobalAttributesLbl, dialogShowsStringPattern);
8817 + XtSetSensitive(MatchPatternDialog.gabSkipBtwStartEndW, dialogShowsStringPattern);
8818 + XtSetSensitive(MatchPatternDialog.gabFlashW, dialogShowsStringPattern);
8819 + XtSetSensitive(MatchPatternDialog.gabSyntaxBasedW, dialogShowsStringPattern);
8821 + XtSetSensitive(MatchPatternDialog.mpdStringPatternTypeLbl, dialogShowsStringPattern);
8822 + XtSetSensitive(MatchPatternDialog.sptStartW, dialogShowsStringPattern);
8823 + XtSetSensitive(MatchPatternDialog.sptMiddleW, dialogShowsStringPattern);
8824 + XtSetSensitive(MatchPatternDialog.sptEndW, dialogShowsStringPattern);
8826 + setSensitiveWordBoundaryBox( dialogShowsStringPattern && !regularExpression );
8828 + XtSetSensitive(MatchPatternDialog.mpdStringAttributesLbl, dialogShowsStringPattern);
8829 + XtSetSensitive(MatchPatternDialog.sabCaseSensitiveW, dialogShowsStringPattern);
8830 + XtSetSensitive(MatchPatternDialog.sabRegularExpressionW, dialogShowsStringPattern);
8832 + XtSetSensitive(MatchPatternDialog.mpdStringPatternLbl, dialogShowsStringPattern);
8833 + XtSetSensitive(MatchPatternDialog.mpdStringPatternW, dialogShowsStringPattern);
8835 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesLbl, !dialogShowsStringPattern);
8836 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesOptMenu, !dialogShowsStringPattern);
8838 + XtVaSetValues(
8839 + MatchPatternDialog.mpdMatchPatternNameLbl,
8840 + XmNlabelString, s1=XmStringCreateSimple(matchPatternNameText),
8841 + NULL);
8842 + XmStringFree(s1);
8844 + XtVaSetValues(
8845 + MatchPatternDialog.mpdStringPatternsLbl,
8846 + XmNlabelString, s1=XmStringCreateSimple(strPatCxtGrpListText),
8847 + NULL);
8848 + XmStringFree(s1);
8850 + MatchPatternDialog.mpdStringPatternIsDisplayed = dialogShowsStringPattern;
8853 +static void setSensitiveWordBoundaryBox(int enable)
8855 + XtSetSensitive(MatchPatternDialog.mpdWordBoundaryLbl, enable);
8856 + XtSetSensitive(MatchPatternDialog.wbbBothW , enable);
8857 + XtSetSensitive(MatchPatternDialog.wbbLeftW , enable);
8858 + XtSetSensitive(MatchPatternDialog.wbbRightW, enable);
8859 + XtSetSensitive(MatchPatternDialog.wbbNoneW , enable);
8862 +static void matchPatternLangModeCB(Widget w, XtPointer clientData, XtPointer callData)
8864 + char *modeName;
8865 + StringMatchTable *oldTable, *newTable;
8866 + StringMatchTable emptyTable = {"", NULL, NULL, NULL, NULL, 0, NULL, 0, NULL};
8867 + StringMatchTable *table;
8868 + DMPTranslationResult translResult;
8869 + int resp;
8871 + /*
8872 + * Get the newly selected mode name. If it's the same, do nothing
8873 + */
8874 + XtVaGetValues(w, XmNuserData, &modeName, NULL);
8875 + if (!strcmp(modeName, MatchPatternDialog.mpdLangModeName))
8876 + return;
8878 + /*
8879 + * Look up the original version of the patterns being edited
8880 + */
8881 + oldTable = (StringMatchTable *)FindStringMatchTable(MatchPatternDialog.mpdLangModeName);
8882 + if (oldTable == NULL)
8883 + oldTable = &emptyTable;
8885 + /*
8886 + * Get the current information displayed by the dialog. If it's bad,
8887 + * give the user the chance to throw it out or go back and fix it. If
8888 + * it has changed, give the user the chance to apply discard or cancel.
8889 + */
8890 + newTable = getDialogStringMatchTable(&translResult);
8892 + if (translResult == DMPTR_EMPTY)
8894 + newTable = &emptyTable;
8897 + if (newTable == NULL)
8899 + if (DialogF(
8900 + DF_WARN, MatchPatternDialog.mpdShell, 2,
8901 + "Incomplete Matching Patterns for Language Mode",
8902 + "Discard incomplete entry for language mode '%s'?",
8903 + "Keep", "Discard",
8904 + MatchPatternDialog.mpdLangModeName) == 1)
8906 + SetLangModeMenu(
8907 + MatchPatternDialog.mpdLmOptMenu,
8908 + MatchPatternDialog.mpdLangModeName);
8910 + return;
8913 + else if (stringMatchTableDiffer(oldTable, newTable))
8915 + if (newTable == &emptyTable)
8916 + newTable = NULL;
8918 + resp =
8919 + DialogF(
8920 + DF_WARN, MatchPatternDialog.mpdShell, 3,
8921 + "Change Language Mode",
8922 + "Apply changes for language mode '%s'?",
8923 + "Apply Changes", "Discard Changes", "Cancel",
8924 + MatchPatternDialog.mpdLangModeName);
8926 + if (resp == 3)
8928 + SetLangModeMenu(
8929 + MatchPatternDialog.mpdLmOptMenu,
8930 + MatchPatternDialog.mpdLangModeName);
8932 + freeStringMatchTable( newTable );
8934 + return;
8936 + else if (resp == 1)
8938 + updateStringMatchTable( newTable );
8940 + /*
8941 + * Don't free the new table due to it's stored in MatchTables now
8942 + */
8943 + newTable = NULL;
8947 + if (newTable != NULL && newTable != &emptyTable)
8948 + freeStringMatchTable(newTable);
8950 + /*
8951 + * Free the old dialog information
8952 + */
8953 + freeVariableDialogData(DISCARD_LANGUAGE_MODE);
8955 + /*
8956 + * Fill the dialog with the new language mode information
8957 + */
8958 + MatchPatternDialog.mpdLangModeName = XtNewString(modeName);
8960 + /*
8961 + * Find the associated matching pattern table to edit
8962 + */
8963 + table = (StringMatchTable *)FindStringMatchTable(MatchPatternDialog.mpdLangModeName);
8965 + /*
8966 + * Copy the list of patterns to one that the user can freely edit
8967 + */
8968 + copyStringMatchTableForDialog( table, &MatchPatternDialog.mpdTable );
8970 + /*
8971 + * Update dialog fields
8972 + */
8973 + ChangeManagedListData(MatchPatternDialog.mpdMatchPatternNamesListW);
8974 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
8977 +static void pmLanguageModeDialogCB(Widget w, XtPointer clientData, XtPointer callData)
8979 + EditLanguageModes();
8983 +** If a matching pattern dialog is up, ask to have the option menu for
8984 +** chosing language mode updated (via a call to CreateLanguageModeMenu)
8986 +void UpdateLanguageModeMenuMatchPattern(void)
8988 + Widget oldMenu;
8990 + if (MatchPatternDialog.mpdShell == NULL)
8991 + return;
8993 + oldMenu = MatchPatternDialog.mpdLmPulldown;
8994 + /*
8995 + * don't include "PLAIN" (4th parameter) in LM menu
8996 + */
8997 + MatchPatternDialog.mpdLmPulldown = CreateLanguageModeMenu(
8998 + XtParent(XtParent(oldMenu)), matchPatternLangModeCB, NULL, False);
8999 + XtVaSetValues(XmOptionButtonGadget(MatchPatternDialog.mpdLmOptMenu),
9000 + XmNsubMenuId, MatchPatternDialog.mpdLmPulldown, NULL);
9001 + SetLangModeMenu(MatchPatternDialog.mpdLmOptMenu, MatchPatternDialog.mpdLangModeName);
9003 + XtDestroyWidget(oldMenu);
9006 +static void *getMatchPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
9007 + void *cbArg)
9009 + DialogMatchPatternSequenceElement *newSeq;
9011 + /*
9012 + * If the dialog is currently displaying the "new" entry and the
9013 + * fields are empty, that's just fine
9014 + */
9015 + if (oldItem == NULL && matchPatternDialogEmpty())
9016 + return NULL;
9018 + /*
9019 + * Read string patterns / sub-pattern names area first
9020 + */
9021 + UpdateManagedList(MatchPatternDialog.mpdStringPatternsListW, True);
9023 + /*
9024 + * If there are no problems reading the data, just return it
9025 + */
9026 + newSeq = readMatchPatternFields(True);
9027 + if (newSeq != NULL)
9028 + return (void *)newSeq;
9030 + /*
9031 + * If there are problems, and the user didn't ask for the fields to be
9032 + * read, give more warning
9033 + */
9034 + if (!explicitRequest)
9036 + if (DialogF(
9037 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9038 + "Discard Matching Pattern Entry",
9039 + "Discard incomplete entry\nfor current matching pattern?",
9040 + "Keep", "Discard") == 2)
9042 + return oldItem == NULL
9043 + ? NULL
9044 + : (void *)copyDialogSequenceElement(
9045 + (DialogMatchPatternSequenceElement *)oldItem);
9049 + /*
9050 + * read data again without "silent" mode to display warning
9051 + */
9052 + newSeq = readMatchPatternFields(False);
9053 + *abort = True;
9055 + return NULL;
9058 +static void setMatchPatternDisplayedCB(void *item, void *cbArg)
9060 + DialogMatchPatternSequenceElement *seqElement;
9061 + DialogMatchPatternTableElement *element;
9062 + DialogMatchPatternGroupElement *group;
9063 + int isGroup;
9065 + seqElement = (DialogMatchPatternSequenceElement *)item;
9067 + MatchPatternDialog.currentDmptSeqElement = seqElement;
9069 + if (item == NULL)
9071 + MatchPatternDialog.currentDmptElement = NULL;
9072 + MatchPatternDialog.currentDmptGroup = NULL;
9074 + XmTextSetString(MatchPatternDialog.mpdMatchPatternNameW, "");
9075 + RadioButtonChangeState(MatchPatternDialog.mptbIndividualW, True, True);
9076 + RadioButtonChangeState(MatchPatternDialog.gabSkipBtwStartEndW, False, False);
9077 + RadioButtonChangeState(MatchPatternDialog.gabFlashW, True, False);
9078 + RadioButtonChangeState(MatchPatternDialog.gabSyntaxBasedW, True, False);
9080 + freeDialogStringPatterns(
9081 + &MatchPatternDialog.currentStringPatterns);
9083 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9085 + setDialogType( STRING_PATTERN_DIALOG );
9087 + else
9089 + isGroup = (seqElement->dmpseType == MPT_GROUP);
9091 + XmTextSetString(MatchPatternDialog.mpdMatchPatternNameW, seqElement->dmpseName);
9093 + if (seqElement->dmpseType == MPT_INDIVIDUAL)
9094 + RadioButtonChangeState(MatchPatternDialog.mptbIndividualW, True, True);
9095 + else if (seqElement->dmpseType == MPT_SUB)
9096 + RadioButtonChangeState(MatchPatternDialog.mptbSubPatternW, True, True);
9097 + else
9098 + RadioButtonChangeState(MatchPatternDialog.mptbContextGroupW, True, True);
9100 + freeDialogStringPatterns(
9101 + &MatchPatternDialog.currentStringPatterns);
9103 + if (isGroup)
9105 + group = (DialogMatchPatternGroupElement *)seqElement->dmpsePtr;
9106 + MatchPatternDialog.currentDmptElement = NULL;
9107 + MatchPatternDialog.currentDmptGroup = group;
9109 + copyDialogPatternNamesFromGroup(
9110 + group,
9111 + &MatchPatternDialog.currentStringPatterns);
9113 + else
9115 + element = (DialogMatchPatternTableElement *)seqElement->dmpsePtr;
9116 + MatchPatternDialog.currentDmptElement = element;
9117 + MatchPatternDialog.currentDmptGroup = NULL;
9119 + RadioButtonChangeState(
9120 + MatchPatternDialog.gabSkipBtwStartEndW,
9121 + element->dmpteSkipBtwnStartEnd,
9122 + False);
9123 + RadioButtonChangeState(
9124 + MatchPatternDialog.gabFlashW,
9125 + element->dmpteFlash,
9126 + False);
9127 + RadioButtonChangeState(
9128 + MatchPatternDialog.gabSyntaxBasedW,
9129 + !element->dmpteIgnoreHighLightInfo,
9130 + False);
9132 + copyDialogStringPatternsFromTable(
9133 + element,
9134 + &MatchPatternDialog.currentStringPatterns);
9137 + setDialogType( !isGroup );
9139 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9143 +static void freeMatchPatternItemCB(void *item)
9145 + freeDialogSequenceElement((DialogMatchPatternSequenceElement *)item);
9149 +** Use "delete confirm" to delete matching pattern name from
9150 +** any group of this matching pattern set, in case of sub-pattern.
9151 +** Always confirm the delete.
9153 +static int deleteMatchPatternItemCB(int itemIndex, void *cbArg)
9155 + DialogMatchPatternSequenceElement *seqElement;
9157 + seqElement = MatchPatternDialog.mpdTable.dmpiSequence[itemIndex];
9159 + if (seqElement->dmpseType == MPT_SUB)
9161 + removeMatchPatternFromAllGroups( seqElement->dmpseName );
9164 + return True;
9167 +static void *getStringPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
9168 + void *cbArg)
9170 + DialogStringPatternElement *newPat;
9171 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
9173 + /*
9174 + * If the string pattern frame is currently displaying the "new" entry and the
9175 + * fields are empty, that's just fine
9176 + */
9177 + if (oldItem == NULL && stringPatternFieldsEmpty(isRelatedToGroup))
9178 + return NULL;
9180 + /*
9181 + * If there are no problems reading the data, just return it
9182 + */
9183 + newPat = readStringPatternFrameFields(True);
9184 + if (newPat != NULL)
9185 + return (void *)newPat;
9187 + /*
9188 + * If there are problems, and the user didn't ask for the fields to be
9189 + * read, give more warning
9190 + */
9192 + if (!explicitRequest)
9194 + if (DialogF(
9195 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9196 + "Discard String Pattern Entry",
9197 + "Discard incomplete entry\nfor current string pattern?",
9198 + "Keep", "Discard") == 2)
9200 + return oldItem == NULL
9201 + ? NULL
9202 + : (void *)copyDialogStringPatternElement(
9203 + (DialogStringPatternElement *)oldItem);
9207 + /*
9208 + * read data again without "silent" mode to display warning
9209 + */
9210 + newPat = readStringPatternFrameFields(False);
9211 + *abort = True;
9213 + return NULL;
9216 +static void setStringPatternDisplayedCB(void *item, void *cbArg)
9218 + DialogStringPatternElement *element = (DialogStringPatternElement *)item;
9219 + PatternElementKind peKind;
9220 + PatternWordBoundary wordBoundary;
9221 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
9223 + if (item == NULL)
9225 + if (isRelatedToGroup)
9227 + updateSubPatternNameMenu(NULL, False);
9229 + else
9231 + XmTextSetString(MatchPatternDialog.mpdStringPatternW, "");
9233 + setSensitiveWordBoundaryBox( True );
9235 + RadioButtonChangeState(MatchPatternDialog.wbbBothW, True, True);
9237 + /*
9238 + * type of "new" string pattern:
9239 + * preset "start", if no string pattern exists at all;
9240 + * else select "end"
9241 + */
9242 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0)
9243 + RadioButtonChangeState(MatchPatternDialog.sptStartW, True, True);
9244 + else
9245 + RadioButtonChangeState(MatchPatternDialog.sptEndW, True, True);
9247 + RadioButtonChangeState(MatchPatternDialog.sabCaseSensitiveW, True, False);
9248 + RadioButtonChangeState(MatchPatternDialog.sabRegularExpressionW, False, False);
9251 + else
9253 + if (isRelatedToGroup)
9255 + updateSubPatternNameMenu(element->dspeText, False);
9257 + else
9259 + XmTextSetString(MatchPatternDialog.mpdStringPatternW, element->dspeText);
9261 + peKind = element->dspeKind;
9262 + wordBoundary = element->dspeWordBoundary;
9264 + if (peKind == PEK_START)
9265 + RadioButtonChangeState(MatchPatternDialog.sptStartW, True, True);
9266 + else if (peKind == PEK_MIDDLE)
9267 + RadioButtonChangeState(MatchPatternDialog.sptMiddleW, True, True);
9268 + else
9269 + RadioButtonChangeState(MatchPatternDialog.sptEndW, True, True);
9271 + if (wordBoundary == PWB_BOTH)
9272 + RadioButtonChangeState(MatchPatternDialog.wbbBothW, True, True);
9273 + else if (wordBoundary == PWB_LEFT)
9274 + RadioButtonChangeState(MatchPatternDialog.wbbLeftW, True, True);
9275 + else if (wordBoundary == PWB_RIGHT)
9276 + RadioButtonChangeState(MatchPatternDialog.wbbRightW, True, True);
9277 + else
9278 + RadioButtonChangeState(MatchPatternDialog.wbbNoneW, True, True);
9280 + RadioButtonChangeState(
9281 + MatchPatternDialog.sabCaseSensitiveW,
9282 + !element->dspeCaseInsensitive,
9283 + False);
9285 + RadioButtonChangeState(
9286 + MatchPatternDialog.sabRegularExpressionW,
9287 + element->dspeRegularExpression,
9288 + False);
9290 + setSensitiveWordBoundaryBox( !element->dspeRegularExpression );
9295 +static void freeStringPatternItemCB(void *item)
9297 + DialogStringPatternElement *patElement;
9299 + patElement = (DialogStringPatternElement *)item;
9301 + freeDialogStringPatternElement(patElement);
9304 +static void destroyCB(Widget w, XtPointer clientData, XtPointer callData)
9306 + freeVariableDialogData(DISCARD_LANGUAGE_MODE);
9308 + MatchPatternDialog.mpdShell = NULL;
9311 +static void okCB(Widget w, XtPointer clientData, XtPointer callData)
9313 + /*
9314 + * change the matching pattern
9315 + */
9316 + if (!getAndUpdateStringMatchTable())
9317 + return;
9319 + /*
9320 + * pop down and destroy the dialog
9321 + */
9322 + XtDestroyWidget(MatchPatternDialog.mpdShell);
9325 +static void applyCB(Widget w, XtPointer clientData, XtPointer callData)
9327 + /*
9328 + * change the matching pattern
9329 + */
9330 + getAndUpdateStringMatchTable();
9333 +static void checkCB(Widget w, XtPointer clientData, XtPointer callData)
9335 + StringMatchTable *newTable;
9336 + DMPTranslationResult translResult;
9338 + /*
9339 + * Get the current information displayed by the dialog.
9340 + * If a new table is available, then the test is passed successfully.
9341 + */
9342 + newTable = getDialogStringMatchTable(&translResult);
9344 + if (newTable != NULL)
9346 + DialogF(
9347 + DF_INF, MatchPatternDialog.mpdShell, 1,
9348 + "Matching Patterns Checked",
9349 + "Matching Patterns checked without error",
9350 + "OK");
9352 + freeStringMatchTable(newTable);
9356 +static void restoreCB(Widget w, XtPointer clientData, XtPointer callData)
9358 + StringMatchTable *defaultTable;
9360 + defaultTable = readDefaultStringMatchTable(MatchPatternDialog.mpdLangModeName);
9362 + if (defaultTable == NULL)
9364 + DialogF(
9365 + DF_WARN, MatchPatternDialog.mpdShell, 1,
9366 + "No Default Matching Pattern",
9367 + "There is no default matching pattern set\nfor language mode %s",
9368 + "OK",
9369 + MatchPatternDialog.mpdLangModeName);
9371 + return;
9374 + if (DialogF(
9375 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9376 + "Discard Changes",
9377 + "Are you sure you want to discard\n"
9378 + "all changes to matching patterns\n"
9379 + "for language mode %s?",
9380 + "Discard", "Cancel",
9381 + MatchPatternDialog.mpdLangModeName) == 2)
9383 + freeStringMatchTable(defaultTable);
9385 + return;
9388 + /*
9389 + * if a stored version of the matching pattern set exists, replace it.
9390 + * if it doesn't, add a new one.
9391 + */
9392 + updateStringMatchTable( defaultTable );
9394 + /*
9395 + * free the old dialog information
9396 + */
9397 + freeVariableDialogData(KEEP_LANGUAGE_MODE);
9399 + /*
9400 + * update the dialog
9401 + */
9402 + copyStringMatchTableForDialog( defaultTable, &MatchPatternDialog.mpdTable );
9404 + ChangeManagedListData(MatchPatternDialog.mpdMatchPatternNamesListW);
9405 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9408 +static void deleteCB(Widget w, XtPointer clientData, XtPointer callData)
9410 + if (DialogF(
9411 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9412 + "Delete Matching Patterns",
9413 + "Are you sure you want to delete\n"
9414 + "all matching patterns for\n"
9415 + "language mode %s?",
9416 + "Yes, Delete", "Cancel",
9417 + MatchPatternDialog.mpdLangModeName) == 2)
9419 + return;
9422 + /*
9423 + * if a stored version of the matching pattern exists, delete it from the list
9424 + */
9425 + DeleteStringMatchTable(MatchPatternDialog.mpdLangModeName);
9427 + /*
9428 + * free the old dialog information
9429 + */
9430 + freeVariableDialogData(KEEP_LANGUAGE_MODE);
9432 + /*
9433 + * clear out the dialog
9434 + */
9435 + ChangeManagedListData(MatchPatternDialog.mpdMatchPatternNamesListW);
9436 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9439 +static void closeCB(Widget w, XtPointer clientData, XtPointer callData)
9441 + /*
9442 + * pop down and destroy the dialog
9443 + */
9444 + XtDestroyWidget(MatchPatternDialog.mpdShell);
9447 +static void helpCB(Widget w, XtPointer clientData, XtPointer callData)
9450 + Help(HELP_MATCHING_PATTERNS);
9454 +static void strPatRegExpressionCB(Widget w, XtPointer clientData, XtPointer callData)
9456 + int regularExpression =
9457 + XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
9459 + setSensitiveWordBoundaryBox( !regularExpression );
9461 + if (regularExpression)
9462 + RadioButtonChangeState(MatchPatternDialog.sabCaseSensitiveW, True, False);
9465 +static void matchPatTypeCB(Widget w, XtPointer clientData, XtPointer callData)
9467 + if (MatchPatternDialog.currentDmptSeqElement != NULL)
9469 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW))
9471 + if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_SUB)
9473 + changeExistingSubPattern("Change to Context Group");
9476 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW) &&
9477 + MatchPatternDialog.currentDmptSeqElement->dmpseType != MPT_GROUP)
9479 + changeStringPatternToGroup();
9482 + else if (XmToggleButtonGetState(MatchPatternDialog.mptbIndividualW))
9484 + if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_SUB)
9486 + changeExistingSubPattern("Change to Individual Matching Pattern");
9488 + else if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_GROUP)
9490 + changeGroupToStringPattern("Change to Individual Matching Pattern");
9493 + else if (XmToggleButtonGetState(MatchPatternDialog.mptbSubPatternW))
9495 + if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_GROUP)
9497 + changeGroupToStringPattern("Change to Sub-Matching Pattern");
9502 + /*
9503 + * if context group button is (still) selected, then update labels etc.
9504 + */
9505 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW))
9507 + setDialogType(CONTEXT_GROUP_DIALOG);
9509 + else
9511 + setDialogType(STRING_PATTERN_DIALOG);
9514 + /*
9515 + * if a "new" entry is selected in matching patterns names list, then provide a
9516 + * list of all sub-pattern names
9517 + */
9518 + if (MatchPatternDialog.currentDmptSeqElement == NULL)
9520 + updateSubPatternNameMenu(NULL, True);
9524 +static void changeExistingSubPattern(
9525 + char *warnTitle)
9527 + DialogMatchPatternGroupElement *group;
9528 + int resp;
9530 + group =
9531 + getDialogGroupUsingMatchPattern(
9532 + MatchPatternDialog.currentDmptElement->dmpteName );
9534 + while ( group != NULL )
9536 + resp =
9537 + DialogF(
9538 + DF_WARN, MatchPatternDialog.mpdShell, 3,
9539 + warnTitle,
9540 + "Sub-pattern '%s' is used at least\n"
9541 + "by context group '%s'.\n\n"
9542 + "Remove this sub-pattern from this resp. all context group(s) ?",
9543 + "No, Keep", "Yes, Remove", "Yes, Remove All",
9544 + MatchPatternDialog.currentDmptElement->dmpteName,
9545 + group->dmpgeName);
9547 + if (resp == 1)
9549 + RadioButtonChangeState(MatchPatternDialog.mptbSubPatternW, True, True);
9551 + return;
9553 + else if (resp == 2)
9555 + removeMatchPatternFromGroup(
9556 + MatchPatternDialog.currentDmptElement->dmpteName,
9557 + group);
9559 + /*
9560 + * look for evtl. next context group holding this matching pattern
9561 + */
9562 + group =
9563 + getDialogGroupUsingMatchPattern(
9564 + MatchPatternDialog.currentDmptElement->dmpteName );
9566 + else
9568 + /*
9569 + * remove this matching pattern form all context groups
9570 + */
9571 + removeMatchPatternFromAllGroups(
9572 + MatchPatternDialog.currentDmptElement->dmpteName);
9574 + return;
9579 +static void changeStringPatternToGroup(void)
9581 + int resp;
9582 + int isSubPattern;
9584 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns != 0)
9586 + resp =
9587 + DialogF(
9588 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9589 + "Change to Context Group",
9590 + "All string patterns of '%s'\n"
9591 + "need to be discarded.\n\n"
9592 + "Discard related string patterns ?",
9593 + "No, Keep", "Yes, Discard",
9594 + MatchPatternDialog.currentDmptElement->dmpteName);
9596 + if (resp == 1)
9598 + isSubPattern = (MatchPatternDialog.currentDmptElement->dmpteType == MPT_SUB);
9600 + if (isSubPattern)
9601 + RadioButtonChangeState(MatchPatternDialog.mptbSubPatternW, True, True);
9602 + else
9603 + RadioButtonChangeState(MatchPatternDialog.mptbIndividualW, True, True);
9605 + return;
9608 + /*
9609 + * remove string patterns & update dialog fields
9610 + */
9611 + freeDialogStringPatterns(&MatchPatternDialog.currentStringPatterns);
9613 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9616 + /*
9617 + * invalidate this sub-/individual pattern
9618 + */
9619 + MatchPatternDialog.currentDmptSeqElement->dmpseValid = False;
9621 + /*
9622 + * update sub-pattern menu due to change to context group
9623 + */
9624 + updateSubPatternNameMenu(NULL, True);
9627 +static void changeGroupToStringPattern(
9628 + char *warnTitle)
9630 + int resp;
9632 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0)
9633 + return;
9635 + resp =
9636 + DialogF(
9637 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9638 + warnTitle,
9639 + "Content of context group '%s'\n"
9640 + "needs to be discarded.\n\n"
9641 + "Discard content ?",
9642 + "No, Keep", "Yes, Discard",
9643 + MatchPatternDialog.currentDmptGroup->dmpgeName);
9645 + if (resp == 1)
9647 + RadioButtonChangeState(MatchPatternDialog.mptbContextGroupW, True, True);
9649 + else
9651 + /*
9652 + * remove string patterns & update dialog fields
9653 + */
9654 + freeDialogStringPatterns(&MatchPatternDialog.currentStringPatterns);
9656 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9661 +** Create a pulldown menu pane with the names of the sub-patterns of
9662 +** the current matching pattern set.
9664 +static Widget createSubPatternNameMenu(
9665 + Widget parent,
9666 + char *currentSubPatName,
9667 + int allSubPatterns)
9669 + NameList nameList;
9670 + Widget menu;
9671 + int i;
9673 + setupSubPatternNameList(currentSubPatName, allSubPatterns, &nameList);
9675 + menu = CreatePulldownMenu(parent, "subPatternNames", NULL, 0);
9677 + for (i=0; i<nameList.nlNumber; i++)
9679 + createSubPatNameMenuEntry(menu, nameList.nlId[i]);
9682 + return menu;
9685 +static void setupSubPatternNameList(
9686 + char *currentSubPatName,
9687 + int allSubPatterns,
9688 + NameList *nameList)
9690 + int n = 0;
9691 + int i;
9692 + DialogMatchPatternSequenceElement *seq;
9693 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
9695 + if (isRelatedToGroup || allSubPatterns)
9697 + /*
9698 + * add "none selected" (default) item
9699 + */
9700 + nameList->nlId[n ++] = SPNM_NONE_SELECTED;
9702 + /*
9703 + * add one item for each (not assigned) sub-pattern name
9704 + */
9705 + for (i=0; i<MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i++)
9707 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
9709 + if (seq->dmpseType == MPT_SUB &&
9710 + seq->dmpseValid &&
9711 + (allSubPatterns ||
9712 + (!isSubPatternNameInCurStrPat(seq->dmpseName) ||
9713 + (currentSubPatName != NULL &&
9714 + (strcmp(seq->dmpseName, currentSubPatName) == 0))) ))
9716 + nameList->nlId[n ++] = seq->dmpseName;
9720 + else
9722 + nameList->nlId[n ++] = "none available ";
9725 + nameList->nlNumber = n;
9729 +** Create a menu entry with the names of one sub-pattern.
9730 +** XmNuserData of this item contains the sub-pattern name.
9732 +static void createSubPatNameMenuEntry(
9733 + Widget menu,
9734 + char *subPatName)
9736 + Widget btn;
9737 + XmString s1;
9739 + btn = XtVaCreateManagedWidget("subPattern", xmPushButtonGadgetClass,
9740 + menu,
9741 + XmNlabelString, s1=XmStringCreateSimple(subPatName),
9742 + XmNmarginHeight, 0,
9743 + XmNuserData, (void *)subPatName, NULL);
9744 + XmStringFree(s1);
9748 +** Set the sub-patterns menu to show a particular sub-pattern name
9750 +static void setSubPatternNameMenu(
9751 + const char *subPatName)
9753 + int i;
9754 + Cardinal nItems;
9755 + WidgetList items;
9756 + Widget pulldown, selectedItem;
9757 + char *itemName;
9759 + XtVaGetValues(MatchPatternDialog.mpdSubPatNamesOptMenu, XmNsubMenuId, &pulldown, NULL);
9760 + XtVaGetValues(pulldown, XmNchildren, &items, XmNnumChildren, &nItems, NULL);
9762 + if (nItems == 0)
9763 + return;
9765 + selectedItem = items[0];
9767 + /*
9768 + * if no subPatName is given, then select first item of option menu
9769 + */
9770 + if (subPatName != NULL)
9772 + for (i=0; i<(int)nItems; i++)
9774 + if (items[i] != NULL && !items[i]->core.being_destroyed)
9776 + XtVaGetValues(items[i], XmNuserData, &itemName, NULL);
9777 + if (!strcmp(itemName, subPatName))
9779 + selectedItem = items[i];
9780 + break;
9786 + XtVaSetValues(MatchPatternDialog.mpdSubPatNamesOptMenu, XmNmenuHistory, selectedItem, NULL);
9790 +** Update sub-pattern names menu, e.g. when a new sub-pattern is defined
9792 +static void updateSubPatternNameMenu(
9793 + char *currentSubPatName,
9794 + int allSubPatterns)
9796 + NameList nameList;
9797 + WidgetList items;
9798 + Cardinal nItems;
9799 + int n;
9800 + XmString st1;
9802 + setupSubPatternNameList(currentSubPatName, allSubPatterns, &nameList);
9804 + /*
9805 + * Go thru all of the items in the sub-pattern names menu
9806 + * and rename them to match the current sub-patterns.
9807 + * Delete any extras.
9808 + */
9809 + XtVaGetValues(
9810 + MatchPatternDialog.mpdSubPatNamesPulldown,
9811 + XmNchildren, &items,
9812 + XmNnumChildren, &nItems,
9813 + NULL);
9815 + for (n=0; n<(int)nItems; n++)
9817 + if (n >= nameList.nlNumber)
9819 + /*
9820 + * unmanaging before destroying stops parent from displaying
9821 + */
9822 + XtUnmanageChild(items[n]);
9823 + XtDestroyWidget(items[n]);
9825 + else
9827 + if (items[n] == NULL || items[n]->core.being_destroyed)
9829 + /*
9830 + * create a new entry (widget) if this one is not existing or
9831 + * if it is marked as to be destroyed
9832 + */
9833 + createSubPatNameMenuEntry(
9834 + MatchPatternDialog.mpdSubPatNamesPulldown, nameList.nlId[n]);
9836 + else
9838 + XtVaSetValues(
9839 + items[n],
9840 + XmNlabelString, st1=XmStringCreateSimple(nameList.nlId[n]),
9841 + XmNuserData, (void *)nameList.nlId[n],
9842 + NULL);
9844 + XmStringFree(st1);
9849 + /*
9850 + * add new items for remaining sub-patterns names
9851 + */
9852 + for (n=(int)nItems; n<nameList.nlNumber; n++)
9854 + createSubPatNameMenuEntry(
9855 + MatchPatternDialog.mpdSubPatNamesPulldown, nameList.nlId[n]);
9858 + /*
9859 + * select entry shown in sub-pattern name option menu
9860 + */
9861 + setSubPatternNameMenu(currentSubPatName);
9864 +static char *getSelectedSubPatternName(void)
9866 + Widget selectedItem;
9867 + char *itemName;
9869 + XtVaGetValues(MatchPatternDialog.mpdSubPatNamesOptMenu, XmNmenuHistory, &selectedItem, NULL);
9870 + XtVaGetValues(selectedItem, XmNuserData, &itemName, NULL);
9872 + return itemName;
9875 +static int isSubPatternNameInCurStrPat(
9876 + char *subPatName)
9878 + int i;
9879 + DialogStringPatterns *curPatNames = &MatchPatternDialog.currentStringPatterns;
9881 + for (i=0; i<curPatNames->dspNumberOfPatterns; i++)
9883 + if (strcmp(curPatNames->dspElements[i]->dspeText, subPatName) == 0)
9884 + return True;
9887 + return False;
9891 +** Read the matching pattern fields of the matching pattern dialog and produce an
9892 +** allocated DialogMatchPatternSequenceElement structure reflecting the contents.
9893 +** Pop up dialogs telling the user what's wrong (Passing "silent" as True,
9894 +** suppresses these dialogs).
9895 +** Returns NULL on error.
9897 +static DialogMatchPatternSequenceElement *readMatchPatternFields(int silent)
9899 + int isGroup;
9900 + char *name;
9901 + char *nameLabel;
9902 + char *nameTitle;
9903 + char *contentTitle;
9904 + char *contentWarningText;
9905 + DialogMatchPatternSequenceElement *newSeq;
9906 + DialogMatchPatternTableElement *newElement;
9907 + DialogMatchPatternGroupElement *newGroup;
9909 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW))
9911 + nameLabel = "context group name";
9912 + nameTitle = "Context Group Name";
9913 + contentTitle = "Context Group Content";
9914 + contentWarningText = "Please assign min. 1\nsub-pattern";
9915 + isGroup = True;
9917 + else
9919 + nameLabel = "matching pattern name";
9920 + nameTitle = "Matching Pattern Name";
9921 + contentTitle = "Matching Pattern Content";
9922 + contentWarningText = "Please specify min. 1\nstring pattern";
9923 + isGroup = False;
9926 + name =
9927 + ReadSymbolicFieldTextWidget(
9928 + MatchPatternDialog.mpdMatchPatternNameW,
9929 + nameLabel,
9930 + silent);
9932 + if (name == NULL)
9934 + return NULL;
9936 + else if (*name == '\0')
9938 + if (!silent)
9940 + DialogF(
9941 + DF_WARN, MatchPatternDialog.mpdShell, 1,
9942 + nameTitle,
9943 + "Please specify a valid name",
9944 + "OK");
9945 + XmProcessTraversal(MatchPatternDialog.mpdMatchPatternNameW, XmTRAVERSE_CURRENT);
9947 + XtFree(name);
9948 + return NULL;
9951 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0)
9953 + if (!silent)
9955 + DialogF(
9956 + DF_WARN, MatchPatternDialog.mpdShell, 1,
9957 + contentTitle,
9958 + contentWarningText,
9959 + "OK");
9961 + XtFree(name);
9962 + return NULL;
9964 + else
9966 + if (!isGroup &&
9967 + !isStartPatternElementAvailable(&MatchPatternDialog.currentStringPatterns))
9969 + if (!silent)
9971 + DialogF(
9972 + DF_WARN, MatchPatternDialog.mpdShell, 1,
9973 + contentTitle,
9974 + "Please specify min. 1 string pattern\nof type 'start'",
9975 + "OK");
9977 + XtFree(name);
9978 + return NULL;
9982 + if (MatchPatternDialog.currentDmptElement != NULL &&
9983 + MatchPatternDialog.currentDmptElement->dmpteType == MPT_SUB &&
9984 + strcmp(MatchPatternDialog.currentDmptElement->dmpteName, name) != 0)
9986 + renameMatchPatternInAllGroups(
9987 + MatchPatternDialog.currentDmptElement->dmpteName,
9988 + name);
9991 + newSeq =
9992 + (DialogMatchPatternSequenceElement *)XtMalloc(sizeof(DialogMatchPatternSequenceElement));
9994 + newSeq->dmpseName = name;
9995 + newSeq->dmpseValid = True;
9997 + if (isGroup)
9999 + newSeq->dmpseType = MPT_GROUP;
10001 + newGroup =
10002 + (DialogMatchPatternGroupElement *)XtMalloc(sizeof(DialogMatchPatternGroupElement));
10004 + newGroup->dmpgeName = XtNewString(name);
10006 + copyDialogPatternNamesToGroup(
10007 + &MatchPatternDialog.currentStringPatterns,
10008 + newGroup);
10010 + newSeq->dmpsePtr = (void *)newGroup;
10012 + else
10014 + if (XmToggleButtonGetState(MatchPatternDialog.mptbIndividualW))
10015 + newSeq->dmpseType = MPT_INDIVIDUAL;
10016 + else
10017 + newSeq->dmpseType = MPT_SUB;
10019 + newElement =
10020 + (DialogMatchPatternTableElement *)XtMalloc(sizeof(DialogMatchPatternTableElement));
10022 + newElement->dmpteName = XtNewString(name);
10023 + newElement->dmpteType = newSeq->dmpseType;
10025 + newElement->dmpteSkipBtwnStartEnd =
10026 + XmToggleButtonGetState(MatchPatternDialog.gabSkipBtwStartEndW);
10028 + newElement->dmpteFlash =
10029 + XmToggleButtonGetState(MatchPatternDialog.gabFlashW);
10031 + newElement->dmpteIgnoreHighLightInfo =
10032 + !XmToggleButtonGetState(MatchPatternDialog.gabSyntaxBasedW);
10034 + copyDialogStringPatterns(
10035 + &MatchPatternDialog.currentStringPatterns,
10036 + &newElement->dmptePatterns);
10038 + newSeq->dmpsePtr = (void *)newElement;
10041 + return newSeq;
10045 +** Check, if min. 1 string pattern of type 'start' is
10046 +** available within dialog.
10047 +** Returns True, if min. 1 start string pattern is
10048 +** populated in dialog.
10050 +static int isStartPatternElementAvailable(
10051 + DialogStringPatterns *dialogPatterns)
10053 + int i;
10055 + for (i=0; i < dialogPatterns->dspNumberOfPatterns; i++)
10057 + if (dialogPatterns->dspElements[i]->dspeKind == PEK_START)
10058 + return True;
10061 + return False;
10065 +** Read the string pattern fields of the string pattern frame and produce an
10066 +** allocated DialogStringPatternElement structure reflecting the contents.
10067 +** Pop up dialogs telling the user what's wrong (Passing "silent" as True,
10068 +** suppresses these dialogs).
10069 +** Returns NULL on error.
10071 +static DialogStringPatternElement *readStringPatternFrameFields(int silent)
10073 + char *stringPatText;
10074 + DialogStringPatternElement *newPatElement;
10075 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
10077 + if (isRelatedToGroup)
10079 + stringPatText = getSelectedSubPatternName();
10080 + if (strcmp(stringPatText, SPNM_NONE_SELECTED) == 0)
10082 + return NULL;
10085 + stringPatText = XtNewString(stringPatText);
10087 + else
10089 + stringPatText =
10090 + XmTextGetString(MatchPatternDialog.mpdStringPatternW);
10092 + if (stringPatText == NULL)
10094 + return NULL;
10096 + else if (*stringPatText == '\0')
10098 + if (!silent)
10100 + DialogF(
10101 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10102 + "String Pattern",
10103 + "Please specify string\npattern content",
10104 + "OK");
10105 + XmProcessTraversal(MatchPatternDialog.mpdStringPatternW, XmTRAVERSE_CURRENT);
10107 + XtFree(stringPatText);
10108 + return NULL;
10112 + newPatElement = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
10114 + newPatElement->dspeText = stringPatText;
10116 + if (isRelatedToGroup)
10118 + newPatElement->dspeKind = PEK_START;
10119 + newPatElement->dspeWordBoundary = PWB_NONE;
10120 + newPatElement->dspeCaseInsensitive = False;
10121 + newPatElement->dspeRegularExpression = False;
10123 + else
10125 + newPatElement->dspeRegularExpression =
10126 + XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
10128 + if (XmToggleButtonGetState(MatchPatternDialog.sptStartW))
10129 + newPatElement->dspeKind = PEK_START;
10130 + else if (XmToggleButtonGetState(MatchPatternDialog.sptMiddleW))
10131 + newPatElement->dspeKind = PEK_MIDDLE;
10132 + else
10133 + newPatElement->dspeKind = PEK_END;
10135 + if (newPatElement->dspeRegularExpression)
10136 + newPatElement->dspeWordBoundary = PWB_NONE;
10137 + else if (XmToggleButtonGetState(MatchPatternDialog.wbbBothW))
10138 + newPatElement->dspeWordBoundary = PWB_BOTH;
10139 + else if (XmToggleButtonGetState(MatchPatternDialog.wbbLeftW))
10140 + newPatElement->dspeWordBoundary = PWB_LEFT;
10141 + else if (XmToggleButtonGetState(MatchPatternDialog.wbbRightW))
10142 + newPatElement->dspeWordBoundary = PWB_RIGHT;
10143 + else
10144 + newPatElement->dspeWordBoundary = PWB_NONE;
10146 + newPatElement->dspeCaseInsensitive =
10147 + !XmToggleButtonGetState(MatchPatternDialog.sabCaseSensitiveW);
10150 + return newPatElement;
10154 +** Returns true if the pattern fields of the matching pattern dialog are set to
10155 +** the default ("New" pattern) state.
10157 +static int matchPatternDialogEmpty(void)
10159 + return
10160 + TextWidgetIsBlank(MatchPatternDialog.mpdMatchPatternNameW) &&
10161 + XmToggleButtonGetState(MatchPatternDialog.mptbIndividualW) &&
10162 + XmToggleButtonGetState(MatchPatternDialog.gabFlashW) &&
10163 + XmToggleButtonGetState(MatchPatternDialog.gabSyntaxBasedW) &&
10164 + stringPatternFrameEmpty();
10168 +** Returns true if the string pattern frame of the matching pattern dialog is set to
10169 +** the default state.
10171 +static int stringPatternFrameEmpty(void)
10173 + return
10174 + stringPatternFieldsEmpty(False) &&
10175 + MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0;
10179 +** Returns true if the string pattern fields of the string pattern frame are set to
10180 +** the default state.
10182 +static int stringPatternFieldsEmpty(
10183 + int strPatIsRelatedToGroup)
10185 + if (strPatIsRelatedToGroup)
10187 + return(
10188 + strcmp( getSelectedSubPatternName(), SPNM_NONE_SELECTED ) == 0);
10190 + else
10192 + return
10193 + TextWidgetIsBlank(MatchPatternDialog.mpdStringPatternW) &&
10194 + XmToggleButtonGetState(MatchPatternDialog.wbbBothW) &&
10195 + XmToggleButtonGetState(MatchPatternDialog.sabCaseSensitiveW) &&
10196 + !XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
10201 +** Get the current content of the matching pattern dialog.
10202 +** If the matching pattern is o.k., then update & apply it
10203 +** to any window which is currently using the matching pattern.
10204 +** If it's bad, then only report it.
10206 +static int getAndUpdateStringMatchTable(void)
10208 + StringMatchTable *newTable;
10209 + DMPTranslationResult translResult;
10211 + /*
10212 + * Get the current information displayed by the dialog. If it's bad,
10213 + * report it to the user & return.
10214 + */
10215 + newTable = getDialogStringMatchTable(&translResult);
10217 + if (newTable == NULL && translResult != DMPTR_EMPTY)
10219 + DialogF(
10220 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10221 + "Incomplete Matching Patterns for Language Mode",
10222 + "Incomplete matching patterns for language mode '%s'.\n"
10223 + "Please complete them first",
10224 + "OK",
10225 + MatchPatternDialog.mpdLangModeName);
10227 + return False;
10230 + /*
10231 + * change the matching pattern
10232 + */
10233 + updateStringMatchTable( newTable );
10235 + return True;
10239 +** Update the matching pattern set being edited in the matching pattern dialog
10240 +** with the information that the dialog is currently displaying, and
10241 +** apply changes to any window which is currently using the matching pattern.
10243 +static void updateStringMatchTable(
10244 + StringMatchTable *newTable)
10246 + WindowInfo *window;
10247 + int i;
10249 + /*
10250 + * Find the matching pattern being modified
10251 + */
10252 + for (i=0; i<NbrMatchTables; i++)
10254 + if (!strcmp(MatchPatternDialog.mpdLangModeName, MatchTables[i]->smtLanguageMode))
10256 + /*
10257 + * replace existing matching pattern
10258 + */
10259 + freeStringMatchTable(MatchTables[i]);
10260 + MatchTables[i] = newTable;
10261 + break;
10265 + if (i == NbrMatchTables)
10267 + /*
10268 + * new match table for language mode -> add it to end
10269 + */
10270 + MatchTables[NbrMatchTables++] = newTable;
10273 + /*
10274 + * Find windows that are currently using this matching pattern set and
10275 + * update this windows
10276 + */
10277 + for (window=WindowList; window!=NULL; window=window->next)
10279 + if ((window->languageMode == PLAIN_LANGUAGE_MODE &&
10280 + !strcmp(PLAIN_LM_STRING, newTable->smtLanguageMode)) ||
10281 + (window->languageMode != PLAIN_LANGUAGE_MODE &&
10282 + !strcmp(LanguageModeName(window->languageMode), newTable->smtLanguageMode)))
10284 + window->stringMatchTable = newTable;
10288 + /*
10289 + * Note that preferences have been changed
10290 + */
10291 + MarkPrefsChanged();
10294 +static StringMatchTable *getDialogStringMatchTable(
10295 + DMPTranslationResult *result)
10297 + int matchPatListIdx =
10298 + ManagedListSelectedIndex(MatchPatternDialog.mpdMatchPatternNamesListW);
10299 + int stringPatListIdx =
10300 + ManagedListSelectedIndex(MatchPatternDialog.mpdStringPatternsListW);
10302 + /*
10303 + * Get the current content of the matching pattern dialog fields
10304 + */
10305 + if (!UpdateManagedList(MatchPatternDialog.mpdStringPatternsListW, True))
10307 + *result = DMPTR_INCOMPLETE;
10309 + return NULL;
10312 + if (!UpdateManagedList(MatchPatternDialog.mpdMatchPatternNamesListW, True))
10314 + *result = DMPTR_INCOMPLETE;
10316 + return NULL;
10319 + SelectManagedListItem(MatchPatternDialog.mpdMatchPatternNamesListW, matchPatListIdx);
10320 + SelectManagedListItem(MatchPatternDialog.mpdStringPatternsListW, stringPatListIdx);
10322 + /*
10323 + * Translate dialog match table to string match table
10324 + */
10325 + return translateDialogStringMatchTable(&MatchPatternDialog.mpdTable, result);
10328 +static StringMatchTable *translateDialogStringMatchTable(
10329 + DialogMatchPatternInfo *dialogTable,
10330 + DMPTranslationResult *result)
10332 + ReadMatchPatternInfo readPatInfo;
10333 + DialogMatchPatternSequenceElement *seq;
10334 + MatchPatternTableElement *newPatElement;
10335 + MatchPatternGroupElement *newGroupElement;
10336 + char *errMsg;
10337 + ErrorInfo errInfo;
10338 + int i;
10340 + initErrorInfo(&errInfo);
10342 + readPatInfo.rmpiNbrOfElements = 0;
10343 + readPatInfo.rmpiNbrOfGroups = 0;
10344 + readPatInfo.rmpiNbrOfSeqElements = 0;
10345 + readPatInfo.rmpiAllPatRE = NULL;
10346 + readPatInfo.rmpiFlashPatRE = NULL;
10348 + /*
10349 + * if no dialog patterns are defined, return "empty" table
10350 + */
10351 + if (dialogTable->dmpiNbrOfSeqElements == 0)
10353 + *result = DMPTR_EMPTY;
10355 + return createStringMatchTable(
10356 + &readPatInfo,
10357 + XtNewString(MatchPatternDialog.mpdLangModeName));
10360 + /*
10361 + * translate dialog matching pattern elements
10362 + */
10363 + for (i=0; i < dialogTable->dmpiNbrOfSeqElements; i++)
10365 + seq = dialogTable->dmpiSequence[i];
10367 + if (seq->dmpseType == MPT_GROUP)
10369 + newGroupElement =
10370 + translateDialogMatchPatternGroupElement(
10371 + &readPatInfo,
10372 + (DialogMatchPatternGroupElement *)seq->dmpsePtr);
10374 + if (newGroupElement == NULL)
10376 + freeReadMatchPatternInfo(&readPatInfo);
10378 + *result = DMPTR_INCOMPLETE;
10380 + return NULL;
10383 + readPatInfo.rmpiGroup[readPatInfo.rmpiNbrOfGroups ++] =
10384 + newGroupElement;
10386 + recordPatternSequence(
10387 + &readPatInfo,
10388 + seq->dmpseName,
10389 + seq->dmpseType,
10390 + readPatInfo.rmpiNbrOfGroups-1 );
10392 + else
10394 + newPatElement =
10395 + translateDialogMatchPatternTableElement(
10396 + (DialogMatchPatternTableElement *)seq->dmpsePtr);
10398 + newPatElement->mpteIndex = readPatInfo.rmpiNbrOfElements;
10400 + readPatInfo.rmpiElement[readPatInfo.rmpiNbrOfElements ++] =
10401 + newPatElement;
10403 + if (newPatElement->mpteType == MPT_INDIVIDUAL)
10405 + if (!assignIndividualGroup(&readPatInfo, &errMsg, newPatElement))
10407 + DialogF(
10408 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10409 + "Assign reg. exp.",
10410 + "%s\n(Pattern: '%s')",
10411 + "OK",
10412 + errMsg,
10413 + newPatElement->mpteName);
10415 + freeReadMatchPatternInfo(&readPatInfo);
10417 + *result = DMPTR_INCOMPLETE;
10419 + return NULL;
10423 + treatDuplicatedMTEntries(readPatInfo.rmpiElement, readPatInfo.rmpiNbrOfElements);
10425 + recordPatternSequence(
10426 + &readPatInfo,
10427 + seq->dmpseName,
10428 + seq->dmpseType,
10429 + newPatElement->mpteIndex );
10433 + /*
10434 + * compile reg. expressions of "read" patterns
10435 + */
10436 + if (createRegExpOfPatterns( &readPatInfo, &errInfo ))
10438 + errInfo.eiLanguageMode = XtNewString(MatchPatternDialog.mpdLangModeName);
10439 + dialogMatchingPatternSetError(
10440 + "Assign all patterns reg. exp.",
10441 + &errInfo);
10443 + freeReadMatchPatternInfo(&readPatInfo);
10445 + *result = DMPTR_INCOMPLETE;
10447 + return NULL;
10450 + *result = DMPTR_OK;
10452 + return createStringMatchTable(
10453 + &readPatInfo,
10454 + XtNewString(MatchPatternDialog.mpdLangModeName));
10457 +static MatchPatternTableElement *translateDialogMatchPatternTableElement(
10458 + DialogMatchPatternTableElement *dialogElement)
10460 + MatchPatternTableElement *newElement;
10462 + newElement =
10463 + (MatchPatternTableElement *)XtMalloc(sizeof(MatchPatternTableElement));
10465 + newElement->mpteName = XtNewString(dialogElement->dmpteName);
10466 + newElement->mpteIndex = NO_ELEMENT_IDX;
10467 + newElement->mpteType = dialogElement->dmpteType;
10468 + newElement->mpteGroup = NO_GROUP_IDX;
10470 + translateDialogPatterns(&dialogElement->dmptePatterns, newElement);
10472 + newElement->mpteSkipBtwnStartEnd = dialogElement->dmpteSkipBtwnStartEnd;
10473 + newElement->mpteFlash = dialogElement->dmpteFlash;
10474 + newElement->mpteIgnoreHighLightInfo = dialogElement->dmpteIgnoreHighLightInfo;
10475 + newElement->mpteStartEndRE = NULL;
10477 + initGlobalBackRefList( newElement->mpteGlobalBackRef );
10479 + return newElement;
10482 +static void translateDialogPatterns(
10483 + DialogStringPatterns *dialogPatterns,
10484 + MatchPatternTableElement *newElement)
10486 + int sizeOfPat;
10487 + int i;
10489 + /*
10490 + * allocate memory for patterns
10491 + */
10492 + newElement->mpteAll.pesNumberOfPattern = dialogPatterns->dspNumberOfPatterns;
10494 + sizeOfPat =
10495 + sizeof(PatternElement *) * dialogPatterns->dspNumberOfPatterns;
10497 + newElement->mpteAll.pesPattern = (PatternElement **)XtMalloc(sizeOfPat);
10499 + /*
10500 + * assign dialog patterns to patterns of MatchPatternTableElement
10501 + */
10502 + for (i=0; i < dialogPatterns->dspNumberOfPatterns; i++)
10504 + newElement->mpteAll.pesPattern[i] =
10505 + createPatternElement(
10506 + XtNewString(dialogPatterns->dspElements[i]->dspeText),
10507 + dialogPatterns->dspElements[i]->dspeKind,
10508 + dialogPatterns->dspElements[i]->dspeWordBoundary,
10509 + dialogPatterns->dspElements[i]->dspeCaseInsensitive,
10510 + dialogPatterns->dspElements[i]->dspeRegularExpression);
10512 + newElement->mpteAll.pesPattern[i]->peIndex = i;
10515 + /*
10516 + * sort pattern elements into start, middle & end arrays
10517 + */
10518 + sortDialogPatternElementSet( &newElement->mpteAll, newElement );
10520 + /*
10521 + * determine mono pattern
10522 + */
10523 + if (newElement->mpteEnd.pesNumberOfPattern == 0)
10525 + newElement->mpteIsMonoPattern = True;
10527 + copyPatternSet( &newElement->mpteStart, &newElement->mpteEnd );
10529 + else
10531 + newElement->mpteIsMonoPattern = False;
10536 + * Sort dialog pattern element set into start, middle & end arrays.
10537 + */
10538 +static void sortDialogPatternElementSet(
10539 + PatternElementSet *allPat,
10540 + MatchPatternTableElement *result)
10542 + int sizeOfPat;
10544 + /*
10545 + * count number of start, middle & end pattern elements
10546 + */
10547 + countPatternElementKind( allPat, result );
10549 + /*
10550 + * allocate pattern elements
10551 + */
10552 + sizeOfPat = sizeof(PatternElement *) * result->mpteStart.pesNumberOfPattern;
10553 + result->mpteStart.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
10555 + if (result->mpteMiddle.pesNumberOfPattern != 0)
10557 + sizeOfPat = sizeof(PatternElement *) * result->mpteMiddle.pesNumberOfPattern;
10558 + result->mpteMiddle.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
10561 + if (result->mpteEnd.pesNumberOfPattern != 0)
10563 + sizeOfPat = sizeof(PatternElement *) * result->mpteEnd.pesNumberOfPattern;
10564 + result->mpteEnd.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
10567 + /*
10568 + * sort pattern elements into start, middle & end arrays
10569 + */
10570 + sortPatternElementSet( allPat, result );
10573 +static MatchPatternGroupElement *translateDialogMatchPatternGroupElement(
10574 + ReadMatchPatternInfo *info,
10575 + DialogMatchPatternGroupElement *dialogGroup)
10577 + int i;
10578 + int error = False;
10579 + MatchPatternTableElement *subPatElement;
10580 + int sizeOfIds;
10581 + MatchPatternGroupElement *group;
10583 + /*
10584 + * Allocate memory for the matching pattern group. Copy name & number of
10585 + * sub patterns.
10586 + */
10587 + group =
10588 + (MatchPatternGroupElement *)XtMalloc( sizeof(MatchPatternGroupElement) );
10590 + group->mpgeName = XtNewString(dialogGroup->dmpgeName);
10591 + group->mpgeNumberOfSubPatterns = dialogGroup->dmpgeNumberOfSubPatterns;
10592 + group->mpgeKeywordRE = NULL;
10594 + /*
10595 + * Allocate memory for the sub-matching pattern IDs
10596 + */
10597 + sizeOfIds = sizeof(char *) * group->mpgeNumberOfSubPatterns;
10598 + group->mpgeSubPatternIds = (char **)XtMalloc( sizeOfIds );
10600 + for (i=0; i < group->mpgeNumberOfSubPatterns; i ++)
10602 + /*
10603 + * Remember sub-matching pattern ID
10604 + */
10605 + group->mpgeSubPatternIds[i] = XtNewString(dialogGroup->dmpgeSubPatternIds[i]);
10607 + /*
10608 + * Assign the index of this group to the sub-matching pattern
10609 + * if no group index was assigned before.
10610 + */
10611 + subPatElement =
10612 + getPatternOfName( info, dialogGroup->dmpgeSubPatternIds[i]);
10614 + if (subPatElement == NULL)
10616 + DialogF(
10617 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10618 + "Group Compilation",
10619 + "Group '%s':\nsub-matching pattern '%s' not defined before",
10620 + "OK",
10621 + group->mpgeName,
10622 + dialogGroup->dmpgeSubPatternIds[i]);
10624 + error = True;
10626 + else
10628 + if (subPatElement->mpteGroup == NO_GROUP_IDX)
10630 + subPatElement->mpteGroup = info->rmpiNbrOfGroups;
10635 + if (error)
10637 + freeMatchPatternGroupElement(group);
10639 + return NULL;
10642 + return group;
10645 +static int stringMatchTableDiffer(
10646 + StringMatchTable *oldTable,
10647 + StringMatchTable *newTable)
10649 + int i, j;
10650 + MatchPatternTable *oldPatTab = oldTable->smtAllPatterns;
10651 + MatchPatternTable *newPatTab = newTable->smtAllPatterns;
10652 + MatchPatternTableElement *oldPat;
10653 + MatchPatternTableElement *newPat;
10654 + MatchPatternGroupElement *oldGroup;
10655 + MatchPatternGroupElement *newGroup;
10656 + MatchPatternSequenceElement *oldSeq;
10657 + MatchPatternSequenceElement *newSeq;
10659 + if (oldTable->smtNumberOfSeqElements != newTable->smtNumberOfSeqElements)
10660 + return True;
10662 + for (i=0; i < oldTable->smtNumberOfSeqElements; i++)
10664 + oldSeq = oldTable->smtSequence[i];
10665 + newSeq = newTable->smtSequence[i];
10667 + if (AllocatedStringsDiffer(oldSeq->mpseName, newSeq->mpseName))
10668 + return True;
10669 + if (oldSeq->mpseType != newSeq->mpseType)
10670 + return True;
10672 + if (oldSeq->mpseType == MPT_GROUP)
10674 + oldGroup = oldTable->smtGroups[oldSeq->mpseIndex];
10675 + newGroup = newTable->smtGroups[newSeq->mpseIndex];
10677 + if (AllocatedStringsDiffer(oldGroup->mpgeName, newGroup->mpgeName))
10678 + return True;
10680 + if (oldGroup->mpgeNumberOfSubPatterns != newGroup->mpgeNumberOfSubPatterns)
10681 + return True;
10683 + for (j=0; j < oldGroup->mpgeNumberOfSubPatterns; j++)
10685 + if (AllocatedStringsDiffer(
10686 + oldGroup->mpgeSubPatternIds[j],
10687 + newGroup->mpgeSubPatternIds[j]))
10688 + return True;
10691 + else
10693 + oldPat = oldPatTab->mptElements[oldSeq->mpseIndex];
10694 + newPat = newPatTab->mptElements[newSeq->mpseIndex];
10696 + if (AllocatedStringsDiffer(oldPat->mpteName, newPat->mpteName))
10697 + return True;
10699 + if (oldPat->mpteType != newPat->mpteType)
10700 + return True;
10702 + if (oldPat->mpteGroup != newPat->mpteGroup)
10703 + return True;
10705 + if (oldPat->mpteAll.pesNumberOfPattern != newPat->mpteAll.pesNumberOfPattern)
10706 + return True;
10708 + for (j=0; j < oldPat->mpteAll.pesNumberOfPattern; j ++)
10710 + if (patternElementDiffer(
10711 + oldPat->mpteAll.pesPattern[j], oldPatTab,
10712 + newPat->mpteAll.pesPattern[j], newPatTab ) )
10713 + return True;
10716 + if (oldPat->mpteIsMonoPattern != newPat->mpteIsMonoPattern)
10717 + return True;
10719 + if (oldPat->mpteSkipBtwnStartEnd != newPat->mpteSkipBtwnStartEnd)
10720 + return True;
10722 + if (oldPat->mpteIgnoreHighLightInfo != newPat->mpteIgnoreHighLightInfo)
10723 + return True;
10725 + if (oldPat->mpteFlash != newPat->mpteFlash)
10726 + return True;
10730 + return False;
10733 +static int patternElementDiffer(
10734 + PatternElement *oldPE,
10735 + MatchPatternTable *oldTab,
10736 + PatternElement *newPE,
10737 + MatchPatternTable *newTab)
10739 + StringPattern *oldSP;
10740 + StringPattern *newSP;
10742 + oldSP = GetStringPattern(oldTab, oldPE);
10743 + newSP = GetStringPattern(newTab, newPE);
10745 + if (AllocatedStringsDiffer(oldSP->spText, newSP->spText))
10746 + return True;
10747 + if (AllocatedStringsDiffer(oldSP->spOrigText, newSP->spOrigText))
10748 + return True;
10749 + if (oldPE->peKind != newPE->peKind)
10750 + return True;
10751 + if (oldSP->spWordBoundary != newSP->spWordBoundary)
10752 + return True;
10753 + if (oldSP->spCaseInsensitive != newSP->spCaseInsensitive)
10754 + return True;
10755 + if (oldSP->spRegularExpression != newSP->spRegularExpression)
10756 + return True;
10758 + return False;
10761 +static DialogMatchPatternGroupElement *getDialogGroupUsingMatchPattern(
10762 + char *matchPatternName)
10764 + DialogMatchPatternSequenceElement *seq;
10765 + DialogMatchPatternGroupElement *group;
10766 + int i, j;
10768 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10770 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
10772 + if (seq->dmpseType == MPT_GROUP)
10774 + group = (DialogMatchPatternGroupElement *)seq->dmpsePtr;
10776 + for (j=0; j < group->dmpgeNumberOfSubPatterns; j ++)
10778 + if (strcmp(group->dmpgeSubPatternIds[j], matchPatternName) == 0)
10779 + return group;
10784 + return NULL;
10787 +static void removeMatchPatternFromGroup(
10788 + char *matchPatternName,
10789 + DialogMatchPatternGroupElement *group)
10791 + int i;
10793 + for (i=0; i < group->dmpgeNumberOfSubPatterns; i ++)
10795 + if (strcmp(group->dmpgeSubPatternIds[i], matchPatternName) == 0)
10797 + /*
10798 + * remove existing matching pattern name from sub-pattern list
10799 + */
10800 + freeXtPtr((void **)&group->dmpgeSubPatternIds[i]);
10801 + memmove(
10802 + &group->dmpgeSubPatternIds[i],
10803 + &group->dmpgeSubPatternIds[i+1],
10804 + (group->dmpgeNumberOfSubPatterns-1 - i) * sizeof(char *));
10805 + group->dmpgeNumberOfSubPatterns --;
10807 + return;
10812 +static void removeMatchPatternFromAllGroups(
10813 + char *matchPatternName)
10815 + DialogMatchPatternSequenceElement *seq;
10816 + DialogMatchPatternGroupElement *group;
10817 + int i;
10819 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10821 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
10823 + if (seq->dmpseType == MPT_GROUP)
10825 + group = (DialogMatchPatternGroupElement *)seq->dmpsePtr;
10827 + removeMatchPatternFromGroup(matchPatternName, group);
10832 +static void renameMatchPatternInGroup(
10833 + char *oldMatchPatternName,
10834 + char *newMatchPatternName,
10835 + DialogMatchPatternGroupElement *group)
10837 + int i;
10839 + for (i=0; i < group->dmpgeNumberOfSubPatterns; i ++)
10841 + if (strcmp(group->dmpgeSubPatternIds[i], oldMatchPatternName) == 0)
10843 + /*
10844 + * rename existing matching pattern name in sub-pattern list
10845 + */
10846 + freeXtPtr((void **)&group->dmpgeSubPatternIds[i]);
10848 + group->dmpgeSubPatternIds[i] =
10849 + XtNewString(newMatchPatternName);
10851 + return;
10856 +static void renameMatchPatternInAllGroups(
10857 + char *oldMatchPatternName,
10858 + char *newMatchPatternName)
10860 + DialogMatchPatternSequenceElement *seq;
10861 + DialogMatchPatternGroupElement *group;
10862 + int i;
10864 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10866 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
10868 + if (seq->dmpseType == MPT_GROUP)
10870 + group = (DialogMatchPatternGroupElement *)seq->dmpsePtr;
10872 + renameMatchPatternInGroup(
10873 + oldMatchPatternName,
10874 + newMatchPatternName,
10875 + group);
10880 +static void freeVariableDialogData(
10881 + int keepLanguageModeName)
10883 + int i;
10885 + if (!keepLanguageModeName)
10886 + freeXtPtr((void **)&MatchPatternDialog.mpdLangModeName);
10888 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10890 + freeDialogSequenceElement(
10891 + MatchPatternDialog.mpdTable.dmpiSequence[i] );
10894 + MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements = 0;
10896 + freeDialogStringPatterns(
10897 + &MatchPatternDialog.currentStringPatterns);
10900 +static void initGlobalBackRefList(
10901 + GlobalBackRefElement *list)
10903 + int i;
10905 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
10907 + list[i].gbreDefByStrPat = NULL;
10908 + list[i].gbreRegExpText = NULL;
10912 +static void initStrPatBackRefList(
10913 + StringPattern *strPat)
10915 + int i;
10917 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
10919 + strPat->spOwnGlobalBackRef[i].spbreRegExpText = NULL;
10920 + strPat->spOwnGlobalBackRef[i].spbreLocalBackRefID = NO_LOCAL_BACK_REF_ID;
10922 + strPat->spGlobalToLocalBackRef[i] = NO_LOCAL_BACK_REF_ID;
10926 +static void initErrorInfo(
10927 + ErrorInfo *errInfo)
10929 + errInfo->eiDetail = NULL;
10930 + errInfo->eiLanguageMode = NULL;
10931 + errInfo->eiMPTabElementName = NULL;
10932 + errInfo->eiStringPatText = NULL;
10933 + errInfo->eiRegExpCompileMsg = NULL;
10934 + errInfo->eiBackRefNbr = 0;
10937 +static void freeErrorInfo(
10938 + ErrorInfo *errInfo)
10940 + freeXtPtr((void **)&errInfo->eiLanguageMode);
10941 + freeXtPtr((void **)&errInfo->eiMPTabElementName);
10942 + freeXtPtr((void **)&errInfo->eiStringPatText);
10945 +static void freeXtPtr(void **ptr)
10947 + if (*ptr != NULL)
10949 + XtFree((char *)*ptr);
10950 + *ptr = NULL;
10954 +static void freePtr(void **ptr)
10956 + if (*ptr != NULL)
10958 + free((char *)*ptr);
10959 + *ptr = NULL;
10962 diff --quilt /dev/null new/source/patternMatchData.h
10963 --- /dev/null
10964 +++ new/source/patternMatchData.h
10965 @@ -0,0 +1,24 @@
10966 +/* $Id: patternMatchData.h,v 1.3 2003/12/12 16:45:25 uleh Exp $ */
10968 +#ifndef NEDIT_PATTERNMATCHDATA_H_INCLUDED
10969 +#define NEDIT_PATTERNMATCHDATA_H_INCLUDED
10971 +void *FindStringMatchTable(const char *langModeName);
10973 +void RenameStringMatchTable(const char *oldName, const char *newName);
10975 +void DeleteStringMatchTable(const char *langModeName);
10977 +void AssignStandardStringMatchTable(const char *langModeName);
10979 +int LMHasStringMatchTable(const char *languageMode);
10981 +int LoadMatchPatternString(char *inString);
10983 +char *WriteMatchPatternString(void);
10985 +void EditMatchPatterns(WindowInfo *window);
10987 +void UpdateLanguageModeMenuMatchPattern(void);
10989 +#endif /* NEDIT_PATTERNMATCHDATA_H_INCLUDED */
10990 diff --quilt old/source/preferences.c new/source/preferences.c
10991 --- old/source/preferences.c
10992 +++ new/source/preferences.c
10993 @@ -47,6 +47,10 @@ static const char CVSID[] = "$Id: prefer
10994 #include "windowTitle.h"
10995 #include "server.h"
10996 #include "tags.h"
10998 +/* Pattern Match Feature */
10999 +#include "patternMatchData.h"
11001 #include "../util/prefFile.h"
11002 #include "../util/misc.h"
11003 #include "../util/DialogF.h"
11004 @@ -280,7 +284,6 @@ static struct prefData {
11005 int emTabDist; /* non-zero tab dist. if emulated tabs are on */
11006 int insertTabs; /* whether to use tabs for padding */
11007 int showMatchingStyle; /* how to flash matching parenthesis */
11008 - int matchSyntaxBased; /* use syntax info to match parenthesis */
11009 int highlightSyntax; /* whether to highlight syntax by default */
11010 int smartTags; /* look for tag in current window first */
11011 int alwaysCheckRelativeTagsSpecs; /* for every new opened file of session */
11012 @@ -350,6 +353,7 @@ static struct {
11013 char *smartIndent;
11014 char *smartIndentCommon;
11015 char *shell;
11016 + char *matchPattern;
11017 } TempStringPrefs;
11019 /* preference descriptions for SavePreferences and RestorePreferences. */
11020 @@ -855,6 +859,72 @@ static PrefDescripRec PrefDescrip[] = {
11021 Matlab:Default", &TempStringPrefs.smartIndent, NULL, True},
11022 {"smartIndentInitCommon", "SmartIndentInitCommon", PREF_ALLOC_STRING,
11023 "Default", &TempStringPrefs.smartIndentCommon, NULL, True},
11024 +/* Pattern Match Feature: matchPatterns resource added */
11025 +#ifdef VMS
11026 +/* The VAX compiler can't compile Java-Script's definition in highlightData.c */
11027 + {"matchPatterns", "MatchPatterns", PREF_ALLOC_STRING,
11028 + "PLAIN:Default\n\
11029 + Ada:Default\n\
11030 + Awk:Default\n\
11031 + C++:Default\n\
11032 + C:Default\n\
11033 + CSS:Default\n\
11034 + Csh:Default\n\
11035 + Fortran:Default\n\
11036 + Java:Default\n\
11037 + LaTeX:Default\n\
11038 + Lex:Default\n\
11039 + Makefile:Default\n\
11040 + Matlab:Default\n\
11041 + NEdit Macro:Default\n\
11042 + Pascal:Default\n\
11043 + Perl:Default\n\
11044 + PostScript:Default\n\
11045 + Python:Default\n\
11046 + Regex:Default\n\
11047 + SGML HTML:Default\n\
11048 + SQL:Default\n\
11049 + Sh Ksh Bash:Default\n\
11050 + Tcl:Default\n\
11051 + VHDL:Default\n\
11052 + Verilog:Default\n\
11053 + XML:Default\n\
11054 + X Resources:Default\n\
11055 + Yacc:Default\n",
11056 + &TempStringPrefs.matchPattern, NULL, True},
11057 +#else
11058 + {"matchPatterns", "MatchPatterns", PREF_ALLOC_STRING,
11059 + "PLAIN:Default\n\
11060 + Ada:Default\n\
11061 + Awk:Default\n\
11062 + C++:Default\n\
11063 + C:Default\n\
11064 + CSS:Default\n\
11065 + Csh:Default\n\
11066 + Fortran:Default\n\
11067 + Java:Default\n\
11068 + JavaScript:Default\n\
11069 + LaTeX:Default\n\
11070 + Lex:Default\n\
11071 + Makefile:Default\n\
11072 + Matlab:Default\n\
11073 + NEdit Macro:Default\n\
11074 + Pascal:Default\n\
11075 + Perl:Default\n\
11076 + PostScript:Default\n\
11077 + Python:Default\n\
11078 + Regex:Default\n\
11079 + SGML HTML:Default\n\
11080 + SQL:Default\n\
11081 + Sh Ksh Bash:Default\n\
11082 + Tcl:Default\n\
11083 + VHDL:Default\n\
11084 + Verilog:Default\n\
11085 + XML:Default\n\
11086 + X Resources:Default\n\
11087 + Yacc:Default\n",
11088 + &TempStringPrefs.matchPattern, NULL, True},
11089 +#endif
11090 {"autoWrap", "AutoWrap", PREF_ENUM, "Continuous",
11091 &PrefData.wrapStyle, AutoWrapTypes, True},
11092 {"wrapMargin", "WrapMargin", PREF_INT, "0",
11093 @@ -871,8 +941,6 @@ static PrefDescripRec PrefDescrip[] = {
11094 &PrefData.saveOldVersion, NULL, True},
11095 {"showMatching", "ShowMatching", PREF_ENUM, "Delimiter",
11096 &PrefData.showMatchingStyle, ShowMatchingTypes, True},
11097 - {"matchSyntaxBased", "MatchSyntaxBased", PREF_BOOLEAN, "True",
11098 - &PrefData.matchSyntaxBased, NULL, True},
11099 {"highlightSyntax", "HighlightSyntax", PREF_BOOLEAN, "True",
11100 &PrefData.highlightSyntax, NULL, True},
11101 {"backlightChars", "BacklightChars", PREF_BOOLEAN, "False",
11102 @@ -1245,6 +1313,7 @@ static void lmApplyCB(Widget w, XtPointe
11103 static void lmCloseCB(Widget w, XtPointer clientData, XtPointer callData);
11104 static int lmDeleteConfirmCB(int itemIndex, void *cbArg);
11105 static int updateLMList(void);
11106 +static int isOldLanguageMode(const char *lmDialogName, const char *oldModeName);
11107 static languageModeRec *copyLanguageModeRec(languageModeRec *lm);
11108 static void *lmGetDisplayedCB(void *oldItem, int explicitRequest, int *abort,
11109 void *cbArg);
11110 @@ -1427,6 +1496,11 @@ static void translatePrefFormats(int con
11111 XtFree(TempStringPrefs.smartIndentCommon);
11112 TempStringPrefs.smartIndentCommon = NULL;
11114 + if (TempStringPrefs.matchPattern != NULL) {
11115 + LoadMatchPatternString(TempStringPrefs.matchPattern);
11116 + XtFree(TempStringPrefs.matchPattern);
11117 + TempStringPrefs.matchPattern = NULL;
11120 /* translate the font names into fontLists suitable for the text widget */
11121 font = XLoadQueryFont(TheDisplay, PrefData.fontString);
11122 @@ -1506,6 +1580,7 @@ void SaveNEditPrefs(Widget parent, int q
11123 TempStringPrefs.styles = WriteStylesString();
11124 TempStringPrefs.smartIndent = WriteSmartIndentString();
11125 TempStringPrefs.smartIndentCommon = WriteSmartIndentCommonString();
11126 + TempStringPrefs.matchPattern = WriteMatchPatternString();
11127 strcpy(PrefData.fileVersion, PREF_FILE_VERSION);
11129 if (!SavePreferences(XtDisplay(parent), prefFileName, HeaderText,
11130 @@ -1525,6 +1600,7 @@ void SaveNEditPrefs(Widget parent, int q
11131 XtFree(TempStringPrefs.styles);
11132 XtFree(TempStringPrefs.smartIndent);
11133 XtFree(TempStringPrefs.smartIndentCommon);
11134 + XtFree(TempStringPrefs.matchPattern);
11136 PrefsHaveChanged = False;
11138 @@ -1920,16 +1996,6 @@ int GetPrefShowMatching(void)
11139 return PrefData.showMatchingStyle;
11142 -void SetPrefMatchSyntaxBased(int state)
11144 - setIntPref(&PrefData.matchSyntaxBased, state);
11147 -int GetPrefMatchSyntaxBased(void)
11149 - return PrefData.matchSyntaxBased;
11152 void SetPrefHighlightSyntax(Boolean state)
11154 setIntPref(&PrefData.highlightSyntax, state);
11155 @@ -3478,6 +3544,21 @@ static int lmDeleteConfirmCB(int itemInd
11156 return False;
11159 + /* Pattern Match Feature: don't allow deletion if data will be lost */
11160 + if (LMHasStringMatchTable(LMDialog.languageModeList[itemIndex]->name))
11162 + DialogF(DF_WARN, LMDialog.shell, 1, "Matching Patterns exist",
11163 + "This language mode has matching patterns\n"
11164 + "defined. Please delete the patterns first,\n"
11165 + "in Preferences -> Default Settings ->\n"
11166 + "Show Matching (..) -> Matching Patterns ..,\n"
11167 + "before proceeding here.", "Dismiss");
11168 + return False;
11171 + /* delete "empty" string match table related to language mode to be deleted */
11172 + DeleteStringMatchTable(LMDialog.languageModeList[itemIndex]->name);
11174 return True;
11177 @@ -3498,15 +3579,15 @@ static int updateLMList(void)
11178 return False;
11180 /* Fix up language mode indices in all open windows (which may change
11181 - if the currently selected mode is deleted or has changed position),
11182 - and update word delimiters */
11183 + if the currently selected mode is renamed, deleted or has changed
11184 + position), and update word delimiters */
11185 for (window=WindowList; window!=NULL; window=window->next) {
11186 if (window->languageMode != PLAIN_LANGUAGE_MODE) {
11187 oldLanguageMode = window->languageMode;
11188 oldModeName = LanguageModes[window->languageMode]->name;
11189 window->languageMode = PLAIN_LANGUAGE_MODE;
11190 for (i=0; i<LMDialog.nLanguageModes; i++) {
11191 - if (!strcmp(oldModeName, LMDialog.languageModeList[i]->name)) {
11192 + if (isOldLanguageMode(LMDialog.languageModeList[i]->name, oldModeName)) {
11193 newDelimiters = LMDialog.languageModeList[i]->delimiters;
11194 if (newDelimiters == NULL)
11195 newDelimiters = GetPrefDelimiters();
11196 @@ -3536,6 +3617,7 @@ static int updateLMList(void)
11197 *strchr(LMDialog.languageModeList[i]->name, ':') = '\0';
11198 RenameHighlightPattern(LMDialog.languageModeList[i]->name, newName);
11199 RenameSmartIndentMacros(LMDialog.languageModeList[i]->name, newName);
11200 + RenameStringMatchTable(LMDialog.languageModeList[i]->name, newName);
11201 memmove(LMDialog.languageModeList[i]->name, newName,
11202 strlen(newName) + 1);
11203 ChangeManagedListData(LMDialog.managedListW);
11204 @@ -3553,13 +3635,24 @@ static int updateLMList(void)
11205 user menu items */
11206 UpdateUserMenuInfo();
11208 + /* Pattern Match Feature: assign standard string match table to new
11209 + language modes */
11210 + for (i=0; i<NLanguageModes; i++) {
11211 + if (FindStringMatchTable(LanguageModeName(i)) == NULL)
11212 + AssignStandardStringMatchTable(LanguageModeName(i));
11215 /* Update the menus in the window menu bars and load any needed
11216 - calltips files */
11217 + calltips files and reassign string match tables */
11218 for (window=WindowList; window!=NULL; window=window->next) {
11219 updateLanguageModeSubmenu(window);
11220 if (window->languageMode != PLAIN_LANGUAGE_MODE &&
11221 LanguageModes[window->languageMode]->defTipsFile != NULL)
11222 AddTagsFile(LanguageModes[window->languageMode]->defTipsFile, TIP);
11224 + window->stringMatchTable =
11225 + FindStringMatchTable(LanguageModeName(window->languageMode));
11227 /* cache user menus: Rebuild all user menus of this window */
11228 RebuildAllMenus(window);
11230 @@ -3568,12 +3661,32 @@ static int updateLMList(void)
11231 UpdateLanguageModeMenu();
11232 /* The same for the smart indent macro dialog */
11233 UpdateLangModeMenuSmartIndent();
11234 + /* The same for the match pattern dialog */
11235 + UpdateLanguageModeMenuMatchPattern();
11236 /* Note that preferences have been changed */
11237 MarkPrefsChanged();
11239 return True;
11243 +** Returns true, if the given old language mode name matches the
11244 +** given (new) language mode dialog name.
11246 +static int isOldLanguageMode(const char *lmDialogName, const char *oldModeName)
11248 + char *c = strchr(lmDialogName, ':');
11249 + int isOldMode = !strcmp(oldModeName, lmDialogName);
11251 + if (!isOldMode && c != NULL) {
11252 + *c = '\0';
11253 + isOldMode = !strcmp(lmDialogName, oldModeName);
11254 + *c = ':';
11257 + return isOldMode;
11260 static void *lmGetDisplayedCB(void *oldItem, int explicitRequest, int *abort,
11261 void *cbArg)
11263 @@ -4567,6 +4680,10 @@ static void reapplyLanguageMode(WindowIn
11264 DeleteTagsFile( LanguageModes[oldMode]->defTipsFile, TIP, False );
11267 + /* Pattern Match Feature: Assign the match pattern related to
11268 + the language mode */
11269 + window->stringMatchTable = FindStringMatchTable(LanguageModeName(mode));
11271 /* Set delimiters for all text widgets */
11272 if (mode == PLAIN_LANGUAGE_MODE || LanguageModes[mode]->delimiters == NULL)
11273 delimiters = GetPrefDelimiters();
11274 @@ -5184,14 +5301,31 @@ char *ReadSymbolicFieldTextWidget(Widget
11276 ** Create a pulldown menu pane with the names of the current language modes.
11277 ** XmNuserData for each item contains the language mode name.
11278 +** Pattern Match Feature: if "includePlain" is set, then 1st menu entry
11279 +** holds "PLAIN".
11281 -Widget CreateLanguageModeMenu(Widget parent, XtCallbackProc cbProc, void *cbArg)
11282 +Widget CreateLanguageModeMenu(
11283 + Widget parent,
11284 + XtCallbackProc cbProc,
11285 + void *cbArg,
11286 + int includePlain)
11288 Widget menu, btn;
11289 int i;
11290 XmString s1;
11292 menu = CreatePulldownMenu(parent, "languageModes", NULL, 0);
11294 + if (includePlain) {
11295 + btn = XtVaCreateManagedWidget("languageMode", xmPushButtonGadgetClass,
11296 + menu,
11297 + XmNlabelString, s1=XmStringCreateSimple("PLAIN"),
11298 + XmNmarginHeight, 0,
11299 + XmNuserData, (void *)"PLAIN", NULL);
11300 + XmStringFree(s1);
11301 + XtAddCallback(btn, XmNactivateCallback, cbProc, cbArg);
11304 for (i=0; i<NLanguageModes; i++) {
11305 btn = XtVaCreateManagedWidget("languageMode", xmPushButtonGadgetClass,
11306 menu,
11307 diff --quilt old/source/preferences.h new/source/preferences.h
11308 --- old/source/preferences.h
11309 +++ new/source/preferences.h
11310 @@ -111,8 +111,6 @@ void SetPrefInsertTabs(int state);
11311 int GetPrefInsertTabs(void);
11312 void SetPrefShowMatching(int state);
11313 int GetPrefShowMatching(void);
11314 -void SetPrefMatchSyntaxBased(int state);
11315 -int GetPrefMatchSyntaxBased(void);
11316 void SetPrefHighlightSyntax(Boolean state);
11317 Boolean GetPrefHighlightSyntax(void);
11318 void SetPrefBacklightChars(int state);
11319 @@ -192,7 +190,7 @@ int FindLanguageMode(const char *languag
11320 void UnloadLanguageModeTipsFile(WindowInfo *window);
11321 void DetermineLanguageMode(WindowInfo *window, int forceNewDefaults);
11322 Widget CreateLanguageModeMenu(Widget parent, XtCallbackProc cbProc,
11323 - void *cbArg);
11324 + void *cbArg, int includePlain);
11325 void SetLangModeMenu(Widget optMenu, const char *modeName);
11326 void CreateLanguageModeSubMenu(WindowInfo* window, const Widget parent,
11327 const char* name, const char* label, const char mnemonic);
11328 diff --quilt old/source/search.c new/source/search.c
11329 --- old/source/search.c
11330 +++ new/source/search.c
11331 @@ -85,6 +85,7 @@ static const char CVSID[] = "$Id: search
11332 #include "../debug.h"
11333 #endif
11335 +#include "patternMatch.h"
11337 int NHist = 0;
11339 @@ -173,6 +174,7 @@ static void checkMultiReplaceListForDoom
11340 WindowInfo* doomedWindow);
11341 static void removeDoomedWindowFromList(WindowInfo* window, int index);
11342 static void unmanageReplaceDialogs(const WindowInfo *window);
11343 +static int getPosForMatchingCharacter(WindowInfo *window);
11344 static void flashTimeoutProc(XtPointer clientData, XtIntervalId *id);
11345 static void eraseFlash(WindowInfo *window);
11346 static int getReplaceDlogInfo(WindowInfo *window, int *direction,
11347 @@ -213,9 +215,6 @@ static void resetReplaceTabGroup(WindowI
11348 static int searchMatchesSelection(WindowInfo *window, const char *searchString,
11349 int searchType, int *left, int *right, int *searchExtentBW,
11350 int *searchExtentFW);
11351 -static int findMatchingChar(WindowInfo *window, char toMatch,
11352 - void *toMatchStyle, int charPos, int startLimit, int endLimit,
11353 - int *matchPos);
11354 static Boolean replaceUsingRE(const char* searchStr, const char* replaceStr,
11355 const char* sourceStr, int beginPos, char* destStr, int maxDestLen,
11356 int prevChar, const char* delimiters, int defaultFlags);
11357 @@ -253,24 +252,6 @@ typedef struct _charMatchTable {
11358 char direction;
11359 } charMatchTable;
11361 -#define N_MATCH_CHARS 13
11362 -#define N_FLASH_CHARS 6
11363 -static charMatchTable MatchingChars[N_MATCH_CHARS] = {
11364 - {'{', '}', SEARCH_FORWARD},
11365 - {'}', '{', SEARCH_BACKWARD},
11366 - {'(', ')', SEARCH_FORWARD},
11367 - {')', '(', SEARCH_BACKWARD},
11368 - {'[', ']', SEARCH_FORWARD},
11369 - {']', '[', SEARCH_BACKWARD},
11370 - {'<', '>', SEARCH_FORWARD},
11371 - {'>', '<', SEARCH_BACKWARD},
11372 - {'/', '/', SEARCH_FORWARD},
11373 - {'"', '"', SEARCH_FORWARD},
11374 - {'\'', '\'', SEARCH_FORWARD},
11375 - {'`', '`', SEARCH_FORWARD},
11376 - {'\\', '\\', SEARCH_FORWARD},
11380 ** Definitions for the search method strings, used as arguments for
11381 ** macro search subroutines and search action routines
11382 @@ -3342,18 +3323,18 @@ static void iSearchTextKeyEH(Widget w, W
11386 -** Check the character before the insertion cursor of textW and flash
11387 -** matching parenthesis, brackets, or braces, by temporarily highlighting
11388 -** the matching character (a timer procedure is scheduled for removing the
11389 -** highlights)
11390 +** Check the characters before the insertion cursor of textW and flash
11391 +** matching patterns (parenthesis e.g. brackets, braces ..) by temporarily
11392 +** highlighting matching characters (a timer procedure is scheduled for
11393 +** removing the highlights)
11395 void FlashMatching(WindowInfo *window, Widget textW)
11397 - char c;
11398 - void *style;
11399 - int pos, matchIndex;
11400 - int startPos, endPos, searchPos, matchPos;
11401 + int pos;
11402 + int direction;
11403 + int startPos, endPos, matchPos, matchLen;
11404 int constrain;
11405 + MatchingType matchingType;
11407 /* if a marker is already drawn, erase it and cancel the timeout */
11408 if (window->flashTimeoutID != 0) {
11409 @@ -3371,48 +3352,43 @@ void FlashMatching(WindowInfo *window, W
11410 if (window->buffer->primary.selected)
11411 return;
11413 - /* get the character to match and the position to start from */
11414 - pos = TextGetCursorPos(textW) - 1;
11415 + /* get the position to start from */
11416 + pos = TextGetCursorPos(textW);
11417 if (pos < 0)
11418 return;
11419 - c = BufGetCharacter(window->buffer, pos);
11420 - style = GetHighlightInfo(window, pos);
11422 - /* is the character one we want to flash? */
11423 - for (matchIndex = 0; matchIndex<N_FLASH_CHARS; matchIndex++) {
11424 - if (MatchingChars[matchIndex].c == c)
11425 - break;
11427 - if (matchIndex == N_FLASH_CHARS)
11428 - return;
11430 /* constrain the search to visible text only when in single-pane mode
11431 AND using delimiter flashing (otherwise search the whole buffer) */
11432 constrain = ((window->nPanes == 0) &&
11433 (window->showMatchingStyle == FLASH_DELIMIT));
11435 - if (MatchingChars[matchIndex].direction == SEARCH_BACKWARD) {
11436 startPos = constrain ? TextFirstVisiblePos(textW) : 0;
11437 - endPos = pos;
11438 - searchPos = endPos;
11439 - } else {
11440 - startPos = pos;
11441 endPos = constrain ? TextLastVisiblePos(textW) :
11442 window->buffer->length;
11443 - searchPos = startPos;
11445 + /* cursor pos. must be between start / end pos. */
11446 + if (pos < startPos || pos > endPos)
11447 + return;
11449 + /* Pattern Match Feature: determine matching type
11450 + (here: flash delimiter or range) */
11451 + if (window->showMatchingStyle == FLASH_DELIMIT) {
11452 + matchingType = MT_FLASH_DELIMIT;
11453 + } else {
11454 + matchingType = MT_FLASH_RANGE;
11457 - /* do the search */
11458 - if (!findMatchingChar(window, c, style, searchPos, startPos, endPos,
11459 - &matchPos))
11460 + /* Pattern Match Feature: do the search */
11461 + if (!FindMatchingString(window, matchingType, &pos, startPos, endPos,
11462 + &matchPos, &matchLen, &direction))
11463 return;
11465 if (window->showMatchingStyle == FLASH_DELIMIT) {
11466 - /* Highlight either the matching character ... */
11467 - BufHighlight(window->buffer, matchPos, matchPos+1);
11468 + /* Highlight either the matching characters ... */
11469 + BufHighlight(window->buffer, matchPos, matchPos + matchLen);
11470 } else {
11471 /* ... or the whole range. */
11472 - if (MatchingChars[matchIndex].direction == SEARCH_BACKWARD) {
11473 + if (direction == SEARCH_BACKWARD) {
11474 BufHighlight(window->buffer, matchPos, pos+1);
11475 } else {
11476 BufHighlight(window->buffer, matchPos+1, pos);
11477 @@ -3426,38 +3402,46 @@ void FlashMatching(WindowInfo *window, W
11478 window->flashPos = matchPos;
11481 -void SelectToMatchingCharacter(WindowInfo *window)
11483 +** Pattern Match Feature:
11484 +** get position of the character to match from the selection, or
11485 +** the character before the insert point if nothing is selected.
11488 +static int getPosForMatchingCharacter(WindowInfo *window)
11490 + int pos;
11491 int selStart, selEnd;
11492 - int startPos, endPos, matchPos;
11493 textBuffer *buf = window->buffer;
11495 - /* get the character to match and its position from the selection, or
11496 - the character before the insert point if nothing is selected.
11497 - Give up if too many characters are selected */
11498 - if (!GetSimpleSelection(buf, &selStart, &selEnd)) {
11499 - selEnd = TextGetCursorPos(window->lastFocus);
11500 - if (window->overstrike)
11501 - selEnd += 1;
11502 - selStart = selEnd - 1;
11503 - if (selStart < 0) {
11504 - XBell(TheDisplay, 0);
11505 - return;
11507 + if (GetSimpleSelection(buf, &selStart, &selEnd)) {
11508 + pos = selEnd;
11510 - if ((selEnd - selStart) != 1) {
11511 - XBell(TheDisplay, 0);
11512 - return;
11513 + else {
11514 + pos = TextGetCursorPos(window->lastFocus);
11518 + return pos;
11521 +void SelectToMatchingCharacter(WindowInfo *window)
11523 + int pos;
11524 + int startPos, endPos, matchPos, matchLen;
11525 + int direction;
11526 + textBuffer *buf = window->buffer;
11528 + /* Pattern Match Feature: get position of the character to match */
11529 + pos = getPosForMatchingCharacter(window);
11531 /* Search for it in the buffer */
11532 - if (!findMatchingChar(window, BufGetCharacter(buf, selStart),
11533 - GetHighlightInfo(window, selStart), selStart, 0, buf->length, &matchPos)) {
11534 + if (!FindMatchingString(window, MT_SELECT, &pos, 0,
11535 + buf->length, &matchPos, &matchLen, &direction)) {
11536 XBell(TheDisplay, 0);
11537 return;
11539 - startPos = (matchPos > selStart) ? selStart : matchPos;
11540 - endPos = (matchPos > selStart) ? matchPos : selStart;
11541 + startPos = (matchPos > pos) ? pos : matchPos;
11542 + endPos = (matchPos > pos) ? matchPos : pos;
11544 /* temporarily shut off autoShowInsertPos before setting the cursor
11545 position so MakeSelectionVisible gets a chance to place the cursor
11546 @@ -3473,32 +3457,17 @@ void SelectToMatchingCharacter(WindowInf
11548 void GotoMatchingCharacter(WindowInfo *window)
11550 - int selStart, selEnd;
11551 - int matchPos;
11552 + int pos;
11553 + int matchPos, matchLen;
11554 + int direction;
11555 textBuffer *buf = window->buffer;
11557 - /* get the character to match and its position from the selection, or
11558 - the character before the insert point if nothing is selected.
11559 - Give up if too many characters are selected */
11560 - if (!GetSimpleSelection(buf, &selStart, &selEnd)) {
11561 - selEnd = TextGetCursorPos(window->lastFocus);
11562 - if (window->overstrike)
11563 - selEnd += 1;
11564 - selStart = selEnd - 1;
11565 - if (selStart < 0) {
11566 - XBell(TheDisplay, 0);
11567 - return;
11570 - if ((selEnd - selStart) != 1) {
11571 - XBell(TheDisplay, 0);
11572 - return;
11574 + /* Pattern Match Feature: get position of the character to match */
11575 + pos = getPosForMatchingCharacter(window);
11577 /* Search for it in the buffer */
11578 - if (!findMatchingChar(window, BufGetCharacter(buf, selStart),
11579 - GetHighlightInfo(window, selStart), selStart, 0,
11580 - buf->length, &matchPos)) {
11581 + if (!FindMatchingString(window, MT_GOTO, &pos, 0,
11582 + buf->length, &matchPos, &matchLen, &direction)) {
11583 XBell(TheDisplay, 0);
11584 return;
11586 @@ -3509,77 +3478,11 @@ void GotoMatchingCharacter(WindowInfo *w
11587 be automatically scrolled on screen and MakeSelectionVisible would do
11588 nothing) */
11589 XtVaSetValues(window->lastFocus, textNautoShowInsertPos, False, NULL);
11590 - TextSetCursorPos(window->lastFocus, matchPos+1);
11591 + TextSetCursorPos(window->lastFocus, matchPos);
11592 MakeSelectionVisible(window, window->lastFocus);
11593 XtVaSetValues(window->lastFocus, textNautoShowInsertPos, True, NULL);
11596 -static int findMatchingChar(WindowInfo *window, char toMatch,
11597 - void* styleToMatch, int charPos, int startLimit, int endLimit,
11598 - int *matchPos)
11600 - int nestDepth, matchIndex, direction, beginPos, pos;
11601 - char matchChar, c;
11602 - void *style = NULL;
11603 - textBuffer *buf = window->buffer;
11604 - int matchSyntaxBased = window->matchSyntaxBased;
11606 - /* If we don't match syntax based, fake a matching style. */
11607 - if (!matchSyntaxBased) style = styleToMatch;
11609 - /* Look up the matching character and match direction */
11610 - for (matchIndex = 0; matchIndex<N_MATCH_CHARS; matchIndex++) {
11611 - if (MatchingChars[matchIndex].c == toMatch)
11612 - break;
11614 - if (matchIndex == N_MATCH_CHARS)
11615 - return FALSE;
11616 - matchChar = MatchingChars[matchIndex].match;
11617 - direction = MatchingChars[matchIndex].direction;
11619 - /* find it in the buffer */
11620 - beginPos = (direction==SEARCH_FORWARD) ? charPos+1 : charPos-1;
11621 - nestDepth = 1;
11622 - if (direction == SEARCH_FORWARD) {
11623 - for (pos=beginPos; pos<endLimit; pos++) {
11624 - c=BufGetCharacter(buf, pos);
11625 - if (c == matchChar) {
11626 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11627 - if (style == styleToMatch) {
11628 - nestDepth--;
11629 - if (nestDepth == 0) {
11630 - *matchPos = pos;
11631 - return TRUE;
11634 - } else if (c == toMatch) {
11635 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11636 - if (style == styleToMatch)
11637 - nestDepth++;
11640 - } else { /* SEARCH_BACKWARD */
11641 - for (pos=beginPos; pos>=startLimit; pos--) {
11642 - c=BufGetCharacter(buf, pos);
11643 - if (c == matchChar) {
11644 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11645 - if (style == styleToMatch) {
11646 - nestDepth--;
11647 - if (nestDepth == 0) {
11648 - *matchPos = pos;
11649 - return TRUE;
11652 - } else if (c == toMatch) {
11653 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11654 - if (style == styleToMatch)
11655 - nestDepth++;
11659 - return FALSE;
11663 ** Xt timer procedure for erasing the matching parenthesis marker.
11665 diff --quilt old/source/smartIndent.c new/source/smartIndent.c
11666 --- old/source/smartIndent.c
11667 +++ new/source/smartIndent.c
11668 @@ -983,9 +983,9 @@ void EditSmartIndentMacros(WindowInfo *w
11669 XmNtopPosition, 1,
11670 XmNrightAttachment, XmATTACH_POSITION,
11671 XmNrightPosition, 99, NULL);
11673 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
11674 SmartIndentDialog.lmPulldown = CreateLanguageModeMenu(lmForm, langModeCB,
11675 - NULL);
11676 + NULL, FALSE);
11677 n = 0;
11678 XtSetArg(args[n], XmNspacing, 0); n++;
11679 XtSetArg(args[n], XmNmarginWidth, 0); n++;
11680 @@ -2155,8 +2155,9 @@ void UpdateLangModeMenuSmartIndent(void)
11681 return;
11683 oldMenu = SmartIndentDialog.lmPulldown;
11684 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
11685 SmartIndentDialog.lmPulldown = CreateLanguageModeMenu(
11686 - XtParent(XtParent(oldMenu)), langModeCB, NULL);
11687 + XtParent(XtParent(oldMenu)), langModeCB, NULL, FALSE);
11688 XtVaSetValues(XmOptionButtonGadget(SmartIndentDialog.lmOptMenu),
11689 XmNsubMenuId, SmartIndentDialog.lmPulldown, NULL);
11690 SetLangModeMenu(SmartIndentDialog.lmOptMenu, SmartIndentDialog.langModeName);
11691 diff --quilt old/source/window.c new/source/window.c
11692 --- old/source/window.c
11693 +++ new/source/window.c
11694 @@ -55,6 +55,7 @@ static const char CVSID[] = "$Id: window
11695 #include "windowTitle.h"
11696 #include "interpret.h"
11697 #include "rangeset.h"
11698 +#include "patternMatchData.h"
11699 #include "../util/clearcase.h"
11700 #include "../util/misc.h"
11701 #include "../util/fileUtils.h"
11702 @@ -277,7 +278,6 @@ WindowInfo *CreateWindow(const char *nam
11703 window->showWrapMargin = GetPrefShowWrapMargin();
11704 window->overstrike = False;
11705 window->showMatchingStyle = GetPrefShowMatching();
11706 - window->matchSyntaxBased = GetPrefMatchSyntaxBased();
11707 window->showStats = GetPrefStatsLine();
11708 window->showISearchLine = GetPrefISearchLine();
11709 window->showLineNumbers = GetPrefLineNums();
11710 @@ -316,6 +316,10 @@ WindowInfo *CreateWindow(const char *nam
11711 window->macroCmdData = NULL;
11712 window->smartIndentData = NULL;
11713 window->languageMode = PLAIN_LANGUAGE_MODE;
11715 + /* Pattern Match Feature: assign "PLAIN" string match table*/
11716 + window->stringMatchTable = FindStringMatchTable(NULL);
11718 window->iSearchHistIndex = 0;
11719 window->iSearchStartPos = -1;
11720 window->replaceLastRegexCase = TRUE;
11721 @@ -3450,7 +3454,6 @@ WindowInfo* CreateDocument(WindowInfo* s
11722 window->showWrapMargin = GetPrefShowWrapMargin();
11723 window->overstrike = False;
11724 window->showMatchingStyle = GetPrefShowMatching();
11725 - window->matchSyntaxBased = GetPrefMatchSyntaxBased();
11726 window->highlightSyntax = GetPrefHighlightSyntax();
11727 window->backlightCharTypes = NULL;
11728 window->backlightChars = GetPrefBacklightChars();
11729 @@ -3485,6 +3488,12 @@ WindowInfo* CreateDocument(WindowInfo* s
11730 window->macroCmdData = NULL;
11731 window->smartIndentData = NULL;
11732 window->languageMode = PLAIN_LANGUAGE_MODE;
11734 + /*
11735 + * Pattern Match Feature:
11736 + */
11737 + window->stringMatchTable = FindStringMatchTable(NULL);
11739 window->iSearchHistIndex = 0;
11740 window->iSearchStartPos = -1;
11741 window->replaceLastRegexCase = TRUE;
11742 @@ -3882,7 +3891,6 @@ void RefreshMenuToggleStates(WindowInfo
11743 #endif
11744 XmToggleButtonSetState(window->autoSaveItem, window->autoSave, False);
11745 XmToggleButtonSetState(window->overtypeModeItem, window->overstrike, False);
11746 - XmToggleButtonSetState(window->matchSyntaxBasedItem, window->matchSyntaxBased, False);
11747 XmToggleButtonSetState(window->readOnlyItem, IS_USER_LOCKED(window->lockReasons), False);
11748 XmToggleButtonSetState(window->transientItem, window->transient, False);
11750 @@ -4446,6 +4454,9 @@ static void cloneDocument(WindowInfo *wi
11751 if (window->highlightSyntax)
11752 StartHighlighting(window, False);
11754 + /* recycle the pattern match data */
11755 + window->stringMatchTable = orgWin->stringMatchTable;
11757 /* copy states of original document */
11758 window->filenameSet = orgWin->filenameSet;
11759 window->fileFormat = orgWin->fileFormat;
11760 @@ -4464,7 +4475,6 @@ static void cloneDocument(WindowInfo *wi
11761 window->wrapMode = orgWin->wrapMode;
11762 SetOverstrike(window, orgWin->overstrike);
11763 window->showMatchingStyle = orgWin->showMatchingStyle;
11764 - window->matchSyntaxBased = orgWin->matchSyntaxBased;
11765 #if 0
11766 window->showStats = orgWin->showStats;
11767 window->showISearchLine = orgWin->showISearchLine;
11768 diff --quilt old/source/built-ins.h new/source/built-ins.h
11769 --- old/source/built-ins.h
11770 +++ new/source/built-ins.h
11771 @@ -62,6 +62,7 @@ MS(call, call)
11772 MS(args, args)
11773 MS(n_args, nArgs)
11774 MS(highlight_calltip_line, highlightCTLine)
11775 +MS(get_matching, getMatching)
11777 MV(cursor, cursor)
11778 MV(line, line)
11779 @@ -88,7 +89,6 @@ MV(highlight_syntax, highlightSyntax)
11780 MV(make_backup_copy, makeBackupCopy)
11781 MV(incremental_backup, incBackup)
11782 MV(show_matching, showMatching)
11783 -MV(match_syntax_based, matchSyntaxBased)
11784 MV(overtype_mode, overTypeMode)
11785 MV(read_only, readOnly)
11786 MV(locked, locked)