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
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
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
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.
55 source/Makefile.common | 6
56 source/Makefile.dependencies | 11
57 source/highlightData.c | 13
61 source/patternMatch.c | 2202 ++++++++++++
62 source/patternMatch.h | 170
63 source/patternMatchData.c | 7780 +++++++++++++++++++++++++++++++++++++++++++
64 source/patternMatchData.h | 24
65 source/preferences.c | 170
66 source/preferences.h | 4
67 source/search.c | 231 -
68 source/smartIndent.c | 7
70 16 files changed, 10773 insertions(+), 297 deletions(-)
72 diff --quilt old/doc/help.etx new/doc/help.etx
75 @@ -866,8 +866,9 @@ Programming with NEdit
76 Though general in appearance, NEdit has many features intended specifically
77 for programmers. Major programming-related topics are listed in separate
78 sections under the heading: "Features for Programming": Syntax_Highlighting_,
79 - Tabs/Emulated_Tabs_, Finding_Declarations_(ctags)_, Calltips_, and
80 - Auto/Smart_Indent_. Minor topics related to programming are discussed below:
81 + Tabs/Emulated_Tabs_, Matching_Parentheses_, Finding_Declarations_(ctags)_,
82 + Calltips_, and Auto/Smart_Indent_. Minor topics related to programming are
87 @@ -925,26 +926,6 @@ Programming with NEdit
88 a column on the current line just leave out the line number. (e.g. Enter
89 ",45" to go the column 45 on the current line.)
91 -3>Matching Parentheses
93 - To help you inspect nested parentheses, brackets, braces, quotes, and other
94 - characters, NEdit has both an automatic parenthesis matching mode, and a Goto
95 - Matching command. Automatic parenthesis matching is activated when you type,
96 - or move the insertion cursor after a parenthesis, bracket, or brace. It
97 - momentarily highlights either the opposite character ('Delimiter') or the
98 - entire expression ('Range') when the opposite character is visible in the
99 - window. To find a matching character anywhere in the file, select it or
100 - position the cursor after it, and choose Goto Matching from the Search menu.
101 - If the character matches itself, such as a quote or slash, select the first
102 - character of the pair. NEdit will match {, (, [, <, ", ', `, /, and \.
103 - Holding the Shift key while typing the accelerator key (Shift+Ctrl+M, by
104 - default), will select all of the text between the matching characters.
106 - When syntax highlighting is enabled, the matching routines can optionally
107 - make use of the syntax information for improved accuracy. In that case,
108 - a brace inside a highlighted string will not match a brace inside a comment,
111 3>Opening Included Files
113 The Open Selected command in the File menu understands the C preprocessor's
114 @@ -1222,6 +1203,39 @@ Syntax Highlighting
115 possible, but unlikely if you are only using the built-in patterns.
116 ----------------------------------------------------------------------
118 +Matching Parentheses
119 +--------------------
121 +3>Matching Parentheses (Patterns)
123 + To help you inspect nested parentheses (e.g. brackets, braces, quotes
124 + etc.) or nested constructs (e.g. "begin" .. "end"), NEdit has both an
125 + automatic parenthesis matching mode, and a Goto Matching command.
127 + A matching pattern can be a single character (like '(', ')'), a literal
128 + string (like '#ifdef', '#endif') or a regular expression (like
131 + Automatic parenthesis matching is activated when you type, or move the
132 + insertion cursor after a parenthesis, bracket, or brace. It momentarily
133 + highlights either the opposite pattern ('Delimiter') or the entire expression
134 + ('Range') when the opposite pattern is visible in the window. To find a
135 + matching pattern anywhere in the file, select it or position the cursor after
136 + it, and choose Goto Matching from the Search menu. If the pattern matches
137 + itself, such as a quote or slash, select the first pattern of the pair.
138 + Holding the Shift key while typing the accelerator key (Shift+Ctrl+M, by
139 + default), will select all of the text between the matching patterns.
141 + When syntax highlighting is enabled, the matching routines can optionally
142 + make use of the syntax information for improved accuracy. In that case,
143 + a brace inside a highlighted string will not match a brace inside a comment,
146 + Matching patterns are language dependent. Matching patterns can be
147 + configured by the user. If no matching patterns are available for the
148 + language that you want to use, you can create new patterns relatively quickly.
149 + The Help section "Matching_Patterns_" under "Customizing", has details.
151 Finding Declarations (ctags)
152 ----------------------------
154 @@ -2580,9 +2594,6 @@ Macro Subroutines
155 Contains the current preference for showing matching pairs,
156 such as "[]" and "{}" pairs. Can be "off", "delimiter", or "range".
158 -**$match_syntax_based**
159 - Whether pair matching should use syntax information, if available.
162 Has a value of 1 if the statistics line is shown, otherwise 0.
164 @@ -2697,6 +2708,15 @@ Macro Subroutines
165 Returns the single character at the position
166 indicated by the first argument to the routine from the current window.
168 +**get_matching( position )**
169 + Find a matching pattern string related to the given position.
170 + Returns info about matching pattern within an array. The array has
171 + the following keys: **pos** (position of the first character of the
172 + matching pattern), **len** (length of the matching pattern), **direction**
173 + (direction where the matching pattern was found: ~0~ = forward;
174 + ~1~ = backward). If no matching pattern was found, then array element
175 + of **pos** holds ~-1~, **len** holds ~0~ and **direction** holds ~-1~.
177 **get_range( start, end )**
178 Returns the text between a starting and ending position from the current
180 @@ -3406,9 +3426,6 @@ Action Routines
181 **set_show_matching( "off" | "delimiter" | "range" )**
182 Set show matching (...) mode for the current window.
184 -**set_match_syntax_based( [0 | 1] )**
185 - Set whether matching should be syntax based for the current window.
187 **set_statistics_line( [0 | 1] )**
188 Show or hide the statistics line for the current window.
189 A value of 0 turns it off and a value of 1 turns it on.
190 @@ -3940,10 +3957,6 @@ Preferences
191 matching delimiter, while Range highlights the whole range of text between
192 the matching delimiters.
194 - Optionally, the matching can make use of syntax information if syntax
195 - highlighting is enabled. Alternatively, the matching is purely character
196 - based. In general, syntax based matching results in fewer false matches.
199 In overtype mode, new characters entered replace the characters in front of
200 the insertion cursor, rather than being inserted before them.
201 @@ -5049,6 +5062,185 @@ Smart Indent Macros
202 keystroke typed, so if you try to get too fancy, you may degrade performance.
203 ----------------------------------------------------------------------
208 +3>Writing Matching Pattern Sets
210 + Matching Patterns Sets are groups of single characters (like '(', ')'),
211 + literal strings (like '#ifdef', '#endif') or a regular expressions (like
212 + '\</.*\>'), which match to each other.
214 + Examples: An open bracket '(' belongs a closing one ')'.
215 + Or: '#ifdef'(start), '#ifndef'(alternative start), '#ifndef' (another
216 + alternative start),'#elif' (optional), '#else' (optional), '#endif' (end)
217 + define a "#ifdef statement matching pattern".
219 + "Opposite pattern highlighting" or "Goto Matching" features are implemented
220 + in NEdit using this matching pattern sets (see Matching_Parentheses_ under
221 + the heading of Features for Programming).
223 + During definition of a new language mode a standard matching pattern set
224 + is assigned to this new language mode.
226 + To modify a matching pattern set, select "Matching Patterns ..." from
227 + "Show Matching (..)" sub-section of the "Default Settings" sub-menu
228 + of the "Preferences" menu.
230 + A matching pattern set is a collection of matching patterns.
232 + A matching pattern usually consists out of string patterns.
234 + The name of a matching pattern set needs to be defined within field "Matching
237 +4>Attributes of matching pattern
239 + A matching pattern holds two types of attributes:
241 +* "Matching Pattern Type" and
242 +* "Global Attributes"
244 + The matching pattern type specifies the kind of the matching pattern
251 + Each matching pattern can be defined as "Individual" or as "Sub-pattern".
252 + A "Sub-pattern" belongs to a context group. A context group is simply a
253 + collection of sub-patterns.
255 + During search for a corresponding pattern, an "Individual" matching pattern
256 + does not care about nesting of other matching patterns.
258 + If a matching pattern out of a "Context group" is searched, then all
259 + sub-pattern sets defined in this group are taken into account during the
262 + In fact, "Individual" matching pattern search is faster than "Context group" /
263 + "Sub-pattern" search. "Context group" / "Sub-pattern" search results in fewer
266 + To define a context group, set "Matching Pattern Type" to "Context group".
267 + Select out of "Sub-Pattern Name" pop-up field all sub-patterns, which
268 + should be placed into this group. **Note**: all "Sub-pattern" used by a context
269 + group must be defined **before** the context group itself.
271 + "Global Attributes" of a matching pattern are
273 +* "Skip content between start / end pattern"
274 +* "Flash matching pattern"
277 + If "Skip content between start / end pattern" is checked, then all text
278 + between the first / last string pattern of the related matching pattern is
279 + not scanned for other string patterns. This is useful for specifying comments.
281 + "Flash matching pattern" indicates, if the string patterns are flashed during
282 + typing. If not checked, then only the "Goto Matching" feature works for the
283 + related matching pattern. Note: if lots of "Flash matching pattern" are
284 + specified, then this may slow down the performance of NEdit: after each
285 + character typed all "Flash matching pattern" are scanned for being
288 + "Syntax based" defines, if the matching pattern can make use of syntax
289 + information if syntax highlighting is enabled. Alternatively, the matching is
290 + purely character based. In general, syntax based matching results in fewer
293 +4>Content of matching pattern
295 + An "Individual" pattern or a "Sub-pattern" may consist out of only one string
296 + pattern (e.g. double quotes '"'). Such a pattern is called "mono pattern".
297 + You can imagine, that a match for a mono pattern is hard to find. A matching
298 + mono pattern search is always started in forward direction. If no match is
299 + found in forward direction, a backward search is started. If the "Global
300 + Attribute" "Syntax based" is selected for a mono pattern, then the character
301 + before / after the match is checked to have the same highlighting style than
302 + the pattern itself. This may help to determine the correct match for a mono
305 + Usually a matching pattern holds two string patterns (e.g. 'begin' and
306 + 'end'). One ('begin') is the start pattern. The other one ('end') is the
307 + end pattern. If the cursor is located behind the start pattern, then a
308 + corresponding end pattern is searched (in forward direction). If the
309 + cursor is located behind the end pattern, then a start pattern is search
310 + (in backward direction):
312 +! +--> start ---> end --+
313 +! +-----------<---------+
315 + Alternative start / end patterns can be defined. In this case one of the
316 + start / end patterns must be in front of the cursor to detect one of the
317 + related end / start patterns:
319 +! +-> start1 -+ +-> end1 -+
320 +! +-+-> start2 -+---+ +--+
321 +! + +-> start3 -+ +-> end2 -+ |
322 +! +---------------<-------------+
324 + At least also "middle" patterns can be defined (e.g. middle patterns
325 + 'elif' or 'else'). If the cursor is located behind a middle pattern then a
326 + next middle pattern or the end pattern is searched in forward direction:
329 +! +--> start -+-> middle -+-> end --+
330 +! +-----------<---------------------+
334 + A string pattern holds three attributes:
336 +* "String Pattern Type"
338 +* "String Attributes"
340 + String Pattern Type specifies if the related string pattern is
341 + a "start", middle, or "end" pattern (see above).
343 + Word boundary defines, if before / after a string pattern a delimiter must be
344 + located ("Both" = pattern is framed by delimiters. "Left" = before pattern
345 + must be a delimiter. "Right" = after pattern must be a delimiter. "None" =
346 + there must be no delimiter before or after pattern).
348 + There are two "String Attributes":
351 +* "Regular Expression"
353 + If "Case Sensitive" is checked (= default), then the matching pattern search
354 + concerning this string pattern differs between upper / lower case of the
355 + characters. If "Case Sensitive" is not set, then the case of the checked
356 + characters is not considered.
358 + "Regular Expression" indicates, that string pattern is treated as
359 + regular expression (if "Regular Expression" is checked) or as literal
360 + string (if "Regular Expression" is not checked).
362 +4>Regular Expression String Pattern
364 + Syntax of regular expression is described by NEdit Help menu item
365 + Regular_Expressions_. Following deviations from this syntax are
366 + existing concerning string patterns:
368 +5>Capturing Parentheses
370 + Capturing Parentheses inside string patterns are of the form `(*n<regex>)',
371 + where n = 1 .. 9. Standard "capturing parentheses" of form `(<regex>)' are
372 + treated as "non-capturing parentheses" by the matching pattern feature.
373 + "n" defines the **global** backreference number, which can be used inside any string
374 + pattern of the same matching pattern (= set of string patterns). So
375 + matching patterns like "\<(*1[^/>])\>" (start string pattern) and "\</\1\>"
376 + (end string pattern) are possible. This matching pattern will match e.g.
377 + <body> .. </body> but will not match <body> .. </head>.
379 +5>Non-Capturing Parentheses
381 + As described above: parentheses constructs like (<regex>) are treated
382 + as `(?:<regex>)' (non-capturing parentheses) by the matching pattern feature.
387 @@ -6079,6 +6271,7 @@ Problems/Defects
388 .. Menu: Tabs/Emulated Tabs # tabs
389 .. Menu: Auto/Smart Indent # indent
390 .. Menu: Syntax Highlighting # syntax
391 +.. Menu: Matching Parentheses # pattern_matching
392 .. Menu: Finding Declarations (ctags) # tags
393 .. Menu: Calltips # calltips
395 @@ -6106,6 +6299,7 @@ Problems/Defects
396 .. Menu: Key Binding # binding
397 .. Menu: Highlighting Patterns # patterns
398 .. Menu: Smart Indent Macros # smart_indent
399 +.. Menu: Matching Patterns # matching_patterns
401 .. Menu: NEdit Command Line # command_line
402 .. Menu: Client/Server Mode # server
403 diff --quilt old/source/Makefile.common new/source/Makefile.common
404 --- old/source/Makefile.common
405 +++ new/source/Makefile.common
406 @@ -7,7 +7,8 @@ OBJS = nedit.o file.o menu.o window.o se
407 help.o preferences.o tags.o userCmds.o shell.o regularExp.o macro.o \
408 text.o textSel.o textDisp.o textBuf.o textDrag.o server.o highlight.o \
409 highlightData.o interpret.o parse.o smartIndent.o regexConvert.o \
410 - rbTree.o windowTitle.o calltips.o server_common.o rangeset.o
411 + rbTree.o windowTitle.o calltips.o server_common.o rangeset.o \
412 + patternMatch.o patternMatchData.o
414 XLTLIB = ../Xlt/libXlt.a
415 XMLLIB = ../Microline/XmL/libXmL.a
416 @@ -37,6 +38,9 @@ smartIndent.o: smartIndent.c
417 highlightData.o: highlightData.c
418 $(CC) $(CFLAGS) $(BIGGER_STRINGS) -c highlightData.c -o $@
420 +patternMatchData.o: patternMatchData.c
421 + $(CC) $(CFLAGS) $(BIGGER_STRINGS) -c patternMatchData.c -o $@
423 help_topic.h help_data.h: ../doc/help.etx
424 (cd ..; $(MAKE) docs)
426 diff --quilt old/source/Makefile.dependencies new/source/Makefile.dependencies
427 --- old/source/Makefile.dependencies
428 +++ new/source/Makefile.dependencies
429 @@ -87,3 +87,14 @@ windowTitle.o: windowTitle.c windowTitle
430 ../util/DialogF.h ../util/utils.h ../util/fileUtils.h \
432 parse.c: parse.h textBuf.h nedit.h rbTree.h interpret.h ops.h
433 +patternMatch.o: patternMatch.c regularExp.h \
434 + textBuf.h search.h window.h preferences.h highlight.h\
435 + patternMatch.h patternMatchData.h
436 +patternMatchData.o: patternMatchData.c ../util/DialogF.h ../util/misc.h \
437 + ../util/managedList.h regularExp.h textBuf.h nedit.h window.h \
438 + preferences.h help.h file.h textP.h patternMatch.h patternMatchData.h
439 +macro.o: patternMatch.h regularExp.h
440 +menu.o: patternMatchData.h
441 +preferences.o: patternMatchData.h
442 +search.o: patternMatch.h
443 +window.o: patternMatchData.h
444 diff --quilt old/source/highlightData.c new/source/highlightData.c
445 --- old/source/highlightData.c
446 +++ new/source/highlightData.c
447 @@ -551,7 +551,7 @@ static char *DefaultPatternSets[] = {
448 Built-in Misc Vars:\"(?<!\\Y)\\$(?:active_pane|args|calltip_ID|column|cursor|display_width|empty_array|file_name|file_path|language_mode|line|locked|max_font_width|min_font_width|modified|n_display_lines|n_panes|rangeset_list|read_only|selection_(?:start|end|left|right)|server_name|text_length|top_line|transient|VERSION|NEDIT_HOME)>\":::Identifier::\n\
449 Built-in Pref Vars:\"(?<!\\Y)\\$(?:auto_indent|em_tab_dist|file_format|font_name|font_name_bold|font_name_bold_italic|font_name_italic|highlight_syntax|incremental_backup|incremental_search_line|make_backup_copy|match_syntax_based|overtype_mode|show_line_numbers|show_matching|statistics_line|tab_dist|use_tabs|wrap_margin|wrap_text)>\":::Identifier2::\n\
450 Built-in Special Vars:\"(?<!\\Y)\\$(?:[1-9]|list_dialog_button|n_args|read_status|search_end|shell_cmd_status|string_dialog_button|sub_sep)>\":::String1::\n\
451 - Built-in Subrs:\"<(?:args|append_file|beep|call|calltip|clipboard_to_string|dialog|filename_dialog|focus_window|get_character|get_pattern_(by_name|at_pos)|get_range|get_selection|get_style_(by_name|at_pos)|getenv|highlight_calltip_line|kill_calltip|length|list_dialog|max|min|n_args|rangeset_(?:add|create|destroy|get_by_name|includes|info|invert|range|set_color|set_mode|set_name|subtract)|read_file|replace_in_string|replace_range|replace_selection|replace_substring|search|search_string|select|select_rectangle|set_cursor_pos|set_transient|shell_command|split|string_compare|string_dialog|string_to_clipboard|substring|t_print|tolower|toupper|valid_number|write_file)(?=\\s*\\()\":::Subroutine::\n\
452 + Built-in Subrs:\"<(?:args|append_file|beep|call|calltip|clipboard_to_string|dialog|filename_dialog|focus_window|get_character|get_matching|get_pattern_(by_name|at_pos)|get_range|get_selection|get_style_(by_name|at_pos)|getenv|highlight_calltip_line|kill_calltip|length|list_dialog|max|min|n_args|rangeset_(?:add|create|destroy|get_by_name|includes|info|invert|range|set_color|set_mode|set_name|subtract)|read_file|replace_in_string|replace_range|replace_selection|replace_substring|search|search_string|select|select_rectangle|set_cursor_pos|set_transient|shell_command|split|string_compare|string_dialog|string_to_clipboard|substring|t_print|tolower|toupper|valid_number|write_file)(?=\\s*\\()\":::Subroutine::\n\
453 Menu Actions:\"<(?:new(?:_tab|_opposite)?|open|open-dialog|open_dialog|open-selected|open_selected|close|save|save-as|save_as|save-as-dialog|save_as_dialog|revert-to-saved|revert_to_saved|revert_to_saved_dialog|include-file|include_file|include-file-dialog|include_file_dialog|load-macro-file|load_macro_file|load-macro-file-dialog|load_macro_file_dialog|load-tags-file|load_tags_file|load-tags-file-dialog|load_tags_file_dialog|unload_tags_file|load_tips_file|load_tips_file_dialog|unload_tips_file|print|print-selection|print_selection|exit|undo|redo|delete|select-all|select_all|shift-left|shift_left|shift-left-by-tab|shift_left_by_tab|shift-right|shift_right|shift-right-by-tab|shift_right_by_tab|find|find-dialog|find_dialog|find-again|find_again|find-selection|find_selection|find_incremental|start_incremental_find|replace|replace-dialog|replace_dialog|replace-all|replace_all|replace-in-selection|replace_in_selection|replace-again|replace_again|replace_find|replace_find_same|replace_find_again|goto-line-number|goto_line_number|goto-line-number-dialog|goto_line_number_dialog|goto-selected|goto_selected|mark|mark-dialog|mark_dialog|goto-mark|goto_mark|goto-mark-dialog|goto_mark_dialog|match|select_to_matching|goto_matching|find-definition|find_definition|show_tip|split-pane|split_pane|close-pane|close_pane|detach_document(?:_dialog)?|move_document_dialog|(?:next|previous|last)_document|uppercase|lowercase|fill-paragraph|fill_paragraph|control-code-dialog|control_code_dialog|filter-selection-dialog|filter_selection_dialog|filter-selection|filter_selection|execute-command|execute_command|execute-command-dialog|execute_command_dialog|execute-command-line|execute_command_line|shell-menu-command|shell_menu_command|macro-menu-command|macro_menu_command|bg_menu_command|post_window_bg_menu|post_tab_context_menu|beginning-of-selection|beginning_of_selection|end-of-selection|end_of_selection|repeat_macro|repeat_dialog|raise_window|focus_pane|set_statistics_line|set_incremental_search_line|set_show_line_numbers|set_auto_indent|set_wrap_text|set_wrap_margin|set_highlight_syntax|set_make_backup_copy|set_incremental_backup|set_show_matching|set_match_syntax_based|set_overtype_mode|set_locked|set_tab_dist|set_em_tab_dist|set_use_tabs|set_fonts|set_language_mode)(?=\\s*\\()\":::Subroutine::\n\
454 Text Actions:\"<(?:self-insert|self_insert|grab-focus|grab_focus|extend-adjust|extend_adjust|extend-start|extend_start|extend-end|extend_end|secondary-adjust|secondary_adjust|secondary-or-drag-adjust|secondary_or_drag_adjust|secondary-start|secondary_start|secondary-or-drag-start|secondary_or_drag_start|process-bdrag|process_bdrag|move-destination|move_destination|move-to|move_to|move-to-or-end-drag|move_to_or_end_drag|end_drag|copy-to|copy_to|copy-to-or-end-drag|copy_to_or_end_drag|exchange|process-cancel|process_cancel|paste-clipboard|paste_clipboard|copy-clipboard|copy_clipboard|cut-clipboard|cut_clipboard|copy-primary|copy_primary|cut-primary|cut_primary|newline|newline-and-indent|newline_and_indent|newline-no-indent|newline_no_indent|delete-selection|delete_selection|delete-previous-character|delete_previous_character|delete-next-character|delete_next_character|delete-previous-word|delete_previous_word|delete-next-word|delete_next_word|delete-to-start-of-line|delete_to_start_of_line|delete-to-end-of-line|delete_to_end_of_line|forward-character|forward_character|backward-character|backward_character|key-select|key_select|process-up|process_up|process-down|process_down|process-shift-up|process_shift_up|process-shift-down|process_shift_down|process-home|process_home|forward-word|forward_word|backward-word|backward_word|forward-paragraph|forward_paragraph|backward-paragraph|backward_paragraph|beginning-of-line|beginning_of_line|end-of-line|end_of_line|beginning-of-file|beginning_of_file|end-of-file|end_of_file|next-page|next_page|previous-page|previous_page|page-left|page_left|page-right|page_right|toggle-overstrike|toggle_overstrike|scroll-up|scroll_up|scroll-down|scroll_down|scroll_left|scroll_right|scroll-to-line|scroll_to_line|select-all|select_all|deselect-all|deselect_all|focusIn|focusOut|process-return|process_return|process-tab|process_tab|insert-string|insert_string|mouse_pan)(?=\\s*\\()\":::Subroutine::\n\
455 Macro Hooks:\"<(?:(?:pre|post)_(?:open|save)|cursor_moved|modified|(?:losing_)?focus)_hook(?=\\s*\\()\":::Subroutine1::\n\
456 @@ -2346,8 +2346,9 @@ void EditHighlightPatterns(WindowInfo *w
457 XmNrightPosition, 99,
460 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
461 HighlightDialog.lmPulldown = CreateLanguageModeMenu(lmForm, langModeCB,
465 XtSetArg(args[n], XmNspacing, 0); n++;
466 XtSetArg(args[n], XmNmarginWidth, 0); n++;
467 @@ -2881,8 +2882,9 @@ void UpdateLanguageModeMenu(void)
470 oldMenu = HighlightDialog.lmPulldown;
471 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
472 HighlightDialog.lmPulldown = CreateLanguageModeMenu(
473 - XtParent(XtParent(oldMenu)), langModeCB, NULL);
474 + XtParent(XtParent(oldMenu)), langModeCB, NULL, FALSE);
475 XtVaSetValues(XmOptionButtonGadget(HighlightDialog.lmOptMenu),
476 XmNsubMenuId, HighlightDialog.lmPulldown, NULL);
477 SetLangModeMenu(HighlightDialog.lmOptMenu, HighlightDialog.langModeName);
478 @@ -2941,6 +2943,9 @@ static void langModeCB(Widget w, XtPoint
480 SetLangModeMenu(HighlightDialog.lmOptMenu,
481 HighlightDialog.langModeName);
483 + freePatternSet(newPatSet);
488 @@ -3040,6 +3045,8 @@ static void restoreCB(Widget w, XtPointe
489 "patterns for language mode %s?", "Discard", "Cancel",
490 HighlightDialog.langModeName) == 2)
492 + freePatternSet(defaultPatSet);
497 diff --quilt old/source/macro.c new/source/macro.c
498 --- old/source/macro.c
499 +++ new/source/macro.c
500 @@ -57,6 +57,8 @@ static const char CVSID[] = "$Id: macro.
501 #include "highlight.h"
502 #include "highlightData.h"
503 #include "rangeset.h"
504 +#include "patternMatch.h"
505 +#include "regularExp.h"
509 @@ -312,8 +314,6 @@ static int incBackupMV(WindowInfo *windo
510 DataValue *result, char **errMsg);
511 static int showMatchingMV(WindowInfo *window, DataValue *argList, int nArgs,
512 DataValue *result, char **errMsg);
513 -static int matchSyntaxBasedMV(WindowInfo *window, DataValue *argList, int nArgs,
514 - DataValue *result, char **errMsg);
515 static int overTypeModeMV(WindowInfo *window, DataValue *argList, int nArgs,
516 DataValue *result, char **errMsg);
517 static int readOnlyMV(WindowInfo *window, DataValue *argList, int nArgs,
518 @@ -429,6 +429,10 @@ static int filenameDialogMS(WindowInfo*
519 static int callMS(WindowInfo *window, DataValue *argList,
520 int nArgs, DataValue *result, char **errMsg);
522 +/* Pattern Match Feature */
523 +static int getMatchingMS(WindowInfo *window, DataValue *argList, int nArgs,
524 + DataValue *result, char **errMsg);
526 /* Built-in subroutines and variables for the macro language */
527 static const BuiltInSubrName MacroSubrs[] = {
529 @@ -491,6 +495,7 @@ static const BuiltInSubrName MacroSubrs[
530 { "get_style_at_pos", getStyleAtPosMS },
531 { "filename_dialog", filenameDialogMS },
533 + { "get_matching", getMatchingMS },
534 { NULL, NULL } /* sentinel */
537 @@ -520,7 +525,6 @@ static const BuiltInSubrName SpecialVars
538 { "$make_backup_copy", makeBackupCopyMV },
539 { "$incremental_backup", incBackupMV },
540 { "$show_matching", showMatchingMV },
541 - { "$match_syntax_based", matchSyntaxBasedMV },
542 { "$overtype_mode", overTypeModeMV },
543 { "$read_only", readOnlyMV },
544 { "$locked", lockedMV },
545 @@ -4530,16 +4534,6 @@ static int showMatchingMV(WindowInfo *wi
549 -static int matchSyntaxBasedMV(WindowInfo *window, DataValue *argList, int nArgs,
550 - DataValue *result, char **errMsg)
552 - result->tag = INT_TAG;
553 - result->val.n = window->matchSyntaxBased ? 1 : 0;
559 static int overTypeModeMV(WindowInfo *window, DataValue *argList, int nArgs,
560 DataValue *result, char **errMsg)
562 @@ -5947,6 +5941,93 @@ static int getPatternAtPosMS(WindowInfo
563 HighlightStyleOfCode(window, patCode), bufferPos);
567 +** Pattern Match Feature:
568 +** Find a matching pattern string related to the given position.
571 +** get_matching(position)
573 +** Returns info about matching pattern within an array. The array has
574 +** the following keys: "pos" (position of the first character of the
575 +** matching pattern), "len" (length of the matching pattern), "direction"
576 +** (direction where the matching pattern was found: "0" = forward;
577 +** "1" = backward). If no matching pattern was found, then array element
578 +** of "pos" holds "-1", "len" holds "0" and "direction" holds "-1".
581 +static int getMatchingMS(WindowInfo *window, DataValue *argList, int nArgs,
582 + DataValue *result, char **errMsg)
585 + int matchPos, matchLen;
587 + textBuffer *buf = window->buffer;
591 + * Perform syntax & semantic check
594 + return wrongNArgsErr(errMsg);
596 + if (!readIntArg(argList[0], &startPos, errMsg))
602 + * do the search; provide default values, if search fails
604 + if (!FindMatchingString(window, MT_MACRO, &startPos, 0, buf->length,
605 + &matchPos, &matchLen, &direction))
613 + * initialize array holding info about matching string
615 + result->tag = ARRAY_TAG;
616 + result->val.arrayPtr = ArrayNew();
619 + * the following array entries will be integers
624 + * insert match position
626 + dv.val.n = matchPos;
627 + if (!ArrayInsert(result, PERM_ALLOC_STR("pos"), &dv))
629 + M_ARRAY_INSERT_FAILURE();
633 + * insert length of matching pattern
635 + dv.val.n = matchLen;
636 + if (!ArrayInsert(result, PERM_ALLOC_STR("len"), &dv))
638 + M_ARRAY_INSERT_FAILURE();
642 + * insert direction where the matching pattern was found
644 + dv.val.n = direction;
645 + if (!ArrayInsert(result, PERM_ALLOC_STR("direction"), &dv))
647 + M_ARRAY_INSERT_FAILURE();
653 static int wrongNArgsErr(char **errMsg)
655 *errMsg = "Wrong number of arguments to function %s";
656 diff --quilt old/source/menu.c new/source/menu.c
657 --- old/source/menu.c
658 +++ new/source/menu.c
659 @@ -49,6 +49,7 @@ static const char CVSID[] = "$Id: menu.c
661 #include "highlight.h"
662 #include "highlightData.h"
663 +#include "patternMatchData.h"
664 #include "interpret.h"
665 #include "smartIndent.h"
666 #include "windowTitle.h"
667 @@ -133,7 +134,6 @@ static void backlightCharsCB(Widget w, W
668 static void showMatchingOffCB(Widget w, WindowInfo *window, caddr_t callData);
669 static void showMatchingDelimitCB(Widget w, WindowInfo *window, caddr_t callData);
670 static void showMatchingRangeCB(Widget w, WindowInfo *window, caddr_t callData);
671 -static void matchSyntaxBasedCB(Widget w, WindowInfo *window, caddr_t callData);
672 static void statsCB(Widget w, WindowInfo *window, caddr_t callData);
673 static void autoIndentOffDefCB(Widget w, WindowInfo *window, caddr_t callData);
674 static void autoIndentDefCB(Widget w, WindowInfo *window, caddr_t callData);
675 @@ -160,9 +160,9 @@ static void tabsDefCB(Widget w, WindowIn
676 static void showMatchingOffDefCB(Widget w, WindowInfo *window, caddr_t callData);
677 static void showMatchingDelimitDefCB(Widget w, WindowInfo *window, caddr_t callData);
678 static void showMatchingRangeDefCB(Widget w, WindowInfo *window, caddr_t callData);
679 -static void matchSyntaxBasedDefCB(Widget w, WindowInfo *window, caddr_t callData);
680 static void highlightOffDefCB(Widget w, WindowInfo *window, caddr_t callData);
681 static void highlightDefCB(Widget w, WindowInfo *window, caddr_t callData);
682 +static void matchPatternsDefCB(Widget w, WindowInfo *window, caddr_t callData);
683 static void backlightCharsDefCB(Widget w, WindowInfo *window, caddr_t callData);
684 static void fontDefCB(Widget w, WindowInfo *window, caddr_t callData);
685 static void colorDefCB(Widget w, WindowInfo *window, caddr_t callData);
686 @@ -409,8 +409,6 @@ static void setIncrementalBackupAP(Widge
688 static void setShowMatchingAP(Widget w, XEvent *event, String *args,
690 -static void setMatchSyntaxBasedAP(Widget w, XEvent *event, String *args,
692 static void setOvertypeModeAP(Widget w, XEvent *event, String *args,
694 static void setLockedAP(Widget w, XEvent *event, String *args,
695 @@ -584,7 +582,6 @@ static XtActionsRec Actions[] = {
697 {"set_incremental_backup", setIncrementalBackupAP},
698 {"set_show_matching", setShowMatchingAP},
699 - {"set_match_syntax_based", setMatchSyntaxBasedAP},
700 {"set_overtype_mode", setOvertypeModeAP},
701 {"set_locked", setLockedAP},
702 {"set_transient", setTransientAP},
703 @@ -1030,9 +1027,8 @@ Widget CreateMenuBar(Widget parent, Wind
704 "range", "Range", 'R', showMatchingRangeDefCB, window,
705 GetPrefShowMatching() == FLASH_RANGE, SHORT);
706 createMenuSeparator(subSubPane, "sep", SHORT);
707 - window->matchSyntaxBasedDefItem = createMenuToggle(subSubPane,
708 - "matchSyntax", "Syntax Based", 'S', matchSyntaxBasedDefCB, window,
709 - GetPrefMatchSyntaxBased(), SHORT);
710 + createMenuItem(subSubPane, "matchPatterns", "Matching Patterns...",
711 + 'M', matchPatternsDefCB, window, FULL);
713 /* Show Cursorline */
714 window->showCursorlineItem = createMenuToggle(subPane,
715 @@ -1154,10 +1150,6 @@ Widget CreateMenuBar(Widget parent, Wind
716 window->showMatchingRangeItem = createMenuRadioToggle(subPane, "range",
717 "Range", 'R', showMatchingRangeCB, window,
718 window->showMatchingStyle == FLASH_RANGE, SHORT);
719 - createMenuSeparator(subPane, "sep", SHORT);
720 - window->matchSyntaxBasedItem = createMenuToggle(subPane, "matchSyntax",
721 - "Syntax Based", 'S', matchSyntaxBasedCB, window,
722 - window->matchSyntaxBased, SHORT);
725 createMenuSeparator(menuPane, "sep2", SHORT);
726 @@ -1689,24 +1681,6 @@ static void showMatchingRangeCB(Widget w
727 ((XmAnyCallbackStruct *)callData)->event, params, 1);
730 -static void matchSyntaxBasedCB(Widget w, WindowInfo *window, caddr_t callData)
732 - Widget menu = MENU_WIDGET(w);
734 - window = WidgetToWindow(menu);
737 - if (shortPrefAskDefault(window->shell, w, "Match Syntax Based")) {
738 - matchSyntaxBasedDefCB(w, window, callData);
739 - SaveNEditPrefs(window->shell, GetPrefShortMenus());
742 - HidePointerOnKeyedEvent(WidgetToWindow(menu)->lastFocus,
743 - ((XmAnyCallbackStruct *)callData)->event);
744 - XtCallActionProc(WidgetToWindow(menu)->lastFocus, "set_match_syntax_based",
745 - ((XmAnyCallbackStruct *)callData)->event, NULL, 0);
748 static void fontCB(Widget w, WindowInfo *window, caddr_t callData)
750 ChooseFonts(WidgetToWindow(MENU_WIDGET(w)), True);
751 @@ -2034,18 +2008,14 @@ static void showMatchingRangeDefCB(Widge
755 -static void matchSyntaxBasedDefCB(Widget w, WindowInfo *window, caddr_t callData)
756 +static void matchPatternsDefCB(Widget w, WindowInfo *window, caddr_t callData)
760 - int state = XmToggleButtonGetState(w);
761 + Widget menu = MENU_WIDGET(w);
762 + WindowInfo *activeWindow = WidgetToWindow(menu);
764 - /* Set the preference and make the other windows' menus agree */
765 - SetPrefMatchSyntaxBased(state);
766 - for (win=WindowList; win!=NULL; win=win->next) {
767 - if (IsTopDocument(win))
768 - XmToggleButtonSetState(win->matchSyntaxBasedDefItem, state, False);
770 + HidePointerOnKeyedEvent(activeWindow->lastFocus,
771 + ((XmAnyCallbackStruct *)callData)->event);
772 + EditMatchPatterns(activeWindow);
775 static void backlightCharsDefCB(Widget w, WindowInfo *window, caddr_t callData)
776 @@ -4288,19 +4258,6 @@ static void setShowMatchingAP(Widget w,
780 -static void setMatchSyntaxBasedAP(Widget w, XEvent *event, String *args,
783 - WindowInfo *window = WidgetToWindow(w);
786 - ACTION_BOOL_PARAM_OR_TOGGLE(newState, *nArgs, args, window->matchSyntaxBased, "set_match_syntax_based");
788 - if (IsTopDocument(window))
789 - XmToggleButtonSetState(window->matchSyntaxBasedItem, newState, False);
790 - window->matchSyntaxBased = newState;
793 static void setOvertypeModeAP(Widget w, XEvent *event, String *args,
796 diff --quilt old/source/nedit.h new/source/nedit.h
797 --- old/source/nedit.h
798 +++ new/source/nedit.h
799 @@ -366,7 +366,6 @@ typedef struct _WindowInfo {
800 Widget showMatchingOffItem;
801 Widget showMatchingDelimitItem;
802 Widget showMatchingRangeItem;
803 - Widget matchSyntaxBasedItem;
804 Widget overtypeModeItem;
805 Widget highlightItem;
806 Widget windowMenuPane;
807 @@ -392,7 +391,6 @@ typedef struct _WindowInfo {
808 Widget showMatchingOffDefItem;
809 Widget showMatchingDelimitDefItem;
810 Widget showMatchingRangeDefItem;
811 - Widget matchSyntaxBasedDefItem;
812 Widget highlightOffDefItem;
813 Widget highlightDefItem;
814 Widget backlightCharsItem;
815 @@ -512,7 +510,6 @@ typedef struct _WindowInfo {
816 char showMatchingStyle; /* How to show matching parens:
817 NO_FLASH, FLASH_DELIMIT, or
819 - char matchSyntaxBased; /* Use syntax info to show matching */
820 Boolean showStats; /* is stats line supposed to be shown */
821 Boolean showISearchLine; /* is incr. search line to be shown */
822 Boolean showLineNumbers; /* is the line number display shown */
823 @@ -558,6 +555,9 @@ typedef struct _WindowInfo {
824 Bool findLastRegexCase; /* idem, for regex mode in find dialog */
825 Bool findLastLiteralCase; /* idem, for literal mode */
827 + /* Pattern Match Feature */
828 + void *stringMatchTable; /* match pattern info related to this window */
831 int replaceScope; /* Current scope for replace dialog */
832 Widget replaceScopeWinToggle; /* Scope for replace = window */
833 diff --quilt /dev/null new/source/patternMatch.c
835 +++ new/source/patternMatch.c
837 +static const char CVSID[] = "$Id: patternMatch.c,v 1.4 2003/10/27 21:59:14 uleh Exp $";
838 +/*******************************************************************************
840 +* patternMatch.c -- Nirvana Editor pattern matching functions *
842 +* Copyright (C) 2003-2004, Uwe Lehnert *
844 +* This is free software; you can redistribute it and/or modify it under the *
845 +* terms of the GNU General Public License as published by the Free Software *
846 +* Foundation; either version 2 of the License, or (at your option) any later *
847 +* version. In addition, you may distribute versions of this program linked to *
848 +* Motif or Open Motif. See README for details. *
850 +* This software is distributed in the hope that it will be useful, but WITHOUT *
851 +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
852 +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
853 +* for more details. *
855 +* You should have received a copy of the GNU General Public License along with *
856 +* software; if not, write to the Free Software Foundation, Inc., 59 Temple *
857 +* Place, Suite 330, Boston, MA 02111-1307 USA *
859 +* Nirvana Text Editor *
860 +* October 27, 2004 *
862 +* Written by Uwe Lehnert *
864 +*******************************************************************************/
866 +#ifdef HAVE_CONFIG_H
867 +#include "../config.h"
877 +#include "../util/VMSparam.h"
880 +#include <sys/param.h>
884 +#include "regularExp.h"
885 +#include "textBuf.h"
888 +#include "preferences.h"
889 +#include "highlight.h"
891 +#include "patternMatch.h"
892 +#include "patternMatchData.h"
895 +#include "../debug.h"
898 +#define MAX_NESTED_PATTERNS 100
900 +#define IGNORE_HIGHLIGHT_CODE -1
902 +typedef struct _SearchRegionInfo {
903 + WindowInfo *sriWindow;
907 + int sriStartOfTextPos;
910 +typedef struct _FoundStringInfo {
916 + const char *fsiDelimiters;
919 +typedef struct _BackRefInfo {
921 + int briCaseInsensitive;
922 + char *briStartPtr[MAX_GLOBAL_BACK_REF_ID];
923 + char *briEndPtr[MAX_GLOBAL_BACK_REF_ID];
926 +typedef struct _MatchingElementInfo {
927 + MatchPatternTableElement *meiElement;
928 + PatternReference meiPatRef;
930 + int meiHighLightCode;
931 + int meiAbsStartPos;
933 + BackRefInfo meiBackRefInfo;
934 +} MatchingElementInfo;
936 +typedef struct _PatternStackElement {
937 + PatternReference psePatRef;
938 + int pseHighLightCode;
939 + BackRefInfo pseBackRefInfo;
940 +} PatternStackElement;
943 + * Prototypes of local functions
945 +void adaptPatternPositions(
946 + MatchingType matchingType,
949 + int startPatternLength,
951 + int matchedPatternLength);
953 +static int findMatchingStringElement(
954 + StringMatchTable *smTable,
955 + SearchRegionInfo *searchRegion,
956 + MatchingElementInfo *matchInfo,
958 + const char *delimiters);
960 +static PatternElementMonoInfo determineMonoPatInfo(
961 + WindowInfo *window,
962 + int patHighLightCode,
965 + PatternElementKind *patElementKind);
967 +static void assignBackRefInfo(
968 + StringPattern *strPat,
969 + BackRefInfo *backRefInfo);
970 +static int doesBackRefInfoMatch(
971 + BackRefInfo *backRefInfo1,
972 + BackRefInfo *backRefInfo2);
973 +static int compareBackRef(
978 + int caseInsensitive);
980 +static int doesPatternElementMatch(
981 + PatternElement *patElement,
982 + FoundStringInfo *foundStringInfo,
983 + BackRefInfo *backRefInfo);
984 +static int doesMPTableElementMatch(
985 + MatchPatternTableElement *element,
986 + FoundStringInfo *foundStringInfo,
987 + PatternElementKind *patternElementKind,
988 + int *patternElementIdx,
989 + BackRefInfo *backRefInfo);
990 +static int getPatternInfo(
991 + MatchPatternTable *table,
992 + FoundStringInfo *foundStringInfo,
993 + PatternReference *patRef,
994 + BackRefInfo *backRefInfo);
996 +static int isPartOfPattern(
997 + MatchPatternTable *table,
998 + int parentElementIdx,
999 + int childElementIdx,
1000 + PatternElementKind patElementKind);
1001 +static int isPartOfPatternElementSet(
1002 + PatternElementSet *patElementSet,
1003 + int patternElementIdx);
1004 +static int isPartOfMiddlePatternElementSet(
1005 + PatternElementSet *patElementSet,
1006 + int patternElementIdx);
1007 +static void considerNextPatternReference(
1008 + MatchPatternTable *table,
1009 + PatternReference *startPatRef,
1010 + PatternReference nxtPatRef,
1013 +static int searchPatternForward(
1014 + MatchPatternTable *table,
1015 + regexp *compiledRE,
1016 + SearchRegionInfo *searchRegion,
1017 + const char *delimiters,
1020 + PatternReference *patRef,
1021 + int *highLightCode,
1022 + BackRefInfo *backRefInfo);
1023 +static int searchPatternBackward(
1024 + MatchPatternTable *table,
1025 + regexp *compiledRE,
1026 + SearchRegionInfo *searchRegion,
1027 + const char *delimiters,
1029 + PatternReference *patRef,
1030 + int *highLightCode,
1031 + int *matchedPatternLength,
1032 + BackRefInfo *backRefInfo);
1034 +static int parseStringElementForward(
1035 + MatchingElementInfo *matchInfo,
1036 + SearchRegionInfo *searchRegion,
1039 + int *matchedPatternLength,
1040 + const char *delimiters);
1041 +static int findRelatedForwardPattern(
1042 + StringMatchTable *table,
1043 + SearchRegionInfo *searchRegion,
1044 + const char *delimiters,
1045 + PatternReference beginPatRef,
1046 + int beginPatHighLightCode,
1047 + BackRefInfo *beginPatBackRefInfo,
1049 + int *matchEndPos);
1051 +static int parseStringElementBackward(
1052 + MatchingElementInfo *matchInfo,
1053 + SearchRegionInfo *searchRegion,
1056 + int *matchedPatternLength,
1057 + const char *delimiters);
1058 +static int findRelatedStartPattern(
1059 + StringMatchTable *table,
1060 + SearchRegionInfo *searchRegion,
1061 + const char *delimiters,
1062 + PatternReference beginPatRef,
1063 + int beginPatHighLightCode,
1064 + BackRefInfo *beginPatBackRefInfo,
1066 + int *matchedPatternLength);
1067 +static void considerStackPatReference(
1068 + PatternElementSet *patSet,
1069 + int stackElementIdx,
1070 + int *foundElementIdx);
1072 +static int getPatternLocatedAtPos(
1073 + regexp *usedPatRE,
1074 + MatchPatternTable *table,
1075 + SearchRegionInfo *searchRegion,
1077 + MatchingElementInfo *matchInfo,
1078 + const char *delimiters);
1079 +static int getMatchedElementInfo(
1080 + WindowInfo *window,
1081 + MatchPatternTable *table,
1082 + FoundStringInfo *foundStringInfo,
1083 + MatchingElementInfo *matchInfo);
1085 +static PatternElement *getPatternOfReference(
1086 + MatchPatternTable *table,
1087 + PatternReference patRef);
1090 +static char *getPatternForDebug(
1091 + MatchPatternTable *table,
1092 + PatternReference patRef );
1093 +static char *patElemKindToString(
1094 + PatternElementKind patElemKind);
1095 +static void printFoundStringForDebug(
1096 + WindowInfo *window,
1102 +** Try to find a matching pattern string related to the given "charPos"
1103 +** inside the given range (defined by startLimit & endLimit).
1104 +** Determine the matching position & the match pattern length (depending
1105 +** on given matchingType), if a matching pattern was found.
1106 +** Returns true, if a matching pattern string was found.
1108 +int FindMatchingString(
1109 + WindowInfo *window,
1110 + MatchingType matchingType,
1115 + int *matchedPatternLength,
1118 + StringMatchTable *smTable = (StringMatchTable *)window->stringMatchTable;
1119 + const char *delimiters;
1120 + SearchRegionInfo searchRegion;
1121 + MatchingElementInfo matchInfo;
1122 + int matchingPatternFound = FALSE;
1125 + if (smTable == NULL || smTable->smtAllPatRE == NULL)
1128 + * No match pattern table available:
1134 + * Get delimiters related to window
1136 + delimiters = GetWindowDelimiters(window);
1137 + if (delimiters == NULL)
1138 + delimiters = GetPrefDelimiters();
1141 + * Select the start pattern reg. exp. to use
1143 + if (matchingType == MT_FLASH_RANGE ||
1144 + matchingType == MT_FLASH_DELIMIT)
1146 + smTable->smtUsedPatRE = smTable->smtFlashPatRE;
1150 + smTable->smtUsedPatRE = smTable->smtAllPatRE;
1154 + * Get a copy of the text buffer area to parse
1156 + searchRegion.sriWindow = window;
1157 + searchRegion.sriText = BufGetRange(window->buffer, startLimit, endLimit);
1158 + searchRegion.sriPrevChar = BufGetCharacter(window->buffer, startLimit - 1);
1159 + searchRegion.sriSuccChar = BufGetCharacter(window->buffer, endLimit);
1160 + searchRegion.sriStartOfTextPos = startLimit;
1162 + relCharPos = *charPos - startLimit;
1165 + * Try to find a matching pattern string using string match table
1168 + if (findMatchingStringElement(
1176 + printf("--- Start at : ");
1177 + printFoundStringForDebug(
1179 + matchInfo.meiAbsStartPos,
1180 + matchInfo.meiLength);
1183 + if (matchInfo.meiDirection == SEARCH_FORWARD)
1185 + matchingPatternFound =
1186 + parseStringElementForward(
1191 + matchedPatternLength,
1196 + matchingPatternFound =
1197 + parseStringElementBackward(
1202 + matchedPatternLength,
1206 + if (matchingPatternFound)
1209 + * Calc. abs. start char pos. (may have been changed if
1210 + * cursor was located inside a string pattern). Adapt
1211 + * pattern positions depending on matchingType.
1213 + *charPos = relCharPos + startLimit;
1214 + *direction = matchInfo.meiDirection;
1216 + adaptPatternPositions(
1218 + matchInfo.meiDirection,
1220 + matchInfo.meiLength,
1222 + *matchedPatternLength);
1226 + XtFree(searchRegion.sriText);
1228 + return matchingPatternFound;
1232 +** Adapt match pattern position / start position depending on the
1233 +** given matching type.
1235 +void adaptPatternPositions(
1236 + MatchingType matchingType,
1239 + int startPatternLength,
1241 + int matchedPatternLength)
1243 + switch (matchingType)
1245 + case MT_FLASH_DELIMIT:
1247 + if (direction == SEARCH_FORWARD)
1249 + (*matchPos) -= matchedPatternLength - 1;
1253 + case MT_FLASH_RANGE:
1255 + if (direction == SEARCH_FORWARD)
1257 + (*charPos) -= startPatternLength;
1266 + if (direction == SEARCH_FORWARD)
1272 + (*matchPos) += matchedPatternLength;
1279 +** Try to find a string pattern at given buffer position 'charPos'.
1280 +** A string pattern is found, if pattern is located before 'charPos' or
1281 +** 'charPos' is located within a pattern.
1282 +** If a string pattern is found, then search direction and string pattern
1283 +** reference / properties are determined.
1284 +** Returns true, if a string pattern was found.
1286 +static int findMatchingStringElement(
1287 + StringMatchTable *smTable,
1288 + SearchRegionInfo *searchRegion,
1289 + MatchingElementInfo *matchInfo,
1291 + const char *delimiters)
1293 + if (getPatternLocatedAtPos(
1294 + smTable->smtUsedPatRE,
1295 + smTable->smtAllPatterns,
1302 + * Pattern found -> define search direction:
1303 + * - START & MIDDLE pattern: matching pattern is searched in
1304 + * forward direction
1305 + * - END pattern: matching pattern is searched in backward
1308 + if (matchInfo->meiPatRef.prKind == PEK_END)
1309 + matchInfo->meiDirection = SEARCH_BACKWARD;
1311 + matchInfo->meiDirection = SEARCH_FORWARD;
1320 +** Return mono pattern info depending on highlight codes
1321 +** of left / right side of string pattern. Update pattern
1322 +** kind if applicable.
1324 +static PatternElementMonoInfo determineMonoPatInfo(
1325 + WindowInfo *window,
1326 + int patHighLightCode,
1329 + PatternElementKind *patElementKind)
1331 + int leftSideHasSameHC;
1332 + int rightSideHasSameHC;
1335 + * Determine, if left side holds same highlight code than
1336 + * found string pattern
1339 + leftSideHasSameHC =
1340 + (HighlightCodeOfPos(window, leftPos) == patHighLightCode);
1342 + leftSideHasSameHC = FALSE;
1345 + * Determine, if right side holds same highlight code than
1346 + * found string pattern
1348 + if (rightPos < window->buffer->length)
1349 + rightSideHasSameHC =
1350 + (HighlightCodeOfPos(window, rightPos) == patHighLightCode);
1352 + rightSideHasSameHC = FALSE;
1354 + if ((rightSideHasSameHC && leftSideHasSameHC) ||
1355 + (!rightSideHasSameHC && !leftSideHasSameHC))
1357 + return PEMI_MONO_AMBIGUOUS_SYNTAX;
1359 + else if (leftSideHasSameHC)
1361 + *patElementKind = PEK_END;
1362 + return PEMI_MONO_DEFINITE_SYNTAX;
1366 + *patElementKind = PEK_START;
1367 + return PEMI_MONO_DEFINITE_SYNTAX;
1372 +** Get backref info out of found string pattern and
1373 +** put it into given backRefInfo.
1375 +static void assignBackRefInfo(
1376 + StringPattern *strPat,
1377 + BackRefInfo *backRefInfo)
1381 + regexp *patRE = strPat->spTextRE;
1383 + backRefInfo->briAvailable = FALSE;
1384 + backRefInfo->briCaseInsensitive = strPat->spCaseInsensitive;
1386 + for (i=0; i<MAX_GLOBAL_BACK_REF_ID; i++)
1388 + localId = strPat->spGlobalToLocalBackRef[i];
1390 + if (localId != NO_LOCAL_BACK_REF_ID)
1392 + backRefInfo->briAvailable = TRUE;
1394 + backRefInfo->briStartPtr[i] = patRE->startp[localId];
1395 + backRefInfo->briEndPtr[i] = patRE->endp[localId];
1399 + backRefInfo->briStartPtr[i] = NULL;
1400 + backRefInfo->briEndPtr[i] = NULL;
1406 +** Check, if given backref infos match.
1407 +** Returns true, if backref infos match.
1409 +static int doesBackRefInfoMatch(
1410 + BackRefInfo *backRefInfo1,
1411 + BackRefInfo *backRefInfo2)
1416 + * if min. one string pattern doesn't hold backref info, then nothing
1417 + * could be compared -> both string pattern are matching.
1419 + if (!backRefInfo1->briAvailable || !backRefInfo2->briAvailable)
1422 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
1424 + if (!compareBackRef(
1425 + backRefInfo1->briStartPtr[i],
1426 + backRefInfo1->briEndPtr[i],
1427 + backRefInfo2->briStartPtr[i],
1428 + backRefInfo2->briEndPtr[i],
1429 + backRefInfo1->briCaseInsensitive || backRefInfo2->briCaseInsensitive))
1439 +** Compares two backref content.
1440 +** Returns true, if backref contents match.
1442 +static int compareBackRef(
1447 + int caseInsensitive)
1452 + if (startPtr1 == NULL && startPtr2 == NULL)
1455 + if (startPtr1 == NULL || startPtr2 == NULL)
1458 + if ((endPtr1 - startPtr1) != (endPtr2 - startPtr2))
1464 + if (caseInsensitive)
1466 + while (s1 != endPtr1)
1468 + if (tolower((unsigned char)*s1++) != tolower((unsigned char)*s2++))
1474 + while (s1 != endPtr1)
1476 + if (*s1++ != *s2++)
1484 +** Verify if given pattern element is located between given
1485 +** start / end pointer of "foundStringInfo". Assign backreference
1486 +** information, if pattern element matches.
1487 +** Returns true, if given pattern element matches.
1489 +static int doesPatternElementMatch(
1490 + PatternElement *patElement,
1491 + FoundStringInfo *foundStringInfo,
1492 + BackRefInfo *backRefInfo)
1496 + StringPattern *strPat;
1499 + switch (patElement->peType)
1502 + strPat = &patElement->peVal.peuSingle;
1504 + case PET_MULTIPLE:
1505 + strPat = &patElement->peVal.peuMulti.mpStringPattern;
1511 + if (strPat->spRegularExpression)
1514 + * check reg. expression:
1519 + foundStringInfo->fsiStartPtr,
1520 + foundStringInfo->fsiEndPtr,
1522 + foundStringInfo->fsiPrevChar,
1523 + foundStringInfo->fsiSuccChar,
1524 + foundStringInfo->fsiDelimiters,
1529 + assignBackRefInfo(strPat, backRefInfo);
1531 + return elementMatch;
1535 + backRefInfo->briAvailable = FALSE;
1538 + * check literal string:
1540 + p = strPat->spText;
1543 + * if length of found string is different from length of
1544 + * given string pattern, then there is no match.
1546 + if (strPat->spLength != foundStringInfo->fsiLength)
1549 + s = foundStringInfo->fsiStartPtr;
1551 + if (strPat->spCaseInsensitive)
1553 + while (s != foundStringInfo->fsiEndPtr)
1555 + if (tolower((unsigned char)*s++) != *p++)
1561 + while (s != foundStringInfo->fsiEndPtr)
1573 +** Verify if a pattern element of given MatchPatternTableElement is
1574 +** located between given start / end pointer of "foundStringInfo".
1575 +** Returns true, if so.
1577 +static int doesMPTableElementMatch(
1578 + MatchPatternTableElement *element,
1579 + FoundStringInfo *foundStringInfo,
1580 + PatternElementKind *patternElementKind,
1581 + int *patternElementIdx,
1582 + BackRefInfo *backRefInfo)
1586 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i ++)
1588 + if (doesPatternElementMatch(
1589 + element->mpteAll.pesPattern[i],
1593 + *patternElementKind = element->mpteAll.pesPattern[i]->peKind;
1594 + *patternElementIdx = i;
1604 +** Determine the pattern element of given MatchPatternTable, which is
1605 +** located between given start / end pointer of "foundStringInfo".
1606 +** Setup related pattern element reference.
1607 +** Returns true, if a pattern element was found.
1609 +static int getPatternInfo(
1610 + MatchPatternTable *table,
1611 + FoundStringInfo *foundStringInfo,
1612 + PatternReference *patRef,
1613 + BackRefInfo *backRefInfo)
1617 + for (i=0; i<table->mptNumberOfElements; i++)
1619 + if (doesMPTableElementMatch(
1620 + table->mptElements[i],
1623 + &patRef->prPatternIdx,
1626 + patRef->prElementIdx = i;
1633 + * Should never been reached !
1635 + patRef->prElementIdx = NO_ELEMENT_IDX;
1636 + patRef->prKind = PEK_UNKNOWN;
1637 + patRef->prPatternIdx = NO_PATTERN_IDX;
1643 +** Check, if given child pattern element is part of given
1644 +** parent pattern element.
1645 +** Returns true, if child is part of parent.
1647 +static int isPartOfPattern(
1648 + MatchPatternTable *table,
1649 + int parentElementIdx,
1650 + int childElementIdx,
1651 + PatternElementKind patElementKind)
1653 + MatchPatternTableElement *parent = table->mptElements[parentElementIdx];
1654 + MatchPatternTableElement *child = table->mptElements[childElementIdx];
1656 + if (childElementIdx == parentElementIdx)
1659 + if (patElementKind == PEK_START)
1661 + if (isPartOfPatternElementSet(&parent->mpteStart, childElementIdx))
1664 + return( isPartOfPatternElementSet(&child->mpteStart, parentElementIdx) );
1666 + else if (patElementKind == PEK_END)
1668 + if (isPartOfPatternElementSet(&parent->mpteEnd, childElementIdx))
1671 + return( isPartOfPatternElementSet(&child->mpteEnd, parentElementIdx) );
1676 + * Given child pattern element is middle pattern: the given pattern element
1677 + * is part of parent pattern, if it's a reference of a middle pattern
1679 + if (isPartOfMiddlePatternElementSet(&parent->mpteMiddle, childElementIdx))
1682 + return( isPartOfMiddlePatternElementSet(&child->mpteMiddle, parentElementIdx) );
1687 +** Check, if given pattern element is part of given pattern element set.
1688 +** Returns true, if so.
1690 +static int isPartOfPatternElementSet(
1691 + PatternElementSet *patElementSet,
1692 + int patternElementIdx)
1694 + PatternElement *patElement;
1697 + for (i=0; i<patElementSet->pesNumberOfPattern; i++)
1699 + if (patElementSet->pesPattern[i]->peType == PET_REFERENCE)
1701 + patElement = patElementSet->pesPattern[i];
1703 + if (patElement->peVal.peuRef.prElementIdx == patternElementIdx)
1714 +** Verify, if given pattern element is part of middle pattern set.
1715 +** That's the case, if an element of the pattern set is reference
1716 +** of a middle pattern, which fits to given pattern element.
1717 +** Returns true, if pattern element is part of middle pattern set.
1719 +static int isPartOfMiddlePatternElementSet(
1720 + PatternElementSet *patElementSet,
1721 + int patternElementIdx)
1723 + PatternElement *patElement;
1726 + for (i=0; i<patElementSet->pesNumberOfPattern; i++)
1728 + if (patElementSet->pesPattern[i]->peType == PET_REFERENCE)
1730 + patElement = patElementSet->pesPattern[i];
1732 + if (patElement->peVal.peuRef.prElementIdx == patternElementIdx &&
1733 + patElement->peKind == PEK_MIDDLE)
1744 +** Update start pattern reference depending on next pattern located
1745 +** after start pattern.
1747 +static void considerNextPatternReference(
1748 + MatchPatternTable *table,
1749 + PatternReference *startPatRef,
1750 + PatternReference nxtPatRef,
1753 + MatchPatternTableElement *tabElement;
1754 + PatternElement *startPat;
1755 + MultiPattern *multiStartPat;
1756 + PatternReference patRef;
1760 + * startPatRef needs no adaption, if element index of start pattern
1761 + * and next pattern are equal (i.e. start and next pattern belong
1762 + * to same pattern element).
1764 + if (startPatRef->prElementIdx == nxtPatRef.prElementIdx)
1768 + * Verify, if start pattern belongs to multiple pattern elements
1769 + * (like "ELSE .. FI" & "ELSE .. ESAC").
1771 + startPat = getPatternOfReference( table, *startPatRef );
1773 + if (startPat->peType == PET_MULTIPLE)
1776 + * Check, if next pattern fits to one of the references of
1777 + * the start multi pattern. If so: adapt start pattern reference.
1779 + multiStartPat = &startPat->peVal.peuMulti;
1781 + for (i=0; i<multiStartPat->mpNumberOfReferences; i ++)
1783 + patRef = multiStartPat->mpRefList[i];
1784 + tabElement = table->mptElements[patRef.prElementIdx];
1786 + if (nxtPatRef.prElementIdx == patRef.prElementIdx &&
1787 + tabElement->mpteGroup == groupIdx)
1789 + *startPatRef = patRef;
1797 +** Search for a string pattern in forward direction, starting at
1798 +** given beginPos. Determine related pattern reference of a found
1800 +** Returns true, if a next string pattern was found.
1802 +static int searchPatternForward(
1803 + MatchPatternTable *table,
1804 + regexp *compiledRE,
1805 + SearchRegionInfo *searchRegion,
1806 + const char *delimiters,
1809 + PatternReference *patRef,
1810 + int *highLightCode,
1811 + BackRefInfo *backRefInfo)
1813 + FoundStringInfo foundStringInfo;
1814 + int matchStartPos;
1815 + int absMatchStartPos;
1816 + MatchPatternTableElement *matchedElement;
1818 + *matchEndPos = -1;
1820 + patRef->prElementIdx = NO_ELEMENT_IDX;
1821 + patRef->prKind = PEK_UNKNOWN;
1822 + patRef->prPatternIdx = NO_PATTERN_IDX;
1824 + *highLightCode = IGNORE_HIGHLIGHT_CODE;
1828 + searchRegion->sriText + beginPos,
1831 + beginPos==0 ? searchRegion->sriPrevChar : searchRegion->sriText[beginPos-1],
1832 + searchRegion->sriSuccChar,
1834 + searchRegion->sriText,
1837 + foundStringInfo.fsiStartPtr = compiledRE->startp[0];
1838 + foundStringInfo.fsiEndPtr = compiledRE->endp[0];
1839 + foundStringInfo.fsiLength =
1840 + foundStringInfo.fsiEndPtr - foundStringInfo.fsiStartPtr;
1842 + foundStringInfo.fsiPrevChar =
1843 + foundStringInfo.fsiStartPtr == searchRegion->sriText ?
1844 + searchRegion->sriPrevChar : *(foundStringInfo.fsiStartPtr - 1);
1846 + foundStringInfo.fsiSuccChar =
1847 + *(foundStringInfo.fsiEndPtr) == '\0' ?
1848 + searchRegion->sriSuccChar : *(foundStringInfo.fsiEndPtr);
1850 + foundStringInfo.fsiDelimiters = delimiters;
1852 + if (getPatternInfo(
1859 + * Next string pattern was found in forward direction and
1860 + * a pattern reference could be assigned to: calculate
1861 + * relative & absolute match positions.
1863 + matchStartPos = foundStringInfo.fsiStartPtr - searchRegion->sriText;
1864 + *matchEndPos = foundStringInfo.fsiEndPtr - searchRegion->sriText;
1866 + absMatchStartPos = matchStartPos + searchRegion->sriStartOfTextPos;
1868 + matchedElement = table->mptElements[patRef->prElementIdx];
1871 + * get highlight code of found string pattern, if applicable
1873 + if (!matchedElement->mpteIgnoreHighLightInfo)
1876 + HighlightCodeOfPos(searchRegion->sriWindow, absMatchStartPos);
1880 + * setup mono pattern info of found string pattern
1882 + if (matchedElement->mpteIsMonoPattern)
1884 + if (matchedElement->mpteIgnoreHighLightInfo)
1886 + patRef->prMonoInfo = PEMI_MONO_NOT_SYNTAX_BASED;
1891 + * determine mono pattern info depending on highLightCodes
1892 + * before / after found string pattern.
1894 + patRef->prMonoInfo =
1895 + determineMonoPatInfo(
1896 + searchRegion->sriWindow,
1898 + absMatchStartPos - 1,
1899 + *matchEndPos + searchRegion->sriStartOfTextPos,
1905 + patRef->prMonoInfo = PEMI_NOT_MONO;
1908 + return matchStartPos;
1913 + * Found string can't be assigned to a pattern element
1914 + * (should never occur).
1922 + * No next string pattern is found in forward direction.
1929 +** Search for a string pattern in backward direction, starting at
1930 +** given beginPos. Determine related pattern reference of a found
1932 +** Returns true, if a next string pattern was found.
1934 +static int searchPatternBackward(
1935 + MatchPatternTable *table,
1936 + regexp *compiledRE,
1937 + SearchRegionInfo *searchRegion,
1938 + const char *delimiters,
1940 + PatternReference *patRef,
1941 + int *highLightCode,
1942 + int *matchedPatternLength,
1943 + BackRefInfo *backRefInfo)
1945 + FoundStringInfo foundStringInfo;
1946 + int matchStartPos;
1947 + int absMatchStartPos;
1948 + MatchPatternTableElement *matchedElement;
1950 + patRef->prElementIdx = NO_ELEMENT_IDX;
1951 + patRef->prKind = PEK_UNKNOWN;
1952 + patRef->prPatternIdx = NO_PATTERN_IDX;
1954 + *highLightCode = IGNORE_HIGHLIGHT_CODE;
1958 + searchRegion->sriText,
1959 + searchRegion->sriText + beginPos,
1961 + searchRegion->sriPrevChar,
1962 + searchRegion->sriText[beginPos] == '\0' ?
1963 + searchRegion->sriSuccChar : searchRegion->sriText[beginPos + 1],
1965 + searchRegion->sriText,
1968 + foundStringInfo.fsiStartPtr = compiledRE->startp[0];
1969 + foundStringInfo.fsiEndPtr = compiledRE->endp[0];
1970 + foundStringInfo.fsiLength =
1971 + foundStringInfo.fsiEndPtr - foundStringInfo.fsiStartPtr;
1973 + foundStringInfo.fsiPrevChar =
1974 + foundStringInfo.fsiStartPtr == searchRegion->sriText ?
1975 + searchRegion->sriPrevChar : *(foundStringInfo.fsiStartPtr - 1);
1977 + foundStringInfo.fsiSuccChar =
1978 + *(foundStringInfo.fsiEndPtr) == '\0' ?
1979 + searchRegion->sriSuccChar : *(foundStringInfo.fsiEndPtr);
1981 + foundStringInfo.fsiDelimiters = delimiters;
1983 + if (getPatternInfo(
1990 + * Next string pattern was found in backward direction and
1991 + * a pattern reference could be assigned to: calculate
1992 + * relative & absolute match positions.
1994 + matchStartPos = foundStringInfo.fsiStartPtr - searchRegion->sriText;
1995 + *matchedPatternLength = foundStringInfo.fsiLength;
1997 + absMatchStartPos = matchStartPos + searchRegion->sriStartOfTextPos;
1999 + matchedElement = table->mptElements[patRef->prElementIdx];
2002 + * get highlight code of found string pattern, if applicable
2004 + if (!matchedElement->mpteIgnoreHighLightInfo)
2007 + HighlightCodeOfPos(searchRegion->sriWindow, absMatchStartPos);
2011 + * setup mono pattern info of found string pattern
2013 + if (matchedElement->mpteIsMonoPattern)
2015 + if (matchedElement->mpteIgnoreHighLightInfo)
2017 + patRef->prMonoInfo = PEMI_MONO_NOT_SYNTAX_BASED;
2022 + * determine mono pattern info depending on highLightCodes
2023 + * before / after found string pattern.
2025 + patRef->prMonoInfo =
2026 + determineMonoPatInfo(
2027 + searchRegion->sriWindow,
2029 + absMatchStartPos - 1,
2030 + absMatchStartPos + *matchedPatternLength,
2036 + patRef->prMonoInfo = PEMI_NOT_MONO;
2039 + return matchStartPos;
2044 + * Found string can't be assigned to a pattern element
2045 + * (should never occur).
2053 + * No next string pattern is found in backward direction.
2060 +** Find matching pattern related to given pattern (stored in
2061 +** 'matchInfo') in forward direction by considering the rules stored in
2062 +** string match table of given window. Determine match position (= abs.
2063 +** pos. of last character of matching string) and length of matching
2064 +** string. If a mono matching pattern couldn't be found in forward
2065 +** direction, then try finding it in backward direction (if found in
2066 +** backward direction, then match position indicates the 1st char. of
2067 +** matching string).
2068 +** Returns true, if a matching pattern was found.
2070 +static int parseStringElementForward(
2071 + MatchingElementInfo *matchInfo,
2072 + SearchRegionInfo *searchRegion,
2075 + int *matchedPatternLength,
2076 + const char *delimiters)
2078 + StringMatchTable *smTable =
2079 + (StringMatchTable *)searchRegion->sriWindow->stringMatchTable;
2080 + MatchPatternTableElement *matchElement = matchInfo->meiElement;
2081 + int beginPos = relCharPos;
2083 + int startStartPos;
2085 + int matchingPatternFound = FALSE;
2088 + * Find matching pattern within text buffer area to parse in
2089 + * forward direction.
2092 + findRelatedForwardPattern(
2096 + matchInfo->meiPatRef,
2097 + matchInfo->meiHighLightCode,
2098 + &matchInfo->meiBackRefInfo,
2102 + if (endEndPos != -1)
2104 + *matchPos = endEndPos - 1 + searchRegion->sriStartOfTextPos;
2105 + *matchedPatternLength = endEndPos - endStartPos;
2107 + matchingPatternFound = TRUE;
2109 + else if (matchElement->mpteIsMonoPattern)
2112 + * mono pattern: forward find fails -> try backward direction.
2113 + * Calc. relative position of 1st char. before found string pattern.
2115 + beginPos = beginPos - matchInfo->meiLength - 1;
2120 + findRelatedStartPattern(
2124 + matchInfo->meiPatRef,
2125 + matchInfo->meiHighLightCode,
2126 + &matchInfo->meiBackRefInfo,
2128 + matchedPatternLength);
2130 + if (startStartPos != -1)
2132 + matchInfo->meiDirection = SEARCH_BACKWARD;
2134 + *matchPos = startStartPos + searchRegion->sriStartOfTextPos;
2136 + matchingPatternFound = TRUE;
2141 + return matchingPatternFound;
2145 +** Find matching pattern related to given begin pattern reference
2146 +** in forward direction by considering the rules stored in given
2147 +** string match table. Determine match position (= relative
2148 +** pos. of last character of matching string).
2149 +** Returns -1, if no matching pattern was found. Else the relative
2150 +** position of 1st char. of matching string is returned.
2152 +static int findRelatedForwardPattern(
2153 + StringMatchTable *table,
2154 + SearchRegionInfo *searchRegion,
2155 + const char *delimiters,
2156 + PatternReference beginPatRef,
2157 + int beginPatHighLightCode,
2158 + BackRefInfo *beginPatBackRefInfo,
2162 + MatchPatternTable *patTable = table->smtAllPatterns;
2163 + int startPos = beginPos;
2164 + int nxtPatStartPos = 0;
2165 + int nxtPatEndPos = 0;
2166 + PatternReference nxtPatRef;
2167 + int nxtPatHighLightCode;
2168 + BackRefInfo nxtPatBackRefInfo;
2169 + PatternStackElement stack[MAX_NESTED_PATTERNS];
2171 + PatternReference startPatRef;
2172 + MatchPatternTableElement *currentElement;
2174 + regexp *groupPatRE;
2175 + regexp *currentPatRE;
2176 + int skipToEnd = FALSE;
2177 + int beginPatternIsMono;
2180 + printf("Forward Start Pos: %d K: %s EI: %d PI: %d HC: %d <%s>\n",
2182 + patElemKindToString(beginPatRef.prKind),
2183 + beginPatRef.prElementIdx,
2184 + beginPatRef.prPatternIdx,
2185 + beginPatHighLightCode,
2186 + getPatternForDebug(patTable, beginPatRef) );
2190 + * put begin pattern info on stack
2192 + stack[stackIdx].psePatRef = beginPatRef;
2193 + stack[stackIdx].pseHighLightCode = beginPatHighLightCode;
2194 + stack[stackIdx].pseBackRefInfo = *beginPatBackRefInfo;
2197 + currentElement = patTable->mptElements[beginPatRef.prElementIdx];
2199 + beginPatternIsMono = currentElement->mpteIsMonoPattern;
2201 + groupIdx = currentElement->mpteGroup;
2204 + * no next pattern can be found, if there is no group assigned
2205 + * to begin pattern (should never occur)
2207 + if (groupIdx == NO_GROUP_IDX)
2209 + *matchEndPos = -1;
2215 + * Remember pattern (= keywords) regular expression of context
2216 + * group related to begin pattern. Use it for forward search.
2218 + groupPatRE = table->smtGroups[groupIdx]->mpgeKeywordRE;
2219 + currentPatRE = groupPatRE;
2222 + * Use start / end pattern regular expression if skip to end is
2223 + * set for begin pattern.
2225 + if (currentElement->mpteSkipBtwnStartEnd)
2227 + currentPatRE = currentElement->mpteStartEndRE;
2231 + while (stackIdx > 0 && nxtPatStartPos != -1)
2234 + * Search for next string pattern in forward direction.
2237 + searchPatternForward(
2245 + &nxtPatHighLightCode,
2246 + &nxtPatBackRefInfo );
2248 + startPatRef = stack[stackIdx-1].psePatRef;
2250 + if (nxtPatStartPos == -1)
2253 + * no next pattern found -> leave loop
2256 + printf(" SI: %d [start K: %s EI: %d PI %d] Pos: %d --> no next pat. found\n",
2258 + patElemKindToString(startPatRef.prKind),
2259 + startPatRef.prElementIdx,
2260 + startPatRef.prPatternIdx,
2267 + * Update start pattern reference depending on next pattern
2268 + * located after start pattern.
2270 + considerNextPatternReference(
2277 + * If current found match pattern table element is a mono pattern and
2278 + * skip to start pattern is active, then the found pattern string is
2279 + * a END one in case of ambiguous or no syntax was detected.
2282 + (nxtPatRef.prMonoInfo == PEMI_MONO_AMBIGUOUS_SYNTAX ||
2283 + nxtPatRef.prMonoInfo == PEMI_MONO_NOT_SYNTAX_BASED))
2285 + nxtPatRef.prKind = PEK_END;
2289 + printf(" SI: %d [start K: %s EI: %d PI %d] Pos: %d-%d K: %s EI: %d PI: %d HC: %d f=<%s> ",
2291 + patElemKindToString(startPatRef.prKind),
2292 + startPatRef.prElementIdx,
2293 + startPatRef.prPatternIdx,
2296 + patElemKindToString(nxtPatRef.prKind),
2297 + nxtPatRef.prElementIdx,
2298 + nxtPatRef.prPatternIdx,
2299 + nxtPatHighLightCode,
2300 + getPatternForDebug(patTable, nxtPatRef) );
2301 + printFoundStringForDebug(
2302 + searchRegion->sriWindow,
2303 + nxtPatStartPos + searchRegion->sriStartOfTextPos,
2304 + nxtPatEndPos - nxtPatStartPos);
2308 + if (nxtPatRef.prKind == PEK_START)
2310 + if (stackIdx >= MAX_NESTED_PATTERNS)
2313 + printf("FORWARD: MAX. NESTED PATTERN DEPTH REACHED !\n");
2315 + nxtPatStartPos = -1;
2316 + nxtPatEndPos = -1;
2318 + else if (!skipToEnd)
2321 + * Put next pattern on stack, if contents between start /
2322 + * end shouldn't be skipped (if "skipToEnd" is set,
2323 + * a (usually illegal) start pattern to skip inside the
2324 + * skipped one is found (e.g. \* \* ..)
2326 + stack[stackIdx].psePatRef = nxtPatRef;
2327 + stack[stackIdx].pseHighLightCode = nxtPatHighLightCode;
2328 + stack[stackIdx].pseBackRefInfo = nxtPatBackRefInfo;
2331 + currentElement = patTable->mptElements[nxtPatRef.prElementIdx];
2334 + * Use start / end pattern regular expression if skip to
2335 + * end is set for found start pattern.
2337 + if (currentElement->mpteSkipBtwnStartEnd)
2339 + currentPatRE = currentElement->mpteStartEndRE;
2343 + else if (beginPatternIsMono)
2346 + * skip to end is set and a mono pattern start is reached:
2347 + * trigger backward search by returning "not found"
2350 + printf(" ---> mono pattern (re-)start -> trigger backward search\n");
2352 + nxtPatStartPos = -1;
2353 + nxtPatEndPos = -1;
2358 + printf(" ---> skip to end: illegal (re-)start pattern !\n");
2362 + else if (nxtPatRef.prKind == PEK_END)
2365 + * ignore current found pattern, if it doesn't fit to the prev.
2368 + if (isPartOfPattern(
2370 + nxtPatRef.prElementIdx,
2371 + startPatRef.prElementIdx,
2373 + (stack[stackIdx - 1].pseHighLightCode == nxtPatHighLightCode ||
2374 + stack[stackIdx - 1].pseHighLightCode == IGNORE_HIGHLIGHT_CODE ||
2375 + nxtPatHighLightCode == IGNORE_HIGHLIGHT_CODE) &&
2376 + doesBackRefInfoMatch(
2377 + &stack[stackIdx - 1].pseBackRefInfo,
2378 + &nxtPatBackRefInfo))
2381 + * use context group pattern again, if end pattern to skip
2386 + currentPatRE = groupPatRE;
2387 + skipToEnd = FALSE;
2391 + * pop. related start pattern from stack.
2396 + else if (!skipToEnd)
2399 + * middle pattern was found: ignore it, if found middle pattern
2400 + * doesn't belong to begin pattern.
2402 + if (stackIdx == 1 &&
2405 + startPatRef.prElementIdx,
2406 + nxtPatRef.prElementIdx,
2407 + nxtPatRef.prKind) &&
2408 + (beginPatHighLightCode == nxtPatHighLightCode ||
2409 + beginPatHighLightCode == IGNORE_HIGHLIGHT_CODE ||
2410 + nxtPatHighLightCode == IGNORE_HIGHLIGHT_CODE) &&
2411 + doesBackRefInfoMatch(
2412 + beginPatBackRefInfo,
2413 + &nxtPatBackRefInfo))
2420 + startPos = nxtPatEndPos;
2423 + *matchEndPos = nxtPatEndPos;
2425 + return nxtPatStartPos;
2429 +** Find matching pattern related to given pattern (stored in
2430 +** 'matchInfo') in backward direction by considering the rules stored in
2431 +** string match table of given window. Determine match position (= abs.
2432 +** pos. of 1st character of matching string) and length of matching
2434 +** Returns true, if a matching pattern was found.
2436 +static int parseStringElementBackward(
2437 + MatchingElementInfo *matchInfo,
2438 + SearchRegionInfo *searchRegion,
2441 + int *matchedPatternLength,
2442 + const char *delimiters)
2444 + StringMatchTable *smTable =
2445 + (StringMatchTable *)searchRegion->sriWindow->stringMatchTable;
2447 + int startStartPos;
2448 + int matchingPatternFound = FALSE;
2451 + * determine begin of search in string buffer (= relative position
2452 + * of 1st char. before found string pattern.)
2454 + beginPos = relCharPos - matchInfo->meiLength - 1;
2460 + * Find matching pattern within text buffer area to parse in
2461 + * backward direction.
2464 + findRelatedStartPattern(
2468 + matchInfo->meiPatRef,
2469 + matchInfo->meiHighLightCode,
2470 + &matchInfo->meiBackRefInfo,
2472 + matchedPatternLength);
2474 + if (startStartPos != -1)
2476 + *matchPos = startStartPos + searchRegion->sriStartOfTextPos;
2477 + matchingPatternFound = TRUE;
2480 + return matchingPatternFound;
2484 +** Find matching pattern related to given begin pattern reference
2485 +** in backward direction by considering the rules stored in given
2486 +** string match table. Determine match position (= relative
2487 +** pos. of 1st character of matching string).
2488 +** Returns -1, if no matching pattern was found. Else the relative
2489 +** position of 1st char. of matching string is returned.
2491 +static int findRelatedStartPattern(
2492 + StringMatchTable *table,
2493 + SearchRegionInfo *searchRegion,
2494 + const char *delimiters,
2495 + PatternReference beginPatRef,
2496 + int beginPatHighLightCode,
2497 + BackRefInfo *beginPatBackRefInfo,
2499 + int *matchedPatternLength)
2501 + MatchPatternTable *patTable = table->smtAllPatterns;
2502 + int startPos = beginPos;
2503 + int prevStartPos = 0;
2504 + PatternReference prevPatRef;
2505 + int prevPatHighLightCode;
2506 + BackRefInfo prevPatBackRefInfo;
2507 + PatternStackElement stack[MAX_NESTED_PATTERNS];
2509 + MatchPatternTableElement *currentElement;
2511 + regexp *groupPatRE;
2512 + regexp *currentPatRE;
2513 + int skipToStart = FALSE;
2516 + * put begin pattern info on stack
2518 + stack[stackIdx].psePatRef = beginPatRef;
2519 + stack[stackIdx].pseHighLightCode = beginPatHighLightCode;
2520 + stack[stackIdx].pseBackRefInfo = *beginPatBackRefInfo;
2523 + currentElement = patTable->mptElements[beginPatRef.prElementIdx];
2526 + printf("Backward Start Pos: %d K: %s EI: %d PI: %d HC: %d <%s>\n",
2528 + patElemKindToString(beginPatRef.prKind),
2529 + beginPatRef.prElementIdx,
2530 + beginPatRef.prPatternIdx,
2531 + beginPatHighLightCode,
2532 + getPatternForDebug(patTable, beginPatRef) );
2535 + groupIdx = currentElement->mpteGroup;
2538 + * no start pattern can be found, if there is no group assigned
2539 + * to begin pattern (should never occur)
2541 + if (groupIdx == NO_GROUP_IDX)
2547 + * Remember pattern (= keywords) regular expression of context
2548 + * group related to begin pattern. Use it for backward search.
2550 + groupPatRE = table->smtGroups[groupIdx]->mpgeKeywordRE;
2551 + currentPatRE = groupPatRE;
2554 + * Use start / end pattern regular expression if skip to start is
2555 + * set for begin pattern.
2557 + if (currentElement->mpteSkipBtwnStartEnd)
2559 + currentPatRE = currentElement->mpteStartEndRE;
2560 + skipToStart = TRUE;
2563 + while (stackIdx > 0 && prevStartPos != -1)
2566 + * Search for previous string pattern in backward direction.
2569 + searchPatternBackward(
2576 + &prevPatHighLightCode,
2577 + matchedPatternLength,
2578 + &prevPatBackRefInfo );
2580 + if (prevStartPos == -1)
2583 + * no previous pattern found -> leave loop
2586 + printf(" SI: %d [K: %s start EI: %d PI %d] Pos: %d --> no next pat. found\n",
2588 + patElemKindToString(stack[stackIdx -1].psePatRef.prKind),
2589 + stack[stackIdx -1].psePatRef.prElementIdx,
2590 + stack[stackIdx -1].psePatRef.prPatternIdx,
2597 + * Update previous pattern reference depending on last stack
2598 + * pattern, which is located in text puffer after previous
2601 + considerNextPatternReference(
2604 + stack[stackIdx - 1].psePatRef,
2608 + * If current found match pattern table element is a mono pattern and
2609 + * skip to start pattern is active, then the found pattern string is
2610 + * a START one in case of ambiguous or no syntax was detected.
2612 + if (skipToStart &&
2613 + (prevPatRef.prMonoInfo == PEMI_MONO_AMBIGUOUS_SYNTAX ||
2614 + prevPatRef.prMonoInfo == PEMI_MONO_NOT_SYNTAX_BASED))
2616 + prevPatRef.prKind = PEK_START;
2620 + printf(" SI: %d [K: %s start EI: %d PI %d] Pos: %d K: %s EI: %d PI: %d HC: %d f=<%s> ",
2622 + patElemKindToString(stack[stackIdx -1].psePatRef.prKind),
2623 + stack[stackIdx -1].psePatRef.prElementIdx,
2624 + stack[stackIdx -1].psePatRef.prPatternIdx,
2626 + patElemKindToString(prevPatRef.prKind),
2627 + prevPatRef.prElementIdx,
2628 + prevPatRef.prPatternIdx,
2629 + prevPatHighLightCode,
2630 + getPatternForDebug(patTable, prevPatRef) );
2631 + printFoundStringForDebug(
2632 + searchRegion->sriWindow,
2633 + prevStartPos + searchRegion->sriStartOfTextPos,
2634 + *matchedPatternLength);
2638 + if (prevPatRef.prKind == PEK_START)
2641 + * If the end pattern of the previous pattern set is a reference,
2642 + * then the prev. element index is the one of the ref. (due to this
2643 + * string was found before and was stored on stack)
2645 + if (patTable->mptElements[prevPatRef.prElementIdx]->mpteGroup == groupIdx)
2647 + considerStackPatReference(
2648 + &patTable->mptElements[prevPatRef.prElementIdx]->mpteEnd,
2649 + stack[stackIdx - 1].psePatRef.prElementIdx,
2650 + &prevPatRef.prElementIdx);
2654 + * Ignore current found pattern, if it doesn't fit to the prev.
2657 + if (stack[stackIdx - 1].psePatRef.prElementIdx == prevPatRef.prElementIdx &&
2658 + (stack[stackIdx - 1].pseHighLightCode == prevPatHighLightCode ||
2659 + stack[stackIdx - 1].pseHighLightCode == IGNORE_HIGHLIGHT_CODE ||
2660 + prevPatHighLightCode == IGNORE_HIGHLIGHT_CODE) &&
2661 + doesBackRefInfoMatch(
2662 + &stack[stackIdx - 1].pseBackRefInfo,
2663 + &prevPatBackRefInfo))
2666 + * use context group pattern again, if start pattern
2667 + * to skip to was found.
2671 + currentPatRE = groupPatRE;
2672 + skipToStart = FALSE;
2676 + * pop. related end pattern from stack.
2681 + else if (prevPatRef.prKind == PEK_END)
2683 + if (stackIdx >= MAX_NESTED_PATTERNS)
2686 + printf("BACKWARD: MAX. NESTED PATTERN DEPTH REACHED !\n");
2688 + prevStartPos = -1;
2690 + else if (!skipToStart)
2693 + * Put prev. pattern on stack, if contents between start /
2694 + * end shouldn't be skipped (if "skipToStart" is set,
2695 + * a (usually illegal) end pattern to skip inside the
2696 + * skipped one is found (e.g. *\ *\ ..)
2698 + stack[stackIdx].psePatRef = prevPatRef;
2699 + stack[stackIdx].pseHighLightCode = prevPatHighLightCode;
2700 + stack[stackIdx].pseBackRefInfo = prevPatBackRefInfo;
2704 + patTable->mptElements[prevPatRef.prElementIdx];
2707 + * Use start / end pattern regular expression if skip to
2708 + * end is set for found end pattern.
2710 + if (currentElement->mpteSkipBtwnStartEnd)
2712 + currentPatRE = currentElement->mpteStartEndRE;
2713 + skipToStart = TRUE;
2717 + startPos = prevStartPos - 1;
2720 + return prevStartPos;
2724 +** Adapt found pattern element index depending on
2725 +** the info stored on (last) stack element and
2726 +** a given pattern set (belonging to the found pattern).
2728 +static void considerStackPatReference(
2729 + PatternElementSet *patSet,
2730 + int stackElementIdx,
2731 + int *foundElementIdx)
2733 + PatternElement *patElement;
2737 + * If found pattern index already indicates, that found pattern
2738 + * belongs to pattern set stored on stack, then no adaption is needed
2740 + if (*foundElementIdx == stackElementIdx)
2744 + * Check all elements of given pattern element set:
2746 + for (i=0; i < patSet->pesNumberOfPattern; i++)
2748 + patElement = patSet->pesPattern[i];
2751 + * If this set element is a reference and this reference fits
2752 + * to the element stored on stack, then adapt found element index:
2753 + * indicate, that found pattern belongs to pattern set stored on stack
2755 + if (patElement->peType == PET_REFERENCE &&
2756 + patElement->peVal.peuRef.prElementIdx == stackElementIdx)
2758 + *foundElementIdx = stackElementIdx;
2766 +** Determines, if a string pattern is located at the given position
2767 +** "relBeginPos" in the given "searchRegion". A string pattern is
2768 +** found, if the pattern is located just before given position
2769 +** "relBeginPos" OR if "relBeginPos" is located within a string pattern.
2771 +** Returns true, if the given "pattern" is located at
2772 +** "relBeginPos". "matchInfo" holds all info needed about matched
2773 +** "start" string pattern.
2775 +static int getPatternLocatedAtPos(
2776 + regexp *usedPatRE,
2777 + MatchPatternTable *table,
2778 + SearchRegionInfo *searchRegion,
2780 + MatchingElementInfo *matchInfo,
2781 + const char *delimiters)
2783 + int searchStartPos = *relBeginPos;
2784 + PatternReference *patRef = &matchInfo->meiPatRef;
2785 + FoundStringInfo foundStringInfo;
2786 + int relMatchStartPos;
2787 + int relMatchEndPos;
2789 + patRef->prElementIdx = NO_ELEMENT_IDX;
2790 + patRef->prKind = PEK_UNKNOWN;
2791 + patRef->prPatternIdx = NO_PATTERN_IDX;
2793 + matchInfo->meiHighLightCode = IGNORE_HIGHLIGHT_CODE;
2794 + matchInfo->meiAbsStartPos = -1;
2795 + matchInfo->meiLength = 0;
2798 + * No backward search possible, if we are at beginning of
2801 + if (searchStartPos == 0)
2805 + * Search in backward direction for 1st occurance of a string pattern
2806 + * starting one char before "searchStartPos".
2810 + searchRegion->sriText,
2811 + searchRegion->sriText + searchStartPos - 1,
2813 + searchRegion->sriPrevChar,
2814 + searchRegion->sriText[searchStartPos],
2816 + searchRegion->sriText,
2820 + * String pattern was found:
2822 + foundStringInfo.fsiStartPtr = usedPatRE->startp[0];
2823 + foundStringInfo.fsiEndPtr = usedPatRE->endp[0];
2824 + foundStringInfo.fsiLength =
2825 + foundStringInfo.fsiEndPtr - foundStringInfo.fsiStartPtr;
2827 + relMatchEndPos = foundStringInfo.fsiEndPtr - searchRegion->sriText;
2828 + relMatchStartPos = foundStringInfo.fsiStartPtr - searchRegion->sriText;
2831 + * Is found pattern located exactly one char before "relBeginPos" OR
2832 + * is "relBeginPos" located within found string pattern ?
2833 + * Note: "relMatchEndPos" indicates 1st pos. in "sriText"
2834 + * which does *not* belong to found string anymore.
2836 + if ((*relBeginPos == relMatchEndPos) ||
2837 + (*relBeginPos >= relMatchStartPos &&
2838 + *relBeginPos < relMatchEndPos))
2840 + *relBeginPos = relMatchEndPos;
2843 + * Determine match element info related to found string.
2845 + matchInfo->meiAbsStartPos =
2846 + foundStringInfo.fsiStartPtr - searchRegion->sriText +
2847 + searchRegion->sriStartOfTextPos;
2848 + matchInfo->meiLength = foundStringInfo.fsiLength;
2850 + foundStringInfo.fsiPrevChar =
2851 + foundStringInfo.fsiStartPtr == searchRegion->sriText ?
2852 + searchRegion->sriPrevChar : *(foundStringInfo.fsiStartPtr - 1);
2854 + foundStringInfo.fsiSuccChar =
2855 + *(foundStringInfo.fsiEndPtr) == '\0' ?
2856 + searchRegion->sriSuccChar : *(foundStringInfo.fsiEndPtr);
2858 + foundStringInfo.fsiDelimiters = delimiters;
2861 + getMatchedElementInfo(
2862 + searchRegion->sriWindow,
2873 +** Get all needed info related to matched "start" string pattern
2874 +** (given by parameter "foundStringInfo").
2876 +** Returns true, if info was determined successfully.
2878 +static int getMatchedElementInfo(
2879 + WindowInfo *window,
2880 + MatchPatternTable *table,
2881 + FoundStringInfo *foundStringInfo,
2882 + MatchingElementInfo *matchInfo)
2884 + PatternReference *patRef = &matchInfo->meiPatRef;
2885 + int absMatchStartPos = matchInfo->meiAbsStartPos;
2886 + MatchPatternTableElement *matchedElement;
2888 + if (getPatternInfo(
2892 + &matchInfo->meiBackRefInfo))
2895 + * A pattern reference could be assigned to found string:
2897 + matchedElement = table->mptElements[patRef->prElementIdx];
2899 + matchInfo->meiElement = matchedElement;
2902 + * get highlight code of found string pattern, if applicable
2904 + if (!matchedElement->mpteIgnoreHighLightInfo)
2906 + matchInfo->meiHighLightCode =
2907 + HighlightCodeOfPos(window, absMatchStartPos);
2911 + * setup mono pattern info of found string pattern
2913 + if (matchedElement->mpteIsMonoPattern)
2915 + if (matchedElement->mpteIgnoreHighLightInfo)
2917 + patRef->prMonoInfo = PEMI_MONO_NOT_SYNTAX_BASED;
2922 + * determine mono pattern info depending on highLightCodes
2923 + * before / after found string pattern.
2925 + patRef->prMonoInfo =
2926 + determineMonoPatInfo(
2928 + matchInfo->meiHighLightCode,
2929 + absMatchStartPos - 1,
2930 + absMatchStartPos + matchInfo->meiLength,
2936 + patRef->prMonoInfo = PEMI_NOT_MONO;
2944 + * Found string can't be assigned to a pattern element
2945 + * (should never occur).
2952 +** Returns string pattern of given pattern element.
2954 +StringPattern *GetStringPattern(
2955 + MatchPatternTable *table,
2956 + PatternElement *pattern )
2958 + switch (pattern->peType)
2961 + return &pattern->peVal.peuSingle;
2964 + case PET_MULTIPLE:
2965 + return &pattern->peVal.peuMulti.mpStringPattern;
2968 + case PET_REFERENCE:
2969 + return GetStringPattern(
2971 + getPatternOfReference(table, pattern->peVal.peuRef));
2976 + * never reached; just to make compiler happy
2982 +** Returns pattern element of given pattern reference.
2984 +static PatternElement *getPatternOfReference(
2985 + MatchPatternTable *table,
2986 + PatternReference patRef)
2988 + MatchPatternTableElement **element = table->mptElements;
2990 + return element[ patRef.prElementIdx ]->mpteAll.pesPattern[patRef.prPatternIdx];
2994 +static char *getPatternForDebug(
2995 + MatchPatternTable *table,
2996 + PatternReference patRef )
2998 + if (patRef.prElementIdx < 0)
3006 + getPatternOfReference(table, patRef))->spText;
3009 +static char *patElemKindToString(
3010 + PatternElementKind patElemKind)
3012 + if (patElemKind == PEK_START)
3014 + else if (patElemKind == PEK_MIDDLE)
3016 + else if (patElemKind == PEK_END)
3022 +static void printFoundStringForDebug(
3023 + WindowInfo *window,
3028 + BufGetRange( window->buffer, absStartPos, absStartPos + length);
3030 + printf("%d (abs.) <%s>",
3039 diff --quilt /dev/null new/source/patternMatch.h
3041 +++ new/source/patternMatch.h
3043 +/* $Id: patternMatch.h,v 1.2 2003/10/11 16:45:25 uleh Exp $ */
3045 +#ifndef NEDIT_PATTERNMATCH_H_INCLUDED
3046 +#define NEDIT_PATTERNMATCH_H_INCLUDED
3048 +#include "regularExp.h"
3050 +#define NO_GROUP_IDX -1
3051 +#define NO_ELEMENT_IDX -1
3052 +#define NO_PATTERN_IDX -1
3054 +#define MAX_GLOBAL_BACK_REF_ID 9
3055 +#define NO_LOCAL_BACK_REF_ID -1
3062 +} PatternElementKind;
3066 + PEMI_MONO_NOT_SYNTAX_BASED,
3067 + PEMI_MONO_AMBIGUOUS_SYNTAX,
3068 + PEMI_MONO_DEFINITE_SYNTAX
3069 +} PatternElementMonoInfo;
3071 +typedef struct _PatternReference {
3072 + PatternElementKind prKind;
3073 + PatternElementMonoInfo prMonoInfo;
3076 +} PatternReference;
3082 +} MatchPatternType;
3084 +typedef struct _MatchPatternSequenceElement {
3086 + MatchPatternType mpseType;
3088 +} MatchPatternSequenceElement;
3090 +typedef struct _MatchPatternGroupElement {
3092 + int mpgeNumberOfSubPatterns;
3093 + char **mpgeSubPatternIds;
3094 + regexp *mpgeKeywordRE;
3095 +} MatchPatternGroupElement;
3102 +} PatternWordBoundary;
3104 +typedef struct _StrPatBackRefElement{
3105 + int spbreLocalBackRefID;
3106 + char *spbreRegExpText;
3107 +} StrPatBackRefElement;
3109 +typedef struct _StringPattern {
3112 + PatternWordBoundary spWordBoundary;
3113 + int spCaseInsensitive;
3114 + int spRegularExpression;
3117 + int spBackRefParsed;
3118 + int spBackRefResolved;
3119 + StrPatBackRefElement spOwnGlobalBackRef[MAX_GLOBAL_BACK_REF_ID];
3120 + int spGlobalToLocalBackRef[MAX_GLOBAL_BACK_REF_ID];
3123 +typedef struct _MultiPattern {
3124 + StringPattern mpStringPattern;
3125 + int mpNumberOfReferences;
3126 + PatternReference *mpRefList;
3133 +} PatternElementType;
3135 +typedef struct _PatternElement {
3137 + PatternElementKind peKind;
3138 + PatternElementType peType;
3140 + StringPattern peuSingle;
3141 + MultiPattern peuMulti;
3142 + PatternReference peuRef;
3146 +typedef struct _PatternElementSet {
3147 + int pesNumberOfPattern;
3148 + PatternElement **pesPattern;
3149 +} PatternElementSet;
3151 +typedef struct _GlobalBackRefElement{
3152 + StringPattern *gbreDefByStrPat;
3153 + char *gbreRegExpText;
3154 +} GlobalBackRefElement;
3156 +typedef struct _MatchPatternTableElement {
3159 + MatchPatternType mpteType;
3161 + PatternElementSet mpteAll;
3162 + PatternElementSet mpteStart;
3163 + PatternElementSet mpteMiddle;
3164 + PatternElementSet mpteEnd;
3166 + int mpteIsMonoPattern;
3167 + int mpteSkipBtwnStartEnd;
3168 + int mpteIgnoreHighLightInfo;
3169 + regexp *mpteStartEndRE;
3170 + GlobalBackRefElement mpteGlobalBackRef[MAX_GLOBAL_BACK_REF_ID];
3171 +} MatchPatternTableElement;
3173 +typedef struct _MatchPatternTable {
3174 + int mptNumberOfElements;
3175 + MatchPatternTableElement **mptElements;
3176 +} MatchPatternTable;
3178 +typedef struct _StringMatchTable {
3179 + char *smtLanguageMode;
3180 + MatchPatternTable *smtAllPatterns;
3181 + regexp *smtAllPatRE;
3182 + regexp *smtFlashPatRE;
3183 + regexp *smtUsedPatRE;
3184 + int smtNumberOfGroups;
3185 + MatchPatternGroupElement **smtGroups;
3186 + int smtNumberOfSeqElements;
3187 + MatchPatternSequenceElement **smtSequence;
3188 +} StringMatchTable;
3198 +int FindMatchingString(
3199 + WindowInfo *window,
3200 + MatchingType matchingType,
3208 +StringPattern *GetStringPattern(
3209 + MatchPatternTable *table,
3210 + PatternElement *pattern);
3212 +#endif /* NEDIT_PATTERNMATCH_H_INCLUDED */
3213 diff --quilt /dev/null new/source/patternMatchData.c
3215 +++ new/source/patternMatchData.c
3217 +static const char CVSID[] = "$Id: patternMatchData.c,v 1.4 2004/10/27 21:57:12 uleh Exp $";
3218 +/*******************************************************************************
3220 +* patternMatchData.c -- Maintain and allow user to edit a matching pattern list*
3221 +* used for pattern matching *
3223 +* Copyright (C) 2003-2004, Uwe Lehnert *
3225 +* This is free software; you can redistribute it and/or modify it under the *
3226 +* terms of the GNU General Public License as published by the Free Software *
3227 +* Foundation; either version 2 of the License, or (at your option) any later *
3228 +* version. In addition, you may distribute versions of this program linked to *
3229 +* Motif or Open Motif. See README for details. *
3231 +* This software is distributed in the hope that it will be useful, but WITHOUT *
3232 +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
3233 +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
3234 +* for more details. *
3236 +* You should have received a copy of the GNU General Public License along with *
3237 +* software; if not, write to the Free Software Foundation, Inc., 59 Temple *
3238 +* Place, Suite 330, Boston, MA 02111-1307 USA *
3240 +* Nirvana Text Editor *
3241 +* October 27, 2004 *
3243 +* Written by Uwe Lehnert *
3245 +*******************************************************************************/
3246 +#ifdef HAVE_CONFIG_H
3247 +#include "../config.h"
3250 +#include <stdlib.h>
3252 +#include <limits.h>
3253 +#include <string.h>
3257 +#include "../util/VMSparam.h"
3260 +#include <sys/param.h>
3265 +#include <Xm/Form.h>
3266 +#include <Xm/Frame.h>
3267 +#include <Xm/Text.h>
3268 +#include <Xm/LabelG.h>
3269 +#include <Xm/PushB.h>
3270 +#include <Xm/PushBG.h>
3271 +#include <Xm/ToggleB.h>
3272 +#include <Xm/RowColumn.h>
3273 +#include <Xm/SeparatoG.h>
3275 +#include "../util/misc.h"
3276 +#include "../util/DialogF.h"
3277 +#include "../util/managedList.h"
3279 +#include "regularExp.h"
3280 +#include "textBuf.h"
3282 +#include "window.h"
3283 +#include "preferences.h"
3288 +#include "patternMatch.h"
3289 +#include "patternMatchData.h"
3291 +#ifdef HAVE_DEBUG_H
3292 +#include "../debug.h"
3298 +#define MAX_LOCAL_BACK_REF_ID 9
3299 +#define LOCAL_BACK_REF_ID_USED -2
3301 +#define MAX_NUMBER_MIDDLE_PATTERN 10
3302 +#define MAX_STRING_PATTERNS 30
3303 +#define MAX_NBR_MATCH_PATTERNS 50
3304 +#define MAX_NBR_MATCH_PATTERN_GROUPS 50
3305 +#define MAX_NBR_SEQ_ELEMENTS MAX_NBR_MATCH_PATTERNS + MAX_NBR_MATCH_PATTERN_GROUPS
3307 +#define MATCH_PAT_NAME_LBL_TXT "Matching Pattern Name"
3308 +#define STRING_PATTERNS_LBL_TXT "String Patterns"
3311 +#define LIST_RIGHT 41
3312 +#define PLAIN_LM_STRING "PLAIN"
3314 +#define SPNM_NONE_SELECTED "none selected"
3316 +#define KEEP_LANGUAGE_MODE True
3317 +#define DISCARD_LANGUAGE_MODE False
3319 +#define STRING_PATTERN_DIALOG True
3320 +#define CONTEXT_GROUP_DIALOG False
3323 + * local data definitions
3325 +typedef struct _ErrorInfo {
3327 + char *eiLanguageMode;
3328 + char *eiMPTabElementName;
3329 + char *eiStringPatText;
3330 + char *eiRegExpCompileMsg;
3334 +typedef struct _BackRefBracketInfo {
3336 + char *brbiContentStart;
3337 + int brbiNestingLevel;
3338 +} BackRefBracketInfo;
3340 +typedef struct _RegExpStringInfo {
3341 + int resiNbrOfAddedMultiPat;
3342 + PatternReference **resiAddedMultiPat;
3343 + char *resiNoneWBRegExpString;
3344 + char *resiLeftWBRegExpString;
3345 + char *resiRightWBRegExpString;
3346 + char *resiBothWBRegExpString;
3347 + int resiLocalBackRefID;
3348 +} RegExpStringInfo;
3350 +typedef struct _ReadMatchPatternInfo {
3351 + int rmpiNbrOfElements;
3352 + MatchPatternTableElement *rmpiElement[MAX_NBR_MATCH_PATTERNS];
3353 + int rmpiNbrOfGroups;
3354 + MatchPatternGroupElement *rmpiGroup[MAX_NBR_MATCH_PATTERN_GROUPS];
3355 + int rmpiNbrOfSeqElements;
3356 + MatchPatternSequenceElement *rmpiSequence[MAX_NBR_SEQ_ELEMENTS];
3357 + regexp *rmpiAllPatRE;
3358 + regexp *rmpiFlashPatRE;
3359 +} ReadMatchPatternInfo;
3361 +typedef struct _DialogStringPatternElement {
3363 + PatternElementKind dspeKind;
3364 + PatternWordBoundary dspeWordBoundary;
3365 + int dspeCaseInsensitive;
3366 + int dspeRegularExpression;
3367 +} DialogStringPatternElement;
3369 +typedef struct _DialogStringPatterns {
3370 + int dspNumberOfPatterns;
3371 + DialogStringPatternElement *dspElements[MAX_STRING_PATTERNS];
3372 +} DialogStringPatterns;
3374 +typedef struct _DialogMatchPatternTableElement {
3376 + MatchPatternType dmpteType;
3377 + DialogStringPatterns dmptePatterns;
3378 + int dmpteSkipBtwnStartEnd;
3379 + int dmpteIgnoreHighLightInfo;
3381 +} DialogMatchPatternTableElement;
3383 +typedef struct _DialogMatchPatternGroupElement {
3385 + int dmpgeNumberOfSubPatterns;
3386 + char *dmpgeSubPatternIds[MAX_NBR_MATCH_PATTERNS];
3387 +} DialogMatchPatternGroupElement;
3389 +typedef struct _DialogMatchPatternSequenceElement {
3391 + MatchPatternType dmpseType;
3394 +} DialogMatchPatternSequenceElement;
3396 +typedef struct _DialogMatchPatternInfo {
3397 + int dmpiNbrOfSeqElements;
3398 + DialogMatchPatternSequenceElement *dmpiSequence[MAX_NBR_SEQ_ELEMENTS];
3399 +} DialogMatchPatternInfo;
3405 +} DMPTranslationResult;
3407 +typedef struct _NameList {
3409 + char *nlId[MAX_NBR_SEQ_ELEMENTS + 1];
3413 + * prototypes of local functions
3415 +static void treatDuplicatedPattern(
3416 + MatchPatternTable *table,
3417 + PatternElement *prevPattern,
3418 + PatternReference prevPatRef,
3419 + PatternElement *lastPattern,
3420 + PatternReference lastPatRef);
3421 +static void treatDuplicatedPatternElements(
3422 + MatchPatternTable *table,
3423 + MatchPatternTableElement *prevElement,
3424 + int prevElementIdx,
3425 + PatternElement *lastPattern,
3426 + PatternReference lastPatRef);
3427 +static void treatDuplicatedMTElements(
3428 + MatchPatternTable *table,
3429 + MatchPatternTableElement *prevElement,
3430 + int prevElementIdx,
3431 + MatchPatternTableElement *lastElement,
3432 + int lastElementIdx);
3433 +static void treatDuplicatedMTEntries(
3434 + MatchPatternTableElement **element,
3435 + int nbrOfElements);
3437 +static int createStrPatRegExpOfElement(
3438 + ReadMatchPatternInfo *readPatInfo,
3439 + MatchPatternTableElement *element,
3440 + ErrorInfo *errInfo);
3441 +static int createStrPatRegExp(
3442 + StringPattern *strPat,
3443 + ErrorInfo *errInfo);
3444 +static void adaptCompileMsg(
3446 + int *globalToLocalBackRef);
3447 +static int localToGlobalBackRef(
3448 + int *globalToLocalBackRef,
3450 +static int createStartEndRegExp(
3451 + ReadMatchPatternInfo *readMatchPatternInfo,
3452 + MatchPatternTableElement *element,
3453 + ErrorInfo *errInfo);
3454 +static int createGroupRegExp(
3455 + ReadMatchPatternInfo *readPatInfo,
3456 + MatchPatternGroupElement *group,
3457 + ErrorInfo *errInfo);
3458 +static void setupRegExpStringBuffers(
3459 + ReadMatchPatternInfo *readMatchPatternInfo,
3460 + RegExpStringInfo *regExpStringInfo);
3461 +static void addSMTRegExpString(
3464 + const char *postfix);
3465 +static void composeStartEndRegExpString(
3466 + ReadMatchPatternInfo *readMatchPatternInfo,
3467 + MatchPatternTableElement *element,
3468 + char **regExpString);
3469 +static void addElementToRegExpString(
3470 + MatchPatternTableElement *element,
3471 + ReadMatchPatternInfo *readMatchPatternInfo,
3472 + RegExpStringInfo *regExpStringInfo);
3473 +static void addUniquePatternToRegExpString(
3474 + PatternElement *patElement,
3475 + PatternReference *patElementReference,
3476 + ReadMatchPatternInfo *readMatchPatternInfo,
3477 + RegExpStringInfo *regExpStringInfo);
3478 +static void addPatternToRegExpString(
3479 + StringPattern *pattern,
3480 + RegExpStringInfo *regExpStringInfo);
3481 +static char *adaptLocalBackRefs(
3483 + int *commonLocalId);
3484 +static void scanForLocalBackRefs(
3486 + int *localBackRefList);
3487 +static int isMultiPatternNotAdded(
3488 + RegExpStringInfo *regExpStringInfo,
3489 + PatternReference *toBeAddedPR);
3490 +static void catSMTRegExpStrings(
3491 + RegExpStringInfo *regExpStringInfo,
3492 + char **regExpString);
3493 +static void freeRegExpStringInfo(
3494 + RegExpStringInfo *regExpStringInfo);
3495 +static int totalKeywordOfTableLen(
3496 + ReadMatchPatternInfo *info,
3497 + int *nbrOfMultiPatterns);
3498 +static int totalMatchPatternTableElementLen(
3499 + ReadMatchPatternInfo *info,
3500 + MatchPatternTableElement *element,
3501 + int *nbrOfMultiPatterns);
3502 +static int patternElementLen(
3503 + ReadMatchPatternInfo *info,
3504 + PatternElement *patElement,
3505 + int *nbrOfMultiPatterns);
3507 +static void parseMatchingPatternSetError(
3508 + const char *stringStart,
3509 + const char *stoppedAt,
3510 + ErrorInfo *errInfo);
3511 +static void dialogMatchingPatternSetError(
3513 + ErrorInfo *errInfo);
3515 +static char *createMatchPatternsString(
3516 + StringMatchTable *table,
3518 +static char *createPatternElementString(
3519 + MatchPatternTable *table,
3520 + PatternElement *pat);
3522 +static StringMatchTable *readDefaultStringMatchTable(const char *langModeName);
3523 +static int isDefaultMatchPatternTable(StringMatchTable *table);
3525 +static void freeReadMatchPatternInfo( ReadMatchPatternInfo *readPatInfo );
3526 +static void freeStringMatchTable( StringMatchTable *table );
3527 +static void freeMatchPatternTableElement( MatchPatternTableElement *element );
3528 +static void freePatternElement( PatternElement *element );
3529 +static void freeStringPattern( StringPattern *strPat );
3530 +static void freeMatchPatternGroupElement( MatchPatternGroupElement *group );
3531 +static void freeMatchPatternSequenceElement( MatchPatternSequenceElement *sequence );
3533 +static StringMatchTable *readMatchPatternSet(char **inPtr);
3534 +static StringMatchTable *readMatchPatternSetContent(
3536 + char *stringStart,
3537 + char *languageMode);
3538 +static int createRegExpOfPatterns(
3539 + ReadMatchPatternInfo *readPatInfo,
3540 + ErrorInfo *errInfo);
3541 +static int createRegExpOfAllPatterns(
3542 + ReadMatchPatternInfo *readPatInfo,
3543 + ErrorInfo *errInfo);
3544 +static int createRegExpOfStrPatterns(
3545 + ReadMatchPatternInfo *readPatInfo,
3546 + ErrorInfo *errInfo);
3547 +static StringMatchTable *createStringMatchTable(
3548 + ReadMatchPatternInfo *readPatInfo,
3549 + char *languageMode);
3550 +static int readMatchPatternEntry(
3552 + ErrorInfo *errInfo,
3553 + ReadMatchPatternInfo *info);
3554 +static void recordPatternSequence(
3555 + ReadMatchPatternInfo *info,
3557 + MatchPatternType type,
3559 +static int assignIndividualGroup(
3560 + ReadMatchPatternInfo *info,
3562 + MatchPatternTableElement *element);
3563 +static MatchPatternTableElement *getPatternOfName(
3564 + ReadMatchPatternInfo *info,
3565 + char *subPatToSearch);
3566 +static MatchPatternGroupElement *readMatchPatternGroup(
3568 + ErrorInfo *errInfo,
3570 + ReadMatchPatternInfo *info);
3571 +static int readPatternElement(
3574 + PatternElement **pattern);
3575 +static PatternElement *createPatternElement(
3576 + char *patternText,
3577 + PatternElementKind patternKind,
3578 + PatternWordBoundary wordBoundary,
3579 + int caseInsensitive,
3580 + int regularExpression);
3582 +static int createGlobalBackRefList(
3583 + ReadMatchPatternInfo *readPatInfo,
3584 + MatchPatternTableElement *element,
3585 + ErrorInfo *errInfo);
3586 +StringPattern *getReadStringPattern(
3587 + ReadMatchPatternInfo *readPatInfo,
3588 + PatternElement *pattern );
3589 +static PatternElement *getReadPatternOfReference(
3590 + ReadMatchPatternInfo *readPatInfo,
3591 + PatternReference *patRef);
3592 +static char *replaceCapturingParentheses(
3593 + const char *source);
3594 +static int parseGlobalBackRefs(
3595 + StringPattern *strPat,
3596 + GlobalBackRefElement *backRefList,
3597 + ErrorInfo *errInfo);
3598 +static int updateGlobalBackRefs(
3599 + StringPattern *strPat,
3600 + GlobalBackRefElement *backRefList,
3601 + ErrorInfo *errInfo);
3602 +static char *createBackRefRegExpText(
3603 + const char *start,
3605 +static int resolveGlobalBackRefs(
3606 + ReadMatchPatternInfo *readPatInfo,
3607 + MatchPatternTableElement *element,
3608 + ErrorInfo *errInfo);
3609 +static int resolveGlobalBackRefsOfStrPat(
3610 + StringPattern *strPat,
3611 + GlobalBackRefElement *backRefList,
3612 + ErrorInfo *errInfo);
3613 +static char *substituteGlobalBackRef(
3614 + StringPattern *strPat,
3618 + GlobalBackRefElement *backRefList,
3619 + ErrorInfo *errInfo);
3620 +static char *replaceBackRefIdByRegExp(
3621 + StringPattern *strPat,
3622 + char *replaceStartPtr,
3624 +static char *convertGlobalToLocalBackRef(
3625 + StringPattern *strPat,
3626 + char *convertPtr);
3628 +static MatchPatternTableElement *readMatchPatternTableElement(
3632 + MatchPatternType type);
3633 +static int sortReadPatternElementSet(
3634 + PatternElementSet *allPat,
3636 + MatchPatternTableElement *result);
3637 +static void countPatternElementKind(
3638 + PatternElementSet *allPat,
3639 + MatchPatternTableElement *result);
3640 +static void sortPatternElementSet(
3641 + PatternElementSet *allPat,
3642 + MatchPatternTableElement *result);
3643 +static void copyPatternSet(
3644 + PatternElementSet *sourcePS,
3645 + PatternElementSet *destPS);
3647 +static int getMPSName(
3649 + ErrorInfo *errInfo,
3651 +static int getMPSTypeAttribute(
3653 + ErrorInfo *errInfo,
3654 + MatchPatternType *type);
3655 +static int getMPSGlobalAttribute(
3658 + int *isMonoPattern,
3661 + int *ignoreHighLightInfo);
3662 +static int getMPSPatternAttribute(
3665 + PatternElementKind *patternKind,
3666 + PatternWordBoundary *wordBoundary,
3667 + int *caseInsensitive,
3668 + int *regularExpression);
3670 +static void copyStringMatchTableForDialog(
3671 + StringMatchTable *sourceTable,
3672 + DialogMatchPatternInfo *dialogTable );
3673 +static void *copyMatchPatternElementForDialog(
3674 + MatchPatternTable *table,
3675 + int sourceElementIdx);
3676 +static void copyPatternForDialog(
3677 + MatchPatternTable *table,
3678 + PatternElement *sourcePattern,
3679 + DialogStringPatternElement **dialogPattern );
3680 +static void *copyGroupElementForDialog(
3681 + MatchPatternGroupElement *sourceGroup);
3682 +static void copySequenceElementForDialog(
3683 + StringMatchTable *sourceTable,
3684 + MatchPatternSequenceElement *sourceSeqElement,
3685 + DialogMatchPatternSequenceElement **dialogSeqElement );
3686 +static DialogMatchPatternSequenceElement *copyDialogSequenceElement(
3687 + DialogMatchPatternSequenceElement *sourceSeq);
3688 +static void freeDialogMatchPatternElement(
3689 + DialogMatchPatternTableElement *dialogElement );
3690 +static void freeDialogStringPatternElement(
3691 + DialogStringPatternElement *element);
3692 +static void freeDialogGroupElement(
3693 + DialogMatchPatternGroupElement *dialogGroup );
3694 +static void freeDialogSequenceElement(
3695 + DialogMatchPatternSequenceElement *dialogSeq );
3697 +static void copyDialogStringPatternsFromTable(
3698 + DialogMatchPatternTableElement *tableElement,
3699 + DialogStringPatterns *destPatterns);
3700 +static void copyDialogStringPatterns(
3701 + DialogStringPatterns *sourcePatterns,
3702 + DialogStringPatterns *destPatterns);
3703 +static void freeDialogStringPatterns(
3704 + DialogStringPatterns *patterns);
3706 +static DialogStringPatternElement *copyDialogStringPatternElement(
3707 + DialogStringPatternElement *sourceElement);
3709 +static void copyDialogPatternNamesFromGroup(
3710 + DialogMatchPatternGroupElement *group,
3711 + DialogStringPatterns *destPatterns);
3712 +static DialogStringPatternElement *copyDialogPatternName(
3713 + char *sourcePatternId);
3714 +static void copyDialogPatternNamesToGroup(
3715 + DialogStringPatterns *sourceNames,
3716 + DialogMatchPatternGroupElement *destGroup);
3718 +static void setDialogType(int dialogShowsStringPattern);
3719 +static void setSensitiveWordBoundaryBox(int enable);
3721 +static void *getStringPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
3723 +static void setStringPatternDisplayedCB(void *item, void *cbArg);
3724 +static void freeStringPatternItemCB(void *item);
3726 +static void *getMatchPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
3728 +static void setMatchPatternDisplayedCB(void *item, void *cbArg);
3729 +static void freeMatchPatternItemCB(void *item);
3730 +static int deleteMatchPatternItemCB(int itemIndex, void *cbArg);
3732 +static void matchPatternLangModeCB(Widget w, XtPointer clientData, XtPointer callData);
3733 +static void pmLanguageModeDialogCB(Widget w, XtPointer clientData, XtPointer callData);
3735 +static void destroyCB(Widget w, XtPointer clientData, XtPointer callData);
3736 +static void okCB(Widget w, XtPointer clientData, XtPointer callData);
3737 +static void applyCB(Widget w, XtPointer clientData, XtPointer callData);
3738 +static void checkCB(Widget w, XtPointer clientData, XtPointer callData);
3739 +static void restoreCB(Widget w, XtPointer clientData, XtPointer callData);
3740 +static void deleteCB(Widget w, XtPointer clientData, XtPointer callData);
3741 +static void closeCB(Widget w, XtPointer clientData, XtPointer callData);
3742 +static void helpCB(Widget w, XtPointer clientData, XtPointer callData);
3744 +static void matchPatTypeCB(Widget w, XtPointer clientData, XtPointer callData);
3745 +static void strPatRegExpressionCB(Widget w, XtPointer clientData, XtPointer callData);
3746 +static void changeExistingSubPattern(char *warnTitle);
3747 +static void changeStringPatternToGroup(void);
3748 +static void changeGroupToStringPattern(char *warnTitle);
3750 +static Widget createSubPatternNameMenu(
3752 + char *currentSubPatName,
3753 + int allSubPatterns);
3754 +static void setupSubPatternNameList(
3755 + char *currentSubPatName,
3756 + int allSubPatterns,
3757 + NameList *nameList);
3758 +static void createSubPatNameMenuEntry(
3760 + char *subPatName);
3761 +static void setSubPatternNameMenu(
3762 + const char *subPatName);
3763 +static void updateSubPatternNameMenu(
3764 + char *currentSubPatName,
3765 + int allSubPatterns);
3766 +static char *getSelectedSubPatternName(void);
3767 +static int isSubPatternNameInCurStrPat(
3768 + char *subPatName);
3770 +static DialogMatchPatternSequenceElement *readMatchPatternFields(int silent);
3771 +static int isStartPatternElementAvailable(
3772 + DialogStringPatterns *dialogPatterns);
3773 +static DialogStringPatternElement *readStringPatternFrameFields(int silent);
3775 +static int matchPatternDialogEmpty(void);
3776 +static int stringPatternFrameEmpty(void);
3777 +static int stringPatternFieldsEmpty(
3778 + int strPatIsRelatedToGroup);
3780 +static int getAndUpdateStringMatchTable(void);
3781 +static void updateStringMatchTable(
3782 + StringMatchTable *newTable);
3784 +static StringMatchTable *getDialogStringMatchTable(
3785 + DMPTranslationResult *result);
3786 +static StringMatchTable *translateDialogStringMatchTable(
3787 + DialogMatchPatternInfo *dialogTable,
3788 + DMPTranslationResult *result);
3789 +static MatchPatternTableElement *translateDialogMatchPatternTableElement(
3790 + DialogMatchPatternTableElement *dialogElement);
3791 +static void translateDialogPatterns(
3792 + DialogStringPatterns *dialogPatterns,
3793 + MatchPatternTableElement *newElement);
3794 +static MatchPatternGroupElement *translateDialogMatchPatternGroupElement(
3795 + ReadMatchPatternInfo *info,
3796 + DialogMatchPatternGroupElement *dialogGroup);
3797 +static void sortDialogPatternElementSet(
3798 + PatternElementSet *allPat,
3799 + MatchPatternTableElement *result);
3801 +static int stringMatchTableDiffer(
3802 + StringMatchTable *oldTable,
3803 + StringMatchTable *newTable);
3805 +static int patternElementDiffer(
3806 + PatternElement *oldPE,
3807 + MatchPatternTable *oldTab,
3808 + PatternElement *newPE,
3809 + MatchPatternTable *newTab);
3811 +static DialogMatchPatternGroupElement *getDialogGroupUsingMatchPattern(
3812 + char *matchPatternName);
3813 +static void removeMatchPatternFromGroup(
3814 + char *matchPatternName,
3815 + DialogMatchPatternGroupElement *group);
3816 +static void removeMatchPatternFromAllGroups(
3817 + char *matchPatternName);
3818 +static void renameMatchPatternInGroup(
3819 + char *oldMatchPatternName,
3820 + char *newMatchPatternName,
3821 + DialogMatchPatternGroupElement *group);
3822 +static void renameMatchPatternInAllGroups(
3823 + char *oldMatchPatternName,
3824 + char *newMatchPatternName);
3826 +static void freeVariableDialogData(
3827 + int keepLanguageModeName);
3829 +static void initGlobalBackRefList(
3830 + GlobalBackRefElement *list);
3831 +static void initStrPatBackRefList(
3832 + StringPattern *strPat);
3834 +StringPattern *getUniqueStringPattern(
3835 + PatternElement *pattern );
3837 +static void initErrorInfo(
3838 + ErrorInfo *errInfo);
3839 +static void freeErrorInfo(
3840 + ErrorInfo *errInfo);
3842 +static void freeXtPtr(void **ptr);
3843 +static void freePtr(void **ptr);
3846 + * matching pattern dialog information
3850 + Widget mpdLmOptMenu;
3851 + Widget mpdLmPulldown;
3852 + Widget mpdMatchPatternNamesListW;
3853 + Widget mpdMatchPatternNameLbl;
3854 + Widget mpdMatchPatternNameW;
3855 + Widget mptbIndividualW;
3856 + Widget mptbSubPatternW;
3857 + Widget mptbContextGroupW;
3858 + Widget mpdGlobalAttributesLbl;
3859 + Widget gabSkipBtwStartEndW;
3861 + Widget gabSyntaxBasedW;
3862 + Widget mpdStringPatternsLbl;
3863 + Widget mpdStringPatternsListW;
3864 + Widget mpdStringPatternTypeLbl;
3866 + Widget sptMiddleW;
3868 + Widget mpdWordBoundaryLbl;
3873 + Widget mpdStringAttributesLbl;
3874 + Widget sabCaseSensitiveW;
3875 + Widget sabRegularExpressionW;
3876 + Widget mpdStringPatternLbl;
3877 + Widget mpdStringPatternW;
3878 + Widget mpdSubPatNamesLbl;
3879 + Widget mpdSubPatNamesOptMenu;
3880 + Widget mpdSubPatNamesPulldown;
3881 + char *mpdLangModeName;
3882 + DialogMatchPatternSequenceElement *currentDmptSeqElement;
3883 + DialogMatchPatternTableElement *currentDmptElement;
3884 + DialogMatchPatternGroupElement *currentDmptGroup;
3885 + DialogStringPatterns currentStringPatterns;
3886 + DialogMatchPatternInfo mpdTable;
3887 + int mpdStringPatternIsDisplayed;
3888 +} MatchPatternDialog =
3889 + {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3890 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3891 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3892 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3893 + NULL, NULL, NULL, NULL,
3900 + * Matching pattern sources loaded from the nedit resources file or set
3903 +static int NbrMatchTables = 0;
3904 +static StringMatchTable *MatchTables[MAX_LANGUAGE_MODES];
3908 + * LanguagePatternSet ::=
3909 + * LanguageName{PatternStatement..}
3911 + * PatternStatement ::=
3912 + * name:[s]:[c][f][m][p][u]:([s|m|e][w|l|r][i]:"pattern":)..)\n)|
3913 + * name:g:"sub-pattern name":..\n..
3916 + * s : sub-pattern (pattern is only matched, if part of a pattern group).
3917 + * g : pattern (context) group (i.e. a sequence of sub-patterns).
3918 + * default: individual pattern (pattern is matched individually).
3919 + * GlobalAttribute:
3920 + * c : the content between start and end pattern is skipped
3921 + * during parsing (e.g. pattern encloses a comment).
3922 + * f : flash matching pattern (if not set, then only jump
3923 + * to matching pattern is supported).
3924 + * m : mono pattern - set exist out of only one single pattern
3925 + * (start pattern = end pattern; e.g. quotes like ")
3926 + * p : ignore highlight info code of single patterns of this set
3928 + * StringPatternKind:
3929 + * s : start string pattern.
3930 + * m : middle string pattern.
3931 + * e : end string pattern.
3932 + * WordBoundaryAttribute:
3933 + * w : pattern is word (i.e. before and after pattern
3934 + * there must be a delimiter).
3935 + * l : before pattern must be a delimiter (left side).
3936 + * r : after pattern must be a delimiter (right side).
3937 + * default: neither before nor after pattern must be a delimiter.
3938 + * StringAttribute:
3939 + * i : pattern is case insensitive (if not set: pattern is
3940 + * case sensitive).
3941 + * x : pattern is regular expression (if not set: pattern is
3942 + * literal string).
3944 + * \n : end of pattern
3947 +static char *DefaultStringMatchTable[] = {
3949 + "Round braces::fp:s:\"(\":e:\")\":\n"
3950 + "Curly braces::fp:s:\"{\":e:\"}\":\n"
3951 + "Squared braces::fp:s:\"[\":e:\"]\":\n"
3952 + "Sharp braces::fp:s:\"<\":e:\">\":\n}",
3954 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
3955 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3956 + "Single Quotes:s:cmf:s:\"'\":\n"
3957 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3958 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3959 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3960 + "#ifdef statement:s:f:sx:\"#\\s*ifdef\":sx:\"#\\s*ifndef\":sx:\"#\\s*if\":mx:\"#\\s*elif\":mx:\"#\\s*else\":ex:\"#\\s*endif\":\n"
3961 + "#if group:g:Comment:Double Quotes:Single Quotes:#ifdef statement:\n"
3962 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
3964 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
3965 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3966 + "Single Quotes:s:cmf:s:\"'\":\n"
3967 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3968 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3969 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3970 + "#ifdef statement:s:f:sx:\"#\\s*ifdef\":sx:\"#\\s*ifndef\":sx:\"#\\s*if\":mx:\"#\\s*elif\":mx:\"#\\s*else\":ex:\"#\\s*endif\":\n"
3971 + "#if group:g:Comment:Double Quotes:Single Quotes:#ifdef statement:\n"
3972 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
3974 + "comment:s:cf:s:\"/*\":e:\"*/\":\n"
3975 + "curly braces:s:f:s:\"{\":e:\"}\":\n"
3976 + "round braces:s:f:s:\"(\":e:\")\":\n"
3977 + "double quotes:s:cfm:s:\"\"\"\":\n"
3978 + "single quotes:s:cfm:s:\"'\":\n"
3979 + "braces:g:comment:single quotes:double quotes:curly braces:round braces:\n}",
3981 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3982 + "Single Quotes:s:cmf:s:\"'\":\n"
3983 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3984 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3985 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3986 + "if statement:s:f:sw:\"if\":mw:\"else\":ew:\"endif\":\n"
3987 + "switch statement:s:f:sw:\"switch\":mw:\"case\":mw:\"default\":ew:\"endsw\":\n"
3988 + "foreach statement:s:f:sw:\"for\":ew:\"end\":\n"
3989 + "while statement:s:f:sw:\"while\":ew:\"end\":\n"
3990 + "statement group:g:Double Quotes:Single Quotes:if statement:switch statement:foreach statement:while statement:\n"
3991 + "Braces:g:Double Quotes:Single Quotes:Squared braces:Round braces:Curly braces:\n}",
3993 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
3994 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3995 + "Single Quotes:s:cmf:s:\"'\":\n"
3996 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3997 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3998 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3999 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
4001 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
4002 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4003 + "Single Quotes:s:cmf:s:\"'\":\n"
4004 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4005 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4006 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4007 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
4009 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4010 + "Single Quotes:s:cmf:s:\"'\":\n"
4011 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4012 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4013 + "Braces:g:Double Quotes:Single Quotes:Curly braces:Round braces:\n}",
4015 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4016 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4017 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4018 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4019 + "Braces:g:Double Quotes:Curly braces:Round braces:Squared braces:\n}",
4021 + "Single Quotes:s:cmf:s:\"'\":\n"
4022 + "Comment1:s:cf:s:\"(*\":e:\"*)\":\n"
4023 + "Comment2:s:cf:s:\"{\":e:\"}\":\n"
4024 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4025 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4026 + "Block:s:f:swi:\"begin\":ewi:\"end\":\n"
4027 + "Case:s:fp:swi:\"case\":ewi:\"end\":\n"
4028 + "Record:s:f:swi:\"record\":ewi:\"end\":\n"
4029 + "Statement:g:Comment1:Comment2:Single Quotes:Block:Case:Record:\n"
4030 + "Braces:g:Comment1:Comment2:Single Quotes:Round braces:Squared braces:\n}",
4032 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
4033 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4034 + "Single Quotes:s:cmf:s:\"'\":\n"
4035 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4036 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4037 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4038 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
4040 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4041 + "Single Quotes:s:cmf:s:\"'\":\n"
4042 + "Sharp braces:s:f:s:\"<\":e:\">\":\n"
4043 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4044 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4045 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4046 + "Braces:g:Double Quotes:Single Quotes:Sharp braces:Curly braces:Round braces:Squared braces:\n}",
4048 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4049 + "Single Quotes:s:cmf:s:\"'\":\n"
4050 + "Back Quotes:s:cfm:s:\"`\":\n"
4051 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4052 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4053 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4054 + "if statement:s:f:sw:\"if\":mw:\"elif\":mw:\"else\":ew:\"fi\":\n"
4055 + "case statement:s:f:sw:\"case\":ew:\"esac\":\n"
4056 + "for statement:s:f:sw:\"for\":mw:\"do\":ew:\"done\":\n"
4057 + "while statement:s:f:sw:\"while\":mw:\"do\":ew:\"done\":\n"
4058 + "statement group:g:Double Quotes:Single Quotes:if statement:case statement:for statement:while statement:\n"
4059 + "Braces:g:Double Quotes:Single Quotes:Back Quotes:Squared braces:Round braces:Curly braces:\n}",
4061 + "round braces:s:f:s:\"(\":e:\")\":\n"
4062 + "comment:s:cf:s:\"<!--\":e:\"-->\":\n"
4063 + "cdata + ignore:s:cf:sx:\"\\<!\\[((?icdata)|(\\s*IGNORE\\s*))\\[\":ex:\"\\]\\]\\>\":\n"
4064 + "short element:s:cf:sx:\"(?n\\<[\\l_][^@$%/\"\"';!>\\s]*(?=[^>]*/\\>))\":ex:\"/\\>\":\n"
4065 + "element pair:s:f:sx:\"(?n\\<(*1[\\l|_][^@$%/\"\"';!>\\s]*)\\>)\":sx:\"(?n\\<(*1[\\l|_][^@$%/\"\"';!>\\s]*)(?=[^>]*[^/]\\>))\":eix:\"\\</\\1\\>\":\n"
4066 + "processing instruction:s:f:sx:\"\\<\\?\\S+\":ex:\"\\?\\>\":\n"
4067 + "double quotes:s:cmf:s:\"\"\"\":\n"
4068 + "single quotes:s:cmf:s:\"'\":\n"
4069 + "tags:g:comment:double quotes:single quotes:round braces:cdata + ignore:element pair:short element:processing instruction:\n}",
4072 +static char *StandardStringMatchTable =
4073 + "{Round braces::fp:s:\"(\":e:\")\":\n"
4074 + "Curly braces::fp:s:\"{\":e:\"}\":\n"
4075 + "Squared braces::fp:s:\"[\":e:\"]\":\n}";
4078 +** Return string match table related to given language mode name.
4079 +** Return NULL, if no table is found.
4081 +void *FindStringMatchTable(const char *langModeName)
4083 + const char *nameToSearch;
4086 + if (langModeName == NULL)
4087 + nameToSearch = PLAIN_LM_STRING;
4089 + nameToSearch = langModeName;
4091 + for (i=0; i<NbrMatchTables; i++)
4092 + if (!strcmp(nameToSearch, MatchTables[i]->smtLanguageMode))
4093 + return (void *)MatchTables[i];
4098 +** Change the language mode name of string match tables for language
4099 +** "oldName" to "newName" in both the stored tables, and the table
4100 +** currently being edited in the dialog.
4102 +void RenameStringMatchTable(const char *oldName, const char *newName)
4106 + for (i=0; i<NbrMatchTables; i++)
4108 + if (!strcmp(oldName, MatchTables[i]->smtLanguageMode))
4110 + XtFree(MatchTables[i]->smtLanguageMode);
4111 + MatchTables[i]->smtLanguageMode = XtNewString(newName);
4114 + if (MatchPatternDialog.mpdShell != NULL)
4116 + if (!strcmp(MatchPatternDialog.mpdLangModeName, oldName))
4118 + XtFree(MatchPatternDialog.mpdLangModeName);
4119 + MatchPatternDialog.mpdLangModeName = XtNewString(newName);
4125 +** Delete string match table related to given language mode name.
4127 +void DeleteStringMatchTable(const char *langModeName)
4131 + for (i=0; i<NbrMatchTables; i++)
4133 + if (!strcmp(langModeName, MatchTables[i]->smtLanguageMode))
4136 + * free (delete) existing matching pattern
4138 + freeStringMatchTable(MatchTables[i]);
4141 + &MatchTables[i+1],
4142 + (NbrMatchTables-1 - i) * sizeof(StringMatchTable *));
4150 +** Assign a standard string match table to a given new language mode.
4152 +void AssignStandardStringMatchTable(const char *langModeName)
4155 + StringMatchTable *newTable;
4158 + * assign standard table for new language mode
4159 + * add table to end
4161 + list = StandardStringMatchTable;
4163 + readMatchPatternSetContent(&list, list, XtNewString(langModeName));
4166 + * add table to end
4168 + MatchTables[NbrMatchTables++] = newTable;
4172 +** Returns True if there is a string match table, or potential table
4173 +** not yet committed in the match pattern dialog for a language mode,
4175 +int LMHasStringMatchTable(const char *languageMode)
4177 + StringMatchTable *table = FindStringMatchTable(languageMode);
4179 + if (table != NULL && table->smtNumberOfSeqElements != 0)
4181 + return MatchPatternDialog.mpdShell != NULL &&
4182 + !strcmp(MatchPatternDialog.mpdLangModeName, languageMode) &&
4183 + MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements != 0;
4187 +** Read a string representing string matching pattern sets and add them
4188 +** to the StringMatchTable list of loaded string match patterns.
4189 +** Returns true, if read of string was successful.
4191 +int LoadMatchPatternString(char *inString)
4193 + char *inPtr = inString;
4194 + StringMatchTable *table;
4200 + * read each matching pattern set
4202 + table = readMatchPatternSet(&inPtr);
4204 + if (table != NULL)
4207 + * add/change the pattern set in the list
4209 + for (i=0; i<NbrMatchTables; i++)
4211 + if (!strcmp(MatchTables[i]->smtLanguageMode, table->smtLanguageMode))
4213 + freeStringMatchTable(MatchTables[i]);
4214 + MatchTables[i] = table;
4218 + if (i == NbrMatchTables)
4220 + MatchTables[NbrMatchTables++] = table;
4221 + if (NbrMatchTables > MAX_LANGUAGE_MODES)
4229 + * find end of this pattern. if the string ends here, we're done
4231 + inPtr = strstr(inPtr, "\n");
4232 + if (inPtr == NULL)
4238 + * skip newline, tabs & spaces in front of next pattern.
4239 + * if the string ends here, we're done
4241 + inPtr += strspn(inPtr, " \t\n");
4242 + if (*inPtr == '\0')
4250 +** Create a string in the correct format for the matchPatterns resource,
4251 +** containing all of the matching pattern information from the stored
4252 +** matching pattern sets for this NEdit session.
4254 +char *WriteMatchPatternString(void)
4256 + char *outStr, *str, *escapedStr;
4257 + textBuffer *outBuf;
4258 + int i, written = False;
4259 + StringMatchTable *table;
4261 + outBuf = BufCreate();
4263 + for (i=0; i<NbrMatchTables; i++)
4265 + table = MatchTables[i];
4269 + BufInsert(outBuf, outBuf->length, table->smtLanguageMode);
4270 + BufInsert(outBuf, outBuf->length, ":");
4272 + if (isDefaultMatchPatternTable(table))
4274 + BufInsert(outBuf, outBuf->length, "Default\n\t");
4278 + BufInsert(outBuf, outBuf->length, "{\n");
4279 + BufInsert(outBuf, outBuf->length,
4280 + str = createMatchPatternsString(table, "\t\t"));
4282 + BufInsert(outBuf, outBuf->length, "\t}\n\t");
4287 + * Get the output string, and lop off the trailing newline and tab
4289 + outStr = BufGetRange(outBuf, 0, outBuf->length - (written?2:0));
4293 + * Protect newlines and backslashes from translation by the resource
4296 + escapedStr = EscapeSensitiveChars(outStr);
4300 + return escapedStr;
4304 +** Check, if last pattern is a duplicate of a previous pattern.
4305 +** Convert last pattern to a reference, if so.
4307 +static void treatDuplicatedPattern(
4308 + MatchPatternTable *table,
4309 + PatternElement *prevPattern,
4310 + PatternReference prevPatRef,
4311 + PatternElement *lastPattern,
4312 + PatternReference lastPatRef)
4314 + StringPattern *prevStringPat;
4315 + StringPattern *lastStringPat;
4316 + StringPattern *stringPat;
4317 + PatternReference *oldList;
4321 + * No duplicate check needed, if previous pattern is a reference,
4322 + * due to the related multi pattern element is checked before.
4324 + if (prevPattern->peType == PET_REFERENCE)
4327 + prevStringPat = GetStringPattern(table, prevPattern);
4328 + lastStringPat = GetStringPattern(table, lastPattern);
4330 + if (!AllocatedStringsDiffer(prevStringPat->spText, lastStringPat->spText) &&
4331 + !AllocatedStringsDiffer(prevStringPat->spOrigText, lastStringPat->spOrigText) &&
4332 + prevStringPat->spWordBoundary == lastStringPat->spWordBoundary &&
4333 + prevStringPat->spCaseInsensitive == lastStringPat->spCaseInsensitive &&
4334 + prevStringPat->spRegularExpression == lastStringPat->spRegularExpression)
4337 + * Patterns are identical: Is prevPattern already a multi pattern ?
4339 + if (prevPattern->peType == PET_MULTIPLE)
4342 + * just add ref. to "lastPattern" to the ref. list
4344 + (prevPattern->peVal.peuMulti.mpNumberOfReferences) ++;
4345 + nbrOfRef = prevPattern->peVal.peuMulti.mpNumberOfReferences;
4346 + oldList = prevPattern->peVal.peuMulti.mpRefList;
4347 + prevPattern->peVal.peuMulti.mpRefList =
4348 + (PatternReference *)XtMalloc( nbrOfRef * sizeof(PatternReference) );
4350 + prevPattern->peVal.peuMulti.mpRefList,
4352 + (nbrOfRef-1) * sizeof(PatternReference) );
4353 + prevPattern->peVal.peuMulti.mpRefList[nbrOfRef-1] = lastPatRef;
4354 + XtFree( (char *)oldList );
4359 + * convert prev. single pattern to multi pattern
4361 + stringPat = &prevPattern->peVal.peuSingle;
4362 + prevPattern->peType = PET_MULTIPLE;
4363 + prevPattern->peVal.peuMulti.mpStringPattern = *stringPat;
4364 + prevPattern->peVal.peuMulti.mpNumberOfReferences = 1;
4365 + prevPattern->peVal.peuMulti.mpRefList =
4366 + (PatternReference *)XtMalloc( sizeof(PatternReference) );
4367 + prevPattern->peVal.peuMulti.mpRefList[0] = lastPatRef;
4371 + * convert last single pattern to reference
4373 + freeStringPattern( &(lastPattern->peVal.peuSingle) );
4374 + lastPattern->peType = PET_REFERENCE;
4375 + lastPattern->peVal.peuRef = prevPatRef;
4380 +** Check, if last pattern is a duplicate of a pattern stored within a
4381 +** previous match pattern table element.
4382 +** Convert last pattern to a reference, if so.
4384 +static void treatDuplicatedPatternElements(
4385 + MatchPatternTable *table,
4386 + MatchPatternTableElement *prevElement,
4387 + int prevElementIdx,
4388 + PatternElement *lastPattern,
4389 + PatternReference lastPatRef)
4392 + PatternReference prevPatRef;
4394 + prevPatRef.prElementIdx = prevElementIdx;
4396 + for (i=0; i<prevElement->mpteAll.pesNumberOfPattern; i++)
4398 + prevPatRef.prPatternIdx = i;
4399 + treatDuplicatedPattern(
4401 + prevElement->mpteAll.pesPattern[i],
4409 +** Check, if a pattern of last match pattern table element is a
4410 +** duplicate of a pattern stored within a previous match pattern table
4412 +** Convert duplicated last patterns to references, if so.
4414 +static void treatDuplicatedMTElements(
4415 + MatchPatternTable *table,
4416 + MatchPatternTableElement *prevElement,
4417 + int prevElementIdx,
4418 + MatchPatternTableElement *lastElement,
4419 + int lastElementIdx)
4422 + PatternReference lastPatRef;
4424 + lastPatRef.prElementIdx = lastElementIdx;
4426 + for (i=0; i<lastElement->mpteAll.pesNumberOfPattern; i++)
4428 + lastPatRef.prPatternIdx = i;
4429 + treatDuplicatedPatternElements(
4433 + lastElement->mpteAll.pesPattern[i],
4439 +** Convert all duplicated patterns of given match pattern table to
4442 +static void treatDuplicatedMTEntries(
4443 + MatchPatternTableElement **element,
4444 + int nbrOfElements)
4447 + MatchPatternTableElement *lastElement;
4448 + int lastElementIdx;
4449 + MatchPatternTable table;
4451 + if (nbrOfElements < 2)
4454 + lastElementIdx = nbrOfElements - 1;
4455 + lastElement = element[lastElementIdx];
4457 + table.mptElements = element;
4458 + table.mptNumberOfElements = nbrOfElements;
4460 + for (i=0; i<nbrOfElements-1; i ++)
4462 + treatDuplicatedMTElements( &table, element[i], i, lastElement, lastElementIdx );
4467 +** Compile regular expressions of all string patterns of given
4468 +** match pattern table element.
4469 +** Returns true, if compilation fails.
4471 +static int createStrPatRegExpOfElement(
4472 + ReadMatchPatternInfo *readPatInfo,
4473 + MatchPatternTableElement *element,
4474 + ErrorInfo *errInfo)
4477 + StringPattern *strPat;
4479 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
4481 + strPat = getReadStringPattern(readPatInfo, element->mpteAll.pesPattern[i]);
4484 + * if current string pattern holds a regular expression, then
4487 + if (strPat->spRegularExpression)
4489 + if (createStrPatRegExp(strPat, errInfo))
4492 + * compilation was not successful
4494 + errInfo->eiMPTabElementName = XtNewString(element->mpteName);
4504 +** Compile regular expressions of given string pattern.
4505 +** Returns true, if compilation fails.
4507 +static int createStrPatRegExp(
4508 + StringPattern *strPat,
4509 + ErrorInfo *errInfo)
4511 + char *regExpString;
4515 + * compose regular expression for start string pattern.
4517 + if( strPat->spCaseInsensitive)
4520 + * Add '(?i .. )' to given text for case insensitive search.
4521 + * Allocate buffer to hold 5 more char than text length
4522 + * (4 char '(?i)' + \0 char.
4524 + regExpString = XtMalloc(strPat->spLength + 5);
4525 + strcpy(regExpString, "(?i");
4526 + strcat(regExpString, strPat->spText);
4527 + strcat(regExpString, ")");
4531 + regExpString = strPat->spText;
4535 + * compile regular expression & free allocated string buffer,
4538 + strPat->spTextRE =
4539 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
4541 + if (strPat->spTextRE == NULL)
4544 + * compilation was not successful: adapt error reason by
4545 + * converting local backrefs to global ones.
4547 + adaptCompileMsg(compileMsg, strPat->spGlobalToLocalBackRef);
4549 + errInfo->eiRegExpCompileMsg = compileMsg;
4550 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
4553 + if (strPat->spCaseInsensitive)
4554 + XtFree( regExpString );
4556 + return (strPat->spTextRE == NULL);
4560 +** adapt regular expression compilation message by converting local
4561 +** backrefs to global ones.
4563 +static void adaptCompileMsg(
4565 + int *globalToLocalBackRef)
4569 + char *s = compileMsg;
4571 + while (*s != '\0')
4575 + if (isdigit((unsigned char)*(s+1)))
4578 + * \n (n=1..9) found: substitute local by global back ref.
4583 + (int)((unsigned char)*s - (unsigned char)'0');
4585 + globalId = localToGlobalBackRef(globalToLocalBackRef, localId);
4587 + *s = (char)((int)('0') + globalId);
4589 + else if (*(s+1) != '\0')
4597 +** translate given local backref to global backref by using
4598 +** given globalToLocalBackRef list.
4600 +static int localToGlobalBackRef(
4601 + int *globalToLocalBackRef,
4606 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
4608 + if (globalToLocalBackRef[i] == localId)
4616 +** Create a regular expression holding keywords of given start & end
4618 +** Returns true, if creation of regular expression has failed.
4620 +static int createStartEndRegExp(
4621 + ReadMatchPatternInfo *readMatchPatternInfo,
4622 + MatchPatternTableElement *element,
4623 + ErrorInfo *errInfo)
4625 + char *regExpString;
4629 + * compose regular expression for start / end pattern.
4631 + composeStartEndRegExpString(
4632 + readMatchPatternInfo,
4637 + * compile regular expression & free allocated string buffer.
4639 + element->mpteStartEndRE =
4640 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
4642 + XtFree( regExpString );
4644 + if( element->mpteStartEndRE == NULL)
4646 + errInfo->eiRegExpCompileMsg = compileMsg;
4647 + errInfo->eiDetail = "Error compiling start / end reg. exp.";
4650 + return (element->mpteStartEndRE == NULL);
4654 +** Create a regular expression holding keywords of given group element.
4655 +** Returns true, if creation of regular expression has failed.
4657 +static int createGroupRegExp(
4658 + ReadMatchPatternInfo *readPatInfo,
4659 + MatchPatternGroupElement *group,
4660 + ErrorInfo *errInfo)
4663 + MatchPatternTableElement *element;
4664 + RegExpStringInfo regExpStringInfo;
4665 + char *regExpString;
4666 + regexp *keywordRE;
4670 + * Allocate buffers for keyword regular expression of this group.
4672 + setupRegExpStringBuffers(
4674 + ®ExpStringInfo);
4676 + for (i=0; i<group->mpgeNumberOfSubPatterns; i++)
4678 + element = getPatternOfName(readPatInfo, group->mpgeSubPatternIds[i]);
4680 + * Add the keywords of the sub pattern to the keyword regular
4681 + * expression string buffer of new group.
4683 + addElementToRegExpString(
4686 + ®ExpStringInfo);
4690 + * Assemble and compile the resulting keyword regular expression string.
4692 + catSMTRegExpStrings(
4693 + ®ExpStringInfo,
4696 + keywordRE = CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
4698 + XtFree( regExpString );
4700 + if (keywordRE == NULL)
4702 + errInfo->eiMPTabElementName = XtNewString(group->mpgeName);
4703 + errInfo->eiRegExpCompileMsg = compileMsg;
4704 + errInfo->eiDetail = "Group: Compile reg. exp. error";
4707 + group->mpgeKeywordRE = keywordRE;
4709 + return (keywordRE == NULL);
4713 +** Allocate memory for regular expression strings to be
4714 +** created out of read match pattern info.
4716 +static void setupRegExpStringBuffers(
4717 + ReadMatchPatternInfo *readMatchPatternInfo,
4718 + RegExpStringInfo *regExpStringInfo)
4721 + int nbrOfMultiPatterns;
4722 + int sizeOfPatRefs;
4725 + * determine total length of pattern characters to determine
4726 + * the size of a string buffer for the regular expression to
4727 + * compose. Count number of total multi patterns, too.
4730 + totalKeywordOfTableLen( readMatchPatternInfo, &nbrOfMultiPatterns );
4733 + * allocate memory to store added multi pattern references (to avoid
4734 + * duplicated keywords strings later on).
4736 + sizeOfPatRefs = sizeof(PatternReference *) * nbrOfMultiPatterns;
4738 + regExpStringInfo->resiAddedMultiPat =
4739 + (PatternReference **)XtMalloc( sizeOfPatRefs );
4741 + regExpStringInfo->resiNbrOfAddedMultiPat = 0;
4744 + * init. ID of capturing local backrefs
4746 + regExpStringInfo->resiLocalBackRefID = 1;
4749 + * allocate & init. string buffers for regular expression:
4750 + * 3 times the size + x of all pattern characters (due to
4751 + * a.) each char may need to be escaped
4752 + * b.) '<(?:', ')>', ')' and '|' need to be added.
4754 + regExpStringInfo->resiNoneWBRegExpString = XtMalloc( 3 * totalLen );
4755 + regExpStringInfo->resiLeftWBRegExpString = XtMalloc( 3 * totalLen + 5 );
4756 + regExpStringInfo->resiRightWBRegExpString = XtMalloc( 3 * totalLen + 5 );
4757 + regExpStringInfo->resiBothWBRegExpString = XtMalloc( 3 * totalLen + 6 );
4759 + strcpy( regExpStringInfo->resiNoneWBRegExpString, "" );
4760 + strcpy( regExpStringInfo->resiLeftWBRegExpString, "" );
4761 + strcpy( regExpStringInfo->resiRightWBRegExpString, "" );
4762 + strcpy( regExpStringInfo->resiBothWBRegExpString, "" );
4766 +** Concatenate given 'partToAdd' string to result string, separated
4767 +** by an OR ('|'). Add 'postfix' at end of result string.
4769 +static void addSMTRegExpString(
4772 + const char *postfix)
4774 + if (strlen(partToAdd) != 0)
4776 + if (strlen(result) != 0)
4778 + strcat( result, "|" );
4781 + strcat( result, partToAdd );
4783 + strcat( result, postfix );
4789 +** Return a string representing given string match table.
4791 +static char *createMatchPatternsString(
4792 + StringMatchTable *table,
4795 + char *outStr, *str;
4796 + textBuffer *outBuf;
4798 + MatchPatternSequenceElement *seq;
4799 + MatchPatternTableElement *element;
4800 + MatchPatternGroupElement *group;
4802 + outBuf = BufCreate();
4804 + for (i=0; i<table->smtNumberOfSeqElements; i++)
4806 + seq = table->smtSequence[i];
4808 + BufInsert(outBuf, outBuf->length, indentStr);
4809 + BufInsert(outBuf, outBuf->length, seq->mpseName);
4810 + BufInsert(outBuf, outBuf->length, ":");
4812 + if (seq->mpseType == MPT_GROUP)
4814 + BufInsert(outBuf, outBuf->length, "g:");
4816 + group = table->smtGroups[seq->mpseIndex];
4818 + for (j=0; j < group->mpgeNumberOfSubPatterns; j ++)
4820 + BufInsert(outBuf, outBuf->length, group->mpgeSubPatternIds[j]);
4821 + BufInsert(outBuf, outBuf->length, ":");
4826 + if (seq->mpseType == MPT_SUB)
4828 + BufInsert(outBuf, outBuf->length, "s");
4830 + BufInsert(outBuf, outBuf->length, ":");
4832 + element = table->smtAllPatterns->mptElements[seq->mpseIndex];
4835 + * write global attributes
4837 + if (element->mpteSkipBtwnStartEnd)
4838 + BufInsert(outBuf, outBuf->length, "c");
4839 + if (element->mpteFlash)
4840 + BufInsert(outBuf, outBuf->length, "f");
4841 + if (element->mpteIsMonoPattern)
4842 + BufInsert(outBuf, outBuf->length, "m");
4843 + if (element->mpteIgnoreHighLightInfo)
4844 + BufInsert(outBuf, outBuf->length, "p");
4845 + BufInsert(outBuf, outBuf->length, ":");
4848 + * write string patterns
4850 + for (j=0; j < element->mpteAll.pesNumberOfPattern; j ++)
4856 + createPatternElementString(
4857 + table->smtAllPatterns,
4858 + element->mpteAll.pesPattern[j]));
4863 + BufInsert(outBuf, outBuf->length, "\n");
4866 + outStr = BufGetAll(outBuf);
4873 +** Return a string representing given pattern element.
4875 +static char *createPatternElementString(
4876 + MatchPatternTable *table,
4877 + PatternElement *pat)
4879 + char *outStr, *str;
4880 + textBuffer *outBuf;
4881 + StringPattern *strPat;
4883 + outBuf = BufCreate();
4885 + strPat = GetStringPattern(table, pat);
4888 + * write string pattern kind
4890 + if (pat->peKind == PEK_START)
4891 + BufInsert(outBuf, outBuf->length, "s");
4892 + else if (pat->peKind == PEK_MIDDLE)
4893 + BufInsert(outBuf, outBuf->length, "m");
4894 + else if (pat->peKind == PEK_END)
4895 + BufInsert(outBuf, outBuf->length, "e");
4898 + * write word boundary
4900 + if (strPat->spWordBoundary == PWB_BOTH)
4901 + BufInsert(outBuf, outBuf->length, "w");
4902 + else if (strPat->spWordBoundary == PWB_LEFT)
4903 + BufInsert(outBuf, outBuf->length, "l");
4904 + else if (strPat->spWordBoundary == PWB_RIGHT)
4905 + BufInsert(outBuf, outBuf->length, "r");
4908 + * write case insensitive flag
4910 + if (strPat->spCaseInsensitive)
4911 + BufInsert(outBuf, outBuf->length, "i");
4914 + * write regular expression flag
4916 + if (strPat->spRegularExpression)
4917 + BufInsert(outBuf, outBuf->length, "x");
4919 + BufInsert(outBuf, outBuf->length, ":");
4922 + * write pattern string
4924 + if( strPat->spOrigText != NULL)
4928 + str = MakeQuotedString(strPat->spOrigText));
4933 + str = MakeQuotedString(strPat->spText));
4936 + BufInsert(outBuf, outBuf->length, ":");
4938 + outStr = BufGetAll(outBuf);
4945 +** Given a language mode name, determine if there is a default (built-in)
4946 +** string match table available for that language mode, and if so, read it and
4947 +** return a new allocated copy of it. The returned pattern set should be
4948 +** freed by the caller with freeStringMatchTable().
4950 +static StringMatchTable *readDefaultStringMatchTable(const char *langModeName)
4952 + int i, modeNameLen;
4955 + modeNameLen = strlen(langModeName);
4957 + for (i=0; i<(int)XtNumber(DefaultStringMatchTable); i++)
4959 + if (!strncmp(langModeName, DefaultStringMatchTable[i], modeNameLen) &&
4960 + DefaultStringMatchTable[i][modeNameLen] == '{')
4962 + list = DefaultStringMatchTable[i];
4963 + return readMatchPatternSet(&list);
4967 + list = StandardStringMatchTable;
4968 + return readMatchPatternSetContent(&list, list, XtNewString(langModeName));
4972 +** Return true, if table exactly matches one of the default matching
4975 +static int isDefaultMatchPatternTable(StringMatchTable *table)
4977 + StringMatchTable *defaultTable;
4980 + defaultTable = readDefaultStringMatchTable(table->smtLanguageMode);
4982 + if (defaultTable == NULL)
4985 + retVal = !stringMatchTableDiffer(table, defaultTable);
4987 + freeStringMatchTable(defaultTable);
4993 +** Read in a string match pattern table character string,
4994 +** and advance *inPtr beyond it.
4995 +** Returns NULL and outputs an error to stderr on failure.
4997 +static StringMatchTable *readMatchPatternSet(char **inPtr)
4999 + char *languageMode;
5000 + StringMatchTable *table = NULL;
5001 + char *stringStart = *inPtr;
5002 + ErrorInfo errInfo;
5004 + initErrorInfo(&errInfo);
5007 + * remove leading whitespace
5009 + *inPtr += strspn(*inPtr, " \t\n");
5012 + * read language mode field
5014 + languageMode = ReadSymbolicField(inPtr);
5017 + * look for initial brace
5019 + if (**inPtr == ':')
5023 + * look for "Default" keyword, and if it's there, return the default
5026 + if (!strncmp(*inPtr, "Default", 7))
5029 + table = readDefaultStringMatchTable(languageMode);
5030 + XtFree(languageMode);
5036 + table = readMatchPatternSetContent(inPtr, stringStart, languageMode);
5038 + if (table == NULL)
5039 + XtFree(languageMode);
5045 +** Read in a content string ("{..}") of match pattern table,
5046 +** and advance *inPtr beyond it.
5047 +** Returns NULL and outputs an error to stderr on failure.
5049 +static StringMatchTable *readMatchPatternSetContent(
5051 + char *stringStart,
5052 + char *languageMode)
5054 + ReadMatchPatternInfo readPatInfo;
5055 + StringMatchTable *table = NULL;
5056 + ErrorInfo errInfo;
5057 + int successful = True;
5058 + int endOfPatternSet = False;
5060 + initErrorInfo(&errInfo);
5063 + * look for initial brace
5065 + if (**inPtr != '{')
5067 + errInfo.eiLanguageMode = XtNewString(languageMode);
5068 + errInfo.eiDetail = "pattern list must begin with \"{\"";
5069 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo );
5076 + readPatInfo.rmpiNbrOfElements = 0;
5077 + readPatInfo.rmpiNbrOfGroups = 0;
5078 + readPatInfo.rmpiNbrOfSeqElements = 0;
5079 + readPatInfo.rmpiAllPatRE = NULL;
5080 + readPatInfo.rmpiFlashPatRE = NULL;
5083 + * parse each pattern in the list
5085 + while (successful && !endOfPatternSet)
5087 + *inPtr += strspn(*inPtr, " \t\n");
5088 + if (**inPtr == '\0')
5090 + errInfo.eiLanguageMode = XtNewString(languageMode);
5091 + errInfo.eiDetail = "end of pattern list not found";
5092 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo);
5093 + successful = False;
5095 + else if (**inPtr == '}')
5098 + endOfPatternSet = True;
5102 + if (!readMatchPatternEntry(inPtr, &errInfo, &readPatInfo))
5104 + errInfo.eiLanguageMode = XtNewString(languageMode);
5105 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo);
5106 + successful = False;
5114 + * compile regular expressions of read patterns
5116 + if (createRegExpOfPatterns(&readPatInfo, &errInfo))
5118 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo);
5119 + successful = False;
5125 + return createStringMatchTable(&readPatInfo, languageMode);
5130 + * free memory of already read patterns
5132 + freeReadMatchPatternInfo(&readPatInfo);
5141 +** Create a reg. exp. of all patterns contained
5142 +** in given read match pattern info.
5144 +static int createRegExpOfPatterns(
5145 + ReadMatchPatternInfo *readPatInfo,
5146 + ErrorInfo *errInfo)
5148 + if (createRegExpOfStrPatterns(readPatInfo, errInfo))
5151 + if (createRegExpOfAllPatterns(readPatInfo, errInfo))
5158 +** Create a "total pattern reg. exp." of all patterns / flash patterns
5159 +** contained in given read match pattern info.
5160 +** Returns true, if create of reg. exp. has failed.
5162 +static int createRegExpOfAllPatterns(
5163 + ReadMatchPatternInfo *readPatInfo,
5164 + ErrorInfo *errInfo)
5167 + RegExpStringInfo allPatRegExpSI;
5168 + RegExpStringInfo flashPatRegExpSI;
5169 + MatchPatternTableElement *element;
5170 + char *regExpString;
5174 + * Allocate buffers for keyword regular expressions.
5176 + setupRegExpStringBuffers(readPatInfo, &allPatRegExpSI);
5177 + setupRegExpStringBuffers(readPatInfo, &flashPatRegExpSI);
5179 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5181 + element = readPatInfo->rmpiElement[i];
5184 + * Add the keywords of the matching pattern to the keyword
5185 + * regular expression string buffer of all patterns.
5187 + addElementToRegExpString(
5193 + * If flash attribute is set, then add the keywords of the
5194 + * matching pattern also to the keyword regular expression
5195 + * string buffer of flash patterns.
5197 + if (element->mpteFlash)
5199 + addElementToRegExpString(
5202 + &flashPatRegExpSI);
5207 + * Assemble and compile the resulting all keywords reg. exp. string.
5209 + catSMTRegExpStrings(
5213 + readPatInfo->rmpiAllPatRE =
5214 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
5216 + XtFree( regExpString );
5218 + if (readPatInfo->rmpiAllPatRE == NULL)
5220 + errInfo->eiRegExpCompileMsg = compileMsg;
5221 + errInfo->eiDetail = "All patterns: compile reg. exp. error";
5226 + * Assemble and compile the resulting flash keywords reg. exp. string.
5228 + catSMTRegExpStrings(
5229 + &flashPatRegExpSI,
5232 + readPatInfo->rmpiFlashPatRE =
5233 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
5235 + XtFree( regExpString );
5237 + if (readPatInfo->rmpiFlashPatRE == NULL)
5239 + errInfo->eiRegExpCompileMsg = compileMsg;
5240 + errInfo->eiDetail = "Flash patterns: compile reg. exp. error";
5245 + * Pattern reg. exp. successful created:
5251 +** Create reg. exp. of single patterns contained in given
5252 +** read match pattern info.
5253 +** Returns true, if create of reg. exp. has failed.
5255 +static int createRegExpOfStrPatterns(
5256 + ReadMatchPatternInfo *readPatInfo,
5257 + ErrorInfo *errInfo)
5260 + MatchPatternTableElement *element;
5261 + MatchPatternGroupElement *group;
5264 + * create global backref list of all elements of read info
5266 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5268 + element = readPatInfo->rmpiElement[i];
5270 + if (!createGlobalBackRefList(readPatInfo, element, errInfo))
5275 + * resolve global backrefs of all elements of read info
5277 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5279 + element = readPatInfo->rmpiElement[i];
5281 + if (!resolveGlobalBackRefs(readPatInfo, element, errInfo))
5286 + * compile reg. exp. of all elements of read info
5288 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5290 + element = readPatInfo->rmpiElement[i];
5292 + if (createStrPatRegExpOfElement(readPatInfo, element, errInfo))
5296 + * create start / end reg. exp. if applicable.
5298 + if (element->mpteSkipBtwnStartEnd)
5300 + if (createStartEndRegExp(readPatInfo, element, errInfo))
5306 + * compile reg. exp. of all groups of read info
5308 + for (i=0; i < readPatInfo->rmpiNbrOfGroups; i ++)
5310 + group = readPatInfo->rmpiGroup[i];
5312 + if (createGroupRegExp(readPatInfo, group, errInfo))
5322 +** Create a string match table out of read match pattern info.
5324 +static StringMatchTable *createStringMatchTable(
5325 + ReadMatchPatternInfo *readPatInfo,
5326 + char *languageMode)
5328 + StringMatchTable *table;
5329 + MatchPatternTable *patTable;
5330 + int sizeOfElements;
5332 + table = (StringMatchTable *)XtMalloc(sizeof(StringMatchTable));
5333 + table->smtLanguageMode = languageMode;
5336 + * allocate a more appropriately sized list to return matching patterns
5338 + patTable = (MatchPatternTable *)XtMalloc(sizeof(MatchPatternTable));
5339 + patTable->mptNumberOfElements = readPatInfo->rmpiNbrOfElements;
5341 + if (readPatInfo->rmpiNbrOfElements > 0)
5344 + sizeof(MatchPatternTableElement *) * readPatInfo->rmpiNbrOfElements;
5345 + patTable->mptElements =
5346 + (MatchPatternTableElement **)XtMalloc(sizeOfElements);
5347 + memcpy(patTable->mptElements, readPatInfo->rmpiElement, sizeOfElements);
5351 + patTable->mptElements = NULL;
5354 + table->smtAllPatterns = patTable;
5356 + table->smtAllPatRE = readPatInfo->rmpiAllPatRE;
5357 + table->smtFlashPatRE = readPatInfo->rmpiFlashPatRE;
5358 + table->smtUsedPatRE = NULL;
5361 + * allocate a more appropriately sized list to return matching pattern groups
5363 + table->smtNumberOfGroups = readPatInfo->rmpiNbrOfGroups;
5364 + if (readPatInfo->rmpiNbrOfGroups > 0)
5367 + sizeof(MatchPatternGroupElement *) * readPatInfo->rmpiNbrOfGroups;
5368 + table->smtGroups =
5369 + (MatchPatternGroupElement **)XtMalloc(sizeOfElements);
5370 + memcpy(table->smtGroups, readPatInfo->rmpiGroup, sizeOfElements);
5374 + table->smtGroups = NULL;
5377 + * allocate a more appropriately sized list to return matching pattern sequence
5379 + table->smtNumberOfSeqElements = readPatInfo->rmpiNbrOfSeqElements;
5380 + if (readPatInfo->rmpiNbrOfSeqElements > 0)
5383 + sizeof(MatchPatternSequenceElement *) * readPatInfo->rmpiNbrOfSeqElements;
5384 + table->smtSequence =
5385 + (MatchPatternSequenceElement **)XtMalloc(sizeOfElements);
5386 + memcpy(table->smtSequence, readPatInfo->rmpiSequence, sizeOfElements);
5390 + table->smtSequence = NULL;
5397 +** Read one match pattern entry of a match pattern string.
5398 +** Returns true, if read was successful.
5400 +static int readMatchPatternEntry(
5402 + ErrorInfo *errInfo,
5403 + ReadMatchPatternInfo *info)
5406 + MatchPatternType type;
5407 + MatchPatternGroupElement *readGroup;
5408 + MatchPatternTableElement *readElement;
5410 + if (!getMPSName( inPtr, errInfo, &name ))
5415 + if (!getMPSTypeAttribute( inPtr, errInfo, &type ))
5417 + errInfo->eiMPTabElementName = XtNewString(name);
5421 + if (type == MPT_GROUP)
5423 + if (info->rmpiNbrOfGroups >= MAX_NBR_MATCH_PATTERN_GROUPS)
5425 + errInfo->eiMPTabElementName = XtNewString(name);
5426 + errInfo->eiDetail = "max number of match pattern groups exceeded";
5430 + readGroup = readMatchPatternGroup( inPtr, errInfo, name, info );
5432 + if (readGroup == NULL)
5434 + errInfo->eiMPTabElementName = XtNewString(name);
5439 + info->rmpiGroup[info->rmpiNbrOfGroups ++] = readGroup;
5441 + recordPatternSequence( info, name, type, info->rmpiNbrOfGroups-1 );
5444 + return (readGroup != NULL);
5448 + if (info->rmpiNbrOfElements >= MAX_NBR_MATCH_PATTERNS)
5450 + errInfo->eiMPTabElementName = XtNewString(name);
5451 + errInfo->eiDetail = "max number of match patterns exceeded";
5457 + readMatchPatternTableElement( inPtr, &errInfo->eiDetail, name, type );
5459 + if (readElement == NULL)
5461 + errInfo->eiMPTabElementName = XtNewString(name);
5466 + readElement->mpteIndex = info->rmpiNbrOfElements;
5468 + info->rmpiElement[info->rmpiNbrOfElements ++] = readElement;
5470 + if (type == MPT_INDIVIDUAL)
5472 + if (!assignIndividualGroup( info, &errInfo->eiDetail, readElement ))
5474 + errInfo->eiMPTabElementName = XtNewString(name);
5479 + treatDuplicatedMTEntries(
5480 + info->rmpiElement, info->rmpiNbrOfElements );
5482 + recordPatternSequence( info, name, type, info->rmpiNbrOfElements-1 );
5485 + return (readElement != NULL);
5490 +** Record match pattern sequence for display of match pattern dialog.
5492 +static void recordPatternSequence(
5493 + ReadMatchPatternInfo *info,
5495 + MatchPatternType type,
5498 + MatchPatternSequenceElement *sequence;
5501 + (MatchPatternSequenceElement *)XtMalloc( sizeof(MatchPatternSequenceElement) );
5503 + sequence->mpseName = XtNewString(name);
5504 + sequence->mpseType = type;
5505 + sequence->mpseIndex = index;
5507 + info->rmpiSequence[info->rmpiNbrOfSeqElements ++] = sequence;
5511 +** Assign a new group to an individual match pattern.
5512 +** Returns true, if assignment was successful.
5514 +static int assignIndividualGroup(
5515 + ReadMatchPatternInfo *info,
5517 + MatchPatternTableElement *element)
5519 + MatchPatternGroupElement *group = NULL;
5521 + if (info->rmpiNbrOfGroups >= MAX_NBR_MATCH_PATTERN_GROUPS)
5523 + *errMsg = "max. number of matching pattern groups exceeded\n";
5528 + * Assign the index of new group to the individual matching pattern
5530 + element->mpteGroup = info->rmpiNbrOfGroups;
5533 + * Allocate memory for the matching pattern group and copy the
5534 + * info into this group element.
5537 + (MatchPatternGroupElement *)XtMalloc( sizeof(MatchPatternGroupElement) );
5539 + group->mpgeName = NULL;
5540 + group->mpgeKeywordRE = NULL;
5543 + * remember name of match pattern table element, which is
5544 + * represented by this group.
5546 + group->mpgeNumberOfSubPatterns = 1;
5547 + group->mpgeSubPatternIds = (char **)XtMalloc( sizeof(char *) );
5548 + group->mpgeSubPatternIds[0] = XtNewString(element->mpteName);
5550 + info->rmpiGroup[info->rmpiNbrOfGroups ++] = group;
5556 +** Get the match pattern table element of given 'patToSearch'
5558 +** Returns NULL, if no element was found.
5560 +static MatchPatternTableElement *getPatternOfName(
5561 + ReadMatchPatternInfo *info,
5562 + char *patToSearch)
5565 + MatchPatternTableElement *element;
5567 + for (i=0; i<info->rmpiNbrOfElements; i ++)
5569 + element = info->rmpiElement[i];
5571 + if (strcmp( element->mpteName, patToSearch ) == 0)
5574 + * Related sub-pattern found:
5581 + * No sub-pattern found:
5587 +** Read match pattern group of given match pattern string.
5588 +** Returns NULL, if read fails.
5590 +static MatchPatternGroupElement *readMatchPatternGroup(
5592 + ErrorInfo *errInfo,
5594 + ReadMatchPatternInfo *info)
5597 + int error = False;
5598 + char *patNameInPtr;
5600 + MatchPatternTableElement *subPatElement;
5601 + int numberOfRelatedSubPattern = 0;
5602 + char *relatedSubPatternId[MAX_NBR_MATCH_PATTERNS];
5604 + MatchPatternGroupElement *group = NULL;
5607 + * Read sub-matching patterns of this group.
5609 + while (**inPtr != '\n' && !error)
5612 + * Read next pattern name from inPtr.
5614 + patNameInPtr = *inPtr;
5615 + subPatName = ReadSymbolicField(inPtr);
5617 + if (subPatName == NULL)
5619 + errInfo->eiDetail = "Sub-Matching Pattern Name expected";
5625 + * Get matching pattern related to sub-matching pattern name.
5628 + getPatternOfName( info, subPatName );
5630 + if (subPatElement == NULL)
5632 + errInfo->eiStringPatText = XtNewString(subPatName);
5633 + errInfo->eiDetail = "Sub-Matching Pattern not defined before";
5636 + else if (numberOfRelatedSubPattern >= MAX_NBR_MATCH_PATTERNS)
5638 + errInfo->eiDetail = "Group holds too many Sub-Matching Patterns";
5641 + else if (subPatElement->mpteType != MPT_SUB)
5643 + errInfo->eiStringPatText = XtNewString(subPatName);
5644 + errInfo->eiDetail = "Not a Sub-Matching Pattern";
5650 + * Remember sub-matching pattern ID
5652 + relatedSubPatternId[numberOfRelatedSubPattern ++] = subPatName;
5655 + * Assign the index of this group to the sub-matching pattern
5656 + * if no group index was assigned before.
5658 + if (subPatElement->mpteGroup == NO_GROUP_IDX)
5660 + subPatElement->mpteGroup = info->rmpiNbrOfGroups;
5665 + * Skip to the start of the next matching pattern name.
5667 + if (!error && !SkipDelimiter(inPtr, &errInfo->eiDetail))
5676 + for (i=0; i < numberOfRelatedSubPattern; i++)
5678 + XtFree( relatedSubPatternId[i] );
5686 + * Allocate memory for the matching pattern group and copy the
5687 + * info into this group element.
5690 + (MatchPatternGroupElement *)XtMalloc( sizeof(MatchPatternGroupElement) );
5692 + group->mpgeName = name;
5693 + group->mpgeKeywordRE = NULL;
5696 + * Allocate memory for the sub-matching pattern IDs & copy
5697 + * related sub-matching pattern into the group element.
5699 + sizeOfIds = sizeof(char *) * numberOfRelatedSubPattern;
5700 + group->mpgeSubPatternIds = (char **)XtMalloc( sizeOfIds );
5702 + memcpy(group->mpgeSubPatternIds, relatedSubPatternId, sizeOfIds);
5704 + group->mpgeNumberOfSubPatterns = numberOfRelatedSubPattern;
5711 +** Read one match pattern element from given match pattern string.
5712 +** Returns true, if read was successful.
5714 +static int readPatternElement(
5717 + PatternElement **pattern)
5719 + PatternElementKind patternKind;
5720 + PatternWordBoundary wordBoundary;
5721 + int caseInsensitive;
5722 + int regularExpression;
5725 + if (!getMPSPatternAttribute(
5731 + ®ularExpression ))
5736 + if (!ReadQuotedString(inPtr, errMsg, &string))
5741 + if (!SkipDelimiter(inPtr, errMsg))
5748 + createPatternElement(
5753 + regularExpression);
5759 +** Create a pattern element.
5761 +static PatternElement *createPatternElement(
5762 + char *patternText,
5763 + PatternElementKind patternKind,
5764 + PatternWordBoundary wordBoundary,
5765 + int caseInsensitive,
5766 + int regularExpression)
5768 + PatternElement *pattern;
5772 + * Convert pattern text to lower case, if case insensitive
5773 + * attribute is set.
5775 + if (caseInsensitive)
5777 + for (s = patternText; *s != '\0'; s ++)
5784 + * Allocate memory for the new pattern element and init. / copy
5785 + * related info into this pattern element.
5787 + pattern = (PatternElement *)XtMalloc( sizeof(PatternElement) );
5789 + initStrPatBackRefList(&pattern->peVal.peuSingle);
5791 + pattern->peKind = patternKind;
5792 + pattern->peIndex = NO_PATTERN_IDX;
5793 + pattern->peType = PET_SINGLE;
5795 + pattern->peVal.peuSingle.spLength = strlen(patternText);
5796 + pattern->peVal.peuSingle.spBackRefParsed = False;
5797 + pattern->peVal.peuSingle.spBackRefResolved = False;
5799 + pattern->peVal.peuSingle.spCaseInsensitive = caseInsensitive;
5800 + pattern->peVal.peuSingle.spRegularExpression = regularExpression;
5801 + pattern->peVal.peuSingle.spTextRE = NULL;
5804 + * Store original string of regular expression patterns due to
5805 + * it may be later adapted (e.g. due to global backrefs etc.).
5807 + if (regularExpression)
5809 + pattern->peVal.peuSingle.spOrigText = patternText;
5810 + pattern->peVal.peuSingle.spText = NULL;
5811 + pattern->peVal.peuSingle.spWordBoundary = PWB_NONE;
5815 + pattern->peVal.peuSingle.spOrigText = NULL;
5816 + pattern->peVal.peuSingle.spText = patternText;
5817 + pattern->peVal.peuSingle.spWordBoundary = wordBoundary;
5824 +** Create a list holding all global backref definitions of given
5825 +** match pattern table element. The list is stored in this given
5827 +** Returns true, if list was successfully created.
5829 +static int createGlobalBackRefList(
5830 + ReadMatchPatternInfo *readPatInfo,
5831 + MatchPatternTableElement *element,
5832 + ErrorInfo *errInfo)
5835 + StringPattern *strPat;
5837 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
5839 + strPat = getReadStringPattern(readPatInfo, element->mpteAll.pesPattern[i]);
5841 + if (strPat->spRegularExpression)
5843 + if (strPat->spBackRefParsed)
5846 + * Global backrefs or this string pattern already parsed:
5847 + * just merge string pattern list with elements one.
5849 + if (!updateGlobalBackRefs(
5851 + element->mpteGlobalBackRef,
5860 + * parse string pattern for global backrefs and
5861 + * merge string pattern list with elements one.
5863 + if (!parseGlobalBackRefs(
5865 + element->mpteGlobalBackRef,
5878 +** Returns read string pattern of given pattern element.
5880 +StringPattern *getReadStringPattern(
5881 + ReadMatchPatternInfo *readPatInfo,
5882 + PatternElement *pattern )
5884 + switch (pattern->peType)
5887 + return &pattern->peVal.peuSingle;
5890 + case PET_MULTIPLE:
5891 + return &pattern->peVal.peuMulti.mpStringPattern;
5894 + case PET_REFERENCE:
5895 + return getReadStringPattern(
5897 + getReadPatternOfReference(readPatInfo, &pattern->peVal.peuRef));
5902 + * never reached; just to make compiler happy
5908 +** Returns read pattern element of given pattern reference.
5910 +static PatternElement *getReadPatternOfReference(
5911 + ReadMatchPatternInfo *readPatInfo,
5912 + PatternReference *patRef)
5914 + MatchPatternTableElement **element = readPatInfo->rmpiElement;
5916 + return element[ patRef->prElementIdx ]->mpteAll.pesPattern[patRef->prPatternIdx];
5920 +** Allocate a new copy of given string and substitute each capturing
5921 +** parentheses inside given string by a non-capturing one.
5922 +** Returns resulting string.
5924 +static char *replaceCapturingParentheses(
5925 + const char *source)
5927 + char *destination;
5930 + int nbrOfOpenBraces = 0;
5935 + * count number of open braces
5937 + while (*s != '\0')
5940 + nbrOfOpenBraces ++;
5944 + * allocate memory for substitued reg. exp. text
5946 + destination = XtMalloc(strlen(source) + 2*nbrOfOpenBraces);
5949 + * substitute each capturing open brace by a non-capturing one
5954 + while (*s != '\0')
5963 + else if (*s == '(')
5967 + if (*s != '?' && *s != '*')
5981 + return destination;
5985 +** Parse given string pattern for global backrefs definitions
5986 +** (syntax: "(*n", where n=1..9). Add found global backrefs to
5987 +** given backRefList.
5988 +** Returns false, if parse fails.
5990 +static int parseGlobalBackRefs(
5991 + StringPattern *strPat,
5992 + GlobalBackRefElement *backRefList,
5993 + ErrorInfo *errInfo)
5996 + char *backRefContent;
5997 + int nestingLevel = 0;
5998 + int stackIdx = -1;
5999 + BackRefBracketInfo backRefInfo[MAX_GLOBAL_BACK_REF_ID+1];
6000 + StrPatBackRefElement *curStrPatBRE;
6002 + strPat->spText = replaceCapturingParentheses(strPat->spOrigText);
6003 + strPat->spLength = strlen(strPat->spText);
6004 + strPat->spBackRefParsed = True;
6006 + s = strPat->spText;
6008 + while (*s != '\0')
6013 + * Ignore escaped characters
6015 + if (*(s+1) != '\0')
6018 + else if (*s == '(')
6020 + if (*(s+1) == '*')
6022 + if (isdigit((unsigned char)*(s+2)))
6025 + * Global backref. definition start found:
6029 + backRefInfo[stackIdx].brbiGlobalId =
6030 + (int)((unsigned char)*(s+2) - (unsigned char)'0') - 1;
6032 + if(backRefInfo[stackIdx].brbiGlobalId < 0)
6034 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6035 + errInfo->eiDetail = "Backref '0' not allowed";
6039 + backRefInfo[stackIdx].brbiContentStart = s+3;
6040 + backRefInfo[stackIdx].brbiNestingLevel = nestingLevel;
6047 + else if (*s == ')')
6050 + if (stackIdx != -1 &&
6051 + backRefInfo[stackIdx].brbiNestingLevel == nestingLevel)
6054 + * Global backref. definition end found: add it to
6055 + * backref. list of string pattern.
6058 + &strPat->spOwnGlobalBackRef[backRefInfo[stackIdx].brbiGlobalId];
6061 + createBackRefRegExpText(
6062 + backRefInfo[stackIdx].brbiContentStart,
6065 + if (curStrPatBRE->spbreRegExpText != NULL)
6067 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6068 + errInfo->eiBackRefNbr = backRefInfo[stackIdx].brbiGlobalId + 1;
6069 + errInfo->eiDetail = "already defined before";
6070 + XtFree(backRefContent);
6075 + curStrPatBRE->spbreRegExpText = backRefContent;
6085 + * Merge global backref. list of string pattern with given backRefList.
6087 + return updateGlobalBackRefs(
6094 +** Merge global backref. list of given string pattern with given backRefList.
6095 +** Returns false, if merge fails.
6097 +static int updateGlobalBackRefs(
6098 + StringPattern *strPat,
6099 + GlobalBackRefElement *backRefList,
6100 + ErrorInfo *errInfo)
6103 + StrPatBackRefElement *curStrPatBRE;
6104 + GlobalBackRefElement *curGlobalBRE;
6106 + for (i=0;i < MAX_GLOBAL_BACK_REF_ID; i ++)
6108 + curStrPatBRE = &strPat->spOwnGlobalBackRef[i];
6110 + if (curStrPatBRE->spbreRegExpText != NULL)
6112 + curGlobalBRE = &backRefList[i];
6114 + if (curGlobalBRE->gbreDefByStrPat != NULL)
6116 + if (strcmp(curGlobalBRE->gbreRegExpText, curStrPatBRE->spbreRegExpText) != 0)
6118 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6119 + errInfo->eiBackRefNbr = i+1;
6120 + errInfo->eiDetail = "already defined before";
6127 + curGlobalBRE->gbreDefByStrPat = strPat;
6128 + curGlobalBRE->gbreRegExpText = curStrPatBRE->spbreRegExpText;
6137 +** Allocate and return a new string holding content of
6138 +** global backref. definition.
6140 +static char *createBackRefRegExpText(
6141 + const char *start,
6144 + int len = end - start;
6145 + char *regExpText = XtMalloc( len+1 );
6147 + memcpy( regExpText, start, len );
6149 + regExpText[len] = '\0';
6151 + return regExpText;
6155 +** Resolve all global backrefs of given match pattern table element.
6156 +** Returns false, if resolve fails.
6158 +static int resolveGlobalBackRefs(
6159 + ReadMatchPatternInfo *readPatInfo,
6160 + MatchPatternTableElement *element,
6161 + ErrorInfo *errInfo)
6164 + StringPattern *strPat;
6166 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
6168 + strPat = getReadStringPattern(readPatInfo, element->mpteAll.pesPattern[i]);
6170 + if (strPat->spRegularExpression && !strPat->spBackRefResolved)
6172 + if (!resolveGlobalBackRefsOfStrPat(strPat, element->mpteGlobalBackRef, errInfo))
6175 + strPat->spBackRefResolved = True;
6183 +** Resolve global backrefs of given string pattern.
6184 +** Returns false, if resolve fails.
6186 +static int resolveGlobalBackRefsOfStrPat(
6187 + StringPattern *strPat,
6188 + GlobalBackRefElement *backRefList,
6189 + ErrorInfo *errInfo)
6195 + s = strPat->spText;
6197 + while (*s != '\0')
6201 + if (isdigit((unsigned char)*(s+1)))
6204 + * \n (n=1..9) found: substitute global backref.
6207 + (int)((unsigned char)*(s+1) - (unsigned char)'0') - 1;
6211 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6212 + errInfo->eiDetail = "backref '\\0' not allowed";
6216 + s = substituteGlobalBackRef(strPat, s, globalId, &localId, backRefList, errInfo);
6221 + else if (*(s+1) != '\0')
6224 + else if (*s == '(')
6226 + if (*(s+1) == '*')
6228 + if (isdigit((unsigned char)*(s+2)))
6231 + * "(*n" (n=1..9) found: substitute global backref. definition.
6234 + (int)((unsigned char)*(s+2) - (unsigned char)'0') - 1;
6236 + strPat->spOwnGlobalBackRef[globalId].spbreLocalBackRefID = localId;
6237 + strPat->spGlobalToLocalBackRef[globalId] = localId;
6241 + s = convertGlobalToLocalBackRef(strPat, s);
6256 +** Substitute global backref (\n, n=1..9) located at given "subsPtr"
6257 +** by its definition or by a local backref.
6259 +** - NULL, if substitute fails or
6260 +** - substituted string pointer, where scan shall continue with.
6262 +static char *substituteGlobalBackRef(
6263 + StringPattern *strPat,
6267 + GlobalBackRefElement *backRefList,
6268 + ErrorInfo *errInfo)
6270 + StrPatBackRefElement *strPatBackRef = &strPat->spOwnGlobalBackRef[globalId];
6273 + if (strPatBackRef->spbreRegExpText == NULL)
6276 + * given global backref definition is not located in given
6277 + * string pattern -> replace backref ID by backref reg. exp.
6279 + if (backRefList[globalId].gbreRegExpText == NULL)
6281 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6282 + errInfo->eiBackRefNbr = globalId + 1;
6283 + errInfo->eiDetail = "not defined within any string pattern";
6287 + if (strPat->spGlobalToLocalBackRef[globalId] == NO_LOCAL_BACK_REF_ID)
6290 + * 1st occurence of global backref ID in this pattern ->
6291 + * replace global backref ID by backref reg. exp.
6293 + s = replaceBackRefIdByRegExp(strPat, subsPtr, backRefList[globalId].gbreRegExpText);
6295 + strPat->spGlobalToLocalBackRef[globalId] = *localId;
6301 + * next occurence of global backref ID in this pattern ->
6302 + * replace global backref ID by local one
6305 + *s = (char)((int)('0') + strPat->spGlobalToLocalBackRef[globalId]);
6311 + * given global backref definition is located in given string pattern
6313 + if (strPatBackRef->spbreLocalBackRefID == NO_LOCAL_BACK_REF_ID)
6315 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6316 + errInfo->eiBackRefNbr = globalId + 1;
6317 + errInfo->eiDetail = "not defined before";
6322 + * replace global backref ID by local one
6325 + *s = (char)((int)('0') + strPatBackRef->spbreLocalBackRefID);
6332 +** Replace global backref ID ("\n", n=1..9), located at given
6333 +** replaceStartPtr, by its definition (given by regExp parameter).
6334 +** Returns string pointer, where scan shall continue with
6336 +static char *replaceBackRefIdByRegExp(
6337 + StringPattern *strPat,
6338 + char *replaceStartPtr,
6341 + char *oldText = strPat->spText;
6344 + char *continueScanPtr;
6345 + int oldLen = strlen(oldText);
6346 + int regExpLen = strlen(regExp);
6347 + int replacePos = replaceStartPtr - oldText;
6348 + int remainingLen = oldLen-replacePos-2;
6351 + * replace "\n" - located at replaceStartPtr - by "(regExp)"
6353 + newText = XtMalloc(oldLen + regExpLen + 3);
6355 + memcpy(newText, oldText, replacePos);
6356 + n = newText + replacePos;
6358 + continueScanPtr = n;
6360 + memcpy(n, regExp, regExpLen);
6364 + memcpy(n, replaceStartPtr+2, remainingLen);
6365 + *(n + remainingLen) = '\0';
6369 + strPat->spText = newText;
6370 + strPat->spLength = strlen(newText);
6372 + return continueScanPtr;
6376 +** Convert global backref definition ("(*n", n=1..9), located at given
6377 +** convertPtr, by capturing parentheses "(".
6378 +** Returns string pointer, where scan shall continue with
6380 +static char *convertGlobalToLocalBackRef(
6381 + StringPattern *strPat,
6384 + char *oldText = strPat->spText;
6386 + int oldLen = strlen(oldText);
6387 + int convertPos = convertPtr - oldText;
6390 + * replace "(*n" - located at convertPtr - by "("
6392 + newText = XtMalloc(oldLen - 1);
6394 + memcpy(newText, oldText, convertPos+1);
6395 + memcpy(newText+convertPos+1, convertPtr+3, oldLen-convertPos-3);
6397 + *(newText + oldLen - 2) = '\0';
6401 + strPat->spText = newText;
6402 + strPat->spLength = strlen(newText);
6404 + return newText + convertPos;
6408 +** Read a match pattern table element from given input string.
6409 +** Return NULL, if read fails.
6411 +static MatchPatternTableElement *readMatchPatternTableElement(
6415 + MatchPatternType type)
6417 + int error = False;
6418 + PatternElement *pattern;
6419 + PatternElement *allPat[MAX_STRING_PATTERNS];
6422 + MatchPatternTableElement *result;
6423 + int isMonoPattern;
6424 + int skipBtwStartEnd;
6426 + int ignoreHighLightInfo;
6429 + if (!getMPSGlobalAttribute(
6435 + &ignoreHighLightInfo ))
6441 + * read all patterns
6443 + while (**inPtr != '\n' && !error)
6445 + if (!readPatternElement( inPtr, errMsg, &pattern ))
6449 + else if (nbrOfPat >= MAX_STRING_PATTERNS)
6451 + *errMsg = "max. number of string patterns exceeded";
6456 + pattern->peIndex = nbrOfPat;
6458 + allPat[nbrOfPat ++] = pattern;
6464 + for (i=0; i < nbrOfPat; i ++)
6465 + freePatternElement( allPat[i] );
6470 + if (nbrOfPat == 0)
6472 + *errMsg = "min. one string pattern needed";
6477 + * allocate & init. MatchPatternTableElement
6480 + (MatchPatternTableElement *)XtMalloc(sizeof(MatchPatternTableElement));
6482 + result->mpteName = name;
6483 + result->mpteIndex = NO_ELEMENT_IDX;
6484 + result->mpteType = type;
6485 + result->mpteGroup = NO_GROUP_IDX;
6487 + sizeOfPat = sizeof(PatternElement *) * nbrOfPat;
6488 + result->mpteAll.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6490 + memcpy(result->mpteAll.pesPattern, allPat, sizeOfPat);
6492 + result->mpteAll.pesNumberOfPattern = nbrOfPat;
6494 + result->mpteIsMonoPattern = isMonoPattern;
6495 + result->mpteSkipBtwnStartEnd = skipBtwStartEnd;
6496 + result->mpteFlash = flash;
6497 + result->mpteIgnoreHighLightInfo = ignoreHighLightInfo;
6499 + result->mpteStartEndRE = NULL;
6501 + initGlobalBackRefList( result->mpteGlobalBackRef );
6504 + * sort start / end / middle pattern
6506 + error = !sortReadPatternElementSet( &result->mpteAll, errMsg, result );
6510 + freeMatchPatternTableElement( result );
6520 + * Sort read pattern element set into start, middle & end arrays.
6521 + * Validate "monopattern" attribute.
6522 + * Returns true, if validation was successful.
6524 +static int sortReadPatternElementSet(
6525 + PatternElementSet *allPat,
6527 + MatchPatternTableElement *result)
6530 + int isMonoPattern = result->mpteIsMonoPattern;
6533 + * count number of start, middle & end pattern elements.
6535 + countPatternElementKind( allPat, result );
6538 + * validate and allocate pattern elements.
6540 + if (result->mpteStart.pesNumberOfPattern != 0)
6542 + sizeOfPat = sizeof(PatternElement *) * result->mpteStart.pesNumberOfPattern;
6543 + result->mpteStart.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6547 + *errMsg = "min. one start pattern needed";
6551 + if (isMonoPattern &&
6552 + (result->mpteMiddle.pesNumberOfPattern != 0 ||
6553 + result->mpteEnd.pesNumberOfPattern !=0))
6555 + *errMsg = "mono pattern: only start pattern(s) allowed due to attribute [m]";
6559 + if (result->mpteMiddle.pesNumberOfPattern != 0)
6561 + sizeOfPat = sizeof(PatternElement *) * result->mpteMiddle.pesNumberOfPattern;
6562 + result->mpteMiddle.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6565 + if (result->mpteEnd.pesNumberOfPattern != 0)
6567 + sizeOfPat = sizeof(PatternElement *) * result->mpteEnd.pesNumberOfPattern;
6568 + result->mpteEnd.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6572 + if (!isMonoPattern)
6574 + *errMsg = "min. one end pattern needed";
6580 + * sort pattern elements into start, middle & end arrays.
6582 + sortPatternElementSet( allPat, result );
6584 + if (isMonoPattern)
6586 + copyPatternSet( &result->mpteStart, &result->mpteEnd );
6593 + * Count number of start, middle & end patterns stored in "allPat".
6595 +static void countPatternElementKind(
6596 + PatternElementSet *allPat,
6597 + MatchPatternTableElement *result)
6601 + result->mpteStart.pesNumberOfPattern = 0;
6602 + result->mpteEnd.pesNumberOfPattern = 0;
6603 + result->mpteMiddle.pesNumberOfPattern = 0;
6605 + result->mpteStart.pesPattern = NULL;
6606 + result->mpteEnd.pesPattern = NULL;
6607 + result->mpteMiddle.pesPattern = NULL;
6609 + for (i=0; i < allPat->pesNumberOfPattern; i ++)
6611 + switch (allPat->pesPattern[i]->peKind)
6614 + result->mpteStart.pesNumberOfPattern ++;
6617 + result->mpteMiddle.pesNumberOfPattern ++;
6620 + result->mpteEnd.pesNumberOfPattern ++;
6628 + * Sort start, middle & end pattern elements into related arrays.
6630 +static void sortPatternElementSet(
6631 + PatternElementSet *allPat,
6632 + MatchPatternTableElement *result)
6637 + for (i=0, s=0, m=0, e=0; i < allPat->pesNumberOfPattern; i ++)
6639 + switch (allPat->pesPattern[i]->peKind)
6642 + result->mpteStart.pesPattern[s ++] = allPat->pesPattern[i];
6645 + result->mpteMiddle.pesPattern[m ++] = allPat->pesPattern[i];
6648 + result->mpteEnd.pesPattern[e ++] = allPat->pesPattern[i];
6655 +static void copyPatternSet(
6656 + PatternElementSet *sourcePS,
6657 + PatternElementSet *destPS)
6661 + destPS->pesNumberOfPattern = sourcePS->pesNumberOfPattern;
6663 + sizeOfPat = sizeof(PatternElement *) * destPS->pesNumberOfPattern;
6664 + destPS->pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6666 + memcpy(destPS->pesPattern, sourcePS->pesPattern, sizeOfPat);
6670 +** Free the allocated memory contained in a ReadMatchPatternInfo data structure
6672 +static void freeReadMatchPatternInfo( ReadMatchPatternInfo *readPatInfo )
6676 + for (i=0; i<readPatInfo->rmpiNbrOfElements; i++)
6677 + freeMatchPatternTableElement(readPatInfo->rmpiElement[i]);
6679 + for (i=0; i<readPatInfo->rmpiNbrOfGroups; i++)
6680 + freeMatchPatternGroupElement(readPatInfo->rmpiGroup[i]);
6682 + for (i=0; i<readPatInfo->rmpiNbrOfSeqElements; i++)
6683 + freeMatchPatternSequenceElement(readPatInfo->rmpiSequence[i]);
6685 + freePtr((void **)&readPatInfo->rmpiAllPatRE);
6687 + freePtr((void **)&readPatInfo->rmpiFlashPatRE);
6691 +** Free the allocated memory contained in a StringMatchTable data structure
6693 +static void freeStringMatchTable( StringMatchTable *table )
6695 + MatchPatternTable *patTable;
6698 + if (table == NULL)
6701 + XtFree(table->smtLanguageMode);
6704 + * Free all matching patterns
6706 + patTable = table->smtAllPatterns;
6708 + for (i=0; i<patTable->mptNumberOfElements; i++)
6709 + freeMatchPatternTableElement(patTable->mptElements[i]);
6711 + XtFree((char *)patTable);
6714 + * Free matching pattern group elements
6716 + for (i=0; i<table->smtNumberOfGroups; i++)
6717 + freeMatchPatternGroupElement(table->smtGroups[i]);
6720 + * Free matching pattern sequence elements
6722 + for (i=0; i<table->smtNumberOfSeqElements; i++)
6723 + freeMatchPatternSequenceElement(table->smtSequence[i]);
6726 + * Free keyword reg. expressions
6728 + freePtr((void **)&table->smtAllPatRE);
6730 + freePtr((void **)&table->smtFlashPatRE);
6732 + XtFree((char *)table);
6736 +** Free the allocated memory contained in a MatchPatternTableElement data structure
6738 +static void freeMatchPatternTableElement( MatchPatternTableElement *element )
6742 + XtFree(element->mpteName);
6744 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
6746 + freePatternElement(element->mpteAll.pesPattern[i]);
6749 + freePtr((void **)&element->mpteStartEndRE);
6751 + freeXtPtr((void **)&element->mpteStart.pesPattern);
6753 + freeXtPtr((void **)&element->mpteMiddle.pesPattern);
6755 + freeXtPtr((void **)&element->mpteEnd.pesPattern);
6757 + XtFree((char *)element);
6761 +** Free the allocated memory contained in a PatternElement data structure
6763 +static void freePatternElement( PatternElement *element )
6765 + if (element->peType == PET_SINGLE)
6766 + freeStringPattern( &(element->peVal.peuSingle) );
6767 + else if (element->peType == PET_MULTIPLE)
6769 + freeStringPattern( &(element->peVal.peuMulti.mpStringPattern) );
6770 + XtFree( (char *)element->peVal.peuMulti.mpRefList );
6773 + XtFree( (char *)element );
6777 +** Free the allocated memory contained in a StringPattern data structure
6779 +static void freeStringPattern( StringPattern *strPat )
6783 + freeXtPtr((void **)&strPat->spText);
6784 + freeXtPtr((void **)&strPat->spOrigText);
6786 + freePtr((void **)&strPat->spTextRE);
6788 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
6789 + freeXtPtr((void **)&strPat->spOwnGlobalBackRef[i].spbreRegExpText);
6793 +** Free the allocated memory contained in a MatchPatternGroupElement data structure
6795 +static void freeMatchPatternGroupElement( MatchPatternGroupElement *group )
6799 + freeXtPtr((void **)&group->mpgeName);
6801 + freePtr((void **)&group->mpgeKeywordRE);
6803 + if (group->mpgeSubPatternIds != NULL)
6805 + for (i=0; i < group->mpgeNumberOfSubPatterns; i++)
6807 + XtFree(group->mpgeSubPatternIds[i]);
6809 + XtFree((char *)group->mpgeSubPatternIds);
6812 + XtFree((char *)group);
6816 +** Free the allocated memory contained in a MatchPatternSequenceElement data structure
6818 +static void freeMatchPatternSequenceElement( MatchPatternSequenceElement *sequence )
6820 + XtFree( sequence->mpseName );
6822 + XtFree( (char *)sequence );
6827 +** Format a matching pattern set parse error.
6829 +static void parseMatchingPatternSetError(
6830 + const char *stringStart,
6831 + const char *stoppedAt,
6832 + ErrorInfo *errInfo)
6834 + char *message = "";
6836 + char *errorInForm = "matching pattern of \"%s\"";
6839 + if (errInfo->eiLanguageMode == NULL)
6841 + errorIn = "matching pattern";
6845 + errorIn = XtMalloc(strlen(errorInForm) + strlen(errInfo->eiLanguageMode)+1);
6846 + sprintf(errorIn, "matching pattern of \"%s\"", errInfo->eiLanguageMode);
6849 + if (errInfo->eiRegExpCompileMsg != NULL)
6852 + * Error message of form:
6853 + * "MP \"eiMPTabElementName\", SP \"eiStringPatText\": eiRegExpCompileMsg" or
6854 + * "MP \"eiMPTabElementName\" - eiDetail: eiRegExpCompileMsg"
6857 + msgLen = strlen(errInfo->eiRegExpCompileMsg) + 1;
6859 + if (errInfo->eiMPTabElementName != NULL)
6860 + msgLen += strlen(errInfo->eiMPTabElementName) + 10;
6862 + if (errInfo->eiDetail != NULL)
6864 + msgLen += strlen(errInfo->eiDetail + 2);
6868 + if (errInfo->eiStringPatText != NULL)
6869 + msgLen += strlen(errInfo->eiStringPatText) + 9;
6872 + message = XtMalloc(msgLen);
6874 + strcpy(message, "");
6876 + if (errInfo->eiMPTabElementName != NULL)
6877 + sprintf( message, "MP \"%s\"", errInfo->eiMPTabElementName);
6879 + if (errInfo->eiDetail == NULL)
6881 + if (errInfo->eiStringPatText != NULL)
6882 + sprintf( message, "%s, SP \"%s\"", message, errInfo->eiStringPatText);
6886 + if (strlen(message) != 0)
6887 + strcat(message, " - ");
6889 + strcat(message, errInfo->eiDetail);
6892 + if (strlen(message) != 0)
6893 + strcat(message, ": ");
6895 + strcat(message, errInfo->eiRegExpCompileMsg);
6897 + else if (errInfo->eiDetail != NULL)
6900 + * Error message of form:
6901 + * "MP \"eiMPTabElementName\", SP \"eiStringPatText\": Backref %d eiDetail
6903 + msgLen = strlen(errInfo->eiDetail) + 1;
6905 + if (errInfo->eiMPTabElementName != NULL)
6906 + msgLen += strlen(errInfo->eiMPTabElementName) + 7;
6907 + if (errInfo->eiStringPatText != NULL)
6908 + msgLen += strlen(errInfo->eiStringPatText) + 9;
6909 + if (errInfo->eiBackRefNbr != 0)
6912 + message = XtMalloc(msgLen);
6914 + strcpy(message, "");
6916 + if (errInfo->eiMPTabElementName != NULL)
6917 + sprintf( message, "MP \"%s\"", errInfo->eiMPTabElementName);
6918 + if (errInfo->eiStringPatText != NULL)
6919 + sprintf( message, "%s, SP \"%s\"", message, errInfo->eiStringPatText);
6921 + if (strlen(message) != 0)
6922 + strcat(message, ": ");
6924 + if (errInfo->eiBackRefNbr != 0)
6925 + sprintf( message, "%s Backref %d ", message, errInfo->eiBackRefNbr);
6927 + strcat(message, errInfo->eiDetail);
6930 + ParseError(NULL, stringStart, stoppedAt, errorIn, message);
6932 + if (errInfo->eiRegExpCompileMsg != NULL || errInfo->eiDetail != NULL)
6937 + if (errInfo->eiLanguageMode != NULL)
6942 + freeErrorInfo(errInfo);
6943 + initErrorInfo(errInfo);
6947 + * Pop-up a warning dialog showing a matching pattern set error.
6949 +static void dialogMatchingPatternSetError(
6951 + ErrorInfo *errInfo)
6957 + * Error message of form:
6958 + * "Name : \"eiMPTabElementName\"\n
6959 + * "String: \"eiStringPatText\"\n
6961 + * eiRegExpCompileMsg\n"
6964 + if (errInfo->eiMPTabElementName != NULL)
6965 + msgLen += strlen(errInfo->eiMPTabElementName) + 15;
6966 + if (errInfo->eiStringPatText != NULL)
6967 + msgLen += strlen(errInfo->eiStringPatText) + 15;
6968 + if (errInfo->eiDetail != NULL)
6969 + msgLen += strlen(errInfo->eiDetail) + 15;
6970 + if (errInfo->eiBackRefNbr != 0)
6972 + if (errInfo->eiRegExpCompileMsg != NULL)
6973 + msgLen += strlen(errInfo->eiRegExpCompileMsg) + 15;
6975 + message = XtMalloc(msgLen);
6977 + strcpy(message, "");
6979 + if (errInfo->eiMPTabElementName != NULL)
6980 + sprintf( message, "%sName : \"%s\"\n", message, errInfo->eiMPTabElementName);
6981 + if (errInfo->eiStringPatText != NULL)
6982 + sprintf( message, "%sPattern: \"%s\"\n", message, errInfo->eiStringPatText);
6983 + if (errInfo->eiBackRefNbr != 0)
6984 + sprintf( message, "%sBackref %d ", message, errInfo->eiBackRefNbr);
6985 + if (errInfo->eiDetail != NULL)
6986 + sprintf( message, "%s%s\n", message, errInfo->eiDetail);
6987 + if (errInfo->eiRegExpCompileMsg != NULL)
6988 + sprintf( message, "%s%s\n", message, errInfo->eiRegExpCompileMsg);
6991 + DF_WARN, MatchPatternDialog.mpdShell, 1,
6993 + "%s(language mode '%s')",
6996 + errInfo->eiLanguageMode);
7000 + freeErrorInfo(errInfo);
7001 + initErrorInfo(errInfo);
7005 +** Get matching pattern set name.
7007 +** patternName ::= "name:"
7008 +** Returns true, if get was successful.
7010 +static int getMPSName(
7012 + ErrorInfo *errInfo,
7016 + char *field = ReadSymbolicField(inPtr);
7018 + if (field == NULL)
7020 + errInfo->eiDetail = "matching pattern name missing";
7024 + if (!SkipDelimiter(inPtr, &dummy))
7026 + errInfo->eiMPTabElementName = XtNewString(field);
7027 + errInfo->eiDetail = "':' missing after matching pattern name";
7038 +** Get matching pattern set type attribute.
7039 +** TypeAttribute ::=
7042 +** s : sub-pattern (pattern is only matched, if part of a pattern group).
7043 +** g : pattern (context) group (i.e. a sequence of sub-patterns).
7044 +** default: individual pattern (pattern is not part of a group and is
7045 +** matched individually.
7046 +** Returns true, if get was successful.
7048 +static int getMPSTypeAttribute(
7050 + ErrorInfo *errInfo,
7051 + MatchPatternType *type)
7053 + char *field = ReadSymbolicField(inPtr);
7054 + int successful = True;
7056 + *type = MPT_INDIVIDUAL;
7058 + if (field != NULL)
7063 + *type = MPT_GROUP;
7069 + errInfo->eiDetail = "unknown matching pattern type attribute";
7070 + successful = False;
7076 + if (!SkipDelimiter(inPtr, &errInfo->eiDetail))
7078 + successful = False;
7082 + freeXtPtr((void **)&field);
7084 + return successful;
7090 +** GlobalAttribute ::=
7091 +** [c][f][m][p][u]:
7093 +** c : the content between start and end pattern is skipped
7094 +** during parsing (e.g. pattern encloses a comment).
7095 +** f : flash matching pattern (if not set, then only jump
7096 +** to matching pattern is supported).
7097 +** m : mono pattern - set exist out of only one single pattern
7098 +** (start pattern = end pattern; e.g. quotes like ")
7099 +** p : ignore highlight info code of single patterns of this set
7102 +** Returns TRUE, if global attribute was successful read.
7104 +static int getMPSGlobalAttribute(
7107 + int *isMonoPattern,
7110 + int *ignoreHighLightInfo)
7112 + char *field = ReadSymbolicField(inPtr);
7114 + int successful = True;
7116 + *isMonoPattern = False;
7119 + *ignoreHighLightInfo = False;
7121 + if (field != NULL)
7123 + attribute = field;
7124 + while (*attribute != '\0' && successful)
7126 + switch (*attribute)
7135 + *isMonoPattern = True;
7138 + *ignoreHighLightInfo = True;
7141 + *errMsg = "unknown global attribute";
7142 + successful = False;
7150 + if (!SkipDelimiter(inPtr, errMsg))
7152 + successful = False;
7156 + freeXtPtr((void **)&field);
7158 + return successful;
7162 +** Get matching pattern set attribute.
7166 +** patternAttribute ::=
7167 +** [s|m|e][w|l|r][i]:
7169 +** StringPatternKind:
7170 +** s : start string pattern.
7171 +** m : middle string pattern.
7172 +** e : end string pattern.
7173 +** WordBoundaryAttribute:
7174 +** w : pattern is word (i.e. before and after pattern
7175 +** there must be a delimiter).
7176 +** l : before pattern must be a delimiter (left side).
7177 +** r : after pattern must be a delimiter (right side).
7178 +** default: neither before nor after pattern must be a delimiter.
7179 +** StringAttribute:
7180 +** i : pattern is case insensitive (if not set: pattern is
7181 +** case sensitive).
7182 +** x : pattern is regular expression (if not set: pattern is
7183 +** literal string).
7185 +** Returns TRUE, if pattern attribute was successful read.
7187 +static int getMPSPatternAttribute(
7190 + PatternElementKind *patternKind,
7191 + PatternWordBoundary *wordBoundary,
7192 + int *caseInsensitive,
7193 + int *regularExpression)
7195 + char *field = ReadSymbolicField(inPtr);
7197 + int successful = True;
7199 + *patternKind = PEK_UNKNOWN;
7200 + *wordBoundary = PWB_NONE;
7201 + *caseInsensitive = False;
7202 + *regularExpression = False;
7204 + if (field != NULL)
7206 + attribute = field;
7207 + while (*attribute != '\0' && successful)
7209 + switch (*attribute)
7212 + *patternKind = PEK_END;
7215 + *caseInsensitive = True;
7218 + *wordBoundary = PWB_LEFT;
7221 + *patternKind = PEK_MIDDLE;
7224 + *wordBoundary = PWB_RIGHT;
7227 + *patternKind = PEK_START;
7230 + *wordBoundary = PWB_BOTH;
7233 + *regularExpression = True;
7236 + *errMsg = "unknown string pattern attribute";
7237 + successful = False;
7245 + if (!SkipDelimiter(inPtr, errMsg))
7247 + successful = False;
7251 + freeXtPtr((void **)&field);
7253 + return successful;
7257 +** Returns the (to be reserved) reg. ex. length of an pattern element.
7258 +** Update total number of multi patterns, too.
7260 +static int patternElementLen(
7261 + ReadMatchPatternInfo *info,
7262 + PatternElement *patElement,
7263 + int *nbrOfMultiPatterns)
7265 + PatternElement *referredElement;
7266 + StringPattern *strPat = NULL;
7267 + int patElementLen;
7269 + switch (patElement->peType)
7272 + strPat = &patElement->peVal.peuSingle;
7275 + case PET_MULTIPLE:
7276 + strPat = &patElement->peVal.peuMulti.mpStringPattern;
7278 + (*nbrOfMultiPatterns) ++;
7282 + case PET_REFERENCE:
7284 + info->rmpiElement[patElement->peVal.peuRef.prElementIdx]->
7285 + mpteAll.pesPattern[patElement->peVal.peuRef.prPatternIdx];
7287 + strPat = &referredElement->peVal.peuMulti.mpStringPattern;
7292 + * reserve additional 4 characters ("(?i)") for case insensitive search
7294 + if (strPat->spCaseInsensitive)
7295 + patElementLen = strPat->spLength + 4;
7297 + patElementLen = strPat->spLength;
7300 + * reserve additional 4 characters ("(?:)") for regular expression
7302 + if (strPat->spRegularExpression)
7303 + patElementLen += 4;
7305 + return patElementLen;
7309 +** Returns the (to be reserved) total reg. ex. length of given
7310 +** MatchPatternTableElement. Update total number of multi patterns, too.
7312 +static int totalMatchPatternTableElementLen(
7313 + ReadMatchPatternInfo *info,
7314 + MatchPatternTableElement *element,
7315 + int *nbrOfMultiPatterns)
7320 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i ++)
7323 + patternElementLen(
7325 + element->mpteAll.pesPattern[i],
7326 + nbrOfMultiPatterns );
7333 +** Returns the (to be reserved) total reg. ex. length of given
7334 +** read match pattern info. Counts total number of multi patterns, too.
7336 +static int totalKeywordOfTableLen(
7337 + ReadMatchPatternInfo *info,
7338 + int *nbrOfMultiPatterns)
7343 + *nbrOfMultiPatterns = 0;
7345 + for (i=0; i<info->rmpiNbrOfElements; i ++)
7348 + totalMatchPatternTableElementLen(
7350 + info->rmpiElement[i],
7351 + nbrOfMultiPatterns);
7358 +** Add given StringPattern to given reg. ex. strings
7360 +static void addPatternToRegExpString(
7361 + StringPattern *pattern,
7362 + RegExpStringInfo *regExpStringInfo)
7364 + char *r = NULL, *s;
7365 + char *adaptedRegExpText = NULL;
7369 + * Select the buffer, where the pattern needs to be added
7370 + * to (depending on its word boundary). Prepare the buffer
7371 + * by evtl. adding a prefix, if related buffer is empty.
7373 + switch (pattern->spWordBoundary)
7376 + prevLen = strlen( regExpStringInfo->resiNoneWBRegExpString );
7378 + r = regExpStringInfo->resiNoneWBRegExpString + strlen( regExpStringInfo->resiNoneWBRegExpString );
7381 + prevLen = strlen( regExpStringInfo->resiLeftWBRegExpString );
7384 + strcpy( regExpStringInfo->resiLeftWBRegExpString, "<(?:" );
7386 + r = regExpStringInfo->resiLeftWBRegExpString + strlen( regExpStringInfo->resiLeftWBRegExpString );
7389 + prevLen = strlen( regExpStringInfo->resiRightWBRegExpString );
7392 + strcpy( regExpStringInfo->resiRightWBRegExpString, "(?:" );
7394 + r = regExpStringInfo->resiRightWBRegExpString + strlen( regExpStringInfo->resiRightWBRegExpString );
7397 + prevLen = strlen( regExpStringInfo->resiBothWBRegExpString );
7400 + strcpy( regExpStringInfo->resiBothWBRegExpString, "<(?:" );
7402 + r = regExpStringInfo->resiBothWBRegExpString + strlen( regExpStringInfo->resiBothWBRegExpString );
7407 + * add an "or" if there is already a pattern in the buffer
7415 + * add "(?i" to order case insensitive search
7417 + if (pattern->spCaseInsensitive)
7425 + * add "(?:" to group this regular expression
7427 + if (pattern->spRegularExpression)
7433 + adaptedRegExpText =
7434 + adaptLocalBackRefs(
7436 + ®ExpStringInfo->resiLocalBackRefID);
7438 + s = adaptedRegExpText;
7442 + s = pattern->spText;
7446 + * add the pattern characters - evtl. escaped, if special
7447 + * regular expression symbols & pattern is no reg. exp. -
7451 + while (*s != '\0')
7453 + if (!pattern->spRegularExpression)
7484 + * close "reg. exp. group" bracket
7486 + if (pattern->spRegularExpression)
7490 + XtFree(adaptedRegExpText);
7494 + * close case insensitive search bracket
7496 + if (pattern->spCaseInsensitive)
7502 + * terminate added string
7508 +** Adapt local backrefs inside given regExpText by common local IDs.
7509 +** Returns new allocated reg. exp. string holding common local backrefs.
7511 +static char *adaptLocalBackRefs(
7513 + int *commonLocalId)
7516 + int ownLocalId = 0;
7517 + char *s = regExpText;
7518 + char *newRegExpText = XtMalloc(strlen(regExpText)*3);
7519 + char *n = newRegExpText;
7520 + int localBackRefList[MAX_LOCAL_BACK_REF_ID];
7523 + * put all local backrefs into "localBackRefList".
7525 + scanForLocalBackRefs(regExpText, localBackRefList);
7527 + while (*s != '\0')
7535 + if (isdigit((unsigned char)*s))
7538 + * \n (n=1..9) found: replace local backref.
7539 + * by "common local ID"
7542 + (int)((unsigned char)*s - (unsigned char)'0') - 1;
7544 + if (localBackRefList[id] != NO_LOCAL_BACK_REF_ID &&
7545 + localBackRefList[id] != LOCAL_BACK_REF_ID_USED)
7547 + *n++ = (char)((int)('0') + localBackRefList[id]);
7556 + else if (*s != '\0')
7559 + * copy escaped character
7564 + else if (*s == '(')
7571 + * non capturing parentheses found -> just copy it
7578 + * capturing parentheses found:
7580 + if (localBackRefList[ownLocalId] == LOCAL_BACK_REF_ID_USED)
7583 + * backref used within given reg. exp. text:
7584 + * remember common local id for replacement later on
7586 + localBackRefList[ownLocalId] = *commonLocalId;
7587 + (*commonLocalId) ++;
7593 + * backref not used within given reg. exp. text:
7594 + * replace capturing parentheses by non capturing one
7608 + * terminate adapted string
7612 + return newRegExpText;
7616 +** Get all local backrefs of given regExpText and put them into
7617 +** given localBackRefList.
7619 +static void scanForLocalBackRefs(
7621 + int *localBackRefList)
7625 + char *s = regExpText;
7627 + for (i=0; i<MAX_LOCAL_BACK_REF_ID; i++)
7629 + localBackRefList[i] = NO_LOCAL_BACK_REF_ID;
7632 + while (*s != '\0')
7636 + if (isdigit((unsigned char)*(s+1)))
7639 + * \n (n=1..9) found: flag usage in local backref list
7642 + (int)((unsigned char)*(s+1) - (unsigned char)'0') - 1;
7644 + localBackRefList[localId] = LOCAL_BACK_REF_ID_USED;
7648 + else if (*(s+1) != '\0')
7656 +** Returns true, if string of given multi pattern reference was
7657 +** not added to regExpStringInfo.
7659 +static int isMultiPatternNotAdded(
7660 + RegExpStringInfo *regExpStringInfo,
7661 + PatternReference *toBeAddedPR)
7664 + PatternReference *addedPR;
7665 + PatternReference *newPR;
7667 + for (i=0; i < regExpStringInfo->resiNbrOfAddedMultiPat; i++)
7669 + addedPR = regExpStringInfo->resiAddedMultiPat[i];
7671 + if (addedPR->prElementIdx == toBeAddedPR->prElementIdx &&
7672 + addedPR->prPatternIdx == toBeAddedPR->prPatternIdx)
7678 + newPR = (PatternReference *)XtMalloc(sizeof(PatternReference));
7680 + *newPR = *toBeAddedPR;
7682 + regExpStringInfo->resiAddedMultiPat[regExpStringInfo->resiNbrOfAddedMultiPat ++] = newPR;
7688 +** add given PatternElement to given reg. exp. strings
7690 +static void addUniquePatternToRegExpString(
7691 + PatternElement *patElement,
7692 + PatternReference *patElementReference,
7693 + ReadMatchPatternInfo *readMatchPatternInfo,
7694 + RegExpStringInfo *regExpStringInfo)
7696 + PatternElement *referredElement;
7697 + PatternReference referredPatReference;
7699 + switch (patElement->peType)
7702 + addPatternToRegExpString(
7703 + &(patElement->peVal.peuSingle),
7704 + regExpStringInfo);
7707 + case PET_MULTIPLE:
7709 + * add element to reg. exp. string only, if it was
7710 + * not added before.
7712 + if (isMultiPatternNotAdded(regExpStringInfo, patElementReference))
7714 + addPatternToRegExpString(
7715 + &(patElement->peVal.peuMulti.mpStringPattern),
7716 + regExpStringInfo);
7720 + case PET_REFERENCE:
7722 + * add referred element to reg. exp. string only, if related
7723 + * multi pattern was not added before.
7725 + referredPatReference = patElement->peVal.peuRef;
7728 + readMatchPatternInfo->rmpiElement[referredPatReference.prElementIdx]->
7729 + mpteAll.pesPattern[referredPatReference.prPatternIdx];
7731 + if (isMultiPatternNotAdded(regExpStringInfo, &referredPatReference))
7733 + addPatternToRegExpString(
7734 + &(referredElement->peVal.peuMulti.mpStringPattern),
7735 + regExpStringInfo);
7742 +** add given MatchPatternTableElement to given reg. ex. strings
7744 +static void addElementToRegExpString(
7745 + MatchPatternTableElement *element,
7746 + ReadMatchPatternInfo *readMatchPatternInfo,
7747 + RegExpStringInfo *regExpStringInfo)
7750 + PatternReference elementRef;
7752 + elementRef.prElementIdx = element->mpteIndex;
7754 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i ++)
7756 + elementRef.prPatternIdx = i;
7758 + addUniquePatternToRegExpString(
7759 + element->mpteAll.pesPattern[i],
7761 + readMatchPatternInfo,
7762 + regExpStringInfo);
7767 +** Concatenate strings stored by regExpStringInfo.
7768 +** Free given regExpStringInfo afterwards.
7769 +** Returns resulting string.
7771 +static void catSMTRegExpStrings(
7772 + RegExpStringInfo *regExpStringInfo,
7773 + char **regExpString)
7778 + * allocate & init. a buffer for the resulting regular expression
7781 + strlen( regExpStringInfo->resiNoneWBRegExpString ) +
7782 + strlen( regExpStringInfo->resiLeftWBRegExpString ) +
7783 + strlen( regExpStringInfo->resiRightWBRegExpString ) +
7784 + strlen( regExpStringInfo->resiBothWBRegExpString ) + 5;
7786 + *regExpString = XtMalloc( resultingLen );
7788 + strcpy( *regExpString, "" );
7791 + * add the single parts to the resulting regular expression
7792 + * (= cat of parts separated by an "or")
7794 + addSMTRegExpString( *regExpString, regExpStringInfo->resiNoneWBRegExpString, "" );
7795 + addSMTRegExpString( *regExpString, regExpStringInfo->resiLeftWBRegExpString, ")" );
7796 + addSMTRegExpString( *regExpString, regExpStringInfo->resiRightWBRegExpString, ")>" );
7797 + addSMTRegExpString( *regExpString, regExpStringInfo->resiBothWBRegExpString, ")>" );
7802 + freeRegExpStringInfo( regExpStringInfo );
7806 +** Free the allocated memory contained in a RegExpStringInfo data structure
7808 +static void freeRegExpStringInfo(
7809 + RegExpStringInfo *regExpStringInfo)
7813 + XtFree( regExpStringInfo->resiNoneWBRegExpString );
7814 + XtFree( regExpStringInfo->resiLeftWBRegExpString );
7815 + XtFree( regExpStringInfo->resiRightWBRegExpString );
7816 + XtFree( regExpStringInfo->resiBothWBRegExpString );
7818 + for (i=0; i < regExpStringInfo->resiNbrOfAddedMultiPat; i ++)
7819 + XtFree( (char *)regExpStringInfo->resiAddedMultiPat[i] );
7821 + XtFree( (char *)regExpStringInfo->resiAddedMultiPat);
7825 +** Compose regular expression for start / end pattern.
7827 +static void composeStartEndRegExpString(
7828 + ReadMatchPatternInfo *readMatchPatternInfo,
7829 + MatchPatternTableElement *element,
7830 + char **regExpString)
7833 + RegExpStringInfo regExpStringInfo;
7834 + PatternReference elementRef;
7835 + PatternElementSet startPat = element->mpteStart;
7836 + PatternElementSet endPat = element->mpteEnd;
7839 + * Allocate buffers for keyword regular expression.
7841 + setupRegExpStringBuffers(
7842 + readMatchPatternInfo,
7843 + ®ExpStringInfo);
7846 + * Treat start / end element of MatchPatternTableElement
7849 + elementRef.prElementIdx = element->mpteIndex;
7851 + for (i=0; i < startPat.pesNumberOfPattern; i ++)
7853 + elementRef.prPatternIdx = startPat.pesPattern[i]->peIndex;
7855 + addUniquePatternToRegExpString(
7856 + startPat.pesPattern[i],
7858 + readMatchPatternInfo,
7859 + ®ExpStringInfo);
7862 + for (i=0; i < endPat.pesNumberOfPattern; i ++)
7864 + elementRef.prPatternIdx = endPat.pesPattern[i]->peIndex;
7866 + addUniquePatternToRegExpString(
7867 + endPat.pesPattern[i],
7869 + readMatchPatternInfo,
7870 + ®ExpStringInfo);
7874 + * Assemble the resulting regular expression
7876 + catSMTRegExpStrings(
7877 + ®ExpStringInfo,
7881 +static void copyStringMatchTableForDialog(
7882 + StringMatchTable *sourceTable,
7883 + DialogMatchPatternInfo *dialogTable )
7888 + * if no source table exist (yet), then set nbr. of elements / groups to 0
7890 + if (sourceTable == NULL)
7892 + dialogTable->dmpiNbrOfSeqElements = 0;
7898 + * copy matching pattern sequence
7900 + dialogTable->dmpiNbrOfSeqElements = sourceTable->smtNumberOfSeqElements;
7902 + for (i=0; i < sourceTable->smtNumberOfSeqElements; i ++)
7904 + copySequenceElementForDialog(
7906 + sourceTable->smtSequence[i],
7907 + &dialogTable->dmpiSequence[i] );
7911 +static void *copyMatchPatternElementForDialog(
7912 + MatchPatternTable *table,
7913 + int sourceElementIdx)
7917 + MatchPatternTableElement *sourceElement;
7918 + DialogMatchPatternTableElement *destination;
7920 + sourceElement = table->mptElements[sourceElementIdx];
7923 + (DialogMatchPatternTableElement *)XtMalloc( sizeof(DialogMatchPatternTableElement) );
7925 + destination->dmpteName = XtNewString(sourceElement->mpteName);
7926 + destination->dmpteType = sourceElement->mpteType;
7927 + destination->dmpteSkipBtwnStartEnd = sourceElement->mpteSkipBtwnStartEnd;
7928 + destination->dmpteIgnoreHighLightInfo = sourceElement->mpteIgnoreHighLightInfo;
7929 + destination->dmpteFlash = sourceElement->mpteFlash;
7931 + for (i=0; i<sourceElement->mpteAll.pesNumberOfPattern; i++)
7933 + copyPatternForDialog(
7935 + sourceElement->mpteAll.pesPattern[i],
7936 + &destination->dmptePatterns.dspElements[patIdx ++]);
7939 + destination->dmptePatterns.dspNumberOfPatterns = patIdx;
7941 + return (void *)destination;
7944 +static void copyPatternForDialog(
7945 + MatchPatternTable *table,
7946 + PatternElement *sourcePattern,
7947 + DialogStringPatternElement **dialogPattern )
7949 + DialogStringPatternElement *newPat;
7950 + StringPattern *strSourcePat = GetStringPattern( table, sourcePattern );
7952 + newPat = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
7953 + *dialogPattern = newPat;
7955 + if( strSourcePat->spOrigText != NULL)
7956 + newPat->dspeText = XtNewString(strSourcePat->spOrigText);
7958 + newPat->dspeText = XtNewString(strSourcePat->spText);
7960 + newPat->dspeKind = sourcePattern->peKind;
7961 + newPat->dspeWordBoundary = strSourcePat->spWordBoundary;
7962 + newPat->dspeCaseInsensitive = strSourcePat->spCaseInsensitive;
7963 + newPat->dspeRegularExpression = strSourcePat->spRegularExpression;
7966 +static void *copyGroupElementForDialog(
7967 + MatchPatternGroupElement *sourceGroup)
7970 + DialogMatchPatternGroupElement *destination;
7973 + (DialogMatchPatternGroupElement *)XtMalloc( sizeof(DialogMatchPatternGroupElement) );
7975 + destination->dmpgeName = XtNewString(sourceGroup->mpgeName);
7976 + destination->dmpgeNumberOfSubPatterns = sourceGroup->mpgeNumberOfSubPatterns;
7978 + for ( i=0; i<destination->dmpgeNumberOfSubPatterns; i ++)
7980 + destination->dmpgeSubPatternIds[i] =
7981 + XtNewString(sourceGroup->mpgeSubPatternIds[i]);
7984 + return destination;
7987 +static void copySequenceElementForDialog(
7988 + StringMatchTable *sourceTable,
7989 + MatchPatternSequenceElement *sourceSeqElement,
7990 + DialogMatchPatternSequenceElement **dialogSeqElement )
7992 + DialogMatchPatternSequenceElement *destSeqElement;
7995 + (DialogMatchPatternSequenceElement *)XtMalloc( sizeof(DialogMatchPatternSequenceElement) );
7997 + *dialogSeqElement = destSeqElement;
7999 + destSeqElement->dmpseName = XtNewString(sourceSeqElement->mpseName);
8000 + destSeqElement->dmpseType = sourceSeqElement->mpseType;
8001 + destSeqElement->dmpseValid = True;
8003 + if (destSeqElement->dmpseType == MPT_GROUP)
8005 + destSeqElement->dmpsePtr =
8006 + copyGroupElementForDialog(
8007 + sourceTable->smtGroups[sourceSeqElement->mpseIndex]);
8011 + destSeqElement->dmpsePtr =
8012 + copyMatchPatternElementForDialog(
8013 + sourceTable->smtAllPatterns,
8014 + sourceSeqElement->mpseIndex);
8018 +static DialogMatchPatternSequenceElement *copyDialogSequenceElement(
8019 + DialogMatchPatternSequenceElement *sourceSeq)
8021 + DialogMatchPatternSequenceElement *destSeq;
8024 + (DialogMatchPatternSequenceElement *)XtMalloc(sizeof(DialogMatchPatternSequenceElement));
8026 + destSeq->dmpseName = XtNewString(sourceSeq->dmpseName);
8027 + destSeq->dmpseType = sourceSeq->dmpseType;
8028 + destSeq->dmpseValid = True;
8030 + destSeq->dmpsePtr = sourceSeq->dmpsePtr;
8035 +static void freeDialogMatchPatternElement(
8036 + DialogMatchPatternTableElement *dialogElement )
8040 + for (i=0; i<dialogElement->dmptePatterns.dspNumberOfPatterns; i ++)
8042 + freeDialogStringPatternElement(
8043 + dialogElement->dmptePatterns.dspElements[i]);
8046 + freeXtPtr((void **)&dialogElement->dmpteName);
8048 + freeXtPtr((void **)&dialogElement);
8051 +static void freeDialogStringPatternElement(
8052 + DialogStringPatternElement *element)
8054 + freeXtPtr((void **)&element->dspeText);
8056 + freeXtPtr((void **)&element);
8059 +static void freeDialogGroupElement(
8060 + DialogMatchPatternGroupElement *dialogGroup )
8064 + for (i=0; i<dialogGroup->dmpgeNumberOfSubPatterns; i ++)
8066 + freeXtPtr((void **)&dialogGroup->dmpgeSubPatternIds[i]);
8069 + freeXtPtr((void **)&dialogGroup->dmpgeName);
8071 + freeXtPtr((void **)&dialogGroup);
8074 +static void freeDialogSequenceElement(
8075 + DialogMatchPatternSequenceElement *dialogSeq )
8077 + freeXtPtr((void **)&dialogSeq->dmpseName);
8079 + if (dialogSeq->dmpseType == MPT_GROUP)
8081 + freeDialogGroupElement(
8082 + (DialogMatchPatternGroupElement *)dialogSeq->dmpsePtr );
8086 + freeDialogMatchPatternElement(
8087 + (DialogMatchPatternTableElement *)dialogSeq->dmpsePtr );
8090 + freeXtPtr((void **)&dialogSeq);
8093 +static void copyDialogStringPatternsFromTable(
8094 + DialogMatchPatternTableElement *tableElement,
8095 + DialogStringPatterns *destPatterns)
8099 + destPatterns->dspNumberOfPatterns =
8100 + tableElement->dmptePatterns.dspNumberOfPatterns;
8102 + for (i=0; i<destPatterns->dspNumberOfPatterns; i++)
8104 + destPatterns->dspElements[i] =
8105 + copyDialogStringPatternElement(
8106 + tableElement->dmptePatterns.dspElements[i] );
8110 +static void copyDialogStringPatterns(
8111 + DialogStringPatterns *sourcePatterns,
8112 + DialogStringPatterns *destPatterns)
8116 + destPatterns->dspNumberOfPatterns =
8117 + sourcePatterns->dspNumberOfPatterns;
8119 + for (i=0; i<destPatterns->dspNumberOfPatterns; i++)
8121 + destPatterns->dspElements[i] =
8122 + copyDialogStringPatternElement(
8123 + sourcePatterns->dspElements[i] );
8127 +static void freeDialogStringPatterns(
8128 + DialogStringPatterns *patterns)
8132 + for (i=0; i<patterns->dspNumberOfPatterns; i++)
8134 + freeDialogStringPatternElement(patterns->dspElements[i]);
8137 + patterns->dspNumberOfPatterns = 0;
8140 +static DialogStringPatternElement *copyDialogStringPatternElement(
8141 + DialogStringPatternElement *sourceElement)
8143 + DialogStringPatternElement *newPatElement;
8145 + newPatElement = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
8147 + newPatElement->dspeText = XtNewString(sourceElement->dspeText);
8148 + newPatElement->dspeKind = sourceElement->dspeKind;
8149 + newPatElement->dspeWordBoundary = sourceElement->dspeWordBoundary;
8150 + newPatElement->dspeCaseInsensitive = sourceElement->dspeCaseInsensitive;
8151 + newPatElement->dspeRegularExpression = sourceElement->dspeRegularExpression;
8153 + return newPatElement;
8156 +static void copyDialogPatternNamesFromGroup(
8157 + DialogMatchPatternGroupElement *group,
8158 + DialogStringPatterns *destPatterns)
8162 + destPatterns->dspNumberOfPatterns =
8163 + group->dmpgeNumberOfSubPatterns;
8165 + for (i=0; i<destPatterns->dspNumberOfPatterns; i++)
8167 + destPatterns->dspElements[i] =
8168 + copyDialogPatternName(
8169 + group->dmpgeSubPatternIds[i] );
8173 +static DialogStringPatternElement *copyDialogPatternName(
8174 + char *sourcePatternId)
8176 + DialogStringPatternElement *newPatElement;
8178 + newPatElement = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
8180 + newPatElement->dspeText = XtNewString(sourcePatternId);
8181 + newPatElement->dspeKind = PEK_START;
8182 + newPatElement->dspeWordBoundary = PWB_NONE;
8183 + newPatElement->dspeCaseInsensitive = False;
8184 + newPatElement->dspeRegularExpression = False;
8186 + return newPatElement;
8189 +static void copyDialogPatternNamesToGroup(
8190 + DialogStringPatterns *sourceNames,
8191 + DialogMatchPatternGroupElement *destGroup)
8195 + destGroup->dmpgeNumberOfSubPatterns =
8196 + sourceNames->dspNumberOfPatterns;
8198 + for (i=0; i<destGroup->dmpgeNumberOfSubPatterns; i++)
8200 + destGroup->dmpgeSubPatternIds[i] =
8202 + sourceNames->dspElements[i]->dspeText);
8208 +** Present a dialog for editing matching pattern information
8210 +void EditMatchPatterns(WindowInfo *window)
8212 + Widget form, lmOptMenu;
8214 + Widget okBtn, applyBtn, checkBtn, deleteBtn, closeBtn, helpBtn;
8215 + Widget restoreBtn, lmBtn;
8216 + Widget matchPatternsForm, matchPatternsFrame, matchPatternsLbl;
8217 + Widget matchPatternTypeBox, matchPatternTypeLbl;
8218 + Widget globalAttributesBox;
8219 + Widget stringPatternsFrame, stringPatternsForm;
8220 + Widget stringPatternTypeBox;
8221 + Widget wordBoundaryBox;
8222 + Widget stringAttributesBox;
8223 + StringMatchTable *table;
8229 + * if the dialog is already displayed, just pop it to the top and return
8231 + if (MatchPatternDialog.mpdShell != NULL)
8233 + RaiseDialogWindow(MatchPatternDialog.mpdShell);
8238 + * decide on an initial language mode
8240 + MatchPatternDialog.mpdLangModeName =
8242 + window->languageMode == PLAIN_LANGUAGE_MODE ?
8243 + PLAIN_LM_STRING : LanguageModeName(window->languageMode));
8246 + * find the associated matching pattern table to edit
8248 + table = (StringMatchTable *)FindStringMatchTable(MatchPatternDialog.mpdLangModeName);
8251 + * copy the list of patterns to one that the user can freely edit
8253 + copyStringMatchTableForDialog( table, &MatchPatternDialog.mpdTable );
8256 + * init. status information of dialog
8258 + MatchPatternDialog.currentDmptSeqElement = NULL;
8259 + MatchPatternDialog.currentDmptElement = NULL;
8260 + MatchPatternDialog.currentDmptGroup = NULL;
8262 + MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns = 0;
8263 + MatchPatternDialog.mpdStringPatternIsDisplayed = True;
8266 + * Create a form widget in an application shell
8269 + XtSetArg(args[n], XmNdeleteResponse, XmDO_NOTHING); n++;
8270 + XtSetArg(args[n], XmNiconName, "Matching Patterns"); n++;
8271 + XtSetArg(args[n], XmNtitle, "Matching (Parenthesis) Patterns"); n++;
8272 + MatchPatternDialog.mpdShell = CreateShellWithBestVis(APP_NAME, APP_CLASS,
8273 + applicationShellWidgetClass, TheDisplay, args, n);
8274 + AddSmallIcon(MatchPatternDialog.mpdShell);
8275 + form = XtVaCreateManagedWidget("editMatchPatterns", xmFormWidgetClass,
8276 + MatchPatternDialog.mpdShell, XmNautoUnmanage, False,
8277 + XmNresizePolicy, XmRESIZE_NONE, NULL);
8278 + XtAddCallback(form, XmNdestroyCallback, destroyCB, NULL);
8279 + AddMotifCloseCallback(MatchPatternDialog.mpdShell, closeCB, NULL);
8281 + lmForm = XtVaCreateManagedWidget("lmForm", xmFormWidgetClass,
8283 + XmNleftAttachment, XmATTACH_POSITION,
8284 + XmNleftPosition, 1,
8285 + XmNtopAttachment, XmATTACH_POSITION,
8286 + XmNtopPosition, 1,
8287 + XmNrightAttachment, XmATTACH_POSITION,
8288 + XmNrightPosition, 99, NULL);
8290 + MatchPatternDialog.mpdLmPulldown =
8291 + CreateLanguageModeMenu(lmForm, matchPatternLangModeCB, NULL, True);
8294 + XtSetArg(args[n], XmNspacing, 0); n++;
8295 + XtSetArg(args[n], XmNmarginWidth, 0); n++;
8296 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
8297 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8298 + XtSetArg(args[n], XmNleftPosition, 50); n++;
8299 + XtSetArg(args[n], XmNsubMenuId, MatchPatternDialog.mpdLmPulldown); n++;
8300 + lmOptMenu = XmCreateOptionMenu(lmForm, "langModeOptMenu", args, n);
8301 + XtManageChild(lmOptMenu);
8302 + MatchPatternDialog.mpdLmOptMenu = lmOptMenu;
8304 + XtVaCreateManagedWidget("lmLbl", xmLabelGadgetClass, lmForm,
8305 + XmNlabelString, s1=XmStringCreateSimple("Language Mode:"),
8307 + XmNuserData, XtParent(MatchPatternDialog.mpdLmOptMenu),
8308 + XmNalignment, XmALIGNMENT_END,
8309 + XmNrightAttachment, XmATTACH_POSITION,
8310 + XmNrightPosition, 50,
8311 + XmNtopAttachment, XmATTACH_FORM,
8312 + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
8313 + XmNbottomWidget, lmOptMenu, NULL);
8316 + lmBtn = XtVaCreateManagedWidget("lmBtn", xmPushButtonWidgetClass, lmForm,
8317 + XmNlabelString, s1=MKSTRING("Add / Modify\nLanguage Mode..."),
8319 + XmNrightAttachment, XmATTACH_FORM,
8320 + XmNtopAttachment, XmATTACH_FORM, NULL);
8321 + XtAddCallback(lmBtn, XmNactivateCallback, pmLanguageModeDialogCB, NULL);
8324 + okBtn = XtVaCreateManagedWidget("ok", xmPushButtonWidgetClass, form,
8325 + XmNlabelString, s1=XmStringCreateSimple("OK"),
8326 + XmNleftAttachment, XmATTACH_POSITION,
8327 + XmNleftPosition, 1,
8328 + XmNrightAttachment, XmATTACH_POSITION,
8329 + XmNrightPosition, 13,
8330 + XmNbottomAttachment, XmATTACH_FORM,
8331 + XmNbottomOffset, BORDER, NULL);
8332 + XtAddCallback(okBtn, XmNactivateCallback, okCB, NULL);
8335 + applyBtn = XtVaCreateManagedWidget("apply", xmPushButtonWidgetClass, form,
8336 + XmNlabelString, s1=XmStringCreateSimple("Apply"),
8338 + XmNleftAttachment, XmATTACH_POSITION,
8339 + XmNleftPosition, 13,
8340 + XmNrightAttachment, XmATTACH_POSITION,
8341 + XmNrightPosition, 26,
8342 + XmNbottomAttachment, XmATTACH_FORM,
8343 + XmNbottomOffset, BORDER, NULL);
8344 + XtAddCallback(applyBtn, XmNactivateCallback, applyCB, NULL);
8347 + checkBtn = XtVaCreateManagedWidget("check", xmPushButtonWidgetClass, form,
8348 + XmNlabelString, s1=XmStringCreateSimple("Check"),
8350 + XmNleftAttachment, XmATTACH_POSITION,
8351 + XmNleftPosition, 26,
8352 + XmNrightAttachment, XmATTACH_POSITION,
8353 + XmNrightPosition, 39,
8354 + XmNbottomAttachment, XmATTACH_FORM,
8355 + XmNbottomOffset, BORDER, NULL);
8356 + XtAddCallback(checkBtn, XmNactivateCallback, checkCB, NULL);
8359 + deleteBtn = XtVaCreateManagedWidget("delete", xmPushButtonWidgetClass, form,
8360 + XmNlabelString, s1=XmStringCreateSimple("Delete"),
8362 + XmNleftAttachment, XmATTACH_POSITION,
8363 + XmNleftPosition, 39,
8364 + XmNrightAttachment, XmATTACH_POSITION,
8365 + XmNrightPosition, 52,
8366 + XmNbottomAttachment, XmATTACH_FORM,
8367 + XmNbottomOffset, BORDER, NULL);
8368 + XtAddCallback(deleteBtn, XmNactivateCallback, deleteCB, NULL);
8371 + restoreBtn = XtVaCreateManagedWidget("restore", xmPushButtonWidgetClass, form,
8372 + XmNlabelString, s1=XmStringCreateSimple("Restore Defaults"),
8374 + XmNleftAttachment, XmATTACH_POSITION,
8375 + XmNleftPosition, 52,
8376 + XmNrightAttachment, XmATTACH_POSITION,
8377 + XmNrightPosition, 73,
8378 + XmNbottomAttachment, XmATTACH_FORM,
8379 + XmNbottomOffset, BORDER, NULL);
8380 + XtAddCallback(restoreBtn, XmNactivateCallback, restoreCB, NULL);
8383 + closeBtn = XtVaCreateManagedWidget("close", xmPushButtonWidgetClass,
8385 + XmNlabelString, s1=XmStringCreateSimple("Close"),
8386 + XmNleftAttachment, XmATTACH_POSITION,
8387 + XmNleftPosition, 73,
8388 + XmNrightAttachment, XmATTACH_POSITION,
8389 + XmNrightPosition, 86,
8390 + XmNbottomAttachment, XmATTACH_FORM,
8391 + XmNbottomOffset, BORDER, NULL);
8392 + XtAddCallback(closeBtn, XmNactivateCallback, closeCB, NULL);
8395 + helpBtn = XtVaCreateManagedWidget("help", xmPushButtonWidgetClass,
8397 + XmNlabelString, s1=XmStringCreateSimple("Help"),
8399 + XmNleftAttachment, XmATTACH_POSITION,
8400 + XmNleftPosition, 86,
8401 + XmNrightAttachment, XmATTACH_POSITION,
8402 + XmNrightPosition, 99,
8403 + XmNbottomAttachment, XmATTACH_FORM,
8404 + XmNbottomOffset, BORDER, NULL);
8405 + XtAddCallback(helpBtn, XmNactivateCallback, helpCB, NULL);
8408 + stringPatternsFrame = XtVaCreateManagedWidget("stringPatternsFrame", xmFrameWidgetClass,
8410 + XmNleftAttachment, XmATTACH_POSITION,
8411 + XmNleftPosition, 1,
8412 + XmNrightAttachment, XmATTACH_POSITION,
8413 + XmNrightPosition, 99,
8414 + XmNbottomAttachment, XmATTACH_WIDGET,
8415 + XmNbottomWidget, okBtn,
8416 + XmNbottomOffset, BORDER, NULL);
8417 + stringPatternsForm = XtVaCreateManagedWidget("stringPatternsForm", xmFormWidgetClass,
8418 + stringPatternsFrame, NULL);
8419 + MatchPatternDialog.mpdStringPatternsLbl = XtVaCreateManagedWidget("mpdStringPatternsLbl", xmLabelGadgetClass,
8420 + stringPatternsFrame,
8421 + XmNlabelString, s1=XmStringCreateSimple(STRING_PATTERNS_LBL_TXT),
8422 + XmNmarginHeight, 0,
8423 + XmNchildType, XmFRAME_TITLE_CHILD, NULL);
8427 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
8428 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8429 + XtSetArg(args[n], XmNleftPosition, 1); n++;
8430 + XtSetArg(args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
8431 + XtSetArg(args[n], XmNrightPosition, LIST_RIGHT-1); n++;
8432 + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
8433 + XtSetArg(args[n], XmNbottomOffset, BORDER); n++;
8434 + MatchPatternDialog.mpdStringPatternsListW =
8435 + CreateManagedList(stringPatternsForm, "stringPatternsList", args,
8436 + n, (void **)MatchPatternDialog.currentStringPatterns.dspElements,
8437 + &MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns,
8438 + MAX_STRING_PATTERNS, 18,
8439 + getStringPatternDisplayedCB, NULL,
8440 + setStringPatternDisplayedCB, NULL,
8441 + freeStringPatternItemCB);
8442 + XtVaSetValues(MatchPatternDialog.mpdStringPatternsLbl, XmNuserData, MatchPatternDialog.mpdStringPatternsListW, NULL);
8444 + MatchPatternDialog.mpdStringPatternTypeLbl = XtVaCreateManagedWidget("mpdStringPatternTypeLbl", xmLabelGadgetClass,
8445 + stringPatternsForm,
8446 + XmNlabelString, s1=XmStringCreateSimple("String Pattern Type:"),
8447 + XmNmarginHeight, 0,
8448 + XmNalignment, XmALIGNMENT_BEGINNING,
8449 + XmNleftAttachment, XmATTACH_POSITION,
8450 + XmNleftPosition, LIST_RIGHT,
8451 + XmNtopAttachment, XmATTACH_FORM, NULL);
8454 + stringPatternTypeBox = XtVaCreateManagedWidget("stringPatternTypeBox", xmRowColumnWidgetClass,
8455 + stringPatternsForm,
8456 + XmNorientation, XmHORIZONTAL,
8457 + XmNpacking, XmPACK_TIGHT,
8458 + XmNradioBehavior, True,
8459 + XmNleftAttachment, XmATTACH_POSITION,
8460 + XmNleftPosition, LIST_RIGHT,
8461 + XmNtopAttachment, XmATTACH_WIDGET,
8462 + XmNtopWidget, MatchPatternDialog.mpdStringPatternTypeLbl, NULL);
8463 + MatchPatternDialog.sptStartW = XtVaCreateManagedWidget("sptStartW",
8464 + xmToggleButtonWidgetClass, stringPatternTypeBox,
8466 + XmNmarginHeight, 0,
8467 + XmNlabelString, s1=XmStringCreateSimple(
8471 + MatchPatternDialog.sptMiddleW = XtVaCreateManagedWidget("sptMiddleW",
8472 + xmToggleButtonWidgetClass, stringPatternTypeBox,
8473 + XmNmarginHeight, 0,
8474 + XmNlabelString, s1=XmStringCreateSimple(
8478 + MatchPatternDialog.sptEndW = XtVaCreateManagedWidget("sptEndW",
8479 + xmToggleButtonWidgetClass, stringPatternTypeBox,
8480 + XmNmarginHeight, 0,
8481 + XmNlabelString, s1=XmStringCreateSimple(
8486 + MatchPatternDialog.mpdWordBoundaryLbl = XtVaCreateManagedWidget("mpdWordBoundaryLbl", xmLabelGadgetClass,
8487 + stringPatternsForm,
8488 + XmNlabelString, s1=XmStringCreateSimple("Word boundary:"),
8489 + XmNmarginHeight, 0,
8490 + XmNalignment, XmALIGNMENT_BEGINNING,
8491 + XmNleftAttachment, XmATTACH_POSITION,
8492 + XmNleftPosition, LIST_RIGHT,
8493 + XmNtopAttachment, XmATTACH_WIDGET,
8494 + XmNtopWidget, stringPatternTypeBox,
8498 + wordBoundaryBox = XtVaCreateManagedWidget("wordBoundaryBox", xmRowColumnWidgetClass,
8499 + stringPatternsForm,
8500 + XmNorientation, XmHORIZONTAL,
8501 + XmNpacking, XmPACK_TIGHT,
8502 + XmNradioBehavior, True,
8503 + XmNleftAttachment, XmATTACH_POSITION,
8504 + XmNleftPosition, LIST_RIGHT,
8505 + XmNtopAttachment, XmATTACH_WIDGET,
8506 + XmNtopWidget, MatchPatternDialog.mpdWordBoundaryLbl, NULL);
8507 + MatchPatternDialog.wbbBothW = XtVaCreateManagedWidget("wbbBothW",
8508 + xmToggleButtonWidgetClass, wordBoundaryBox,
8510 + XmNmarginHeight, 0,
8511 + XmNlabelString, s1=XmStringCreateSimple(
8512 + "Both (pattern is word)"),
8515 + MatchPatternDialog.wbbLeftW = XtVaCreateManagedWidget("wbbLeftW",
8516 + xmToggleButtonWidgetClass, wordBoundaryBox,
8517 + XmNmarginHeight, 0,
8518 + XmNlabelString, s1=XmStringCreateSimple(
8522 + MatchPatternDialog.wbbRightW = XtVaCreateManagedWidget("wbbRightW",
8523 + xmToggleButtonWidgetClass, wordBoundaryBox,
8524 + XmNmarginHeight, 0,
8525 + XmNlabelString, s1=XmStringCreateSimple(
8529 + MatchPatternDialog.wbbNoneW = XtVaCreateManagedWidget("wbbNoneW",
8530 + xmToggleButtonWidgetClass, wordBoundaryBox,
8531 + XmNmarginHeight, 0,
8532 + XmNlabelString, s1=XmStringCreateSimple(
8537 + MatchPatternDialog.mpdStringAttributesLbl = XtVaCreateManagedWidget("mpdStringAttributesLbl", xmLabelGadgetClass,
8538 + stringPatternsForm,
8539 + XmNlabelString, s1=XmStringCreateSimple("String Attributes:"),
8540 + XmNmarginHeight, 0,
8541 + XmNalignment, XmALIGNMENT_BEGINNING,
8542 + XmNleftAttachment, XmATTACH_POSITION,
8543 + XmNleftPosition, LIST_RIGHT,
8544 + XmNtopAttachment, XmATTACH_WIDGET,
8545 + XmNtopWidget, wordBoundaryBox, NULL);
8548 + stringAttributesBox = XtVaCreateManagedWidget("stringAttributesBox", xmRowColumnWidgetClass,
8549 + stringPatternsForm,
8550 + XmNorientation, XmHORIZONTAL,
8551 + XmNpacking, XmPACK_TIGHT,
8552 + XmNleftAttachment, XmATTACH_POSITION,
8553 + XmNleftPosition, LIST_RIGHT,
8554 + XmNtopAttachment, XmATTACH_WIDGET,
8555 + XmNtopWidget, MatchPatternDialog.mpdStringAttributesLbl, NULL);
8556 + MatchPatternDialog.sabRegularExpressionW = XtVaCreateManagedWidget("sabRegularExpressionW",
8557 + xmToggleButtonWidgetClass, stringAttributesBox,
8559 + XmNmarginHeight, 0,
8560 + XmNlabelString, s1=XmStringCreateSimple(
8561 + "Regular Expression"),
8564 + XtAddCallback(MatchPatternDialog.sabRegularExpressionW, XmNvalueChangedCallback,
8565 + strPatRegExpressionCB, NULL);
8566 + MatchPatternDialog.sabCaseSensitiveW = XtVaCreateManagedWidget("sabCaseSensitiveW",
8567 + xmToggleButtonWidgetClass, stringAttributesBox,
8569 + XmNmarginHeight, 0,
8570 + XmNlabelString, s1=XmStringCreateSimple(
8571 + "Case Sensitive"),
8575 + MatchPatternDialog.mpdStringPatternLbl = XtVaCreateManagedWidget("mpdStringPatternLbl", xmLabelGadgetClass,
8576 + stringPatternsForm,
8577 + XmNlabelString, s1=XmStringCreateSimple("String Pattern"),
8579 + XmNalignment, XmALIGNMENT_BEGINNING,
8580 + XmNleftAttachment, XmATTACH_POSITION,
8581 + XmNleftPosition, LIST_RIGHT,
8582 + XmNtopAttachment, XmATTACH_WIDGET,
8583 + XmNtopWidget, stringAttributesBox,
8584 + XmNtopOffset, BORDER,
8588 + MatchPatternDialog.mpdStringPatternW = XtVaCreateManagedWidget("mpdStringPatternW", xmTextWidgetClass,
8589 + stringPatternsForm,
8590 + XmNleftAttachment, XmATTACH_POSITION,
8591 + XmNleftPosition, LIST_RIGHT,
8592 + XmNtopAttachment, XmATTACH_WIDGET,
8593 + XmNtopWidget, MatchPatternDialog.mpdStringPatternLbl,
8594 + XmNrightAttachment, XmATTACH_FORM,
8595 + XmNrightOffset, BORDER,
8597 + RemapDeleteKey(MatchPatternDialog.mpdStringPatternW);
8598 + XtVaSetValues(MatchPatternDialog.mpdStringPatternLbl, XmNuserData, MatchPatternDialog.mpdStringPatternW, NULL);
8600 + MatchPatternDialog.mpdSubPatNamesLbl = XtVaCreateManagedWidget("mpdSubPatNamesLbl", xmLabelGadgetClass,
8601 + stringPatternsForm,
8602 + XmNlabelString, s1=XmStringCreateSimple("Sub-Pattern Name"),
8604 + XmNalignment, XmALIGNMENT_BEGINNING,
8605 + XmNleftAttachment, XmATTACH_POSITION,
8606 + XmNleftPosition, LIST_RIGHT,
8607 + XmNtopAttachment, XmATTACH_WIDGET,
8608 + XmNtopWidget, MatchPatternDialog.mpdStringPatternW,
8609 + XmNtopOffset, BORDER,
8613 + MatchPatternDialog.mpdSubPatNamesPulldown =
8614 + createSubPatternNameMenu(stringPatternsForm, NULL, False);
8617 + XtSetArg(args[n], XmNspacing, 0); n++;
8618 + XtSetArg(args[n], XmNmarginWidth, 0); n++;
8619 + XtSetArg(args[n], XmNresizeWidth, True); n++;
8620 + XtSetArg(args[n], XmNresizeHeight, True); n++;
8621 + XtSetArg(args[n], XmNnavigationType, XmTAB_GROUP); n++;
8622 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
8623 + XtSetArg(args[n], XmNtopWidget, MatchPatternDialog.mpdSubPatNamesLbl); n++;
8624 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8625 + XtSetArg(args[n], XmNleftPosition, LIST_RIGHT); n++;
8626 + XtSetArg(args[n], XmNsubMenuId, MatchPatternDialog.mpdSubPatNamesPulldown); n++;
8627 + MatchPatternDialog.mpdSubPatNamesOptMenu =
8628 + XmCreateOptionMenu(stringPatternsForm, "subPatNamesOptMenu", args, n);
8629 + XtManageChild(MatchPatternDialog.mpdSubPatNamesOptMenu);
8632 + MatchPatternDialog.mpdSubPatNamesLbl,
8633 + XmNuserData, XtParent(MatchPatternDialog.mpdSubPatNamesOptMenu),
8636 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesLbl, False);
8637 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesOptMenu, False);
8639 + matchPatternsFrame = XtVaCreateManagedWidget("matchPatternsFrame", xmFrameWidgetClass,
8641 + XmNleftAttachment, XmATTACH_POSITION,
8642 + XmNleftPosition, 1,
8643 + XmNtopAttachment, XmATTACH_WIDGET,
8644 + XmNtopWidget, lmForm,
8645 + XmNrightAttachment, XmATTACH_POSITION,
8646 + XmNrightPosition, 99,
8647 + XmNbottomAttachment, XmATTACH_WIDGET,
8648 + XmNbottomWidget, stringPatternsFrame,
8649 + XmNbottomOffset, BORDER, NULL);
8650 + matchPatternsForm = XtVaCreateManagedWidget("matchPatternsForm", xmFormWidgetClass,
8651 + matchPatternsFrame, NULL);
8652 + matchPatternsLbl = XtVaCreateManagedWidget("matchPatternsLbl", xmLabelGadgetClass,
8653 + matchPatternsFrame,
8654 + XmNlabelString, s1=XmStringCreateSimple("Matching Patterns"),
8656 + XmNmarginHeight, 0,
8657 + XmNchildType, XmFRAME_TITLE_CHILD, NULL);
8660 + matchPatternTypeLbl = XtVaCreateManagedWidget("matchPatternTypeLbl", xmLabelGadgetClass,
8661 + matchPatternsForm,
8662 + XmNlabelString, s1=XmStringCreateSimple("Matching Pattern Type:"),
8663 + XmNmarginHeight, 0,
8664 + XmNalignment, XmALIGNMENT_BEGINNING,
8665 + XmNleftAttachment, XmATTACH_POSITION,
8666 + XmNleftPosition, LIST_RIGHT,
8667 + XmNtopAttachment, XmATTACH_FORM, NULL);
8670 + matchPatternTypeBox = XtVaCreateManagedWidget("matchPatternTypeBox", xmRowColumnWidgetClass,
8671 + matchPatternsForm,
8672 + XmNpacking, XmPACK_COLUMN,
8673 + XmNradioBehavior, True,
8674 + XmNleftAttachment, XmATTACH_POSITION,
8675 + XmNleftPosition, LIST_RIGHT,
8676 + XmNtopAttachment, XmATTACH_WIDGET,
8677 + XmNtopWidget, matchPatternTypeLbl, NULL);
8678 + MatchPatternDialog.mptbIndividualW = XtVaCreateManagedWidget("mptbIndividualW",
8679 + xmToggleButtonWidgetClass, matchPatternTypeBox,
8681 + XmNmarginHeight, 0,
8682 + XmNlabelString, s1=XmStringCreateSimple(
8684 + XmNmnemonic, 'I', NULL);
8686 + XtAddCallback(MatchPatternDialog.mptbIndividualW, XmNvalueChangedCallback,
8687 + matchPatTypeCB, NULL);
8688 + MatchPatternDialog.mptbSubPatternW = XtVaCreateManagedWidget("mptbSubPatternW",
8689 + xmToggleButtonWidgetClass, matchPatternTypeBox,
8690 + XmNmarginHeight, 0,
8691 + XmNlabelString, s1=XmStringCreateSimple(
8692 + "Sub-pattern (belongs to context group)"),
8693 + XmNmnemonic, 'u', NULL);
8695 + XtAddCallback(MatchPatternDialog.mptbSubPatternW, XmNvalueChangedCallback,
8696 + matchPatTypeCB, NULL);
8697 + MatchPatternDialog.mptbContextGroupW = XtVaCreateManagedWidget("mptbContextGroupW",
8698 + xmToggleButtonWidgetClass, matchPatternTypeBox,
8699 + XmNmarginHeight, 0,
8700 + XmNlabelString, s1=XmStringCreateSimple(
8702 + XmNmnemonic, 'g', NULL);
8704 + XtAddCallback(MatchPatternDialog.mptbContextGroupW, XmNvalueChangedCallback,
8705 + matchPatTypeCB, NULL);
8707 + MatchPatternDialog.mpdGlobalAttributesLbl = XtVaCreateManagedWidget("mpdGlobalAttributesLbl",
8708 + xmLabelGadgetClass, matchPatternsForm,
8709 + XmNlabelString, s1=XmStringCreateSimple("Global Attributes:"),
8710 + XmNmarginHeight, 0,
8711 + XmNalignment, XmALIGNMENT_BEGINNING,
8712 + XmNleftAttachment, XmATTACH_POSITION,
8713 + XmNleftPosition, LIST_RIGHT,
8714 + XmNtopAttachment, XmATTACH_WIDGET,
8715 + XmNtopOffset, BORDER,
8716 + XmNtopWidget, matchPatternTypeBox, NULL);
8719 + globalAttributesBox = XtVaCreateManagedWidget("globalAttributesBox", xmRowColumnWidgetClass,
8720 + matchPatternsForm,
8721 + XmNpacking, XmPACK_COLUMN,
8722 + XmNleftAttachment, XmATTACH_POSITION,
8723 + XmNleftPosition, LIST_RIGHT,
8724 + XmNtopAttachment, XmATTACH_WIDGET,
8725 + XmNtopWidget, MatchPatternDialog.mpdGlobalAttributesLbl, NULL);
8726 + MatchPatternDialog.gabSkipBtwStartEndW = XtVaCreateManagedWidget("gabSkipBtwStartEndW",
8727 + xmToggleButtonWidgetClass, globalAttributesBox,
8728 + XmNmarginHeight, 0,
8729 + XmNlabelString, s1=XmStringCreateSimple(
8730 + "Skip content between start / end pattern"),
8731 + XmNmnemonic, 'c', NULL);
8733 + MatchPatternDialog.gabFlashW = XtVaCreateManagedWidget("gabFlashW",
8734 + xmToggleButtonWidgetClass, globalAttributesBox,
8736 + XmNmarginHeight, 0,
8737 + XmNlabelString, s1=XmStringCreateSimple(
8738 + "Flash matching pattern"),
8739 + XmNmnemonic, 'l', NULL);
8741 + MatchPatternDialog.gabSyntaxBasedW = XtVaCreateManagedWidget("gabSyntaxBasedW",
8742 + xmToggleButtonWidgetClass, globalAttributesBox,
8744 + XmNmarginHeight, 0,
8745 + XmNlabelString, s1=XmStringCreateSimple(
8747 + XmNmnemonic, 'b', NULL);
8750 + MatchPatternDialog.mpdMatchPatternNameLbl = XtVaCreateManagedWidget("mpdMatchPatternNameLbl", xmLabelGadgetClass,
8751 + matchPatternsForm,
8752 + XmNlabelString, s1=XmStringCreateSimple(MATCH_PAT_NAME_LBL_TXT),
8754 + XmNalignment, XmALIGNMENT_BEGINNING,
8755 + XmNleftAttachment, XmATTACH_POSITION,
8756 + XmNleftPosition, LIST_RIGHT,
8757 + XmNtopAttachment, XmATTACH_WIDGET,
8758 + XmNtopWidget, globalAttributesBox,
8759 + XmNtopOffset, BORDER, NULL);
8762 + MatchPatternDialog.mpdMatchPatternNameW = XtVaCreateManagedWidget("mpdMatchPatternNameW", xmTextWidgetClass,
8763 + matchPatternsForm,
8764 + XmNleftAttachment, XmATTACH_POSITION,
8765 + XmNleftPosition, LIST_RIGHT,
8766 + XmNtopAttachment, XmATTACH_WIDGET,
8767 + XmNtopWidget, MatchPatternDialog.mpdMatchPatternNameLbl,
8768 + XmNrightAttachment, XmATTACH_FORM,
8769 + XmNrightOffset, BORDER,
8770 + XmNbottomAttachment, XmATTACH_FORM,
8771 + XmNbottomOffset, BORDER,
8773 + RemapDeleteKey(MatchPatternDialog.mpdMatchPatternNameW);
8774 + XtVaSetValues(MatchPatternDialog.mpdMatchPatternNameLbl, XmNuserData, MatchPatternDialog.mpdMatchPatternNameW, NULL);
8777 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
8778 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8779 + XtSetArg(args[n], XmNleftPosition, 1); n++;
8780 + XtSetArg(args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
8781 + XtSetArg(args[n], XmNrightPosition, LIST_RIGHT-1); n++;
8782 + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
8784 + XtSetArg(args[n], XmNbottomOffset, BORDER); n++;
8785 + MatchPatternDialog.mpdMatchPatternNamesListW =
8786 + CreateManagedList(
8787 + matchPatternsForm, "mpdMatchPatternNamesListW",
8789 + (void **)MatchPatternDialog.mpdTable.dmpiSequence, &MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements,
8790 + MAX_NBR_MATCH_PATTERNS, 18,
8791 + getMatchPatternDisplayedCB, NULL,
8792 + setMatchPatternDisplayedCB, NULL,
8793 + freeMatchPatternItemCB);
8794 + AddDeleteConfirmCB(MatchPatternDialog.mpdMatchPatternNamesListW, deleteMatchPatternItemCB, NULL);
8796 + XtVaSetValues(matchPatternsLbl, XmNuserData, MatchPatternDialog.mpdMatchPatternNamesListW, NULL);
8799 + * set initial default button
8801 + XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
8802 + XtVaSetValues(form, XmNcancelButton, closeBtn, NULL);
8805 + * handle mnemonic selection of buttons and focus to dialog
8807 + AddDialogMnemonicHandler(form, False);
8810 + * fill in the dialog information for the selected language mode
8812 + SetLangModeMenu(MatchPatternDialog.mpdLmOptMenu, MatchPatternDialog.mpdLangModeName);
8815 + * realize all of the widgets in the new dialog
8817 + RealizeWithoutForcingPosition(MatchPatternDialog.mpdShell);
8821 +** Modify match pattern dialog depending on showing a string pattern
8822 +** or a context group.
8824 +static void setDialogType(int dialogShowsStringPattern)
8826 + char *matchPatternNameText;
8827 + char *strPatCxtGrpListText;
8829 + int regularExpression =
8830 + XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
8833 + * check, if dialog mode needs to be switched
8835 + if (MatchPatternDialog.mpdStringPatternIsDisplayed == dialogShowsStringPattern)
8840 + if (dialogShowsStringPattern)
8842 + matchPatternNameText = MATCH_PAT_NAME_LBL_TXT;
8843 + strPatCxtGrpListText = STRING_PATTERNS_LBL_TXT;
8847 + matchPatternNameText = "Context Group Name";
8848 + strPatCxtGrpListText = "Related Sub-Patterns";
8851 + XtSetSensitive(MatchPatternDialog.mpdGlobalAttributesLbl, dialogShowsStringPattern);
8852 + XtSetSensitive(MatchPatternDialog.gabSkipBtwStartEndW, dialogShowsStringPattern);
8853 + XtSetSensitive(MatchPatternDialog.gabFlashW, dialogShowsStringPattern);
8854 + XtSetSensitive(MatchPatternDialog.gabSyntaxBasedW, dialogShowsStringPattern);
8856 + XtSetSensitive(MatchPatternDialog.mpdStringPatternTypeLbl, dialogShowsStringPattern);
8857 + XtSetSensitive(MatchPatternDialog.sptStartW, dialogShowsStringPattern);
8858 + XtSetSensitive(MatchPatternDialog.sptMiddleW, dialogShowsStringPattern);
8859 + XtSetSensitive(MatchPatternDialog.sptEndW, dialogShowsStringPattern);
8861 + setSensitiveWordBoundaryBox( dialogShowsStringPattern && !regularExpression );
8863 + XtSetSensitive(MatchPatternDialog.mpdStringAttributesLbl, dialogShowsStringPattern);
8864 + XtSetSensitive(MatchPatternDialog.sabCaseSensitiveW, dialogShowsStringPattern);
8865 + XtSetSensitive(MatchPatternDialog.sabRegularExpressionW, dialogShowsStringPattern);
8867 + XtSetSensitive(MatchPatternDialog.mpdStringPatternLbl, dialogShowsStringPattern);
8868 + XtSetSensitive(MatchPatternDialog.mpdStringPatternW, dialogShowsStringPattern);
8870 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesLbl, !dialogShowsStringPattern);
8871 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesOptMenu, !dialogShowsStringPattern);
8874 + MatchPatternDialog.mpdMatchPatternNameLbl,
8875 + XmNlabelString, s1=XmStringCreateSimple(matchPatternNameText),
8880 + MatchPatternDialog.mpdStringPatternsLbl,
8881 + XmNlabelString, s1=XmStringCreateSimple(strPatCxtGrpListText),
8885 + MatchPatternDialog.mpdStringPatternIsDisplayed = dialogShowsStringPattern;
8888 +static void setSensitiveWordBoundaryBox(int enable)
8890 + XtSetSensitive(MatchPatternDialog.mpdWordBoundaryLbl, enable);
8891 + XtSetSensitive(MatchPatternDialog.wbbBothW , enable);
8892 + XtSetSensitive(MatchPatternDialog.wbbLeftW , enable);
8893 + XtSetSensitive(MatchPatternDialog.wbbRightW, enable);
8894 + XtSetSensitive(MatchPatternDialog.wbbNoneW , enable);
8897 +static void matchPatternLangModeCB(Widget w, XtPointer clientData, XtPointer callData)
8900 + StringMatchTable *oldTable, *newTable;
8901 + StringMatchTable emptyTable = {"", NULL, NULL, NULL, NULL, 0, NULL, 0, NULL};
8902 + StringMatchTable *table;
8903 + DMPTranslationResult translResult;
8907 + * Get the newly selected mode name. If it's the same, do nothing
8909 + XtVaGetValues(w, XmNuserData, &modeName, NULL);
8910 + if (!strcmp(modeName, MatchPatternDialog.mpdLangModeName))
8914 + * Look up the original version of the patterns being edited
8916 + oldTable = (StringMatchTable *)FindStringMatchTable(MatchPatternDialog.mpdLangModeName);
8917 + if (oldTable == NULL)
8918 + oldTable = &emptyTable;
8921 + * Get the current information displayed by the dialog. If it's bad,
8922 + * give the user the chance to throw it out or go back and fix it. If
8923 + * it has changed, give the user the chance to apply discard or cancel.
8925 + newTable = getDialogStringMatchTable(&translResult);
8927 + if (translResult == DMPTR_EMPTY)
8929 + newTable = &emptyTable;
8932 + if (newTable == NULL)
8935 + DF_WARN, MatchPatternDialog.mpdShell, 2,
8936 + "Incomplete Matching Patterns for Language Mode",
8937 + "Discard incomplete entry for language mode '%s'?",
8938 + "Keep", "Discard",
8939 + MatchPatternDialog.mpdLangModeName) == 1)
8942 + MatchPatternDialog.mpdLmOptMenu,
8943 + MatchPatternDialog.mpdLangModeName);
8948 + else if (stringMatchTableDiffer(oldTable, newTable))
8950 + if (newTable == &emptyTable)
8955 + DF_WARN, MatchPatternDialog.mpdShell, 3,
8956 + "Change Language Mode",
8957 + "Apply changes for language mode '%s'?",
8958 + "Apply Changes", "Discard Changes", "Cancel",
8959 + MatchPatternDialog.mpdLangModeName);
8964 + MatchPatternDialog.mpdLmOptMenu,
8965 + MatchPatternDialog.mpdLangModeName);
8967 + freeStringMatchTable( newTable );
8971 + else if (resp == 1)
8973 + updateStringMatchTable( newTable );
8976 + * Don't free the new table due to it's stored in MatchTables now
8982 + if (newTable != NULL && newTable != &emptyTable)
8983 + freeStringMatchTable(newTable);
8986 + * Free the old dialog information
8988 + freeVariableDialogData(DISCARD_LANGUAGE_MODE);
8991 + * Fill the dialog with the new language mode information
8993 + MatchPatternDialog.mpdLangModeName = XtNewString(modeName);
8996 + * Find the associated matching pattern table to edit
8998 + table = (StringMatchTable *)FindStringMatchTable(MatchPatternDialog.mpdLangModeName);
9001 + * Copy the list of patterns to one that the user can freely edit
9003 + copyStringMatchTableForDialog( table, &MatchPatternDialog.mpdTable );
9006 + * Update dialog fields
9008 + ChangeManagedListData(MatchPatternDialog.mpdMatchPatternNamesListW);
9009 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9012 +static void pmLanguageModeDialogCB(Widget w, XtPointer clientData, XtPointer callData)
9014 + EditLanguageModes();
9018 +** If a matching pattern dialog is up, ask to have the option menu for
9019 +** chosing language mode updated (via a call to CreateLanguageModeMenu)
9021 +void UpdateLanguageModeMenuMatchPattern(void)
9025 + if (MatchPatternDialog.mpdShell == NULL)
9028 + oldMenu = MatchPatternDialog.mpdLmPulldown;
9030 + * don't include "PLAIN" (4th parameter) in LM menu
9032 + MatchPatternDialog.mpdLmPulldown = CreateLanguageModeMenu(
9033 + XtParent(XtParent(oldMenu)), matchPatternLangModeCB, NULL, False);
9034 + XtVaSetValues(XmOptionButtonGadget(MatchPatternDialog.mpdLmOptMenu),
9035 + XmNsubMenuId, MatchPatternDialog.mpdLmPulldown, NULL);
9036 + SetLangModeMenu(MatchPatternDialog.mpdLmOptMenu, MatchPatternDialog.mpdLangModeName);
9038 + XtDestroyWidget(oldMenu);
9041 +static void *getMatchPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
9044 + DialogMatchPatternSequenceElement *newSeq;
9047 + * If the dialog is currently displaying the "new" entry and the
9048 + * fields are empty, that's just fine
9050 + if (oldItem == NULL && matchPatternDialogEmpty())
9054 + * Read string patterns / sub-pattern names area first
9056 + UpdateManagedList(MatchPatternDialog.mpdStringPatternsListW, True);
9059 + * If there are no problems reading the data, just return it
9061 + newSeq = readMatchPatternFields(True);
9062 + if (newSeq != NULL)
9063 + return (void *)newSeq;
9066 + * If there are problems, and the user didn't ask for the fields to be
9067 + * read, give more warning
9069 + if (!explicitRequest)
9072 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9073 + "Discard Matching Pattern Entry",
9074 + "Discard incomplete entry\nfor current matching pattern?",
9075 + "Keep", "Discard") == 2)
9077 + return oldItem == NULL
9079 + : (void *)copyDialogSequenceElement(
9080 + (DialogMatchPatternSequenceElement *)oldItem);
9085 + * read data again without "silent" mode to display warning
9087 + newSeq = readMatchPatternFields(False);
9093 +static void setMatchPatternDisplayedCB(void *item, void *cbArg)
9095 + DialogMatchPatternSequenceElement *seqElement;
9096 + DialogMatchPatternTableElement *element;
9097 + DialogMatchPatternGroupElement *group;
9100 + seqElement = (DialogMatchPatternSequenceElement *)item;
9102 + MatchPatternDialog.currentDmptSeqElement = seqElement;
9106 + MatchPatternDialog.currentDmptElement = NULL;
9107 + MatchPatternDialog.currentDmptGroup = NULL;
9109 + XmTextSetString(MatchPatternDialog.mpdMatchPatternNameW, "");
9110 + RadioButtonChangeState(MatchPatternDialog.mptbIndividualW, True, True);
9111 + RadioButtonChangeState(MatchPatternDialog.gabSkipBtwStartEndW, False, False);
9112 + RadioButtonChangeState(MatchPatternDialog.gabFlashW, True, False);
9113 + RadioButtonChangeState(MatchPatternDialog.gabSyntaxBasedW, True, False);
9115 + freeDialogStringPatterns(
9116 + &MatchPatternDialog.currentStringPatterns);
9118 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9120 + setDialogType( STRING_PATTERN_DIALOG );
9124 + isGroup = (seqElement->dmpseType == MPT_GROUP);
9126 + XmTextSetString(MatchPatternDialog.mpdMatchPatternNameW, seqElement->dmpseName);
9128 + if (seqElement->dmpseType == MPT_INDIVIDUAL)
9129 + RadioButtonChangeState(MatchPatternDialog.mptbIndividualW, True, True);
9130 + else if (seqElement->dmpseType == MPT_SUB)
9131 + RadioButtonChangeState(MatchPatternDialog.mptbSubPatternW, True, True);
9133 + RadioButtonChangeState(MatchPatternDialog.mptbContextGroupW, True, True);
9135 + freeDialogStringPatterns(
9136 + &MatchPatternDialog.currentStringPatterns);
9140 + group = (DialogMatchPatternGroupElement *)seqElement->dmpsePtr;
9141 + MatchPatternDialog.currentDmptElement = NULL;
9142 + MatchPatternDialog.currentDmptGroup = group;
9144 + copyDialogPatternNamesFromGroup(
9146 + &MatchPatternDialog.currentStringPatterns);
9150 + element = (DialogMatchPatternTableElement *)seqElement->dmpsePtr;
9151 + MatchPatternDialog.currentDmptElement = element;
9152 + MatchPatternDialog.currentDmptGroup = NULL;
9154 + RadioButtonChangeState(
9155 + MatchPatternDialog.gabSkipBtwStartEndW,
9156 + element->dmpteSkipBtwnStartEnd,
9158 + RadioButtonChangeState(
9159 + MatchPatternDialog.gabFlashW,
9160 + element->dmpteFlash,
9162 + RadioButtonChangeState(
9163 + MatchPatternDialog.gabSyntaxBasedW,
9164 + !element->dmpteIgnoreHighLightInfo,
9167 + copyDialogStringPatternsFromTable(
9169 + &MatchPatternDialog.currentStringPatterns);
9172 + setDialogType( !isGroup );
9174 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9178 +static void freeMatchPatternItemCB(void *item)
9180 + freeDialogSequenceElement((DialogMatchPatternSequenceElement *)item);
9184 +** Use "delete confirm" to delete matching pattern name from
9185 +** any group of this matching pattern set, in case of sub-pattern.
9186 +** Always confirm the delete.
9188 +static int deleteMatchPatternItemCB(int itemIndex, void *cbArg)
9190 + DialogMatchPatternSequenceElement *seqElement;
9192 + seqElement = MatchPatternDialog.mpdTable.dmpiSequence[itemIndex];
9194 + if (seqElement->dmpseType == MPT_SUB)
9196 + removeMatchPatternFromAllGroups( seqElement->dmpseName );
9202 +static void *getStringPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
9205 + DialogStringPatternElement *newPat;
9206 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
9209 + * If the string pattern frame is currently displaying the "new" entry and the
9210 + * fields are empty, that's just fine
9212 + if (oldItem == NULL && stringPatternFieldsEmpty(isRelatedToGroup))
9216 + * If there are no problems reading the data, just return it
9218 + newPat = readStringPatternFrameFields(True);
9219 + if (newPat != NULL)
9220 + return (void *)newPat;
9223 + * If there are problems, and the user didn't ask for the fields to be
9224 + * read, give more warning
9227 + if (!explicitRequest)
9230 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9231 + "Discard String Pattern Entry",
9232 + "Discard incomplete entry\nfor current string pattern?",
9233 + "Keep", "Discard") == 2)
9235 + return oldItem == NULL
9237 + : (void *)copyDialogStringPatternElement(
9238 + (DialogStringPatternElement *)oldItem);
9243 + * read data again without "silent" mode to display warning
9245 + newPat = readStringPatternFrameFields(False);
9251 +static void setStringPatternDisplayedCB(void *item, void *cbArg)
9253 + DialogStringPatternElement *element = (DialogStringPatternElement *)item;
9254 + PatternElementKind peKind;
9255 + PatternWordBoundary wordBoundary;
9256 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
9260 + if (isRelatedToGroup)
9262 + updateSubPatternNameMenu(NULL, False);
9266 + XmTextSetString(MatchPatternDialog.mpdStringPatternW, "");
9268 + setSensitiveWordBoundaryBox( True );
9270 + RadioButtonChangeState(MatchPatternDialog.wbbBothW, True, True);
9273 + * type of "new" string pattern:
9274 + * preset "start", if no string pattern exists at all;
9275 + * else select "end"
9277 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0)
9278 + RadioButtonChangeState(MatchPatternDialog.sptStartW, True, True);
9280 + RadioButtonChangeState(MatchPatternDialog.sptEndW, True, True);
9282 + RadioButtonChangeState(MatchPatternDialog.sabCaseSensitiveW, True, False);
9283 + RadioButtonChangeState(MatchPatternDialog.sabRegularExpressionW, False, False);
9288 + if (isRelatedToGroup)
9290 + updateSubPatternNameMenu(element->dspeText, False);
9294 + XmTextSetString(MatchPatternDialog.mpdStringPatternW, element->dspeText);
9296 + peKind = element->dspeKind;
9297 + wordBoundary = element->dspeWordBoundary;
9299 + if (peKind == PEK_START)
9300 + RadioButtonChangeState(MatchPatternDialog.sptStartW, True, True);
9301 + else if (peKind == PEK_MIDDLE)
9302 + RadioButtonChangeState(MatchPatternDialog.sptMiddleW, True, True);
9304 + RadioButtonChangeState(MatchPatternDialog.sptEndW, True, True);
9306 + if (wordBoundary == PWB_BOTH)
9307 + RadioButtonChangeState(MatchPatternDialog.wbbBothW, True, True);
9308 + else if (wordBoundary == PWB_LEFT)
9309 + RadioButtonChangeState(MatchPatternDialog.wbbLeftW, True, True);
9310 + else if (wordBoundary == PWB_RIGHT)
9311 + RadioButtonChangeState(MatchPatternDialog.wbbRightW, True, True);
9313 + RadioButtonChangeState(MatchPatternDialog.wbbNoneW, True, True);
9315 + RadioButtonChangeState(
9316 + MatchPatternDialog.sabCaseSensitiveW,
9317 + !element->dspeCaseInsensitive,
9320 + RadioButtonChangeState(
9321 + MatchPatternDialog.sabRegularExpressionW,
9322 + element->dspeRegularExpression,
9325 + setSensitiveWordBoundaryBox( !element->dspeRegularExpression );
9330 +static void freeStringPatternItemCB(void *item)
9332 + DialogStringPatternElement *patElement;
9334 + patElement = (DialogStringPatternElement *)item;
9336 + freeDialogStringPatternElement(patElement);
9339 +static void destroyCB(Widget w, XtPointer clientData, XtPointer callData)
9341 + freeVariableDialogData(DISCARD_LANGUAGE_MODE);
9343 + MatchPatternDialog.mpdShell = NULL;
9346 +static void okCB(Widget w, XtPointer clientData, XtPointer callData)
9349 + * change the matching pattern
9351 + if (!getAndUpdateStringMatchTable())
9355 + * pop down and destroy the dialog
9357 + XtDestroyWidget(MatchPatternDialog.mpdShell);
9360 +static void applyCB(Widget w, XtPointer clientData, XtPointer callData)
9363 + * change the matching pattern
9365 + getAndUpdateStringMatchTable();
9368 +static void checkCB(Widget w, XtPointer clientData, XtPointer callData)
9370 + StringMatchTable *newTable;
9371 + DMPTranslationResult translResult;
9374 + * Get the current information displayed by the dialog.
9375 + * If a new table is available, then the test is passed successfully.
9377 + newTable = getDialogStringMatchTable(&translResult);
9379 + if (newTable != NULL)
9382 + DF_INF, MatchPatternDialog.mpdShell, 1,
9383 + "Matching Patterns Checked",
9384 + "Matching Patterns checked without error",
9387 + freeStringMatchTable(newTable);
9391 +static void restoreCB(Widget w, XtPointer clientData, XtPointer callData)
9393 + StringMatchTable *defaultTable;
9395 + defaultTable = readDefaultStringMatchTable(MatchPatternDialog.mpdLangModeName);
9397 + if (defaultTable == NULL)
9400 + DF_WARN, MatchPatternDialog.mpdShell, 1,
9401 + "No Default Matching Pattern",
9402 + "There is no default matching pattern set\nfor language mode %s",
9404 + MatchPatternDialog.mpdLangModeName);
9410 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9411 + "Discard Changes",
9412 + "Are you sure you want to discard\n"
9413 + "all changes to matching patterns\n"
9414 + "for language mode %s?",
9415 + "Discard", "Cancel",
9416 + MatchPatternDialog.mpdLangModeName) == 2)
9418 + freeStringMatchTable(defaultTable);
9424 + * if a stored version of the matching pattern set exists, replace it.
9425 + * if it doesn't, add a new one.
9427 + updateStringMatchTable( defaultTable );
9430 + * free the old dialog information
9432 + freeVariableDialogData(KEEP_LANGUAGE_MODE);
9435 + * update the dialog
9437 + copyStringMatchTableForDialog( defaultTable, &MatchPatternDialog.mpdTable );
9439 + ChangeManagedListData(MatchPatternDialog.mpdMatchPatternNamesListW);
9440 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9443 +static void deleteCB(Widget w, XtPointer clientData, XtPointer callData)
9446 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9447 + "Delete Matching Patterns",
9448 + "Are you sure you want to delete\n"
9449 + "all matching patterns for\n"
9450 + "language mode %s?",
9451 + "Yes, Delete", "Cancel",
9452 + MatchPatternDialog.mpdLangModeName) == 2)
9458 + * if a stored version of the matching pattern exists, delete it from the list
9460 + DeleteStringMatchTable(MatchPatternDialog.mpdLangModeName);
9463 + * free the old dialog information
9465 + freeVariableDialogData(KEEP_LANGUAGE_MODE);
9468 + * clear out the dialog
9470 + ChangeManagedListData(MatchPatternDialog.mpdMatchPatternNamesListW);
9471 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9474 +static void closeCB(Widget w, XtPointer clientData, XtPointer callData)
9477 + * pop down and destroy the dialog
9479 + XtDestroyWidget(MatchPatternDialog.mpdShell);
9482 +static void helpCB(Widget w, XtPointer clientData, XtPointer callData)
9485 + Help(HELP_MATCHING_PATTERNS);
9489 +static void strPatRegExpressionCB(Widget w, XtPointer clientData, XtPointer callData)
9491 + int regularExpression =
9492 + XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
9494 + setSensitiveWordBoundaryBox( !regularExpression );
9496 + if (regularExpression)
9497 + RadioButtonChangeState(MatchPatternDialog.sabCaseSensitiveW, True, False);
9500 +static void matchPatTypeCB(Widget w, XtPointer clientData, XtPointer callData)
9502 + if (MatchPatternDialog.currentDmptSeqElement != NULL)
9504 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW))
9506 + if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_SUB)
9508 + changeExistingSubPattern("Change to Context Group");
9511 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW) &&
9512 + MatchPatternDialog.currentDmptSeqElement->dmpseType != MPT_GROUP)
9514 + changeStringPatternToGroup();
9517 + else if (XmToggleButtonGetState(MatchPatternDialog.mptbIndividualW))
9519 + if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_SUB)
9521 + changeExistingSubPattern("Change to Individual Matching Pattern");
9523 + else if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_GROUP)
9525 + changeGroupToStringPattern("Change to Individual Matching Pattern");
9528 + else if (XmToggleButtonGetState(MatchPatternDialog.mptbSubPatternW))
9530 + if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_GROUP)
9532 + changeGroupToStringPattern("Change to Sub-Matching Pattern");
9538 + * if context group button is (still) selected, then update labels etc.
9540 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW))
9542 + setDialogType(CONTEXT_GROUP_DIALOG);
9546 + setDialogType(STRING_PATTERN_DIALOG);
9550 + * if a "new" entry is selected in matching patterns names list, then provide a
9551 + * list of all sub-pattern names
9553 + if (MatchPatternDialog.currentDmptSeqElement == NULL)
9555 + updateSubPatternNameMenu(NULL, True);
9559 +static void changeExistingSubPattern(
9562 + DialogMatchPatternGroupElement *group;
9566 + getDialogGroupUsingMatchPattern(
9567 + MatchPatternDialog.currentDmptElement->dmpteName );
9569 + while ( group != NULL )
9573 + DF_WARN, MatchPatternDialog.mpdShell, 3,
9575 + "Sub-pattern '%s' is used at least\n"
9576 + "by context group '%s'.\n\n"
9577 + "Remove this sub-pattern from this resp. all context group(s) ?",
9578 + "No, Keep", "Yes, Remove", "Yes, Remove All",
9579 + MatchPatternDialog.currentDmptElement->dmpteName,
9580 + group->dmpgeName);
9584 + RadioButtonChangeState(MatchPatternDialog.mptbSubPatternW, True, True);
9588 + else if (resp == 2)
9590 + removeMatchPatternFromGroup(
9591 + MatchPatternDialog.currentDmptElement->dmpteName,
9595 + * look for evtl. next context group holding this matching pattern
9598 + getDialogGroupUsingMatchPattern(
9599 + MatchPatternDialog.currentDmptElement->dmpteName );
9604 + * remove this matching pattern form all context groups
9606 + removeMatchPatternFromAllGroups(
9607 + MatchPatternDialog.currentDmptElement->dmpteName);
9614 +static void changeStringPatternToGroup(void)
9619 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns != 0)
9623 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9624 + "Change to Context Group",
9625 + "All string patterns of '%s'\n"
9626 + "need to be discarded.\n\n"
9627 + "Discard related string patterns ?",
9628 + "No, Keep", "Yes, Discard",
9629 + MatchPatternDialog.currentDmptElement->dmpteName);
9633 + isSubPattern = (MatchPatternDialog.currentDmptElement->dmpteType == MPT_SUB);
9636 + RadioButtonChangeState(MatchPatternDialog.mptbSubPatternW, True, True);
9638 + RadioButtonChangeState(MatchPatternDialog.mptbIndividualW, True, True);
9644 + * remove string patterns & update dialog fields
9646 + freeDialogStringPatterns(&MatchPatternDialog.currentStringPatterns);
9648 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9652 + * invalidate this sub-/individual pattern
9654 + MatchPatternDialog.currentDmptSeqElement->dmpseValid = False;
9657 + * update sub-pattern menu due to change to context group
9659 + updateSubPatternNameMenu(NULL, True);
9662 +static void changeGroupToStringPattern(
9667 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0)
9672 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9674 + "Content of context group '%s'\n"
9675 + "needs to be discarded.\n\n"
9676 + "Discard content ?",
9677 + "No, Keep", "Yes, Discard",
9678 + MatchPatternDialog.currentDmptGroup->dmpgeName);
9682 + RadioButtonChangeState(MatchPatternDialog.mptbContextGroupW, True, True);
9687 + * remove string patterns & update dialog fields
9689 + freeDialogStringPatterns(&MatchPatternDialog.currentStringPatterns);
9691 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9696 +** Create a pulldown menu pane with the names of the sub-patterns of
9697 +** the current matching pattern set.
9699 +static Widget createSubPatternNameMenu(
9701 + char *currentSubPatName,
9702 + int allSubPatterns)
9704 + NameList nameList;
9708 + setupSubPatternNameList(currentSubPatName, allSubPatterns, &nameList);
9710 + menu = CreatePulldownMenu(parent, "subPatternNames", NULL, 0);
9712 + for (i=0; i<nameList.nlNumber; i++)
9714 + createSubPatNameMenuEntry(menu, nameList.nlId[i]);
9720 +static void setupSubPatternNameList(
9721 + char *currentSubPatName,
9722 + int allSubPatterns,
9723 + NameList *nameList)
9727 + DialogMatchPatternSequenceElement *seq;
9728 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
9730 + if (isRelatedToGroup || allSubPatterns)
9733 + * add "none selected" (default) item
9735 + nameList->nlId[n ++] = SPNM_NONE_SELECTED;
9738 + * add one item for each (not assigned) sub-pattern name
9740 + for (i=0; i<MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i++)
9742 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
9744 + if (seq->dmpseType == MPT_SUB &&
9745 + seq->dmpseValid &&
9746 + (allSubPatterns ||
9747 + (!isSubPatternNameInCurStrPat(seq->dmpseName) ||
9748 + (currentSubPatName != NULL &&
9749 + (strcmp(seq->dmpseName, currentSubPatName) == 0))) ))
9751 + nameList->nlId[n ++] = seq->dmpseName;
9757 + nameList->nlId[n ++] = "none available ";
9760 + nameList->nlNumber = n;
9764 +** Create a menu entry with the names of one sub-pattern.
9765 +** XmNuserData of this item contains the sub-pattern name.
9767 +static void createSubPatNameMenuEntry(
9774 + btn = XtVaCreateManagedWidget("subPattern", xmPushButtonGadgetClass,
9776 + XmNlabelString, s1=XmStringCreateSimple(subPatName),
9777 + XmNmarginHeight, 0,
9778 + XmNuserData, (void *)subPatName, NULL);
9783 +** Set the sub-patterns menu to show a particular sub-pattern name
9785 +static void setSubPatternNameMenu(
9786 + const char *subPatName)
9791 + Widget pulldown, selectedItem;
9794 + XtVaGetValues(MatchPatternDialog.mpdSubPatNamesOptMenu, XmNsubMenuId, &pulldown, NULL);
9795 + XtVaGetValues(pulldown, XmNchildren, &items, XmNnumChildren, &nItems, NULL);
9800 + selectedItem = items[0];
9803 + * if no subPatName is given, then select first item of option menu
9805 + if (subPatName != NULL)
9807 + for (i=0; i<(int)nItems; i++)
9809 + if (items[i] != NULL && !items[i]->core.being_destroyed)
9811 + XtVaGetValues(items[i], XmNuserData, &itemName, NULL);
9812 + if (!strcmp(itemName, subPatName))
9814 + selectedItem = items[i];
9821 + XtVaSetValues(MatchPatternDialog.mpdSubPatNamesOptMenu, XmNmenuHistory, selectedItem, NULL);
9825 +** Update sub-pattern names menu, e.g. when a new sub-pattern is defined
9827 +static void updateSubPatternNameMenu(
9828 + char *currentSubPatName,
9829 + int allSubPatterns)
9831 + NameList nameList;
9837 + setupSubPatternNameList(currentSubPatName, allSubPatterns, &nameList);
9840 + * Go thru all of the items in the sub-pattern names menu
9841 + * and rename them to match the current sub-patterns.
9842 + * Delete any extras.
9845 + MatchPatternDialog.mpdSubPatNamesPulldown,
9846 + XmNchildren, &items,
9847 + XmNnumChildren, &nItems,
9850 + for (n=0; n<(int)nItems; n++)
9852 + if (n >= nameList.nlNumber)
9855 + * unmanaging before destroying stops parent from displaying
9857 + XtUnmanageChild(items[n]);
9858 + XtDestroyWidget(items[n]);
9862 + if (items[n] == NULL || items[n]->core.being_destroyed)
9865 + * create a new entry (widget) if this one is not existing or
9866 + * if it is marked as to be destroyed
9868 + createSubPatNameMenuEntry(
9869 + MatchPatternDialog.mpdSubPatNamesPulldown, nameList.nlId[n]);
9875 + XmNlabelString, st1=XmStringCreateSimple(nameList.nlId[n]),
9876 + XmNuserData, (void *)nameList.nlId[n],
9879 + XmStringFree(st1);
9885 + * add new items for remaining sub-patterns names
9887 + for (n=(int)nItems; n<nameList.nlNumber; n++)
9889 + createSubPatNameMenuEntry(
9890 + MatchPatternDialog.mpdSubPatNamesPulldown, nameList.nlId[n]);
9894 + * select entry shown in sub-pattern name option menu
9896 + setSubPatternNameMenu(currentSubPatName);
9899 +static char *getSelectedSubPatternName(void)
9901 + Widget selectedItem;
9904 + XtVaGetValues(MatchPatternDialog.mpdSubPatNamesOptMenu, XmNmenuHistory, &selectedItem, NULL);
9905 + XtVaGetValues(selectedItem, XmNuserData, &itemName, NULL);
9910 +static int isSubPatternNameInCurStrPat(
9914 + DialogStringPatterns *curPatNames = &MatchPatternDialog.currentStringPatterns;
9916 + for (i=0; i<curPatNames->dspNumberOfPatterns; i++)
9918 + if (strcmp(curPatNames->dspElements[i]->dspeText, subPatName) == 0)
9926 +** Read the matching pattern fields of the matching pattern dialog and produce an
9927 +** allocated DialogMatchPatternSequenceElement structure reflecting the contents.
9928 +** Pop up dialogs telling the user what's wrong (Passing "silent" as True,
9929 +** suppresses these dialogs).
9930 +** Returns NULL on error.
9932 +static DialogMatchPatternSequenceElement *readMatchPatternFields(int silent)
9938 + char *contentTitle;
9939 + char *contentWarningText;
9940 + DialogMatchPatternSequenceElement *newSeq;
9941 + DialogMatchPatternTableElement *newElement;
9942 + DialogMatchPatternGroupElement *newGroup;
9944 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW))
9946 + nameLabel = "context group name";
9947 + nameTitle = "Context Group Name";
9948 + contentTitle = "Context Group Content";
9949 + contentWarningText = "Please assign min. 1\nsub-pattern";
9954 + nameLabel = "matching pattern name";
9955 + nameTitle = "Matching Pattern Name";
9956 + contentTitle = "Matching Pattern Content";
9957 + contentWarningText = "Please specify min. 1\nstring pattern";
9962 + ReadSymbolicFieldTextWidget(
9963 + MatchPatternDialog.mpdMatchPatternNameW,
9971 + else if (*name == '\0')
9976 + DF_WARN, MatchPatternDialog.mpdShell, 1,
9978 + "Please specify a valid name",
9980 + XmProcessTraversal(MatchPatternDialog.mpdMatchPatternNameW, XmTRAVERSE_CURRENT);
9986 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0)
9991 + DF_WARN, MatchPatternDialog.mpdShell, 1,
9993 + contentWarningText,
10002 + !isStartPatternElementAvailable(&MatchPatternDialog.currentStringPatterns))
10007 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10009 + "Please specify min. 1 string pattern\nof type 'start'",
10017 + if (MatchPatternDialog.currentDmptElement != NULL &&
10018 + MatchPatternDialog.currentDmptElement->dmpteType == MPT_SUB &&
10019 + strcmp(MatchPatternDialog.currentDmptElement->dmpteName, name) != 0)
10021 + renameMatchPatternInAllGroups(
10022 + MatchPatternDialog.currentDmptElement->dmpteName,
10027 + (DialogMatchPatternSequenceElement *)XtMalloc(sizeof(DialogMatchPatternSequenceElement));
10029 + newSeq->dmpseName = name;
10030 + newSeq->dmpseValid = True;
10034 + newSeq->dmpseType = MPT_GROUP;
10037 + (DialogMatchPatternGroupElement *)XtMalloc(sizeof(DialogMatchPatternGroupElement));
10039 + newGroup->dmpgeName = XtNewString(name);
10041 + copyDialogPatternNamesToGroup(
10042 + &MatchPatternDialog.currentStringPatterns,
10045 + newSeq->dmpsePtr = (void *)newGroup;
10049 + if (XmToggleButtonGetState(MatchPatternDialog.mptbIndividualW))
10050 + newSeq->dmpseType = MPT_INDIVIDUAL;
10052 + newSeq->dmpseType = MPT_SUB;
10055 + (DialogMatchPatternTableElement *)XtMalloc(sizeof(DialogMatchPatternTableElement));
10057 + newElement->dmpteName = XtNewString(name);
10058 + newElement->dmpteType = newSeq->dmpseType;
10060 + newElement->dmpteSkipBtwnStartEnd =
10061 + XmToggleButtonGetState(MatchPatternDialog.gabSkipBtwStartEndW);
10063 + newElement->dmpteFlash =
10064 + XmToggleButtonGetState(MatchPatternDialog.gabFlashW);
10066 + newElement->dmpteIgnoreHighLightInfo =
10067 + !XmToggleButtonGetState(MatchPatternDialog.gabSyntaxBasedW);
10069 + copyDialogStringPatterns(
10070 + &MatchPatternDialog.currentStringPatterns,
10071 + &newElement->dmptePatterns);
10073 + newSeq->dmpsePtr = (void *)newElement;
10080 +** Check, if min. 1 string pattern of type 'start' is
10081 +** available within dialog.
10082 +** Returns True, if min. 1 start string pattern is
10083 +** populated in dialog.
10085 +static int isStartPatternElementAvailable(
10086 + DialogStringPatterns *dialogPatterns)
10090 + for (i=0; i < dialogPatterns->dspNumberOfPatterns; i++)
10092 + if (dialogPatterns->dspElements[i]->dspeKind == PEK_START)
10100 +** Read the string pattern fields of the string pattern frame and produce an
10101 +** allocated DialogStringPatternElement structure reflecting the contents.
10102 +** Pop up dialogs telling the user what's wrong (Passing "silent" as True,
10103 +** suppresses these dialogs).
10104 +** Returns NULL on error.
10106 +static DialogStringPatternElement *readStringPatternFrameFields(int silent)
10108 + char *stringPatText;
10109 + DialogStringPatternElement *newPatElement;
10110 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
10112 + if (isRelatedToGroup)
10114 + stringPatText = getSelectedSubPatternName();
10115 + if (strcmp(stringPatText, SPNM_NONE_SELECTED) == 0)
10120 + stringPatText = XtNewString(stringPatText);
10125 + XmTextGetString(MatchPatternDialog.mpdStringPatternW);
10127 + if (stringPatText == NULL)
10131 + else if (*stringPatText == '\0')
10136 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10137 + "String Pattern",
10138 + "Please specify string\npattern content",
10140 + XmProcessTraversal(MatchPatternDialog.mpdStringPatternW, XmTRAVERSE_CURRENT);
10142 + XtFree(stringPatText);
10147 + newPatElement = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
10149 + newPatElement->dspeText = stringPatText;
10151 + if (isRelatedToGroup)
10153 + newPatElement->dspeKind = PEK_START;
10154 + newPatElement->dspeWordBoundary = PWB_NONE;
10155 + newPatElement->dspeCaseInsensitive = False;
10156 + newPatElement->dspeRegularExpression = False;
10160 + newPatElement->dspeRegularExpression =
10161 + XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
10163 + if (XmToggleButtonGetState(MatchPatternDialog.sptStartW))
10164 + newPatElement->dspeKind = PEK_START;
10165 + else if (XmToggleButtonGetState(MatchPatternDialog.sptMiddleW))
10166 + newPatElement->dspeKind = PEK_MIDDLE;
10168 + newPatElement->dspeKind = PEK_END;
10170 + if (newPatElement->dspeRegularExpression)
10171 + newPatElement->dspeWordBoundary = PWB_NONE;
10172 + else if (XmToggleButtonGetState(MatchPatternDialog.wbbBothW))
10173 + newPatElement->dspeWordBoundary = PWB_BOTH;
10174 + else if (XmToggleButtonGetState(MatchPatternDialog.wbbLeftW))
10175 + newPatElement->dspeWordBoundary = PWB_LEFT;
10176 + else if (XmToggleButtonGetState(MatchPatternDialog.wbbRightW))
10177 + newPatElement->dspeWordBoundary = PWB_RIGHT;
10179 + newPatElement->dspeWordBoundary = PWB_NONE;
10181 + newPatElement->dspeCaseInsensitive =
10182 + !XmToggleButtonGetState(MatchPatternDialog.sabCaseSensitiveW);
10185 + return newPatElement;
10189 +** Returns true if the pattern fields of the matching pattern dialog are set to
10190 +** the default ("New" pattern) state.
10192 +static int matchPatternDialogEmpty(void)
10195 + TextWidgetIsBlank(MatchPatternDialog.mpdMatchPatternNameW) &&
10196 + XmToggleButtonGetState(MatchPatternDialog.mptbIndividualW) &&
10197 + XmToggleButtonGetState(MatchPatternDialog.gabFlashW) &&
10198 + XmToggleButtonGetState(MatchPatternDialog.gabSyntaxBasedW) &&
10199 + stringPatternFrameEmpty();
10203 +** Returns true if the string pattern frame of the matching pattern dialog is set to
10204 +** the default state.
10206 +static int stringPatternFrameEmpty(void)
10209 + stringPatternFieldsEmpty(False) &&
10210 + MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0;
10214 +** Returns true if the string pattern fields of the string pattern frame are set to
10215 +** the default state.
10217 +static int stringPatternFieldsEmpty(
10218 + int strPatIsRelatedToGroup)
10220 + if (strPatIsRelatedToGroup)
10223 + strcmp( getSelectedSubPatternName(), SPNM_NONE_SELECTED ) == 0);
10228 + TextWidgetIsBlank(MatchPatternDialog.mpdStringPatternW) &&
10229 + XmToggleButtonGetState(MatchPatternDialog.wbbBothW) &&
10230 + XmToggleButtonGetState(MatchPatternDialog.sabCaseSensitiveW) &&
10231 + !XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
10236 +** Get the current content of the matching pattern dialog.
10237 +** If the matching pattern is o.k., then update & apply it
10238 +** to any window which is currently using the matching pattern.
10239 +** If it's bad, then only report it.
10241 +static int getAndUpdateStringMatchTable(void)
10243 + StringMatchTable *newTable;
10244 + DMPTranslationResult translResult;
10247 + * Get the current information displayed by the dialog. If it's bad,
10248 + * report it to the user & return.
10250 + newTable = getDialogStringMatchTable(&translResult);
10252 + if (newTable == NULL && translResult != DMPTR_EMPTY)
10255 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10256 + "Incomplete Matching Patterns for Language Mode",
10257 + "Incomplete matching patterns for language mode '%s'.\n"
10258 + "Please complete them first",
10260 + MatchPatternDialog.mpdLangModeName);
10266 + * change the matching pattern
10268 + updateStringMatchTable( newTable );
10274 +** Update the matching pattern set being edited in the matching pattern dialog
10275 +** with the information that the dialog is currently displaying, and
10276 +** apply changes to any window which is currently using the matching pattern.
10278 +static void updateStringMatchTable(
10279 + StringMatchTable *newTable)
10281 + WindowInfo *window;
10285 + * Find the matching pattern being modified
10287 + for (i=0; i<NbrMatchTables; i++)
10289 + if (!strcmp(MatchPatternDialog.mpdLangModeName, MatchTables[i]->smtLanguageMode))
10292 + * replace existing matching pattern
10294 + freeStringMatchTable(MatchTables[i]);
10295 + MatchTables[i] = newTable;
10300 + if (i == NbrMatchTables)
10303 + * new match table for language mode -> add it to end
10305 + MatchTables[NbrMatchTables++] = newTable;
10309 + * Find windows that are currently using this matching pattern set and
10310 + * update this windows
10312 + for (window=WindowList; window!=NULL; window=window->next)
10314 + if ((window->languageMode == PLAIN_LANGUAGE_MODE &&
10315 + !strcmp(PLAIN_LM_STRING, newTable->smtLanguageMode)) ||
10316 + (window->languageMode != PLAIN_LANGUAGE_MODE &&
10317 + !strcmp(LanguageModeName(window->languageMode), newTable->smtLanguageMode)))
10319 + window->stringMatchTable = newTable;
10324 + * Note that preferences have been changed
10326 + MarkPrefsChanged();
10329 +static StringMatchTable *getDialogStringMatchTable(
10330 + DMPTranslationResult *result)
10332 + int matchPatListIdx =
10333 + ManagedListSelectedIndex(MatchPatternDialog.mpdMatchPatternNamesListW);
10334 + int stringPatListIdx =
10335 + ManagedListSelectedIndex(MatchPatternDialog.mpdStringPatternsListW);
10338 + * Get the current content of the matching pattern dialog fields
10340 + if (!UpdateManagedList(MatchPatternDialog.mpdStringPatternsListW, True))
10342 + *result = DMPTR_INCOMPLETE;
10347 + if (!UpdateManagedList(MatchPatternDialog.mpdMatchPatternNamesListW, True))
10349 + *result = DMPTR_INCOMPLETE;
10354 + SelectManagedListItem(MatchPatternDialog.mpdMatchPatternNamesListW, matchPatListIdx);
10355 + SelectManagedListItem(MatchPatternDialog.mpdStringPatternsListW, stringPatListIdx);
10358 + * Translate dialog match table to string match table
10360 + return translateDialogStringMatchTable(&MatchPatternDialog.mpdTable, result);
10363 +static StringMatchTable *translateDialogStringMatchTable(
10364 + DialogMatchPatternInfo *dialogTable,
10365 + DMPTranslationResult *result)
10367 + ReadMatchPatternInfo readPatInfo;
10368 + DialogMatchPatternSequenceElement *seq;
10369 + MatchPatternTableElement *newPatElement;
10370 + MatchPatternGroupElement *newGroupElement;
10372 + ErrorInfo errInfo;
10375 + initErrorInfo(&errInfo);
10377 + readPatInfo.rmpiNbrOfElements = 0;
10378 + readPatInfo.rmpiNbrOfGroups = 0;
10379 + readPatInfo.rmpiNbrOfSeqElements = 0;
10380 + readPatInfo.rmpiAllPatRE = NULL;
10381 + readPatInfo.rmpiFlashPatRE = NULL;
10384 + * if no dialog patterns are defined, return "empty" table
10386 + if (dialogTable->dmpiNbrOfSeqElements == 0)
10388 + *result = DMPTR_EMPTY;
10390 + return createStringMatchTable(
10392 + XtNewString(MatchPatternDialog.mpdLangModeName));
10396 + * translate dialog matching pattern elements
10398 + for (i=0; i < dialogTable->dmpiNbrOfSeqElements; i++)
10400 + seq = dialogTable->dmpiSequence[i];
10402 + if (seq->dmpseType == MPT_GROUP)
10404 + newGroupElement =
10405 + translateDialogMatchPatternGroupElement(
10407 + (DialogMatchPatternGroupElement *)seq->dmpsePtr);
10409 + if (newGroupElement == NULL)
10411 + freeReadMatchPatternInfo(&readPatInfo);
10413 + *result = DMPTR_INCOMPLETE;
10418 + readPatInfo.rmpiGroup[readPatInfo.rmpiNbrOfGroups ++] =
10421 + recordPatternSequence(
10425 + readPatInfo.rmpiNbrOfGroups-1 );
10430 + translateDialogMatchPatternTableElement(
10431 + (DialogMatchPatternTableElement *)seq->dmpsePtr);
10433 + newPatElement->mpteIndex = readPatInfo.rmpiNbrOfElements;
10435 + readPatInfo.rmpiElement[readPatInfo.rmpiNbrOfElements ++] =
10438 + if (newPatElement->mpteType == MPT_INDIVIDUAL)
10440 + if (!assignIndividualGroup(&readPatInfo, &errMsg, newPatElement))
10443 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10444 + "Assign reg. exp.",
10445 + "%s\n(Pattern: '%s')",
10448 + newPatElement->mpteName);
10450 + freeReadMatchPatternInfo(&readPatInfo);
10452 + *result = DMPTR_INCOMPLETE;
10458 + treatDuplicatedMTEntries(readPatInfo.rmpiElement, readPatInfo.rmpiNbrOfElements);
10460 + recordPatternSequence(
10464 + newPatElement->mpteIndex );
10469 + * compile reg. expressions of "read" patterns
10471 + if (createRegExpOfPatterns( &readPatInfo, &errInfo ))
10473 + errInfo.eiLanguageMode = XtNewString(MatchPatternDialog.mpdLangModeName);
10474 + dialogMatchingPatternSetError(
10475 + "Assign all patterns reg. exp.",
10478 + freeReadMatchPatternInfo(&readPatInfo);
10480 + *result = DMPTR_INCOMPLETE;
10485 + *result = DMPTR_OK;
10487 + return createStringMatchTable(
10489 + XtNewString(MatchPatternDialog.mpdLangModeName));
10492 +static MatchPatternTableElement *translateDialogMatchPatternTableElement(
10493 + DialogMatchPatternTableElement *dialogElement)
10495 + MatchPatternTableElement *newElement;
10498 + (MatchPatternTableElement *)XtMalloc(sizeof(MatchPatternTableElement));
10500 + newElement->mpteName = XtNewString(dialogElement->dmpteName);
10501 + newElement->mpteIndex = NO_ELEMENT_IDX;
10502 + newElement->mpteType = dialogElement->dmpteType;
10503 + newElement->mpteGroup = NO_GROUP_IDX;
10505 + translateDialogPatterns(&dialogElement->dmptePatterns, newElement);
10507 + newElement->mpteSkipBtwnStartEnd = dialogElement->dmpteSkipBtwnStartEnd;
10508 + newElement->mpteFlash = dialogElement->dmpteFlash;
10509 + newElement->mpteIgnoreHighLightInfo = dialogElement->dmpteIgnoreHighLightInfo;
10510 + newElement->mpteStartEndRE = NULL;
10512 + initGlobalBackRefList( newElement->mpteGlobalBackRef );
10514 + return newElement;
10517 +static void translateDialogPatterns(
10518 + DialogStringPatterns *dialogPatterns,
10519 + MatchPatternTableElement *newElement)
10525 + * allocate memory for patterns
10527 + newElement->mpteAll.pesNumberOfPattern = dialogPatterns->dspNumberOfPatterns;
10530 + sizeof(PatternElement *) * dialogPatterns->dspNumberOfPatterns;
10532 + newElement->mpteAll.pesPattern = (PatternElement **)XtMalloc(sizeOfPat);
10535 + * assign dialog patterns to patterns of MatchPatternTableElement
10537 + for (i=0; i < dialogPatterns->dspNumberOfPatterns; i++)
10539 + newElement->mpteAll.pesPattern[i] =
10540 + createPatternElement(
10541 + XtNewString(dialogPatterns->dspElements[i]->dspeText),
10542 + dialogPatterns->dspElements[i]->dspeKind,
10543 + dialogPatterns->dspElements[i]->dspeWordBoundary,
10544 + dialogPatterns->dspElements[i]->dspeCaseInsensitive,
10545 + dialogPatterns->dspElements[i]->dspeRegularExpression);
10547 + newElement->mpteAll.pesPattern[i]->peIndex = i;
10551 + * sort pattern elements into start, middle & end arrays
10553 + sortDialogPatternElementSet( &newElement->mpteAll, newElement );
10556 + * determine mono pattern
10558 + if (newElement->mpteEnd.pesNumberOfPattern == 0)
10560 + newElement->mpteIsMonoPattern = True;
10562 + copyPatternSet( &newElement->mpteStart, &newElement->mpteEnd );
10566 + newElement->mpteIsMonoPattern = False;
10571 + * Sort dialog pattern element set into start, middle & end arrays.
10573 +static void sortDialogPatternElementSet(
10574 + PatternElementSet *allPat,
10575 + MatchPatternTableElement *result)
10580 + * count number of start, middle & end pattern elements
10582 + countPatternElementKind( allPat, result );
10585 + * allocate pattern elements
10587 + sizeOfPat = sizeof(PatternElement *) * result->mpteStart.pesNumberOfPattern;
10588 + result->mpteStart.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
10590 + if (result->mpteMiddle.pesNumberOfPattern != 0)
10592 + sizeOfPat = sizeof(PatternElement *) * result->mpteMiddle.pesNumberOfPattern;
10593 + result->mpteMiddle.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
10596 + if (result->mpteEnd.pesNumberOfPattern != 0)
10598 + sizeOfPat = sizeof(PatternElement *) * result->mpteEnd.pesNumberOfPattern;
10599 + result->mpteEnd.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
10603 + * sort pattern elements into start, middle & end arrays
10605 + sortPatternElementSet( allPat, result );
10608 +static MatchPatternGroupElement *translateDialogMatchPatternGroupElement(
10609 + ReadMatchPatternInfo *info,
10610 + DialogMatchPatternGroupElement *dialogGroup)
10613 + int error = False;
10614 + MatchPatternTableElement *subPatElement;
10616 + MatchPatternGroupElement *group;
10619 + * Allocate memory for the matching pattern group. Copy name & number of
10623 + (MatchPatternGroupElement *)XtMalloc( sizeof(MatchPatternGroupElement) );
10625 + group->mpgeName = XtNewString(dialogGroup->dmpgeName);
10626 + group->mpgeNumberOfSubPatterns = dialogGroup->dmpgeNumberOfSubPatterns;
10627 + group->mpgeKeywordRE = NULL;
10630 + * Allocate memory for the sub-matching pattern IDs
10632 + sizeOfIds = sizeof(char *) * group->mpgeNumberOfSubPatterns;
10633 + group->mpgeSubPatternIds = (char **)XtMalloc( sizeOfIds );
10635 + for (i=0; i < group->mpgeNumberOfSubPatterns; i ++)
10638 + * Remember sub-matching pattern ID
10640 + group->mpgeSubPatternIds[i] = XtNewString(dialogGroup->dmpgeSubPatternIds[i]);
10643 + * Assign the index of this group to the sub-matching pattern
10644 + * if no group index was assigned before.
10647 + getPatternOfName( info, dialogGroup->dmpgeSubPatternIds[i]);
10649 + if (subPatElement == NULL)
10652 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10653 + "Group Compilation",
10654 + "Group '%s':\nsub-matching pattern '%s' not defined before",
10657 + dialogGroup->dmpgeSubPatternIds[i]);
10663 + if (subPatElement->mpteGroup == NO_GROUP_IDX)
10665 + subPatElement->mpteGroup = info->rmpiNbrOfGroups;
10672 + freeMatchPatternGroupElement(group);
10680 +static int stringMatchTableDiffer(
10681 + StringMatchTable *oldTable,
10682 + StringMatchTable *newTable)
10685 + MatchPatternTable *oldPatTab = oldTable->smtAllPatterns;
10686 + MatchPatternTable *newPatTab = newTable->smtAllPatterns;
10687 + MatchPatternTableElement *oldPat;
10688 + MatchPatternTableElement *newPat;
10689 + MatchPatternGroupElement *oldGroup;
10690 + MatchPatternGroupElement *newGroup;
10691 + MatchPatternSequenceElement *oldSeq;
10692 + MatchPatternSequenceElement *newSeq;
10694 + if (oldTable->smtNumberOfSeqElements != newTable->smtNumberOfSeqElements)
10697 + for (i=0; i < oldTable->smtNumberOfSeqElements; i++)
10699 + oldSeq = oldTable->smtSequence[i];
10700 + newSeq = newTable->smtSequence[i];
10702 + if (AllocatedStringsDiffer(oldSeq->mpseName, newSeq->mpseName))
10704 + if (oldSeq->mpseType != newSeq->mpseType)
10707 + if (oldSeq->mpseType == MPT_GROUP)
10709 + oldGroup = oldTable->smtGroups[oldSeq->mpseIndex];
10710 + newGroup = newTable->smtGroups[newSeq->mpseIndex];
10712 + if (AllocatedStringsDiffer(oldGroup->mpgeName, newGroup->mpgeName))
10715 + if (oldGroup->mpgeNumberOfSubPatterns != newGroup->mpgeNumberOfSubPatterns)
10718 + for (j=0; j < oldGroup->mpgeNumberOfSubPatterns; j++)
10720 + if (AllocatedStringsDiffer(
10721 + oldGroup->mpgeSubPatternIds[j],
10722 + newGroup->mpgeSubPatternIds[j]))
10728 + oldPat = oldPatTab->mptElements[oldSeq->mpseIndex];
10729 + newPat = newPatTab->mptElements[newSeq->mpseIndex];
10731 + if (AllocatedStringsDiffer(oldPat->mpteName, newPat->mpteName))
10734 + if (oldPat->mpteType != newPat->mpteType)
10737 + if (oldPat->mpteGroup != newPat->mpteGroup)
10740 + if (oldPat->mpteAll.pesNumberOfPattern != newPat->mpteAll.pesNumberOfPattern)
10743 + for (j=0; j < oldPat->mpteAll.pesNumberOfPattern; j ++)
10745 + if (patternElementDiffer(
10746 + oldPat->mpteAll.pesPattern[j], oldPatTab,
10747 + newPat->mpteAll.pesPattern[j], newPatTab ) )
10751 + if (oldPat->mpteIsMonoPattern != newPat->mpteIsMonoPattern)
10754 + if (oldPat->mpteSkipBtwnStartEnd != newPat->mpteSkipBtwnStartEnd)
10757 + if (oldPat->mpteIgnoreHighLightInfo != newPat->mpteIgnoreHighLightInfo)
10760 + if (oldPat->mpteFlash != newPat->mpteFlash)
10768 +static int patternElementDiffer(
10769 + PatternElement *oldPE,
10770 + MatchPatternTable *oldTab,
10771 + PatternElement *newPE,
10772 + MatchPatternTable *newTab)
10774 + StringPattern *oldSP;
10775 + StringPattern *newSP;
10777 + oldSP = GetStringPattern(oldTab, oldPE);
10778 + newSP = GetStringPattern(newTab, newPE);
10780 + if (AllocatedStringsDiffer(oldSP->spText, newSP->spText))
10782 + if (AllocatedStringsDiffer(oldSP->spOrigText, newSP->spOrigText))
10784 + if (oldPE->peKind != newPE->peKind)
10786 + if (oldSP->spWordBoundary != newSP->spWordBoundary)
10788 + if (oldSP->spCaseInsensitive != newSP->spCaseInsensitive)
10790 + if (oldSP->spRegularExpression != newSP->spRegularExpression)
10796 +static DialogMatchPatternGroupElement *getDialogGroupUsingMatchPattern(
10797 + char *matchPatternName)
10799 + DialogMatchPatternSequenceElement *seq;
10800 + DialogMatchPatternGroupElement *group;
10803 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10805 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
10807 + if (seq->dmpseType == MPT_GROUP)
10809 + group = (DialogMatchPatternGroupElement *)seq->dmpsePtr;
10811 + for (j=0; j < group->dmpgeNumberOfSubPatterns; j ++)
10813 + if (strcmp(group->dmpgeSubPatternIds[j], matchPatternName) == 0)
10822 +static void removeMatchPatternFromGroup(
10823 + char *matchPatternName,
10824 + DialogMatchPatternGroupElement *group)
10828 + for (i=0; i < group->dmpgeNumberOfSubPatterns; i ++)
10830 + if (strcmp(group->dmpgeSubPatternIds[i], matchPatternName) == 0)
10833 + * remove existing matching pattern name from sub-pattern list
10835 + freeXtPtr((void **)&group->dmpgeSubPatternIds[i]);
10837 + &group->dmpgeSubPatternIds[i],
10838 + &group->dmpgeSubPatternIds[i+1],
10839 + (group->dmpgeNumberOfSubPatterns-1 - i) * sizeof(char *));
10840 + group->dmpgeNumberOfSubPatterns --;
10847 +static void removeMatchPatternFromAllGroups(
10848 + char *matchPatternName)
10850 + DialogMatchPatternSequenceElement *seq;
10851 + DialogMatchPatternGroupElement *group;
10854 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10856 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
10858 + if (seq->dmpseType == MPT_GROUP)
10860 + group = (DialogMatchPatternGroupElement *)seq->dmpsePtr;
10862 + removeMatchPatternFromGroup(matchPatternName, group);
10867 +static void renameMatchPatternInGroup(
10868 + char *oldMatchPatternName,
10869 + char *newMatchPatternName,
10870 + DialogMatchPatternGroupElement *group)
10874 + for (i=0; i < group->dmpgeNumberOfSubPatterns; i ++)
10876 + if (strcmp(group->dmpgeSubPatternIds[i], oldMatchPatternName) == 0)
10879 + * rename existing matching pattern name in sub-pattern list
10881 + freeXtPtr((void **)&group->dmpgeSubPatternIds[i]);
10883 + group->dmpgeSubPatternIds[i] =
10884 + XtNewString(newMatchPatternName);
10891 +static void renameMatchPatternInAllGroups(
10892 + char *oldMatchPatternName,
10893 + char *newMatchPatternName)
10895 + DialogMatchPatternSequenceElement *seq;
10896 + DialogMatchPatternGroupElement *group;
10899 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10901 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
10903 + if (seq->dmpseType == MPT_GROUP)
10905 + group = (DialogMatchPatternGroupElement *)seq->dmpsePtr;
10907 + renameMatchPatternInGroup(
10908 + oldMatchPatternName,
10909 + newMatchPatternName,
10915 +static void freeVariableDialogData(
10916 + int keepLanguageModeName)
10920 + if (!keepLanguageModeName)
10921 + freeXtPtr((void **)&MatchPatternDialog.mpdLangModeName);
10923 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10925 + freeDialogSequenceElement(
10926 + MatchPatternDialog.mpdTable.dmpiSequence[i] );
10929 + MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements = 0;
10931 + freeDialogStringPatterns(
10932 + &MatchPatternDialog.currentStringPatterns);
10935 +static void initGlobalBackRefList(
10936 + GlobalBackRefElement *list)
10940 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
10942 + list[i].gbreDefByStrPat = NULL;
10943 + list[i].gbreRegExpText = NULL;
10947 +static void initStrPatBackRefList(
10948 + StringPattern *strPat)
10952 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
10954 + strPat->spOwnGlobalBackRef[i].spbreRegExpText = NULL;
10955 + strPat->spOwnGlobalBackRef[i].spbreLocalBackRefID = NO_LOCAL_BACK_REF_ID;
10957 + strPat->spGlobalToLocalBackRef[i] = NO_LOCAL_BACK_REF_ID;
10961 +static void initErrorInfo(
10962 + ErrorInfo *errInfo)
10964 + errInfo->eiDetail = NULL;
10965 + errInfo->eiLanguageMode = NULL;
10966 + errInfo->eiMPTabElementName = NULL;
10967 + errInfo->eiStringPatText = NULL;
10968 + errInfo->eiRegExpCompileMsg = NULL;
10969 + errInfo->eiBackRefNbr = 0;
10972 +static void freeErrorInfo(
10973 + ErrorInfo *errInfo)
10975 + freeXtPtr((void **)&errInfo->eiLanguageMode);
10976 + freeXtPtr((void **)&errInfo->eiMPTabElementName);
10977 + freeXtPtr((void **)&errInfo->eiStringPatText);
10980 +static void freeXtPtr(void **ptr)
10982 + if (*ptr != NULL)
10984 + XtFree((char *)*ptr);
10989 +static void freePtr(void **ptr)
10991 + if (*ptr != NULL)
10993 + free((char *)*ptr);
10997 diff --quilt /dev/null new/source/patternMatchData.h
10999 +++ new/source/patternMatchData.h
11001 +/* $Id: patternMatchData.h,v 1.3 2003/12/12 16:45:25 uleh Exp $ */
11003 +#ifndef NEDIT_PATTERNMATCHDATA_H_INCLUDED
11004 +#define NEDIT_PATTERNMATCHDATA_H_INCLUDED
11006 +void *FindStringMatchTable(const char *langModeName);
11008 +void RenameStringMatchTable(const char *oldName, const char *newName);
11010 +void DeleteStringMatchTable(const char *langModeName);
11012 +void AssignStandardStringMatchTable(const char *langModeName);
11014 +int LMHasStringMatchTable(const char *languageMode);
11016 +int LoadMatchPatternString(char *inString);
11018 +char *WriteMatchPatternString(void);
11020 +void EditMatchPatterns(WindowInfo *window);
11022 +void UpdateLanguageModeMenuMatchPattern(void);
11024 +#endif /* NEDIT_PATTERNMATCHDATA_H_INCLUDED */
11025 diff --quilt old/source/preferences.c new/source/preferences.c
11026 --- old/source/preferences.c
11027 +++ new/source/preferences.c
11028 @@ -47,6 +47,10 @@ static const char CVSID[] = "$Id: prefer
11029 #include "windowTitle.h"
11030 #include "server.h"
11033 +/* Pattern Match Feature */
11034 +#include "patternMatchData.h"
11036 #include "../util/prefFile.h"
11037 #include "../util/misc.h"
11038 #include "../util/DialogF.h"
11039 @@ -280,7 +284,6 @@ static struct prefData {
11040 int emTabDist; /* non-zero tab dist. if emulated tabs are on */
11041 int insertTabs; /* whether to use tabs for padding */
11042 int showMatchingStyle; /* how to flash matching parenthesis */
11043 - int matchSyntaxBased; /* use syntax info to match parenthesis */
11044 int highlightSyntax; /* whether to highlight syntax by default */
11045 int smartTags; /* look for tag in current window first */
11046 int alwaysCheckRelativeTagsSpecs; /* for every new opened file of session */
11047 @@ -350,6 +353,7 @@ static struct {
11049 char *smartIndentCommon;
11051 + char *matchPattern;
11054 /* preference descriptions for SavePreferences and RestorePreferences. */
11055 @@ -855,6 +859,72 @@ static PrefDescripRec PrefDescrip[] = {
11056 Matlab:Default", &TempStringPrefs.smartIndent, NULL, True},
11057 {"smartIndentInitCommon", "SmartIndentInitCommon", PREF_ALLOC_STRING,
11058 "Default", &TempStringPrefs.smartIndentCommon, NULL, True},
11059 +/* Pattern Match Feature: matchPatterns resource added */
11061 +/* The VAX compiler can't compile Java-Script's definition in highlightData.c */
11062 + {"matchPatterns", "MatchPatterns", PREF_ALLOC_STRING,
11063 + "PLAIN:Default\n\
11070 + Fortran:Default\n\
11074 + Makefile:Default\n\
11075 + Matlab:Default\n\
11076 + NEdit Macro:Default\n\
11077 + Pascal:Default\n\
11079 + PostScript:Default\n\
11080 + Python:Default\n\
11082 + SGML HTML:Default\n\
11084 + Sh Ksh Bash:Default\n\
11087 + Verilog:Default\n\
11089 + X Resources:Default\n\
11091 + &TempStringPrefs.matchPattern, NULL, True},
11093 + {"matchPatterns", "MatchPatterns", PREF_ALLOC_STRING,
11094 + "PLAIN:Default\n\
11101 + Fortran:Default\n\
11103 + JavaScript:Default\n\
11106 + Makefile:Default\n\
11107 + Matlab:Default\n\
11108 + NEdit Macro:Default\n\
11109 + Pascal:Default\n\
11111 + PostScript:Default\n\
11112 + Python:Default\n\
11114 + SGML HTML:Default\n\
11116 + Sh Ksh Bash:Default\n\
11119 + Verilog:Default\n\
11121 + X Resources:Default\n\
11123 + &TempStringPrefs.matchPattern, NULL, True},
11125 {"autoWrap", "AutoWrap", PREF_ENUM, "Continuous",
11126 &PrefData.wrapStyle, AutoWrapTypes, True},
11127 {"wrapMargin", "WrapMargin", PREF_INT, "0",
11128 @@ -871,8 +941,6 @@ static PrefDescripRec PrefDescrip[] = {
11129 &PrefData.saveOldVersion, NULL, True},
11130 {"showMatching", "ShowMatching", PREF_ENUM, "Delimiter",
11131 &PrefData.showMatchingStyle, ShowMatchingTypes, True},
11132 - {"matchSyntaxBased", "MatchSyntaxBased", PREF_BOOLEAN, "True",
11133 - &PrefData.matchSyntaxBased, NULL, True},
11134 {"highlightSyntax", "HighlightSyntax", PREF_BOOLEAN, "True",
11135 &PrefData.highlightSyntax, NULL, True},
11136 {"backlightChars", "BacklightChars", PREF_BOOLEAN, "False",
11137 @@ -1245,6 +1313,7 @@ static void lmApplyCB(Widget w, XtPointe
11138 static void lmCloseCB(Widget w, XtPointer clientData, XtPointer callData);
11139 static int lmDeleteConfirmCB(int itemIndex, void *cbArg);
11140 static int updateLMList(void);
11141 +static int isOldLanguageMode(const char *lmDialogName, const char *oldModeName);
11142 static languageModeRec *copyLanguageModeRec(languageModeRec *lm);
11143 static void *lmGetDisplayedCB(void *oldItem, int explicitRequest, int *abort,
11145 @@ -1427,6 +1496,11 @@ static void translatePrefFormats(int con
11146 XtFree(TempStringPrefs.smartIndentCommon);
11147 TempStringPrefs.smartIndentCommon = NULL;
11149 + if (TempStringPrefs.matchPattern != NULL) {
11150 + LoadMatchPatternString(TempStringPrefs.matchPattern);
11151 + XtFree(TempStringPrefs.matchPattern);
11152 + TempStringPrefs.matchPattern = NULL;
11155 /* translate the font names into fontLists suitable for the text widget */
11156 font = XLoadQueryFont(TheDisplay, PrefData.fontString);
11157 @@ -1506,6 +1580,7 @@ void SaveNEditPrefs(Widget parent, int q
11158 TempStringPrefs.styles = WriteStylesString();
11159 TempStringPrefs.smartIndent = WriteSmartIndentString();
11160 TempStringPrefs.smartIndentCommon = WriteSmartIndentCommonString();
11161 + TempStringPrefs.matchPattern = WriteMatchPatternString();
11162 strcpy(PrefData.fileVersion, PREF_FILE_VERSION);
11164 if (!SavePreferences(XtDisplay(parent), prefFileName, HeaderText,
11165 @@ -1525,6 +1600,7 @@ void SaveNEditPrefs(Widget parent, int q
11166 XtFree(TempStringPrefs.styles);
11167 XtFree(TempStringPrefs.smartIndent);
11168 XtFree(TempStringPrefs.smartIndentCommon);
11169 + XtFree(TempStringPrefs.matchPattern);
11171 PrefsHaveChanged = False;
11173 @@ -1921,16 +1997,6 @@ int GetPrefShowMatching(void)
11174 return PrefData.showMatchingStyle;
11177 -void SetPrefMatchSyntaxBased(int state)
11179 - setIntPref(&PrefData.matchSyntaxBased, state);
11182 -int GetPrefMatchSyntaxBased(void)
11184 - return PrefData.matchSyntaxBased;
11187 void SetPrefHighlightSyntax(Boolean state)
11189 setIntPref(&PrefData.highlightSyntax, state);
11190 @@ -3480,6 +3546,21 @@ static int lmDeleteConfirmCB(int itemInd
11194 + /* Pattern Match Feature: don't allow deletion if data will be lost */
11195 + if (LMHasStringMatchTable(LMDialog.languageModeList[itemIndex]->name))
11197 + DialogF(DF_WARN, LMDialog.shell, 1, "Matching Patterns exist",
11198 + "This language mode has matching patterns\n"
11199 + "defined. Please delete the patterns first,\n"
11200 + "in Preferences -> Default Settings ->\n"
11201 + "Show Matching (..) -> Matching Patterns ..,\n"
11202 + "before proceeding here.", "Dismiss");
11206 + /* delete "empty" string match table related to language mode to be deleted */
11207 + DeleteStringMatchTable(LMDialog.languageModeList[itemIndex]->name);
11212 @@ -3500,15 +3581,15 @@ static int updateLMList(void)
11215 /* Fix up language mode indices in all open windows (which may change
11216 - if the currently selected mode is deleted or has changed position),
11217 - and update word delimiters */
11218 + if the currently selected mode is renamed, deleted or has changed
11219 + position), and update word delimiters */
11220 for (window=WindowList; window!=NULL; window=window->next) {
11221 if (window->languageMode != PLAIN_LANGUAGE_MODE) {
11222 oldLanguageMode = window->languageMode;
11223 oldModeName = LanguageModes[window->languageMode]->name;
11224 window->languageMode = PLAIN_LANGUAGE_MODE;
11225 for (i=0; i<LMDialog.nLanguageModes; i++) {
11226 - if (!strcmp(oldModeName, LMDialog.languageModeList[i]->name)) {
11227 + if (isOldLanguageMode(LMDialog.languageModeList[i]->name, oldModeName)) {
11228 newDelimiters = LMDialog.languageModeList[i]->delimiters;
11229 if (newDelimiters == NULL)
11230 newDelimiters = GetPrefDelimiters();
11231 @@ -3538,6 +3619,7 @@ static int updateLMList(void)
11232 *strchr(LMDialog.languageModeList[i]->name, ':') = '\0';
11233 RenameHighlightPattern(LMDialog.languageModeList[i]->name, newName);
11234 RenameSmartIndentMacros(LMDialog.languageModeList[i]->name, newName);
11235 + RenameStringMatchTable(LMDialog.languageModeList[i]->name, newName);
11236 memmove(LMDialog.languageModeList[i]->name, newName,
11237 strlen(newName) + 1);
11238 ChangeManagedListData(LMDialog.managedListW);
11239 @@ -3555,13 +3637,24 @@ static int updateLMList(void)
11241 UpdateUserMenuInfo();
11243 + /* Pattern Match Feature: assign standard string match table to new
11244 + language modes */
11245 + for (i=0; i<NLanguageModes; i++) {
11246 + if (FindStringMatchTable(LanguageModeName(i)) == NULL)
11247 + AssignStandardStringMatchTable(LanguageModeName(i));
11250 /* Update the menus in the window menu bars and load any needed
11251 - calltips files */
11252 + calltips files and reassign string match tables */
11253 for (window=WindowList; window!=NULL; window=window->next) {
11254 updateLanguageModeSubmenu(window);
11255 if (window->languageMode != PLAIN_LANGUAGE_MODE &&
11256 LanguageModes[window->languageMode]->defTipsFile != NULL)
11257 AddTagsFile(LanguageModes[window->languageMode]->defTipsFile, TIP);
11259 + window->stringMatchTable =
11260 + FindStringMatchTable(LanguageModeName(window->languageMode));
11262 /* cache user menus: Rebuild all user menus of this window */
11263 RebuildAllMenus(window);
11265 @@ -3570,12 +3663,32 @@ static int updateLMList(void)
11266 UpdateLanguageModeMenu();
11267 /* The same for the smart indent macro dialog */
11268 UpdateLangModeMenuSmartIndent();
11269 + /* The same for the match pattern dialog */
11270 + UpdateLanguageModeMenuMatchPattern();
11271 /* Note that preferences have been changed */
11272 MarkPrefsChanged();
11278 +** Returns true, if the given old language mode name matches the
11279 +** given (new) language mode dialog name.
11281 +static int isOldLanguageMode(const char *lmDialogName, const char *oldModeName)
11283 + char *c = strchr(lmDialogName, ':');
11284 + int isOldMode = !strcmp(oldModeName, lmDialogName);
11286 + if (!isOldMode && c != NULL) {
11288 + isOldMode = !strcmp(lmDialogName, oldModeName);
11292 + return isOldMode;
11295 static void *lmGetDisplayedCB(void *oldItem, int explicitRequest, int *abort,
11298 @@ -4569,6 +4682,10 @@ static void reapplyLanguageMode(WindowIn
11299 DeleteTagsFile( LanguageModes[oldMode]->defTipsFile, TIP, False );
11302 + /* Pattern Match Feature: Assign the match pattern related to
11303 + the language mode */
11304 + window->stringMatchTable = FindStringMatchTable(LanguageModeName(mode));
11306 /* Set delimiters for all text widgets */
11307 if (mode == PLAIN_LANGUAGE_MODE || LanguageModes[mode]->delimiters == NULL)
11308 delimiters = GetPrefDelimiters();
11309 @@ -5186,14 +5303,31 @@ char *ReadSymbolicFieldTextWidget(Widget
11311 ** Create a pulldown menu pane with the names of the current language modes.
11312 ** XmNuserData for each item contains the language mode name.
11313 +** Pattern Match Feature: if "includePlain" is set, then 1st menu entry
11316 -Widget CreateLanguageModeMenu(Widget parent, XtCallbackProc cbProc, void *cbArg)
11317 +Widget CreateLanguageModeMenu(
11319 + XtCallbackProc cbProc,
11321 + int includePlain)
11327 menu = CreatePulldownMenu(parent, "languageModes", NULL, 0);
11329 + if (includePlain) {
11330 + btn = XtVaCreateManagedWidget("languageMode", xmPushButtonGadgetClass,
11332 + XmNlabelString, s1=XmStringCreateSimple("PLAIN"),
11333 + XmNmarginHeight, 0,
11334 + XmNuserData, (void *)"PLAIN", NULL);
11335 + XmStringFree(s1);
11336 + XtAddCallback(btn, XmNactivateCallback, cbProc, cbArg);
11339 for (i=0; i<NLanguageModes; i++) {
11340 btn = XtVaCreateManagedWidget("languageMode", xmPushButtonGadgetClass,
11342 diff --quilt old/source/preferences.h new/source/preferences.h
11343 --- old/source/preferences.h
11344 +++ new/source/preferences.h
11345 @@ -111,8 +111,6 @@ void SetPrefInsertTabs(int state);
11346 int GetPrefInsertTabs(void);
11347 void SetPrefShowMatching(int state);
11348 int GetPrefShowMatching(void);
11349 -void SetPrefMatchSyntaxBased(int state);
11350 -int GetPrefMatchSyntaxBased(void);
11351 void SetPrefHighlightSyntax(Boolean state);
11352 Boolean GetPrefHighlightSyntax(void);
11353 void SetPrefBacklightChars(int state);
11354 @@ -192,7 +190,7 @@ int FindLanguageMode(const char *languag
11355 void UnloadLanguageModeTipsFile(WindowInfo *window);
11356 void DetermineLanguageMode(WindowInfo *window, int forceNewDefaults);
11357 Widget CreateLanguageModeMenu(Widget parent, XtCallbackProc cbProc,
11359 + void *cbArg, int includePlain);
11360 void SetLangModeMenu(Widget optMenu, const char *modeName);
11361 void CreateLanguageModeSubMenu(WindowInfo* window, const Widget parent,
11362 const char* name, const char* label, const char mnemonic);
11363 diff --quilt old/source/search.c new/source/search.c
11364 --- old/source/search.c
11365 +++ new/source/search.c
11366 @@ -85,6 +85,7 @@ static const char CVSID[] = "$Id: search
11367 #include "../debug.h"
11370 +#include "patternMatch.h"
11374 @@ -173,6 +174,7 @@ static void checkMultiReplaceListForDoom
11375 WindowInfo* doomedWindow);
11376 static void removeDoomedWindowFromList(WindowInfo* window, int index);
11377 static void unmanageReplaceDialogs(const WindowInfo *window);
11378 +static int getPosForMatchingCharacter(WindowInfo *window);
11379 static void flashTimeoutProc(XtPointer clientData, XtIntervalId *id);
11380 static void eraseFlash(WindowInfo *window);
11381 static int getReplaceDlogInfo(WindowInfo *window, int *direction,
11382 @@ -213,9 +215,6 @@ static void resetReplaceTabGroup(WindowI
11383 static int searchMatchesSelection(WindowInfo *window, const char *searchString,
11384 int searchType, int *left, int *right, int *searchExtentBW,
11385 int *searchExtentFW);
11386 -static int findMatchingChar(WindowInfo *window, char toMatch,
11387 - void *toMatchStyle, int charPos, int startLimit, int endLimit,
11389 static Boolean replaceUsingRE(const char* searchStr, const char* replaceStr,
11390 const char* sourceStr, int beginPos, char* destStr, int maxDestLen,
11391 int prevChar, const char* delimiters, int defaultFlags);
11392 @@ -253,24 +252,6 @@ typedef struct _charMatchTable {
11396 -#define N_MATCH_CHARS 13
11397 -#define N_FLASH_CHARS 6
11398 -static charMatchTable MatchingChars[N_MATCH_CHARS] = {
11399 - {'{', '}', SEARCH_FORWARD},
11400 - {'}', '{', SEARCH_BACKWARD},
11401 - {'(', ')', SEARCH_FORWARD},
11402 - {')', '(', SEARCH_BACKWARD},
11403 - {'[', ']', SEARCH_FORWARD},
11404 - {']', '[', SEARCH_BACKWARD},
11405 - {'<', '>', SEARCH_FORWARD},
11406 - {'>', '<', SEARCH_BACKWARD},
11407 - {'/', '/', SEARCH_FORWARD},
11408 - {'"', '"', SEARCH_FORWARD},
11409 - {'\'', '\'', SEARCH_FORWARD},
11410 - {'`', '`', SEARCH_FORWARD},
11411 - {'\\', '\\', SEARCH_FORWARD},
11415 ** Definitions for the search method strings, used as arguments for
11416 ** macro search subroutines and search action routines
11417 @@ -3342,18 +3323,18 @@ static void iSearchTextKeyEH(Widget w, W
11421 -** Check the character before the insertion cursor of textW and flash
11422 -** matching parenthesis, brackets, or braces, by temporarily highlighting
11423 -** the matching character (a timer procedure is scheduled for removing the
11425 +** Check the characters before the insertion cursor of textW and flash
11426 +** matching patterns (parenthesis e.g. brackets, braces ..) by temporarily
11427 +** highlighting matching characters (a timer procedure is scheduled for
11428 +** removing the highlights)
11430 void FlashMatching(WindowInfo *window, Widget textW)
11434 - int pos, matchIndex;
11435 - int startPos, endPos, searchPos, matchPos;
11438 + int startPos, endPos, matchPos, matchLen;
11440 + MatchingType matchingType;
11442 /* if a marker is already drawn, erase it and cancel the timeout */
11443 if (window->flashTimeoutID != 0) {
11444 @@ -3371,48 +3352,43 @@ void FlashMatching(WindowInfo *window, W
11445 if (window->buffer->primary.selected)
11448 - /* get the character to match and the position to start from */
11449 - pos = TextGetCursorPos(textW) - 1;
11450 + /* get the position to start from */
11451 + pos = TextGetCursorPos(textW);
11454 - c = BufGetCharacter(window->buffer, pos);
11455 - style = GetHighlightInfo(window, pos);
11457 - /* is the character one we want to flash? */
11458 - for (matchIndex = 0; matchIndex<N_FLASH_CHARS; matchIndex++) {
11459 - if (MatchingChars[matchIndex].c == c)
11462 - if (matchIndex == N_FLASH_CHARS)
11465 /* constrain the search to visible text only when in single-pane mode
11466 AND using delimiter flashing (otherwise search the whole buffer) */
11467 constrain = ((window->nPanes == 0) &&
11468 (window->showMatchingStyle == FLASH_DELIMIT));
11470 - if (MatchingChars[matchIndex].direction == SEARCH_BACKWARD) {
11471 startPos = constrain ? TextFirstVisiblePos(textW) : 0;
11473 - searchPos = endPos;
11476 endPos = constrain ? TextLastVisiblePos(textW) :
11477 window->buffer->length;
11478 - searchPos = startPos;
11480 + /* cursor pos. must be between start / end pos. */
11481 + if (pos < startPos || pos > endPos)
11484 + /* Pattern Match Feature: determine matching type
11485 + (here: flash delimiter or range) */
11486 + if (window->showMatchingStyle == FLASH_DELIMIT) {
11487 + matchingType = MT_FLASH_DELIMIT;
11489 + matchingType = MT_FLASH_RANGE;
11492 - /* do the search */
11493 - if (!findMatchingChar(window, c, style, searchPos, startPos, endPos,
11495 + /* Pattern Match Feature: do the search */
11496 + if (!FindMatchingString(window, matchingType, &pos, startPos, endPos,
11497 + &matchPos, &matchLen, &direction))
11500 if (window->showMatchingStyle == FLASH_DELIMIT) {
11501 - /* Highlight either the matching character ... */
11502 - BufHighlight(window->buffer, matchPos, matchPos+1);
11503 + /* Highlight either the matching characters ... */
11504 + BufHighlight(window->buffer, matchPos, matchPos + matchLen);
11506 /* ... or the whole range. */
11507 - if (MatchingChars[matchIndex].direction == SEARCH_BACKWARD) {
11508 + if (direction == SEARCH_BACKWARD) {
11509 BufHighlight(window->buffer, matchPos, pos+1);
11511 BufHighlight(window->buffer, matchPos+1, pos);
11512 @@ -3426,38 +3402,46 @@ void FlashMatching(WindowInfo *window, W
11513 window->flashPos = matchPos;
11516 -void SelectToMatchingCharacter(WindowInfo *window)
11518 +** Pattern Match Feature:
11519 +** get position of the character to match from the selection, or
11520 +** the character before the insert point if nothing is selected.
11523 +static int getPosForMatchingCharacter(WindowInfo *window)
11526 int selStart, selEnd;
11527 - int startPos, endPos, matchPos;
11528 textBuffer *buf = window->buffer;
11530 - /* get the character to match and its position from the selection, or
11531 - the character before the insert point if nothing is selected.
11532 - Give up if too many characters are selected */
11533 - if (!GetSimpleSelection(buf, &selStart, &selEnd)) {
11534 - selEnd = TextGetCursorPos(window->lastFocus);
11535 - if (window->overstrike)
11537 - selStart = selEnd - 1;
11538 - if (selStart < 0) {
11539 - XBell(TheDisplay, 0);
11542 + if (GetSimpleSelection(buf, &selStart, &selEnd)) {
11545 - if ((selEnd - selStart) != 1) {
11546 - XBell(TheDisplay, 0);
11549 + pos = TextGetCursorPos(window->lastFocus);
11556 +void SelectToMatchingCharacter(WindowInfo *window)
11559 + int startPos, endPos, matchPos, matchLen;
11561 + textBuffer *buf = window->buffer;
11563 + /* Pattern Match Feature: get position of the character to match */
11564 + pos = getPosForMatchingCharacter(window);
11566 /* Search for it in the buffer */
11567 - if (!findMatchingChar(window, BufGetCharacter(buf, selStart),
11568 - GetHighlightInfo(window, selStart), selStart, 0, buf->length, &matchPos)) {
11569 + if (!FindMatchingString(window, MT_SELECT, &pos, 0,
11570 + buf->length, &matchPos, &matchLen, &direction)) {
11571 XBell(TheDisplay, 0);
11574 - startPos = (matchPos > selStart) ? selStart : matchPos;
11575 - endPos = (matchPos > selStart) ? matchPos : selStart;
11576 + startPos = (matchPos > pos) ? pos : matchPos;
11577 + endPos = (matchPos > pos) ? matchPos : pos;
11579 /* temporarily shut off autoShowInsertPos before setting the cursor
11580 position so MakeSelectionVisible gets a chance to place the cursor
11581 @@ -3473,32 +3457,17 @@ void SelectToMatchingCharacter(WindowInf
11583 void GotoMatchingCharacter(WindowInfo *window)
11585 - int selStart, selEnd;
11588 + int matchPos, matchLen;
11590 textBuffer *buf = window->buffer;
11592 - /* get the character to match and its position from the selection, or
11593 - the character before the insert point if nothing is selected.
11594 - Give up if too many characters are selected */
11595 - if (!GetSimpleSelection(buf, &selStart, &selEnd)) {
11596 - selEnd = TextGetCursorPos(window->lastFocus);
11597 - if (window->overstrike)
11599 - selStart = selEnd - 1;
11600 - if (selStart < 0) {
11601 - XBell(TheDisplay, 0);
11605 - if ((selEnd - selStart) != 1) {
11606 - XBell(TheDisplay, 0);
11609 + /* Pattern Match Feature: get position of the character to match */
11610 + pos = getPosForMatchingCharacter(window);
11612 /* Search for it in the buffer */
11613 - if (!findMatchingChar(window, BufGetCharacter(buf, selStart),
11614 - GetHighlightInfo(window, selStart), selStart, 0,
11615 - buf->length, &matchPos)) {
11616 + if (!FindMatchingString(window, MT_GOTO, &pos, 0,
11617 + buf->length, &matchPos, &matchLen, &direction)) {
11618 XBell(TheDisplay, 0);
11621 @@ -3509,77 +3478,11 @@ void GotoMatchingCharacter(WindowInfo *w
11622 be automatically scrolled on screen and MakeSelectionVisible would do
11624 XtVaSetValues(window->lastFocus, textNautoShowInsertPos, False, NULL);
11625 - TextSetCursorPos(window->lastFocus, matchPos+1);
11626 + TextSetCursorPos(window->lastFocus, matchPos);
11627 MakeSelectionVisible(window, window->lastFocus);
11628 XtVaSetValues(window->lastFocus, textNautoShowInsertPos, True, NULL);
11631 -static int findMatchingChar(WindowInfo *window, char toMatch,
11632 - void* styleToMatch, int charPos, int startLimit, int endLimit,
11635 - int nestDepth, matchIndex, direction, beginPos, pos;
11636 - char matchChar, c;
11637 - void *style = NULL;
11638 - textBuffer *buf = window->buffer;
11639 - int matchSyntaxBased = window->matchSyntaxBased;
11641 - /* If we don't match syntax based, fake a matching style. */
11642 - if (!matchSyntaxBased) style = styleToMatch;
11644 - /* Look up the matching character and match direction */
11645 - for (matchIndex = 0; matchIndex<N_MATCH_CHARS; matchIndex++) {
11646 - if (MatchingChars[matchIndex].c == toMatch)
11649 - if (matchIndex == N_MATCH_CHARS)
11651 - matchChar = MatchingChars[matchIndex].match;
11652 - direction = MatchingChars[matchIndex].direction;
11654 - /* find it in the buffer */
11655 - beginPos = (direction==SEARCH_FORWARD) ? charPos+1 : charPos-1;
11657 - if (direction == SEARCH_FORWARD) {
11658 - for (pos=beginPos; pos<endLimit; pos++) {
11659 - c=BufGetCharacter(buf, pos);
11660 - if (c == matchChar) {
11661 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11662 - if (style == styleToMatch) {
11664 - if (nestDepth == 0) {
11669 - } else if (c == toMatch) {
11670 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11671 - if (style == styleToMatch)
11675 - } else { /* SEARCH_BACKWARD */
11676 - for (pos=beginPos; pos>=startLimit; pos--) {
11677 - c=BufGetCharacter(buf, pos);
11678 - if (c == matchChar) {
11679 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11680 - if (style == styleToMatch) {
11682 - if (nestDepth == 0) {
11687 - } else if (c == toMatch) {
11688 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11689 - if (style == styleToMatch)
11698 ** Xt timer procedure for erasing the matching parenthesis marker.
11700 diff --quilt old/source/smartIndent.c new/source/smartIndent.c
11701 --- old/source/smartIndent.c
11702 +++ new/source/smartIndent.c
11703 @@ -983,9 +983,9 @@ void EditSmartIndentMacros(WindowInfo *w
11705 XmNrightAttachment, XmATTACH_POSITION,
11706 XmNrightPosition, 99, NULL);
11708 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
11709 SmartIndentDialog.lmPulldown = CreateLanguageModeMenu(lmForm, langModeCB,
11713 XtSetArg(args[n], XmNspacing, 0); n++;
11714 XtSetArg(args[n], XmNmarginWidth, 0); n++;
11715 @@ -2155,8 +2155,9 @@ void UpdateLangModeMenuSmartIndent(void)
11718 oldMenu = SmartIndentDialog.lmPulldown;
11719 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
11720 SmartIndentDialog.lmPulldown = CreateLanguageModeMenu(
11721 - XtParent(XtParent(oldMenu)), langModeCB, NULL);
11722 + XtParent(XtParent(oldMenu)), langModeCB, NULL, FALSE);
11723 XtVaSetValues(XmOptionButtonGadget(SmartIndentDialog.lmOptMenu),
11724 XmNsubMenuId, SmartIndentDialog.lmPulldown, NULL);
11725 SetLangModeMenu(SmartIndentDialog.lmOptMenu, SmartIndentDialog.langModeName);
11726 diff --quilt old/source/window.c new/source/window.c
11727 --- old/source/window.c
11728 +++ new/source/window.c
11729 @@ -55,6 +55,7 @@ static const char CVSID[] = "$Id: window
11730 #include "windowTitle.h"
11731 #include "interpret.h"
11732 #include "rangeset.h"
11733 +#include "patternMatchData.h"
11734 #include "../util/clearcase.h"
11735 #include "../util/misc.h"
11736 #include "../util/fileUtils.h"
11737 @@ -277,7 +278,6 @@ WindowInfo *CreateWindow(const char *nam
11738 window->showWrapMargin = GetPrefShowWrapMargin();
11739 window->overstrike = False;
11740 window->showMatchingStyle = GetPrefShowMatching();
11741 - window->matchSyntaxBased = GetPrefMatchSyntaxBased();
11742 window->showStats = GetPrefStatsLine();
11743 window->showISearchLine = GetPrefISearchLine();
11744 window->showLineNumbers = GetPrefLineNums();
11745 @@ -316,6 +316,10 @@ WindowInfo *CreateWindow(const char *nam
11746 window->macroCmdData = NULL;
11747 window->smartIndentData = NULL;
11748 window->languageMode = PLAIN_LANGUAGE_MODE;
11750 + /* Pattern Match Feature: assign "PLAIN" string match table*/
11751 + window->stringMatchTable = FindStringMatchTable(NULL);
11753 window->iSearchHistIndex = 0;
11754 window->iSearchStartPos = -1;
11755 window->replaceLastRegexCase = TRUE;
11756 @@ -3450,7 +3454,6 @@ WindowInfo* CreateDocument(WindowInfo* s
11757 window->showWrapMargin = GetPrefShowWrapMargin();
11758 window->overstrike = False;
11759 window->showMatchingStyle = GetPrefShowMatching();
11760 - window->matchSyntaxBased = GetPrefMatchSyntaxBased();
11761 window->highlightSyntax = GetPrefHighlightSyntax();
11762 window->backlightCharTypes = NULL;
11763 window->backlightChars = GetPrefBacklightChars();
11764 @@ -3485,6 +3488,12 @@ WindowInfo* CreateDocument(WindowInfo* s
11765 window->macroCmdData = NULL;
11766 window->smartIndentData = NULL;
11767 window->languageMode = PLAIN_LANGUAGE_MODE;
11770 + * Pattern Match Feature:
11772 + window->stringMatchTable = FindStringMatchTable(NULL);
11774 window->iSearchHistIndex = 0;
11775 window->iSearchStartPos = -1;
11776 window->replaceLastRegexCase = TRUE;
11777 @@ -3882,7 +3891,6 @@ void RefreshMenuToggleStates(WindowInfo
11779 XmToggleButtonSetState(window->autoSaveItem, window->autoSave, False);
11780 XmToggleButtonSetState(window->overtypeModeItem, window->overstrike, False);
11781 - XmToggleButtonSetState(window->matchSyntaxBasedItem, window->matchSyntaxBased, False);
11782 XmToggleButtonSetState(window->readOnlyItem, IS_USER_LOCKED(window->lockReasons), False);
11783 XmToggleButtonSetState(window->transientItem, window->transient, False);
11785 @@ -4446,6 +4454,9 @@ static void cloneDocument(WindowInfo *wi
11786 if (window->highlightSyntax)
11787 StartHighlighting(window, False);
11789 + /* recycle the pattern match data */
11790 + window->stringMatchTable = orgWin->stringMatchTable;
11792 /* copy states of original document */
11793 window->filenameSet = orgWin->filenameSet;
11794 window->fileFormat = orgWin->fileFormat;
11795 @@ -4464,7 +4475,6 @@ static void cloneDocument(WindowInfo *wi
11796 window->wrapMode = orgWin->wrapMode;
11797 SetOverstrike(window, orgWin->overstrike);
11798 window->showMatchingStyle = orgWin->showMatchingStyle;
11799 - window->matchSyntaxBased = orgWin->matchSyntaxBased;
11801 window->showStats = orgWin->showStats;
11802 window->showISearchLine = orgWin->showISearchLine;