CVS rebase
[nedit-bw.git] / matching_patterns.patch
blob316fd1421c6896af357cad1e9c6277ad94878e85
1 ---
4 ---
6 doc/help.etx | 258 +
7 source/Makefile.common | 6
8 source/Makefile.dependencies | 11
9 source/highlightData.c | 13
10 source/macro.c | 107
11 source/menu.c | 63
12 source/nedit.h | 6
13 source/patternMatch.c | 2202 ++++++++++++
14 source/patternMatch.h | 170
15 source/patternMatchData.c | 7780 +++++++++++++++++++++++++++++++++++++++++++
16 source/patternMatchData.h | 24
17 source/preferences.c | 170
18 source/preferences.h | 4
19 source/search.c | 231 -
20 source/smartIndent.c | 7
21 source/window.c | 18
22 16 files changed, 10773 insertions(+), 297 deletions(-)
24 diff --quilt old/doc/help.etx new/doc/help.etx
25 --- old/doc/help.etx
26 +++ new/doc/help.etx
27 @@ -866,8 +866,9 @@ Programming with NEdit
28 Though general in appearance, NEdit has many features intended specifically
29 for programmers. Major programming-related topics are listed in separate
30 sections under the heading: "Features for Programming": Syntax_Highlighting_,
31 - Tabs/Emulated_Tabs_, Finding_Declarations_(ctags)_, Calltips_, and
32 - Auto/Smart_Indent_. Minor topics related to programming are discussed below:
33 + Tabs/Emulated_Tabs_, Matching_Parentheses_, Finding_Declarations_(ctags)_,
34 + Calltips_, and Auto/Smart_Indent_. Minor topics related to programming are
35 + discussed below:
37 3>Language Modes
39 @@ -925,26 +926,6 @@ Programming with NEdit
40 a column on the current line just leave out the line number. (e.g. Enter
41 ",45" to go the column 45 on the current line.)
43 -3>Matching Parentheses
45 - To help you inspect nested parentheses, brackets, braces, quotes, and other
46 - characters, NEdit has both an automatic parenthesis matching mode, and a Goto
47 - Matching command. Automatic parenthesis matching is activated when you type,
48 - or move the insertion cursor after a parenthesis, bracket, or brace. It
49 - momentarily highlights either the opposite character ('Delimiter') or the
50 - entire expression ('Range') when the opposite character is visible in the
51 - window. To find a matching character anywhere in the file, select it or
52 - position the cursor after it, and choose Goto Matching from the Search menu.
53 - If the character matches itself, such as a quote or slash, select the first
54 - character of the pair. NEdit will match {, (, [, <, ", ', `, /, and \.
55 - Holding the Shift key while typing the accelerator key (Shift+Ctrl+M, by
56 - default), will select all of the text between the matching characters.
58 - When syntax highlighting is enabled, the matching routines can optionally
59 - make use of the syntax information for improved accuracy. In that case,
60 - a brace inside a highlighted string will not match a brace inside a comment,
61 - for instance.
63 3>Opening Included Files
65 The Open Selected command in the File menu understands the C preprocessor's
66 @@ -1222,6 +1203,39 @@ Syntax Highlighting
67 possible, but unlikely if you are only using the built-in patterns.
68 ----------------------------------------------------------------------
70 +Matching Parentheses
71 +--------------------
73 +3>Matching Parentheses (Patterns)
75 + To help you inspect nested parentheses (e.g. brackets, braces, quotes
76 + etc.) or nested constructs (e.g. "begin" .. "end"), NEdit has both an
77 + automatic parenthesis matching mode, and a Goto Matching command.
79 + A matching pattern can be a single character (like '(', ')'), a literal
80 + string (like '#ifdef', '#endif') or a regular expression (like
81 + '\</.*\>').
83 + Automatic parenthesis matching is activated when you type, or move the
84 + insertion cursor after a parenthesis, bracket, or brace. It momentarily
85 + highlights either the opposite pattern ('Delimiter') or the entire expression
86 + ('Range') when the opposite pattern is visible in the window. To find a
87 + matching pattern anywhere in the file, select it or position the cursor after
88 + it, and choose Goto Matching from the Search menu. If the pattern matches
89 + itself, such as a quote or slash, select the first pattern of the pair.
90 + Holding the Shift key while typing the accelerator key (Shift+Ctrl+M, by
91 + default), will select all of the text between the matching patterns.
93 + When syntax highlighting is enabled, the matching routines can optionally
94 + make use of the syntax information for improved accuracy. In that case,
95 + a brace inside a highlighted string will not match a brace inside a comment,
96 + for instance.
98 + Matching patterns are language dependent. Matching patterns can be
99 + configured by the user. If no matching patterns are available for the
100 + language that you want to use, you can create new patterns relatively quickly.
101 + The Help section "Matching_Patterns_" under "Customizing", has details.
103 Finding Declarations (ctags)
104 ----------------------------
106 @@ -2580,9 +2594,6 @@ Macro Subroutines
107 Contains the current preference for showing matching pairs,
108 such as "[]" and "{}" pairs. Can be "off", "delimiter", or "range".
110 -**$match_syntax_based**
111 - Whether pair matching should use syntax information, if available.
113 **$statistics_line**
114 Has a value of 1 if the statistics line is shown, otherwise 0.
116 @@ -2697,6 +2708,15 @@ Macro Subroutines
117 Returns the single character at the position
118 indicated by the first argument to the routine from the current window.
120 +**get_matching( position )**
121 + Find a matching pattern string related to the given position.
122 + Returns info about matching pattern within an array. The array has
123 + the following keys: **pos** (position of the first character of the
124 + matching pattern), **len** (length of the matching pattern), **direction**
125 + (direction where the matching pattern was found: ~0~ = forward;
126 + ~1~ = backward). If no matching pattern was found, then array element
127 + of **pos** holds ~-1~, **len** holds ~0~ and **direction** holds ~-1~.
129 **get_range( start, end )**
130 Returns the text between a starting and ending position from the current
131 window.
132 @@ -3406,9 +3426,6 @@ Action Routines
133 **set_show_matching( "off" | "delimiter" | "range" )**
134 Set show matching (...) mode for the current window.
136 -**set_match_syntax_based( [0 | 1] )**
137 - Set whether matching should be syntax based for the current window.
139 **set_statistics_line( [0 | 1] )**
140 Show or hide the statistics line for the current window.
141 A value of 0 turns it off and a value of 1 turns it on.
142 @@ -3940,10 +3957,6 @@ Preferences
143 matching delimiter, while Range highlights the whole range of text between
144 the matching delimiters.
146 - Optionally, the matching can make use of syntax information if syntax
147 - highlighting is enabled. Alternatively, the matching is purely character
148 - based. In general, syntax based matching results in fewer false matches.
150 **Overtype**
151 In overtype mode, new characters entered replace the characters in front of
152 the insertion cursor, rather than being inserted before them.
153 @@ -5049,6 +5062,185 @@ Smart Indent Macros
154 keystroke typed, so if you try to get too fancy, you may degrade performance.
155 ----------------------------------------------------------------------
157 +Matching Patterns
158 +-----------------
160 +3>Writing Matching Pattern Sets
162 + Matching Patterns Sets are groups of single characters (like '(', ')'),
163 + literal strings (like '#ifdef', '#endif') or a regular expressions (like
164 + '\</.*\>'), which match to each other.
166 + Examples: An open bracket '(' belongs a closing one ')'.
167 + Or: '#ifdef'(start), '#ifndef'(alternative start), '#ifndef' (another
168 + alternative start),'#elif' (optional), '#else' (optional), '#endif' (end)
169 + define a "#ifdef statement matching pattern".
171 + "Opposite pattern highlighting" or "Goto Matching" features are implemented
172 + in NEdit using this matching pattern sets (see Matching_Parentheses_ under
173 + the heading of Features for Programming).
175 + During definition of a new language mode a standard matching pattern set
176 + is assigned to this new language mode.
178 + To modify a matching pattern set, select "Matching Patterns ..." from
179 + "Show Matching (..)" sub-section of the "Default Settings" sub-menu
180 + of the "Preferences" menu.
182 + A matching pattern set is a collection of matching patterns.
184 + A matching pattern usually consists out of string patterns.
186 + The name of a matching pattern set needs to be defined within field "Matching
187 + Pattern Name".
189 +4>Attributes of matching pattern
191 + A matching pattern holds two types of attributes:
193 +* "Matching Pattern Type" and
194 +* "Global Attributes"
196 + The matching pattern type specifies the kind of the matching pattern
197 + entry:
199 +* "Individual" or
200 +* "Sub-pattern" or
201 +* "Context group"
203 + Each matching pattern can be defined as "Individual" or as "Sub-pattern".
204 + A "Sub-pattern" belongs to a context group. A context group is simply a
205 + collection of sub-patterns.
207 + During search for a corresponding pattern, an "Individual" matching pattern
208 + does not care about nesting of other matching patterns.
210 + If a matching pattern out of a "Context group" is searched, then all
211 + sub-pattern sets defined in this group are taken into account during the
212 + search.
214 + In fact, "Individual" matching pattern search is faster than "Context group" /
215 + "Sub-pattern" search. "Context group" / "Sub-pattern" search results in fewer
216 + false matches.
218 + To define a context group, set "Matching Pattern Type" to "Context group".
219 + Select out of "Sub-Pattern Name" pop-up field all sub-patterns, which
220 + should be placed into this group. **Note**: all "Sub-pattern" used by a context
221 + group must be defined **before** the context group itself.
223 + "Global Attributes" of a matching pattern are
225 +* "Skip content between start / end pattern"
226 +* "Flash matching pattern"
227 +* "Syntax based"
229 + If "Skip content between start / end pattern" is checked, then all text
230 + between the first / last string pattern of the related matching pattern is
231 + not scanned for other string patterns. This is useful for specifying comments.
233 + "Flash matching pattern" indicates, if the string patterns are flashed during
234 + typing. If not checked, then only the "Goto Matching" feature works for the
235 + related matching pattern. Note: if lots of "Flash matching pattern" are
236 + specified, then this may slow down the performance of NEdit: after each
237 + character typed all "Flash matching pattern" are scanned for being
238 + applicable ...
240 + "Syntax based" defines, if the matching pattern can make use of syntax
241 + information if syntax highlighting is enabled. Alternatively, the matching is
242 + purely character based. In general, syntax based matching results in fewer
243 + false matches.
245 +4>Content of matching pattern
247 + An "Individual" pattern or a "Sub-pattern" may consist out of only one string
248 + pattern (e.g. double quotes '"'). Such a pattern is called "mono pattern".
249 + You can imagine, that a match for a mono pattern is hard to find. A matching
250 + mono pattern search is always started in forward direction. If no match is
251 + found in forward direction, a backward search is started. If the "Global
252 + Attribute" "Syntax based" is selected for a mono pattern, then the character
253 + before / after the match is checked to have the same highlighting style than
254 + the pattern itself. This may help to determine the correct match for a mono
255 + pattern.
257 + Usually a matching pattern holds two string patterns (e.g. 'begin' and
258 + 'end'). One ('begin') is the start pattern. The other one ('end') is the
259 + end pattern. If the cursor is located behind the start pattern, then a
260 + corresponding end pattern is searched (in forward direction). If the
261 + cursor is located behind the end pattern, then a start pattern is search
262 + (in backward direction):
264 +! +--> start ---> end --+
265 +! +-----------<---------+
267 + Alternative start / end patterns can be defined. In this case one of the
268 + start / end patterns must be in front of the cursor to detect one of the
269 + related end / start patterns:
271 +! +-> start1 -+ +-> end1 -+
272 +! +-+-> start2 -+---+ +--+
273 +! + +-> start3 -+ +-> end2 -+ |
274 +! +---------------<-------------+
276 + At least also "middle" patterns can be defined (e.g. middle patterns
277 + 'elif' or 'else'). If the cursor is located behind a middle pattern then a
278 + next middle pattern or the end pattern is searched in forward direction:
280 +! +-----<-----+
281 +! +--> start -+-> middle -+-> end --+
282 +! +-----------<---------------------+
284 +4>String pattern
286 + A string pattern holds three attributes:
288 +* "String Pattern Type"
289 +* "Word Boundary"
290 +* "String Attributes"
292 + String Pattern Type specifies if the related string pattern is
293 + a "start", middle, or "end" pattern (see above).
295 + Word boundary defines, if before / after a string pattern a delimiter must be
296 + located ("Both" = pattern is framed by delimiters. "Left" = before pattern
297 + must be a delimiter. "Right" = after pattern must be a delimiter. "None" =
298 + there must be no delimiter before or after pattern).
300 + There are two "String Attributes":
302 +* "Case Sensitive"
303 +* "Regular Expression"
305 + If "Case Sensitive" is checked (= default), then the matching pattern search
306 + concerning this string pattern differs between upper / lower case of the
307 + characters. If "Case Sensitive" is not set, then the case of the checked
308 + characters is not considered.
310 + "Regular Expression" indicates, that string pattern is treated as
311 + regular expression (if "Regular Expression" is checked) or as literal
312 + string (if "Regular Expression" is not checked).
314 +4>Regular Expression String Pattern
316 + Syntax of regular expression is described by NEdit Help menu item
317 + Regular_Expressions_. Following deviations from this syntax are
318 + existing concerning string patterns:
320 +5>Capturing Parentheses
322 + Capturing Parentheses inside string patterns are of the form `(*n<regex>)',
323 + where n = 1 .. 9. Standard "capturing parentheses" of form `(<regex>)' are
324 + treated as "non-capturing parentheses" by the matching pattern feature.
325 + "n" defines the **global** backreference number, which can be used inside any string
326 + pattern of the same matching pattern (= set of string patterns). So
327 + matching patterns like "\<(*1[^/>])\>" (start string pattern) and "\</\1\>"
328 + (end string pattern) are possible. This matching pattern will match e.g.
329 + <body> .. </body> but will not match <body> .. </head>.
331 +5>Non-Capturing Parentheses
333 + As described above: parentheses constructs like (<regex>) are treated
334 + as `(?:<regex>)' (non-capturing parentheses) by the matching pattern feature.
336 NEdit Command Line
337 ------------------
339 @@ -6079,6 +6271,7 @@ Problems/Defects
340 .. Menu: Tabs/Emulated Tabs # tabs
341 .. Menu: Auto/Smart Indent # indent
342 .. Menu: Syntax Highlighting # syntax
343 +.. Menu: Matching Parentheses # pattern_matching
344 .. Menu: Finding Declarations (ctags) # tags
345 .. Menu: Calltips # calltips
347 @@ -6106,6 +6299,7 @@ Problems/Defects
348 .. Menu: Key Binding # binding
349 .. Menu: Highlighting Patterns # patterns
350 .. Menu: Smart Indent Macros # smart_indent
351 +.. Menu: Matching Patterns # matching_patterns
353 .. Menu: NEdit Command Line # command_line
354 .. Menu: Client/Server Mode # server
355 diff --quilt old/source/Makefile.common new/source/Makefile.common
356 --- old/source/Makefile.common
357 +++ new/source/Makefile.common
358 @@ -7,7 +7,8 @@ OBJS = nedit.o file.o menu.o window.o se
359 help.o preferences.o tags.o userCmds.o shell.o regularExp.o macro.o \
360 text.o textSel.o textDisp.o textBuf.o textDrag.o server.o highlight.o \
361 highlightData.o interpret.o parse.o smartIndent.o regexConvert.o \
362 - rbTree.o windowTitle.o calltips.o server_common.o rangeset.o
363 + rbTree.o windowTitle.o calltips.o server_common.o rangeset.o \
364 + patternMatch.o patternMatchData.o
366 XLTLIB = ../Xlt/libXlt.a
367 XMLLIB = ../Microline/XmL/libXmL.a
368 @@ -37,6 +38,9 @@ smartIndent.o: smartIndent.c
369 highlightData.o: highlightData.c
370 $(CC) $(CFLAGS) $(BIGGER_STRINGS) -c highlightData.c -o $@
372 +patternMatchData.o: patternMatchData.c
373 + $(CC) $(CFLAGS) $(BIGGER_STRINGS) -c patternMatchData.c -o $@
375 help_topic.h help_data.h: ../doc/help.etx
376 (cd ..; $(MAKE) docs)
378 diff --quilt old/source/Makefile.dependencies new/source/Makefile.dependencies
379 --- old/source/Makefile.dependencies
380 +++ new/source/Makefile.dependencies
381 @@ -86,3 +86,14 @@ windowTitle.o: windowTitle.c windowTitle
382 preferences.h help.h help_topic.h ../util/prefFile.h ../util/misc.h \
383 ../util/DialogF.h ../util/utils.h ../util/fileUtils.h \
384 ../util/clearcase.h
385 +patternMatch.o: patternMatch.c regularExp.h \
386 + textBuf.h search.h window.h preferences.h highlight.h\
387 + patternMatch.h patternMatchData.h
388 +patternMatchData.o: patternMatchData.c ../util/DialogF.h ../util/misc.h \
389 + ../util/managedList.h regularExp.h textBuf.h nedit.h window.h \
390 + preferences.h help.h file.h textP.h patternMatch.h patternMatchData.h
391 +macro.o: patternMatch.h regularExp.h
392 +menu.o: patternMatchData.h
393 +preferences.o: patternMatchData.h
394 +search.o: patternMatch.h
395 +window.o: patternMatchData.h
396 diff --quilt old/source/highlightData.c new/source/highlightData.c
397 --- old/source/highlightData.c
398 +++ new/source/highlightData.c
399 @@ -551,7 +551,7 @@ static char *DefaultPatternSets[] = {
400 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\
401 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\
402 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\
403 - Built-in Subrs:\"<(?: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|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\
404 + Built-in Subrs:\"<(?: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|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\
405 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\
406 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\
407 Macro Hooks:\"<(?:(?:pre|post)_(?:open|save)|cursor_moved|modified|(?:losing_)?focus)_hook(?=\\s*\\()\":::Subroutine1::\n\
408 @@ -2346,8 +2346,9 @@ void EditHighlightPatterns(WindowInfo *w
409 XmNrightPosition, 99,
410 NULL);
412 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
413 HighlightDialog.lmPulldown = CreateLanguageModeMenu(lmForm, langModeCB,
414 - NULL);
415 + NULL, FALSE);
416 n = 0;
417 XtSetArg(args[n], XmNspacing, 0); n++;
418 XtSetArg(args[n], XmNmarginWidth, 0); n++;
419 @@ -2881,8 +2882,9 @@ void UpdateLanguageModeMenu(void)
420 return;
422 oldMenu = HighlightDialog.lmPulldown;
423 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
424 HighlightDialog.lmPulldown = CreateLanguageModeMenu(
425 - XtParent(XtParent(oldMenu)), langModeCB, NULL);
426 + XtParent(XtParent(oldMenu)), langModeCB, NULL, FALSE);
427 XtVaSetValues(XmOptionButtonGadget(HighlightDialog.lmOptMenu),
428 XmNsubMenuId, HighlightDialog.lmPulldown, NULL);
429 SetLangModeMenu(HighlightDialog.lmOptMenu, HighlightDialog.langModeName);
430 @@ -2941,6 +2943,9 @@ static void langModeCB(Widget w, XtPoint
432 SetLangModeMenu(HighlightDialog.lmOptMenu,
433 HighlightDialog.langModeName);
435 + freePatternSet(newPatSet);
437 return;
439 if (resp == 1)
440 @@ -3040,6 +3045,8 @@ static void restoreCB(Widget w, XtPointe
441 "patterns for language mode %s?", "Discard", "Cancel",
442 HighlightDialog.langModeName) == 2)
444 + freePatternSet(defaultPatSet);
446 return;
449 diff --quilt old/source/macro.c new/source/macro.c
450 --- old/source/macro.c
451 +++ new/source/macro.c
452 @@ -57,6 +57,8 @@ static const char CVSID[] = "$Id: macro.
453 #include "highlight.h"
454 #include "highlightData.h"
455 #include "rangeset.h"
456 +#include "patternMatch.h"
457 +#include "regularExp.h"
459 #include <stdio.h>
460 #include <stdlib.h>
461 @@ -297,8 +299,6 @@ static int incBackupMV(WindowInfo *windo
462 DataValue *result, char **errMsg);
463 static int showMatchingMV(WindowInfo *window, DataValue *argList, int nArgs,
464 DataValue *result, char **errMsg);
465 -static int matchSyntaxBasedMV(WindowInfo *window, DataValue *argList, int nArgs,
466 - DataValue *result, char **errMsg);
467 static int overTypeModeMV(WindowInfo *window, DataValue *argList, int nArgs,
468 DataValue *result, char **errMsg);
469 static int readOnlyMV(WindowInfo *window, DataValue *argList, int nArgs,
470 @@ -414,6 +414,10 @@ static int filenameDialogMS(WindowInfo*
471 static int callMS(WindowInfo *window, DataValue *argList,
472 int nArgs, DataValue *result, char **errMsg);
474 +/* Pattern Match Feature */
475 +static int getMatchingMS(WindowInfo *window, DataValue *argList, int nArgs,
476 + DataValue *result, char **errMsg);
478 /* Built-in subroutines and variables for the macro language */
479 static const BuiltInSubrName MacroSubrs[] = {
480 { "length", lengthMS },
481 @@ -474,6 +478,7 @@ static const BuiltInSubrName MacroSubrs[
482 { "get_style_at_pos", getStyleAtPosMS },
483 { "filename_dialog", filenameDialogMS },
484 { "call", callMS },
485 + { "get_matching", getMatchingMS },
486 { NULL, NULL } /* sentinel */
489 @@ -503,7 +508,6 @@ static const BuiltInSubrName SpecialVars
490 { "$make_backup_copy", makeBackupCopyMV },
491 { "$incremental_backup", incBackupMV },
492 { "$show_matching", showMatchingMV },
493 - { "$match_syntax_based", matchSyntaxBasedMV },
494 { "$overtype_mode", overTypeModeMV },
495 { "$read_only", readOnlyMV },
496 { "$locked", lockedMV },
497 @@ -4527,16 +4531,6 @@ static int showMatchingMV(WindowInfo *wi
498 return True;
501 -static int matchSyntaxBasedMV(WindowInfo *window, DataValue *argList, int nArgs,
502 - DataValue *result, char **errMsg)
504 - result->tag = INT_TAG;
505 - result->val.n = window->matchSyntaxBased ? 1 : 0;
506 - return True;
511 static int overTypeModeMV(WindowInfo *window, DataValue *argList, int nArgs,
512 DataValue *result, char **errMsg)
514 @@ -5944,6 +5938,93 @@ static int getPatternAtPosMS(WindowInfo
515 HighlightStyleOfCode(window, patCode), bufferPos);
519 +** Pattern Match Feature:
520 +** Find a matching pattern string related to the given position.
522 +** Syntax:
523 +** get_matching(position)
525 +** Returns info about matching pattern within an array. The array has
526 +** the following keys: "pos" (position of the first character of the
527 +** matching pattern), "len" (length of the matching pattern), "direction"
528 +** (direction where the matching pattern was found: "0" = forward;
529 +** "1" = backward). If no matching pattern was found, then array element
530 +** of "pos" holds "-1", "len" holds "0" and "direction" holds "-1".
533 +static int getMatchingMS(WindowInfo *window, DataValue *argList, int nArgs,
534 + DataValue *result, char **errMsg)
536 + int startPos;
537 + int matchPos, matchLen;
538 + int direction;
539 + textBuffer *buf = window->buffer;
540 + DataValue dv;
542 + /*
543 + * Perform syntax & semantic check
544 + */
545 + if (nArgs != 1 )
546 + return wrongNArgsErr(errMsg);
548 + if (!readIntArg(argList[0], &startPos, errMsg))
549 + return False;
551 + startPos ++;
553 + /*
554 + * do the search; provide default values, if search fails
555 + */
556 + if (!FindMatchingString(window, MT_MACRO, &startPos, 0, buf->length,
557 + &matchPos, &matchLen, &direction))
559 + matchPos = -1;
560 + matchLen = 0;
561 + direction = -1;
564 + /*
565 + * initialize array holding info about matching string
566 + */
567 + result->tag = ARRAY_TAG;
568 + result->val.arrayPtr = ArrayNew();
570 + /*
571 + * the following array entries will be integers
572 + */
573 + dv.tag = INT_TAG;
575 + /*
576 + * insert match position
577 + */
578 + dv.val.n = matchPos;
579 + if (!ArrayInsert(result, PERM_ALLOC_STR("pos"), &dv))
581 + M_ARRAY_INSERT_FAILURE();
584 + /*
585 + * insert length of matching pattern
586 + */
587 + dv.val.n = matchLen;
588 + if (!ArrayInsert(result, PERM_ALLOC_STR("len"), &dv))
590 + M_ARRAY_INSERT_FAILURE();
593 + /*
594 + * insert direction where the matching pattern was found
595 + */
596 + dv.val.n = direction;
597 + if (!ArrayInsert(result, PERM_ALLOC_STR("direction"), &dv))
599 + M_ARRAY_INSERT_FAILURE();
602 + return True;
605 static int wrongNArgsErr(char **errMsg)
607 *errMsg = "Wrong number of arguments to function %s";
608 diff --quilt old/source/menu.c new/source/menu.c
609 --- old/source/menu.c
610 +++ new/source/menu.c
611 @@ -49,6 +49,7 @@ static const char CVSID[] = "$Id: menu.c
612 #include "macro.h"
613 #include "highlight.h"
614 #include "highlightData.h"
615 +#include "patternMatchData.h"
616 #include "interpret.h"
617 #include "smartIndent.h"
618 #include "windowTitle.h"
619 @@ -133,7 +134,6 @@ static void backlightCharsCB(Widget w, W
620 static void showMatchingOffCB(Widget w, WindowInfo *window, caddr_t callData);
621 static void showMatchingDelimitCB(Widget w, WindowInfo *window, caddr_t callData);
622 static void showMatchingRangeCB(Widget w, WindowInfo *window, caddr_t callData);
623 -static void matchSyntaxBasedCB(Widget w, WindowInfo *window, caddr_t callData);
624 static void statsCB(Widget w, WindowInfo *window, caddr_t callData);
625 static void autoIndentOffDefCB(Widget w, WindowInfo *window, caddr_t callData);
626 static void autoIndentDefCB(Widget w, WindowInfo *window, caddr_t callData);
627 @@ -160,9 +160,9 @@ static void tabsDefCB(Widget w, WindowIn
628 static void showMatchingOffDefCB(Widget w, WindowInfo *window, caddr_t callData);
629 static void showMatchingDelimitDefCB(Widget w, WindowInfo *window, caddr_t callData);
630 static void showMatchingRangeDefCB(Widget w, WindowInfo *window, caddr_t callData);
631 -static void matchSyntaxBasedDefCB(Widget w, WindowInfo *window, caddr_t callData);
632 static void highlightOffDefCB(Widget w, WindowInfo *window, caddr_t callData);
633 static void highlightDefCB(Widget w, WindowInfo *window, caddr_t callData);
634 +static void matchPatternsDefCB(Widget w, WindowInfo *window, caddr_t callData);
635 static void backlightCharsDefCB(Widget w, WindowInfo *window, caddr_t callData);
636 static void fontDefCB(Widget w, WindowInfo *window, caddr_t callData);
637 static void colorDefCB(Widget w, WindowInfo *window, caddr_t callData);
638 @@ -409,8 +409,6 @@ static void setIncrementalBackupAP(Widge
639 Cardinal *nArgs);
640 static void setShowMatchingAP(Widget w, XEvent *event, String *args,
641 Cardinal *nArgs);
642 -static void setMatchSyntaxBasedAP(Widget w, XEvent *event, String *args,
643 - Cardinal *nArgs);
644 static void setOvertypeModeAP(Widget w, XEvent *event, String *args,
645 Cardinal *nArgs);
646 static void setLockedAP(Widget w, XEvent *event, String *args,
647 @@ -584,7 +582,6 @@ static XtActionsRec Actions[] = {
648 #endif
649 {"set_incremental_backup", setIncrementalBackupAP},
650 {"set_show_matching", setShowMatchingAP},
651 - {"set_match_syntax_based", setMatchSyntaxBasedAP},
652 {"set_overtype_mode", setOvertypeModeAP},
653 {"set_locked", setLockedAP},
654 {"set_transient", setTransientAP},
655 @@ -1030,9 +1027,8 @@ Widget CreateMenuBar(Widget parent, Wind
656 "range", "Range", 'R', showMatchingRangeDefCB, window,
657 GetPrefShowMatching() == FLASH_RANGE, SHORT);
658 createMenuSeparator(subSubPane, "sep", SHORT);
659 - window->matchSyntaxBasedDefItem = createMenuToggle(subSubPane,
660 - "matchSyntax", "Syntax Based", 'S', matchSyntaxBasedDefCB, window,
661 - GetPrefMatchSyntaxBased(), SHORT);
662 + createMenuItem(subSubPane, "matchPatterns", "Matching Patterns...",
663 + 'M', matchPatternsDefCB, window, FULL);
665 /* Show Cursorline */
666 window->showCursorlineItem = createMenuToggle(subPane,
667 @@ -1154,10 +1150,6 @@ Widget CreateMenuBar(Widget parent, Wind
668 window->showMatchingRangeItem = createMenuRadioToggle(subPane, "range",
669 "Range", 'R', showMatchingRangeCB, window,
670 window->showMatchingStyle == FLASH_RANGE, SHORT);
671 - createMenuSeparator(subPane, "sep", SHORT);
672 - window->matchSyntaxBasedItem = createMenuToggle(subPane, "matchSyntax",
673 - "Syntax Based", 'S', matchSyntaxBasedCB, window,
674 - window->matchSyntaxBased, SHORT);
676 #ifndef SGI_CUSTOM
677 createMenuSeparator(menuPane, "sep2", SHORT);
678 @@ -1689,24 +1681,6 @@ static void showMatchingRangeCB(Widget w
679 ((XmAnyCallbackStruct *)callData)->event, params, 1);
682 -static void matchSyntaxBasedCB(Widget w, WindowInfo *window, caddr_t callData)
684 - Widget menu = MENU_WIDGET(w);
686 - window = WidgetToWindow(menu);
688 -#ifdef SGI_CUSTOM
689 - if (shortPrefAskDefault(window->shell, w, "Match Syntax Based")) {
690 - matchSyntaxBasedDefCB(w, window, callData);
691 - SaveNEditPrefs(window->shell, GetPrefShortMenus());
693 -#endif
694 - HidePointerOnKeyedEvent(WidgetToWindow(menu)->lastFocus,
695 - ((XmAnyCallbackStruct *)callData)->event);
696 - XtCallActionProc(WidgetToWindow(menu)->lastFocus, "set_match_syntax_based",
697 - ((XmAnyCallbackStruct *)callData)->event, NULL, 0);
700 static void fontCB(Widget w, WindowInfo *window, caddr_t callData)
702 ChooseFonts(WidgetToWindow(MENU_WIDGET(w)), True);
703 @@ -2034,18 +2008,14 @@ static void showMatchingRangeDefCB(Widge
707 -static void matchSyntaxBasedDefCB(Widget w, WindowInfo *window, caddr_t callData)
708 +static void matchPatternsDefCB(Widget w, WindowInfo *window, caddr_t callData)
710 - WindowInfo *win;
712 - int state = XmToggleButtonGetState(w);
713 + Widget menu = MENU_WIDGET(w);
714 + WindowInfo *activeWindow = WidgetToWindow(menu);
716 - /* Set the preference and make the other windows' menus agree */
717 - SetPrefMatchSyntaxBased(state);
718 - for (win=WindowList; win!=NULL; win=win->next) {
719 - if (IsTopDocument(win))
720 - XmToggleButtonSetState(win->matchSyntaxBasedDefItem, state, False);
722 + HidePointerOnKeyedEvent(activeWindow->lastFocus,
723 + ((XmAnyCallbackStruct *)callData)->event);
724 + EditMatchPatterns(activeWindow);
727 static void backlightCharsDefCB(Widget w, WindowInfo *window, caddr_t callData)
728 @@ -4288,19 +4258,6 @@ static void setShowMatchingAP(Widget w,
732 -static void setMatchSyntaxBasedAP(Widget w, XEvent *event, String *args,
733 - Cardinal *nArgs)
735 - WindowInfo *window = WidgetToWindow(w);
736 - Boolean newState;
738 - ACTION_BOOL_PARAM_OR_TOGGLE(newState, *nArgs, args, window->matchSyntaxBased, "set_match_syntax_based");
740 - if (IsTopDocument(window))
741 - XmToggleButtonSetState(window->matchSyntaxBasedItem, newState, False);
742 - window->matchSyntaxBased = newState;
745 static void setOvertypeModeAP(Widget w, XEvent *event, String *args,
746 Cardinal *nArgs)
748 diff --quilt old/source/nedit.h new/source/nedit.h
749 --- old/source/nedit.h
750 +++ new/source/nedit.h
751 @@ -366,7 +366,6 @@ typedef struct _WindowInfo {
752 Widget showMatchingOffItem;
753 Widget showMatchingDelimitItem;
754 Widget showMatchingRangeItem;
755 - Widget matchSyntaxBasedItem;
756 Widget overtypeModeItem;
757 Widget highlightItem;
758 Widget windowMenuPane;
759 @@ -392,7 +391,6 @@ typedef struct _WindowInfo {
760 Widget showMatchingOffDefItem;
761 Widget showMatchingDelimitDefItem;
762 Widget showMatchingRangeDefItem;
763 - Widget matchSyntaxBasedDefItem;
764 Widget highlightOffDefItem;
765 Widget highlightDefItem;
766 Widget backlightCharsItem;
767 @@ -512,7 +510,6 @@ typedef struct _WindowInfo {
768 char showMatchingStyle; /* How to show matching parens:
769 NO_FLASH, FLASH_DELIMIT, or
770 FLASH_RANGE */
771 - char matchSyntaxBased; /* Use syntax info to show matching */
772 Boolean showStats; /* is stats line supposed to be shown */
773 Boolean showISearchLine; /* is incr. search line to be shown */
774 Boolean showLineNumbers; /* is the line number display shown */
775 @@ -558,6 +555,9 @@ typedef struct _WindowInfo {
776 Bool findLastRegexCase; /* idem, for regex mode in find dialog */
777 Bool findLastLiteralCase; /* idem, for literal mode */
779 + /* Pattern Match Feature */
780 + void *stringMatchTable; /* match pattern info related to this window */
782 #ifdef REPLACE_SCOPE
783 int replaceScope; /* Current scope for replace dialog */
784 Widget replaceScopeWinToggle; /* Scope for replace = window */
785 diff --quilt /dev/null new/source/patternMatch.c
786 --- /dev/null
787 +++ new/source/patternMatch.c
788 @@ -0,0 +1,2202 @@
789 +static const char CVSID[] = "$Id: patternMatch.c,v 1.4 2003/10/27 21:59:14 uleh Exp $";
790 +/*******************************************************************************
791 +* *
792 +* patternMatch.c -- Nirvana Editor pattern matching functions *
793 +* *
794 +* Copyright (C) 2003-2004, Uwe Lehnert *
795 +* *
796 +* This is free software; you can redistribute it and/or modify it under the *
797 +* terms of the GNU General Public License as published by the Free Software *
798 +* Foundation; either version 2 of the License, or (at your option) any later *
799 +* version. In addition, you may distribute versions of this program linked to *
800 +* Motif or Open Motif. See README for details. *
801 +* *
802 +* This software is distributed in the hope that it will be useful, but WITHOUT *
803 +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
804 +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
805 +* for more details. *
806 +* *
807 +* You should have received a copy of the GNU General Public License along with *
808 +* software; if not, write to the Free Software Foundation, Inc., 59 Temple *
809 +* Place, Suite 330, Boston, MA 02111-1307 USA *
810 +* *
811 +* Nirvana Text Editor *
812 +* October 27, 2004 *
813 +* *
814 +* Written by Uwe Lehnert *
815 +* *
816 +*******************************************************************************/
818 +#ifdef HAVE_CONFIG_H
819 +#include "../config.h"
820 +#endif
822 +#include <stdlib.h>
823 +#include <stdio.h>
824 +#include <limits.h>
825 +#include <string.h>
826 +#include <ctype.h>
828 +#ifdef VMS
829 +#include "../util/VMSparam.h"
830 +#else
831 +#ifndef __MVS__
832 +#include <sys/param.h>
833 +#endif
834 +#endif /*VMS*/
836 +#include "regularExp.h"
837 +#include "textBuf.h"
838 +#include "search.h"
839 +#include "window.h"
840 +#include "preferences.h"
841 +#include "highlight.h"
843 +#include "patternMatch.h"
844 +#include "patternMatchData.h"
846 +#ifdef HAVE_DEBUG_H
847 +#include "../debug.h"
848 +#endif
850 +#define MAX_NESTED_PATTERNS 100
852 +#define IGNORE_HIGHLIGHT_CODE -1
854 +typedef struct _SearchRegionInfo {
855 + WindowInfo *sriWindow;
856 + char *sriText;
857 + char sriPrevChar;
858 + char sriSuccChar;
859 + int sriStartOfTextPos;
860 +} SearchRegionInfo;
862 +typedef struct _FoundStringInfo {
863 + char *fsiStartPtr;
864 + char *fsiEndPtr;
865 + int fsiLength;
866 + char fsiPrevChar;
867 + char fsiSuccChar;
868 + const char *fsiDelimiters;
869 +} FoundStringInfo;
871 +typedef struct _BackRefInfo {
872 + int briAvailable;
873 + int briCaseInsensitive;
874 + char *briStartPtr[MAX_GLOBAL_BACK_REF_ID];
875 + char *briEndPtr[MAX_GLOBAL_BACK_REF_ID];
876 +} BackRefInfo;
878 +typedef struct _MatchingElementInfo {
879 + MatchPatternTableElement *meiElement;
880 + PatternReference meiPatRef;
881 + int meiDirection;
882 + int meiHighLightCode;
883 + int meiAbsStartPos;
884 + int meiLength;
885 + BackRefInfo meiBackRefInfo;
886 +} MatchingElementInfo;
888 +typedef struct _PatternStackElement {
889 + PatternReference psePatRef;
890 + int pseHighLightCode;
891 + BackRefInfo pseBackRefInfo;
892 +} PatternStackElement;
895 + * Prototypes of local functions
896 + */
897 +void adaptPatternPositions(
898 + MatchingType matchingType,
899 + int direction,
900 + int *charPos,
901 + int startPatternLength,
902 + int *matchPos,
903 + int matchedPatternLength);
905 +static int findMatchingStringElement(
906 + StringMatchTable *smTable,
907 + SearchRegionInfo *searchRegion,
908 + MatchingElementInfo *matchInfo,
909 + int *charPos,
910 + const char *delimiters);
912 +static PatternElementMonoInfo determineMonoPatInfo(
913 + WindowInfo *window,
914 + int patHighLightCode,
915 + int leftPos,
916 + int rightPos,
917 + PatternElementKind *patElementKind);
919 +static void assignBackRefInfo(
920 + StringPattern *strPat,
921 + BackRefInfo *backRefInfo);
922 +static int doesBackRefInfoMatch(
923 + BackRefInfo *backRefInfo1,
924 + BackRefInfo *backRefInfo2);
925 +static int compareBackRef(
926 + char *startPtr1,
927 + char *endPtr1,
928 + char *startPtr2,
929 + char *endPtr2,
930 + int caseInsensitive);
932 +static int doesPatternElementMatch(
933 + PatternElement *patElement,
934 + FoundStringInfo *foundStringInfo,
935 + BackRefInfo *backRefInfo);
936 +static int doesMPTableElementMatch(
937 + MatchPatternTableElement *element,
938 + FoundStringInfo *foundStringInfo,
939 + PatternElementKind *patternElementKind,
940 + int *patternElementIdx,
941 + BackRefInfo *backRefInfo);
942 +static int getPatternInfo(
943 + MatchPatternTable *table,
944 + FoundStringInfo *foundStringInfo,
945 + PatternReference *patRef,
946 + BackRefInfo *backRefInfo);
948 +static int isPartOfPattern(
949 + MatchPatternTable *table,
950 + int parentElementIdx,
951 + int childElementIdx,
952 + PatternElementKind patElementKind);
953 +static int isPartOfPatternElementSet(
954 + PatternElementSet *patElementSet,
955 + int patternElementIdx);
956 +static int isPartOfMiddlePatternElementSet(
957 + PatternElementSet *patElementSet,
958 + int patternElementIdx);
959 +static void considerNextPatternReference(
960 + MatchPatternTable *table,
961 + PatternReference *startPatRef,
962 + PatternReference nxtPatRef,
963 + int groupIdx);
965 +static int searchPatternForward(
966 + MatchPatternTable *table,
967 + regexp *compiledRE,
968 + SearchRegionInfo *searchRegion,
969 + const char *delimiters,
970 + int beginPos,
971 + int *matchEndPos,
972 + PatternReference *patRef,
973 + int *highLightCode,
974 + BackRefInfo *backRefInfo);
975 +static int searchPatternBackward(
976 + MatchPatternTable *table,
977 + regexp *compiledRE,
978 + SearchRegionInfo *searchRegion,
979 + const char *delimiters,
980 + int beginPos,
981 + PatternReference *patRef,
982 + int *highLightCode,
983 + int *matchedPatternLength,
984 + BackRefInfo *backRefInfo);
986 +static int parseStringElementForward(
987 + MatchingElementInfo *matchInfo,
988 + SearchRegionInfo *searchRegion,
989 + int relCharPos,
990 + int *matchPos,
991 + int *matchedPatternLength,
992 + const char *delimiters);
993 +static int findRelatedForwardPattern(
994 + StringMatchTable *table,
995 + SearchRegionInfo *searchRegion,
996 + const char *delimiters,
997 + PatternReference beginPatRef,
998 + int beginPatHighLightCode,
999 + BackRefInfo *beginPatBackRefInfo,
1000 + int beginPos,
1001 + int *matchEndPos);
1003 +static int parseStringElementBackward(
1004 + MatchingElementInfo *matchInfo,
1005 + SearchRegionInfo *searchRegion,
1006 + int relCharPos,
1007 + int *matchPos,
1008 + int *matchedPatternLength,
1009 + const char *delimiters);
1010 +static int findRelatedStartPattern(
1011 + StringMatchTable *table,
1012 + SearchRegionInfo *searchRegion,
1013 + const char *delimiters,
1014 + PatternReference beginPatRef,
1015 + int beginPatHighLightCode,
1016 + BackRefInfo *beginPatBackRefInfo,
1017 + int beginPos,
1018 + int *matchedPatternLength);
1019 +static void considerStackPatReference(
1020 + PatternElementSet *patSet,
1021 + int stackElementIdx,
1022 + int *foundElementIdx);
1024 +static int getPatternLocatedAtPos(
1025 + regexp *usedPatRE,
1026 + MatchPatternTable *table,
1027 + SearchRegionInfo *searchRegion,
1028 + int *relBeginPos,
1029 + MatchingElementInfo *matchInfo,
1030 + const char *delimiters);
1031 +static int getMatchedElementInfo(
1032 + WindowInfo *window,
1033 + MatchPatternTable *table,
1034 + FoundStringInfo *foundStringInfo,
1035 + MatchingElementInfo *matchInfo);
1037 +static PatternElement *getPatternOfReference(
1038 + MatchPatternTable *table,
1039 + PatternReference patRef);
1041 +#ifdef DEBUG_FIND
1042 +static char *getPatternForDebug(
1043 + MatchPatternTable *table,
1044 + PatternReference patRef );
1045 +static char *patElemKindToString(
1046 + PatternElementKind patElemKind);
1047 +static void printFoundStringForDebug(
1048 + WindowInfo *window,
1049 + int absStartPos,
1050 + int length);
1051 +#endif
1054 +** Try to find a matching pattern string related to the given "charPos"
1055 +** inside the given range (defined by startLimit & endLimit).
1056 +** Determine the matching position & the match pattern length (depending
1057 +** on given matchingType), if a matching pattern was found.
1058 +** Returns true, if a matching pattern string was found.
1060 +int FindMatchingString(
1061 + WindowInfo *window,
1062 + MatchingType matchingType,
1063 + int *charPos,
1064 + int startLimit,
1065 + int endLimit,
1066 + int *matchPos,
1067 + int *matchedPatternLength,
1068 + int *direction)
1070 + StringMatchTable *smTable = (StringMatchTable *)window->stringMatchTable;
1071 + const char *delimiters;
1072 + SearchRegionInfo searchRegion;
1073 + MatchingElementInfo matchInfo;
1074 + int matchingPatternFound = FALSE;
1075 + int relCharPos;
1077 + if (smTable == NULL || smTable->smtAllPatRE == NULL)
1079 + /*
1080 + * No match pattern table available:
1081 + */
1082 + return FALSE;
1085 + /*
1086 + * Get delimiters related to window
1087 + */
1088 + delimiters = GetWindowDelimiters(window);
1089 + if (delimiters == NULL)
1090 + delimiters = GetPrefDelimiters();
1092 + /*
1093 + * Select the start pattern reg. exp. to use
1094 + */
1095 + if (matchingType == MT_FLASH_RANGE ||
1096 + matchingType == MT_FLASH_DELIMIT)
1098 + smTable->smtUsedPatRE = smTable->smtFlashPatRE;
1100 + else
1102 + smTable->smtUsedPatRE = smTable->smtAllPatRE;
1105 + /*
1106 + * Get a copy of the text buffer area to parse
1107 + */
1108 + searchRegion.sriWindow = window;
1109 + searchRegion.sriText = BufGetRange(window->buffer, startLimit, endLimit);
1110 + searchRegion.sriPrevChar = BufGetCharacter(window->buffer, startLimit - 1);
1111 + searchRegion.sriSuccChar = BufGetCharacter(window->buffer, endLimit);
1112 + searchRegion.sriStartOfTextPos = startLimit;
1114 + relCharPos = *charPos - startLimit;
1116 + /*
1117 + * Try to find a matching pattern string using string match table
1118 + * of window
1119 + */
1120 + if (findMatchingStringElement(
1121 + smTable,
1122 + &searchRegion,
1123 + &matchInfo,
1124 + &relCharPos,
1125 + delimiters ))
1127 +#ifdef DEBUG_FIND
1128 + printf("--- Start at : ");
1129 + printFoundStringForDebug(
1130 + window,
1131 + matchInfo.meiAbsStartPos,
1132 + matchInfo.meiLength);
1133 + printf(" ---\n");
1134 +#endif
1135 + if (matchInfo.meiDirection == SEARCH_FORWARD)
1137 + matchingPatternFound =
1138 + parseStringElementForward(
1139 + &matchInfo,
1140 + &searchRegion,
1141 + relCharPos,
1142 + matchPos,
1143 + matchedPatternLength,
1144 + delimiters );
1146 + else
1148 + matchingPatternFound =
1149 + parseStringElementBackward(
1150 + &matchInfo,
1151 + &searchRegion,
1152 + relCharPos,
1153 + matchPos,
1154 + matchedPatternLength,
1155 + delimiters );
1158 + if (matchingPatternFound)
1160 + /*
1161 + * Calc. abs. start char pos. (may have been changed if
1162 + * cursor was located inside a string pattern). Adapt
1163 + * pattern positions depending on matchingType.
1164 + */
1165 + *charPos = relCharPos + startLimit;
1166 + *direction = matchInfo.meiDirection;
1168 + adaptPatternPositions(
1169 + matchingType,
1170 + matchInfo.meiDirection,
1171 + charPos,
1172 + matchInfo.meiLength,
1173 + matchPos,
1174 + *matchedPatternLength);
1178 + XtFree(searchRegion.sriText);
1180 + return matchingPatternFound;
1184 +** Adapt match pattern position / start position depending on the
1185 +** given matching type.
1187 +void adaptPatternPositions(
1188 + MatchingType matchingType,
1189 + int direction,
1190 + int *charPos,
1191 + int startPatternLength,
1192 + int *matchPos,
1193 + int matchedPatternLength)
1195 + switch (matchingType)
1197 + case MT_FLASH_DELIMIT:
1198 + case MT_MACRO:
1199 + if (direction == SEARCH_FORWARD)
1201 + (*matchPos) -= matchedPatternLength - 1;
1203 + break;
1205 + case MT_FLASH_RANGE:
1206 + case MT_SELECT:
1207 + if (direction == SEARCH_FORWARD)
1209 + (*charPos) -= startPatternLength;
1211 + else
1213 + (*charPos) --;
1215 + break;
1217 + case MT_GOTO:
1218 + if (direction == SEARCH_FORWARD)
1220 + (*matchPos) ++;
1222 + else
1224 + (*matchPos) += matchedPatternLength;
1226 + break;
1231 +** Try to find a string pattern at given buffer position 'charPos'.
1232 +** A string pattern is found, if pattern is located before 'charPos' or
1233 +** 'charPos' is located within a pattern.
1234 +** If a string pattern is found, then search direction and string pattern
1235 +** reference / properties are determined.
1236 +** Returns true, if a string pattern was found.
1238 +static int findMatchingStringElement(
1239 + StringMatchTable *smTable,
1240 + SearchRegionInfo *searchRegion,
1241 + MatchingElementInfo *matchInfo,
1242 + int *charPos,
1243 + const char *delimiters)
1245 + if (getPatternLocatedAtPos(
1246 + smTable->smtUsedPatRE,
1247 + smTable->smtAllPatterns,
1248 + searchRegion,
1249 + charPos,
1250 + matchInfo,
1251 + delimiters))
1253 + /*
1254 + * Pattern found -> define search direction:
1255 + * - START & MIDDLE pattern: matching pattern is searched in
1256 + * forward direction
1257 + * - END pattern: matching pattern is searched in backward
1258 + * direction
1259 + */
1260 + if (matchInfo->meiPatRef.prKind == PEK_END)
1261 + matchInfo->meiDirection = SEARCH_BACKWARD;
1262 + else
1263 + matchInfo->meiDirection = SEARCH_FORWARD;
1265 + return TRUE;
1268 + return FALSE;
1272 +** Return mono pattern info depending on highlight codes
1273 +** of left / right side of string pattern. Update pattern
1274 +** kind if applicable.
1276 +static PatternElementMonoInfo determineMonoPatInfo(
1277 + WindowInfo *window,
1278 + int patHighLightCode,
1279 + int leftPos,
1280 + int rightPos,
1281 + PatternElementKind *patElementKind)
1283 + int leftSideHasSameHC;
1284 + int rightSideHasSameHC;
1286 + /*
1287 + * Determine, if left side holds same highlight code than
1288 + * found string pattern
1289 + */
1290 + if (leftPos >= 0)
1291 + leftSideHasSameHC =
1292 + (HighlightCodeOfPos(window, leftPos) == patHighLightCode);
1293 + else
1294 + leftSideHasSameHC = FALSE;
1296 + /*
1297 + * Determine, if right side holds same highlight code than
1298 + * found string pattern
1299 + */
1300 + if (rightPos < window->buffer->length)
1301 + rightSideHasSameHC =
1302 + (HighlightCodeOfPos(window, rightPos) == patHighLightCode);
1303 + else
1304 + rightSideHasSameHC = FALSE;
1306 + if ((rightSideHasSameHC && leftSideHasSameHC) ||
1307 + (!rightSideHasSameHC && !leftSideHasSameHC))
1309 + return PEMI_MONO_AMBIGUOUS_SYNTAX;
1311 + else if (leftSideHasSameHC)
1313 + *patElementKind = PEK_END;
1314 + return PEMI_MONO_DEFINITE_SYNTAX;
1316 + else
1318 + *patElementKind = PEK_START;
1319 + return PEMI_MONO_DEFINITE_SYNTAX;
1324 +** Get backref info out of found string pattern and
1325 +** put it into given backRefInfo.
1327 +static void assignBackRefInfo(
1328 + StringPattern *strPat,
1329 + BackRefInfo *backRefInfo)
1331 + int i;
1332 + int localId;
1333 + regexp *patRE = strPat->spTextRE;
1335 + backRefInfo->briAvailable = FALSE;
1336 + backRefInfo->briCaseInsensitive = strPat->spCaseInsensitive;
1338 + for (i=0; i<MAX_GLOBAL_BACK_REF_ID; i++)
1340 + localId = strPat->spGlobalToLocalBackRef[i];
1342 + if (localId != NO_LOCAL_BACK_REF_ID)
1344 + backRefInfo->briAvailable = TRUE;
1346 + backRefInfo->briStartPtr[i] = patRE->startp[localId];
1347 + backRefInfo->briEndPtr[i] = patRE->endp[localId];
1349 + else
1351 + backRefInfo->briStartPtr[i] = NULL;
1352 + backRefInfo->briEndPtr[i] = NULL;
1358 +** Check, if given backref infos match.
1359 +** Returns true, if backref infos match.
1361 +static int doesBackRefInfoMatch(
1362 + BackRefInfo *backRefInfo1,
1363 + BackRefInfo *backRefInfo2)
1365 + int i;
1367 + /*
1368 + * if min. one string pattern doesn't hold backref info, then nothing
1369 + * could be compared -> both string pattern are matching.
1370 + */
1371 + if (!backRefInfo1->briAvailable || !backRefInfo2->briAvailable)
1372 + return TRUE;
1374 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
1376 + if (!compareBackRef(
1377 + backRefInfo1->briStartPtr[i],
1378 + backRefInfo1->briEndPtr[i],
1379 + backRefInfo2->briStartPtr[i],
1380 + backRefInfo2->briEndPtr[i],
1381 + backRefInfo1->briCaseInsensitive || backRefInfo2->briCaseInsensitive))
1383 + return FALSE;
1387 + return TRUE;
1391 +** Compares two backref content.
1392 +** Returns true, if backref contents match.
1394 +static int compareBackRef(
1395 + char *startPtr1,
1396 + char *endPtr1,
1397 + char *startPtr2,
1398 + char *endPtr2,
1399 + int caseInsensitive)
1401 + char *s1;
1402 + char *s2;
1404 + if (startPtr1 == NULL && startPtr2 == NULL)
1405 + return TRUE;
1407 + if (startPtr1 == NULL || startPtr2 == NULL)
1408 + return FALSE;
1410 + if ((endPtr1 - startPtr1) != (endPtr2 - startPtr2))
1411 + return FALSE;
1413 + s1 = startPtr1;
1414 + s2 = startPtr2;
1416 + if (caseInsensitive)
1418 + while (s1 != endPtr1)
1420 + if (tolower((unsigned char)*s1++) != tolower((unsigned char)*s2++))
1421 + return FALSE;
1424 + else
1426 + while (s1 != endPtr1)
1428 + if (*s1++ != *s2++)
1429 + return FALSE;
1432 + return TRUE;
1436 +** Verify if given pattern element is located between given
1437 +** start / end pointer of "foundStringInfo". Assign backreference
1438 +** information, if pattern element matches.
1439 +** Returns true, if given pattern element matches.
1441 +static int doesPatternElementMatch(
1442 + PatternElement *patElement,
1443 + FoundStringInfo *foundStringInfo,
1444 + BackRefInfo *backRefInfo)
1446 + char *s;
1447 + char *p;
1448 + StringPattern *strPat;
1449 + int elementMatch;
1451 + switch (patElement->peType)
1453 + case PET_SINGLE:
1454 + strPat = &patElement->peVal.peuSingle;
1455 + break;
1456 + case PET_MULTIPLE:
1457 + strPat = &patElement->peVal.peuMulti.mpStringPattern;
1458 + break;
1459 + default:
1460 + return FALSE;
1463 + if (strPat->spRegularExpression)
1465 + /*
1466 + * check reg. expression:
1467 + */
1468 + elementMatch =
1469 + ExecRE(
1470 + strPat->spTextRE,
1471 + foundStringInfo->fsiStartPtr,
1472 + foundStringInfo->fsiEndPtr,
1473 + FALSE,
1474 + foundStringInfo->fsiPrevChar,
1475 + foundStringInfo->fsiSuccChar,
1476 + foundStringInfo->fsiDelimiters,
1477 + NULL,
1478 + NULL);
1480 + if (elementMatch)
1481 + assignBackRefInfo(strPat, backRefInfo);
1483 + return elementMatch;
1485 + else
1487 + backRefInfo->briAvailable = FALSE;
1489 + /*
1490 + * check literal string:
1491 + */
1492 + p = strPat->spText;
1494 + /*
1495 + * if length of found string is different from length of
1496 + * given string pattern, then there is no match.
1497 + */
1498 + if (strPat->spLength != foundStringInfo->fsiLength)
1499 + return FALSE;
1501 + s = foundStringInfo->fsiStartPtr;
1503 + if (strPat->spCaseInsensitive)
1505 + while (s != foundStringInfo->fsiEndPtr)
1507 + if (tolower((unsigned char)*s++) != *p++)
1508 + return FALSE;
1511 + else
1513 + while (s != foundStringInfo->fsiEndPtr)
1515 + if (*s++ != *p++)
1516 + return FALSE;
1521 + return TRUE;
1525 +** Verify if a pattern element of given MatchPatternTableElement is
1526 +** located between given start / end pointer of "foundStringInfo".
1527 +** Returns true, if so.
1529 +static int doesMPTableElementMatch(
1530 + MatchPatternTableElement *element,
1531 + FoundStringInfo *foundStringInfo,
1532 + PatternElementKind *patternElementKind,
1533 + int *patternElementIdx,
1534 + BackRefInfo *backRefInfo)
1536 + int i;
1538 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i ++)
1540 + if (doesPatternElementMatch(
1541 + element->mpteAll.pesPattern[i],
1542 + foundStringInfo,
1543 + backRefInfo))
1545 + *patternElementKind = element->mpteAll.pesPattern[i]->peKind;
1546 + *patternElementIdx = i;
1548 + return TRUE;
1552 + return FALSE;
1556 +** Determine the pattern element of given MatchPatternTable, which is
1557 +** located between given start / end pointer of "foundStringInfo".
1558 +** Setup related pattern element reference.
1559 +** Returns true, if a pattern element was found.
1561 +static int getPatternInfo(
1562 + MatchPatternTable *table,
1563 + FoundStringInfo *foundStringInfo,
1564 + PatternReference *patRef,
1565 + BackRefInfo *backRefInfo)
1567 + int i;
1569 + for (i=0; i<table->mptNumberOfElements; i++)
1571 + if (doesMPTableElementMatch(
1572 + table->mptElements[i],
1573 + foundStringInfo,
1574 + &patRef->prKind,
1575 + &patRef->prPatternIdx,
1576 + backRefInfo))
1578 + patRef->prElementIdx = i;
1580 + return TRUE;
1584 + /*
1585 + * Should never been reached !
1586 + */
1587 + patRef->prElementIdx = NO_ELEMENT_IDX;
1588 + patRef->prKind = PEK_UNKNOWN;
1589 + patRef->prPatternIdx = NO_PATTERN_IDX;
1591 + return FALSE;
1595 +** Check, if given child pattern element is part of given
1596 +** parent pattern element.
1597 +** Returns true, if child is part of parent.
1599 +static int isPartOfPattern(
1600 + MatchPatternTable *table,
1601 + int parentElementIdx,
1602 + int childElementIdx,
1603 + PatternElementKind patElementKind)
1605 + MatchPatternTableElement *parent = table->mptElements[parentElementIdx];
1606 + MatchPatternTableElement *child = table->mptElements[childElementIdx];
1608 + if (childElementIdx == parentElementIdx)
1609 + return TRUE;
1611 + if (patElementKind == PEK_START)
1613 + if (isPartOfPatternElementSet(&parent->mpteStart, childElementIdx))
1614 + return TRUE;
1616 + return( isPartOfPatternElementSet(&child->mpteStart, parentElementIdx) );
1618 + else if (patElementKind == PEK_END)
1620 + if (isPartOfPatternElementSet(&parent->mpteEnd, childElementIdx))
1621 + return TRUE;
1623 + return( isPartOfPatternElementSet(&child->mpteEnd, parentElementIdx) );
1625 + else
1627 + /*
1628 + * Given child pattern element is middle pattern: the given pattern element
1629 + * is part of parent pattern, if it's a reference of a middle pattern
1630 + */
1631 + if (isPartOfMiddlePatternElementSet(&parent->mpteMiddle, childElementIdx))
1632 + return TRUE;
1634 + return( isPartOfMiddlePatternElementSet(&child->mpteMiddle, parentElementIdx) );
1639 +** Check, if given pattern element is part of given pattern element set.
1640 +** Returns true, if so.
1642 +static int isPartOfPatternElementSet(
1643 + PatternElementSet *patElementSet,
1644 + int patternElementIdx)
1646 + PatternElement *patElement;
1647 + int i;
1649 + for (i=0; i<patElementSet->pesNumberOfPattern; i++)
1651 + if (patElementSet->pesPattern[i]->peType == PET_REFERENCE)
1653 + patElement = patElementSet->pesPattern[i];
1655 + if (patElement->peVal.peuRef.prElementIdx == patternElementIdx)
1657 + return TRUE;
1662 + return FALSE;
1666 +** Verify, if given pattern element is part of middle pattern set.
1667 +** That's the case, if an element of the pattern set is reference
1668 +** of a middle pattern, which fits to given pattern element.
1669 +** Returns true, if pattern element is part of middle pattern set.
1670 + */
1671 +static int isPartOfMiddlePatternElementSet(
1672 + PatternElementSet *patElementSet,
1673 + int patternElementIdx)
1675 + PatternElement *patElement;
1676 + int i;
1678 + for (i=0; i<patElementSet->pesNumberOfPattern; i++)
1680 + if (patElementSet->pesPattern[i]->peType == PET_REFERENCE)
1682 + patElement = patElementSet->pesPattern[i];
1684 + if (patElement->peVal.peuRef.prElementIdx == patternElementIdx &&
1685 + patElement->peKind == PEK_MIDDLE)
1687 + return TRUE;
1692 + return FALSE;
1696 +** Update start pattern reference depending on next pattern located
1697 +** after start pattern.
1699 +static void considerNextPatternReference(
1700 + MatchPatternTable *table,
1701 + PatternReference *startPatRef,
1702 + PatternReference nxtPatRef,
1703 + int groupIdx)
1705 + MatchPatternTableElement *tabElement;
1706 + PatternElement *startPat;
1707 + MultiPattern *multiStartPat;
1708 + PatternReference patRef;
1709 + int i;
1711 + /*
1712 + * startPatRef needs no adaption, if element index of start pattern
1713 + * and next pattern are equal (i.e. start and next pattern belong
1714 + * to same pattern element).
1715 + */
1716 + if (startPatRef->prElementIdx == nxtPatRef.prElementIdx)
1717 + return;
1719 + /*
1720 + * Verify, if start pattern belongs to multiple pattern elements
1721 + * (like "ELSE .. FI" & "ELSE .. ESAC").
1722 + */
1723 + startPat = getPatternOfReference( table, *startPatRef );
1725 + if (startPat->peType == PET_MULTIPLE)
1727 + /*
1728 + * Check, if next pattern fits to one of the references of
1729 + * the start multi pattern. If so: adapt start pattern reference.
1730 + */
1731 + multiStartPat = &startPat->peVal.peuMulti;
1733 + for (i=0; i<multiStartPat->mpNumberOfReferences; i ++)
1735 + patRef = multiStartPat->mpRefList[i];
1736 + tabElement = table->mptElements[patRef.prElementIdx];
1738 + if (nxtPatRef.prElementIdx == patRef.prElementIdx &&
1739 + tabElement->mpteGroup == groupIdx)
1741 + *startPatRef = patRef;
1742 + return;
1749 +** Search for a string pattern in forward direction, starting at
1750 +** given beginPos. Determine related pattern reference of a found
1751 +** string pattern.
1752 +** Returns true, if a next string pattern was found.
1754 +static int searchPatternForward(
1755 + MatchPatternTable *table,
1756 + regexp *compiledRE,
1757 + SearchRegionInfo *searchRegion,
1758 + const char *delimiters,
1759 + int beginPos,
1760 + int *matchEndPos,
1761 + PatternReference *patRef,
1762 + int *highLightCode,
1763 + BackRefInfo *backRefInfo)
1765 + FoundStringInfo foundStringInfo;
1766 + int matchStartPos;
1767 + int absMatchStartPos;
1768 + MatchPatternTableElement *matchedElement;
1770 + *matchEndPos = -1;
1772 + patRef->prElementIdx = NO_ELEMENT_IDX;
1773 + patRef->prKind = PEK_UNKNOWN;
1774 + patRef->prPatternIdx = NO_PATTERN_IDX;
1776 + *highLightCode = IGNORE_HIGHLIGHT_CODE;
1778 + if (ExecRE(
1779 + compiledRE,
1780 + searchRegion->sriText + beginPos,
1781 + NULL,
1782 + FALSE,
1783 + beginPos==0 ? searchRegion->sriPrevChar : searchRegion->sriText[beginPos-1],
1784 + searchRegion->sriSuccChar,
1785 + delimiters,
1786 + searchRegion->sriText,
1787 + NULL))
1789 + foundStringInfo.fsiStartPtr = compiledRE->startp[0];
1790 + foundStringInfo.fsiEndPtr = compiledRE->endp[0];
1791 + foundStringInfo.fsiLength =
1792 + foundStringInfo.fsiEndPtr - foundStringInfo.fsiStartPtr;
1794 + foundStringInfo.fsiPrevChar =
1795 + foundStringInfo.fsiStartPtr == searchRegion->sriText ?
1796 + searchRegion->sriPrevChar : *(foundStringInfo.fsiStartPtr - 1);
1798 + foundStringInfo.fsiSuccChar =
1799 + *(foundStringInfo.fsiEndPtr) == '\0' ?
1800 + searchRegion->sriSuccChar : *(foundStringInfo.fsiEndPtr);
1802 + foundStringInfo.fsiDelimiters = delimiters;
1804 + if (getPatternInfo(
1805 + table,
1806 + &foundStringInfo,
1807 + patRef,
1808 + backRefInfo))
1810 + /*
1811 + * Next string pattern was found in forward direction and
1812 + * a pattern reference could be assigned to: calculate
1813 + * relative & absolute match positions.
1814 + */
1815 + matchStartPos = foundStringInfo.fsiStartPtr - searchRegion->sriText;
1816 + *matchEndPos = foundStringInfo.fsiEndPtr - searchRegion->sriText;
1818 + absMatchStartPos = matchStartPos + searchRegion->sriStartOfTextPos;
1820 + matchedElement = table->mptElements[patRef->prElementIdx];
1822 + /*
1823 + * get highlight code of found string pattern, if applicable
1824 + */
1825 + if (!matchedElement->mpteIgnoreHighLightInfo)
1827 + *highLightCode =
1828 + HighlightCodeOfPos(searchRegion->sriWindow, absMatchStartPos);
1831 + /*
1832 + * setup mono pattern info of found string pattern
1833 + */
1834 + if (matchedElement->mpteIsMonoPattern)
1836 + if (matchedElement->mpteIgnoreHighLightInfo)
1838 + patRef->prMonoInfo = PEMI_MONO_NOT_SYNTAX_BASED;
1840 + else
1842 + /*
1843 + * determine mono pattern info depending on highLightCodes
1844 + * before / after found string pattern.
1845 + */
1846 + patRef->prMonoInfo =
1847 + determineMonoPatInfo(
1848 + searchRegion->sriWindow,
1849 + *highLightCode,
1850 + absMatchStartPos - 1,
1851 + *matchEndPos + searchRegion->sriStartOfTextPos,
1852 + &patRef->prKind);
1855 + else
1857 + patRef->prMonoInfo = PEMI_NOT_MONO;
1860 + return matchStartPos;
1862 + else
1864 + /*
1865 + * Found string can't be assigned to a pattern element
1866 + * (should never occur).
1867 + */
1868 + return -1;
1871 + else
1873 + /*
1874 + * No next string pattern is found in forward direction.
1875 + */
1876 + return -1;
1881 +** Search for a string pattern in backward direction, starting at
1882 +** given beginPos. Determine related pattern reference of a found
1883 +** string pattern.
1884 +** Returns true, if a next string pattern was found.
1886 +static int searchPatternBackward(
1887 + MatchPatternTable *table,
1888 + regexp *compiledRE,
1889 + SearchRegionInfo *searchRegion,
1890 + const char *delimiters,
1891 + int beginPos,
1892 + PatternReference *patRef,
1893 + int *highLightCode,
1894 + int *matchedPatternLength,
1895 + BackRefInfo *backRefInfo)
1897 + FoundStringInfo foundStringInfo;
1898 + int matchStartPos;
1899 + int absMatchStartPos;
1900 + MatchPatternTableElement *matchedElement;
1902 + patRef->prElementIdx = NO_ELEMENT_IDX;
1903 + patRef->prKind = PEK_UNKNOWN;
1904 + patRef->prPatternIdx = NO_PATTERN_IDX;
1906 + *highLightCode = IGNORE_HIGHLIGHT_CODE;
1908 + if (ExecRE(
1909 + compiledRE,
1910 + searchRegion->sriText,
1911 + searchRegion->sriText + beginPos,
1912 + TRUE,
1913 + searchRegion->sriPrevChar,
1914 + searchRegion->sriText[beginPos] == '\0' ?
1915 + searchRegion->sriSuccChar : searchRegion->sriText[beginPos + 1],
1916 + delimiters,
1917 + searchRegion->sriText,
1918 + NULL))
1920 + foundStringInfo.fsiStartPtr = compiledRE->startp[0];
1921 + foundStringInfo.fsiEndPtr = compiledRE->endp[0];
1922 + foundStringInfo.fsiLength =
1923 + foundStringInfo.fsiEndPtr - foundStringInfo.fsiStartPtr;
1925 + foundStringInfo.fsiPrevChar =
1926 + foundStringInfo.fsiStartPtr == searchRegion->sriText ?
1927 + searchRegion->sriPrevChar : *(foundStringInfo.fsiStartPtr - 1);
1929 + foundStringInfo.fsiSuccChar =
1930 + *(foundStringInfo.fsiEndPtr) == '\0' ?
1931 + searchRegion->sriSuccChar : *(foundStringInfo.fsiEndPtr);
1933 + foundStringInfo.fsiDelimiters = delimiters;
1935 + if (getPatternInfo(
1936 + table,
1937 + &foundStringInfo,
1938 + patRef,
1939 + backRefInfo))
1941 + /*
1942 + * Next string pattern was found in backward direction and
1943 + * a pattern reference could be assigned to: calculate
1944 + * relative & absolute match positions.
1945 + */
1946 + matchStartPos = foundStringInfo.fsiStartPtr - searchRegion->sriText;
1947 + *matchedPatternLength = foundStringInfo.fsiLength;
1949 + absMatchStartPos = matchStartPos + searchRegion->sriStartOfTextPos;
1951 + matchedElement = table->mptElements[patRef->prElementIdx];
1953 + /*
1954 + * get highlight code of found string pattern, if applicable
1955 + */
1956 + if (!matchedElement->mpteIgnoreHighLightInfo)
1958 + *highLightCode =
1959 + HighlightCodeOfPos(searchRegion->sriWindow, absMatchStartPos);
1962 + /*
1963 + * setup mono pattern info of found string pattern
1964 + */
1965 + if (matchedElement->mpteIsMonoPattern)
1967 + if (matchedElement->mpteIgnoreHighLightInfo)
1969 + patRef->prMonoInfo = PEMI_MONO_NOT_SYNTAX_BASED;
1971 + else
1973 + /*
1974 + * determine mono pattern info depending on highLightCodes
1975 + * before / after found string pattern.
1976 + */
1977 + patRef->prMonoInfo =
1978 + determineMonoPatInfo(
1979 + searchRegion->sriWindow,
1980 + *highLightCode,
1981 + absMatchStartPos - 1,
1982 + absMatchStartPos + *matchedPatternLength,
1983 + &patRef->prKind);
1986 + else
1988 + patRef->prMonoInfo = PEMI_NOT_MONO;
1991 + return matchStartPos;
1993 + else
1995 + /*
1996 + * Found string can't be assigned to a pattern element
1997 + * (should never occur).
1998 + */
1999 + return -1;
2002 + else
2004 + /*
2005 + * No next string pattern is found in backward direction.
2006 + */
2007 + return -1;
2012 +** Find matching pattern related to given pattern (stored in
2013 +** 'matchInfo') in forward direction by considering the rules stored in
2014 +** string match table of given window. Determine match position (= abs.
2015 +** pos. of last character of matching string) and length of matching
2016 +** string. If a mono matching pattern couldn't be found in forward
2017 +** direction, then try finding it in backward direction (if found in
2018 +** backward direction, then match position indicates the 1st char. of
2019 +** matching string).
2020 +** Returns true, if a matching pattern was found.
2022 +static int parseStringElementForward(
2023 + MatchingElementInfo *matchInfo,
2024 + SearchRegionInfo *searchRegion,
2025 + int relCharPos,
2026 + int *matchPos,
2027 + int *matchedPatternLength,
2028 + const char *delimiters)
2030 + StringMatchTable *smTable =
2031 + (StringMatchTable *)searchRegion->sriWindow->stringMatchTable;
2032 + MatchPatternTableElement *matchElement = matchInfo->meiElement;
2033 + int beginPos = relCharPos;
2034 + int endStartPos;
2035 + int startStartPos;
2036 + int endEndPos;
2037 + int matchingPatternFound = FALSE;
2039 + /*
2040 + * Find matching pattern within text buffer area to parse in
2041 + * forward direction.
2042 + */
2043 + endStartPos =
2044 + findRelatedForwardPattern(
2045 + smTable,
2046 + searchRegion,
2047 + delimiters,
2048 + matchInfo->meiPatRef,
2049 + matchInfo->meiHighLightCode,
2050 + &matchInfo->meiBackRefInfo,
2051 + beginPos,
2052 + &endEndPos);
2054 + if (endEndPos != -1)
2056 + *matchPos = endEndPos - 1 + searchRegion->sriStartOfTextPos;
2057 + *matchedPatternLength = endEndPos - endStartPos;
2059 + matchingPatternFound = TRUE;
2061 + else if (matchElement->mpteIsMonoPattern)
2063 + /*
2064 + * mono pattern: forward find fails -> try backward direction.
2065 + * Calc. relative position of 1st char. before found string pattern.
2066 + */
2067 + beginPos = beginPos - matchInfo->meiLength - 1;
2069 + if (beginPos > 0)
2071 + startStartPos =
2072 + findRelatedStartPattern(
2073 + smTable,
2074 + searchRegion,
2075 + delimiters,
2076 + matchInfo->meiPatRef,
2077 + matchInfo->meiHighLightCode,
2078 + &matchInfo->meiBackRefInfo,
2079 + beginPos,
2080 + matchedPatternLength);
2082 + if (startStartPos != -1)
2084 + matchInfo->meiDirection = SEARCH_BACKWARD;
2086 + *matchPos = startStartPos + searchRegion->sriStartOfTextPos;
2088 + matchingPatternFound = TRUE;
2093 + return matchingPatternFound;
2097 +** Find matching pattern related to given begin pattern reference
2098 +** in forward direction by considering the rules stored in given
2099 +** string match table. Determine match position (= relative
2100 +** pos. of last character of matching string).
2101 +** Returns -1, if no matching pattern was found. Else the relative
2102 +** position of 1st char. of matching string is returned.
2104 +static int findRelatedForwardPattern(
2105 + StringMatchTable *table,
2106 + SearchRegionInfo *searchRegion,
2107 + const char *delimiters,
2108 + PatternReference beginPatRef,
2109 + int beginPatHighLightCode,
2110 + BackRefInfo *beginPatBackRefInfo,
2111 + int beginPos,
2112 + int *matchEndPos)
2114 + MatchPatternTable *patTable = table->smtAllPatterns;
2115 + int startPos = beginPos;
2116 + int nxtPatStartPos = 0;
2117 + int nxtPatEndPos = 0;
2118 + PatternReference nxtPatRef;
2119 + int nxtPatHighLightCode;
2120 + BackRefInfo nxtPatBackRefInfo;
2121 + PatternStackElement stack[MAX_NESTED_PATTERNS];
2122 + int stackIdx = 0;
2123 + PatternReference startPatRef;
2124 + MatchPatternTableElement *currentElement;
2125 + int groupIdx;
2126 + regexp *groupPatRE;
2127 + regexp *currentPatRE;
2128 + int skipToEnd = FALSE;
2129 + int beginPatternIsMono;
2131 +#ifdef DEBUG_FIND
2132 + printf("Forward Start Pos: %d K: %s EI: %d PI: %d HC: %d <%s>\n",
2133 + startPos,
2134 + patElemKindToString(beginPatRef.prKind),
2135 + beginPatRef.prElementIdx,
2136 + beginPatRef.prPatternIdx,
2137 + beginPatHighLightCode,
2138 + getPatternForDebug(patTable, beginPatRef) );
2139 +#endif
2141 + /*
2142 + * put begin pattern info on stack
2143 + */
2144 + stack[stackIdx].psePatRef = beginPatRef;
2145 + stack[stackIdx].pseHighLightCode = beginPatHighLightCode;
2146 + stack[stackIdx].pseBackRefInfo = *beginPatBackRefInfo;
2147 + stackIdx ++;
2149 + currentElement = patTable->mptElements[beginPatRef.prElementIdx];
2151 + beginPatternIsMono = currentElement->mpteIsMonoPattern;
2153 + groupIdx = currentElement->mpteGroup;
2155 + /*
2156 + * no next pattern can be found, if there is no group assigned
2157 + * to begin pattern (should never occur)
2158 + */
2159 + if (groupIdx == NO_GROUP_IDX)
2161 + *matchEndPos = -1;
2163 + return -1;
2166 + /*
2167 + * Remember pattern (= keywords) regular expression of context
2168 + * group related to begin pattern. Use it for forward search.
2169 + */
2170 + groupPatRE = table->smtGroups[groupIdx]->mpgeKeywordRE;
2171 + currentPatRE = groupPatRE;
2173 + /*
2174 + * Use start / end pattern regular expression if skip to end is
2175 + * set for begin pattern.
2176 + */
2177 + if (currentElement->mpteSkipBtwnStartEnd)
2179 + currentPatRE = currentElement->mpteStartEndRE;
2180 + skipToEnd = TRUE;
2183 + while (stackIdx > 0 && nxtPatStartPos != -1)
2185 + /*
2186 + * Search for next string pattern in forward direction.
2187 + */
2188 + nxtPatStartPos =
2189 + searchPatternForward(
2190 + patTable,
2191 + currentPatRE,
2192 + searchRegion,
2193 + delimiters,
2194 + startPos,
2195 + &nxtPatEndPos,
2196 + &nxtPatRef,
2197 + &nxtPatHighLightCode,
2198 + &nxtPatBackRefInfo );
2200 + startPatRef = stack[stackIdx-1].psePatRef;
2202 + if (nxtPatStartPos == -1)
2204 + /*
2205 + * no next pattern found -> leave loop
2206 + */
2207 +#ifdef DEBUG_FIND
2208 + printf(" SI: %d [start K: %s EI: %d PI %d] Pos: %d --> no next pat. found\n",
2209 + stackIdx,
2210 + patElemKindToString(startPatRef.prKind),
2211 + startPatRef.prElementIdx,
2212 + startPatRef.prPatternIdx,
2213 + startPos);
2214 +#endif
2215 + break;
2218 + /*
2219 + * Update start pattern reference depending on next pattern
2220 + * located after start pattern.
2221 + */
2222 + considerNextPatternReference(
2223 + patTable,
2224 + &startPatRef,
2225 + nxtPatRef,
2226 + groupIdx );
2228 + /*
2229 + * If current found match pattern table element is a mono pattern and
2230 + * skip to start pattern is active, then the found pattern string is
2231 + * a END one in case of ambiguous or no syntax was detected.
2232 + */
2233 + if (skipToEnd &&
2234 + (nxtPatRef.prMonoInfo == PEMI_MONO_AMBIGUOUS_SYNTAX ||
2235 + nxtPatRef.prMonoInfo == PEMI_MONO_NOT_SYNTAX_BASED))
2237 + nxtPatRef.prKind = PEK_END;
2240 +#ifdef DEBUG_FIND
2241 + printf(" SI: %d [start K: %s EI: %d PI %d] Pos: %d-%d K: %s EI: %d PI: %d HC: %d f=<%s> ",
2242 + stackIdx,
2243 + patElemKindToString(startPatRef.prKind),
2244 + startPatRef.prElementIdx,
2245 + startPatRef.prPatternIdx,
2246 + nxtPatStartPos,
2247 + nxtPatEndPos,
2248 + patElemKindToString(nxtPatRef.prKind),
2249 + nxtPatRef.prElementIdx,
2250 + nxtPatRef.prPatternIdx,
2251 + nxtPatHighLightCode,
2252 + getPatternForDebug(patTable, nxtPatRef) );
2253 + printFoundStringForDebug(
2254 + searchRegion->sriWindow,
2255 + nxtPatStartPos + searchRegion->sriStartOfTextPos,
2256 + nxtPatEndPos - nxtPatStartPos);
2257 + printf("\n");
2258 +#endif
2260 + if (nxtPatRef.prKind == PEK_START)
2262 + if (stackIdx >= MAX_NESTED_PATTERNS)
2264 +#ifdef DEBUG_FIND
2265 + printf("FORWARD: MAX. NESTED PATTERN DEPTH REACHED !\n");
2266 +#endif
2267 + nxtPatStartPos = -1;
2268 + nxtPatEndPos = -1;
2270 + else if (!skipToEnd)
2272 + /*
2273 + * Put next pattern on stack, if contents between start /
2274 + * end shouldn't be skipped (if "skipToEnd" is set,
2275 + * a (usually illegal) start pattern to skip inside the
2276 + * skipped one is found (e.g. \* \* ..)
2277 + */
2278 + stack[stackIdx].psePatRef = nxtPatRef;
2279 + stack[stackIdx].pseHighLightCode = nxtPatHighLightCode;
2280 + stack[stackIdx].pseBackRefInfo = nxtPatBackRefInfo;
2281 + stackIdx ++;
2283 + currentElement = patTable->mptElements[nxtPatRef.prElementIdx];
2285 + /*
2286 + * Use start / end pattern regular expression if skip to
2287 + * end is set for found start pattern.
2288 + */
2289 + if (currentElement->mpteSkipBtwnStartEnd)
2291 + currentPatRE = currentElement->mpteStartEndRE;
2292 + skipToEnd = TRUE;
2295 + else if (beginPatternIsMono)
2297 + /*
2298 + * skip to end is set and a mono pattern start is reached:
2299 + * trigger backward search by returning "not found"
2300 + */
2301 +#ifdef DEBUG_FIND
2302 + printf(" ---> mono pattern (re-)start -> trigger backward search\n");
2303 +#endif
2304 + nxtPatStartPos = -1;
2305 + nxtPatEndPos = -1;
2307 +#ifdef DEBUG_FIND
2308 + else
2310 + printf(" ---> skip to end: illegal (re-)start pattern !\n");
2312 +#endif
2314 + else if (nxtPatRef.prKind == PEK_END)
2316 + /*
2317 + * ignore current found pattern, if it doesn't fit to the prev.
2318 + * opened one.
2319 + */
2320 + if (isPartOfPattern(
2321 + patTable,
2322 + nxtPatRef.prElementIdx,
2323 + startPatRef.prElementIdx,
2324 + PEK_END) &&
2325 + (stack[stackIdx - 1].pseHighLightCode == nxtPatHighLightCode ||
2326 + stack[stackIdx - 1].pseHighLightCode == IGNORE_HIGHLIGHT_CODE ||
2327 + nxtPatHighLightCode == IGNORE_HIGHLIGHT_CODE) &&
2328 + doesBackRefInfoMatch(
2329 + &stack[stackIdx - 1].pseBackRefInfo,
2330 + &nxtPatBackRefInfo))
2332 + /*
2333 + * use context group pattern again, if end pattern to skip
2334 + * to was found.
2335 + */
2336 + if (skipToEnd)
2338 + currentPatRE = groupPatRE;
2339 + skipToEnd = FALSE;
2342 + /*
2343 + * pop. related start pattern from stack.
2344 + */
2345 + stackIdx --;
2348 + else if (!skipToEnd)
2350 + /*
2351 + * middle pattern was found: ignore it, if found middle pattern
2352 + * doesn't belong to begin pattern.
2353 + */
2354 + if (stackIdx == 1 &&
2355 + isPartOfPattern(
2356 + patTable,
2357 + startPatRef.prElementIdx,
2358 + nxtPatRef.prElementIdx,
2359 + nxtPatRef.prKind) &&
2360 + (beginPatHighLightCode == nxtPatHighLightCode ||
2361 + beginPatHighLightCode == IGNORE_HIGHLIGHT_CODE ||
2362 + nxtPatHighLightCode == IGNORE_HIGHLIGHT_CODE) &&
2363 + doesBackRefInfoMatch(
2364 + beginPatBackRefInfo,
2365 + &nxtPatBackRefInfo))
2368 + stackIdx --;
2372 + startPos = nxtPatEndPos;
2375 + *matchEndPos = nxtPatEndPos;
2377 + return nxtPatStartPos;
2381 +** Find matching pattern related to given pattern (stored in
2382 +** 'matchInfo') in backward direction by considering the rules stored in
2383 +** string match table of given window. Determine match position (= abs.
2384 +** pos. of 1st character of matching string) and length of matching
2385 +** string.
2386 +** Returns true, if a matching pattern was found.
2388 +static int parseStringElementBackward(
2389 + MatchingElementInfo *matchInfo,
2390 + SearchRegionInfo *searchRegion,
2391 + int relCharPos,
2392 + int *matchPos,
2393 + int *matchedPatternLength,
2394 + const char *delimiters)
2396 + StringMatchTable *smTable =
2397 + (StringMatchTable *)searchRegion->sriWindow->stringMatchTable;
2398 + int beginPos;
2399 + int startStartPos;
2400 + int matchingPatternFound = FALSE;
2402 + /*
2403 + * determine begin of search in string buffer (= relative position
2404 + * of 1st char. before found string pattern.)
2405 + */
2406 + beginPos = relCharPos - matchInfo->meiLength - 1;
2408 + if (beginPos < 0)
2409 + return FALSE;
2411 + /*
2412 + * Find matching pattern within text buffer area to parse in
2413 + * backward direction.
2414 + */
2415 + startStartPos =
2416 + findRelatedStartPattern(
2417 + smTable,
2418 + searchRegion,
2419 + delimiters,
2420 + matchInfo->meiPatRef,
2421 + matchInfo->meiHighLightCode,
2422 + &matchInfo->meiBackRefInfo,
2423 + beginPos,
2424 + matchedPatternLength);
2426 + if (startStartPos != -1)
2428 + *matchPos = startStartPos + searchRegion->sriStartOfTextPos;
2429 + matchingPatternFound = TRUE;
2432 + return matchingPatternFound;
2436 +** Find matching pattern related to given begin pattern reference
2437 +** in backward direction by considering the rules stored in given
2438 +** string match table. Determine match position (= relative
2439 +** pos. of 1st character of matching string).
2440 +** Returns -1, if no matching pattern was found. Else the relative
2441 +** position of 1st char. of matching string is returned.
2443 +static int findRelatedStartPattern(
2444 + StringMatchTable *table,
2445 + SearchRegionInfo *searchRegion,
2446 + const char *delimiters,
2447 + PatternReference beginPatRef,
2448 + int beginPatHighLightCode,
2449 + BackRefInfo *beginPatBackRefInfo,
2450 + int beginPos,
2451 + int *matchedPatternLength)
2453 + MatchPatternTable *patTable = table->smtAllPatterns;
2454 + int startPos = beginPos;
2455 + int prevStartPos = 0;
2456 + PatternReference prevPatRef;
2457 + int prevPatHighLightCode;
2458 + BackRefInfo prevPatBackRefInfo;
2459 + PatternStackElement stack[MAX_NESTED_PATTERNS];
2460 + int stackIdx = 0;
2461 + MatchPatternTableElement *currentElement;
2462 + int groupIdx;
2463 + regexp *groupPatRE;
2464 + regexp *currentPatRE;
2465 + int skipToStart = FALSE;
2467 + /*
2468 + * put begin pattern info on stack
2469 + */
2470 + stack[stackIdx].psePatRef = beginPatRef;
2471 + stack[stackIdx].pseHighLightCode = beginPatHighLightCode;
2472 + stack[stackIdx].pseBackRefInfo = *beginPatBackRefInfo;
2473 + stackIdx ++;
2475 + currentElement = patTable->mptElements[beginPatRef.prElementIdx];
2477 +#ifdef DEBUG_FIND
2478 + printf("Backward Start Pos: %d K: %s EI: %d PI: %d HC: %d <%s>\n",
2479 + startPos,
2480 + patElemKindToString(beginPatRef.prKind),
2481 + beginPatRef.prElementIdx,
2482 + beginPatRef.prPatternIdx,
2483 + beginPatHighLightCode,
2484 + getPatternForDebug(patTable, beginPatRef) );
2485 +#endif
2487 + groupIdx = currentElement->mpteGroup;
2489 + /*
2490 + * no start pattern can be found, if there is no group assigned
2491 + * to begin pattern (should never occur)
2492 + */
2493 + if (groupIdx == NO_GROUP_IDX)
2495 + return -1;
2498 + /*
2499 + * Remember pattern (= keywords) regular expression of context
2500 + * group related to begin pattern. Use it for backward search.
2501 + */
2502 + groupPatRE = table->smtGroups[groupIdx]->mpgeKeywordRE;
2503 + currentPatRE = groupPatRE;
2505 + /*
2506 + * Use start / end pattern regular expression if skip to start is
2507 + * set for begin pattern.
2508 + */
2509 + if (currentElement->mpteSkipBtwnStartEnd)
2511 + currentPatRE = currentElement->mpteStartEndRE;
2512 + skipToStart = TRUE;
2515 + while (stackIdx > 0 && prevStartPos != -1)
2517 + /*
2518 + * Search for previous string pattern in backward direction.
2519 + */
2520 + prevStartPos =
2521 + searchPatternBackward(
2522 + patTable,
2523 + currentPatRE,
2524 + searchRegion,
2525 + delimiters,
2526 + startPos,
2527 + &prevPatRef,
2528 + &prevPatHighLightCode,
2529 + matchedPatternLength,
2530 + &prevPatBackRefInfo );
2532 + if (prevStartPos == -1)
2534 + /*
2535 + * no previous pattern found -> leave loop
2536 + */
2537 +#ifdef DEBUG_FIND
2538 + printf(" SI: %d [K: %s start EI: %d PI %d] Pos: %d --> no next pat. found\n",
2539 + stackIdx,
2540 + patElemKindToString(stack[stackIdx -1].psePatRef.prKind),
2541 + stack[stackIdx -1].psePatRef.prElementIdx,
2542 + stack[stackIdx -1].psePatRef.prPatternIdx,
2543 + startPos);
2544 +#endif
2545 + break;
2548 + /*
2549 + * Update previous pattern reference depending on last stack
2550 + * pattern, which is located in text puffer after previous
2551 + * start pattern.
2552 + */
2553 + considerNextPatternReference(
2554 + patTable,
2555 + &prevPatRef,
2556 + stack[stackIdx - 1].psePatRef,
2557 + groupIdx);
2559 + /*
2560 + * If current found match pattern table element is a mono pattern and
2561 + * skip to start pattern is active, then the found pattern string is
2562 + * a START one in case of ambiguous or no syntax was detected.
2563 + */
2564 + if (skipToStart &&
2565 + (prevPatRef.prMonoInfo == PEMI_MONO_AMBIGUOUS_SYNTAX ||
2566 + prevPatRef.prMonoInfo == PEMI_MONO_NOT_SYNTAX_BASED))
2568 + prevPatRef.prKind = PEK_START;
2571 +#ifdef DEBUG_FIND
2572 + printf(" SI: %d [K: %s start EI: %d PI %d] Pos: %d K: %s EI: %d PI: %d HC: %d f=<%s> ",
2573 + stackIdx,
2574 + patElemKindToString(stack[stackIdx -1].psePatRef.prKind),
2575 + stack[stackIdx -1].psePatRef.prElementIdx,
2576 + stack[stackIdx -1].psePatRef.prPatternIdx,
2577 + prevStartPos,
2578 + patElemKindToString(prevPatRef.prKind),
2579 + prevPatRef.prElementIdx,
2580 + prevPatRef.prPatternIdx,
2581 + prevPatHighLightCode,
2582 + getPatternForDebug(patTable, prevPatRef) );
2583 + printFoundStringForDebug(
2584 + searchRegion->sriWindow,
2585 + prevStartPos + searchRegion->sriStartOfTextPos,
2586 + *matchedPatternLength);
2587 + printf("\n");
2588 +#endif
2590 + if (prevPatRef.prKind == PEK_START)
2592 + /*
2593 + * If the end pattern of the previous pattern set is a reference,
2594 + * then the prev. element index is the one of the ref. (due to this
2595 + * string was found before and was stored on stack)
2596 + */
2597 + if (patTable->mptElements[prevPatRef.prElementIdx]->mpteGroup == groupIdx)
2599 + considerStackPatReference(
2600 + &patTable->mptElements[prevPatRef.prElementIdx]->mpteEnd,
2601 + stack[stackIdx - 1].psePatRef.prElementIdx,
2602 + &prevPatRef.prElementIdx);
2605 + /*
2606 + * Ignore current found pattern, if it doesn't fit to the prev.
2607 + * opened one.
2608 + */
2609 + if (stack[stackIdx - 1].psePatRef.prElementIdx == prevPatRef.prElementIdx &&
2610 + (stack[stackIdx - 1].pseHighLightCode == prevPatHighLightCode ||
2611 + stack[stackIdx - 1].pseHighLightCode == IGNORE_HIGHLIGHT_CODE ||
2612 + prevPatHighLightCode == IGNORE_HIGHLIGHT_CODE) &&
2613 + doesBackRefInfoMatch(
2614 + &stack[stackIdx - 1].pseBackRefInfo,
2615 + &prevPatBackRefInfo))
2617 + /*
2618 + * use context group pattern again, if start pattern
2619 + * to skip to was found.
2620 + */
2621 + if (skipToStart)
2623 + currentPatRE = groupPatRE;
2624 + skipToStart = FALSE;
2627 + /*
2628 + * pop. related end pattern from stack.
2629 + */
2630 + stackIdx --;
2633 + else if (prevPatRef.prKind == PEK_END)
2635 + if (stackIdx >= MAX_NESTED_PATTERNS)
2637 +#ifdef DEBUG_FIND
2638 + printf("BACKWARD: MAX. NESTED PATTERN DEPTH REACHED !\n");
2639 +#endif
2640 + prevStartPos = -1;
2642 + else if (!skipToStart)
2644 + /*
2645 + * Put prev. pattern on stack, if contents between start /
2646 + * end shouldn't be skipped (if "skipToStart" is set,
2647 + * a (usually illegal) end pattern to skip inside the
2648 + * skipped one is found (e.g. *\ *\ ..)
2649 + */
2650 + stack[stackIdx].psePatRef = prevPatRef;
2651 + stack[stackIdx].pseHighLightCode = prevPatHighLightCode;
2652 + stack[stackIdx].pseBackRefInfo = prevPatBackRefInfo;
2653 + stackIdx ++;
2655 + currentElement =
2656 + patTable->mptElements[prevPatRef.prElementIdx];
2658 + /*
2659 + * Use start / end pattern regular expression if skip to
2660 + * end is set for found end pattern.
2661 + */
2662 + if (currentElement->mpteSkipBtwnStartEnd)
2664 + currentPatRE = currentElement->mpteStartEndRE;
2665 + skipToStart = TRUE;
2669 + startPos = prevStartPos - 1;
2672 + return prevStartPos;
2676 +** Adapt found pattern element index depending on
2677 +** the info stored on (last) stack element and
2678 +** a given pattern set (belonging to the found pattern).
2680 +static void considerStackPatReference(
2681 + PatternElementSet *patSet,
2682 + int stackElementIdx,
2683 + int *foundElementIdx)
2685 + PatternElement *patElement;
2686 + int i;
2688 + /*
2689 + * If found pattern index already indicates, that found pattern
2690 + * belongs to pattern set stored on stack, then no adaption is needed
2691 + */
2692 + if (*foundElementIdx == stackElementIdx)
2693 + return;
2695 + /*
2696 + * Check all elements of given pattern element set:
2697 + */
2698 + for (i=0; i < patSet->pesNumberOfPattern; i++)
2700 + patElement = patSet->pesPattern[i];
2702 + /*
2703 + * If this set element is a reference and this reference fits
2704 + * to the element stored on stack, then adapt found element index:
2705 + * indicate, that found pattern belongs to pattern set stored on stack
2706 + */
2707 + if (patElement->peType == PET_REFERENCE &&
2708 + patElement->peVal.peuRef.prElementIdx == stackElementIdx)
2710 + *foundElementIdx = stackElementIdx;
2712 + return;
2718 +** Determines, if a string pattern is located at the given position
2719 +** "relBeginPos" in the given "searchRegion". A string pattern is
2720 +** found, if the pattern is located just before given position
2721 +** "relBeginPos" OR if "relBeginPos" is located within a string pattern.
2723 +** Returns true, if the given "pattern" is located at
2724 +** "relBeginPos". "matchInfo" holds all info needed about matched
2725 +** "start" string pattern.
2727 +static int getPatternLocatedAtPos(
2728 + regexp *usedPatRE,
2729 + MatchPatternTable *table,
2730 + SearchRegionInfo *searchRegion,
2731 + int *relBeginPos,
2732 + MatchingElementInfo *matchInfo,
2733 + const char *delimiters)
2735 + int searchStartPos = *relBeginPos;
2736 + PatternReference *patRef = &matchInfo->meiPatRef;
2737 + FoundStringInfo foundStringInfo;
2738 + int relMatchStartPos;
2739 + int relMatchEndPos;
2741 + patRef->prElementIdx = NO_ELEMENT_IDX;
2742 + patRef->prKind = PEK_UNKNOWN;
2743 + patRef->prPatternIdx = NO_PATTERN_IDX;
2745 + matchInfo->meiHighLightCode = IGNORE_HIGHLIGHT_CODE;
2746 + matchInfo->meiAbsStartPos = -1;
2747 + matchInfo->meiLength = 0;
2749 + /*
2750 + * No backward search possible, if we are at beginning of
2751 + * search region
2752 + */
2753 + if (searchStartPos == 0)
2754 + return FALSE;
2756 + /*
2757 + * Search in backward direction for 1st occurance of a string pattern
2758 + * starting one char before "searchStartPos".
2759 + */
2760 + if (ExecRE(
2761 + usedPatRE,
2762 + searchRegion->sriText,
2763 + searchRegion->sriText + searchStartPos - 1,
2764 + TRUE,
2765 + searchRegion->sriPrevChar,
2766 + searchRegion->sriText[searchStartPos],
2767 + delimiters,
2768 + searchRegion->sriText,
2769 + NULL))
2771 + /*
2772 + * String pattern was found:
2773 + */
2774 + foundStringInfo.fsiStartPtr = usedPatRE->startp[0];
2775 + foundStringInfo.fsiEndPtr = usedPatRE->endp[0];
2776 + foundStringInfo.fsiLength =
2777 + foundStringInfo.fsiEndPtr - foundStringInfo.fsiStartPtr;
2779 + relMatchEndPos = foundStringInfo.fsiEndPtr - searchRegion->sriText;
2780 + relMatchStartPos = foundStringInfo.fsiStartPtr - searchRegion->sriText;
2782 + /*
2783 + * Is found pattern located exactly one char before "relBeginPos" OR
2784 + * is "relBeginPos" located within found string pattern ?
2785 + * Note: "relMatchEndPos" indicates 1st pos. in "sriText"
2786 + * which does *not* belong to found string anymore.
2787 + */
2788 + if ((*relBeginPos == relMatchEndPos) ||
2789 + (*relBeginPos >= relMatchStartPos &&
2790 + *relBeginPos < relMatchEndPos))
2792 + *relBeginPos = relMatchEndPos;
2794 + /*
2795 + * Determine match element info related to found string.
2796 + */
2797 + matchInfo->meiAbsStartPos =
2798 + foundStringInfo.fsiStartPtr - searchRegion->sriText +
2799 + searchRegion->sriStartOfTextPos;
2800 + matchInfo->meiLength = foundStringInfo.fsiLength;
2802 + foundStringInfo.fsiPrevChar =
2803 + foundStringInfo.fsiStartPtr == searchRegion->sriText ?
2804 + searchRegion->sriPrevChar : *(foundStringInfo.fsiStartPtr - 1);
2806 + foundStringInfo.fsiSuccChar =
2807 + *(foundStringInfo.fsiEndPtr) == '\0' ?
2808 + searchRegion->sriSuccChar : *(foundStringInfo.fsiEndPtr);
2810 + foundStringInfo.fsiDelimiters = delimiters;
2812 + return(
2813 + getMatchedElementInfo(
2814 + searchRegion->sriWindow,
2815 + table,
2816 + &foundStringInfo,
2817 + matchInfo));
2821 + return FALSE;
2825 +** Get all needed info related to matched "start" string pattern
2826 +** (given by parameter "foundStringInfo").
2828 +** Returns true, if info was determined successfully.
2830 +static int getMatchedElementInfo(
2831 + WindowInfo *window,
2832 + MatchPatternTable *table,
2833 + FoundStringInfo *foundStringInfo,
2834 + MatchingElementInfo *matchInfo)
2836 + PatternReference *patRef = &matchInfo->meiPatRef;
2837 + int absMatchStartPos = matchInfo->meiAbsStartPos;
2838 + MatchPatternTableElement *matchedElement;
2840 + if (getPatternInfo(
2841 + table,
2842 + foundStringInfo,
2843 + patRef,
2844 + &matchInfo->meiBackRefInfo))
2846 + /*
2847 + * A pattern reference could be assigned to found string:
2848 + */
2849 + matchedElement = table->mptElements[patRef->prElementIdx];
2851 + matchInfo->meiElement = matchedElement;
2853 + /*
2854 + * get highlight code of found string pattern, if applicable
2855 + */
2856 + if (!matchedElement->mpteIgnoreHighLightInfo)
2858 + matchInfo->meiHighLightCode =
2859 + HighlightCodeOfPos(window, absMatchStartPos);
2862 + /*
2863 + * setup mono pattern info of found string pattern
2864 + */
2865 + if (matchedElement->mpteIsMonoPattern)
2867 + if (matchedElement->mpteIgnoreHighLightInfo)
2869 + patRef->prMonoInfo = PEMI_MONO_NOT_SYNTAX_BASED;
2871 + else
2873 + /*
2874 + * determine mono pattern info depending on highLightCodes
2875 + * before / after found string pattern.
2876 + */
2877 + patRef->prMonoInfo =
2878 + determineMonoPatInfo(
2879 + window,
2880 + matchInfo->meiHighLightCode,
2881 + absMatchStartPos - 1,
2882 + absMatchStartPos + matchInfo->meiLength,
2883 + &patRef->prKind);
2886 + else
2888 + patRef->prMonoInfo = PEMI_NOT_MONO;
2891 + return TRUE;
2893 + else
2895 + /*
2896 + * Found string can't be assigned to a pattern element
2897 + * (should never occur).
2898 + */
2899 + return FALSE;
2904 +** Returns string pattern of given pattern element.
2906 +StringPattern *GetStringPattern(
2907 + MatchPatternTable *table,
2908 + PatternElement *pattern )
2910 + switch (pattern->peType)
2912 + case PET_SINGLE:
2913 + return &pattern->peVal.peuSingle;
2914 + break;
2916 + case PET_MULTIPLE:
2917 + return &pattern->peVal.peuMulti.mpStringPattern;
2918 + break;
2920 + case PET_REFERENCE:
2921 + return GetStringPattern(
2922 + table,
2923 + getPatternOfReference(table, pattern->peVal.peuRef));
2924 + break;
2927 + /*
2928 + * never reached; just to make compiler happy
2929 + */
2930 + return NULL;
2934 +** Returns pattern element of given pattern reference.
2936 +static PatternElement *getPatternOfReference(
2937 + MatchPatternTable *table,
2938 + PatternReference patRef)
2940 + MatchPatternTableElement **element = table->mptElements;
2942 + return element[ patRef.prElementIdx ]->mpteAll.pesPattern[patRef.prPatternIdx];
2945 +#ifdef DEBUG_FIND
2946 +static char *getPatternForDebug(
2947 + MatchPatternTable *table,
2948 + PatternReference patRef )
2950 + if (patRef.prElementIdx < 0)
2952 + return "---";
2955 + return
2956 + GetStringPattern(
2957 + table,
2958 + getPatternOfReference(table, patRef))->spText;
2961 +static char *patElemKindToString(
2962 + PatternElementKind patElemKind)
2964 + if (patElemKind == PEK_START)
2965 + return "START";
2966 + else if (patElemKind == PEK_MIDDLE)
2967 + return "MIDDLE";
2968 + else if (patElemKind == PEK_END)
2969 + return "END";
2970 + else
2971 + return "UNKNOWN";
2974 +static void printFoundStringForDebug(
2975 + WindowInfo *window,
2976 + int absStartPos,
2977 + int length)
2979 + char *foundStr =
2980 + BufGetRange( window->buffer, absStartPos, absStartPos + length);
2982 + printf("%d (abs.) <%s>",
2983 + absStartPos,
2984 + foundStr);
2986 + XtFree(foundStr);
2988 +#endif
2991 diff --quilt /dev/null new/source/patternMatch.h
2992 --- /dev/null
2993 +++ new/source/patternMatch.h
2994 @@ -0,0 +1,170 @@
2995 +/* $Id: patternMatch.h,v 1.2 2003/10/11 16:45:25 uleh Exp $ */
2997 +#ifndef NEDIT_PATTERNMATCH_H_INCLUDED
2998 +#define NEDIT_PATTERNMATCH_H_INCLUDED
3000 +#include "regularExp.h"
3002 +#define NO_GROUP_IDX -1
3003 +#define NO_ELEMENT_IDX -1
3004 +#define NO_PATTERN_IDX -1
3006 +#define MAX_GLOBAL_BACK_REF_ID 9
3007 +#define NO_LOCAL_BACK_REF_ID -1
3009 +typedef enum {
3010 + PEK_UNKNOWN,
3011 + PEK_START,
3012 + PEK_END,
3013 + PEK_MIDDLE
3014 +} PatternElementKind;
3016 +typedef enum {
3017 + PEMI_NOT_MONO,
3018 + PEMI_MONO_NOT_SYNTAX_BASED,
3019 + PEMI_MONO_AMBIGUOUS_SYNTAX,
3020 + PEMI_MONO_DEFINITE_SYNTAX
3021 +} PatternElementMonoInfo;
3023 +typedef struct _PatternReference {
3024 + PatternElementKind prKind;
3025 + PatternElementMonoInfo prMonoInfo;
3026 + int prElementIdx;
3027 + int prPatternIdx;
3028 +} PatternReference;
3030 +typedef enum {
3031 + MPT_INDIVIDUAL,
3032 + MPT_SUB,
3033 + MPT_GROUP
3034 +} MatchPatternType;
3036 +typedef struct _MatchPatternSequenceElement {
3037 + char *mpseName;
3038 + MatchPatternType mpseType;
3039 + int mpseIndex;
3040 +} MatchPatternSequenceElement;
3042 +typedef struct _MatchPatternGroupElement {
3043 + char *mpgeName;
3044 + int mpgeNumberOfSubPatterns;
3045 + char **mpgeSubPatternIds;
3046 + regexp *mpgeKeywordRE;
3047 +} MatchPatternGroupElement;
3049 +typedef enum {
3050 + PWB_NONE,
3051 + PWB_LEFT,
3052 + PWB_RIGHT,
3053 + PWB_BOTH
3054 +} PatternWordBoundary;
3056 +typedef struct _StrPatBackRefElement{
3057 + int spbreLocalBackRefID;
3058 + char *spbreRegExpText;
3059 +} StrPatBackRefElement;
3061 +typedef struct _StringPattern {
3062 + char *spText;
3063 + int spLength;
3064 + PatternWordBoundary spWordBoundary;
3065 + int spCaseInsensitive;
3066 + int spRegularExpression;
3067 + regexp *spTextRE;
3068 + char *spOrigText;
3069 + int spBackRefParsed;
3070 + int spBackRefResolved;
3071 + StrPatBackRefElement spOwnGlobalBackRef[MAX_GLOBAL_BACK_REF_ID];
3072 + int spGlobalToLocalBackRef[MAX_GLOBAL_BACK_REF_ID];
3073 +} StringPattern;
3075 +typedef struct _MultiPattern {
3076 + StringPattern mpStringPattern;
3077 + int mpNumberOfReferences;
3078 + PatternReference *mpRefList;
3079 +} MultiPattern;
3081 +typedef enum {
3082 + PET_SINGLE,
3083 + PET_MULTIPLE,
3084 + PET_REFERENCE
3085 +} PatternElementType;
3087 +typedef struct _PatternElement {
3088 + int peIndex;
3089 + PatternElementKind peKind;
3090 + PatternElementType peType;
3091 + union {
3092 + StringPattern peuSingle;
3093 + MultiPattern peuMulti;
3094 + PatternReference peuRef;
3095 + } peVal;
3096 +} PatternElement;
3098 +typedef struct _PatternElementSet {
3099 + int pesNumberOfPattern;
3100 + PatternElement **pesPattern;
3101 +} PatternElementSet;
3103 +typedef struct _GlobalBackRefElement{
3104 + StringPattern *gbreDefByStrPat;
3105 + char *gbreRegExpText;
3106 +} GlobalBackRefElement;
3108 +typedef struct _MatchPatternTableElement {
3109 + char *mpteName;
3110 + int mpteIndex;
3111 + MatchPatternType mpteType;
3112 + int mpteGroup;
3113 + PatternElementSet mpteAll;
3114 + PatternElementSet mpteStart;
3115 + PatternElementSet mpteMiddle;
3116 + PatternElementSet mpteEnd;
3117 + int mpteFlash;
3118 + int mpteIsMonoPattern;
3119 + int mpteSkipBtwnStartEnd;
3120 + int mpteIgnoreHighLightInfo;
3121 + regexp *mpteStartEndRE;
3122 + GlobalBackRefElement mpteGlobalBackRef[MAX_GLOBAL_BACK_REF_ID];
3123 +} MatchPatternTableElement;
3125 +typedef struct _MatchPatternTable {
3126 + int mptNumberOfElements;
3127 + MatchPatternTableElement **mptElements;
3128 +} MatchPatternTable;
3130 +typedef struct _StringMatchTable {
3131 + char *smtLanguageMode;
3132 + MatchPatternTable *smtAllPatterns;
3133 + regexp *smtAllPatRE;
3134 + regexp *smtFlashPatRE;
3135 + regexp *smtUsedPatRE;
3136 + int smtNumberOfGroups;
3137 + MatchPatternGroupElement **smtGroups;
3138 + int smtNumberOfSeqElements;
3139 + MatchPatternSequenceElement **smtSequence;
3140 +} StringMatchTable;
3142 +typedef enum {
3143 + MT_FLASH_DELIMIT,
3144 + MT_FLASH_RANGE,
3145 + MT_SELECT,
3146 + MT_GOTO,
3147 + MT_MACRO
3148 +} MatchingType;
3150 +int FindMatchingString(
3151 + WindowInfo *window,
3152 + MatchingType matchingType,
3153 + int *charPos,
3154 + int startLimit,
3155 + int endLimit,
3156 + int *matchPos,
3157 + int *matchLength,
3158 + int *direction);
3160 +StringPattern *GetStringPattern(
3161 + MatchPatternTable *table,
3162 + PatternElement *pattern);
3164 +#endif /* NEDIT_PATTERNMATCH_H_INCLUDED */
3165 diff --quilt /dev/null new/source/patternMatchData.c
3166 --- /dev/null
3167 +++ new/source/patternMatchData.c
3168 @@ -0,0 +1,7780 @@
3169 +static const char CVSID[] = "$Id: patternMatchData.c,v 1.4 2004/10/27 21:57:12 uleh Exp $";
3170 +/*******************************************************************************
3171 +* *
3172 +* patternMatchData.c -- Maintain and allow user to edit a matching pattern list*
3173 +* used for pattern matching *
3174 +* *
3175 +* Copyright (C) 2003-2004, Uwe Lehnert *
3176 +* *
3177 +* This is free software; you can redistribute it and/or modify it under the *
3178 +* terms of the GNU General Public License as published by the Free Software *
3179 +* Foundation; either version 2 of the License, or (at your option) any later *
3180 +* version. In addition, you may distribute versions of this program linked to *
3181 +* Motif or Open Motif. See README for details. *
3182 +* *
3183 +* This software is distributed in the hope that it will be useful, but WITHOUT *
3184 +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
3185 +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
3186 +* for more details. *
3187 +* *
3188 +* You should have received a copy of the GNU General Public License along with *
3189 +* software; if not, write to the Free Software Foundation, Inc., 59 Temple *
3190 +* Place, Suite 330, Boston, MA 02111-1307 USA *
3191 +* *
3192 +* Nirvana Text Editor *
3193 +* October 27, 2004 *
3194 +* *
3195 +* Written by Uwe Lehnert *
3196 +* *
3197 +*******************************************************************************/
3198 +#ifdef HAVE_CONFIG_H
3199 +#include "../config.h"
3200 +#endif
3202 +#include <stdlib.h>
3203 +#include <stdio.h>
3204 +#include <limits.h>
3205 +#include <string.h>
3206 +#include <ctype.h>
3208 +#ifdef VMS
3209 +#include "../util/VMSparam.h"
3210 +#else
3211 +#ifndef __MVS__
3212 +#include <sys/param.h>
3213 +#endif
3214 +#endif /*VMS*/
3216 +#include <Xm/Xm.h>
3217 +#include <Xm/Form.h>
3218 +#include <Xm/Frame.h>
3219 +#include <Xm/Text.h>
3220 +#include <Xm/LabelG.h>
3221 +#include <Xm/PushB.h>
3222 +#include <Xm/PushBG.h>
3223 +#include <Xm/ToggleB.h>
3224 +#include <Xm/RowColumn.h>
3225 +#include <Xm/SeparatoG.h>
3227 +#include "../util/misc.h"
3228 +#include "../util/DialogF.h"
3229 +#include "../util/managedList.h"
3231 +#include "regularExp.h"
3232 +#include "textBuf.h"
3233 +#include "nedit.h"
3234 +#include "window.h"
3235 +#include "preferences.h"
3236 +#include "help.h"
3237 +#include "file.h"
3238 +#include "textP.h"
3240 +#include "patternMatch.h"
3241 +#include "patternMatchData.h"
3243 +#ifdef HAVE_DEBUG_H
3244 +#include "../debug.h"
3245 +#endif
3248 + * local synonyms
3249 + */
3250 +#define MAX_LOCAL_BACK_REF_ID 9
3251 +#define LOCAL_BACK_REF_ID_USED -2
3253 +#define MAX_NUMBER_MIDDLE_PATTERN 10
3254 +#define MAX_STRING_PATTERNS 30
3255 +#define MAX_NBR_MATCH_PATTERNS 50
3256 +#define MAX_NBR_MATCH_PATTERN_GROUPS 50
3257 +#define MAX_NBR_SEQ_ELEMENTS MAX_NBR_MATCH_PATTERNS + MAX_NBR_MATCH_PATTERN_GROUPS
3259 +#define MATCH_PAT_NAME_LBL_TXT "Matching Pattern Name"
3260 +#define STRING_PATTERNS_LBL_TXT "String Patterns"
3262 +#define BORDER 4
3263 +#define LIST_RIGHT 41
3264 +#define PLAIN_LM_STRING "PLAIN"
3266 +#define SPNM_NONE_SELECTED "none selected"
3268 +#define KEEP_LANGUAGE_MODE True
3269 +#define DISCARD_LANGUAGE_MODE False
3271 +#define STRING_PATTERN_DIALOG True
3272 +#define CONTEXT_GROUP_DIALOG False
3275 + * local data definitions
3276 + */
3277 +typedef struct _ErrorInfo {
3278 + char *eiDetail;
3279 + char *eiLanguageMode;
3280 + char *eiMPTabElementName;
3281 + char *eiStringPatText;
3282 + char *eiRegExpCompileMsg;
3283 + int eiBackRefNbr;
3284 +} ErrorInfo;
3286 +typedef struct _BackRefBracketInfo {
3287 + int brbiGlobalId;
3288 + char *brbiContentStart;
3289 + int brbiNestingLevel;
3290 +} BackRefBracketInfo;
3292 +typedef struct _RegExpStringInfo {
3293 + int resiNbrOfAddedMultiPat;
3294 + PatternReference **resiAddedMultiPat;
3295 + char *resiNoneWBRegExpString;
3296 + char *resiLeftWBRegExpString;
3297 + char *resiRightWBRegExpString;
3298 + char *resiBothWBRegExpString;
3299 + int resiLocalBackRefID;
3300 +} RegExpStringInfo;
3302 +typedef struct _ReadMatchPatternInfo {
3303 + int rmpiNbrOfElements;
3304 + MatchPatternTableElement *rmpiElement[MAX_NBR_MATCH_PATTERNS];
3305 + int rmpiNbrOfGroups;
3306 + MatchPatternGroupElement *rmpiGroup[MAX_NBR_MATCH_PATTERN_GROUPS];
3307 + int rmpiNbrOfSeqElements;
3308 + MatchPatternSequenceElement *rmpiSequence[MAX_NBR_SEQ_ELEMENTS];
3309 + regexp *rmpiAllPatRE;
3310 + regexp *rmpiFlashPatRE;
3311 +} ReadMatchPatternInfo;
3313 +typedef struct _DialogStringPatternElement {
3314 + char *dspeText;
3315 + PatternElementKind dspeKind;
3316 + PatternWordBoundary dspeWordBoundary;
3317 + int dspeCaseInsensitive;
3318 + int dspeRegularExpression;
3319 +} DialogStringPatternElement;
3321 +typedef struct _DialogStringPatterns {
3322 + int dspNumberOfPatterns;
3323 + DialogStringPatternElement *dspElements[MAX_STRING_PATTERNS];
3324 +} DialogStringPatterns;
3326 +typedef struct _DialogMatchPatternTableElement {
3327 + char *dmpteName;
3328 + MatchPatternType dmpteType;
3329 + DialogStringPatterns dmptePatterns;
3330 + int dmpteSkipBtwnStartEnd;
3331 + int dmpteIgnoreHighLightInfo;
3332 + int dmpteFlash;
3333 +} DialogMatchPatternTableElement;
3335 +typedef struct _DialogMatchPatternGroupElement {
3336 + char *dmpgeName;
3337 + int dmpgeNumberOfSubPatterns;
3338 + char *dmpgeSubPatternIds[MAX_NBR_MATCH_PATTERNS];
3339 +} DialogMatchPatternGroupElement;
3341 +typedef struct _DialogMatchPatternSequenceElement {
3342 + char *dmpseName;
3343 + MatchPatternType dmpseType;
3344 + int dmpseValid;
3345 + void *dmpsePtr;
3346 +} DialogMatchPatternSequenceElement;
3348 +typedef struct _DialogMatchPatternInfo {
3349 + int dmpiNbrOfSeqElements;
3350 + DialogMatchPatternSequenceElement *dmpiSequence[MAX_NBR_SEQ_ELEMENTS];
3351 +} DialogMatchPatternInfo;
3353 +typedef enum {
3354 + DMPTR_OK,
3355 + DMPTR_EMPTY,
3356 + DMPTR_INCOMPLETE
3357 +} DMPTranslationResult;
3359 +typedef struct _NameList {
3360 + int nlNumber;
3361 + char *nlId[MAX_NBR_SEQ_ELEMENTS + 1];
3362 +} NameList;
3365 + * prototypes of local functions
3366 + */
3367 +static void treatDuplicatedPattern(
3368 + MatchPatternTable *table,
3369 + PatternElement *prevPattern,
3370 + PatternReference prevPatRef,
3371 + PatternElement *lastPattern,
3372 + PatternReference lastPatRef);
3373 +static void treatDuplicatedPatternElements(
3374 + MatchPatternTable *table,
3375 + MatchPatternTableElement *prevElement,
3376 + int prevElementIdx,
3377 + PatternElement *lastPattern,
3378 + PatternReference lastPatRef);
3379 +static void treatDuplicatedMTElements(
3380 + MatchPatternTable *table,
3381 + MatchPatternTableElement *prevElement,
3382 + int prevElementIdx,
3383 + MatchPatternTableElement *lastElement,
3384 + int lastElementIdx);
3385 +static void treatDuplicatedMTEntries(
3386 + MatchPatternTableElement **element,
3387 + int nbrOfElements);
3389 +static int createStrPatRegExpOfElement(
3390 + ReadMatchPatternInfo *readPatInfo,
3391 + MatchPatternTableElement *element,
3392 + ErrorInfo *errInfo);
3393 +static int createStrPatRegExp(
3394 + StringPattern *strPat,
3395 + ErrorInfo *errInfo);
3396 +static void adaptCompileMsg(
3397 + char *compileMsg,
3398 + int *globalToLocalBackRef);
3399 +static int localToGlobalBackRef(
3400 + int *globalToLocalBackRef,
3401 + int localId);
3402 +static int createStartEndRegExp(
3403 + ReadMatchPatternInfo *readMatchPatternInfo,
3404 + MatchPatternTableElement *element,
3405 + ErrorInfo *errInfo);
3406 +static int createGroupRegExp(
3407 + ReadMatchPatternInfo *readPatInfo,
3408 + MatchPatternGroupElement *group,
3409 + ErrorInfo *errInfo);
3410 +static void setupRegExpStringBuffers(
3411 + ReadMatchPatternInfo *readMatchPatternInfo,
3412 + RegExpStringInfo *regExpStringInfo);
3413 +static void addSMTRegExpString(
3414 + char *result,
3415 + char *partToAdd,
3416 + const char *postfix);
3417 +static void composeStartEndRegExpString(
3418 + ReadMatchPatternInfo *readMatchPatternInfo,
3419 + MatchPatternTableElement *element,
3420 + char **regExpString);
3421 +static void addElementToRegExpString(
3422 + MatchPatternTableElement *element,
3423 + ReadMatchPatternInfo *readMatchPatternInfo,
3424 + RegExpStringInfo *regExpStringInfo);
3425 +static void addUniquePatternToRegExpString(
3426 + PatternElement *patElement,
3427 + PatternReference *patElementReference,
3428 + ReadMatchPatternInfo *readMatchPatternInfo,
3429 + RegExpStringInfo *regExpStringInfo);
3430 +static void addPatternToRegExpString(
3431 + StringPattern *pattern,
3432 + RegExpStringInfo *regExpStringInfo);
3433 +static char *adaptLocalBackRefs(
3434 + char *regExpText,
3435 + int *commonLocalId);
3436 +static void scanForLocalBackRefs(
3437 + char *regExpText,
3438 + int *localBackRefList);
3439 +static int isMultiPatternNotAdded(
3440 + RegExpStringInfo *regExpStringInfo,
3441 + PatternReference *toBeAddedPR);
3442 +static void catSMTRegExpStrings(
3443 + RegExpStringInfo *regExpStringInfo,
3444 + char **regExpString);
3445 +static void freeRegExpStringInfo(
3446 + RegExpStringInfo *regExpStringInfo);
3447 +static int totalKeywordOfTableLen(
3448 + ReadMatchPatternInfo *info,
3449 + int *nbrOfMultiPatterns);
3450 +static int totalMatchPatternTableElementLen(
3451 + ReadMatchPatternInfo *info,
3452 + MatchPatternTableElement *element,
3453 + int *nbrOfMultiPatterns);
3454 +static int patternElementLen(
3455 + ReadMatchPatternInfo *info,
3456 + PatternElement *patElement,
3457 + int *nbrOfMultiPatterns);
3459 +static void parseMatchingPatternSetError(
3460 + const char *stringStart,
3461 + const char *stoppedAt,
3462 + ErrorInfo *errInfo);
3463 +static void dialogMatchingPatternSetError(
3464 + char *title,
3465 + ErrorInfo *errInfo);
3467 +static char *createMatchPatternsString(
3468 + StringMatchTable *table,
3469 + char *indentStr);
3470 +static char *createPatternElementString(
3471 + MatchPatternTable *table,
3472 + PatternElement *pat);
3474 +static StringMatchTable *readDefaultStringMatchTable(const char *langModeName);
3475 +static int isDefaultMatchPatternTable(StringMatchTable *table);
3477 +static void freeReadMatchPatternInfo( ReadMatchPatternInfo *readPatInfo );
3478 +static void freeStringMatchTable( StringMatchTable *table );
3479 +static void freeMatchPatternTableElement( MatchPatternTableElement *element );
3480 +static void freePatternElement( PatternElement *element );
3481 +static void freeStringPattern( StringPattern *strPat );
3482 +static void freeMatchPatternGroupElement( MatchPatternGroupElement *group );
3483 +static void freeMatchPatternSequenceElement( MatchPatternSequenceElement *sequence );
3485 +static StringMatchTable *readMatchPatternSet(char **inPtr);
3486 +static StringMatchTable *readMatchPatternSetContent(
3487 + char **inPtr,
3488 + char *stringStart,
3489 + char *languageMode);
3490 +static int createRegExpOfPatterns(
3491 + ReadMatchPatternInfo *readPatInfo,
3492 + ErrorInfo *errInfo);
3493 +static int createRegExpOfAllPatterns(
3494 + ReadMatchPatternInfo *readPatInfo,
3495 + ErrorInfo *errInfo);
3496 +static int createRegExpOfStrPatterns(
3497 + ReadMatchPatternInfo *readPatInfo,
3498 + ErrorInfo *errInfo);
3499 +static StringMatchTable *createStringMatchTable(
3500 + ReadMatchPatternInfo *readPatInfo,
3501 + char *languageMode);
3502 +static int readMatchPatternEntry(
3503 + char **inPtr,
3504 + ErrorInfo *errInfo,
3505 + ReadMatchPatternInfo *info);
3506 +static void recordPatternSequence(
3507 + ReadMatchPatternInfo *info,
3508 + char *name,
3509 + MatchPatternType type,
3510 + int index);
3511 +static int assignIndividualGroup(
3512 + ReadMatchPatternInfo *info,
3513 + char **errMsg,
3514 + MatchPatternTableElement *element);
3515 +static MatchPatternTableElement *getPatternOfName(
3516 + ReadMatchPatternInfo *info,
3517 + char *subPatToSearch);
3518 +static MatchPatternGroupElement *readMatchPatternGroup(
3519 + char **inPtr,
3520 + ErrorInfo *errInfo,
3521 + char *name,
3522 + ReadMatchPatternInfo *info);
3523 +static int readPatternElement(
3524 + char **inPtr,
3525 + char **errMsg,
3526 + PatternElement **pattern);
3527 +static PatternElement *createPatternElement(
3528 + char *patternText,
3529 + PatternElementKind patternKind,
3530 + PatternWordBoundary wordBoundary,
3531 + int caseInsensitive,
3532 + int regularExpression);
3534 +static int createGlobalBackRefList(
3535 + ReadMatchPatternInfo *readPatInfo,
3536 + MatchPatternTableElement *element,
3537 + ErrorInfo *errInfo);
3538 +StringPattern *getReadStringPattern(
3539 + ReadMatchPatternInfo *readPatInfo,
3540 + PatternElement *pattern );
3541 +static PatternElement *getReadPatternOfReference(
3542 + ReadMatchPatternInfo *readPatInfo,
3543 + PatternReference *patRef);
3544 +static char *replaceCapturingParentheses(
3545 + const char *source);
3546 +static int parseGlobalBackRefs(
3547 + StringPattern *strPat,
3548 + GlobalBackRefElement *backRefList,
3549 + ErrorInfo *errInfo);
3550 +static int updateGlobalBackRefs(
3551 + StringPattern *strPat,
3552 + GlobalBackRefElement *backRefList,
3553 + ErrorInfo *errInfo);
3554 +static char *createBackRefRegExpText(
3555 + const char *start,
3556 + const char *end);
3557 +static int resolveGlobalBackRefs(
3558 + ReadMatchPatternInfo *readPatInfo,
3559 + MatchPatternTableElement *element,
3560 + ErrorInfo *errInfo);
3561 +static int resolveGlobalBackRefsOfStrPat(
3562 + StringPattern *strPat,
3563 + GlobalBackRefElement *backRefList,
3564 + ErrorInfo *errInfo);
3565 +static char *substituteGlobalBackRef(
3566 + StringPattern *strPat,
3567 + char *subsPtr,
3568 + int globalId,
3569 + int *localId,
3570 + GlobalBackRefElement *backRefList,
3571 + ErrorInfo *errInfo);
3572 +static char *replaceBackRefIdByRegExp(
3573 + StringPattern *strPat,
3574 + char *replaceStartPtr,
3575 + char *regExp);
3576 +static char *convertGlobalToLocalBackRef(
3577 + StringPattern *strPat,
3578 + char *convertPtr);
3580 +static MatchPatternTableElement *readMatchPatternTableElement(
3581 + char **inPtr,
3582 + char **errMsg,
3583 + char *name,
3584 + MatchPatternType type);
3585 +static int sortReadPatternElementSet(
3586 + PatternElementSet *allPat,
3587 + char **errMsg,
3588 + MatchPatternTableElement *result);
3589 +static void countPatternElementKind(
3590 + PatternElementSet *allPat,
3591 + MatchPatternTableElement *result);
3592 +static void sortPatternElementSet(
3593 + PatternElementSet *allPat,
3594 + MatchPatternTableElement *result);
3595 +static void copyPatternSet(
3596 + PatternElementSet *sourcePS,
3597 + PatternElementSet *destPS);
3599 +static int getMPSName(
3600 + char **inPtr,
3601 + ErrorInfo *errInfo,
3602 + char **name );
3603 +static int getMPSTypeAttribute(
3604 + char **inPtr,
3605 + ErrorInfo *errInfo,
3606 + MatchPatternType *type);
3607 +static int getMPSGlobalAttribute(
3608 + char **inPtr,
3609 + char **errMsg,
3610 + int *isMonoPattern,
3611 + int *comment,
3612 + int *flash,
3613 + int *ignoreHighLightInfo);
3614 +static int getMPSPatternAttribute(
3615 + char **inPtr,
3616 + char **errMsg,
3617 + PatternElementKind *patternKind,
3618 + PatternWordBoundary *wordBoundary,
3619 + int *caseInsensitive,
3620 + int *regularExpression);
3622 +static void copyStringMatchTableForDialog(
3623 + StringMatchTable *sourceTable,
3624 + DialogMatchPatternInfo *dialogTable );
3625 +static void *copyMatchPatternElementForDialog(
3626 + MatchPatternTable *table,
3627 + int sourceElementIdx);
3628 +static void copyPatternForDialog(
3629 + MatchPatternTable *table,
3630 + PatternElement *sourcePattern,
3631 + DialogStringPatternElement **dialogPattern );
3632 +static void *copyGroupElementForDialog(
3633 + MatchPatternGroupElement *sourceGroup);
3634 +static void copySequenceElementForDialog(
3635 + StringMatchTable *sourceTable,
3636 + MatchPatternSequenceElement *sourceSeqElement,
3637 + DialogMatchPatternSequenceElement **dialogSeqElement );
3638 +static DialogMatchPatternSequenceElement *copyDialogSequenceElement(
3639 + DialogMatchPatternSequenceElement *sourceSeq);
3640 +static void freeDialogMatchPatternElement(
3641 + DialogMatchPatternTableElement *dialogElement );
3642 +static void freeDialogStringPatternElement(
3643 + DialogStringPatternElement *element);
3644 +static void freeDialogGroupElement(
3645 + DialogMatchPatternGroupElement *dialogGroup );
3646 +static void freeDialogSequenceElement(
3647 + DialogMatchPatternSequenceElement *dialogSeq );
3649 +static void copyDialogStringPatternsFromTable(
3650 + DialogMatchPatternTableElement *tableElement,
3651 + DialogStringPatterns *destPatterns);
3652 +static void copyDialogStringPatterns(
3653 + DialogStringPatterns *sourcePatterns,
3654 + DialogStringPatterns *destPatterns);
3655 +static void freeDialogStringPatterns(
3656 + DialogStringPatterns *patterns);
3658 +static DialogStringPatternElement *copyDialogStringPatternElement(
3659 + DialogStringPatternElement *sourceElement);
3661 +static void copyDialogPatternNamesFromGroup(
3662 + DialogMatchPatternGroupElement *group,
3663 + DialogStringPatterns *destPatterns);
3664 +static DialogStringPatternElement *copyDialogPatternName(
3665 + char *sourcePatternId);
3666 +static void copyDialogPatternNamesToGroup(
3667 + DialogStringPatterns *sourceNames,
3668 + DialogMatchPatternGroupElement *destGroup);
3670 +static void setDialogType(int dialogShowsStringPattern);
3671 +static void setSensitiveWordBoundaryBox(int enable);
3673 +static void *getStringPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
3674 + void *cbArg);
3675 +static void setStringPatternDisplayedCB(void *item, void *cbArg);
3676 +static void freeStringPatternItemCB(void *item);
3678 +static void *getMatchPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
3679 + void *cbArg);
3680 +static void setMatchPatternDisplayedCB(void *item, void *cbArg);
3681 +static void freeMatchPatternItemCB(void *item);
3682 +static int deleteMatchPatternItemCB(int itemIndex, void *cbArg);
3684 +static void matchPatternLangModeCB(Widget w, XtPointer clientData, XtPointer callData);
3685 +static void pmLanguageModeDialogCB(Widget w, XtPointer clientData, XtPointer callData);
3687 +static void destroyCB(Widget w, XtPointer clientData, XtPointer callData);
3688 +static void okCB(Widget w, XtPointer clientData, XtPointer callData);
3689 +static void applyCB(Widget w, XtPointer clientData, XtPointer callData);
3690 +static void checkCB(Widget w, XtPointer clientData, XtPointer callData);
3691 +static void restoreCB(Widget w, XtPointer clientData, XtPointer callData);
3692 +static void deleteCB(Widget w, XtPointer clientData, XtPointer callData);
3693 +static void closeCB(Widget w, XtPointer clientData, XtPointer callData);
3694 +static void helpCB(Widget w, XtPointer clientData, XtPointer callData);
3696 +static void matchPatTypeCB(Widget w, XtPointer clientData, XtPointer callData);
3697 +static void strPatRegExpressionCB(Widget w, XtPointer clientData, XtPointer callData);
3698 +static void changeExistingSubPattern(char *warnTitle);
3699 +static void changeStringPatternToGroup(void);
3700 +static void changeGroupToStringPattern(char *warnTitle);
3702 +static Widget createSubPatternNameMenu(
3703 + Widget parent,
3704 + char *currentSubPatName,
3705 + int allSubPatterns);
3706 +static void setupSubPatternNameList(
3707 + char *currentSubPatName,
3708 + int allSubPatterns,
3709 + NameList *nameList);
3710 +static void createSubPatNameMenuEntry(
3711 + Widget menu,
3712 + char *subPatName);
3713 +static void setSubPatternNameMenu(
3714 + const char *subPatName);
3715 +static void updateSubPatternNameMenu(
3716 + char *currentSubPatName,
3717 + int allSubPatterns);
3718 +static char *getSelectedSubPatternName(void);
3719 +static int isSubPatternNameInCurStrPat(
3720 + char *subPatName);
3722 +static DialogMatchPatternSequenceElement *readMatchPatternFields(int silent);
3723 +static int isStartPatternElementAvailable(
3724 + DialogStringPatterns *dialogPatterns);
3725 +static DialogStringPatternElement *readStringPatternFrameFields(int silent);
3727 +static int matchPatternDialogEmpty(void);
3728 +static int stringPatternFrameEmpty(void);
3729 +static int stringPatternFieldsEmpty(
3730 + int strPatIsRelatedToGroup);
3732 +static int getAndUpdateStringMatchTable(void);
3733 +static void updateStringMatchTable(
3734 + StringMatchTable *newTable);
3736 +static StringMatchTable *getDialogStringMatchTable(
3737 + DMPTranslationResult *result);
3738 +static StringMatchTable *translateDialogStringMatchTable(
3739 + DialogMatchPatternInfo *dialogTable,
3740 + DMPTranslationResult *result);
3741 +static MatchPatternTableElement *translateDialogMatchPatternTableElement(
3742 + DialogMatchPatternTableElement *dialogElement);
3743 +static void translateDialogPatterns(
3744 + DialogStringPatterns *dialogPatterns,
3745 + MatchPatternTableElement *newElement);
3746 +static MatchPatternGroupElement *translateDialogMatchPatternGroupElement(
3747 + ReadMatchPatternInfo *info,
3748 + DialogMatchPatternGroupElement *dialogGroup);
3749 +static void sortDialogPatternElementSet(
3750 + PatternElementSet *allPat,
3751 + MatchPatternTableElement *result);
3753 +static int stringMatchTableDiffer(
3754 + StringMatchTable *oldTable,
3755 + StringMatchTable *newTable);
3757 +static int patternElementDiffer(
3758 + PatternElement *oldPE,
3759 + MatchPatternTable *oldTab,
3760 + PatternElement *newPE,
3761 + MatchPatternTable *newTab);
3763 +static DialogMatchPatternGroupElement *getDialogGroupUsingMatchPattern(
3764 + char *matchPatternName);
3765 +static void removeMatchPatternFromGroup(
3766 + char *matchPatternName,
3767 + DialogMatchPatternGroupElement *group);
3768 +static void removeMatchPatternFromAllGroups(
3769 + char *matchPatternName);
3770 +static void renameMatchPatternInGroup(
3771 + char *oldMatchPatternName,
3772 + char *newMatchPatternName,
3773 + DialogMatchPatternGroupElement *group);
3774 +static void renameMatchPatternInAllGroups(
3775 + char *oldMatchPatternName,
3776 + char *newMatchPatternName);
3778 +static void freeVariableDialogData(
3779 + int keepLanguageModeName);
3781 +static void initGlobalBackRefList(
3782 + GlobalBackRefElement *list);
3783 +static void initStrPatBackRefList(
3784 + StringPattern *strPat);
3786 +StringPattern *getUniqueStringPattern(
3787 + PatternElement *pattern );
3789 +static void initErrorInfo(
3790 + ErrorInfo *errInfo);
3791 +static void freeErrorInfo(
3792 + ErrorInfo *errInfo);
3794 +static void freeXtPtr(void **ptr);
3795 +static void freePtr(void **ptr);
3798 + * matching pattern dialog information
3799 + */
3800 +static struct {
3801 + Widget mpdShell;
3802 + Widget mpdLmOptMenu;
3803 + Widget mpdLmPulldown;
3804 + Widget mpdMatchPatternNamesListW;
3805 + Widget mpdMatchPatternNameLbl;
3806 + Widget mpdMatchPatternNameW;
3807 + Widget mptbIndividualW;
3808 + Widget mptbSubPatternW;
3809 + Widget mptbContextGroupW;
3810 + Widget mpdGlobalAttributesLbl;
3811 + Widget gabSkipBtwStartEndW;
3812 + Widget gabFlashW;
3813 + Widget gabSyntaxBasedW;
3814 + Widget mpdStringPatternsLbl;
3815 + Widget mpdStringPatternsListW;
3816 + Widget mpdStringPatternTypeLbl;
3817 + Widget sptStartW;
3818 + Widget sptMiddleW;
3819 + Widget sptEndW;
3820 + Widget mpdWordBoundaryLbl;
3821 + Widget wbbBothW;
3822 + Widget wbbLeftW;
3823 + Widget wbbRightW;
3824 + Widget wbbNoneW;
3825 + Widget mpdStringAttributesLbl;
3826 + Widget sabCaseSensitiveW;
3827 + Widget sabRegularExpressionW;
3828 + Widget mpdStringPatternLbl;
3829 + Widget mpdStringPatternW;
3830 + Widget mpdSubPatNamesLbl;
3831 + Widget mpdSubPatNamesOptMenu;
3832 + Widget mpdSubPatNamesPulldown;
3833 + char *mpdLangModeName;
3834 + DialogMatchPatternSequenceElement *currentDmptSeqElement;
3835 + DialogMatchPatternTableElement *currentDmptElement;
3836 + DialogMatchPatternGroupElement *currentDmptGroup;
3837 + DialogStringPatterns currentStringPatterns;
3838 + DialogMatchPatternInfo mpdTable;
3839 + int mpdStringPatternIsDisplayed;
3840 +} MatchPatternDialog =
3841 + {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3842 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3843 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3844 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3845 + NULL, NULL, NULL, NULL,
3846 + {0, {NULL}},
3847 + {0, {NULL}},
3848 + True
3849 + };
3852 + * Matching pattern sources loaded from the nedit resources file or set
3853 + * by the user
3854 + */
3855 +static int NbrMatchTables = 0;
3856 +static StringMatchTable *MatchTables[MAX_LANGUAGE_MODES];
3859 + * Syntax:
3860 + * LanguagePatternSet ::=
3861 + * LanguageName{PatternStatement..}
3863 + * PatternStatement ::=
3864 + * name:[s]:[c][f][m][p][u]:([s|m|e][w|l|r][i]:"pattern":)..)\n)|
3865 + * name:g:"sub-pattern name":..\n..
3867 + * TypeAttribute:
3868 + * s : sub-pattern (pattern is only matched, if part of a pattern group).
3869 + * g : pattern (context) group (i.e. a sequence of sub-patterns).
3870 + * default: individual pattern (pattern is matched individually).
3871 + * GlobalAttribute:
3872 + * c : the content between start and end pattern is skipped
3873 + * during parsing (e.g. pattern encloses a comment).
3874 + * f : flash matching pattern (if not set, then only jump
3875 + * to matching pattern is supported).
3876 + * m : mono pattern - set exist out of only one single pattern
3877 + * (start pattern = end pattern; e.g. quotes like ")
3878 + * p : ignore highlight info code of single patterns of this set
3879 + * ("plain").
3880 + * StringPatternKind:
3881 + * s : start string pattern.
3882 + * m : middle string pattern.
3883 + * e : end string pattern.
3884 + * WordBoundaryAttribute:
3885 + * w : pattern is word (i.e. before and after pattern
3886 + * there must be a delimiter).
3887 + * l : before pattern must be a delimiter (left side).
3888 + * r : after pattern must be a delimiter (right side).
3889 + * default: neither before nor after pattern must be a delimiter.
3890 + * StringAttribute:
3891 + * i : pattern is case insensitive (if not set: pattern is
3892 + * case sensitive).
3893 + * x : pattern is regular expression (if not set: pattern is
3894 + * literal string).
3896 + * \n : end of pattern
3897 + */
3899 +static char *DefaultStringMatchTable[] = {
3900 + "PLAIN{"
3901 + "Round braces::fp:s:\"(\":e:\")\":\n"
3902 + "Curly braces::fp:s:\"{\":e:\"}\":\n"
3903 + "Squared braces::fp:s:\"[\":e:\"]\":\n"
3904 + "Sharp braces::fp:s:\"<\":e:\">\":\n}",
3905 + "C++{"
3906 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
3907 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3908 + "Single Quotes:s:cmf:s:\"'\":\n"
3909 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3910 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3911 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3912 + "#ifdef statement:s:f:sx:\"#\\s*ifdef\":sx:\"#\\s*ifndef\":sx:\"#\\s*if\":mx:\"#\\s*elif\":mx:\"#\\s*else\":ex:\"#\\s*endif\":\n"
3913 + "#if group:g:Comment:Double Quotes:Single Quotes:#ifdef statement:\n"
3914 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
3915 + "C{"
3916 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
3917 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3918 + "Single Quotes:s:cmf:s:\"'\":\n"
3919 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3920 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3921 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3922 + "#ifdef statement:s:f:sx:\"#\\s*ifdef\":sx:\"#\\s*ifndef\":sx:\"#\\s*if\":mx:\"#\\s*elif\":mx:\"#\\s*else\":ex:\"#\\s*endif\":\n"
3923 + "#if group:g:Comment:Double Quotes:Single Quotes:#ifdef statement:\n"
3924 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
3925 + "CSS{"
3926 + "comment:s:cf:s:\"/*\":e:\"*/\":\n"
3927 + "curly braces:s:f:s:\"{\":e:\"}\":\n"
3928 + "round braces:s:f:s:\"(\":e:\")\":\n"
3929 + "double quotes:s:cfm:s:\"\"\"\":\n"
3930 + "single quotes:s:cfm:s:\"'\":\n"
3931 + "braces:g:comment:single quotes:double quotes:curly braces:round braces:\n}",
3932 + "Csh{"
3933 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3934 + "Single Quotes:s:cmf:s:\"'\":\n"
3935 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3936 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3937 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3938 + "if statement:s:f:sw:\"if\":mw:\"else\":ew:\"endif\":\n"
3939 + "switch statement:s:f:sw:\"switch\":mw:\"case\":mw:\"default\":ew:\"endsw\":\n"
3940 + "foreach statement:s:f:sw:\"for\":ew:\"end\":\n"
3941 + "while statement:s:f:sw:\"while\":ew:\"end\":\n"
3942 + "statement group:g:Double Quotes:Single Quotes:if statement:switch statement:foreach statement:while statement:\n"
3943 + "Braces:g:Double Quotes:Single Quotes:Squared braces:Round braces:Curly braces:\n}",
3944 + "Java{"
3945 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
3946 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3947 + "Single Quotes:s:cmf:s:\"'\":\n"
3948 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3949 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3950 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3951 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
3952 + "JavaScript{"
3953 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
3954 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3955 + "Single Quotes:s:cmf:s:\"'\":\n"
3956 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3957 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3958 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3959 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
3960 + "Makefile{"
3961 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3962 + "Single Quotes:s:cmf:s:\"'\":\n"
3963 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3964 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3965 + "Braces:g:Double Quotes:Single Quotes:Curly braces:Round braces:\n}",
3966 + "NEdit Macro{"
3967 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3968 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3969 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3970 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3971 + "Braces:g:Double Quotes:Curly braces:Round braces:Squared braces:\n}",
3972 + "Pascal{"
3973 + "Single Quotes:s:cmf:s:\"'\":\n"
3974 + "Comment1:s:cf:s:\"(*\":e:\"*)\":\n"
3975 + "Comment2:s:cf:s:\"{\":e:\"}\":\n"
3976 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3977 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3978 + "Block:s:f:swi:\"begin\":ewi:\"end\":\n"
3979 + "Case:s:fp:swi:\"case\":ewi:\"end\":\n"
3980 + "Record:s:f:swi:\"record\":ewi:\"end\":\n"
3981 + "Statement:g:Comment1:Comment2:Single Quotes:Block:Case:Record:\n"
3982 + "Braces:g:Comment1:Comment2:Single Quotes:Round braces:Squared braces:\n}",
3983 + "Perl{"
3984 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
3985 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3986 + "Single Quotes:s:cmf:s:\"'\":\n"
3987 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3988 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3989 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3990 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
3991 + "SGML HTML{"
3992 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
3993 + "Single Quotes:s:cmf:s:\"'\":\n"
3994 + "Sharp braces:s:f:s:\"<\":e:\">\":\n"
3995 + "Round braces:s:f:s:\"(\":e:\")\":\n"
3996 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
3997 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
3998 + "Braces:g:Double Quotes:Single Quotes:Sharp braces:Curly braces:Round braces:Squared braces:\n}",
3999 + "Sh Ksh Bash{"
4000 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4001 + "Single Quotes:s:cmf:s:\"'\":\n"
4002 + "Back Quotes:s:cfm:s:\"`\":\n"
4003 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4004 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4005 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4006 + "if statement:s:f:sw:\"if\":mw:\"elif\":mw:\"else\":ew:\"fi\":\n"
4007 + "case statement:s:f:sw:\"case\":ew:\"esac\":\n"
4008 + "for statement:s:f:sw:\"for\":mw:\"do\":ew:\"done\":\n"
4009 + "while statement:s:f:sw:\"while\":mw:\"do\":ew:\"done\":\n"
4010 + "statement group:g:Double Quotes:Single Quotes:if statement:case statement:for statement:while statement:\n"
4011 + "Braces:g:Double Quotes:Single Quotes:Back Quotes:Squared braces:Round braces:Curly braces:\n}",
4012 + "XML{"
4013 + "round braces:s:f:s:\"(\":e:\")\":\n"
4014 + "comment:s:cf:s:\"<!--\":e:\"-->\":\n"
4015 + "cdata + ignore:s:cf:sx:\"\\<!\\[((?icdata)|(\\s*IGNORE\\s*))\\[\":ex:\"\\]\\]\\>\":\n"
4016 + "short element:s:cf:sx:\"(?n\\<[\\l_][^@$%/\"\"';!>\\s]*(?=[^>]*/\\>))\":ex:\"/\\>\":\n"
4017 + "element pair:s:f:sx:\"(?n\\<(*1[\\l|_][^@$%/\"\"';!>\\s]*)\\>)\":sx:\"(?n\\<(*1[\\l|_][^@$%/\"\"';!>\\s]*)(?=[^>]*[^/]\\>))\":eix:\"\\</\\1\\>\":\n"
4018 + "processing instruction:s:f:sx:\"\\<\\?\\S+\":ex:\"\\?\\>\":\n"
4019 + "double quotes:s:cmf:s:\"\"\"\":\n"
4020 + "single quotes:s:cmf:s:\"'\":\n"
4021 + "tags:g:comment:double quotes:single quotes:round braces:cdata + ignore:element pair:short element:processing instruction:\n}",
4022 + };
4024 +static char *StandardStringMatchTable =
4025 + "{Round braces::fp:s:\"(\":e:\")\":\n"
4026 + "Curly braces::fp:s:\"{\":e:\"}\":\n"
4027 + "Squared braces::fp:s:\"[\":e:\"]\":\n}";
4030 +** Return string match table related to given language mode name.
4031 +** Return NULL, if no table is found.
4033 +void *FindStringMatchTable(const char *langModeName)
4035 + const char *nameToSearch;
4036 + int i;
4038 + if (langModeName == NULL)
4039 + nameToSearch = PLAIN_LM_STRING;
4040 + else
4041 + nameToSearch = langModeName;
4043 + for (i=0; i<NbrMatchTables; i++)
4044 + if (!strcmp(nameToSearch, MatchTables[i]->smtLanguageMode))
4045 + return (void *)MatchTables[i];
4046 + return NULL;
4050 +** Change the language mode name of string match tables for language
4051 +** "oldName" to "newName" in both the stored tables, and the table
4052 +** currently being edited in the dialog.
4054 +void RenameStringMatchTable(const char *oldName, const char *newName)
4056 + int i;
4058 + for (i=0; i<NbrMatchTables; i++)
4060 + if (!strcmp(oldName, MatchTables[i]->smtLanguageMode))
4062 + XtFree(MatchTables[i]->smtLanguageMode);
4063 + MatchTables[i]->smtLanguageMode = XtNewString(newName);
4066 + if (MatchPatternDialog.mpdShell != NULL)
4068 + if (!strcmp(MatchPatternDialog.mpdLangModeName, oldName))
4070 + XtFree(MatchPatternDialog.mpdLangModeName);
4071 + MatchPatternDialog.mpdLangModeName = XtNewString(newName);
4077 +** Delete string match table related to given language mode name.
4079 +void DeleteStringMatchTable(const char *langModeName)
4081 + int i;
4083 + for (i=0; i<NbrMatchTables; i++)
4085 + if (!strcmp(langModeName, MatchTables[i]->smtLanguageMode))
4087 + /*
4088 + * free (delete) existing matching pattern
4089 + */
4090 + freeStringMatchTable(MatchTables[i]);
4091 + memmove(
4092 + &MatchTables[i],
4093 + &MatchTables[i+1],
4094 + (NbrMatchTables-1 - i) * sizeof(StringMatchTable *));
4095 + NbrMatchTables--;
4096 + break;
4102 +** Assign a standard string match table to a given new language mode.
4104 +void AssignStandardStringMatchTable(const char *langModeName)
4106 + char *list;
4107 + StringMatchTable *newTable;
4109 + /*
4110 + * assign standard table for new language mode
4111 + * add table to end
4112 + */
4113 + list = StandardStringMatchTable;
4114 + newTable =
4115 + readMatchPatternSetContent(&list, list, XtNewString(langModeName));
4117 + /*
4118 + * add table to end
4119 + */
4120 + MatchTables[NbrMatchTables++] = newTable;
4124 +** Returns True if there is a string match table, or potential table
4125 +** not yet committed in the match pattern dialog for a language mode,
4127 +int LMHasStringMatchTable(const char *languageMode)
4129 + StringMatchTable *table = FindStringMatchTable(languageMode);
4131 + if (table != NULL && table->smtNumberOfSeqElements != 0)
4132 + return True;
4133 + return MatchPatternDialog.mpdShell != NULL &&
4134 + !strcmp(MatchPatternDialog.mpdLangModeName, languageMode) &&
4135 + MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements != 0;
4139 +** Read a string representing string matching pattern sets and add them
4140 +** to the StringMatchTable list of loaded string match patterns.
4141 +** Returns true, if read of string was successful.
4143 +int LoadMatchPatternString(char *inString)
4145 + char *inPtr = inString;
4146 + StringMatchTable *table;
4147 + int i;
4149 + for (;;)
4151 + /*
4152 + * read each matching pattern set
4153 + */
4154 + table = readMatchPatternSet(&inPtr);
4156 + if (table != NULL)
4158 + /*
4159 + * add/change the pattern set in the list
4160 + */
4161 + for (i=0; i<NbrMatchTables; i++)
4163 + if (!strcmp(MatchTables[i]->smtLanguageMode, table->smtLanguageMode))
4165 + freeStringMatchTable(MatchTables[i]);
4166 + MatchTables[i] = table;
4167 + break;
4170 + if (i == NbrMatchTables)
4172 + MatchTables[NbrMatchTables++] = table;
4173 + if (NbrMatchTables > MAX_LANGUAGE_MODES)
4175 + return False;
4180 + /*
4181 + * find end of this pattern. if the string ends here, we're done
4182 + */
4183 + inPtr = strstr(inPtr, "\n");
4184 + if (inPtr == NULL)
4186 + return True;
4189 + /*
4190 + * skip newline, tabs & spaces in front of next pattern.
4191 + * if the string ends here, we're done
4192 + */
4193 + inPtr += strspn(inPtr, " \t\n");
4194 + if (*inPtr == '\0')
4196 + return True;
4202 +** Create a string in the correct format for the matchPatterns resource,
4203 +** containing all of the matching pattern information from the stored
4204 +** matching pattern sets for this NEdit session.
4206 +char *WriteMatchPatternString(void)
4208 + char *outStr, *str, *escapedStr;
4209 + textBuffer *outBuf;
4210 + int i, written = False;
4211 + StringMatchTable *table;
4213 + outBuf = BufCreate();
4215 + for (i=0; i<NbrMatchTables; i++)
4217 + table = MatchTables[i];
4219 + written = True;
4221 + BufInsert(outBuf, outBuf->length, table->smtLanguageMode);
4222 + BufInsert(outBuf, outBuf->length, ":");
4224 + if (isDefaultMatchPatternTable(table))
4226 + BufInsert(outBuf, outBuf->length, "Default\n\t");
4228 + else
4230 + BufInsert(outBuf, outBuf->length, "{\n");
4231 + BufInsert(outBuf, outBuf->length,
4232 + str = createMatchPatternsString(table, "\t\t"));
4233 + XtFree(str);
4234 + BufInsert(outBuf, outBuf->length, "\t}\n\t");
4238 + /*
4239 + * Get the output string, and lop off the trailing newline and tab
4240 + */
4241 + outStr = BufGetRange(outBuf, 0, outBuf->length - (written?2:0));
4242 + BufFree(outBuf);
4244 + /*
4245 + * Protect newlines and backslashes from translation by the resource
4246 + * reader
4247 + */
4248 + escapedStr = EscapeSensitiveChars(outStr);
4250 + XtFree(outStr);
4252 + return escapedStr;
4256 +** Check, if last pattern is a duplicate of a previous pattern.
4257 +** Convert last pattern to a reference, if so.
4259 +static void treatDuplicatedPattern(
4260 + MatchPatternTable *table,
4261 + PatternElement *prevPattern,
4262 + PatternReference prevPatRef,
4263 + PatternElement *lastPattern,
4264 + PatternReference lastPatRef)
4266 + StringPattern *prevStringPat;
4267 + StringPattern *lastStringPat;
4268 + StringPattern *stringPat;
4269 + PatternReference *oldList;
4270 + int nbrOfRef;
4272 + /*
4273 + * No duplicate check needed, if previous pattern is a reference,
4274 + * due to the related multi pattern element is checked before.
4275 + */
4276 + if (prevPattern->peType == PET_REFERENCE)
4277 + return;
4279 + prevStringPat = GetStringPattern(table, prevPattern);
4280 + lastStringPat = GetStringPattern(table, lastPattern);
4282 + if (!AllocatedStringsDiffer(prevStringPat->spText, lastStringPat->spText) &&
4283 + !AllocatedStringsDiffer(prevStringPat->spOrigText, lastStringPat->spOrigText) &&
4284 + prevStringPat->spWordBoundary == lastStringPat->spWordBoundary &&
4285 + prevStringPat->spCaseInsensitive == lastStringPat->spCaseInsensitive &&
4286 + prevStringPat->spRegularExpression == lastStringPat->spRegularExpression)
4288 + /*
4289 + * Patterns are identical: Is prevPattern already a multi pattern ?
4290 + */
4291 + if (prevPattern->peType == PET_MULTIPLE)
4293 + /*
4294 + * just add ref. to "lastPattern" to the ref. list
4295 + */
4296 + (prevPattern->peVal.peuMulti.mpNumberOfReferences) ++;
4297 + nbrOfRef = prevPattern->peVal.peuMulti.mpNumberOfReferences;
4298 + oldList = prevPattern->peVal.peuMulti.mpRefList;
4299 + prevPattern->peVal.peuMulti.mpRefList =
4300 + (PatternReference *)XtMalloc( nbrOfRef * sizeof(PatternReference) );
4301 + memcpy(
4302 + prevPattern->peVal.peuMulti.mpRefList,
4303 + oldList,
4304 + (nbrOfRef-1) * sizeof(PatternReference) );
4305 + prevPattern->peVal.peuMulti.mpRefList[nbrOfRef-1] = lastPatRef;
4306 + XtFree( (char *)oldList );
4308 + else
4310 + /*
4311 + * convert prev. single pattern to multi pattern
4312 + */
4313 + stringPat = &prevPattern->peVal.peuSingle;
4314 + prevPattern->peType = PET_MULTIPLE;
4315 + prevPattern->peVal.peuMulti.mpStringPattern = *stringPat;
4316 + prevPattern->peVal.peuMulti.mpNumberOfReferences = 1;
4317 + prevPattern->peVal.peuMulti.mpRefList =
4318 + (PatternReference *)XtMalloc( sizeof(PatternReference) );
4319 + prevPattern->peVal.peuMulti.mpRefList[0] = lastPatRef;
4322 + /*
4323 + * convert last single pattern to reference
4324 + */
4325 + freeStringPattern( &(lastPattern->peVal.peuSingle) );
4326 + lastPattern->peType = PET_REFERENCE;
4327 + lastPattern->peVal.peuRef = prevPatRef;
4332 +** Check, if last pattern is a duplicate of a pattern stored within a
4333 +** previous match pattern table element.
4334 +** Convert last pattern to a reference, if so.
4336 +static void treatDuplicatedPatternElements(
4337 + MatchPatternTable *table,
4338 + MatchPatternTableElement *prevElement,
4339 + int prevElementIdx,
4340 + PatternElement *lastPattern,
4341 + PatternReference lastPatRef)
4343 + int i;
4344 + PatternReference prevPatRef;
4346 + prevPatRef.prElementIdx = prevElementIdx;
4348 + for (i=0; i<prevElement->mpteAll.pesNumberOfPattern; i++)
4350 + prevPatRef.prPatternIdx = i;
4351 + treatDuplicatedPattern(
4352 + table,
4353 + prevElement->mpteAll.pesPattern[i],
4354 + prevPatRef,
4355 + lastPattern,
4356 + lastPatRef);
4361 +** Check, if a pattern of last match pattern table element is a
4362 +** duplicate of a pattern stored within a previous match pattern table
4363 +** element.
4364 +** Convert duplicated last patterns to references, if so.
4366 +static void treatDuplicatedMTElements(
4367 + MatchPatternTable *table,
4368 + MatchPatternTableElement *prevElement,
4369 + int prevElementIdx,
4370 + MatchPatternTableElement *lastElement,
4371 + int lastElementIdx)
4373 + int i;
4374 + PatternReference lastPatRef;
4376 + lastPatRef.prElementIdx = lastElementIdx;
4378 + for (i=0; i<lastElement->mpteAll.pesNumberOfPattern; i++)
4380 + lastPatRef.prPatternIdx = i;
4381 + treatDuplicatedPatternElements(
4382 + table,
4383 + prevElement,
4384 + prevElementIdx,
4385 + lastElement->mpteAll.pesPattern[i],
4386 + lastPatRef);
4391 +** Convert all duplicated patterns of given match pattern table to
4392 +** references.
4394 +static void treatDuplicatedMTEntries(
4395 + MatchPatternTableElement **element,
4396 + int nbrOfElements)
4398 + int i;
4399 + MatchPatternTableElement *lastElement;
4400 + int lastElementIdx;
4401 + MatchPatternTable table;
4403 + if (nbrOfElements < 2)
4404 + return;
4406 + lastElementIdx = nbrOfElements - 1;
4407 + lastElement = element[lastElementIdx];
4409 + table.mptElements = element;
4410 + table.mptNumberOfElements = nbrOfElements;
4412 + for (i=0; i<nbrOfElements-1; i ++)
4414 + treatDuplicatedMTElements( &table, element[i], i, lastElement, lastElementIdx );
4419 +** Compile regular expressions of all string patterns of given
4420 +** match pattern table element.
4421 +** Returns true, if compilation fails.
4423 +static int createStrPatRegExpOfElement(
4424 + ReadMatchPatternInfo *readPatInfo,
4425 + MatchPatternTableElement *element,
4426 + ErrorInfo *errInfo)
4428 + int i;
4429 + StringPattern *strPat;
4431 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
4433 + strPat = getReadStringPattern(readPatInfo, element->mpteAll.pesPattern[i]);
4435 + /*
4436 + * if current string pattern holds a regular expression, then
4437 + * compile it
4438 + */
4439 + if (strPat->spRegularExpression)
4441 + if (createStrPatRegExp(strPat, errInfo))
4443 + /*
4444 + * compilation was not successful
4445 + */
4446 + errInfo->eiMPTabElementName = XtNewString(element->mpteName);
4447 + return True;
4452 + return False;
4456 +** Compile regular expressions of given string pattern.
4457 +** Returns true, if compilation fails.
4459 +static int createStrPatRegExp(
4460 + StringPattern *strPat,
4461 + ErrorInfo *errInfo)
4463 + char *regExpString;
4464 + char *compileMsg;
4466 + /*
4467 + * compose regular expression for start string pattern.
4468 + */
4469 + if( strPat->spCaseInsensitive)
4471 + /*
4472 + * Add '(?i .. )' to given text for case insensitive search.
4473 + * Allocate buffer to hold 5 more char than text length
4474 + * (4 char '(?i)' + \0 char.
4475 + */
4476 + regExpString = XtMalloc(strPat->spLength + 5);
4477 + strcpy(regExpString, "(?i");
4478 + strcat(regExpString, strPat->spText);
4479 + strcat(regExpString, ")");
4481 + else
4483 + regExpString = strPat->spText;
4486 + /*
4487 + * compile regular expression & free allocated string buffer,
4488 + * if applicable.
4489 + */
4490 + strPat->spTextRE =
4491 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
4493 + if (strPat->spTextRE == NULL)
4495 + /*
4496 + * compilation was not successful: adapt error reason by
4497 + * converting local backrefs to global ones.
4498 + */
4499 + adaptCompileMsg(compileMsg, strPat->spGlobalToLocalBackRef);
4501 + errInfo->eiRegExpCompileMsg = compileMsg;
4502 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
4505 + if (strPat->spCaseInsensitive)
4506 + XtFree( regExpString );
4508 + return (strPat->spTextRE == NULL);
4512 +** adapt regular expression compilation message by converting local
4513 +** backrefs to global ones.
4515 +static void adaptCompileMsg(
4516 + char *compileMsg,
4517 + int *globalToLocalBackRef)
4519 + int localId;
4520 + int globalId;
4521 + char *s = compileMsg;
4523 + while (*s != '\0')
4525 + if (*s == '\\')
4527 + if (isdigit((unsigned char)*(s+1)))
4529 + /*
4530 + * \n (n=1..9) found: substitute local by global back ref.
4531 + */
4532 + s ++;
4534 + localId =
4535 + (int)((unsigned char)*s - (unsigned char)'0');
4537 + globalId = localToGlobalBackRef(globalToLocalBackRef, localId);
4539 + *s = (char)((int)('0') + globalId);
4541 + else if (*(s+1) != '\0')
4542 + s ++;
4544 + s ++;
4549 +** translate given local backref to global backref by using
4550 +** given globalToLocalBackRef list.
4552 +static int localToGlobalBackRef(
4553 + int *globalToLocalBackRef,
4554 + int localId)
4556 + int i;
4558 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
4560 + if (globalToLocalBackRef[i] == localId)
4561 + return i+1;
4564 + return 0;
4568 +** Create a regular expression holding keywords of given start & end
4569 +** pattern set.
4570 +** Returns true, if creation of regular expression has failed.
4572 +static int createStartEndRegExp(
4573 + ReadMatchPatternInfo *readMatchPatternInfo,
4574 + MatchPatternTableElement *element,
4575 + ErrorInfo *errInfo)
4577 + char *regExpString;
4578 + char *compileMsg;
4580 + /*
4581 + * compose regular expression for start / end pattern.
4582 + */
4583 + composeStartEndRegExpString(
4584 + readMatchPatternInfo,
4585 + element,
4586 + &regExpString);
4588 + /*
4589 + * compile regular expression & free allocated string buffer.
4590 + */
4591 + element->mpteStartEndRE =
4592 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
4594 + XtFree( regExpString );
4596 + if( element->mpteStartEndRE == NULL)
4598 + errInfo->eiRegExpCompileMsg = compileMsg;
4599 + errInfo->eiDetail = "Error compiling start / end reg. exp.";
4602 + return (element->mpteStartEndRE == NULL);
4606 +** Create a regular expression holding keywords of given group element.
4607 +** Returns true, if creation of regular expression has failed.
4609 +static int createGroupRegExp(
4610 + ReadMatchPatternInfo *readPatInfo,
4611 + MatchPatternGroupElement *group,
4612 + ErrorInfo *errInfo)
4614 + int i;
4615 + MatchPatternTableElement *element;
4616 + RegExpStringInfo regExpStringInfo;
4617 + char *regExpString;
4618 + regexp *keywordRE;
4619 + char *compileMsg;
4621 + /*
4622 + * Allocate buffers for keyword regular expression of this group.
4623 + */
4624 + setupRegExpStringBuffers(
4625 + readPatInfo,
4626 + &regExpStringInfo);
4628 + for (i=0; i<group->mpgeNumberOfSubPatterns; i++)
4630 + element = getPatternOfName(readPatInfo, group->mpgeSubPatternIds[i]);
4631 + /*
4632 + * Add the keywords of the sub pattern to the keyword regular
4633 + * expression string buffer of new group.
4634 + */
4635 + addElementToRegExpString(
4636 + element,
4637 + readPatInfo,
4638 + &regExpStringInfo);
4641 + /*
4642 + * Assemble and compile the resulting keyword regular expression string.
4643 + */
4644 + catSMTRegExpStrings(
4645 + &regExpStringInfo,
4646 + &regExpString);
4648 + keywordRE = CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
4650 + XtFree( regExpString );
4652 + if (keywordRE == NULL)
4654 + errInfo->eiMPTabElementName = XtNewString(group->mpgeName);
4655 + errInfo->eiRegExpCompileMsg = compileMsg;
4656 + errInfo->eiDetail = "Group: Compile reg. exp. error";
4659 + group->mpgeKeywordRE = keywordRE;
4661 + return (keywordRE == NULL);
4665 +** Allocate memory for regular expression strings to be
4666 +** created out of read match pattern info.
4668 +static void setupRegExpStringBuffers(
4669 + ReadMatchPatternInfo *readMatchPatternInfo,
4670 + RegExpStringInfo *regExpStringInfo)
4672 + int totalLen;
4673 + int nbrOfMultiPatterns;
4674 + int sizeOfPatRefs;
4676 + /*
4677 + * determine total length of pattern characters to determine
4678 + * the size of a string buffer for the regular expression to
4679 + * compose. Count number of total multi patterns, too.
4680 + */
4681 + totalLen =
4682 + totalKeywordOfTableLen( readMatchPatternInfo, &nbrOfMultiPatterns );
4684 + /*
4685 + * allocate memory to store added multi pattern references (to avoid
4686 + * duplicated keywords strings later on).
4687 + */
4688 + sizeOfPatRefs = sizeof(PatternReference *) * nbrOfMultiPatterns;
4690 + regExpStringInfo->resiAddedMultiPat =
4691 + (PatternReference **)XtMalloc( sizeOfPatRefs );
4693 + regExpStringInfo->resiNbrOfAddedMultiPat = 0;
4695 + /*
4696 + * init. ID of capturing local backrefs
4697 + */
4698 + regExpStringInfo->resiLocalBackRefID = 1;
4700 + /*
4701 + * allocate & init. string buffers for regular expression:
4702 + * 3 times the size + x of all pattern characters (due to
4703 + * a.) each char may need to be escaped
4704 + * b.) '<(?:', ')>', ')' and '|' need to be added.
4705 + */
4706 + regExpStringInfo->resiNoneWBRegExpString = XtMalloc( 3 * totalLen );
4707 + regExpStringInfo->resiLeftWBRegExpString = XtMalloc( 3 * totalLen + 5 );
4708 + regExpStringInfo->resiRightWBRegExpString = XtMalloc( 3 * totalLen + 5 );
4709 + regExpStringInfo->resiBothWBRegExpString = XtMalloc( 3 * totalLen + 6 );
4711 + strcpy( regExpStringInfo->resiNoneWBRegExpString, "" );
4712 + strcpy( regExpStringInfo->resiLeftWBRegExpString, "" );
4713 + strcpy( regExpStringInfo->resiRightWBRegExpString, "" );
4714 + strcpy( regExpStringInfo->resiBothWBRegExpString, "" );
4718 +** Concatenate given 'partToAdd' string to result string, separated
4719 +** by an OR ('|'). Add 'postfix' at end of result string.
4721 +static void addSMTRegExpString(
4722 + char *result,
4723 + char *partToAdd,
4724 + const char *postfix)
4726 + if (strlen(partToAdd) != 0)
4728 + if (strlen(result) != 0)
4730 + strcat( result, "|" );
4733 + strcat( result, partToAdd );
4735 + strcat( result, postfix );
4741 +** Return a string representing given string match table.
4743 +static char *createMatchPatternsString(
4744 + StringMatchTable *table,
4745 + char *indentStr)
4747 + char *outStr, *str;
4748 + textBuffer *outBuf;
4749 + int i, j;
4750 + MatchPatternSequenceElement *seq;
4751 + MatchPatternTableElement *element;
4752 + MatchPatternGroupElement *group;
4754 + outBuf = BufCreate();
4756 + for (i=0; i<table->smtNumberOfSeqElements; i++)
4758 + seq = table->smtSequence[i];
4760 + BufInsert(outBuf, outBuf->length, indentStr);
4761 + BufInsert(outBuf, outBuf->length, seq->mpseName);
4762 + BufInsert(outBuf, outBuf->length, ":");
4764 + if (seq->mpseType == MPT_GROUP)
4766 + BufInsert(outBuf, outBuf->length, "g:");
4768 + group = table->smtGroups[seq->mpseIndex];
4770 + for (j=0; j < group->mpgeNumberOfSubPatterns; j ++)
4772 + BufInsert(outBuf, outBuf->length, group->mpgeSubPatternIds[j]);
4773 + BufInsert(outBuf, outBuf->length, ":");
4776 + else
4778 + if (seq->mpseType == MPT_SUB)
4780 + BufInsert(outBuf, outBuf->length, "s");
4782 + BufInsert(outBuf, outBuf->length, ":");
4784 + element = table->smtAllPatterns->mptElements[seq->mpseIndex];
4786 + /*
4787 + * write global attributes
4788 + */
4789 + if (element->mpteSkipBtwnStartEnd)
4790 + BufInsert(outBuf, outBuf->length, "c");
4791 + if (element->mpteFlash)
4792 + BufInsert(outBuf, outBuf->length, "f");
4793 + if (element->mpteIsMonoPattern)
4794 + BufInsert(outBuf, outBuf->length, "m");
4795 + if (element->mpteIgnoreHighLightInfo)
4796 + BufInsert(outBuf, outBuf->length, "p");
4797 + BufInsert(outBuf, outBuf->length, ":");
4799 + /*
4800 + * write string patterns
4801 + */
4802 + for (j=0; j < element->mpteAll.pesNumberOfPattern; j ++)
4804 + BufInsert(
4805 + outBuf,
4806 + outBuf->length,
4807 + str =
4808 + createPatternElementString(
4809 + table->smtAllPatterns,
4810 + element->mpteAll.pesPattern[j]));
4811 + XtFree(str);
4815 + BufInsert(outBuf, outBuf->length, "\n");
4818 + outStr = BufGetAll(outBuf);
4819 + BufFree(outBuf);
4821 + return outStr;
4825 +** Return a string representing given pattern element.
4827 +static char *createPatternElementString(
4828 + MatchPatternTable *table,
4829 + PatternElement *pat)
4831 + char *outStr, *str;
4832 + textBuffer *outBuf;
4833 + StringPattern *strPat;
4835 + outBuf = BufCreate();
4837 + strPat = GetStringPattern(table, pat);
4839 + /*
4840 + * write string pattern kind
4841 + */
4842 + if (pat->peKind == PEK_START)
4843 + BufInsert(outBuf, outBuf->length, "s");
4844 + else if (pat->peKind == PEK_MIDDLE)
4845 + BufInsert(outBuf, outBuf->length, "m");
4846 + else if (pat->peKind == PEK_END)
4847 + BufInsert(outBuf, outBuf->length, "e");
4849 + /*
4850 + * write word boundary
4851 + */
4852 + if (strPat->spWordBoundary == PWB_BOTH)
4853 + BufInsert(outBuf, outBuf->length, "w");
4854 + else if (strPat->spWordBoundary == PWB_LEFT)
4855 + BufInsert(outBuf, outBuf->length, "l");
4856 + else if (strPat->spWordBoundary == PWB_RIGHT)
4857 + BufInsert(outBuf, outBuf->length, "r");
4859 + /*
4860 + * write case insensitive flag
4861 + */
4862 + if (strPat->spCaseInsensitive)
4863 + BufInsert(outBuf, outBuf->length, "i");
4865 + /*
4866 + * write regular expression flag
4867 + */
4868 + if (strPat->spRegularExpression)
4869 + BufInsert(outBuf, outBuf->length, "x");
4871 + BufInsert(outBuf, outBuf->length, ":");
4873 + /*
4874 + * write pattern string
4875 + */
4876 + if( strPat->spOrigText != NULL)
4877 + BufInsert(
4878 + outBuf,
4879 + outBuf->length,
4880 + str = MakeQuotedString(strPat->spOrigText));
4881 + else
4882 + BufInsert(
4883 + outBuf,
4884 + outBuf->length,
4885 + str = MakeQuotedString(strPat->spText));
4886 + XtFree(str);
4888 + BufInsert(outBuf, outBuf->length, ":");
4890 + outStr = BufGetAll(outBuf);
4891 + BufFree(outBuf);
4893 + return outStr;
4897 +** Given a language mode name, determine if there is a default (built-in)
4898 +** string match table available for that language mode, and if so, read it and
4899 +** return a new allocated copy of it. The returned pattern set should be
4900 +** freed by the caller with freeStringMatchTable().
4902 +static StringMatchTable *readDefaultStringMatchTable(const char *langModeName)
4904 + int i, modeNameLen;
4905 + char *list;
4907 + modeNameLen = strlen(langModeName);
4909 + for (i=0; i<(int)XtNumber(DefaultStringMatchTable); i++)
4911 + if (!strncmp(langModeName, DefaultStringMatchTable[i], modeNameLen) &&
4912 + DefaultStringMatchTable[i][modeNameLen] == '{')
4914 + list = DefaultStringMatchTable[i];
4915 + return readMatchPatternSet(&list);
4919 + list = StandardStringMatchTable;
4920 + return readMatchPatternSetContent(&list, list, XtNewString(langModeName));
4924 +** Return true, if table exactly matches one of the default matching
4925 +** pattern tables.
4927 +static int isDefaultMatchPatternTable(StringMatchTable *table)
4929 + StringMatchTable *defaultTable;
4930 + int retVal;
4932 + defaultTable = readDefaultStringMatchTable(table->smtLanguageMode);
4934 + if (defaultTable == NULL)
4935 + return False;
4937 + retVal = !stringMatchTableDiffer(table, defaultTable);
4939 + freeStringMatchTable(defaultTable);
4941 + return retVal;
4945 +** Read in a string match pattern table character string,
4946 +** and advance *inPtr beyond it.
4947 +** Returns NULL and outputs an error to stderr on failure.
4949 +static StringMatchTable *readMatchPatternSet(char **inPtr)
4951 + char *languageMode;
4952 + StringMatchTable *table = NULL;
4953 + char *stringStart = *inPtr;
4954 + ErrorInfo errInfo;
4956 + initErrorInfo(&errInfo);
4958 + /*
4959 + * remove leading whitespace
4960 + */
4961 + *inPtr += strspn(*inPtr, " \t\n");
4963 + /*
4964 + * read language mode field
4965 + */
4966 + languageMode = ReadSymbolicField(inPtr);
4968 + /*
4969 + * look for initial brace
4970 + */
4971 + if (**inPtr == ':')
4973 + (*inPtr) ++;
4974 + /*
4975 + * look for "Default" keyword, and if it's there, return the default
4976 + * pattern set
4977 + */
4978 + if (!strncmp(*inPtr, "Default", 7))
4980 + *inPtr += 7;
4981 + table = readDefaultStringMatchTable(languageMode);
4982 + XtFree(languageMode);
4984 + return table;
4988 + table = readMatchPatternSetContent(inPtr, stringStart, languageMode);
4990 + if (table == NULL)
4991 + XtFree(languageMode);
4993 + return table;
4997 +** Read in a content string ("{..}") of match pattern table,
4998 +** and advance *inPtr beyond it.
4999 +** Returns NULL and outputs an error to stderr on failure.
5001 +static StringMatchTable *readMatchPatternSetContent(
5002 + char **inPtr,
5003 + char *stringStart,
5004 + char *languageMode)
5006 + ReadMatchPatternInfo readPatInfo;
5007 + StringMatchTable *table = NULL;
5008 + ErrorInfo errInfo;
5009 + int successful = True;
5010 + int endOfPatternSet = False;
5012 + initErrorInfo(&errInfo);
5014 + /*
5015 + * look for initial brace
5016 + */
5017 + if (**inPtr != '{')
5019 + errInfo.eiLanguageMode = XtNewString(languageMode);
5020 + errInfo.eiDetail = "pattern list must begin with \"{\"";
5021 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo );
5023 + return NULL;
5026 + (*inPtr)++;
5028 + readPatInfo.rmpiNbrOfElements = 0;
5029 + readPatInfo.rmpiNbrOfGroups = 0;
5030 + readPatInfo.rmpiNbrOfSeqElements = 0;
5031 + readPatInfo.rmpiAllPatRE = NULL;
5032 + readPatInfo.rmpiFlashPatRE = NULL;
5034 + /*
5035 + * parse each pattern in the list
5036 + */
5037 + while (successful && !endOfPatternSet)
5039 + *inPtr += strspn(*inPtr, " \t\n");
5040 + if (**inPtr == '\0')
5042 + errInfo.eiLanguageMode = XtNewString(languageMode);
5043 + errInfo.eiDetail = "end of pattern list not found";
5044 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo);
5045 + successful = False;
5047 + else if (**inPtr == '}')
5049 + (*inPtr)++;
5050 + endOfPatternSet = True;
5052 + else
5054 + if (!readMatchPatternEntry(inPtr, &errInfo, &readPatInfo))
5056 + errInfo.eiLanguageMode = XtNewString(languageMode);
5057 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo);
5058 + successful = False;
5063 + if (successful)
5065 + /*
5066 + * compile regular expressions of read patterns
5067 + */
5068 + if (createRegExpOfPatterns(&readPatInfo, &errInfo))
5070 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo);
5071 + successful = False;
5075 + if (successful)
5077 + return createStringMatchTable(&readPatInfo, languageMode);
5079 + else
5081 + /*
5082 + * free memory of already read patterns
5083 + */
5084 + freeReadMatchPatternInfo(&readPatInfo);
5086 + return NULL;
5089 + return table;
5093 +** Create a reg. exp. of all patterns contained
5094 +** in given read match pattern info.
5096 +static int createRegExpOfPatterns(
5097 + ReadMatchPatternInfo *readPatInfo,
5098 + ErrorInfo *errInfo)
5100 + if (createRegExpOfStrPatterns(readPatInfo, errInfo))
5101 + return True;
5103 + if (createRegExpOfAllPatterns(readPatInfo, errInfo))
5104 + return True;
5106 + return False;
5110 +** Create a "total pattern reg. exp." of all patterns / flash patterns
5111 +** contained in given read match pattern info.
5112 +** Returns true, if create of reg. exp. has failed.
5114 +static int createRegExpOfAllPatterns(
5115 + ReadMatchPatternInfo *readPatInfo,
5116 + ErrorInfo *errInfo)
5118 + int i;
5119 + RegExpStringInfo allPatRegExpSI;
5120 + RegExpStringInfo flashPatRegExpSI;
5121 + MatchPatternTableElement *element;
5122 + char *regExpString;
5123 + char *compileMsg;
5125 + /*
5126 + * Allocate buffers for keyword regular expressions.
5127 + */
5128 + setupRegExpStringBuffers(readPatInfo, &allPatRegExpSI);
5129 + setupRegExpStringBuffers(readPatInfo, &flashPatRegExpSI);
5131 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5133 + element = readPatInfo->rmpiElement[i];
5135 + /*
5136 + * Add the keywords of the matching pattern to the keyword
5137 + * regular expression string buffer of all patterns.
5138 + */
5139 + addElementToRegExpString(
5140 + element,
5141 + readPatInfo,
5142 + &allPatRegExpSI);
5144 + /*
5145 + * If flash attribute is set, then add the keywords of the
5146 + * matching pattern also to the keyword regular expression
5147 + * string buffer of flash patterns.
5148 + */
5149 + if (element->mpteFlash)
5151 + addElementToRegExpString(
5152 + element,
5153 + readPatInfo,
5154 + &flashPatRegExpSI);
5158 + /*
5159 + * Assemble and compile the resulting all keywords reg. exp. string.
5160 + */
5161 + catSMTRegExpStrings(
5162 + &allPatRegExpSI,
5163 + &regExpString);
5165 + readPatInfo->rmpiAllPatRE =
5166 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
5168 + XtFree( regExpString );
5170 + if (readPatInfo->rmpiAllPatRE == NULL)
5172 + errInfo->eiRegExpCompileMsg = compileMsg;
5173 + errInfo->eiDetail = "All patterns: compile reg. exp. error";
5174 + return True;
5177 + /*
5178 + * Assemble and compile the resulting flash keywords reg. exp. string.
5179 + */
5180 + catSMTRegExpStrings(
5181 + &flashPatRegExpSI,
5182 + &regExpString);
5184 + readPatInfo->rmpiFlashPatRE =
5185 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
5187 + XtFree( regExpString );
5189 + if (readPatInfo->rmpiFlashPatRE == NULL)
5191 + errInfo->eiRegExpCompileMsg = compileMsg;
5192 + errInfo->eiDetail = "Flash patterns: compile reg. exp. error";
5193 + return True;
5196 + /*
5197 + * Pattern reg. exp. successful created:
5198 + */
5199 + return False;
5203 +** Create reg. exp. of single patterns contained in given
5204 +** read match pattern info.
5205 +** Returns true, if create of reg. exp. has failed.
5207 +static int createRegExpOfStrPatterns(
5208 + ReadMatchPatternInfo *readPatInfo,
5209 + ErrorInfo *errInfo)
5211 + int i;
5212 + MatchPatternTableElement *element;
5213 + MatchPatternGroupElement *group;
5215 + /*
5216 + * create global backref list of all elements of read info
5217 + */
5218 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5220 + element = readPatInfo->rmpiElement[i];
5222 + if (!createGlobalBackRefList(readPatInfo, element, errInfo))
5223 + return True;
5226 + /*
5227 + * resolve global backrefs of all elements of read info
5228 + */
5229 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5231 + element = readPatInfo->rmpiElement[i];
5233 + if (!resolveGlobalBackRefs(readPatInfo, element, errInfo))
5234 + return True;
5237 + /*
5238 + * compile reg. exp. of all elements of read info
5239 + */
5240 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5242 + element = readPatInfo->rmpiElement[i];
5244 + if (createStrPatRegExpOfElement(readPatInfo, element, errInfo))
5245 + return True;
5247 + /*
5248 + * create start / end reg. exp. if applicable.
5249 + */
5250 + if (element->mpteSkipBtwnStartEnd)
5252 + if (createStartEndRegExp(readPatInfo, element, errInfo))
5253 + return True;
5257 + /*
5258 + * compile reg. exp. of all groups of read info
5259 + */
5260 + for (i=0; i < readPatInfo->rmpiNbrOfGroups; i ++)
5262 + group = readPatInfo->rmpiGroup[i];
5264 + if (createGroupRegExp(readPatInfo, group, errInfo))
5266 + return True;
5270 + return False;
5274 +** Create a string match table out of read match pattern info.
5276 +static StringMatchTable *createStringMatchTable(
5277 + ReadMatchPatternInfo *readPatInfo,
5278 + char *languageMode)
5280 + StringMatchTable *table;
5281 + MatchPatternTable *patTable;
5282 + int sizeOfElements;
5284 + table = (StringMatchTable *)XtMalloc(sizeof(StringMatchTable));
5285 + table->smtLanguageMode = languageMode;
5287 + /*
5288 + * allocate a more appropriately sized list to return matching patterns
5289 + */
5290 + patTable = (MatchPatternTable *)XtMalloc(sizeof(MatchPatternTable));
5291 + patTable->mptNumberOfElements = readPatInfo->rmpiNbrOfElements;
5293 + if (readPatInfo->rmpiNbrOfElements > 0)
5295 + sizeOfElements =
5296 + sizeof(MatchPatternTableElement *) * readPatInfo->rmpiNbrOfElements;
5297 + patTable->mptElements =
5298 + (MatchPatternTableElement **)XtMalloc(sizeOfElements);
5299 + memcpy(patTable->mptElements, readPatInfo->rmpiElement, sizeOfElements);
5301 + else
5303 + patTable->mptElements = NULL;
5306 + table->smtAllPatterns = patTable;
5308 + table->smtAllPatRE = readPatInfo->rmpiAllPatRE;
5309 + table->smtFlashPatRE = readPatInfo->rmpiFlashPatRE;
5310 + table->smtUsedPatRE = NULL;
5312 + /*
5313 + * allocate a more appropriately sized list to return matching pattern groups
5314 + */
5315 + table->smtNumberOfGroups = readPatInfo->rmpiNbrOfGroups;
5316 + if (readPatInfo->rmpiNbrOfGroups > 0)
5318 + sizeOfElements =
5319 + sizeof(MatchPatternGroupElement *) * readPatInfo->rmpiNbrOfGroups;
5320 + table->smtGroups =
5321 + (MatchPatternGroupElement **)XtMalloc(sizeOfElements);
5322 + memcpy(table->smtGroups, readPatInfo->rmpiGroup, sizeOfElements);
5324 + else
5326 + table->smtGroups = NULL;
5328 + /*
5329 + * allocate a more appropriately sized list to return matching pattern sequence
5330 + */
5331 + table->smtNumberOfSeqElements = readPatInfo->rmpiNbrOfSeqElements;
5332 + if (readPatInfo->rmpiNbrOfSeqElements > 0)
5334 + sizeOfElements =
5335 + sizeof(MatchPatternSequenceElement *) * readPatInfo->rmpiNbrOfSeqElements;
5336 + table->smtSequence =
5337 + (MatchPatternSequenceElement **)XtMalloc(sizeOfElements);
5338 + memcpy(table->smtSequence, readPatInfo->rmpiSequence, sizeOfElements);
5340 + else
5342 + table->smtSequence = NULL;
5345 + return table;
5349 +** Read one match pattern entry of a match pattern string.
5350 +** Returns true, if read was successful.
5352 +static int readMatchPatternEntry(
5353 + char **inPtr,
5354 + ErrorInfo *errInfo,
5355 + ReadMatchPatternInfo *info)
5357 + char *name;
5358 + MatchPatternType type;
5359 + MatchPatternGroupElement *readGroup;
5360 + MatchPatternTableElement *readElement;
5362 + if (!getMPSName( inPtr, errInfo, &name ))
5364 + return False;
5367 + if (!getMPSTypeAttribute( inPtr, errInfo, &type ))
5369 + errInfo->eiMPTabElementName = XtNewString(name);
5370 + return False;
5373 + if (type == MPT_GROUP)
5375 + if (info->rmpiNbrOfGroups >= MAX_NBR_MATCH_PATTERN_GROUPS)
5377 + errInfo->eiMPTabElementName = XtNewString(name);
5378 + errInfo->eiDetail = "max number of match pattern groups exceeded";
5379 + return False;
5382 + readGroup = readMatchPatternGroup( inPtr, errInfo, name, info );
5384 + if (readGroup == NULL)
5386 + errInfo->eiMPTabElementName = XtNewString(name);
5387 + XtFree( name );
5389 + else
5391 + info->rmpiGroup[info->rmpiNbrOfGroups ++] = readGroup;
5393 + recordPatternSequence( info, name, type, info->rmpiNbrOfGroups-1 );
5396 + return (readGroup != NULL);
5398 + else
5400 + if (info->rmpiNbrOfElements >= MAX_NBR_MATCH_PATTERNS)
5402 + errInfo->eiMPTabElementName = XtNewString(name);
5403 + errInfo->eiDetail = "max number of match patterns exceeded";
5404 + XtFree( name );
5405 + return False;
5408 + readElement =
5409 + readMatchPatternTableElement( inPtr, &errInfo->eiDetail, name, type );
5411 + if (readElement == NULL)
5413 + errInfo->eiMPTabElementName = XtNewString(name);
5414 + XtFree( name );
5416 + else
5418 + readElement->mpteIndex = info->rmpiNbrOfElements;
5420 + info->rmpiElement[info->rmpiNbrOfElements ++] = readElement;
5422 + if (type == MPT_INDIVIDUAL)
5424 + if (!assignIndividualGroup( info, &errInfo->eiDetail, readElement ))
5426 + errInfo->eiMPTabElementName = XtNewString(name);
5427 + return False;
5431 + treatDuplicatedMTEntries(
5432 + info->rmpiElement, info->rmpiNbrOfElements );
5434 + recordPatternSequence( info, name, type, info->rmpiNbrOfElements-1 );
5437 + return (readElement != NULL);
5442 +** Record match pattern sequence for display of match pattern dialog.
5444 +static void recordPatternSequence(
5445 + ReadMatchPatternInfo *info,
5446 + char *name,
5447 + MatchPatternType type,
5448 + int index)
5450 + MatchPatternSequenceElement *sequence;
5452 + sequence =
5453 + (MatchPatternSequenceElement *)XtMalloc( sizeof(MatchPatternSequenceElement) );
5455 + sequence->mpseName = XtNewString(name);
5456 + sequence->mpseType = type;
5457 + sequence->mpseIndex = index;
5459 + info->rmpiSequence[info->rmpiNbrOfSeqElements ++] = sequence;
5463 +** Assign a new group to an individual match pattern.
5464 +** Returns true, if assignment was successful.
5466 +static int assignIndividualGroup(
5467 + ReadMatchPatternInfo *info,
5468 + char **errMsg,
5469 + MatchPatternTableElement *element)
5471 + MatchPatternGroupElement *group = NULL;
5473 + if (info->rmpiNbrOfGroups >= MAX_NBR_MATCH_PATTERN_GROUPS)
5475 + *errMsg = "max. number of matching pattern groups exceeded\n";
5476 + return False;
5479 + /*
5480 + * Assign the index of new group to the individual matching pattern
5481 + */
5482 + element->mpteGroup = info->rmpiNbrOfGroups;
5484 + /*
5485 + * Allocate memory for the matching pattern group and copy the
5486 + * info into this group element.
5487 + */
5488 + group =
5489 + (MatchPatternGroupElement *)XtMalloc( sizeof(MatchPatternGroupElement) );
5491 + group->mpgeName = NULL;
5492 + group->mpgeKeywordRE = NULL;
5494 + /*
5495 + * remember name of match pattern table element, which is
5496 + * represented by this group.
5497 + */
5498 + group->mpgeNumberOfSubPatterns = 1;
5499 + group->mpgeSubPatternIds = (char **)XtMalloc( sizeof(char *) );
5500 + group->mpgeSubPatternIds[0] = XtNewString(element->mpteName);
5502 + info->rmpiGroup[info->rmpiNbrOfGroups ++] = group;
5504 + return True;
5508 +** Get the match pattern table element of given 'patToSearch'
5509 +** name.
5510 +** Returns NULL, if no element was found.
5512 +static MatchPatternTableElement *getPatternOfName(
5513 + ReadMatchPatternInfo *info,
5514 + char *patToSearch)
5516 + int i;
5517 + MatchPatternTableElement *element;
5519 + for (i=0; i<info->rmpiNbrOfElements; i ++)
5521 + element = info->rmpiElement[i];
5523 + if (strcmp( element->mpteName, patToSearch ) == 0)
5525 + /*
5526 + * Related sub-pattern found:
5527 + */
5528 + return element;
5532 + /*
5533 + * No sub-pattern found:
5534 + */
5535 + return NULL;
5539 +** Read match pattern group of given match pattern string.
5540 +** Returns NULL, if read fails.
5542 +static MatchPatternGroupElement *readMatchPatternGroup(
5543 + char **inPtr,
5544 + ErrorInfo *errInfo,
5545 + char *name,
5546 + ReadMatchPatternInfo *info)
5548 + int i;
5549 + int error = False;
5550 + char *patNameInPtr;
5551 + char *subPatName;
5552 + MatchPatternTableElement *subPatElement;
5553 + int numberOfRelatedSubPattern = 0;
5554 + char *relatedSubPatternId[MAX_NBR_MATCH_PATTERNS];
5555 + int sizeOfIds;
5556 + MatchPatternGroupElement *group = NULL;
5558 + /*
5559 + * Read sub-matching patterns of this group.
5560 + */
5561 + while (**inPtr != '\n' && !error)
5563 + /*
5564 + * Read next pattern name from inPtr.
5565 + */
5566 + patNameInPtr = *inPtr;
5567 + subPatName = ReadSymbolicField(inPtr);
5569 + if (subPatName == NULL)
5571 + errInfo->eiDetail = "Sub-Matching Pattern Name expected";
5572 + error = True;
5574 + else
5576 + /*
5577 + * Get matching pattern related to sub-matching pattern name.
5578 + */
5579 + subPatElement =
5580 + getPatternOfName( info, subPatName );
5582 + if (subPatElement == NULL)
5584 + errInfo->eiStringPatText = XtNewString(subPatName);
5585 + errInfo->eiDetail = "Sub-Matching Pattern not defined before";
5586 + error = True;
5588 + else if (numberOfRelatedSubPattern >= MAX_NBR_MATCH_PATTERNS)
5590 + errInfo->eiDetail = "Group holds too many Sub-Matching Patterns";
5591 + error = True;
5593 + else if (subPatElement->mpteType != MPT_SUB)
5595 + errInfo->eiStringPatText = XtNewString(subPatName);
5596 + errInfo->eiDetail = "Not a Sub-Matching Pattern";
5597 + error = True;
5599 + else
5601 + /*
5602 + * Remember sub-matching pattern ID
5603 + */
5604 + relatedSubPatternId[numberOfRelatedSubPattern ++] = subPatName;
5606 + /*
5607 + * Assign the index of this group to the sub-matching pattern
5608 + * if no group index was assigned before.
5609 + */
5610 + if (subPatElement->mpteGroup == NO_GROUP_IDX)
5612 + subPatElement->mpteGroup = info->rmpiNbrOfGroups;
5616 + /*
5617 + * Skip to the start of the next matching pattern name.
5618 + */
5619 + if (!error && !SkipDelimiter(inPtr, &errInfo->eiDetail))
5621 + error = True;
5626 + if (error)
5628 + for (i=0; i < numberOfRelatedSubPattern; i++)
5630 + XtFree( relatedSubPatternId[i] );
5633 + return NULL;
5635 + else
5637 + /*
5638 + * Allocate memory for the matching pattern group and copy the
5639 + * info into this group element.
5640 + */
5641 + group =
5642 + (MatchPatternGroupElement *)XtMalloc( sizeof(MatchPatternGroupElement) );
5644 + group->mpgeName = name;
5645 + group->mpgeKeywordRE = NULL;
5647 + /*
5648 + * Allocate memory for the sub-matching pattern IDs & copy
5649 + * related sub-matching pattern into the group element.
5650 + */
5651 + sizeOfIds = sizeof(char *) * numberOfRelatedSubPattern;
5652 + group->mpgeSubPatternIds = (char **)XtMalloc( sizeOfIds );
5654 + memcpy(group->mpgeSubPatternIds, relatedSubPatternId, sizeOfIds);
5656 + group->mpgeNumberOfSubPatterns = numberOfRelatedSubPattern;
5658 + return group;
5663 +** Read one match pattern element from given match pattern string.
5664 +** Returns true, if read was successful.
5666 +static int readPatternElement(
5667 + char **inPtr,
5668 + char **errMsg,
5669 + PatternElement **pattern)
5671 + PatternElementKind patternKind;
5672 + PatternWordBoundary wordBoundary;
5673 + int caseInsensitive;
5674 + int regularExpression;
5675 + char *string;
5677 + if (!getMPSPatternAttribute(
5678 + inPtr,
5679 + errMsg,
5680 + &patternKind,
5681 + &wordBoundary,
5682 + &caseInsensitive,
5683 + &regularExpression ))
5685 + return False;
5688 + if (!ReadQuotedString(inPtr, errMsg, &string))
5690 + return False;
5693 + if (!SkipDelimiter(inPtr, errMsg))
5695 + XtFree( string );
5696 + return False;
5699 + *pattern =
5700 + createPatternElement(
5701 + string,
5702 + patternKind,
5703 + wordBoundary,
5704 + caseInsensitive,
5705 + regularExpression);
5707 + return True;
5711 +** Create a pattern element.
5713 +static PatternElement *createPatternElement(
5714 + char *patternText,
5715 + PatternElementKind patternKind,
5716 + PatternWordBoundary wordBoundary,
5717 + int caseInsensitive,
5718 + int regularExpression)
5720 + PatternElement *pattern;
5721 + char *s;
5723 + /*
5724 + * Convert pattern text to lower case, if case insensitive
5725 + * attribute is set.
5726 + */
5727 + if (caseInsensitive)
5729 + for (s = patternText; *s != '\0'; s ++)
5731 + *s = tolower(*s);
5735 + /*
5736 + * Allocate memory for the new pattern element and init. / copy
5737 + * related info into this pattern element.
5738 + */
5739 + pattern = (PatternElement *)XtMalloc( sizeof(PatternElement) );
5741 + initStrPatBackRefList(&pattern->peVal.peuSingle);
5743 + pattern->peKind = patternKind;
5744 + pattern->peIndex = NO_PATTERN_IDX;
5745 + pattern->peType = PET_SINGLE;
5747 + pattern->peVal.peuSingle.spLength = strlen(patternText);
5748 + pattern->peVal.peuSingle.spBackRefParsed = False;
5749 + pattern->peVal.peuSingle.spBackRefResolved = False;
5751 + pattern->peVal.peuSingle.spCaseInsensitive = caseInsensitive;
5752 + pattern->peVal.peuSingle.spRegularExpression = regularExpression;
5753 + pattern->peVal.peuSingle.spTextRE = NULL;
5755 + /*
5756 + * Store original string of regular expression patterns due to
5757 + * it may be later adapted (e.g. due to global backrefs etc.).
5758 + */
5759 + if (regularExpression)
5761 + pattern->peVal.peuSingle.spOrigText = patternText;
5762 + pattern->peVal.peuSingle.spText = NULL;
5763 + pattern->peVal.peuSingle.spWordBoundary = PWB_NONE;
5765 + else
5767 + pattern->peVal.peuSingle.spOrigText = NULL;
5768 + pattern->peVal.peuSingle.spText = patternText;
5769 + pattern->peVal.peuSingle.spWordBoundary = wordBoundary;
5772 + return pattern;
5776 +** Create a list holding all global backref definitions of given
5777 +** match pattern table element. The list is stored in this given
5778 +** element.
5779 +** Returns true, if list was successfully created.
5781 +static int createGlobalBackRefList(
5782 + ReadMatchPatternInfo *readPatInfo,
5783 + MatchPatternTableElement *element,
5784 + ErrorInfo *errInfo)
5786 + int i;
5787 + StringPattern *strPat;
5789 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
5791 + strPat = getReadStringPattern(readPatInfo, element->mpteAll.pesPattern[i]);
5793 + if (strPat->spRegularExpression)
5795 + if (strPat->spBackRefParsed)
5797 + /*
5798 + * Global backrefs or this string pattern already parsed:
5799 + * just merge string pattern list with elements one.
5800 + */
5801 + if (!updateGlobalBackRefs(
5802 + strPat,
5803 + element->mpteGlobalBackRef,
5804 + errInfo))
5806 + return False;
5809 + else
5811 + /*
5812 + * parse string pattern for global backrefs and
5813 + * merge string pattern list with elements one.
5814 + */
5815 + if (!parseGlobalBackRefs(
5816 + strPat,
5817 + element->mpteGlobalBackRef,
5818 + errInfo))
5820 + return False;
5826 + return True;
5830 +** Returns read string pattern of given pattern element.
5832 +StringPattern *getReadStringPattern(
5833 + ReadMatchPatternInfo *readPatInfo,
5834 + PatternElement *pattern )
5836 + switch (pattern->peType)
5838 + case PET_SINGLE:
5839 + return &pattern->peVal.peuSingle;
5840 + break;
5842 + case PET_MULTIPLE:
5843 + return &pattern->peVal.peuMulti.mpStringPattern;
5844 + break;
5846 + case PET_REFERENCE:
5847 + return getReadStringPattern(
5848 + readPatInfo,
5849 + getReadPatternOfReference(readPatInfo, &pattern->peVal.peuRef));
5850 + break;
5853 + /*
5854 + * never reached; just to make compiler happy
5855 + */
5856 + return NULL;
5860 +** Returns read pattern element of given pattern reference.
5862 +static PatternElement *getReadPatternOfReference(
5863 + ReadMatchPatternInfo *readPatInfo,
5864 + PatternReference *patRef)
5866 + MatchPatternTableElement **element = readPatInfo->rmpiElement;
5868 + return element[ patRef->prElementIdx ]->mpteAll.pesPattern[patRef->prPatternIdx];
5872 +** Allocate a new copy of given string and substitute each capturing
5873 +** parentheses inside given string by a non-capturing one.
5874 +** Returns resulting string.
5876 +static char *replaceCapturingParentheses(
5877 + const char *source)
5879 + char *destination;
5880 + const char *s;
5881 + char *d;
5882 + int nbrOfOpenBraces = 0;
5884 + s = source;
5886 + /*
5887 + * count number of open braces
5888 + */
5889 + while (*s != '\0')
5891 + if (*s++ == '(')
5892 + nbrOfOpenBraces ++;
5895 + /*
5896 + * allocate memory for substitued reg. exp. text
5897 + */
5898 + destination = XtMalloc(strlen(source) + 2*nbrOfOpenBraces);
5900 + /*
5901 + * substitute each capturing open brace by a non-capturing one
5902 + */
5903 + s = source;
5904 + d = destination;
5906 + while (*s != '\0')
5908 + if (*s == '\\')
5910 + *d++ = *s++;
5912 + if (*s != '\0')
5913 + *d++ = *s++;
5915 + else if (*s == '(')
5917 + *d++ = *s++;
5919 + if (*s != '?' && *s != '*')
5921 + *d++ = '?';
5922 + *d++ = ':';
5925 + else
5927 + *d++ = *s++;
5931 + *d = '\0';
5933 + return destination;
5937 +** Parse given string pattern for global backrefs definitions
5938 +** (syntax: "(*n", where n=1..9). Add found global backrefs to
5939 +** given backRefList.
5940 +** Returns false, if parse fails.
5942 +static int parseGlobalBackRefs(
5943 + StringPattern *strPat,
5944 + GlobalBackRefElement *backRefList,
5945 + ErrorInfo *errInfo)
5947 + char *s;
5948 + char *backRefContent;
5949 + int nestingLevel = 0;
5950 + int stackIdx = -1;
5951 + BackRefBracketInfo backRefInfo[MAX_GLOBAL_BACK_REF_ID+1];
5952 + StrPatBackRefElement *curStrPatBRE;
5954 + strPat->spText = replaceCapturingParentheses(strPat->spOrigText);
5955 + strPat->spLength = strlen(strPat->spText);
5956 + strPat->spBackRefParsed = True;
5958 + s = strPat->spText;
5960 + while (*s != '\0')
5962 + if (*s == '\\')
5964 + /*
5965 + * Ignore escaped characters
5966 + */
5967 + if (*(s+1) != '\0')
5968 + s ++;
5970 + else if (*s == '(')
5972 + if (*(s+1) == '*')
5974 + if (isdigit((unsigned char)*(s+2)))
5976 + /*
5977 + * Global backref. definition start found:
5978 + */
5979 + stackIdx ++;
5981 + backRefInfo[stackIdx].brbiGlobalId =
5982 + (int)((unsigned char)*(s+2) - (unsigned char)'0') - 1;
5984 + if(backRefInfo[stackIdx].brbiGlobalId < 0)
5986 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
5987 + errInfo->eiDetail = "Backref '0' not allowed";
5988 + return False;
5991 + backRefInfo[stackIdx].brbiContentStart = s+3;
5992 + backRefInfo[stackIdx].brbiNestingLevel = nestingLevel;
5993 + s ++;
5995 + s ++;
5997 + nestingLevel ++;
5999 + else if (*s == ')')
6001 + nestingLevel --;
6002 + if (stackIdx != -1 &&
6003 + backRefInfo[stackIdx].brbiNestingLevel == nestingLevel)
6005 + /*
6006 + * Global backref. definition end found: add it to
6007 + * backref. list of string pattern.
6008 + */
6009 + curStrPatBRE =
6010 + &strPat->spOwnGlobalBackRef[backRefInfo[stackIdx].brbiGlobalId];
6012 + backRefContent =
6013 + createBackRefRegExpText(
6014 + backRefInfo[stackIdx].brbiContentStart,
6015 + s);
6017 + if (curStrPatBRE->spbreRegExpText != NULL)
6019 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6020 + errInfo->eiBackRefNbr = backRefInfo[stackIdx].brbiGlobalId + 1;
6021 + errInfo->eiDetail = "already defined before";
6022 + XtFree(backRefContent);
6023 + return False;
6025 + else
6027 + curStrPatBRE->spbreRegExpText = backRefContent;
6030 + stackIdx --;
6033 + s ++;
6036 + /*
6037 + * Merge global backref. list of string pattern with given backRefList.
6038 + */
6039 + return updateGlobalBackRefs(
6040 + strPat,
6041 + backRefList,
6042 + errInfo);
6046 +** Merge global backref. list of given string pattern with given backRefList.
6047 +** Returns false, if merge fails.
6049 +static int updateGlobalBackRefs(
6050 + StringPattern *strPat,
6051 + GlobalBackRefElement *backRefList,
6052 + ErrorInfo *errInfo)
6054 + int i;
6055 + StrPatBackRefElement *curStrPatBRE;
6056 + GlobalBackRefElement *curGlobalBRE;
6058 + for (i=0;i < MAX_GLOBAL_BACK_REF_ID; i ++)
6060 + curStrPatBRE = &strPat->spOwnGlobalBackRef[i];
6062 + if (curStrPatBRE->spbreRegExpText != NULL)
6064 + curGlobalBRE = &backRefList[i];
6066 + if (curGlobalBRE->gbreDefByStrPat != NULL)
6068 + if (strcmp(curGlobalBRE->gbreRegExpText, curStrPatBRE->spbreRegExpText) != 0)
6070 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6071 + errInfo->eiBackRefNbr = i+1;
6072 + errInfo->eiDetail = "already defined before";
6074 + return False;
6077 + else
6079 + curGlobalBRE->gbreDefByStrPat = strPat;
6080 + curGlobalBRE->gbreRegExpText = curStrPatBRE->spbreRegExpText;
6085 + return True;
6089 +** Allocate and return a new string holding content of
6090 +** global backref. definition.
6092 +static char *createBackRefRegExpText(
6093 + const char *start,
6094 + const char *end)
6096 + int len = end - start;
6097 + char *regExpText = XtMalloc( len+1 );
6099 + memcpy( regExpText, start, len );
6101 + regExpText[len] = '\0';
6103 + return regExpText;
6107 +** Resolve all global backrefs of given match pattern table element.
6108 +** Returns false, if resolve fails.
6110 +static int resolveGlobalBackRefs(
6111 + ReadMatchPatternInfo *readPatInfo,
6112 + MatchPatternTableElement *element,
6113 + ErrorInfo *errInfo)
6115 + int i;
6116 + StringPattern *strPat;
6118 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
6120 + strPat = getReadStringPattern(readPatInfo, element->mpteAll.pesPattern[i]);
6122 + if (strPat->spRegularExpression && !strPat->spBackRefResolved)
6124 + if (!resolveGlobalBackRefsOfStrPat(strPat, element->mpteGlobalBackRef, errInfo))
6125 + return False;
6127 + strPat->spBackRefResolved = True;
6131 + return True;
6135 +** Resolve global backrefs of given string pattern.
6136 +** Returns false, if resolve fails.
6138 +static int resolveGlobalBackRefsOfStrPat(
6139 + StringPattern *strPat,
6140 + GlobalBackRefElement *backRefList,
6141 + ErrorInfo *errInfo)
6143 + char *s;
6144 + int globalId;
6145 + int localId = 1;
6147 + s = strPat->spText;
6149 + while (*s != '\0')
6151 + if (*s == '\\')
6153 + if (isdigit((unsigned char)*(s+1)))
6155 + /*
6156 + * \n (n=1..9) found: substitute global backref.
6157 + */
6158 + globalId =
6159 + (int)((unsigned char)*(s+1) - (unsigned char)'0') - 1;
6161 + if(globalId < 0)
6163 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6164 + errInfo->eiDetail = "backref '\\0' not allowed";
6165 + return False;
6168 + s = substituteGlobalBackRef(strPat, s, globalId, &localId, backRefList, errInfo);
6170 + if (s == NULL)
6171 + return False;
6173 + else if (*(s+1) != '\0')
6174 + s ++;
6176 + else if (*s == '(')
6178 + if (*(s+1) == '*')
6180 + if (isdigit((unsigned char)*(s+2)))
6182 + /*
6183 + * "(*n" (n=1..9) found: substitute global backref. definition.
6184 + */
6185 + globalId =
6186 + (int)((unsigned char)*(s+2) - (unsigned char)'0') - 1;
6188 + strPat->spOwnGlobalBackRef[globalId].spbreLocalBackRefID = localId;
6189 + strPat->spGlobalToLocalBackRef[globalId] = localId;
6191 + localId ++;
6193 + s = convertGlobalToLocalBackRef(strPat, s);
6195 + else
6197 + s ++;
6201 + s ++;
6204 + return True;
6208 +** Substitute global backref (\n, n=1..9) located at given "subsPtr"
6209 +** by its definition or by a local backref.
6210 +** Returns
6211 +** - NULL, if substitute fails or
6212 +** - substituted string pointer, where scan shall continue with.
6214 +static char *substituteGlobalBackRef(
6215 + StringPattern *strPat,
6216 + char *subsPtr,
6217 + int globalId,
6218 + int *localId,
6219 + GlobalBackRefElement *backRefList,
6220 + ErrorInfo *errInfo)
6222 + StrPatBackRefElement *strPatBackRef = &strPat->spOwnGlobalBackRef[globalId];
6223 + char *s;
6225 + if (strPatBackRef->spbreRegExpText == NULL)
6227 + /*
6228 + * given global backref definition is not located in given
6229 + * string pattern -> replace backref ID by backref reg. exp.
6230 + */
6231 + if (backRefList[globalId].gbreRegExpText == NULL)
6233 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6234 + errInfo->eiBackRefNbr = globalId + 1;
6235 + errInfo->eiDetail = "not defined within any string pattern";
6236 + return NULL;
6239 + if (strPat->spGlobalToLocalBackRef[globalId] == NO_LOCAL_BACK_REF_ID)
6241 + /*
6242 + * 1st occurence of global backref ID in this pattern ->
6243 + * replace global backref ID by backref reg. exp.
6244 + */
6245 + s = replaceBackRefIdByRegExp(strPat, subsPtr, backRefList[globalId].gbreRegExpText);
6247 + strPat->spGlobalToLocalBackRef[globalId] = *localId;
6248 + (*localId) ++;
6250 + else
6252 + /*
6253 + * next occurence of global backref ID in this pattern ->
6254 + * replace global backref ID by local one
6255 + */
6256 + s = subsPtr + 1;
6257 + *s = (char)((int)('0') + strPat->spGlobalToLocalBackRef[globalId]);
6260 + else
6262 + /*
6263 + * given global backref definition is located in given string pattern
6264 + */
6265 + if (strPatBackRef->spbreLocalBackRefID == NO_LOCAL_BACK_REF_ID)
6267 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6268 + errInfo->eiBackRefNbr = globalId + 1;
6269 + errInfo->eiDetail = "not defined before";
6270 + return NULL;
6273 + /*
6274 + * replace global backref ID by local one
6275 + */
6276 + s = subsPtr + 1;
6277 + *s = (char)((int)('0') + strPatBackRef->spbreLocalBackRefID);
6280 + return s;
6284 +** Replace global backref ID ("\n", n=1..9), located at given
6285 +** replaceStartPtr, by its definition (given by regExp parameter).
6286 +** Returns string pointer, where scan shall continue with
6288 +static char *replaceBackRefIdByRegExp(
6289 + StringPattern *strPat,
6290 + char *replaceStartPtr,
6291 + char *regExp)
6293 + char *oldText = strPat->spText;
6294 + char *newText;
6295 + char *n;
6296 + char *continueScanPtr;
6297 + int oldLen = strlen(oldText);
6298 + int regExpLen = strlen(regExp);
6299 + int replacePos = replaceStartPtr - oldText;
6300 + int remainingLen = oldLen-replacePos-2;
6302 + /*
6303 + * replace "\n" - located at replaceStartPtr - by "(regExp)"
6304 + */
6305 + newText = XtMalloc(oldLen + regExpLen + 3);
6307 + memcpy(newText, oldText, replacePos);
6308 + n = newText + replacePos;
6309 + *n = '(';
6310 + continueScanPtr = n;
6311 + n ++;
6312 + memcpy(n, regExp, regExpLen);
6313 + n += regExpLen;
6314 + *n = ')';
6315 + n ++;
6316 + memcpy(n, replaceStartPtr+2, remainingLen);
6317 + *(n + remainingLen) = '\0';
6319 + XtFree(oldText);
6321 + strPat->spText = newText;
6322 + strPat->spLength = strlen(newText);
6324 + return continueScanPtr;
6328 +** Convert global backref definition ("(*n", n=1..9), located at given
6329 +** convertPtr, by capturing parentheses "(".
6330 +** Returns string pointer, where scan shall continue with
6332 +static char *convertGlobalToLocalBackRef(
6333 + StringPattern *strPat,
6334 + char *convertPtr)
6336 + char *oldText = strPat->spText;
6337 + char *newText;
6338 + int oldLen = strlen(oldText);
6339 + int convertPos = convertPtr - oldText;
6341 + /*
6342 + * replace "(*n" - located at convertPtr - by "("
6343 + */
6344 + newText = XtMalloc(oldLen - 1);
6346 + memcpy(newText, oldText, convertPos+1);
6347 + memcpy(newText+convertPos+1, convertPtr+3, oldLen-convertPos-3);
6349 + *(newText + oldLen - 2) = '\0';
6351 + XtFree(oldText);
6353 + strPat->spText = newText;
6354 + strPat->spLength = strlen(newText);
6356 + return newText + convertPos;
6360 +** Read a match pattern table element from given input string.
6361 +** Return NULL, if read fails.
6363 +static MatchPatternTableElement *readMatchPatternTableElement(
6364 + char **inPtr,
6365 + char **errMsg,
6366 + char *name,
6367 + MatchPatternType type)
6369 + int error = False;
6370 + PatternElement *pattern;
6371 + PatternElement *allPat[MAX_STRING_PATTERNS];
6372 + int nbrOfPat = 0;
6373 + int sizeOfPat;
6374 + MatchPatternTableElement *result;
6375 + int isMonoPattern;
6376 + int skipBtwStartEnd;
6377 + int flash;
6378 + int ignoreHighLightInfo;
6379 + int i;
6381 + if (!getMPSGlobalAttribute(
6382 + inPtr,
6383 + errMsg,
6384 + &isMonoPattern,
6385 + &skipBtwStartEnd,
6386 + &flash,
6387 + &ignoreHighLightInfo ))
6389 + return NULL;
6392 + /*
6393 + * read all patterns
6394 + */
6395 + while (**inPtr != '\n' && !error)
6397 + if (!readPatternElement( inPtr, errMsg, &pattern ))
6399 + error = True;
6401 + else if (nbrOfPat >= MAX_STRING_PATTERNS)
6403 + *errMsg = "max. number of string patterns exceeded";
6404 + error = True;
6406 + else
6408 + pattern->peIndex = nbrOfPat;
6410 + allPat[nbrOfPat ++] = pattern;
6414 + if (error)
6416 + for (i=0; i < nbrOfPat; i ++)
6417 + freePatternElement( allPat[i] );
6419 + return NULL;
6422 + if (nbrOfPat == 0)
6424 + *errMsg = "min. one string pattern needed";
6425 + return NULL;
6428 + /*
6429 + * allocate & init. MatchPatternTableElement
6430 + */
6431 + result =
6432 + (MatchPatternTableElement *)XtMalloc(sizeof(MatchPatternTableElement));
6434 + result->mpteName = name;
6435 + result->mpteIndex = NO_ELEMENT_IDX;
6436 + result->mpteType = type;
6437 + result->mpteGroup = NO_GROUP_IDX;
6439 + sizeOfPat = sizeof(PatternElement *) * nbrOfPat;
6440 + result->mpteAll.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6442 + memcpy(result->mpteAll.pesPattern, allPat, sizeOfPat);
6444 + result->mpteAll.pesNumberOfPattern = nbrOfPat;
6446 + result->mpteIsMonoPattern = isMonoPattern;
6447 + result->mpteSkipBtwnStartEnd = skipBtwStartEnd;
6448 + result->mpteFlash = flash;
6449 + result->mpteIgnoreHighLightInfo = ignoreHighLightInfo;
6451 + result->mpteStartEndRE = NULL;
6453 + initGlobalBackRefList( result->mpteGlobalBackRef );
6455 + /*
6456 + * sort start / end / middle pattern
6457 + */
6458 + error = !sortReadPatternElementSet( &result->mpteAll, errMsg, result );
6460 + if (error)
6462 + freeMatchPatternTableElement( result );
6463 + return NULL;
6465 + else
6467 + return result;
6472 + * Sort read pattern element set into start, middle & end arrays.
6473 + * Validate "monopattern" attribute.
6474 + * Returns true, if validation was successful.
6475 + */
6476 +static int sortReadPatternElementSet(
6477 + PatternElementSet *allPat,
6478 + char **errMsg,
6479 + MatchPatternTableElement *result)
6481 + int sizeOfPat;
6482 + int isMonoPattern = result->mpteIsMonoPattern;
6484 + /*
6485 + * count number of start, middle & end pattern elements.
6486 + */
6487 + countPatternElementKind( allPat, result );
6489 + /*
6490 + * validate and allocate pattern elements.
6491 + */
6492 + if (result->mpteStart.pesNumberOfPattern != 0)
6494 + sizeOfPat = sizeof(PatternElement *) * result->mpteStart.pesNumberOfPattern;
6495 + result->mpteStart.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6497 + else
6499 + *errMsg = "min. one start pattern needed";
6500 + return False;
6503 + if (isMonoPattern &&
6504 + (result->mpteMiddle.pesNumberOfPattern != 0 ||
6505 + result->mpteEnd.pesNumberOfPattern !=0))
6507 + *errMsg = "mono pattern: only start pattern(s) allowed due to attribute [m]";
6508 + return False;
6511 + if (result->mpteMiddle.pesNumberOfPattern != 0)
6513 + sizeOfPat = sizeof(PatternElement *) * result->mpteMiddle.pesNumberOfPattern;
6514 + result->mpteMiddle.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6517 + if (result->mpteEnd.pesNumberOfPattern != 0)
6519 + sizeOfPat = sizeof(PatternElement *) * result->mpteEnd.pesNumberOfPattern;
6520 + result->mpteEnd.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6522 + else
6524 + if (!isMonoPattern)
6526 + *errMsg = "min. one end pattern needed";
6527 + return False;
6531 + /*
6532 + * sort pattern elements into start, middle & end arrays.
6533 + */
6534 + sortPatternElementSet( allPat, result );
6536 + if (isMonoPattern)
6538 + copyPatternSet( &result->mpteStart, &result->mpteEnd );
6541 + return True;
6545 + * Count number of start, middle & end patterns stored in "allPat".
6546 + */
6547 +static void countPatternElementKind(
6548 + PatternElementSet *allPat,
6549 + MatchPatternTableElement *result)
6551 + int i;
6553 + result->mpteStart.pesNumberOfPattern = 0;
6554 + result->mpteEnd.pesNumberOfPattern = 0;
6555 + result->mpteMiddle.pesNumberOfPattern = 0;
6557 + result->mpteStart.pesPattern = NULL;
6558 + result->mpteEnd.pesPattern = NULL;
6559 + result->mpteMiddle.pesPattern = NULL;
6561 + for (i=0; i < allPat->pesNumberOfPattern; i ++)
6563 + switch (allPat->pesPattern[i]->peKind)
6565 + case PEK_START:
6566 + result->mpteStart.pesNumberOfPattern ++;
6567 + break;
6568 + case PEK_MIDDLE:
6569 + result->mpteMiddle.pesNumberOfPattern ++;
6570 + break;
6571 + case PEK_END:
6572 + result->mpteEnd.pesNumberOfPattern ++;
6573 + break;
6574 + default:;
6580 + * Sort start, middle & end pattern elements into related arrays.
6581 + */
6582 +static void sortPatternElementSet(
6583 + PatternElementSet *allPat,
6584 + MatchPatternTableElement *result)
6586 + int i;
6587 + int s,m,e;
6589 + for (i=0, s=0, m=0, e=0; i < allPat->pesNumberOfPattern; i ++)
6591 + switch (allPat->pesPattern[i]->peKind)
6593 + case PEK_START:
6594 + result->mpteStart.pesPattern[s ++] = allPat->pesPattern[i];
6595 + break;
6596 + case PEK_MIDDLE:
6597 + result->mpteMiddle.pesPattern[m ++] = allPat->pesPattern[i];
6598 + break;
6599 + case PEK_END:
6600 + result->mpteEnd.pesPattern[e ++] = allPat->pesPattern[i];
6601 + break;
6602 + default:;
6607 +static void copyPatternSet(
6608 + PatternElementSet *sourcePS,
6609 + PatternElementSet *destPS)
6611 + int sizeOfPat;
6613 + destPS->pesNumberOfPattern = sourcePS->pesNumberOfPattern;
6615 + sizeOfPat = sizeof(PatternElement *) * destPS->pesNumberOfPattern;
6616 + destPS->pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6618 + memcpy(destPS->pesPattern, sourcePS->pesPattern, sizeOfPat);
6622 +** Free the allocated memory contained in a ReadMatchPatternInfo data structure
6624 +static void freeReadMatchPatternInfo( ReadMatchPatternInfo *readPatInfo )
6626 + int i;
6628 + for (i=0; i<readPatInfo->rmpiNbrOfElements; i++)
6629 + freeMatchPatternTableElement(readPatInfo->rmpiElement[i]);
6631 + for (i=0; i<readPatInfo->rmpiNbrOfGroups; i++)
6632 + freeMatchPatternGroupElement(readPatInfo->rmpiGroup[i]);
6634 + for (i=0; i<readPatInfo->rmpiNbrOfSeqElements; i++)
6635 + freeMatchPatternSequenceElement(readPatInfo->rmpiSequence[i]);
6637 + freePtr((void **)&readPatInfo->rmpiAllPatRE);
6639 + freePtr((void **)&readPatInfo->rmpiFlashPatRE);
6643 +** Free the allocated memory contained in a StringMatchTable data structure
6645 +static void freeStringMatchTable( StringMatchTable *table )
6647 + MatchPatternTable *patTable;
6648 + int i;
6650 + if (table == NULL)
6651 + return;
6653 + XtFree(table->smtLanguageMode);
6655 + /*
6656 + * Free all matching patterns
6657 + */
6658 + patTable = table->smtAllPatterns;
6660 + for (i=0; i<patTable->mptNumberOfElements; i++)
6661 + freeMatchPatternTableElement(patTable->mptElements[i]);
6663 + XtFree((char *)patTable);
6665 + /*
6666 + * Free matching pattern group elements
6667 + */
6668 + for (i=0; i<table->smtNumberOfGroups; i++)
6669 + freeMatchPatternGroupElement(table->smtGroups[i]);
6671 + /*
6672 + * Free matching pattern sequence elements
6673 + */
6674 + for (i=0; i<table->smtNumberOfSeqElements; i++)
6675 + freeMatchPatternSequenceElement(table->smtSequence[i]);
6677 + /*
6678 + * Free keyword reg. expressions
6679 + */
6680 + freePtr((void **)&table->smtAllPatRE);
6682 + freePtr((void **)&table->smtFlashPatRE);
6684 + XtFree((char *)table);
6688 +** Free the allocated memory contained in a MatchPatternTableElement data structure
6690 +static void freeMatchPatternTableElement( MatchPatternTableElement *element )
6692 + int i;
6694 + XtFree(element->mpteName);
6696 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
6698 + freePatternElement(element->mpteAll.pesPattern[i]);
6701 + freePtr((void **)&element->mpteStartEndRE);
6703 + freeXtPtr((void **)&element->mpteStart.pesPattern);
6705 + freeXtPtr((void **)&element->mpteMiddle.pesPattern);
6707 + freeXtPtr((void **)&element->mpteEnd.pesPattern);
6709 + XtFree((char *)element);
6713 +** Free the allocated memory contained in a PatternElement data structure
6715 +static void freePatternElement( PatternElement *element )
6717 + if (element->peType == PET_SINGLE)
6718 + freeStringPattern( &(element->peVal.peuSingle) );
6719 + else if (element->peType == PET_MULTIPLE)
6721 + freeStringPattern( &(element->peVal.peuMulti.mpStringPattern) );
6722 + XtFree( (char *)element->peVal.peuMulti.mpRefList );
6725 + XtFree( (char *)element );
6729 +** Free the allocated memory contained in a StringPattern data structure
6731 +static void freeStringPattern( StringPattern *strPat )
6733 + int i;
6735 + freeXtPtr((void **)&strPat->spText);
6736 + freeXtPtr((void **)&strPat->spOrigText);
6738 + freePtr((void **)&strPat->spTextRE);
6740 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
6741 + freeXtPtr((void **)&strPat->spOwnGlobalBackRef[i].spbreRegExpText);
6745 +** Free the allocated memory contained in a MatchPatternGroupElement data structure
6747 +static void freeMatchPatternGroupElement( MatchPatternGroupElement *group )
6749 + int i;
6751 + freeXtPtr((void **)&group->mpgeName);
6753 + freePtr((void **)&group->mpgeKeywordRE);
6755 + if (group->mpgeSubPatternIds != NULL)
6757 + for (i=0; i < group->mpgeNumberOfSubPatterns; i++)
6759 + XtFree(group->mpgeSubPatternIds[i]);
6761 + XtFree((char *)group->mpgeSubPatternIds);
6764 + XtFree((char *)group);
6768 +** Free the allocated memory contained in a MatchPatternSequenceElement data structure
6770 +static void freeMatchPatternSequenceElement( MatchPatternSequenceElement *sequence )
6772 + XtFree( sequence->mpseName );
6774 + XtFree( (char *)sequence );
6779 +** Format a matching pattern set parse error.
6781 +static void parseMatchingPatternSetError(
6782 + const char *stringStart,
6783 + const char *stoppedAt,
6784 + ErrorInfo *errInfo)
6786 + char *message = "";
6787 + int msgLen;
6788 + char *errorInForm = "matching pattern of \"%s\"";
6789 + char *errorIn;
6791 + if (errInfo->eiLanguageMode == NULL)
6793 + errorIn = "matching pattern";
6795 + else
6797 + errorIn = XtMalloc(strlen(errorInForm) + strlen(errInfo->eiLanguageMode)+1);
6798 + sprintf(errorIn, "matching pattern of \"%s\"", errInfo->eiLanguageMode);
6801 + if (errInfo->eiRegExpCompileMsg != NULL)
6803 + /*
6804 + * Error message of form:
6805 + * "MP \"eiMPTabElementName\", SP \"eiStringPatText\": eiRegExpCompileMsg" or
6806 + * "MP \"eiMPTabElementName\" - eiDetail: eiRegExpCompileMsg"
6807 + */
6809 + msgLen = strlen(errInfo->eiRegExpCompileMsg) + 1;
6811 + if (errInfo->eiMPTabElementName != NULL)
6812 + msgLen += strlen(errInfo->eiMPTabElementName) + 10;
6814 + if (errInfo->eiDetail != NULL)
6816 + msgLen += strlen(errInfo->eiDetail + 2);
6818 + else
6820 + if (errInfo->eiStringPatText != NULL)
6821 + msgLen += strlen(errInfo->eiStringPatText) + 9;
6824 + message = XtMalloc(msgLen);
6826 + strcpy(message, "");
6828 + if (errInfo->eiMPTabElementName != NULL)
6829 + sprintf( message, "MP \"%s\"", errInfo->eiMPTabElementName);
6831 + if (errInfo->eiDetail == NULL)
6833 + if (errInfo->eiStringPatText != NULL)
6834 + sprintf( message, "%s, SP \"%s\"", message, errInfo->eiStringPatText);
6836 + else
6838 + if (strlen(message) != 0)
6839 + strcat(message, " - ");
6841 + strcat(message, errInfo->eiDetail);
6844 + if (strlen(message) != 0)
6845 + strcat(message, ": ");
6847 + strcat(message, errInfo->eiRegExpCompileMsg);
6849 + else if (errInfo->eiDetail != NULL)
6851 + /*
6852 + * Error message of form:
6853 + * "MP \"eiMPTabElementName\", SP \"eiStringPatText\": Backref %d eiDetail
6854 + */
6855 + msgLen = strlen(errInfo->eiDetail) + 1;
6857 + if (errInfo->eiMPTabElementName != NULL)
6858 + msgLen += strlen(errInfo->eiMPTabElementName) + 7;
6859 + if (errInfo->eiStringPatText != NULL)
6860 + msgLen += strlen(errInfo->eiStringPatText) + 9;
6861 + if (errInfo->eiBackRefNbr != 0)
6862 + msgLen += 15;
6864 + message = XtMalloc(msgLen);
6866 + strcpy(message, "");
6868 + if (errInfo->eiMPTabElementName != NULL)
6869 + sprintf( message, "MP \"%s\"", errInfo->eiMPTabElementName);
6870 + if (errInfo->eiStringPatText != NULL)
6871 + sprintf( message, "%s, SP \"%s\"", message, errInfo->eiStringPatText);
6873 + if (strlen(message) != 0)
6874 + strcat(message, ": ");
6876 + if (errInfo->eiBackRefNbr != 0)
6877 + sprintf( message, "%s Backref %d ", message, errInfo->eiBackRefNbr);
6879 + strcat(message, errInfo->eiDetail);
6882 + ParseError(NULL, stringStart, stoppedAt, errorIn, message);
6884 + if (errInfo->eiRegExpCompileMsg != NULL || errInfo->eiDetail != NULL)
6886 + XtFree(message);
6889 + if (errInfo->eiLanguageMode != NULL)
6891 + XtFree(errorIn);
6894 + freeErrorInfo(errInfo);
6895 + initErrorInfo(errInfo);
6899 + * Pop-up a warning dialog showing a matching pattern set error.
6900 + */
6901 +static void dialogMatchingPatternSetError(
6902 + char *title,
6903 + ErrorInfo *errInfo)
6905 + char *message;
6906 + int msgLen = 1;
6908 + /*
6909 + * Error message of form:
6910 + * "Name : \"eiMPTabElementName\"\n
6911 + * "String: \"eiStringPatText\"\n
6912 + * eiDetail\n
6913 + * eiRegExpCompileMsg\n"
6914 + */
6916 + if (errInfo->eiMPTabElementName != NULL)
6917 + msgLen += strlen(errInfo->eiMPTabElementName) + 15;
6918 + if (errInfo->eiStringPatText != NULL)
6919 + msgLen += strlen(errInfo->eiStringPatText) + 15;
6920 + if (errInfo->eiDetail != NULL)
6921 + msgLen += strlen(errInfo->eiDetail) + 15;
6922 + if (errInfo->eiBackRefNbr != 0)
6923 + msgLen += 15;
6924 + if (errInfo->eiRegExpCompileMsg != NULL)
6925 + msgLen += strlen(errInfo->eiRegExpCompileMsg) + 15;
6927 + message = XtMalloc(msgLen);
6929 + strcpy(message, "");
6931 + if (errInfo->eiMPTabElementName != NULL)
6932 + sprintf( message, "%sName : \"%s\"\n", message, errInfo->eiMPTabElementName);
6933 + if (errInfo->eiStringPatText != NULL)
6934 + sprintf( message, "%sPattern: \"%s\"\n", message, errInfo->eiStringPatText);
6935 + if (errInfo->eiBackRefNbr != 0)
6936 + sprintf( message, "%sBackref %d ", message, errInfo->eiBackRefNbr);
6937 + if (errInfo->eiDetail != NULL)
6938 + sprintf( message, "%s%s\n", message, errInfo->eiDetail);
6939 + if (errInfo->eiRegExpCompileMsg != NULL)
6940 + sprintf( message, "%s%s\n", message, errInfo->eiRegExpCompileMsg);
6942 + DialogF(
6943 + DF_WARN, MatchPatternDialog.mpdShell, 1,
6944 + title,
6945 + "%s(language mode '%s')",
6946 + "OK",
6947 + message,
6948 + errInfo->eiLanguageMode);
6950 + XtFree(message);
6952 + freeErrorInfo(errInfo);
6953 + initErrorInfo(errInfo);
6957 +** Get matching pattern set name.
6958 +** Syntax:
6959 +** patternName ::= "name:"
6960 +** Returns true, if get was successful.
6962 +static int getMPSName(
6963 + char **inPtr,
6964 + ErrorInfo *errInfo,
6965 + char **name )
6967 + char *dummy;
6968 + char *field = ReadSymbolicField(inPtr);
6970 + if (field == NULL)
6972 + errInfo->eiDetail = "matching pattern name missing";
6973 + return False;
6976 + if (!SkipDelimiter(inPtr, &dummy))
6978 + errInfo->eiMPTabElementName = XtNewString(field);
6979 + errInfo->eiDetail = "':' missing after matching pattern name";
6980 + XtFree( field );
6981 + return False;
6984 + *name = field;
6986 + return True;
6990 +** Get matching pattern set type attribute.
6991 +** TypeAttribute ::=
6992 +** [s|g]:
6994 +** s : sub-pattern (pattern is only matched, if part of a pattern group).
6995 +** g : pattern (context) group (i.e. a sequence of sub-patterns).
6996 +** default: individual pattern (pattern is not part of a group and is
6997 +** matched individually.
6998 +** Returns true, if get was successful.
7000 +static int getMPSTypeAttribute(
7001 + char **inPtr,
7002 + ErrorInfo *errInfo,
7003 + MatchPatternType *type)
7005 + char *field = ReadSymbolicField(inPtr);
7006 + int successful = True;
7008 + *type = MPT_INDIVIDUAL;
7010 + if (field != NULL)
7012 + switch (*field)
7014 + case 'g':
7015 + *type = MPT_GROUP;
7016 + break;
7017 + case 's':
7018 + *type = MPT_SUB;
7019 + break;
7020 + default:
7021 + errInfo->eiDetail = "unknown matching pattern type attribute";
7022 + successful = False;
7026 + if (successful)
7028 + if (!SkipDelimiter(inPtr, &errInfo->eiDetail))
7030 + successful = False;
7034 + freeXtPtr((void **)&field);
7036 + return successful;
7040 +** Syntax:
7042 +** GlobalAttribute ::=
7043 +** [c][f][m][p][u]:
7045 +** c : the content between start and end pattern is skipped
7046 +** during parsing (e.g. pattern encloses a comment).
7047 +** f : flash matching pattern (if not set, then only jump
7048 +** to matching pattern is supported).
7049 +** m : mono pattern - set exist out of only one single pattern
7050 +** (start pattern = end pattern; e.g. quotes like ")
7051 +** p : ignore highlight info code of single patterns of this set
7052 +** ("plain").
7054 +** Returns TRUE, if global attribute was successful read.
7056 +static int getMPSGlobalAttribute(
7057 + char **inPtr,
7058 + char **errMsg,
7059 + int *isMonoPattern,
7060 + int *comment,
7061 + int *flash,
7062 + int *ignoreHighLightInfo)
7064 + char *field = ReadSymbolicField(inPtr);
7065 + char *attribute;
7066 + int successful = True;
7068 + *isMonoPattern = False;
7069 + *comment = False;
7070 + *flash = False;
7071 + *ignoreHighLightInfo = False;
7073 + if (field != NULL)
7075 + attribute = field;
7076 + while (*attribute != '\0' && successful)
7078 + switch (*attribute)
7080 + case 'c':
7081 + *comment = True;
7082 + break;
7083 + case 'f':
7084 + *flash = True;
7085 + break;
7086 + case 'm':
7087 + *isMonoPattern = True;
7088 + break;
7089 + case 'p':
7090 + *ignoreHighLightInfo = True;
7091 + break;
7092 + default:
7093 + *errMsg = "unknown global attribute";
7094 + successful = False;
7096 + attribute ++;
7100 + if (successful)
7102 + if (!SkipDelimiter(inPtr, errMsg))
7104 + successful = False;
7108 + freeXtPtr((void **)&field);
7110 + return successful;
7114 +** Get matching pattern set attribute.
7116 +** Syntax:
7118 +** patternAttribute ::=
7119 +** [s|m|e][w|l|r][i]:
7121 +** StringPatternKind:
7122 +** s : start string pattern.
7123 +** m : middle string pattern.
7124 +** e : end string pattern.
7125 +** WordBoundaryAttribute:
7126 +** w : pattern is word (i.e. before and after pattern
7127 +** there must be a delimiter).
7128 +** l : before pattern must be a delimiter (left side).
7129 +** r : after pattern must be a delimiter (right side).
7130 +** default: neither before nor after pattern must be a delimiter.
7131 +** StringAttribute:
7132 +** i : pattern is case insensitive (if not set: pattern is
7133 +** case sensitive).
7134 +** x : pattern is regular expression (if not set: pattern is
7135 +** literal string).
7137 +** Returns TRUE, if pattern attribute was successful read.
7139 +static int getMPSPatternAttribute(
7140 + char **inPtr,
7141 + char **errMsg,
7142 + PatternElementKind *patternKind,
7143 + PatternWordBoundary *wordBoundary,
7144 + int *caseInsensitive,
7145 + int *regularExpression)
7147 + char *field = ReadSymbolicField(inPtr);
7148 + char *attribute;
7149 + int successful = True;
7151 + *patternKind = PEK_UNKNOWN;
7152 + *wordBoundary = PWB_NONE;
7153 + *caseInsensitive = False;
7154 + *regularExpression = False;
7156 + if (field != NULL)
7158 + attribute = field;
7159 + while (*attribute != '\0' && successful)
7161 + switch (*attribute)
7163 + case 'e':
7164 + *patternKind = PEK_END;
7165 + break;
7166 + case 'i':
7167 + *caseInsensitive = True;
7168 + break;
7169 + case 'l':
7170 + *wordBoundary = PWB_LEFT;
7171 + break;
7172 + case 'm':
7173 + *patternKind = PEK_MIDDLE;
7174 + break;
7175 + case 'r':
7176 + *wordBoundary = PWB_RIGHT;
7177 + break;
7178 + case 's':
7179 + *patternKind = PEK_START;
7180 + break;
7181 + case 'w':
7182 + *wordBoundary = PWB_BOTH;
7183 + break;
7184 + case 'x':
7185 + *regularExpression = True;
7186 + break;
7187 + default:
7188 + *errMsg = "unknown string pattern attribute";
7189 + successful = False;
7191 + attribute ++;
7195 + if (successful)
7197 + if (!SkipDelimiter(inPtr, errMsg))
7199 + successful = False;
7203 + freeXtPtr((void **)&field);
7205 + return successful;
7209 +** Returns the (to be reserved) reg. ex. length of an pattern element.
7210 +** Update total number of multi patterns, too.
7212 +static int patternElementLen(
7213 + ReadMatchPatternInfo *info,
7214 + PatternElement *patElement,
7215 + int *nbrOfMultiPatterns)
7217 + PatternElement *referredElement;
7218 + StringPattern *strPat = NULL;
7219 + int patElementLen;
7221 + switch (patElement->peType)
7223 + case PET_SINGLE:
7224 + strPat = &patElement->peVal.peuSingle;
7225 + break;
7227 + case PET_MULTIPLE:
7228 + strPat = &patElement->peVal.peuMulti.mpStringPattern;
7230 + (*nbrOfMultiPatterns) ++;
7232 + break;
7234 + case PET_REFERENCE:
7235 + referredElement =
7236 + info->rmpiElement[patElement->peVal.peuRef.prElementIdx]->
7237 + mpteAll.pesPattern[patElement->peVal.peuRef.prPatternIdx];
7239 + strPat = &referredElement->peVal.peuMulti.mpStringPattern;
7240 + break;
7243 + /*
7244 + * reserve additional 4 characters ("(?i)") for case insensitive search
7245 + */
7246 + if (strPat->spCaseInsensitive)
7247 + patElementLen = strPat->spLength + 4;
7248 + else
7249 + patElementLen = strPat->spLength;
7251 + /*
7252 + * reserve additional 4 characters ("(?:)") for regular expression
7253 + */
7254 + if (strPat->spRegularExpression)
7255 + patElementLen += 4;
7257 + return patElementLen;
7261 +** Returns the (to be reserved) total reg. ex. length of given
7262 +** MatchPatternTableElement. Update total number of multi patterns, too.
7264 +static int totalMatchPatternTableElementLen(
7265 + ReadMatchPatternInfo *info,
7266 + MatchPatternTableElement *element,
7267 + int *nbrOfMultiPatterns)
7269 + int i;
7270 + int totalLen = 0;
7272 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i ++)
7274 + totalLen +=
7275 + patternElementLen(
7276 + info,
7277 + element->mpteAll.pesPattern[i],
7278 + nbrOfMultiPatterns );
7281 + return totalLen;
7285 +** Returns the (to be reserved) total reg. ex. length of given
7286 +** read match pattern info. Counts total number of multi patterns, too.
7288 +static int totalKeywordOfTableLen(
7289 + ReadMatchPatternInfo *info,
7290 + int *nbrOfMultiPatterns)
7292 + int i;
7293 + int totalLen = 0;
7295 + *nbrOfMultiPatterns = 0;
7297 + for (i=0; i<info->rmpiNbrOfElements; i ++)
7299 + totalLen +=
7300 + totalMatchPatternTableElementLen(
7301 + info,
7302 + info->rmpiElement[i],
7303 + nbrOfMultiPatterns);
7306 + return totalLen;
7310 +** Add given StringPattern to given reg. ex. strings
7312 +static void addPatternToRegExpString(
7313 + StringPattern *pattern,
7314 + RegExpStringInfo *regExpStringInfo)
7316 + char *r = NULL, *s;
7317 + char *adaptedRegExpText = NULL;
7318 + int prevLen = 0;
7320 + /*
7321 + * Select the buffer, where the pattern needs to be added
7322 + * to (depending on its word boundary). Prepare the buffer
7323 + * by evtl. adding a prefix, if related buffer is empty.
7324 + */
7325 + switch (pattern->spWordBoundary)
7327 + case PWB_NONE:
7328 + prevLen = strlen( regExpStringInfo->resiNoneWBRegExpString );
7330 + r = regExpStringInfo->resiNoneWBRegExpString + strlen( regExpStringInfo->resiNoneWBRegExpString );
7331 + break;
7332 + case PWB_LEFT:
7333 + prevLen = strlen( regExpStringInfo->resiLeftWBRegExpString );
7334 + if (prevLen == 0)
7336 + strcpy( regExpStringInfo->resiLeftWBRegExpString, "<(?:" );
7338 + r = regExpStringInfo->resiLeftWBRegExpString + strlen( regExpStringInfo->resiLeftWBRegExpString );
7339 + break;
7340 + case PWB_RIGHT:
7341 + prevLen = strlen( regExpStringInfo->resiRightWBRegExpString );
7342 + if (prevLen == 0)
7344 + strcpy( regExpStringInfo->resiRightWBRegExpString, "(?:" );
7346 + r = regExpStringInfo->resiRightWBRegExpString + strlen( regExpStringInfo->resiRightWBRegExpString );
7347 + break;
7348 + case PWB_BOTH:
7349 + prevLen = strlen( regExpStringInfo->resiBothWBRegExpString );
7350 + if (prevLen == 0)
7352 + strcpy( regExpStringInfo->resiBothWBRegExpString, "<(?:" );
7354 + r = regExpStringInfo->resiBothWBRegExpString + strlen( regExpStringInfo->resiBothWBRegExpString );
7355 + break;
7358 + /*
7359 + * add an "or" if there is already a pattern in the buffer
7360 + */
7361 + if (prevLen != 0)
7363 + *r++ = '|';
7366 + /*
7367 + * add "(?i" to order case insensitive search
7368 + */
7369 + if (pattern->spCaseInsensitive)
7371 + *r++ = '(';
7372 + *r++ = '?';
7373 + *r++ = 'i';
7376 + /*
7377 + * add "(?:" to group this regular expression
7378 + */
7379 + if (pattern->spRegularExpression)
7381 + *r++ = '(';
7382 + *r++ = '?';
7383 + *r++ = ':';
7385 + adaptedRegExpText =
7386 + adaptLocalBackRefs(
7387 + pattern->spText,
7388 + &regExpStringInfo->resiLocalBackRefID);
7390 + s = adaptedRegExpText;
7392 + else
7394 + s = pattern->spText;
7397 + /*
7398 + * add the pattern characters - evtl. escaped, if special
7399 + * regular expression symbols & pattern is no reg. exp. -
7400 + * to the buffer:
7401 + */
7403 + while (*s != '\0')
7405 + if (!pattern->spRegularExpression)
7407 + switch (*s)
7409 + case '(':
7410 + case ')':
7411 + case '-':
7412 + case '[':
7413 + case ']':
7414 + case '<':
7415 + case '>':
7416 + case '{':
7417 + case '}':
7418 + case '.':
7419 + case '\\':
7420 + case '|':
7421 + case '^':
7422 + case '$':
7423 + case '*':
7424 + case '+':
7425 + case '?':
7426 + case '&':
7427 + *r++ = '\\';
7428 + break;
7429 + };
7432 + *r++ = *s++;
7435 + /*
7436 + * close "reg. exp. group" bracket
7437 + */
7438 + if (pattern->spRegularExpression)
7440 + *r++ = ')';
7442 + XtFree(adaptedRegExpText);
7445 + /*
7446 + * close case insensitive search bracket
7447 + */
7448 + if (pattern->spCaseInsensitive)
7450 + *r++ = ')';
7453 + /*
7454 + * terminate added string
7455 + */
7456 + *r = '\0';
7460 +** Adapt local backrefs inside given regExpText by common local IDs.
7461 +** Returns new allocated reg. exp. string holding common local backrefs.
7463 +static char *adaptLocalBackRefs(
7464 + char *regExpText,
7465 + int *commonLocalId)
7467 + int id;
7468 + int ownLocalId = 0;
7469 + char *s = regExpText;
7470 + char *newRegExpText = XtMalloc(strlen(regExpText)*3);
7471 + char *n = newRegExpText;
7472 + int localBackRefList[MAX_LOCAL_BACK_REF_ID];
7474 + /*
7475 + * put all local backrefs into "localBackRefList".
7476 + */
7477 + scanForLocalBackRefs(regExpText, localBackRefList);
7479 + while (*s != '\0')
7481 + *n++ = *s;
7483 + if (*s == '\\')
7485 + s++;
7487 + if (isdigit((unsigned char)*s))
7489 + /*
7490 + * \n (n=1..9) found: replace local backref.
7491 + * by "common local ID"
7492 + */
7493 + id =
7494 + (int)((unsigned char)*s - (unsigned char)'0') - 1;
7496 + if (localBackRefList[id] != NO_LOCAL_BACK_REF_ID &&
7497 + localBackRefList[id] != LOCAL_BACK_REF_ID_USED)
7499 + *n++ = (char)((int)('0') + localBackRefList[id]);
7501 + else
7503 + *n++ = '0';
7506 + s ++;
7508 + else if (*s != '\0')
7510 + /*
7511 + * copy escaped character
7512 + */
7513 + *n++ = *s++;
7516 + else if (*s == '(')
7518 + s ++;
7520 + if (*s == '?')
7522 + /*
7523 + * non capturing parentheses found -> just copy it
7524 + */
7525 + *n++ = *s++;
7527 + else
7529 + /*
7530 + * capturing parentheses found:
7531 + */
7532 + if (localBackRefList[ownLocalId] == LOCAL_BACK_REF_ID_USED)
7534 + /*
7535 + * backref used within given reg. exp. text:
7536 + * remember common local id for replacement later on
7537 + */
7538 + localBackRefList[ownLocalId] = *commonLocalId;
7539 + (*commonLocalId) ++;
7540 + ownLocalId ++;
7542 + else
7544 + /*
7545 + * backref not used within given reg. exp. text:
7546 + * replace capturing parentheses by non capturing one
7547 + */
7548 + *n++ = '?';
7549 + *n++ = ':';
7553 + else
7555 + s ++;
7559 + /*
7560 + * terminate adapted string
7561 + */
7562 + *n = '\0';
7564 + return newRegExpText;
7568 +** Get all local backrefs of given regExpText and put them into
7569 +** given localBackRefList.
7571 +static void scanForLocalBackRefs(
7572 + char *regExpText,
7573 + int *localBackRefList)
7575 + int i;
7576 + int localId;
7577 + char *s = regExpText;
7579 + for (i=0; i<MAX_LOCAL_BACK_REF_ID; i++)
7581 + localBackRefList[i] = NO_LOCAL_BACK_REF_ID;
7584 + while (*s != '\0')
7586 + if (*s == '\\')
7588 + if (isdigit((unsigned char)*(s+1)))
7590 + /*
7591 + * \n (n=1..9) found: flag usage in local backref list
7592 + */
7593 + localId =
7594 + (int)((unsigned char)*(s+1) - (unsigned char)'0') - 1;
7596 + localBackRefList[localId] = LOCAL_BACK_REF_ID_USED;
7598 + s ++;
7600 + else if (*(s+1) != '\0')
7601 + s ++;
7603 + s ++;
7608 +** Returns true, if string of given multi pattern reference was
7609 +** not added to regExpStringInfo.
7611 +static int isMultiPatternNotAdded(
7612 + RegExpStringInfo *regExpStringInfo,
7613 + PatternReference *toBeAddedPR)
7615 + int i;
7616 + PatternReference *addedPR;
7617 + PatternReference *newPR;
7619 + for (i=0; i < regExpStringInfo->resiNbrOfAddedMultiPat; i++)
7621 + addedPR = regExpStringInfo->resiAddedMultiPat[i];
7623 + if (addedPR->prElementIdx == toBeAddedPR->prElementIdx &&
7624 + addedPR->prPatternIdx == toBeAddedPR->prPatternIdx)
7626 + return False;
7630 + newPR = (PatternReference *)XtMalloc(sizeof(PatternReference));
7632 + *newPR = *toBeAddedPR;
7634 + regExpStringInfo->resiAddedMultiPat[regExpStringInfo->resiNbrOfAddedMultiPat ++] = newPR;
7636 + return True;
7640 +** add given PatternElement to given reg. exp. strings
7642 +static void addUniquePatternToRegExpString(
7643 + PatternElement *patElement,
7644 + PatternReference *patElementReference,
7645 + ReadMatchPatternInfo *readMatchPatternInfo,
7646 + RegExpStringInfo *regExpStringInfo)
7648 + PatternElement *referredElement;
7649 + PatternReference referredPatReference;
7651 + switch (patElement->peType)
7653 + case PET_SINGLE:
7654 + addPatternToRegExpString(
7655 + &(patElement->peVal.peuSingle),
7656 + regExpStringInfo);
7657 + break;
7659 + case PET_MULTIPLE:
7660 + /*
7661 + * add element to reg. exp. string only, if it was
7662 + * not added before.
7663 + */
7664 + if (isMultiPatternNotAdded(regExpStringInfo, patElementReference))
7666 + addPatternToRegExpString(
7667 + &(patElement->peVal.peuMulti.mpStringPattern),
7668 + regExpStringInfo);
7670 + break;
7672 + case PET_REFERENCE:
7673 + /*
7674 + * add referred element to reg. exp. string only, if related
7675 + * multi pattern was not added before.
7676 + */
7677 + referredPatReference = patElement->peVal.peuRef;
7679 + referredElement =
7680 + readMatchPatternInfo->rmpiElement[referredPatReference.prElementIdx]->
7681 + mpteAll.pesPattern[referredPatReference.prPatternIdx];
7683 + if (isMultiPatternNotAdded(regExpStringInfo, &referredPatReference))
7685 + addPatternToRegExpString(
7686 + &(referredElement->peVal.peuMulti.mpStringPattern),
7687 + regExpStringInfo);
7689 + break;
7694 +** add given MatchPatternTableElement to given reg. ex. strings
7696 +static void addElementToRegExpString(
7697 + MatchPatternTableElement *element,
7698 + ReadMatchPatternInfo *readMatchPatternInfo,
7699 + RegExpStringInfo *regExpStringInfo)
7701 + int i;
7702 + PatternReference elementRef;
7704 + elementRef.prElementIdx = element->mpteIndex;
7706 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i ++)
7708 + elementRef.prPatternIdx = i;
7710 + addUniquePatternToRegExpString(
7711 + element->mpteAll.pesPattern[i],
7712 + &elementRef,
7713 + readMatchPatternInfo,
7714 + regExpStringInfo);
7719 +** Concatenate strings stored by regExpStringInfo.
7720 +** Free given regExpStringInfo afterwards.
7721 +** Returns resulting string.
7723 +static void catSMTRegExpStrings(
7724 + RegExpStringInfo *regExpStringInfo,
7725 + char **regExpString)
7727 + int resultingLen;
7729 + /*
7730 + * allocate & init. a buffer for the resulting regular expression
7731 + */
7732 + resultingLen =
7733 + strlen( regExpStringInfo->resiNoneWBRegExpString ) +
7734 + strlen( regExpStringInfo->resiLeftWBRegExpString ) +
7735 + strlen( regExpStringInfo->resiRightWBRegExpString ) +
7736 + strlen( regExpStringInfo->resiBothWBRegExpString ) + 5;
7738 + *regExpString = XtMalloc( resultingLen );
7740 + strcpy( *regExpString, "" );
7742 + /*
7743 + * add the single parts to the resulting regular expression
7744 + * (= cat of parts separated by an "or")
7745 + */
7746 + addSMTRegExpString( *regExpString, regExpStringInfo->resiNoneWBRegExpString, "" );
7747 + addSMTRegExpString( *regExpString, regExpStringInfo->resiLeftWBRegExpString, ")" );
7748 + addSMTRegExpString( *regExpString, regExpStringInfo->resiRightWBRegExpString, ")>" );
7749 + addSMTRegExpString( *regExpString, regExpStringInfo->resiBothWBRegExpString, ")>" );
7751 + /*
7752 + * free buffers
7753 + */
7754 + freeRegExpStringInfo( regExpStringInfo );
7758 +** Free the allocated memory contained in a RegExpStringInfo data structure
7760 +static void freeRegExpStringInfo(
7761 + RegExpStringInfo *regExpStringInfo)
7763 + int i;
7765 + XtFree( regExpStringInfo->resiNoneWBRegExpString );
7766 + XtFree( regExpStringInfo->resiLeftWBRegExpString );
7767 + XtFree( regExpStringInfo->resiRightWBRegExpString );
7768 + XtFree( regExpStringInfo->resiBothWBRegExpString );
7770 + for (i=0; i < regExpStringInfo->resiNbrOfAddedMultiPat; i ++)
7771 + XtFree( (char *)regExpStringInfo->resiAddedMultiPat[i] );
7773 + XtFree( (char *)regExpStringInfo->resiAddedMultiPat);
7777 +** Compose regular expression for start / end pattern.
7779 +static void composeStartEndRegExpString(
7780 + ReadMatchPatternInfo *readMatchPatternInfo,
7781 + MatchPatternTableElement *element,
7782 + char **regExpString)
7784 + int i;
7785 + RegExpStringInfo regExpStringInfo;
7786 + PatternReference elementRef;
7787 + PatternElementSet startPat = element->mpteStart;
7788 + PatternElementSet endPat = element->mpteEnd;
7790 + /*
7791 + * Allocate buffers for keyword regular expression.
7792 + */
7793 + setupRegExpStringBuffers(
7794 + readMatchPatternInfo,
7795 + &regExpStringInfo);
7797 + /*
7798 + * Treat start / end element of MatchPatternTableElement
7799 + */
7801 + elementRef.prElementIdx = element->mpteIndex;
7803 + for (i=0; i < startPat.pesNumberOfPattern; i ++)
7805 + elementRef.prPatternIdx = startPat.pesPattern[i]->peIndex;
7807 + addUniquePatternToRegExpString(
7808 + startPat.pesPattern[i],
7809 + &elementRef,
7810 + readMatchPatternInfo,
7811 + &regExpStringInfo);
7814 + for (i=0; i < endPat.pesNumberOfPattern; i ++)
7816 + elementRef.prPatternIdx = endPat.pesPattern[i]->peIndex;
7818 + addUniquePatternToRegExpString(
7819 + endPat.pesPattern[i],
7820 + &elementRef,
7821 + readMatchPatternInfo,
7822 + &regExpStringInfo);
7825 + /*
7826 + * Assemble the resulting regular expression
7827 + */
7828 + catSMTRegExpStrings(
7829 + &regExpStringInfo,
7830 + regExpString);
7833 +static void copyStringMatchTableForDialog(
7834 + StringMatchTable *sourceTable,
7835 + DialogMatchPatternInfo *dialogTable )
7837 + int i;
7839 + /*
7840 + * if no source table exist (yet), then set nbr. of elements / groups to 0
7841 + */
7842 + if (sourceTable == NULL)
7844 + dialogTable->dmpiNbrOfSeqElements = 0;
7846 + return;
7849 + /*
7850 + * copy matching pattern sequence
7851 + */
7852 + dialogTable->dmpiNbrOfSeqElements = sourceTable->smtNumberOfSeqElements;
7854 + for (i=0; i < sourceTable->smtNumberOfSeqElements; i ++)
7856 + copySequenceElementForDialog(
7857 + sourceTable,
7858 + sourceTable->smtSequence[i],
7859 + &dialogTable->dmpiSequence[i] );
7863 +static void *copyMatchPatternElementForDialog(
7864 + MatchPatternTable *table,
7865 + int sourceElementIdx)
7867 + int i;
7868 + int patIdx = 0;
7869 + MatchPatternTableElement *sourceElement;
7870 + DialogMatchPatternTableElement *destination;
7872 + sourceElement = table->mptElements[sourceElementIdx];
7874 + destination =
7875 + (DialogMatchPatternTableElement *)XtMalloc( sizeof(DialogMatchPatternTableElement) );
7877 + destination->dmpteName = XtNewString(sourceElement->mpteName);
7878 + destination->dmpteType = sourceElement->mpteType;
7879 + destination->dmpteSkipBtwnStartEnd = sourceElement->mpteSkipBtwnStartEnd;
7880 + destination->dmpteIgnoreHighLightInfo = sourceElement->mpteIgnoreHighLightInfo;
7881 + destination->dmpteFlash = sourceElement->mpteFlash;
7883 + for (i=0; i<sourceElement->mpteAll.pesNumberOfPattern; i++)
7885 + copyPatternForDialog(
7886 + table,
7887 + sourceElement->mpteAll.pesPattern[i],
7888 + &destination->dmptePatterns.dspElements[patIdx ++]);
7891 + destination->dmptePatterns.dspNumberOfPatterns = patIdx;
7893 + return (void *)destination;
7896 +static void copyPatternForDialog(
7897 + MatchPatternTable *table,
7898 + PatternElement *sourcePattern,
7899 + DialogStringPatternElement **dialogPattern )
7901 + DialogStringPatternElement *newPat;
7902 + StringPattern *strSourcePat = GetStringPattern( table, sourcePattern );
7904 + newPat = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
7905 + *dialogPattern = newPat;
7907 + if( strSourcePat->spOrigText != NULL)
7908 + newPat->dspeText = XtNewString(strSourcePat->spOrigText);
7909 + else
7910 + newPat->dspeText = XtNewString(strSourcePat->spText);
7912 + newPat->dspeKind = sourcePattern->peKind;
7913 + newPat->dspeWordBoundary = strSourcePat->spWordBoundary;
7914 + newPat->dspeCaseInsensitive = strSourcePat->spCaseInsensitive;
7915 + newPat->dspeRegularExpression = strSourcePat->spRegularExpression;
7918 +static void *copyGroupElementForDialog(
7919 + MatchPatternGroupElement *sourceGroup)
7921 + int i;
7922 + DialogMatchPatternGroupElement *destination;
7924 + destination =
7925 + (DialogMatchPatternGroupElement *)XtMalloc( sizeof(DialogMatchPatternGroupElement) );
7927 + destination->dmpgeName = XtNewString(sourceGroup->mpgeName);
7928 + destination->dmpgeNumberOfSubPatterns = sourceGroup->mpgeNumberOfSubPatterns;
7930 + for ( i=0; i<destination->dmpgeNumberOfSubPatterns; i ++)
7932 + destination->dmpgeSubPatternIds[i] =
7933 + XtNewString(sourceGroup->mpgeSubPatternIds[i]);
7936 + return destination;
7939 +static void copySequenceElementForDialog(
7940 + StringMatchTable *sourceTable,
7941 + MatchPatternSequenceElement *sourceSeqElement,
7942 + DialogMatchPatternSequenceElement **dialogSeqElement )
7944 + DialogMatchPatternSequenceElement *destSeqElement;
7946 + destSeqElement =
7947 + (DialogMatchPatternSequenceElement *)XtMalloc( sizeof(DialogMatchPatternSequenceElement) );
7949 + *dialogSeqElement = destSeqElement;
7951 + destSeqElement->dmpseName = XtNewString(sourceSeqElement->mpseName);
7952 + destSeqElement->dmpseType = sourceSeqElement->mpseType;
7953 + destSeqElement->dmpseValid = True;
7955 + if (destSeqElement->dmpseType == MPT_GROUP)
7957 + destSeqElement->dmpsePtr =
7958 + copyGroupElementForDialog(
7959 + sourceTable->smtGroups[sourceSeqElement->mpseIndex]);
7961 + else
7963 + destSeqElement->dmpsePtr =
7964 + copyMatchPatternElementForDialog(
7965 + sourceTable->smtAllPatterns,
7966 + sourceSeqElement->mpseIndex);
7970 +static DialogMatchPatternSequenceElement *copyDialogSequenceElement(
7971 + DialogMatchPatternSequenceElement *sourceSeq)
7973 + DialogMatchPatternSequenceElement *destSeq;
7975 + destSeq =
7976 + (DialogMatchPatternSequenceElement *)XtMalloc(sizeof(DialogMatchPatternSequenceElement));
7978 + destSeq->dmpseName = XtNewString(sourceSeq->dmpseName);
7979 + destSeq->dmpseType = sourceSeq->dmpseType;
7980 + destSeq->dmpseValid = True;
7982 + destSeq->dmpsePtr = sourceSeq->dmpsePtr;
7984 + return destSeq;
7987 +static void freeDialogMatchPatternElement(
7988 + DialogMatchPatternTableElement *dialogElement )
7990 + int i;
7992 + for (i=0; i<dialogElement->dmptePatterns.dspNumberOfPatterns; i ++)
7994 + freeDialogStringPatternElement(
7995 + dialogElement->dmptePatterns.dspElements[i]);
7998 + freeXtPtr((void **)&dialogElement->dmpteName);
8000 + freeXtPtr((void **)&dialogElement);
8003 +static void freeDialogStringPatternElement(
8004 + DialogStringPatternElement *element)
8006 + freeXtPtr((void **)&element->dspeText);
8008 + freeXtPtr((void **)&element);
8011 +static void freeDialogGroupElement(
8012 + DialogMatchPatternGroupElement *dialogGroup )
8014 + int i;
8016 + for (i=0; i<dialogGroup->dmpgeNumberOfSubPatterns; i ++)
8018 + freeXtPtr((void **)&dialogGroup->dmpgeSubPatternIds[i]);
8021 + freeXtPtr((void **)&dialogGroup->dmpgeName);
8023 + freeXtPtr((void **)&dialogGroup);
8026 +static void freeDialogSequenceElement(
8027 + DialogMatchPatternSequenceElement *dialogSeq )
8029 + freeXtPtr((void **)&dialogSeq->dmpseName);
8031 + if (dialogSeq->dmpseType == MPT_GROUP)
8033 + freeDialogGroupElement(
8034 + (DialogMatchPatternGroupElement *)dialogSeq->dmpsePtr );
8036 + else
8038 + freeDialogMatchPatternElement(
8039 + (DialogMatchPatternTableElement *)dialogSeq->dmpsePtr );
8042 + freeXtPtr((void **)&dialogSeq);
8045 +static void copyDialogStringPatternsFromTable(
8046 + DialogMatchPatternTableElement *tableElement,
8047 + DialogStringPatterns *destPatterns)
8049 + int i;
8051 + destPatterns->dspNumberOfPatterns =
8052 + tableElement->dmptePatterns.dspNumberOfPatterns;
8054 + for (i=0; i<destPatterns->dspNumberOfPatterns; i++)
8056 + destPatterns->dspElements[i] =
8057 + copyDialogStringPatternElement(
8058 + tableElement->dmptePatterns.dspElements[i] );
8062 +static void copyDialogStringPatterns(
8063 + DialogStringPatterns *sourcePatterns,
8064 + DialogStringPatterns *destPatterns)
8066 + int i;
8068 + destPatterns->dspNumberOfPatterns =
8069 + sourcePatterns->dspNumberOfPatterns;
8071 + for (i=0; i<destPatterns->dspNumberOfPatterns; i++)
8073 + destPatterns->dspElements[i] =
8074 + copyDialogStringPatternElement(
8075 + sourcePatterns->dspElements[i] );
8079 +static void freeDialogStringPatterns(
8080 + DialogStringPatterns *patterns)
8082 + int i;
8084 + for (i=0; i<patterns->dspNumberOfPatterns; i++)
8086 + freeDialogStringPatternElement(patterns->dspElements[i]);
8089 + patterns->dspNumberOfPatterns = 0;
8092 +static DialogStringPatternElement *copyDialogStringPatternElement(
8093 + DialogStringPatternElement *sourceElement)
8095 + DialogStringPatternElement *newPatElement;
8097 + newPatElement = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
8099 + newPatElement->dspeText = XtNewString(sourceElement->dspeText);
8100 + newPatElement->dspeKind = sourceElement->dspeKind;
8101 + newPatElement->dspeWordBoundary = sourceElement->dspeWordBoundary;
8102 + newPatElement->dspeCaseInsensitive = sourceElement->dspeCaseInsensitive;
8103 + newPatElement->dspeRegularExpression = sourceElement->dspeRegularExpression;
8105 + return newPatElement;
8108 +static void copyDialogPatternNamesFromGroup(
8109 + DialogMatchPatternGroupElement *group,
8110 + DialogStringPatterns *destPatterns)
8112 + int i;
8114 + destPatterns->dspNumberOfPatterns =
8115 + group->dmpgeNumberOfSubPatterns;
8117 + for (i=0; i<destPatterns->dspNumberOfPatterns; i++)
8119 + destPatterns->dspElements[i] =
8120 + copyDialogPatternName(
8121 + group->dmpgeSubPatternIds[i] );
8125 +static DialogStringPatternElement *copyDialogPatternName(
8126 + char *sourcePatternId)
8128 + DialogStringPatternElement *newPatElement;
8130 + newPatElement = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
8132 + newPatElement->dspeText = XtNewString(sourcePatternId);
8133 + newPatElement->dspeKind = PEK_START;
8134 + newPatElement->dspeWordBoundary = PWB_NONE;
8135 + newPatElement->dspeCaseInsensitive = False;
8136 + newPatElement->dspeRegularExpression = False;
8138 + return newPatElement;
8141 +static void copyDialogPatternNamesToGroup(
8142 + DialogStringPatterns *sourceNames,
8143 + DialogMatchPatternGroupElement *destGroup)
8145 + int i;
8147 + destGroup->dmpgeNumberOfSubPatterns =
8148 + sourceNames->dspNumberOfPatterns;
8150 + for (i=0; i<destGroup->dmpgeNumberOfSubPatterns; i++)
8152 + destGroup->dmpgeSubPatternIds[i] =
8153 + XtNewString(
8154 + sourceNames->dspElements[i]->dspeText);
8160 +** Present a dialog for editing matching pattern information
8162 +void EditMatchPatterns(WindowInfo *window)
8164 + Widget form, lmOptMenu;
8165 + Widget lmForm;
8166 + Widget okBtn, applyBtn, checkBtn, deleteBtn, closeBtn, helpBtn;
8167 + Widget restoreBtn, lmBtn;
8168 + Widget matchPatternsForm, matchPatternsFrame, matchPatternsLbl;
8169 + Widget matchPatternTypeBox, matchPatternTypeLbl;
8170 + Widget globalAttributesBox;
8171 + Widget stringPatternsFrame, stringPatternsForm;
8172 + Widget stringPatternTypeBox;
8173 + Widget wordBoundaryBox;
8174 + Widget stringAttributesBox;
8175 + StringMatchTable *table;
8176 + XmString s1;
8177 + int n;
8178 + Arg args[20];
8180 + /*
8181 + * if the dialog is already displayed, just pop it to the top and return
8182 + */
8183 + if (MatchPatternDialog.mpdShell != NULL)
8185 + RaiseDialogWindow(MatchPatternDialog.mpdShell);
8186 + return;
8189 + /*
8190 + * decide on an initial language mode
8191 + */
8192 + MatchPatternDialog.mpdLangModeName =
8193 + XtNewString(
8194 + window->languageMode == PLAIN_LANGUAGE_MODE ?
8195 + PLAIN_LM_STRING : LanguageModeName(window->languageMode));
8197 + /*
8198 + * find the associated matching pattern table to edit
8199 + */
8200 + table = (StringMatchTable *)FindStringMatchTable(MatchPatternDialog.mpdLangModeName);
8202 + /*
8203 + * copy the list of patterns to one that the user can freely edit
8204 + */
8205 + copyStringMatchTableForDialog( table, &MatchPatternDialog.mpdTable );
8207 + /*
8208 + * init. status information of dialog
8209 + */
8210 + MatchPatternDialog.currentDmptSeqElement = NULL;
8211 + MatchPatternDialog.currentDmptElement = NULL;
8212 + MatchPatternDialog.currentDmptGroup = NULL;
8214 + MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns = 0;
8215 + MatchPatternDialog.mpdStringPatternIsDisplayed = True;
8217 + /*
8218 + * Create a form widget in an application shell
8219 + */
8220 + n = 0;
8221 + XtSetArg(args[n], XmNdeleteResponse, XmDO_NOTHING); n++;
8222 + XtSetArg(args[n], XmNiconName, "Matching Patterns"); n++;
8223 + XtSetArg(args[n], XmNtitle, "Matching (Parenthesis) Patterns"); n++;
8224 + MatchPatternDialog.mpdShell = CreateShellWithBestVis(APP_NAME, APP_CLASS,
8225 + applicationShellWidgetClass, TheDisplay, args, n);
8226 + AddSmallIcon(MatchPatternDialog.mpdShell);
8227 + form = XtVaCreateManagedWidget("editMatchPatterns", xmFormWidgetClass,
8228 + MatchPatternDialog.mpdShell, XmNautoUnmanage, False,
8229 + XmNresizePolicy, XmRESIZE_NONE, NULL);
8230 + XtAddCallback(form, XmNdestroyCallback, destroyCB, NULL);
8231 + AddMotifCloseCallback(MatchPatternDialog.mpdShell, closeCB, NULL);
8233 + lmForm = XtVaCreateManagedWidget("lmForm", xmFormWidgetClass,
8234 + form,
8235 + XmNleftAttachment, XmATTACH_POSITION,
8236 + XmNleftPosition, 1,
8237 + XmNtopAttachment, XmATTACH_POSITION,
8238 + XmNtopPosition, 1,
8239 + XmNrightAttachment, XmATTACH_POSITION,
8240 + XmNrightPosition, 99, NULL);
8242 + MatchPatternDialog.mpdLmPulldown =
8243 + CreateLanguageModeMenu(lmForm, matchPatternLangModeCB, NULL, True);
8245 + n = 0;
8246 + XtSetArg(args[n], XmNspacing, 0); n++;
8247 + XtSetArg(args[n], XmNmarginWidth, 0); n++;
8248 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
8249 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8250 + XtSetArg(args[n], XmNleftPosition, 50); n++;
8251 + XtSetArg(args[n], XmNsubMenuId, MatchPatternDialog.mpdLmPulldown); n++;
8252 + lmOptMenu = XmCreateOptionMenu(lmForm, "langModeOptMenu", args, n);
8253 + XtManageChild(lmOptMenu);
8254 + MatchPatternDialog.mpdLmOptMenu = lmOptMenu;
8256 + XtVaCreateManagedWidget("lmLbl", xmLabelGadgetClass, lmForm,
8257 + XmNlabelString, s1=XmStringCreateSimple("Language Mode:"),
8258 + XmNmnemonic, 'M',
8259 + XmNuserData, XtParent(MatchPatternDialog.mpdLmOptMenu),
8260 + XmNalignment, XmALIGNMENT_END,
8261 + XmNrightAttachment, XmATTACH_POSITION,
8262 + XmNrightPosition, 50,
8263 + XmNtopAttachment, XmATTACH_FORM,
8264 + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
8265 + XmNbottomWidget, lmOptMenu, NULL);
8266 + XmStringFree(s1);
8268 + lmBtn = XtVaCreateManagedWidget("lmBtn", xmPushButtonWidgetClass, lmForm,
8269 + XmNlabelString, s1=MKSTRING("Add / Modify\nLanguage Mode..."),
8270 + XmNmnemonic, 'A',
8271 + XmNrightAttachment, XmATTACH_FORM,
8272 + XmNtopAttachment, XmATTACH_FORM, NULL);
8273 + XtAddCallback(lmBtn, XmNactivateCallback, pmLanguageModeDialogCB, NULL);
8274 + XmStringFree(s1);
8276 + okBtn = XtVaCreateManagedWidget("ok", xmPushButtonWidgetClass, form,
8277 + XmNlabelString, s1=XmStringCreateSimple("OK"),
8278 + XmNleftAttachment, XmATTACH_POSITION,
8279 + XmNleftPosition, 1,
8280 + XmNrightAttachment, XmATTACH_POSITION,
8281 + XmNrightPosition, 13,
8282 + XmNbottomAttachment, XmATTACH_FORM,
8283 + XmNbottomOffset, BORDER, NULL);
8284 + XtAddCallback(okBtn, XmNactivateCallback, okCB, NULL);
8285 + XmStringFree(s1);
8287 + applyBtn = XtVaCreateManagedWidget("apply", xmPushButtonWidgetClass, form,
8288 + XmNlabelString, s1=XmStringCreateSimple("Apply"),
8289 + XmNmnemonic, 'y',
8290 + XmNleftAttachment, XmATTACH_POSITION,
8291 + XmNleftPosition, 13,
8292 + XmNrightAttachment, XmATTACH_POSITION,
8293 + XmNrightPosition, 26,
8294 + XmNbottomAttachment, XmATTACH_FORM,
8295 + XmNbottomOffset, BORDER, NULL);
8296 + XtAddCallback(applyBtn, XmNactivateCallback, applyCB, NULL);
8297 + XmStringFree(s1);
8299 + checkBtn = XtVaCreateManagedWidget("check", xmPushButtonWidgetClass, form,
8300 + XmNlabelString, s1=XmStringCreateSimple("Check"),
8301 + XmNmnemonic, 'k',
8302 + XmNleftAttachment, XmATTACH_POSITION,
8303 + XmNleftPosition, 26,
8304 + XmNrightAttachment, XmATTACH_POSITION,
8305 + XmNrightPosition, 39,
8306 + XmNbottomAttachment, XmATTACH_FORM,
8307 + XmNbottomOffset, BORDER, NULL);
8308 + XtAddCallback(checkBtn, XmNactivateCallback, checkCB, NULL);
8309 + XmStringFree(s1);
8311 + deleteBtn = XtVaCreateManagedWidget("delete", xmPushButtonWidgetClass, form,
8312 + XmNlabelString, s1=XmStringCreateSimple("Delete"),
8313 + XmNmnemonic, 'D',
8314 + XmNleftAttachment, XmATTACH_POSITION,
8315 + XmNleftPosition, 39,
8316 + XmNrightAttachment, XmATTACH_POSITION,
8317 + XmNrightPosition, 52,
8318 + XmNbottomAttachment, XmATTACH_FORM,
8319 + XmNbottomOffset, BORDER, NULL);
8320 + XtAddCallback(deleteBtn, XmNactivateCallback, deleteCB, NULL);
8321 + XmStringFree(s1);
8323 + restoreBtn = XtVaCreateManagedWidget("restore", xmPushButtonWidgetClass, form,
8324 + XmNlabelString, s1=XmStringCreateSimple("Restore Defaults"),
8325 + XmNmnemonic, 'f',
8326 + XmNleftAttachment, XmATTACH_POSITION,
8327 + XmNleftPosition, 52,
8328 + XmNrightAttachment, XmATTACH_POSITION,
8329 + XmNrightPosition, 73,
8330 + XmNbottomAttachment, XmATTACH_FORM,
8331 + XmNbottomOffset, BORDER, NULL);
8332 + XtAddCallback(restoreBtn, XmNactivateCallback, restoreCB, NULL);
8333 + XmStringFree(s1);
8335 + closeBtn = XtVaCreateManagedWidget("close", xmPushButtonWidgetClass,
8336 + form,
8337 + XmNlabelString, s1=XmStringCreateSimple("Close"),
8338 + XmNleftAttachment, XmATTACH_POSITION,
8339 + XmNleftPosition, 73,
8340 + XmNrightAttachment, XmATTACH_POSITION,
8341 + XmNrightPosition, 86,
8342 + XmNbottomAttachment, XmATTACH_FORM,
8343 + XmNbottomOffset, BORDER, NULL);
8344 + XtAddCallback(closeBtn, XmNactivateCallback, closeCB, NULL);
8345 + XmStringFree(s1);
8347 + helpBtn = XtVaCreateManagedWidget("help", xmPushButtonWidgetClass,
8348 + form,
8349 + XmNlabelString, s1=XmStringCreateSimple("Help"),
8350 + XmNmnemonic, 'H',
8351 + XmNleftAttachment, XmATTACH_POSITION,
8352 + XmNleftPosition, 86,
8353 + XmNrightAttachment, XmATTACH_POSITION,
8354 + XmNrightPosition, 99,
8355 + XmNbottomAttachment, XmATTACH_FORM,
8356 + XmNbottomOffset, BORDER, NULL);
8357 + XtAddCallback(helpBtn, XmNactivateCallback, helpCB, NULL);
8358 + XmStringFree(s1);
8360 + stringPatternsFrame = XtVaCreateManagedWidget("stringPatternsFrame", xmFrameWidgetClass,
8361 + form,
8362 + XmNleftAttachment, XmATTACH_POSITION,
8363 + XmNleftPosition, 1,
8364 + XmNrightAttachment, XmATTACH_POSITION,
8365 + XmNrightPosition, 99,
8366 + XmNbottomAttachment, XmATTACH_WIDGET,
8367 + XmNbottomWidget, okBtn,
8368 + XmNbottomOffset, BORDER, NULL);
8369 + stringPatternsForm = XtVaCreateManagedWidget("stringPatternsForm", xmFormWidgetClass,
8370 + stringPatternsFrame, NULL);
8371 + MatchPatternDialog.mpdStringPatternsLbl = XtVaCreateManagedWidget("mpdStringPatternsLbl", xmLabelGadgetClass,
8372 + stringPatternsFrame,
8373 + XmNlabelString, s1=XmStringCreateSimple(STRING_PATTERNS_LBL_TXT),
8374 + XmNmarginHeight, 0,
8375 + XmNchildType, XmFRAME_TITLE_CHILD, NULL);
8376 + XmStringFree(s1);
8378 + n = 0;
8379 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
8380 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8381 + XtSetArg(args[n], XmNleftPosition, 1); n++;
8382 + XtSetArg(args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
8383 + XtSetArg(args[n], XmNrightPosition, LIST_RIGHT-1); n++;
8384 + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
8385 + XtSetArg(args[n], XmNbottomOffset, BORDER); n++;
8386 + MatchPatternDialog.mpdStringPatternsListW =
8387 + CreateManagedList(stringPatternsForm, "stringPatternsList", args,
8388 + n, (void **)MatchPatternDialog.currentStringPatterns.dspElements,
8389 + &MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns,
8390 + MAX_STRING_PATTERNS, 18,
8391 + getStringPatternDisplayedCB, NULL,
8392 + setStringPatternDisplayedCB, NULL,
8393 + freeStringPatternItemCB);
8394 + XtVaSetValues(MatchPatternDialog.mpdStringPatternsLbl, XmNuserData, MatchPatternDialog.mpdStringPatternsListW, NULL);
8396 + MatchPatternDialog.mpdStringPatternTypeLbl = XtVaCreateManagedWidget("mpdStringPatternTypeLbl", xmLabelGadgetClass,
8397 + stringPatternsForm,
8398 + XmNlabelString, s1=XmStringCreateSimple("String Pattern Type:"),
8399 + XmNmarginHeight, 0,
8400 + XmNalignment, XmALIGNMENT_BEGINNING,
8401 + XmNleftAttachment, XmATTACH_POSITION,
8402 + XmNleftPosition, LIST_RIGHT,
8403 + XmNtopAttachment, XmATTACH_FORM, NULL);
8404 + XmStringFree(s1);
8406 + stringPatternTypeBox = XtVaCreateManagedWidget("stringPatternTypeBox", xmRowColumnWidgetClass,
8407 + stringPatternsForm,
8408 + XmNorientation, XmHORIZONTAL,
8409 + XmNpacking, XmPACK_TIGHT,
8410 + XmNradioBehavior, True,
8411 + XmNleftAttachment, XmATTACH_POSITION,
8412 + XmNleftPosition, LIST_RIGHT,
8413 + XmNtopAttachment, XmATTACH_WIDGET,
8414 + XmNtopWidget, MatchPatternDialog.mpdStringPatternTypeLbl, NULL);
8415 + MatchPatternDialog.sptStartW = XtVaCreateManagedWidget("sptStartW",
8416 + xmToggleButtonWidgetClass, stringPatternTypeBox,
8417 + XmNset, True,
8418 + XmNmarginHeight, 0,
8419 + XmNlabelString, s1=XmStringCreateSimple(
8420 + "Start"),
8421 + NULL);
8422 + XmStringFree(s1);
8423 + MatchPatternDialog.sptMiddleW = XtVaCreateManagedWidget("sptMiddleW",
8424 + xmToggleButtonWidgetClass, stringPatternTypeBox,
8425 + XmNmarginHeight, 0,
8426 + XmNlabelString, s1=XmStringCreateSimple(
8427 + "Middle"),
8428 + NULL);
8429 + XmStringFree(s1);
8430 + MatchPatternDialog.sptEndW = XtVaCreateManagedWidget("sptEndW",
8431 + xmToggleButtonWidgetClass, stringPatternTypeBox,
8432 + XmNmarginHeight, 0,
8433 + XmNlabelString, s1=XmStringCreateSimple(
8434 + "End"),
8435 + NULL);
8436 + XmStringFree(s1);
8438 + MatchPatternDialog.mpdWordBoundaryLbl = XtVaCreateManagedWidget("mpdWordBoundaryLbl", xmLabelGadgetClass,
8439 + stringPatternsForm,
8440 + XmNlabelString, s1=XmStringCreateSimple("Word boundary:"),
8441 + XmNmarginHeight, 0,
8442 + XmNalignment, XmALIGNMENT_BEGINNING,
8443 + XmNleftAttachment, XmATTACH_POSITION,
8444 + XmNleftPosition, LIST_RIGHT,
8445 + XmNtopAttachment, XmATTACH_WIDGET,
8446 + XmNtopWidget, stringPatternTypeBox,
8447 + NULL);
8448 + XmStringFree(s1);
8450 + wordBoundaryBox = XtVaCreateManagedWidget("wordBoundaryBox", xmRowColumnWidgetClass,
8451 + stringPatternsForm,
8452 + XmNorientation, XmHORIZONTAL,
8453 + XmNpacking, XmPACK_TIGHT,
8454 + XmNradioBehavior, True,
8455 + XmNleftAttachment, XmATTACH_POSITION,
8456 + XmNleftPosition, LIST_RIGHT,
8457 + XmNtopAttachment, XmATTACH_WIDGET,
8458 + XmNtopWidget, MatchPatternDialog.mpdWordBoundaryLbl, NULL);
8459 + MatchPatternDialog.wbbBothW = XtVaCreateManagedWidget("wbbBothW",
8460 + xmToggleButtonWidgetClass, wordBoundaryBox,
8461 + XmNset, True,
8462 + XmNmarginHeight, 0,
8463 + XmNlabelString, s1=XmStringCreateSimple(
8464 + "Both (pattern is word)"),
8465 + NULL);
8466 + XmStringFree(s1);
8467 + MatchPatternDialog.wbbLeftW = XtVaCreateManagedWidget("wbbLeftW",
8468 + xmToggleButtonWidgetClass, wordBoundaryBox,
8469 + XmNmarginHeight, 0,
8470 + XmNlabelString, s1=XmStringCreateSimple(
8471 + "Left"),
8472 + NULL);
8473 + XmStringFree(s1);
8474 + MatchPatternDialog.wbbRightW = XtVaCreateManagedWidget("wbbRightW",
8475 + xmToggleButtonWidgetClass, wordBoundaryBox,
8476 + XmNmarginHeight, 0,
8477 + XmNlabelString, s1=XmStringCreateSimple(
8478 + "Right"),
8479 + NULL);
8480 + XmStringFree(s1);
8481 + MatchPatternDialog.wbbNoneW = XtVaCreateManagedWidget("wbbNoneW",
8482 + xmToggleButtonWidgetClass, wordBoundaryBox,
8483 + XmNmarginHeight, 0,
8484 + XmNlabelString, s1=XmStringCreateSimple(
8485 + "None"),
8486 + NULL);
8487 + XmStringFree(s1);
8489 + MatchPatternDialog.mpdStringAttributesLbl = XtVaCreateManagedWidget("mpdStringAttributesLbl", xmLabelGadgetClass,
8490 + stringPatternsForm,
8491 + XmNlabelString, s1=XmStringCreateSimple("String Attributes:"),
8492 + XmNmarginHeight, 0,
8493 + XmNalignment, XmALIGNMENT_BEGINNING,
8494 + XmNleftAttachment, XmATTACH_POSITION,
8495 + XmNleftPosition, LIST_RIGHT,
8496 + XmNtopAttachment, XmATTACH_WIDGET,
8497 + XmNtopWidget, wordBoundaryBox, NULL);
8498 + XmStringFree(s1);
8500 + stringAttributesBox = XtVaCreateManagedWidget("stringAttributesBox", xmRowColumnWidgetClass,
8501 + stringPatternsForm,
8502 + XmNorientation, XmHORIZONTAL,
8503 + XmNpacking, XmPACK_TIGHT,
8504 + XmNleftAttachment, XmATTACH_POSITION,
8505 + XmNleftPosition, LIST_RIGHT,
8506 + XmNtopAttachment, XmATTACH_WIDGET,
8507 + XmNtopWidget, MatchPatternDialog.mpdStringAttributesLbl, NULL);
8508 + MatchPatternDialog.sabRegularExpressionW = XtVaCreateManagedWidget("sabRegularExpressionW",
8509 + xmToggleButtonWidgetClass, stringAttributesBox,
8510 + XmNset, False,
8511 + XmNmarginHeight, 0,
8512 + XmNlabelString, s1=XmStringCreateSimple(
8513 + "Regular Expression"),
8514 + NULL);
8515 + XmStringFree(s1);
8516 + XtAddCallback(MatchPatternDialog.sabRegularExpressionW, XmNvalueChangedCallback,
8517 + strPatRegExpressionCB, NULL);
8518 + MatchPatternDialog.sabCaseSensitiveW = XtVaCreateManagedWidget("sabCaseSensitiveW",
8519 + xmToggleButtonWidgetClass, stringAttributesBox,
8520 + XmNset, True,
8521 + XmNmarginHeight, 0,
8522 + XmNlabelString, s1=XmStringCreateSimple(
8523 + "Case Sensitive"),
8524 + NULL);
8525 + XmStringFree(s1);
8527 + MatchPatternDialog.mpdStringPatternLbl = XtVaCreateManagedWidget("mpdStringPatternLbl", xmLabelGadgetClass,
8528 + stringPatternsForm,
8529 + XmNlabelString, s1=XmStringCreateSimple("String Pattern"),
8530 + XmNmnemonic, 'S',
8531 + XmNalignment, XmALIGNMENT_BEGINNING,
8532 + XmNleftAttachment, XmATTACH_POSITION,
8533 + XmNleftPosition, LIST_RIGHT,
8534 + XmNtopAttachment, XmATTACH_WIDGET,
8535 + XmNtopWidget, stringAttributesBox,
8536 + XmNtopOffset, BORDER,
8537 + NULL);
8538 + XmStringFree(s1);
8540 + MatchPatternDialog.mpdStringPatternW = XtVaCreateManagedWidget("mpdStringPatternW", xmTextWidgetClass,
8541 + stringPatternsForm,
8542 + XmNleftAttachment, XmATTACH_POSITION,
8543 + XmNleftPosition, LIST_RIGHT,
8544 + XmNtopAttachment, XmATTACH_WIDGET,
8545 + XmNtopWidget, MatchPatternDialog.mpdStringPatternLbl,
8546 + XmNrightAttachment, XmATTACH_FORM,
8547 + XmNrightOffset, BORDER,
8548 + NULL);
8549 + RemapDeleteKey(MatchPatternDialog.mpdStringPatternW);
8550 + XtVaSetValues(MatchPatternDialog.mpdStringPatternLbl, XmNuserData, MatchPatternDialog.mpdStringPatternW, NULL);
8552 + MatchPatternDialog.mpdSubPatNamesLbl = XtVaCreateManagedWidget("mpdSubPatNamesLbl", xmLabelGadgetClass,
8553 + stringPatternsForm,
8554 + XmNlabelString, s1=XmStringCreateSimple("Sub-Pattern Name"),
8555 + XmNmnemonic, 't',
8556 + XmNalignment, XmALIGNMENT_BEGINNING,
8557 + XmNleftAttachment, XmATTACH_POSITION,
8558 + XmNleftPosition, LIST_RIGHT,
8559 + XmNtopAttachment, XmATTACH_WIDGET,
8560 + XmNtopWidget, MatchPatternDialog.mpdStringPatternW,
8561 + XmNtopOffset, BORDER,
8562 + NULL);
8563 + XmStringFree(s1);
8565 + MatchPatternDialog.mpdSubPatNamesPulldown =
8566 + createSubPatternNameMenu(stringPatternsForm, NULL, False);
8568 + n = 0;
8569 + XtSetArg(args[n], XmNspacing, 0); n++;
8570 + XtSetArg(args[n], XmNmarginWidth, 0); n++;
8571 + XtSetArg(args[n], XmNresizeWidth, True); n++;
8572 + XtSetArg(args[n], XmNresizeHeight, True); n++;
8573 + XtSetArg(args[n], XmNnavigationType, XmTAB_GROUP); n++;
8574 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
8575 + XtSetArg(args[n], XmNtopWidget, MatchPatternDialog.mpdSubPatNamesLbl); n++;
8576 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8577 + XtSetArg(args[n], XmNleftPosition, LIST_RIGHT); n++;
8578 + XtSetArg(args[n], XmNsubMenuId, MatchPatternDialog.mpdSubPatNamesPulldown); n++;
8579 + MatchPatternDialog.mpdSubPatNamesOptMenu =
8580 + XmCreateOptionMenu(stringPatternsForm, "subPatNamesOptMenu", args, n);
8581 + XtManageChild(MatchPatternDialog.mpdSubPatNamesOptMenu);
8583 + XtVaSetValues(
8584 + MatchPatternDialog.mpdSubPatNamesLbl,
8585 + XmNuserData, XtParent(MatchPatternDialog.mpdSubPatNamesOptMenu),
8586 + NULL);
8588 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesLbl, False);
8589 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesOptMenu, False);
8591 + matchPatternsFrame = XtVaCreateManagedWidget("matchPatternsFrame", xmFrameWidgetClass,
8592 + form,
8593 + XmNleftAttachment, XmATTACH_POSITION,
8594 + XmNleftPosition, 1,
8595 + XmNtopAttachment, XmATTACH_WIDGET,
8596 + XmNtopWidget, lmForm,
8597 + XmNrightAttachment, XmATTACH_POSITION,
8598 + XmNrightPosition, 99,
8599 + XmNbottomAttachment, XmATTACH_WIDGET,
8600 + XmNbottomWidget, stringPatternsFrame,
8601 + XmNbottomOffset, BORDER, NULL);
8602 + matchPatternsForm = XtVaCreateManagedWidget("matchPatternsForm", xmFormWidgetClass,
8603 + matchPatternsFrame, NULL);
8604 + matchPatternsLbl = XtVaCreateManagedWidget("matchPatternsLbl", xmLabelGadgetClass,
8605 + matchPatternsFrame,
8606 + XmNlabelString, s1=XmStringCreateSimple("Matching Patterns"),
8607 + XmNmnemonic, 'P',
8608 + XmNmarginHeight, 0,
8609 + XmNchildType, XmFRAME_TITLE_CHILD, NULL);
8610 + XmStringFree(s1);
8612 + matchPatternTypeLbl = XtVaCreateManagedWidget("matchPatternTypeLbl", xmLabelGadgetClass,
8613 + matchPatternsForm,
8614 + XmNlabelString, s1=XmStringCreateSimple("Matching Pattern Type:"),
8615 + XmNmarginHeight, 0,
8616 + XmNalignment, XmALIGNMENT_BEGINNING,
8617 + XmNleftAttachment, XmATTACH_POSITION,
8618 + XmNleftPosition, LIST_RIGHT,
8619 + XmNtopAttachment, XmATTACH_FORM, NULL);
8620 + XmStringFree(s1);
8622 + matchPatternTypeBox = XtVaCreateManagedWidget("matchPatternTypeBox", xmRowColumnWidgetClass,
8623 + matchPatternsForm,
8624 + XmNpacking, XmPACK_COLUMN,
8625 + XmNradioBehavior, True,
8626 + XmNleftAttachment, XmATTACH_POSITION,
8627 + XmNleftPosition, LIST_RIGHT,
8628 + XmNtopAttachment, XmATTACH_WIDGET,
8629 + XmNtopWidget, matchPatternTypeLbl, NULL);
8630 + MatchPatternDialog.mptbIndividualW = XtVaCreateManagedWidget("mptbIndividualW",
8631 + xmToggleButtonWidgetClass, matchPatternTypeBox,
8632 + XmNset, True,
8633 + XmNmarginHeight, 0,
8634 + XmNlabelString, s1=XmStringCreateSimple(
8635 + "Individual"),
8636 + XmNmnemonic, 'I', NULL);
8637 + XmStringFree(s1);
8638 + XtAddCallback(MatchPatternDialog.mptbIndividualW, XmNvalueChangedCallback,
8639 + matchPatTypeCB, NULL);
8640 + MatchPatternDialog.mptbSubPatternW = XtVaCreateManagedWidget("mptbSubPatternW",
8641 + xmToggleButtonWidgetClass, matchPatternTypeBox,
8642 + XmNmarginHeight, 0,
8643 + XmNlabelString, s1=XmStringCreateSimple(
8644 + "Sub-pattern (belongs to context group)"),
8645 + XmNmnemonic, 'u', NULL);
8646 + XmStringFree(s1);
8647 + XtAddCallback(MatchPatternDialog.mptbSubPatternW, XmNvalueChangedCallback,
8648 + matchPatTypeCB, NULL);
8649 + MatchPatternDialog.mptbContextGroupW = XtVaCreateManagedWidget("mptbContextGroupW",
8650 + xmToggleButtonWidgetClass, matchPatternTypeBox,
8651 + XmNmarginHeight, 0,
8652 + XmNlabelString, s1=XmStringCreateSimple(
8653 + "Context group"),
8654 + XmNmnemonic, 'g', NULL);
8655 + XmStringFree(s1);
8656 + XtAddCallback(MatchPatternDialog.mptbContextGroupW, XmNvalueChangedCallback,
8657 + matchPatTypeCB, NULL);
8659 + MatchPatternDialog.mpdGlobalAttributesLbl = XtVaCreateManagedWidget("mpdGlobalAttributesLbl",
8660 + xmLabelGadgetClass, matchPatternsForm,
8661 + XmNlabelString, s1=XmStringCreateSimple("Global Attributes:"),
8662 + XmNmarginHeight, 0,
8663 + XmNalignment, XmALIGNMENT_BEGINNING,
8664 + XmNleftAttachment, XmATTACH_POSITION,
8665 + XmNleftPosition, LIST_RIGHT,
8666 + XmNtopAttachment, XmATTACH_WIDGET,
8667 + XmNtopOffset, BORDER,
8668 + XmNtopWidget, matchPatternTypeBox, NULL);
8669 + XmStringFree(s1);
8671 + globalAttributesBox = XtVaCreateManagedWidget("globalAttributesBox", xmRowColumnWidgetClass,
8672 + matchPatternsForm,
8673 + XmNpacking, XmPACK_COLUMN,
8674 + XmNleftAttachment, XmATTACH_POSITION,
8675 + XmNleftPosition, LIST_RIGHT,
8676 + XmNtopAttachment, XmATTACH_WIDGET,
8677 + XmNtopWidget, MatchPatternDialog.mpdGlobalAttributesLbl, NULL);
8678 + MatchPatternDialog.gabSkipBtwStartEndW = XtVaCreateManagedWidget("gabSkipBtwStartEndW",
8679 + xmToggleButtonWidgetClass, globalAttributesBox,
8680 + XmNmarginHeight, 0,
8681 + XmNlabelString, s1=XmStringCreateSimple(
8682 + "Skip content between start / end pattern"),
8683 + XmNmnemonic, 'c', NULL);
8684 + XmStringFree(s1);
8685 + MatchPatternDialog.gabFlashW = XtVaCreateManagedWidget("gabFlashW",
8686 + xmToggleButtonWidgetClass, globalAttributesBox,
8687 + XmNset, True,
8688 + XmNmarginHeight, 0,
8689 + XmNlabelString, s1=XmStringCreateSimple(
8690 + "Flash matching pattern"),
8691 + XmNmnemonic, 'l', NULL);
8692 + XmStringFree(s1);
8693 + MatchPatternDialog.gabSyntaxBasedW = XtVaCreateManagedWidget("gabSyntaxBasedW",
8694 + xmToggleButtonWidgetClass, globalAttributesBox,
8695 + XmNset, True,
8696 + XmNmarginHeight, 0,
8697 + XmNlabelString, s1=XmStringCreateSimple(
8698 + "Syntax based"),
8699 + XmNmnemonic, 'b', NULL);
8700 + XmStringFree(s1);
8702 + MatchPatternDialog.mpdMatchPatternNameLbl = XtVaCreateManagedWidget("mpdMatchPatternNameLbl", xmLabelGadgetClass,
8703 + matchPatternsForm,
8704 + XmNlabelString, s1=XmStringCreateSimple(MATCH_PAT_NAME_LBL_TXT),
8705 + XmNmnemonic, 'N',
8706 + XmNalignment, XmALIGNMENT_BEGINNING,
8707 + XmNleftAttachment, XmATTACH_POSITION,
8708 + XmNleftPosition, LIST_RIGHT,
8709 + XmNtopAttachment, XmATTACH_WIDGET,
8710 + XmNtopWidget, globalAttributesBox,
8711 + XmNtopOffset, BORDER, NULL);
8712 + XmStringFree(s1);
8714 + MatchPatternDialog.mpdMatchPatternNameW = XtVaCreateManagedWidget("mpdMatchPatternNameW", xmTextWidgetClass,
8715 + matchPatternsForm,
8716 + XmNleftAttachment, XmATTACH_POSITION,
8717 + XmNleftPosition, LIST_RIGHT,
8718 + XmNtopAttachment, XmATTACH_WIDGET,
8719 + XmNtopWidget, MatchPatternDialog.mpdMatchPatternNameLbl,
8720 + XmNrightAttachment, XmATTACH_FORM,
8721 + XmNrightOffset, BORDER,
8722 + XmNbottomAttachment, XmATTACH_FORM,
8723 + XmNbottomOffset, BORDER,
8724 + NULL);
8725 + RemapDeleteKey(MatchPatternDialog.mpdMatchPatternNameW);
8726 + XtVaSetValues(MatchPatternDialog.mpdMatchPatternNameLbl, XmNuserData, MatchPatternDialog.mpdMatchPatternNameW, NULL);
8728 + n = 0;
8729 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
8730 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8731 + XtSetArg(args[n], XmNleftPosition, 1); n++;
8732 + XtSetArg(args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
8733 + XtSetArg(args[n], XmNrightPosition, LIST_RIGHT-1); n++;
8734 + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
8736 + XtSetArg(args[n], XmNbottomOffset, BORDER); n++;
8737 + MatchPatternDialog.mpdMatchPatternNamesListW =
8738 + CreateManagedList(
8739 + matchPatternsForm, "mpdMatchPatternNamesListW",
8740 + args, n,
8741 + (void **)MatchPatternDialog.mpdTable.dmpiSequence, &MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements,
8742 + MAX_NBR_MATCH_PATTERNS, 18,
8743 + getMatchPatternDisplayedCB, NULL,
8744 + setMatchPatternDisplayedCB, NULL,
8745 + freeMatchPatternItemCB);
8746 + AddDeleteConfirmCB(MatchPatternDialog.mpdMatchPatternNamesListW, deleteMatchPatternItemCB, NULL);
8748 + XtVaSetValues(matchPatternsLbl, XmNuserData, MatchPatternDialog.mpdMatchPatternNamesListW, NULL);
8750 + /*
8751 + * set initial default button
8752 + */
8753 + XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
8754 + XtVaSetValues(form, XmNcancelButton, closeBtn, NULL);
8756 + /*
8757 + * handle mnemonic selection of buttons and focus to dialog
8758 + */
8759 + AddDialogMnemonicHandler(form, False);
8761 + /*
8762 + * fill in the dialog information for the selected language mode
8763 + */
8764 + SetLangModeMenu(MatchPatternDialog.mpdLmOptMenu, MatchPatternDialog.mpdLangModeName);
8766 + /*
8767 + * realize all of the widgets in the new dialog
8768 + */
8769 + RealizeWithoutForcingPosition(MatchPatternDialog.mpdShell);
8773 +** Modify match pattern dialog depending on showing a string pattern
8774 +** or a context group.
8776 +static void setDialogType(int dialogShowsStringPattern)
8778 + char *matchPatternNameText;
8779 + char *strPatCxtGrpListText;
8780 + XmString s1;
8781 + int regularExpression =
8782 + XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
8784 + /*
8785 + * check, if dialog mode needs to be switched
8786 + */
8787 + if (MatchPatternDialog.mpdStringPatternIsDisplayed == dialogShowsStringPattern)
8789 + return;
8792 + if (dialogShowsStringPattern)
8794 + matchPatternNameText = MATCH_PAT_NAME_LBL_TXT;
8795 + strPatCxtGrpListText = STRING_PATTERNS_LBL_TXT;
8797 + else
8799 + matchPatternNameText = "Context Group Name";
8800 + strPatCxtGrpListText = "Related Sub-Patterns";
8803 + XtSetSensitive(MatchPatternDialog.mpdGlobalAttributesLbl, dialogShowsStringPattern);
8804 + XtSetSensitive(MatchPatternDialog.gabSkipBtwStartEndW, dialogShowsStringPattern);
8805 + XtSetSensitive(MatchPatternDialog.gabFlashW, dialogShowsStringPattern);
8806 + XtSetSensitive(MatchPatternDialog.gabSyntaxBasedW, dialogShowsStringPattern);
8808 + XtSetSensitive(MatchPatternDialog.mpdStringPatternTypeLbl, dialogShowsStringPattern);
8809 + XtSetSensitive(MatchPatternDialog.sptStartW, dialogShowsStringPattern);
8810 + XtSetSensitive(MatchPatternDialog.sptMiddleW, dialogShowsStringPattern);
8811 + XtSetSensitive(MatchPatternDialog.sptEndW, dialogShowsStringPattern);
8813 + setSensitiveWordBoundaryBox( dialogShowsStringPattern && !regularExpression );
8815 + XtSetSensitive(MatchPatternDialog.mpdStringAttributesLbl, dialogShowsStringPattern);
8816 + XtSetSensitive(MatchPatternDialog.sabCaseSensitiveW, dialogShowsStringPattern);
8817 + XtSetSensitive(MatchPatternDialog.sabRegularExpressionW, dialogShowsStringPattern);
8819 + XtSetSensitive(MatchPatternDialog.mpdStringPatternLbl, dialogShowsStringPattern);
8820 + XtSetSensitive(MatchPatternDialog.mpdStringPatternW, dialogShowsStringPattern);
8822 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesLbl, !dialogShowsStringPattern);
8823 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesOptMenu, !dialogShowsStringPattern);
8825 + XtVaSetValues(
8826 + MatchPatternDialog.mpdMatchPatternNameLbl,
8827 + XmNlabelString, s1=XmStringCreateSimple(matchPatternNameText),
8828 + NULL);
8829 + XmStringFree(s1);
8831 + XtVaSetValues(
8832 + MatchPatternDialog.mpdStringPatternsLbl,
8833 + XmNlabelString, s1=XmStringCreateSimple(strPatCxtGrpListText),
8834 + NULL);
8835 + XmStringFree(s1);
8837 + MatchPatternDialog.mpdStringPatternIsDisplayed = dialogShowsStringPattern;
8840 +static void setSensitiveWordBoundaryBox(int enable)
8842 + XtSetSensitive(MatchPatternDialog.mpdWordBoundaryLbl, enable);
8843 + XtSetSensitive(MatchPatternDialog.wbbBothW , enable);
8844 + XtSetSensitive(MatchPatternDialog.wbbLeftW , enable);
8845 + XtSetSensitive(MatchPatternDialog.wbbRightW, enable);
8846 + XtSetSensitive(MatchPatternDialog.wbbNoneW , enable);
8849 +static void matchPatternLangModeCB(Widget w, XtPointer clientData, XtPointer callData)
8851 + char *modeName;
8852 + StringMatchTable *oldTable, *newTable;
8853 + StringMatchTable emptyTable = {"", NULL, NULL, NULL, NULL, 0, NULL, 0, NULL};
8854 + StringMatchTable *table;
8855 + DMPTranslationResult translResult;
8856 + int resp;
8858 + /*
8859 + * Get the newly selected mode name. If it's the same, do nothing
8860 + */
8861 + XtVaGetValues(w, XmNuserData, &modeName, NULL);
8862 + if (!strcmp(modeName, MatchPatternDialog.mpdLangModeName))
8863 + return;
8865 + /*
8866 + * Look up the original version of the patterns being edited
8867 + */
8868 + oldTable = (StringMatchTable *)FindStringMatchTable(MatchPatternDialog.mpdLangModeName);
8869 + if (oldTable == NULL)
8870 + oldTable = &emptyTable;
8872 + /*
8873 + * Get the current information displayed by the dialog. If it's bad,
8874 + * give the user the chance to throw it out or go back and fix it. If
8875 + * it has changed, give the user the chance to apply discard or cancel.
8876 + */
8877 + newTable = getDialogStringMatchTable(&translResult);
8879 + if (translResult == DMPTR_EMPTY)
8881 + newTable = &emptyTable;
8884 + if (newTable == NULL)
8886 + if (DialogF(
8887 + DF_WARN, MatchPatternDialog.mpdShell, 2,
8888 + "Incomplete Matching Patterns for Language Mode",
8889 + "Discard incomplete entry for language mode '%s'?",
8890 + "Keep", "Discard",
8891 + MatchPatternDialog.mpdLangModeName) == 1)
8893 + SetLangModeMenu(
8894 + MatchPatternDialog.mpdLmOptMenu,
8895 + MatchPatternDialog.mpdLangModeName);
8897 + return;
8900 + else if (stringMatchTableDiffer(oldTable, newTable))
8902 + if (newTable == &emptyTable)
8903 + newTable = NULL;
8905 + resp =
8906 + DialogF(
8907 + DF_WARN, MatchPatternDialog.mpdShell, 3,
8908 + "Change Language Mode",
8909 + "Apply changes for language mode '%s'?",
8910 + "Apply Changes", "Discard Changes", "Cancel",
8911 + MatchPatternDialog.mpdLangModeName);
8913 + if (resp == 3)
8915 + SetLangModeMenu(
8916 + MatchPatternDialog.mpdLmOptMenu,
8917 + MatchPatternDialog.mpdLangModeName);
8919 + freeStringMatchTable( newTable );
8921 + return;
8923 + else if (resp == 1)
8925 + updateStringMatchTable( newTable );
8927 + /*
8928 + * Don't free the new table due to it's stored in MatchTables now
8929 + */
8930 + newTable = NULL;
8934 + if (newTable != NULL && newTable != &emptyTable)
8935 + freeStringMatchTable(newTable);
8937 + /*
8938 + * Free the old dialog information
8939 + */
8940 + freeVariableDialogData(DISCARD_LANGUAGE_MODE);
8942 + /*
8943 + * Fill the dialog with the new language mode information
8944 + */
8945 + MatchPatternDialog.mpdLangModeName = XtNewString(modeName);
8947 + /*
8948 + * Find the associated matching pattern table to edit
8949 + */
8950 + table = (StringMatchTable *)FindStringMatchTable(MatchPatternDialog.mpdLangModeName);
8952 + /*
8953 + * Copy the list of patterns to one that the user can freely edit
8954 + */
8955 + copyStringMatchTableForDialog( table, &MatchPatternDialog.mpdTable );
8957 + /*
8958 + * Update dialog fields
8959 + */
8960 + ChangeManagedListData(MatchPatternDialog.mpdMatchPatternNamesListW);
8961 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
8964 +static void pmLanguageModeDialogCB(Widget w, XtPointer clientData, XtPointer callData)
8966 + EditLanguageModes();
8970 +** If a matching pattern dialog is up, ask to have the option menu for
8971 +** chosing language mode updated (via a call to CreateLanguageModeMenu)
8973 +void UpdateLanguageModeMenuMatchPattern(void)
8975 + Widget oldMenu;
8977 + if (MatchPatternDialog.mpdShell == NULL)
8978 + return;
8980 + oldMenu = MatchPatternDialog.mpdLmPulldown;
8981 + /*
8982 + * don't include "PLAIN" (4th parameter) in LM menu
8983 + */
8984 + MatchPatternDialog.mpdLmPulldown = CreateLanguageModeMenu(
8985 + XtParent(XtParent(oldMenu)), matchPatternLangModeCB, NULL, False);
8986 + XtVaSetValues(XmOptionButtonGadget(MatchPatternDialog.mpdLmOptMenu),
8987 + XmNsubMenuId, MatchPatternDialog.mpdLmPulldown, NULL);
8988 + SetLangModeMenu(MatchPatternDialog.mpdLmOptMenu, MatchPatternDialog.mpdLangModeName);
8990 + XtDestroyWidget(oldMenu);
8993 +static void *getMatchPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
8994 + void *cbArg)
8996 + DialogMatchPatternSequenceElement *newSeq;
8998 + /*
8999 + * If the dialog is currently displaying the "new" entry and the
9000 + * fields are empty, that's just fine
9001 + */
9002 + if (oldItem == NULL && matchPatternDialogEmpty())
9003 + return NULL;
9005 + /*
9006 + * Read string patterns / sub-pattern names area first
9007 + */
9008 + UpdateManagedList(MatchPatternDialog.mpdStringPatternsListW, True);
9010 + /*
9011 + * If there are no problems reading the data, just return it
9012 + */
9013 + newSeq = readMatchPatternFields(True);
9014 + if (newSeq != NULL)
9015 + return (void *)newSeq;
9017 + /*
9018 + * If there are problems, and the user didn't ask for the fields to be
9019 + * read, give more warning
9020 + */
9021 + if (!explicitRequest)
9023 + if (DialogF(
9024 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9025 + "Discard Matching Pattern Entry",
9026 + "Discard incomplete entry\nfor current matching pattern?",
9027 + "Keep", "Discard") == 2)
9029 + return oldItem == NULL
9030 + ? NULL
9031 + : (void *)copyDialogSequenceElement(
9032 + (DialogMatchPatternSequenceElement *)oldItem);
9036 + /*
9037 + * read data again without "silent" mode to display warning
9038 + */
9039 + newSeq = readMatchPatternFields(False);
9040 + *abort = True;
9042 + return NULL;
9045 +static void setMatchPatternDisplayedCB(void *item, void *cbArg)
9047 + DialogMatchPatternSequenceElement *seqElement;
9048 + DialogMatchPatternTableElement *element;
9049 + DialogMatchPatternGroupElement *group;
9050 + int isGroup;
9052 + seqElement = (DialogMatchPatternSequenceElement *)item;
9054 + MatchPatternDialog.currentDmptSeqElement = seqElement;
9056 + if (item == NULL)
9058 + MatchPatternDialog.currentDmptElement = NULL;
9059 + MatchPatternDialog.currentDmptGroup = NULL;
9061 + XmTextSetString(MatchPatternDialog.mpdMatchPatternNameW, "");
9062 + RadioButtonChangeState(MatchPatternDialog.mptbIndividualW, True, True);
9063 + RadioButtonChangeState(MatchPatternDialog.gabSkipBtwStartEndW, False, False);
9064 + RadioButtonChangeState(MatchPatternDialog.gabFlashW, True, False);
9065 + RadioButtonChangeState(MatchPatternDialog.gabSyntaxBasedW, True, False);
9067 + freeDialogStringPatterns(
9068 + &MatchPatternDialog.currentStringPatterns);
9070 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9072 + setDialogType( STRING_PATTERN_DIALOG );
9074 + else
9076 + isGroup = (seqElement->dmpseType == MPT_GROUP);
9078 + XmTextSetString(MatchPatternDialog.mpdMatchPatternNameW, seqElement->dmpseName);
9080 + if (seqElement->dmpseType == MPT_INDIVIDUAL)
9081 + RadioButtonChangeState(MatchPatternDialog.mptbIndividualW, True, True);
9082 + else if (seqElement->dmpseType == MPT_SUB)
9083 + RadioButtonChangeState(MatchPatternDialog.mptbSubPatternW, True, True);
9084 + else
9085 + RadioButtonChangeState(MatchPatternDialog.mptbContextGroupW, True, True);
9087 + freeDialogStringPatterns(
9088 + &MatchPatternDialog.currentStringPatterns);
9090 + if (isGroup)
9092 + group = (DialogMatchPatternGroupElement *)seqElement->dmpsePtr;
9093 + MatchPatternDialog.currentDmptElement = NULL;
9094 + MatchPatternDialog.currentDmptGroup = group;
9096 + copyDialogPatternNamesFromGroup(
9097 + group,
9098 + &MatchPatternDialog.currentStringPatterns);
9100 + else
9102 + element = (DialogMatchPatternTableElement *)seqElement->dmpsePtr;
9103 + MatchPatternDialog.currentDmptElement = element;
9104 + MatchPatternDialog.currentDmptGroup = NULL;
9106 + RadioButtonChangeState(
9107 + MatchPatternDialog.gabSkipBtwStartEndW,
9108 + element->dmpteSkipBtwnStartEnd,
9109 + False);
9110 + RadioButtonChangeState(
9111 + MatchPatternDialog.gabFlashW,
9112 + element->dmpteFlash,
9113 + False);
9114 + RadioButtonChangeState(
9115 + MatchPatternDialog.gabSyntaxBasedW,
9116 + !element->dmpteIgnoreHighLightInfo,
9117 + False);
9119 + copyDialogStringPatternsFromTable(
9120 + element,
9121 + &MatchPatternDialog.currentStringPatterns);
9124 + setDialogType( !isGroup );
9126 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9130 +static void freeMatchPatternItemCB(void *item)
9132 + freeDialogSequenceElement((DialogMatchPatternSequenceElement *)item);
9136 +** Use "delete confirm" to delete matching pattern name from
9137 +** any group of this matching pattern set, in case of sub-pattern.
9138 +** Always confirm the delete.
9140 +static int deleteMatchPatternItemCB(int itemIndex, void *cbArg)
9142 + DialogMatchPatternSequenceElement *seqElement;
9144 + seqElement = MatchPatternDialog.mpdTable.dmpiSequence[itemIndex];
9146 + if (seqElement->dmpseType == MPT_SUB)
9148 + removeMatchPatternFromAllGroups( seqElement->dmpseName );
9151 + return True;
9154 +static void *getStringPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
9155 + void *cbArg)
9157 + DialogStringPatternElement *newPat;
9158 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
9160 + /*
9161 + * If the string pattern frame is currently displaying the "new" entry and the
9162 + * fields are empty, that's just fine
9163 + */
9164 + if (oldItem == NULL && stringPatternFieldsEmpty(isRelatedToGroup))
9165 + return NULL;
9167 + /*
9168 + * If there are no problems reading the data, just return it
9169 + */
9170 + newPat = readStringPatternFrameFields(True);
9171 + if (newPat != NULL)
9172 + return (void *)newPat;
9174 + /*
9175 + * If there are problems, and the user didn't ask for the fields to be
9176 + * read, give more warning
9177 + */
9179 + if (!explicitRequest)
9181 + if (DialogF(
9182 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9183 + "Discard String Pattern Entry",
9184 + "Discard incomplete entry\nfor current string pattern?",
9185 + "Keep", "Discard") == 2)
9187 + return oldItem == NULL
9188 + ? NULL
9189 + : (void *)copyDialogStringPatternElement(
9190 + (DialogStringPatternElement *)oldItem);
9194 + /*
9195 + * read data again without "silent" mode to display warning
9196 + */
9197 + newPat = readStringPatternFrameFields(False);
9198 + *abort = True;
9200 + return NULL;
9203 +static void setStringPatternDisplayedCB(void *item, void *cbArg)
9205 + DialogStringPatternElement *element = (DialogStringPatternElement *)item;
9206 + PatternElementKind peKind;
9207 + PatternWordBoundary wordBoundary;
9208 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
9210 + if (item == NULL)
9212 + if (isRelatedToGroup)
9214 + updateSubPatternNameMenu(NULL, False);
9216 + else
9218 + XmTextSetString(MatchPatternDialog.mpdStringPatternW, "");
9220 + setSensitiveWordBoundaryBox( True );
9222 + RadioButtonChangeState(MatchPatternDialog.wbbBothW, True, True);
9224 + /*
9225 + * type of "new" string pattern:
9226 + * preset "start", if no string pattern exists at all;
9227 + * else select "end"
9228 + */
9229 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0)
9230 + RadioButtonChangeState(MatchPatternDialog.sptStartW, True, True);
9231 + else
9232 + RadioButtonChangeState(MatchPatternDialog.sptEndW, True, True);
9234 + RadioButtonChangeState(MatchPatternDialog.sabCaseSensitiveW, True, False);
9235 + RadioButtonChangeState(MatchPatternDialog.sabRegularExpressionW, False, False);
9238 + else
9240 + if (isRelatedToGroup)
9242 + updateSubPatternNameMenu(element->dspeText, False);
9244 + else
9246 + XmTextSetString(MatchPatternDialog.mpdStringPatternW, element->dspeText);
9248 + peKind = element->dspeKind;
9249 + wordBoundary = element->dspeWordBoundary;
9251 + if (peKind == PEK_START)
9252 + RadioButtonChangeState(MatchPatternDialog.sptStartW, True, True);
9253 + else if (peKind == PEK_MIDDLE)
9254 + RadioButtonChangeState(MatchPatternDialog.sptMiddleW, True, True);
9255 + else
9256 + RadioButtonChangeState(MatchPatternDialog.sptEndW, True, True);
9258 + if (wordBoundary == PWB_BOTH)
9259 + RadioButtonChangeState(MatchPatternDialog.wbbBothW, True, True);
9260 + else if (wordBoundary == PWB_LEFT)
9261 + RadioButtonChangeState(MatchPatternDialog.wbbLeftW, True, True);
9262 + else if (wordBoundary == PWB_RIGHT)
9263 + RadioButtonChangeState(MatchPatternDialog.wbbRightW, True, True);
9264 + else
9265 + RadioButtonChangeState(MatchPatternDialog.wbbNoneW, True, True);
9267 + RadioButtonChangeState(
9268 + MatchPatternDialog.sabCaseSensitiveW,
9269 + !element->dspeCaseInsensitive,
9270 + False);
9272 + RadioButtonChangeState(
9273 + MatchPatternDialog.sabRegularExpressionW,
9274 + element->dspeRegularExpression,
9275 + False);
9277 + setSensitiveWordBoundaryBox( !element->dspeRegularExpression );
9282 +static void freeStringPatternItemCB(void *item)
9284 + DialogStringPatternElement *patElement;
9286 + patElement = (DialogStringPatternElement *)item;
9288 + freeDialogStringPatternElement(patElement);
9291 +static void destroyCB(Widget w, XtPointer clientData, XtPointer callData)
9293 + freeVariableDialogData(DISCARD_LANGUAGE_MODE);
9295 + MatchPatternDialog.mpdShell = NULL;
9298 +static void okCB(Widget w, XtPointer clientData, XtPointer callData)
9300 + /*
9301 + * change the matching pattern
9302 + */
9303 + if (!getAndUpdateStringMatchTable())
9304 + return;
9306 + /*
9307 + * pop down and destroy the dialog
9308 + */
9309 + XtDestroyWidget(MatchPatternDialog.mpdShell);
9312 +static void applyCB(Widget w, XtPointer clientData, XtPointer callData)
9314 + /*
9315 + * change the matching pattern
9316 + */
9317 + getAndUpdateStringMatchTable();
9320 +static void checkCB(Widget w, XtPointer clientData, XtPointer callData)
9322 + StringMatchTable *newTable;
9323 + DMPTranslationResult translResult;
9325 + /*
9326 + * Get the current information displayed by the dialog.
9327 + * If a new table is available, then the test is passed successfully.
9328 + */
9329 + newTable = getDialogStringMatchTable(&translResult);
9331 + if (newTable != NULL)
9333 + DialogF(
9334 + DF_INF, MatchPatternDialog.mpdShell, 1,
9335 + "Matching Patterns Checked",
9336 + "Matching Patterns checked without error",
9337 + "OK");
9339 + freeStringMatchTable(newTable);
9343 +static void restoreCB(Widget w, XtPointer clientData, XtPointer callData)
9345 + StringMatchTable *defaultTable;
9347 + defaultTable = readDefaultStringMatchTable(MatchPatternDialog.mpdLangModeName);
9349 + if (defaultTable == NULL)
9351 + DialogF(
9352 + DF_WARN, MatchPatternDialog.mpdShell, 1,
9353 + "No Default Matching Pattern",
9354 + "There is no default matching pattern set\nfor language mode %s",
9355 + "OK",
9356 + MatchPatternDialog.mpdLangModeName);
9358 + return;
9361 + if (DialogF(
9362 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9363 + "Discard Changes",
9364 + "Are you sure you want to discard\n"
9365 + "all changes to matching patterns\n"
9366 + "for language mode %s?",
9367 + "Discard", "Cancel",
9368 + MatchPatternDialog.mpdLangModeName) == 2)
9370 + freeStringMatchTable(defaultTable);
9372 + return;
9375 + /*
9376 + * if a stored version of the matching pattern set exists, replace it.
9377 + * if it doesn't, add a new one.
9378 + */
9379 + updateStringMatchTable( defaultTable );
9381 + /*
9382 + * free the old dialog information
9383 + */
9384 + freeVariableDialogData(KEEP_LANGUAGE_MODE);
9386 + /*
9387 + * update the dialog
9388 + */
9389 + copyStringMatchTableForDialog( defaultTable, &MatchPatternDialog.mpdTable );
9391 + ChangeManagedListData(MatchPatternDialog.mpdMatchPatternNamesListW);
9392 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9395 +static void deleteCB(Widget w, XtPointer clientData, XtPointer callData)
9397 + if (DialogF(
9398 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9399 + "Delete Matching Patterns",
9400 + "Are you sure you want to delete\n"
9401 + "all matching patterns for\n"
9402 + "language mode %s?",
9403 + "Yes, Delete", "Cancel",
9404 + MatchPatternDialog.mpdLangModeName) == 2)
9406 + return;
9409 + /*
9410 + * if a stored version of the matching pattern exists, delete it from the list
9411 + */
9412 + DeleteStringMatchTable(MatchPatternDialog.mpdLangModeName);
9414 + /*
9415 + * free the old dialog information
9416 + */
9417 + freeVariableDialogData(KEEP_LANGUAGE_MODE);
9419 + /*
9420 + * clear out the dialog
9421 + */
9422 + ChangeManagedListData(MatchPatternDialog.mpdMatchPatternNamesListW);
9423 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9426 +static void closeCB(Widget w, XtPointer clientData, XtPointer callData)
9428 + /*
9429 + * pop down and destroy the dialog
9430 + */
9431 + XtDestroyWidget(MatchPatternDialog.mpdShell);
9434 +static void helpCB(Widget w, XtPointer clientData, XtPointer callData)
9437 + Help(HELP_MATCHING_PATTERNS);
9441 +static void strPatRegExpressionCB(Widget w, XtPointer clientData, XtPointer callData)
9443 + int regularExpression =
9444 + XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
9446 + setSensitiveWordBoundaryBox( !regularExpression );
9448 + if (regularExpression)
9449 + RadioButtonChangeState(MatchPatternDialog.sabCaseSensitiveW, True, False);
9452 +static void matchPatTypeCB(Widget w, XtPointer clientData, XtPointer callData)
9454 + if (MatchPatternDialog.currentDmptSeqElement != NULL)
9456 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW))
9458 + if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_SUB)
9460 + changeExistingSubPattern("Change to Context Group");
9463 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW) &&
9464 + MatchPatternDialog.currentDmptSeqElement->dmpseType != MPT_GROUP)
9466 + changeStringPatternToGroup();
9469 + else if (XmToggleButtonGetState(MatchPatternDialog.mptbIndividualW))
9471 + if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_SUB)
9473 + changeExistingSubPattern("Change to Individual Matching Pattern");
9475 + else if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_GROUP)
9477 + changeGroupToStringPattern("Change to Individual Matching Pattern");
9480 + else if (XmToggleButtonGetState(MatchPatternDialog.mptbSubPatternW))
9482 + if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_GROUP)
9484 + changeGroupToStringPattern("Change to Sub-Matching Pattern");
9489 + /*
9490 + * if context group button is (still) selected, then update labels etc.
9491 + */
9492 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW))
9494 + setDialogType(CONTEXT_GROUP_DIALOG);
9496 + else
9498 + setDialogType(STRING_PATTERN_DIALOG);
9501 + /*
9502 + * if a "new" entry is selected in matching patterns names list, then provide a
9503 + * list of all sub-pattern names
9504 + */
9505 + if (MatchPatternDialog.currentDmptSeqElement == NULL)
9507 + updateSubPatternNameMenu(NULL, True);
9511 +static void changeExistingSubPattern(
9512 + char *warnTitle)
9514 + DialogMatchPatternGroupElement *group;
9515 + int resp;
9517 + group =
9518 + getDialogGroupUsingMatchPattern(
9519 + MatchPatternDialog.currentDmptElement->dmpteName );
9521 + while ( group != NULL )
9523 + resp =
9524 + DialogF(
9525 + DF_WARN, MatchPatternDialog.mpdShell, 3,
9526 + warnTitle,
9527 + "Sub-pattern '%s' is used at least\n"
9528 + "by context group '%s'.\n\n"
9529 + "Remove this sub-pattern from this resp. all context group(s) ?",
9530 + "No, Keep", "Yes, Remove", "Yes, Remove All",
9531 + MatchPatternDialog.currentDmptElement->dmpteName,
9532 + group->dmpgeName);
9534 + if (resp == 1)
9536 + RadioButtonChangeState(MatchPatternDialog.mptbSubPatternW, True, True);
9538 + return;
9540 + else if (resp == 2)
9542 + removeMatchPatternFromGroup(
9543 + MatchPatternDialog.currentDmptElement->dmpteName,
9544 + group);
9546 + /*
9547 + * look for evtl. next context group holding this matching pattern
9548 + */
9549 + group =
9550 + getDialogGroupUsingMatchPattern(
9551 + MatchPatternDialog.currentDmptElement->dmpteName );
9553 + else
9555 + /*
9556 + * remove this matching pattern form all context groups
9557 + */
9558 + removeMatchPatternFromAllGroups(
9559 + MatchPatternDialog.currentDmptElement->dmpteName);
9561 + return;
9566 +static void changeStringPatternToGroup(void)
9568 + int resp;
9569 + int isSubPattern;
9571 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns != 0)
9573 + resp =
9574 + DialogF(
9575 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9576 + "Change to Context Group",
9577 + "All string patterns of '%s'\n"
9578 + "need to be discarded.\n\n"
9579 + "Discard related string patterns ?",
9580 + "No, Keep", "Yes, Discard",
9581 + MatchPatternDialog.currentDmptElement->dmpteName);
9583 + if (resp == 1)
9585 + isSubPattern = (MatchPatternDialog.currentDmptElement->dmpteType == MPT_SUB);
9587 + if (isSubPattern)
9588 + RadioButtonChangeState(MatchPatternDialog.mptbSubPatternW, True, True);
9589 + else
9590 + RadioButtonChangeState(MatchPatternDialog.mptbIndividualW, True, True);
9592 + return;
9595 + /*
9596 + * remove string patterns & update dialog fields
9597 + */
9598 + freeDialogStringPatterns(&MatchPatternDialog.currentStringPatterns);
9600 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9603 + /*
9604 + * invalidate this sub-/individual pattern
9605 + */
9606 + MatchPatternDialog.currentDmptSeqElement->dmpseValid = False;
9608 + /*
9609 + * update sub-pattern menu due to change to context group
9610 + */
9611 + updateSubPatternNameMenu(NULL, True);
9614 +static void changeGroupToStringPattern(
9615 + char *warnTitle)
9617 + int resp;
9619 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0)
9620 + return;
9622 + resp =
9623 + DialogF(
9624 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9625 + warnTitle,
9626 + "Content of context group '%s'\n"
9627 + "needs to be discarded.\n\n"
9628 + "Discard content ?",
9629 + "No, Keep", "Yes, Discard",
9630 + MatchPatternDialog.currentDmptGroup->dmpgeName);
9632 + if (resp == 1)
9634 + RadioButtonChangeState(MatchPatternDialog.mptbContextGroupW, True, True);
9636 + else
9638 + /*
9639 + * remove string patterns & update dialog fields
9640 + */
9641 + freeDialogStringPatterns(&MatchPatternDialog.currentStringPatterns);
9643 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9648 +** Create a pulldown menu pane with the names of the sub-patterns of
9649 +** the current matching pattern set.
9651 +static Widget createSubPatternNameMenu(
9652 + Widget parent,
9653 + char *currentSubPatName,
9654 + int allSubPatterns)
9656 + NameList nameList;
9657 + Widget menu;
9658 + int i;
9660 + setupSubPatternNameList(currentSubPatName, allSubPatterns, &nameList);
9662 + menu = CreatePulldownMenu(parent, "subPatternNames", NULL, 0);
9664 + for (i=0; i<nameList.nlNumber; i++)
9666 + createSubPatNameMenuEntry(menu, nameList.nlId[i]);
9669 + return menu;
9672 +static void setupSubPatternNameList(
9673 + char *currentSubPatName,
9674 + int allSubPatterns,
9675 + NameList *nameList)
9677 + int n = 0;
9678 + int i;
9679 + DialogMatchPatternSequenceElement *seq;
9680 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
9682 + if (isRelatedToGroup || allSubPatterns)
9684 + /*
9685 + * add "none selected" (default) item
9686 + */
9687 + nameList->nlId[n ++] = SPNM_NONE_SELECTED;
9689 + /*
9690 + * add one item for each (not assigned) sub-pattern name
9691 + */
9692 + for (i=0; i<MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i++)
9694 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
9696 + if (seq->dmpseType == MPT_SUB &&
9697 + seq->dmpseValid &&
9698 + (allSubPatterns ||
9699 + (!isSubPatternNameInCurStrPat(seq->dmpseName) ||
9700 + (currentSubPatName != NULL &&
9701 + (strcmp(seq->dmpseName, currentSubPatName) == 0))) ))
9703 + nameList->nlId[n ++] = seq->dmpseName;
9707 + else
9709 + nameList->nlId[n ++] = "none available ";
9712 + nameList->nlNumber = n;
9716 +** Create a menu entry with the names of one sub-pattern.
9717 +** XmNuserData of this item contains the sub-pattern name.
9719 +static void createSubPatNameMenuEntry(
9720 + Widget menu,
9721 + char *subPatName)
9723 + Widget btn;
9724 + XmString s1;
9726 + btn = XtVaCreateManagedWidget("subPattern", xmPushButtonGadgetClass,
9727 + menu,
9728 + XmNlabelString, s1=XmStringCreateSimple(subPatName),
9729 + XmNmarginHeight, 0,
9730 + XmNuserData, (void *)subPatName, NULL);
9731 + XmStringFree(s1);
9735 +** Set the sub-patterns menu to show a particular sub-pattern name
9737 +static void setSubPatternNameMenu(
9738 + const char *subPatName)
9740 + int i;
9741 + Cardinal nItems;
9742 + WidgetList items;
9743 + Widget pulldown, selectedItem;
9744 + char *itemName;
9746 + XtVaGetValues(MatchPatternDialog.mpdSubPatNamesOptMenu, XmNsubMenuId, &pulldown, NULL);
9747 + XtVaGetValues(pulldown, XmNchildren, &items, XmNnumChildren, &nItems, NULL);
9749 + if (nItems == 0)
9750 + return;
9752 + selectedItem = items[0];
9754 + /*
9755 + * if no subPatName is given, then select first item of option menu
9756 + */
9757 + if (subPatName != NULL)
9759 + for (i=0; i<(int)nItems; i++)
9761 + if (items[i] != NULL && !items[i]->core.being_destroyed)
9763 + XtVaGetValues(items[i], XmNuserData, &itemName, NULL);
9764 + if (!strcmp(itemName, subPatName))
9766 + selectedItem = items[i];
9767 + break;
9773 + XtVaSetValues(MatchPatternDialog.mpdSubPatNamesOptMenu, XmNmenuHistory, selectedItem, NULL);
9777 +** Update sub-pattern names menu, e.g. when a new sub-pattern is defined
9779 +static void updateSubPatternNameMenu(
9780 + char *currentSubPatName,
9781 + int allSubPatterns)
9783 + NameList nameList;
9784 + WidgetList items;
9785 + Cardinal nItems;
9786 + int n;
9787 + XmString st1;
9789 + setupSubPatternNameList(currentSubPatName, allSubPatterns, &nameList);
9791 + /*
9792 + * Go thru all of the items in the sub-pattern names menu
9793 + * and rename them to match the current sub-patterns.
9794 + * Delete any extras.
9795 + */
9796 + XtVaGetValues(
9797 + MatchPatternDialog.mpdSubPatNamesPulldown,
9798 + XmNchildren, &items,
9799 + XmNnumChildren, &nItems,
9800 + NULL);
9802 + for (n=0; n<(int)nItems; n++)
9804 + if (n >= nameList.nlNumber)
9806 + /*
9807 + * unmanaging before destroying stops parent from displaying
9808 + */
9809 + XtUnmanageChild(items[n]);
9810 + XtDestroyWidget(items[n]);
9812 + else
9814 + if (items[n] == NULL || items[n]->core.being_destroyed)
9816 + /*
9817 + * create a new entry (widget) if this one is not existing or
9818 + * if it is marked as to be destroyed
9819 + */
9820 + createSubPatNameMenuEntry(
9821 + MatchPatternDialog.mpdSubPatNamesPulldown, nameList.nlId[n]);
9823 + else
9825 + XtVaSetValues(
9826 + items[n],
9827 + XmNlabelString, st1=XmStringCreateSimple(nameList.nlId[n]),
9828 + XmNuserData, (void *)nameList.nlId[n],
9829 + NULL);
9831 + XmStringFree(st1);
9836 + /*
9837 + * add new items for remaining sub-patterns names
9838 + */
9839 + for (n=(int)nItems; n<nameList.nlNumber; n++)
9841 + createSubPatNameMenuEntry(
9842 + MatchPatternDialog.mpdSubPatNamesPulldown, nameList.nlId[n]);
9845 + /*
9846 + * select entry shown in sub-pattern name option menu
9847 + */
9848 + setSubPatternNameMenu(currentSubPatName);
9851 +static char *getSelectedSubPatternName(void)
9853 + Widget selectedItem;
9854 + char *itemName;
9856 + XtVaGetValues(MatchPatternDialog.mpdSubPatNamesOptMenu, XmNmenuHistory, &selectedItem, NULL);
9857 + XtVaGetValues(selectedItem, XmNuserData, &itemName, NULL);
9859 + return itemName;
9862 +static int isSubPatternNameInCurStrPat(
9863 + char *subPatName)
9865 + int i;
9866 + DialogStringPatterns *curPatNames = &MatchPatternDialog.currentStringPatterns;
9868 + for (i=0; i<curPatNames->dspNumberOfPatterns; i++)
9870 + if (strcmp(curPatNames->dspElements[i]->dspeText, subPatName) == 0)
9871 + return True;
9874 + return False;
9878 +** Read the matching pattern fields of the matching pattern dialog and produce an
9879 +** allocated DialogMatchPatternSequenceElement structure reflecting the contents.
9880 +** Pop up dialogs telling the user what's wrong (Passing "silent" as True,
9881 +** suppresses these dialogs).
9882 +** Returns NULL on error.
9884 +static DialogMatchPatternSequenceElement *readMatchPatternFields(int silent)
9886 + int isGroup;
9887 + char *name;
9888 + char *nameLabel;
9889 + char *nameTitle;
9890 + char *contentTitle;
9891 + char *contentWarningText;
9892 + DialogMatchPatternSequenceElement *newSeq;
9893 + DialogMatchPatternTableElement *newElement;
9894 + DialogMatchPatternGroupElement *newGroup;
9896 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW))
9898 + nameLabel = "context group name";
9899 + nameTitle = "Context Group Name";
9900 + contentTitle = "Context Group Content";
9901 + contentWarningText = "Please assign min. 1\nsub-pattern";
9902 + isGroup = True;
9904 + else
9906 + nameLabel = "matching pattern name";
9907 + nameTitle = "Matching Pattern Name";
9908 + contentTitle = "Matching Pattern Content";
9909 + contentWarningText = "Please specify min. 1\nstring pattern";
9910 + isGroup = False;
9913 + name =
9914 + ReadSymbolicFieldTextWidget(
9915 + MatchPatternDialog.mpdMatchPatternNameW,
9916 + nameLabel,
9917 + silent);
9919 + if (name == NULL)
9921 + return NULL;
9923 + else if (*name == '\0')
9925 + if (!silent)
9927 + DialogF(
9928 + DF_WARN, MatchPatternDialog.mpdShell, 1,
9929 + nameTitle,
9930 + "Please specify a valid name",
9931 + "OK");
9932 + XmProcessTraversal(MatchPatternDialog.mpdMatchPatternNameW, XmTRAVERSE_CURRENT);
9934 + XtFree(name);
9935 + return NULL;
9938 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0)
9940 + if (!silent)
9942 + DialogF(
9943 + DF_WARN, MatchPatternDialog.mpdShell, 1,
9944 + contentTitle,
9945 + contentWarningText,
9946 + "OK");
9948 + XtFree(name);
9949 + return NULL;
9951 + else
9953 + if (!isGroup &&
9954 + !isStartPatternElementAvailable(&MatchPatternDialog.currentStringPatterns))
9956 + if (!silent)
9958 + DialogF(
9959 + DF_WARN, MatchPatternDialog.mpdShell, 1,
9960 + contentTitle,
9961 + "Please specify min. 1 string pattern\nof type 'start'",
9962 + "OK");
9964 + XtFree(name);
9965 + return NULL;
9969 + if (MatchPatternDialog.currentDmptElement != NULL &&
9970 + MatchPatternDialog.currentDmptElement->dmpteType == MPT_SUB &&
9971 + strcmp(MatchPatternDialog.currentDmptElement->dmpteName, name) != 0)
9973 + renameMatchPatternInAllGroups(
9974 + MatchPatternDialog.currentDmptElement->dmpteName,
9975 + name);
9978 + newSeq =
9979 + (DialogMatchPatternSequenceElement *)XtMalloc(sizeof(DialogMatchPatternSequenceElement));
9981 + newSeq->dmpseName = name;
9982 + newSeq->dmpseValid = True;
9984 + if (isGroup)
9986 + newSeq->dmpseType = MPT_GROUP;
9988 + newGroup =
9989 + (DialogMatchPatternGroupElement *)XtMalloc(sizeof(DialogMatchPatternGroupElement));
9991 + newGroup->dmpgeName = XtNewString(name);
9993 + copyDialogPatternNamesToGroup(
9994 + &MatchPatternDialog.currentStringPatterns,
9995 + newGroup);
9997 + newSeq->dmpsePtr = (void *)newGroup;
9999 + else
10001 + if (XmToggleButtonGetState(MatchPatternDialog.mptbIndividualW))
10002 + newSeq->dmpseType = MPT_INDIVIDUAL;
10003 + else
10004 + newSeq->dmpseType = MPT_SUB;
10006 + newElement =
10007 + (DialogMatchPatternTableElement *)XtMalloc(sizeof(DialogMatchPatternTableElement));
10009 + newElement->dmpteName = XtNewString(name);
10010 + newElement->dmpteType = newSeq->dmpseType;
10012 + newElement->dmpteSkipBtwnStartEnd =
10013 + XmToggleButtonGetState(MatchPatternDialog.gabSkipBtwStartEndW);
10015 + newElement->dmpteFlash =
10016 + XmToggleButtonGetState(MatchPatternDialog.gabFlashW);
10018 + newElement->dmpteIgnoreHighLightInfo =
10019 + !XmToggleButtonGetState(MatchPatternDialog.gabSyntaxBasedW);
10021 + copyDialogStringPatterns(
10022 + &MatchPatternDialog.currentStringPatterns,
10023 + &newElement->dmptePatterns);
10025 + newSeq->dmpsePtr = (void *)newElement;
10028 + return newSeq;
10032 +** Check, if min. 1 string pattern of type 'start' is
10033 +** available within dialog.
10034 +** Returns True, if min. 1 start string pattern is
10035 +** populated in dialog.
10037 +static int isStartPatternElementAvailable(
10038 + DialogStringPatterns *dialogPatterns)
10040 + int i;
10042 + for (i=0; i < dialogPatterns->dspNumberOfPatterns; i++)
10044 + if (dialogPatterns->dspElements[i]->dspeKind == PEK_START)
10045 + return True;
10048 + return False;
10052 +** Read the string pattern fields of the string pattern frame and produce an
10053 +** allocated DialogStringPatternElement structure reflecting the contents.
10054 +** Pop up dialogs telling the user what's wrong (Passing "silent" as True,
10055 +** suppresses these dialogs).
10056 +** Returns NULL on error.
10058 +static DialogStringPatternElement *readStringPatternFrameFields(int silent)
10060 + char *stringPatText;
10061 + DialogStringPatternElement *newPatElement;
10062 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
10064 + if (isRelatedToGroup)
10066 + stringPatText = getSelectedSubPatternName();
10067 + if (strcmp(stringPatText, SPNM_NONE_SELECTED) == 0)
10069 + return NULL;
10072 + stringPatText = XtNewString(stringPatText);
10074 + else
10076 + stringPatText =
10077 + XmTextGetString(MatchPatternDialog.mpdStringPatternW);
10079 + if (stringPatText == NULL)
10081 + return NULL;
10083 + else if (*stringPatText == '\0')
10085 + if (!silent)
10087 + DialogF(
10088 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10089 + "String Pattern",
10090 + "Please specify string\npattern content",
10091 + "OK");
10092 + XmProcessTraversal(MatchPatternDialog.mpdStringPatternW, XmTRAVERSE_CURRENT);
10094 + XtFree(stringPatText);
10095 + return NULL;
10099 + newPatElement = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
10101 + newPatElement->dspeText = stringPatText;
10103 + if (isRelatedToGroup)
10105 + newPatElement->dspeKind = PEK_START;
10106 + newPatElement->dspeWordBoundary = PWB_NONE;
10107 + newPatElement->dspeCaseInsensitive = False;
10108 + newPatElement->dspeRegularExpression = False;
10110 + else
10112 + newPatElement->dspeRegularExpression =
10113 + XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
10115 + if (XmToggleButtonGetState(MatchPatternDialog.sptStartW))
10116 + newPatElement->dspeKind = PEK_START;
10117 + else if (XmToggleButtonGetState(MatchPatternDialog.sptMiddleW))
10118 + newPatElement->dspeKind = PEK_MIDDLE;
10119 + else
10120 + newPatElement->dspeKind = PEK_END;
10122 + if (newPatElement->dspeRegularExpression)
10123 + newPatElement->dspeWordBoundary = PWB_NONE;
10124 + else if (XmToggleButtonGetState(MatchPatternDialog.wbbBothW))
10125 + newPatElement->dspeWordBoundary = PWB_BOTH;
10126 + else if (XmToggleButtonGetState(MatchPatternDialog.wbbLeftW))
10127 + newPatElement->dspeWordBoundary = PWB_LEFT;
10128 + else if (XmToggleButtonGetState(MatchPatternDialog.wbbRightW))
10129 + newPatElement->dspeWordBoundary = PWB_RIGHT;
10130 + else
10131 + newPatElement->dspeWordBoundary = PWB_NONE;
10133 + newPatElement->dspeCaseInsensitive =
10134 + !XmToggleButtonGetState(MatchPatternDialog.sabCaseSensitiveW);
10137 + return newPatElement;
10141 +** Returns true if the pattern fields of the matching pattern dialog are set to
10142 +** the default ("New" pattern) state.
10144 +static int matchPatternDialogEmpty(void)
10146 + return
10147 + TextWidgetIsBlank(MatchPatternDialog.mpdMatchPatternNameW) &&
10148 + XmToggleButtonGetState(MatchPatternDialog.mptbIndividualW) &&
10149 + XmToggleButtonGetState(MatchPatternDialog.gabFlashW) &&
10150 + XmToggleButtonGetState(MatchPatternDialog.gabSyntaxBasedW) &&
10151 + stringPatternFrameEmpty();
10155 +** Returns true if the string pattern frame of the matching pattern dialog is set to
10156 +** the default state.
10158 +static int stringPatternFrameEmpty(void)
10160 + return
10161 + stringPatternFieldsEmpty(False) &&
10162 + MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0;
10166 +** Returns true if the string pattern fields of the string pattern frame are set to
10167 +** the default state.
10169 +static int stringPatternFieldsEmpty(
10170 + int strPatIsRelatedToGroup)
10172 + if (strPatIsRelatedToGroup)
10174 + return(
10175 + strcmp( getSelectedSubPatternName(), SPNM_NONE_SELECTED ) == 0);
10177 + else
10179 + return
10180 + TextWidgetIsBlank(MatchPatternDialog.mpdStringPatternW) &&
10181 + XmToggleButtonGetState(MatchPatternDialog.wbbBothW) &&
10182 + XmToggleButtonGetState(MatchPatternDialog.sabCaseSensitiveW) &&
10183 + !XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
10188 +** Get the current content of the matching pattern dialog.
10189 +** If the matching pattern is o.k., then update & apply it
10190 +** to any window which is currently using the matching pattern.
10191 +** If it's bad, then only report it.
10193 +static int getAndUpdateStringMatchTable(void)
10195 + StringMatchTable *newTable;
10196 + DMPTranslationResult translResult;
10198 + /*
10199 + * Get the current information displayed by the dialog. If it's bad,
10200 + * report it to the user & return.
10201 + */
10202 + newTable = getDialogStringMatchTable(&translResult);
10204 + if (newTable == NULL && translResult != DMPTR_EMPTY)
10206 + DialogF(
10207 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10208 + "Incomplete Matching Patterns for Language Mode",
10209 + "Incomplete matching patterns for language mode '%s'.\n"
10210 + "Please complete them first",
10211 + "OK",
10212 + MatchPatternDialog.mpdLangModeName);
10214 + return False;
10217 + /*
10218 + * change the matching pattern
10219 + */
10220 + updateStringMatchTable( newTable );
10222 + return True;
10226 +** Update the matching pattern set being edited in the matching pattern dialog
10227 +** with the information that the dialog is currently displaying, and
10228 +** apply changes to any window which is currently using the matching pattern.
10230 +static void updateStringMatchTable(
10231 + StringMatchTable *newTable)
10233 + WindowInfo *window;
10234 + int i;
10236 + /*
10237 + * Find the matching pattern being modified
10238 + */
10239 + for (i=0; i<NbrMatchTables; i++)
10241 + if (!strcmp(MatchPatternDialog.mpdLangModeName, MatchTables[i]->smtLanguageMode))
10243 + /*
10244 + * replace existing matching pattern
10245 + */
10246 + freeStringMatchTable(MatchTables[i]);
10247 + MatchTables[i] = newTable;
10248 + break;
10252 + if (i == NbrMatchTables)
10254 + /*
10255 + * new match table for language mode -> add it to end
10256 + */
10257 + MatchTables[NbrMatchTables++] = newTable;
10260 + /*
10261 + * Find windows that are currently using this matching pattern set and
10262 + * update this windows
10263 + */
10264 + for (window=WindowList; window!=NULL; window=window->next)
10266 + if ((window->languageMode == PLAIN_LANGUAGE_MODE &&
10267 + !strcmp(PLAIN_LM_STRING, newTable->smtLanguageMode)) ||
10268 + (window->languageMode != PLAIN_LANGUAGE_MODE &&
10269 + !strcmp(LanguageModeName(window->languageMode), newTable->smtLanguageMode)))
10271 + window->stringMatchTable = newTable;
10275 + /*
10276 + * Note that preferences have been changed
10277 + */
10278 + MarkPrefsChanged();
10281 +static StringMatchTable *getDialogStringMatchTable(
10282 + DMPTranslationResult *result)
10284 + int matchPatListIdx =
10285 + ManagedListSelectedIndex(MatchPatternDialog.mpdMatchPatternNamesListW);
10286 + int stringPatListIdx =
10287 + ManagedListSelectedIndex(MatchPatternDialog.mpdStringPatternsListW);
10289 + /*
10290 + * Get the current content of the matching pattern dialog fields
10291 + */
10292 + if (!UpdateManagedList(MatchPatternDialog.mpdStringPatternsListW, True))
10294 + *result = DMPTR_INCOMPLETE;
10296 + return NULL;
10299 + if (!UpdateManagedList(MatchPatternDialog.mpdMatchPatternNamesListW, True))
10301 + *result = DMPTR_INCOMPLETE;
10303 + return NULL;
10306 + SelectManagedListItem(MatchPatternDialog.mpdMatchPatternNamesListW, matchPatListIdx);
10307 + SelectManagedListItem(MatchPatternDialog.mpdStringPatternsListW, stringPatListIdx);
10309 + /*
10310 + * Translate dialog match table to string match table
10311 + */
10312 + return translateDialogStringMatchTable(&MatchPatternDialog.mpdTable, result);
10315 +static StringMatchTable *translateDialogStringMatchTable(
10316 + DialogMatchPatternInfo *dialogTable,
10317 + DMPTranslationResult *result)
10319 + ReadMatchPatternInfo readPatInfo;
10320 + DialogMatchPatternSequenceElement *seq;
10321 + MatchPatternTableElement *newPatElement;
10322 + MatchPatternGroupElement *newGroupElement;
10323 + char *errMsg;
10324 + ErrorInfo errInfo;
10325 + int i;
10327 + initErrorInfo(&errInfo);
10329 + readPatInfo.rmpiNbrOfElements = 0;
10330 + readPatInfo.rmpiNbrOfGroups = 0;
10331 + readPatInfo.rmpiNbrOfSeqElements = 0;
10332 + readPatInfo.rmpiAllPatRE = NULL;
10333 + readPatInfo.rmpiFlashPatRE = NULL;
10335 + /*
10336 + * if no dialog patterns are defined, return "empty" table
10337 + */
10338 + if (dialogTable->dmpiNbrOfSeqElements == 0)
10340 + *result = DMPTR_EMPTY;
10342 + return createStringMatchTable(
10343 + &readPatInfo,
10344 + XtNewString(MatchPatternDialog.mpdLangModeName));
10347 + /*
10348 + * translate dialog matching pattern elements
10349 + */
10350 + for (i=0; i < dialogTable->dmpiNbrOfSeqElements; i++)
10352 + seq = dialogTable->dmpiSequence[i];
10354 + if (seq->dmpseType == MPT_GROUP)
10356 + newGroupElement =
10357 + translateDialogMatchPatternGroupElement(
10358 + &readPatInfo,
10359 + (DialogMatchPatternGroupElement *)seq->dmpsePtr);
10361 + if (newGroupElement == NULL)
10363 + freeReadMatchPatternInfo(&readPatInfo);
10365 + *result = DMPTR_INCOMPLETE;
10367 + return NULL;
10370 + readPatInfo.rmpiGroup[readPatInfo.rmpiNbrOfGroups ++] =
10371 + newGroupElement;
10373 + recordPatternSequence(
10374 + &readPatInfo,
10375 + seq->dmpseName,
10376 + seq->dmpseType,
10377 + readPatInfo.rmpiNbrOfGroups-1 );
10379 + else
10381 + newPatElement =
10382 + translateDialogMatchPatternTableElement(
10383 + (DialogMatchPatternTableElement *)seq->dmpsePtr);
10385 + newPatElement->mpteIndex = readPatInfo.rmpiNbrOfElements;
10387 + readPatInfo.rmpiElement[readPatInfo.rmpiNbrOfElements ++] =
10388 + newPatElement;
10390 + if (newPatElement->mpteType == MPT_INDIVIDUAL)
10392 + if (!assignIndividualGroup(&readPatInfo, &errMsg, newPatElement))
10394 + DialogF(
10395 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10396 + "Assign reg. exp.",
10397 + "%s\n(Pattern: '%s')",
10398 + "OK",
10399 + errMsg,
10400 + newPatElement->mpteName);
10402 + freeReadMatchPatternInfo(&readPatInfo);
10404 + *result = DMPTR_INCOMPLETE;
10406 + return NULL;
10410 + treatDuplicatedMTEntries(readPatInfo.rmpiElement, readPatInfo.rmpiNbrOfElements);
10412 + recordPatternSequence(
10413 + &readPatInfo,
10414 + seq->dmpseName,
10415 + seq->dmpseType,
10416 + newPatElement->mpteIndex );
10420 + /*
10421 + * compile reg. expressions of "read" patterns
10422 + */
10423 + if (createRegExpOfPatterns( &readPatInfo, &errInfo ))
10425 + errInfo.eiLanguageMode = XtNewString(MatchPatternDialog.mpdLangModeName);
10426 + dialogMatchingPatternSetError(
10427 + "Assign all patterns reg. exp.",
10428 + &errInfo);
10430 + freeReadMatchPatternInfo(&readPatInfo);
10432 + *result = DMPTR_INCOMPLETE;
10434 + return NULL;
10437 + *result = DMPTR_OK;
10439 + return createStringMatchTable(
10440 + &readPatInfo,
10441 + XtNewString(MatchPatternDialog.mpdLangModeName));
10444 +static MatchPatternTableElement *translateDialogMatchPatternTableElement(
10445 + DialogMatchPatternTableElement *dialogElement)
10447 + MatchPatternTableElement *newElement;
10449 + newElement =
10450 + (MatchPatternTableElement *)XtMalloc(sizeof(MatchPatternTableElement));
10452 + newElement->mpteName = XtNewString(dialogElement->dmpteName);
10453 + newElement->mpteIndex = NO_ELEMENT_IDX;
10454 + newElement->mpteType = dialogElement->dmpteType;
10455 + newElement->mpteGroup = NO_GROUP_IDX;
10457 + translateDialogPatterns(&dialogElement->dmptePatterns, newElement);
10459 + newElement->mpteSkipBtwnStartEnd = dialogElement->dmpteSkipBtwnStartEnd;
10460 + newElement->mpteFlash = dialogElement->dmpteFlash;
10461 + newElement->mpteIgnoreHighLightInfo = dialogElement->dmpteIgnoreHighLightInfo;
10462 + newElement->mpteStartEndRE = NULL;
10464 + initGlobalBackRefList( newElement->mpteGlobalBackRef );
10466 + return newElement;
10469 +static void translateDialogPatterns(
10470 + DialogStringPatterns *dialogPatterns,
10471 + MatchPatternTableElement *newElement)
10473 + int sizeOfPat;
10474 + int i;
10476 + /*
10477 + * allocate memory for patterns
10478 + */
10479 + newElement->mpteAll.pesNumberOfPattern = dialogPatterns->dspNumberOfPatterns;
10481 + sizeOfPat =
10482 + sizeof(PatternElement *) * dialogPatterns->dspNumberOfPatterns;
10484 + newElement->mpteAll.pesPattern = (PatternElement **)XtMalloc(sizeOfPat);
10486 + /*
10487 + * assign dialog patterns to patterns of MatchPatternTableElement
10488 + */
10489 + for (i=0; i < dialogPatterns->dspNumberOfPatterns; i++)
10491 + newElement->mpteAll.pesPattern[i] =
10492 + createPatternElement(
10493 + XtNewString(dialogPatterns->dspElements[i]->dspeText),
10494 + dialogPatterns->dspElements[i]->dspeKind,
10495 + dialogPatterns->dspElements[i]->dspeWordBoundary,
10496 + dialogPatterns->dspElements[i]->dspeCaseInsensitive,
10497 + dialogPatterns->dspElements[i]->dspeRegularExpression);
10499 + newElement->mpteAll.pesPattern[i]->peIndex = i;
10502 + /*
10503 + * sort pattern elements into start, middle & end arrays
10504 + */
10505 + sortDialogPatternElementSet( &newElement->mpteAll, newElement );
10507 + /*
10508 + * determine mono pattern
10509 + */
10510 + if (newElement->mpteEnd.pesNumberOfPattern == 0)
10512 + newElement->mpteIsMonoPattern = True;
10514 + copyPatternSet( &newElement->mpteStart, &newElement->mpteEnd );
10516 + else
10518 + newElement->mpteIsMonoPattern = False;
10523 + * Sort dialog pattern element set into start, middle & end arrays.
10524 + */
10525 +static void sortDialogPatternElementSet(
10526 + PatternElementSet *allPat,
10527 + MatchPatternTableElement *result)
10529 + int sizeOfPat;
10531 + /*
10532 + * count number of start, middle & end pattern elements
10533 + */
10534 + countPatternElementKind( allPat, result );
10536 + /*
10537 + * allocate pattern elements
10538 + */
10539 + sizeOfPat = sizeof(PatternElement *) * result->mpteStart.pesNumberOfPattern;
10540 + result->mpteStart.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
10542 + if (result->mpteMiddle.pesNumberOfPattern != 0)
10544 + sizeOfPat = sizeof(PatternElement *) * result->mpteMiddle.pesNumberOfPattern;
10545 + result->mpteMiddle.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
10548 + if (result->mpteEnd.pesNumberOfPattern != 0)
10550 + sizeOfPat = sizeof(PatternElement *) * result->mpteEnd.pesNumberOfPattern;
10551 + result->mpteEnd.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
10554 + /*
10555 + * sort pattern elements into start, middle & end arrays
10556 + */
10557 + sortPatternElementSet( allPat, result );
10560 +static MatchPatternGroupElement *translateDialogMatchPatternGroupElement(
10561 + ReadMatchPatternInfo *info,
10562 + DialogMatchPatternGroupElement *dialogGroup)
10564 + int i;
10565 + int error = False;
10566 + MatchPatternTableElement *subPatElement;
10567 + int sizeOfIds;
10568 + MatchPatternGroupElement *group;
10570 + /*
10571 + * Allocate memory for the matching pattern group. Copy name & number of
10572 + * sub patterns.
10573 + */
10574 + group =
10575 + (MatchPatternGroupElement *)XtMalloc( sizeof(MatchPatternGroupElement) );
10577 + group->mpgeName = XtNewString(dialogGroup->dmpgeName);
10578 + group->mpgeNumberOfSubPatterns = dialogGroup->dmpgeNumberOfSubPatterns;
10579 + group->mpgeKeywordRE = NULL;
10581 + /*
10582 + * Allocate memory for the sub-matching pattern IDs
10583 + */
10584 + sizeOfIds = sizeof(char *) * group->mpgeNumberOfSubPatterns;
10585 + group->mpgeSubPatternIds = (char **)XtMalloc( sizeOfIds );
10587 + for (i=0; i < group->mpgeNumberOfSubPatterns; i ++)
10589 + /*
10590 + * Remember sub-matching pattern ID
10591 + */
10592 + group->mpgeSubPatternIds[i] = XtNewString(dialogGroup->dmpgeSubPatternIds[i]);
10594 + /*
10595 + * Assign the index of this group to the sub-matching pattern
10596 + * if no group index was assigned before.
10597 + */
10598 + subPatElement =
10599 + getPatternOfName( info, dialogGroup->dmpgeSubPatternIds[i]);
10601 + if (subPatElement == NULL)
10603 + DialogF(
10604 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10605 + "Group Compilation",
10606 + "Group '%s':\nsub-matching pattern '%s' not defined before",
10607 + "OK",
10608 + group->mpgeName,
10609 + dialogGroup->dmpgeSubPatternIds[i]);
10611 + error = True;
10613 + else
10615 + if (subPatElement->mpteGroup == NO_GROUP_IDX)
10617 + subPatElement->mpteGroup = info->rmpiNbrOfGroups;
10622 + if (error)
10624 + freeMatchPatternGroupElement(group);
10626 + return NULL;
10629 + return group;
10632 +static int stringMatchTableDiffer(
10633 + StringMatchTable *oldTable,
10634 + StringMatchTable *newTable)
10636 + int i, j;
10637 + MatchPatternTable *oldPatTab = oldTable->smtAllPatterns;
10638 + MatchPatternTable *newPatTab = newTable->smtAllPatterns;
10639 + MatchPatternTableElement *oldPat;
10640 + MatchPatternTableElement *newPat;
10641 + MatchPatternGroupElement *oldGroup;
10642 + MatchPatternGroupElement *newGroup;
10643 + MatchPatternSequenceElement *oldSeq;
10644 + MatchPatternSequenceElement *newSeq;
10646 + if (oldTable->smtNumberOfSeqElements != newTable->smtNumberOfSeqElements)
10647 + return True;
10649 + for (i=0; i < oldTable->smtNumberOfSeqElements; i++)
10651 + oldSeq = oldTable->smtSequence[i];
10652 + newSeq = newTable->smtSequence[i];
10654 + if (AllocatedStringsDiffer(oldSeq->mpseName, newSeq->mpseName))
10655 + return True;
10656 + if (oldSeq->mpseType != newSeq->mpseType)
10657 + return True;
10659 + if (oldSeq->mpseType == MPT_GROUP)
10661 + oldGroup = oldTable->smtGroups[oldSeq->mpseIndex];
10662 + newGroup = newTable->smtGroups[newSeq->mpseIndex];
10664 + if (AllocatedStringsDiffer(oldGroup->mpgeName, newGroup->mpgeName))
10665 + return True;
10667 + if (oldGroup->mpgeNumberOfSubPatterns != newGroup->mpgeNumberOfSubPatterns)
10668 + return True;
10670 + for (j=0; j < oldGroup->mpgeNumberOfSubPatterns; j++)
10672 + if (AllocatedStringsDiffer(
10673 + oldGroup->mpgeSubPatternIds[j],
10674 + newGroup->mpgeSubPatternIds[j]))
10675 + return True;
10678 + else
10680 + oldPat = oldPatTab->mptElements[oldSeq->mpseIndex];
10681 + newPat = newPatTab->mptElements[newSeq->mpseIndex];
10683 + if (AllocatedStringsDiffer(oldPat->mpteName, newPat->mpteName))
10684 + return True;
10686 + if (oldPat->mpteType != newPat->mpteType)
10687 + return True;
10689 + if (oldPat->mpteGroup != newPat->mpteGroup)
10690 + return True;
10692 + if (oldPat->mpteAll.pesNumberOfPattern != newPat->mpteAll.pesNumberOfPattern)
10693 + return True;
10695 + for (j=0; j < oldPat->mpteAll.pesNumberOfPattern; j ++)
10697 + if (patternElementDiffer(
10698 + oldPat->mpteAll.pesPattern[j], oldPatTab,
10699 + newPat->mpteAll.pesPattern[j], newPatTab ) )
10700 + return True;
10703 + if (oldPat->mpteIsMonoPattern != newPat->mpteIsMonoPattern)
10704 + return True;
10706 + if (oldPat->mpteSkipBtwnStartEnd != newPat->mpteSkipBtwnStartEnd)
10707 + return True;
10709 + if (oldPat->mpteIgnoreHighLightInfo != newPat->mpteIgnoreHighLightInfo)
10710 + return True;
10712 + if (oldPat->mpteFlash != newPat->mpteFlash)
10713 + return True;
10717 + return False;
10720 +static int patternElementDiffer(
10721 + PatternElement *oldPE,
10722 + MatchPatternTable *oldTab,
10723 + PatternElement *newPE,
10724 + MatchPatternTable *newTab)
10726 + StringPattern *oldSP;
10727 + StringPattern *newSP;
10729 + oldSP = GetStringPattern(oldTab, oldPE);
10730 + newSP = GetStringPattern(newTab, newPE);
10732 + if (AllocatedStringsDiffer(oldSP->spText, newSP->spText))
10733 + return True;
10734 + if (AllocatedStringsDiffer(oldSP->spOrigText, newSP->spOrigText))
10735 + return True;
10736 + if (oldPE->peKind != newPE->peKind)
10737 + return True;
10738 + if (oldSP->spWordBoundary != newSP->spWordBoundary)
10739 + return True;
10740 + if (oldSP->spCaseInsensitive != newSP->spCaseInsensitive)
10741 + return True;
10742 + if (oldSP->spRegularExpression != newSP->spRegularExpression)
10743 + return True;
10745 + return False;
10748 +static DialogMatchPatternGroupElement *getDialogGroupUsingMatchPattern(
10749 + char *matchPatternName)
10751 + DialogMatchPatternSequenceElement *seq;
10752 + DialogMatchPatternGroupElement *group;
10753 + int i, j;
10755 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10757 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
10759 + if (seq->dmpseType == MPT_GROUP)
10761 + group = (DialogMatchPatternGroupElement *)seq->dmpsePtr;
10763 + for (j=0; j < group->dmpgeNumberOfSubPatterns; j ++)
10765 + if (strcmp(group->dmpgeSubPatternIds[j], matchPatternName) == 0)
10766 + return group;
10771 + return NULL;
10774 +static void removeMatchPatternFromGroup(
10775 + char *matchPatternName,
10776 + DialogMatchPatternGroupElement *group)
10778 + int i;
10780 + for (i=0; i < group->dmpgeNumberOfSubPatterns; i ++)
10782 + if (strcmp(group->dmpgeSubPatternIds[i], matchPatternName) == 0)
10784 + /*
10785 + * remove existing matching pattern name from sub-pattern list
10786 + */
10787 + freeXtPtr((void **)&group->dmpgeSubPatternIds[i]);
10788 + memmove(
10789 + &group->dmpgeSubPatternIds[i],
10790 + &group->dmpgeSubPatternIds[i+1],
10791 + (group->dmpgeNumberOfSubPatterns-1 - i) * sizeof(char *));
10792 + group->dmpgeNumberOfSubPatterns --;
10794 + return;
10799 +static void removeMatchPatternFromAllGroups(
10800 + char *matchPatternName)
10802 + DialogMatchPatternSequenceElement *seq;
10803 + DialogMatchPatternGroupElement *group;
10804 + int i;
10806 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10808 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
10810 + if (seq->dmpseType == MPT_GROUP)
10812 + group = (DialogMatchPatternGroupElement *)seq->dmpsePtr;
10814 + removeMatchPatternFromGroup(matchPatternName, group);
10819 +static void renameMatchPatternInGroup(
10820 + char *oldMatchPatternName,
10821 + char *newMatchPatternName,
10822 + DialogMatchPatternGroupElement *group)
10824 + int i;
10826 + for (i=0; i < group->dmpgeNumberOfSubPatterns; i ++)
10828 + if (strcmp(group->dmpgeSubPatternIds[i], oldMatchPatternName) == 0)
10830 + /*
10831 + * rename existing matching pattern name in sub-pattern list
10832 + */
10833 + freeXtPtr((void **)&group->dmpgeSubPatternIds[i]);
10835 + group->dmpgeSubPatternIds[i] =
10836 + XtNewString(newMatchPatternName);
10838 + return;
10843 +static void renameMatchPatternInAllGroups(
10844 + char *oldMatchPatternName,
10845 + char *newMatchPatternName)
10847 + DialogMatchPatternSequenceElement *seq;
10848 + DialogMatchPatternGroupElement *group;
10849 + int i;
10851 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10853 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
10855 + if (seq->dmpseType == MPT_GROUP)
10857 + group = (DialogMatchPatternGroupElement *)seq->dmpsePtr;
10859 + renameMatchPatternInGroup(
10860 + oldMatchPatternName,
10861 + newMatchPatternName,
10862 + group);
10867 +static void freeVariableDialogData(
10868 + int keepLanguageModeName)
10870 + int i;
10872 + if (!keepLanguageModeName)
10873 + freeXtPtr((void **)&MatchPatternDialog.mpdLangModeName);
10875 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10877 + freeDialogSequenceElement(
10878 + MatchPatternDialog.mpdTable.dmpiSequence[i] );
10881 + MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements = 0;
10883 + freeDialogStringPatterns(
10884 + &MatchPatternDialog.currentStringPatterns);
10887 +static void initGlobalBackRefList(
10888 + GlobalBackRefElement *list)
10890 + int i;
10892 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
10894 + list[i].gbreDefByStrPat = NULL;
10895 + list[i].gbreRegExpText = NULL;
10899 +static void initStrPatBackRefList(
10900 + StringPattern *strPat)
10902 + int i;
10904 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
10906 + strPat->spOwnGlobalBackRef[i].spbreRegExpText = NULL;
10907 + strPat->spOwnGlobalBackRef[i].spbreLocalBackRefID = NO_LOCAL_BACK_REF_ID;
10909 + strPat->spGlobalToLocalBackRef[i] = NO_LOCAL_BACK_REF_ID;
10913 +static void initErrorInfo(
10914 + ErrorInfo *errInfo)
10916 + errInfo->eiDetail = NULL;
10917 + errInfo->eiLanguageMode = NULL;
10918 + errInfo->eiMPTabElementName = NULL;
10919 + errInfo->eiStringPatText = NULL;
10920 + errInfo->eiRegExpCompileMsg = NULL;
10921 + errInfo->eiBackRefNbr = 0;
10924 +static void freeErrorInfo(
10925 + ErrorInfo *errInfo)
10927 + freeXtPtr((void **)&errInfo->eiLanguageMode);
10928 + freeXtPtr((void **)&errInfo->eiMPTabElementName);
10929 + freeXtPtr((void **)&errInfo->eiStringPatText);
10932 +static void freeXtPtr(void **ptr)
10934 + if (*ptr != NULL)
10936 + XtFree((char *)*ptr);
10937 + *ptr = NULL;
10941 +static void freePtr(void **ptr)
10943 + if (*ptr != NULL)
10945 + free((char *)*ptr);
10946 + *ptr = NULL;
10949 diff --quilt /dev/null new/source/patternMatchData.h
10950 --- /dev/null
10951 +++ new/source/patternMatchData.h
10952 @@ -0,0 +1,24 @@
10953 +/* $Id: patternMatchData.h,v 1.3 2003/12/12 16:45:25 uleh Exp $ */
10955 +#ifndef NEDIT_PATTERNMATCHDATA_H_INCLUDED
10956 +#define NEDIT_PATTERNMATCHDATA_H_INCLUDED
10958 +void *FindStringMatchTable(const char *langModeName);
10960 +void RenameStringMatchTable(const char *oldName, const char *newName);
10962 +void DeleteStringMatchTable(const char *langModeName);
10964 +void AssignStandardStringMatchTable(const char *langModeName);
10966 +int LMHasStringMatchTable(const char *languageMode);
10968 +int LoadMatchPatternString(char *inString);
10970 +char *WriteMatchPatternString(void);
10972 +void EditMatchPatterns(WindowInfo *window);
10974 +void UpdateLanguageModeMenuMatchPattern(void);
10976 +#endif /* NEDIT_PATTERNMATCHDATA_H_INCLUDED */
10977 diff --quilt old/source/preferences.c new/source/preferences.c
10978 --- old/source/preferences.c
10979 +++ new/source/preferences.c
10980 @@ -47,6 +47,10 @@ static const char CVSID[] = "$Id: prefer
10981 #include "windowTitle.h"
10982 #include "server.h"
10983 #include "tags.h"
10985 +/* Pattern Match Feature */
10986 +#include "patternMatchData.h"
10988 #include "../util/prefFile.h"
10989 #include "../util/misc.h"
10990 #include "../util/DialogF.h"
10991 @@ -280,7 +284,6 @@ static struct prefData {
10992 int emTabDist; /* non-zero tab dist. if emulated tabs are on */
10993 int insertTabs; /* whether to use tabs for padding */
10994 int showMatchingStyle; /* how to flash matching parenthesis */
10995 - int matchSyntaxBased; /* use syntax info to match parenthesis */
10996 int highlightSyntax; /* whether to highlight syntax by default */
10997 int smartTags; /* look for tag in current window first */
10998 int alwaysCheckRelativeTagsSpecs; /* for every new opened file of session */
10999 @@ -350,6 +353,7 @@ static struct {
11000 char *smartIndent;
11001 char *smartIndentCommon;
11002 char *shell;
11003 + char *matchPattern;
11004 } TempStringPrefs;
11006 /* preference descriptions for SavePreferences and RestorePreferences. */
11007 @@ -855,6 +859,72 @@ static PrefDescripRec PrefDescrip[] = {
11008 Matlab:Default", &TempStringPrefs.smartIndent, NULL, True},
11009 {"smartIndentInitCommon", "SmartIndentInitCommon", PREF_ALLOC_STRING,
11010 "Default", &TempStringPrefs.smartIndentCommon, NULL, True},
11011 +/* Pattern Match Feature: matchPatterns resource added */
11012 +#ifdef VMS
11013 +/* The VAX compiler can't compile Java-Script's definition in highlightData.c */
11014 + {"matchPatterns", "MatchPatterns", PREF_ALLOC_STRING,
11015 + "PLAIN:Default\n\
11016 + Ada:Default\n\
11017 + Awk:Default\n\
11018 + C++:Default\n\
11019 + C:Default\n\
11020 + CSS:Default\n\
11021 + Csh:Default\n\
11022 + Fortran:Default\n\
11023 + Java:Default\n\
11024 + LaTeX:Default\n\
11025 + Lex:Default\n\
11026 + Makefile:Default\n\
11027 + Matlab:Default\n\
11028 + NEdit Macro:Default\n\
11029 + Pascal:Default\n\
11030 + Perl:Default\n\
11031 + PostScript:Default\n\
11032 + Python:Default\n\
11033 + Regex:Default\n\
11034 + SGML HTML:Default\n\
11035 + SQL:Default\n\
11036 + Sh Ksh Bash:Default\n\
11037 + Tcl:Default\n\
11038 + VHDL:Default\n\
11039 + Verilog:Default\n\
11040 + XML:Default\n\
11041 + X Resources:Default\n\
11042 + Yacc:Default\n",
11043 + &TempStringPrefs.matchPattern, NULL, True},
11044 +#else
11045 + {"matchPatterns", "MatchPatterns", PREF_ALLOC_STRING,
11046 + "PLAIN:Default\n\
11047 + Ada:Default\n\
11048 + Awk:Default\n\
11049 + C++:Default\n\
11050 + C:Default\n\
11051 + CSS:Default\n\
11052 + Csh:Default\n\
11053 + Fortran:Default\n\
11054 + Java:Default\n\
11055 + JavaScript:Default\n\
11056 + LaTeX:Default\n\
11057 + Lex:Default\n\
11058 + Makefile:Default\n\
11059 + Matlab:Default\n\
11060 + NEdit Macro:Default\n\
11061 + Pascal:Default\n\
11062 + Perl:Default\n\
11063 + PostScript:Default\n\
11064 + Python:Default\n\
11065 + Regex:Default\n\
11066 + SGML HTML:Default\n\
11067 + SQL:Default\n\
11068 + Sh Ksh Bash:Default\n\
11069 + Tcl:Default\n\
11070 + VHDL:Default\n\
11071 + Verilog:Default\n\
11072 + XML:Default\n\
11073 + X Resources:Default\n\
11074 + Yacc:Default\n",
11075 + &TempStringPrefs.matchPattern, NULL, True},
11076 +#endif
11077 {"autoWrap", "AutoWrap", PREF_ENUM, "Continuous",
11078 &PrefData.wrapStyle, AutoWrapTypes, True},
11079 {"wrapMargin", "WrapMargin", PREF_INT, "0",
11080 @@ -871,8 +941,6 @@ static PrefDescripRec PrefDescrip[] = {
11081 &PrefData.saveOldVersion, NULL, True},
11082 {"showMatching", "ShowMatching", PREF_ENUM, "Delimiter",
11083 &PrefData.showMatchingStyle, ShowMatchingTypes, True},
11084 - {"matchSyntaxBased", "MatchSyntaxBased", PREF_BOOLEAN, "True",
11085 - &PrefData.matchSyntaxBased, NULL, True},
11086 {"highlightSyntax", "HighlightSyntax", PREF_BOOLEAN, "True",
11087 &PrefData.highlightSyntax, NULL, True},
11088 {"backlightChars", "BacklightChars", PREF_BOOLEAN, "False",
11089 @@ -1245,6 +1313,7 @@ static void lmApplyCB(Widget w, XtPointe
11090 static void lmCloseCB(Widget w, XtPointer clientData, XtPointer callData);
11091 static int lmDeleteConfirmCB(int itemIndex, void *cbArg);
11092 static int updateLMList(void);
11093 +static int isOldLanguageMode(const char *lmDialogName, const char *oldModeName);
11094 static languageModeRec *copyLanguageModeRec(languageModeRec *lm);
11095 static void *lmGetDisplayedCB(void *oldItem, int explicitRequest, int *abort,
11096 void *cbArg);
11097 @@ -1428,6 +1497,11 @@ static void translatePrefFormats(int con
11098 XtFree(TempStringPrefs.smartIndentCommon);
11099 TempStringPrefs.smartIndentCommon = NULL;
11101 + if (TempStringPrefs.matchPattern != NULL) {
11102 + LoadMatchPatternString(TempStringPrefs.matchPattern);
11103 + XtFree(TempStringPrefs.matchPattern);
11104 + TempStringPrefs.matchPattern = NULL;
11107 /* translate the font names into fontLists suitable for the text widget */
11108 font = XLoadQueryFont(TheDisplay, PrefData.fontString);
11109 @@ -1507,6 +1581,7 @@ void SaveNEditPrefs(Widget parent, int q
11110 TempStringPrefs.styles = WriteStylesString();
11111 TempStringPrefs.smartIndent = WriteSmartIndentString();
11112 TempStringPrefs.smartIndentCommon = WriteSmartIndentCommonString();
11113 + TempStringPrefs.matchPattern = WriteMatchPatternString();
11114 strcpy(PrefData.fileVersion, PREF_FILE_VERSION);
11116 if (!SavePreferences(XtDisplay(parent), prefFileName, HeaderText,
11117 @@ -1526,6 +1601,7 @@ void SaveNEditPrefs(Widget parent, int q
11118 XtFree(TempStringPrefs.styles);
11119 XtFree(TempStringPrefs.smartIndent);
11120 XtFree(TempStringPrefs.smartIndentCommon);
11121 + XtFree(TempStringPrefs.matchPattern);
11123 PrefsHaveChanged = False;
11125 @@ -1922,16 +1998,6 @@ int GetPrefShowMatching(void)
11126 return PrefData.showMatchingStyle;
11129 -void SetPrefMatchSyntaxBased(int state)
11131 - setIntPref(&PrefData.matchSyntaxBased, state);
11134 -int GetPrefMatchSyntaxBased(void)
11136 - return PrefData.matchSyntaxBased;
11139 void SetPrefHighlightSyntax(Boolean state)
11141 setIntPref(&PrefData.highlightSyntax, state);
11142 @@ -3481,6 +3547,21 @@ static int lmDeleteConfirmCB(int itemInd
11143 return False;
11146 + /* Pattern Match Feature: don't allow deletion if data will be lost */
11147 + if (LMHasStringMatchTable(LMDialog.languageModeList[itemIndex]->name))
11149 + DialogF(DF_WARN, LMDialog.shell, 1, "Matching Patterns exist",
11150 + "This language mode has matching patterns\n"
11151 + "defined. Please delete the patterns first,\n"
11152 + "in Preferences -> Default Settings ->\n"
11153 + "Show Matching (..) -> Matching Patterns ..,\n"
11154 + "before proceeding here.", "Dismiss");
11155 + return False;
11158 + /* delete "empty" string match table related to language mode to be deleted */
11159 + DeleteStringMatchTable(LMDialog.languageModeList[itemIndex]->name);
11161 return True;
11164 @@ -3501,15 +3582,15 @@ static int updateLMList(void)
11165 return False;
11167 /* Fix up language mode indices in all open windows (which may change
11168 - if the currently selected mode is deleted or has changed position),
11169 - and update word delimiters */
11170 + if the currently selected mode is renamed, deleted or has changed
11171 + position), and update word delimiters */
11172 for (window=WindowList; window!=NULL; window=window->next) {
11173 if (window->languageMode != PLAIN_LANGUAGE_MODE) {
11174 oldLanguageMode = window->languageMode;
11175 oldModeName = LanguageModes[window->languageMode]->name;
11176 window->languageMode = PLAIN_LANGUAGE_MODE;
11177 for (i=0; i<LMDialog.nLanguageModes; i++) {
11178 - if (!strcmp(oldModeName, LMDialog.languageModeList[i]->name)) {
11179 + if (isOldLanguageMode(LMDialog.languageModeList[i]->name, oldModeName)) {
11180 newDelimiters = LMDialog.languageModeList[i]->delimiters;
11181 if (newDelimiters == NULL)
11182 newDelimiters = GetPrefDelimiters();
11183 @@ -3539,6 +3620,7 @@ static int updateLMList(void)
11184 *strchr(LMDialog.languageModeList[i]->name, ':') = '\0';
11185 RenameHighlightPattern(LMDialog.languageModeList[i]->name, newName);
11186 RenameSmartIndentMacros(LMDialog.languageModeList[i]->name, newName);
11187 + RenameStringMatchTable(LMDialog.languageModeList[i]->name, newName);
11188 memmove(LMDialog.languageModeList[i]->name, newName,
11189 strlen(newName) + 1);
11190 ChangeManagedListData(LMDialog.managedListW);
11191 @@ -3556,13 +3638,24 @@ static int updateLMList(void)
11192 user menu items */
11193 UpdateUserMenuInfo();
11195 + /* Pattern Match Feature: assign standard string match table to new
11196 + language modes */
11197 + for (i=0; i<NLanguageModes; i++) {
11198 + if (FindStringMatchTable(LanguageModeName(i)) == NULL)
11199 + AssignStandardStringMatchTable(LanguageModeName(i));
11202 /* Update the menus in the window menu bars and load any needed
11203 - calltips files */
11204 + calltips files and reassign string match tables */
11205 for (window=WindowList; window!=NULL; window=window->next) {
11206 updateLanguageModeSubmenu(window);
11207 if (window->languageMode != PLAIN_LANGUAGE_MODE &&
11208 LanguageModes[window->languageMode]->defTipsFile != NULL)
11209 AddTagsFile(LanguageModes[window->languageMode]->defTipsFile, TIP);
11211 + window->stringMatchTable =
11212 + FindStringMatchTable(LanguageModeName(window->languageMode));
11214 /* cache user menus: Rebuild all user menus of this window */
11215 RebuildAllMenus(window);
11217 @@ -3571,12 +3664,32 @@ static int updateLMList(void)
11218 UpdateLanguageModeMenu();
11219 /* The same for the smart indent macro dialog */
11220 UpdateLangModeMenuSmartIndent();
11221 + /* The same for the match pattern dialog */
11222 + UpdateLanguageModeMenuMatchPattern();
11223 /* Note that preferences have been changed */
11224 MarkPrefsChanged();
11226 return True;
11230 +** Returns true, if the given old language mode name matches the
11231 +** given (new) language mode dialog name.
11233 +static int isOldLanguageMode(const char *lmDialogName, const char *oldModeName)
11235 + char *c = strchr(lmDialogName, ':');
11236 + int isOldMode = !strcmp(oldModeName, lmDialogName);
11238 + if (!isOldMode && c != NULL) {
11239 + *c = '\0';
11240 + isOldMode = !strcmp(lmDialogName, oldModeName);
11241 + *c = ':';
11244 + return isOldMode;
11247 static void *lmGetDisplayedCB(void *oldItem, int explicitRequest, int *abort,
11248 void *cbArg)
11250 @@ -4570,6 +4683,10 @@ static void reapplyLanguageMode(WindowIn
11251 DeleteTagsFile( LanguageModes[oldMode]->defTipsFile, TIP, False );
11254 + /* Pattern Match Feature: Assign the match pattern related to
11255 + the language mode */
11256 + window->stringMatchTable = FindStringMatchTable(LanguageModeName(mode));
11258 /* Set delimiters for all text widgets */
11259 if (mode == PLAIN_LANGUAGE_MODE || LanguageModes[mode]->delimiters == NULL)
11260 delimiters = GetPrefDelimiters();
11261 @@ -5187,14 +5304,31 @@ char *ReadSymbolicFieldTextWidget(Widget
11263 ** Create a pulldown menu pane with the names of the current language modes.
11264 ** XmNuserData for each item contains the language mode name.
11265 +** Pattern Match Feature: if "includePlain" is set, then 1st menu entry
11266 +** holds "PLAIN".
11268 -Widget CreateLanguageModeMenu(Widget parent, XtCallbackProc cbProc, void *cbArg)
11269 +Widget CreateLanguageModeMenu(
11270 + Widget parent,
11271 + XtCallbackProc cbProc,
11272 + void *cbArg,
11273 + int includePlain)
11275 Widget menu, btn;
11276 int i;
11277 XmString s1;
11279 menu = CreatePulldownMenu(parent, "languageModes", NULL, 0);
11281 + if (includePlain) {
11282 + btn = XtVaCreateManagedWidget("languageMode", xmPushButtonGadgetClass,
11283 + menu,
11284 + XmNlabelString, s1=XmStringCreateSimple("PLAIN"),
11285 + XmNmarginHeight, 0,
11286 + XmNuserData, (void *)"PLAIN", NULL);
11287 + XmStringFree(s1);
11288 + XtAddCallback(btn, XmNactivateCallback, cbProc, cbArg);
11291 for (i=0; i<NLanguageModes; i++) {
11292 btn = XtVaCreateManagedWidget("languageMode", xmPushButtonGadgetClass,
11293 menu,
11294 diff --quilt old/source/preferences.h new/source/preferences.h
11295 --- old/source/preferences.h
11296 +++ new/source/preferences.h
11297 @@ -111,8 +111,6 @@ void SetPrefInsertTabs(int state);
11298 int GetPrefInsertTabs(void);
11299 void SetPrefShowMatching(int state);
11300 int GetPrefShowMatching(void);
11301 -void SetPrefMatchSyntaxBased(int state);
11302 -int GetPrefMatchSyntaxBased(void);
11303 void SetPrefHighlightSyntax(Boolean state);
11304 Boolean GetPrefHighlightSyntax(void);
11305 void SetPrefBacklightChars(int state);
11306 @@ -191,7 +189,7 @@ int FindLanguageMode(const char *languag
11307 void UnloadLanguageModeTipsFile(WindowInfo *window);
11308 void DetermineLanguageMode(WindowInfo *window, int forceNewDefaults);
11309 Widget CreateLanguageModeMenu(Widget parent, XtCallbackProc cbProc,
11310 - void *cbArg);
11311 + void *cbArg, int includePlain);
11312 void SetLangModeMenu(Widget optMenu, const char *modeName);
11313 void CreateLanguageModeSubMenu(WindowInfo* window, const Widget parent,
11314 const char* name, const char* label, const char mnemonic);
11315 diff --quilt old/source/search.c new/source/search.c
11316 --- old/source/search.c
11317 +++ new/source/search.c
11318 @@ -85,6 +85,7 @@ static const char CVSID[] = "$Id: search
11319 #include "../debug.h"
11320 #endif
11322 +#include "patternMatch.h"
11324 int NHist = 0;
11326 @@ -173,6 +174,7 @@ static void checkMultiReplaceListForDoom
11327 WindowInfo* doomedWindow);
11328 static void removeDoomedWindowFromList(WindowInfo* window, int index);
11329 static void unmanageReplaceDialogs(const WindowInfo *window);
11330 +static int getPosForMatchingCharacter(WindowInfo *window);
11331 static void flashTimeoutProc(XtPointer clientData, XtIntervalId *id);
11332 static void eraseFlash(WindowInfo *window);
11333 static int getReplaceDlogInfo(WindowInfo *window, int *direction,
11334 @@ -213,9 +215,6 @@ static void resetReplaceTabGroup(WindowI
11335 static int searchMatchesSelection(WindowInfo *window, const char *searchString,
11336 int searchType, int *left, int *right, int *searchExtentBW,
11337 int *searchExtentFW);
11338 -static int findMatchingChar(WindowInfo *window, char toMatch,
11339 - void *toMatchStyle, int charPos, int startLimit, int endLimit,
11340 - int *matchPos);
11341 static Boolean replaceUsingRE(const char* searchStr, const char* replaceStr,
11342 const char* sourceStr, int beginPos, char* destStr, int maxDestLen,
11343 int prevChar, const char* delimiters, int defaultFlags);
11344 @@ -253,24 +252,6 @@ typedef struct _charMatchTable {
11345 char direction;
11346 } charMatchTable;
11348 -#define N_MATCH_CHARS 13
11349 -#define N_FLASH_CHARS 6
11350 -static charMatchTable MatchingChars[N_MATCH_CHARS] = {
11351 - {'{', '}', SEARCH_FORWARD},
11352 - {'}', '{', SEARCH_BACKWARD},
11353 - {'(', ')', SEARCH_FORWARD},
11354 - {')', '(', SEARCH_BACKWARD},
11355 - {'[', ']', SEARCH_FORWARD},
11356 - {']', '[', SEARCH_BACKWARD},
11357 - {'<', '>', SEARCH_FORWARD},
11358 - {'>', '<', SEARCH_BACKWARD},
11359 - {'/', '/', SEARCH_FORWARD},
11360 - {'"', '"', SEARCH_FORWARD},
11361 - {'\'', '\'', SEARCH_FORWARD},
11362 - {'`', '`', SEARCH_FORWARD},
11363 - {'\\', '\\', SEARCH_FORWARD},
11367 ** Definitions for the search method strings, used as arguments for
11368 ** macro search subroutines and search action routines
11369 @@ -3338,18 +3319,18 @@ static void iSearchTextKeyEH(Widget w, W
11373 -** Check the character before the insertion cursor of textW and flash
11374 -** matching parenthesis, brackets, or braces, by temporarily highlighting
11375 -** the matching character (a timer procedure is scheduled for removing the
11376 -** highlights)
11377 +** Check the characters before the insertion cursor of textW and flash
11378 +** matching patterns (parenthesis e.g. brackets, braces ..) by temporarily
11379 +** highlighting matching characters (a timer procedure is scheduled for
11380 +** removing the highlights)
11382 void FlashMatching(WindowInfo *window, Widget textW)
11384 - char c;
11385 - void *style;
11386 - int pos, matchIndex;
11387 - int startPos, endPos, searchPos, matchPos;
11388 + int pos;
11389 + int direction;
11390 + int startPos, endPos, matchPos, matchLen;
11391 int constrain;
11392 + MatchingType matchingType;
11394 /* if a marker is already drawn, erase it and cancel the timeout */
11395 if (window->flashTimeoutID != 0) {
11396 @@ -3367,48 +3348,43 @@ void FlashMatching(WindowInfo *window, W
11397 if (window->buffer->primary.selected)
11398 return;
11400 - /* get the character to match and the position to start from */
11401 - pos = TextGetCursorPos(textW) - 1;
11402 + /* get the position to start from */
11403 + pos = TextGetCursorPos(textW);
11404 if (pos < 0)
11405 return;
11406 - c = BufGetCharacter(window->buffer, pos);
11407 - style = GetHighlightInfo(window, pos);
11409 - /* is the character one we want to flash? */
11410 - for (matchIndex = 0; matchIndex<N_FLASH_CHARS; matchIndex++) {
11411 - if (MatchingChars[matchIndex].c == c)
11412 - break;
11414 - if (matchIndex == N_FLASH_CHARS)
11415 - return;
11417 /* constrain the search to visible text only when in single-pane mode
11418 AND using delimiter flashing (otherwise search the whole buffer) */
11419 constrain = ((window->nPanes == 0) &&
11420 (window->showMatchingStyle == FLASH_DELIMIT));
11422 - if (MatchingChars[matchIndex].direction == SEARCH_BACKWARD) {
11423 startPos = constrain ? TextFirstVisiblePos(textW) : 0;
11424 - endPos = pos;
11425 - searchPos = endPos;
11426 - } else {
11427 - startPos = pos;
11428 endPos = constrain ? TextLastVisiblePos(textW) :
11429 window->buffer->length;
11430 - searchPos = startPos;
11432 + /* cursor pos. must be between start / end pos. */
11433 + if (pos < startPos || pos > endPos)
11434 + return;
11436 + /* Pattern Match Feature: determine matching type
11437 + (here: flash delimiter or range) */
11438 + if (window->showMatchingStyle == FLASH_DELIMIT) {
11439 + matchingType = MT_FLASH_DELIMIT;
11440 + } else {
11441 + matchingType = MT_FLASH_RANGE;
11444 - /* do the search */
11445 - if (!findMatchingChar(window, c, style, searchPos, startPos, endPos,
11446 - &matchPos))
11447 + /* Pattern Match Feature: do the search */
11448 + if (!FindMatchingString(window, matchingType, &pos, startPos, endPos,
11449 + &matchPos, &matchLen, &direction))
11450 return;
11452 if (window->showMatchingStyle == FLASH_DELIMIT) {
11453 - /* Highlight either the matching character ... */
11454 - BufHighlight(window->buffer, matchPos, matchPos+1);
11455 + /* Highlight either the matching characters ... */
11456 + BufHighlight(window->buffer, matchPos, matchPos + matchLen);
11457 } else {
11458 /* ... or the whole range. */
11459 - if (MatchingChars[matchIndex].direction == SEARCH_BACKWARD) {
11460 + if (direction == SEARCH_BACKWARD) {
11461 BufHighlight(window->buffer, matchPos, pos+1);
11462 } else {
11463 BufHighlight(window->buffer, matchPos+1, pos);
11464 @@ -3422,38 +3398,46 @@ void FlashMatching(WindowInfo *window, W
11465 window->flashPos = matchPos;
11468 -void SelectToMatchingCharacter(WindowInfo *window)
11470 +** Pattern Match Feature:
11471 +** get position of the character to match from the selection, or
11472 +** the character before the insert point if nothing is selected.
11475 +static int getPosForMatchingCharacter(WindowInfo *window)
11477 + int pos;
11478 int selStart, selEnd;
11479 - int startPos, endPos, matchPos;
11480 textBuffer *buf = window->buffer;
11482 - /* get the character to match and its position from the selection, or
11483 - the character before the insert point if nothing is selected.
11484 - Give up if too many characters are selected */
11485 - if (!GetSimpleSelection(buf, &selStart, &selEnd)) {
11486 - selEnd = TextGetCursorPos(window->lastFocus);
11487 - if (window->overstrike)
11488 - selEnd += 1;
11489 - selStart = selEnd - 1;
11490 - if (selStart < 0) {
11491 - XBell(TheDisplay, 0);
11492 - return;
11494 + if (GetSimpleSelection(buf, &selStart, &selEnd)) {
11495 + pos = selEnd;
11497 - if ((selEnd - selStart) != 1) {
11498 - XBell(TheDisplay, 0);
11499 - return;
11500 + else {
11501 + pos = TextGetCursorPos(window->lastFocus);
11505 + return pos;
11508 +void SelectToMatchingCharacter(WindowInfo *window)
11510 + int pos;
11511 + int startPos, endPos, matchPos, matchLen;
11512 + int direction;
11513 + textBuffer *buf = window->buffer;
11515 + /* Pattern Match Feature: get position of the character to match */
11516 + pos = getPosForMatchingCharacter(window);
11518 /* Search for it in the buffer */
11519 - if (!findMatchingChar(window, BufGetCharacter(buf, selStart),
11520 - GetHighlightInfo(window, selStart), selStart, 0, buf->length, &matchPos)) {
11521 + if (!FindMatchingString(window, MT_SELECT, &pos, 0,
11522 + buf->length, &matchPos, &matchLen, &direction)) {
11523 XBell(TheDisplay, 0);
11524 return;
11526 - startPos = (matchPos > selStart) ? selStart : matchPos;
11527 - endPos = (matchPos > selStart) ? matchPos : selStart;
11528 + startPos = (matchPos > pos) ? pos : matchPos;
11529 + endPos = (matchPos > pos) ? matchPos : pos;
11531 /* temporarily shut off autoShowInsertPos before setting the cursor
11532 position so MakeSelectionVisible gets a chance to place the cursor
11533 @@ -3469,32 +3453,17 @@ void SelectToMatchingCharacter(WindowInf
11535 void GotoMatchingCharacter(WindowInfo *window)
11537 - int selStart, selEnd;
11538 - int matchPos;
11539 + int pos;
11540 + int matchPos, matchLen;
11541 + int direction;
11542 textBuffer *buf = window->buffer;
11544 - /* get the character to match and its position from the selection, or
11545 - the character before the insert point if nothing is selected.
11546 - Give up if too many characters are selected */
11547 - if (!GetSimpleSelection(buf, &selStart, &selEnd)) {
11548 - selEnd = TextGetCursorPos(window->lastFocus);
11549 - if (window->overstrike)
11550 - selEnd += 1;
11551 - selStart = selEnd - 1;
11552 - if (selStart < 0) {
11553 - XBell(TheDisplay, 0);
11554 - return;
11557 - if ((selEnd - selStart) != 1) {
11558 - XBell(TheDisplay, 0);
11559 - return;
11561 + /* Pattern Match Feature: get position of the character to match */
11562 + pos = getPosForMatchingCharacter(window);
11564 /* Search for it in the buffer */
11565 - if (!findMatchingChar(window, BufGetCharacter(buf, selStart),
11566 - GetHighlightInfo(window, selStart), selStart, 0,
11567 - buf->length, &matchPos)) {
11568 + if (!FindMatchingString(window, MT_GOTO, &pos, 0,
11569 + buf->length, &matchPos, &matchLen, &direction)) {
11570 XBell(TheDisplay, 0);
11571 return;
11573 @@ -3505,77 +3474,11 @@ void GotoMatchingCharacter(WindowInfo *w
11574 be automatically scrolled on screen and MakeSelectionVisible would do
11575 nothing) */
11576 XtVaSetValues(window->lastFocus, textNautoShowInsertPos, False, NULL);
11577 - TextSetCursorPos(window->lastFocus, matchPos+1);
11578 + TextSetCursorPos(window->lastFocus, matchPos);
11579 MakeSelectionVisible(window, window->lastFocus);
11580 XtVaSetValues(window->lastFocus, textNautoShowInsertPos, True, NULL);
11583 -static int findMatchingChar(WindowInfo *window, char toMatch,
11584 - void* styleToMatch, int charPos, int startLimit, int endLimit,
11585 - int *matchPos)
11587 - int nestDepth, matchIndex, direction, beginPos, pos;
11588 - char matchChar, c;
11589 - void *style = NULL;
11590 - textBuffer *buf = window->buffer;
11591 - int matchSyntaxBased = window->matchSyntaxBased;
11593 - /* If we don't match syntax based, fake a matching style. */
11594 - if (!matchSyntaxBased) style = styleToMatch;
11596 - /* Look up the matching character and match direction */
11597 - for (matchIndex = 0; matchIndex<N_MATCH_CHARS; matchIndex++) {
11598 - if (MatchingChars[matchIndex].c == toMatch)
11599 - break;
11601 - if (matchIndex == N_MATCH_CHARS)
11602 - return FALSE;
11603 - matchChar = MatchingChars[matchIndex].match;
11604 - direction = MatchingChars[matchIndex].direction;
11606 - /* find it in the buffer */
11607 - beginPos = (direction==SEARCH_FORWARD) ? charPos+1 : charPos-1;
11608 - nestDepth = 1;
11609 - if (direction == SEARCH_FORWARD) {
11610 - for (pos=beginPos; pos<endLimit; pos++) {
11611 - c=BufGetCharacter(buf, pos);
11612 - if (c == matchChar) {
11613 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11614 - if (style == styleToMatch) {
11615 - nestDepth--;
11616 - if (nestDepth == 0) {
11617 - *matchPos = pos;
11618 - return TRUE;
11621 - } else if (c == toMatch) {
11622 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11623 - if (style == styleToMatch)
11624 - nestDepth++;
11627 - } else { /* SEARCH_BACKWARD */
11628 - for (pos=beginPos; pos>=startLimit; pos--) {
11629 - c=BufGetCharacter(buf, pos);
11630 - if (c == matchChar) {
11631 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11632 - if (style == styleToMatch) {
11633 - nestDepth--;
11634 - if (nestDepth == 0) {
11635 - *matchPos = pos;
11636 - return TRUE;
11639 - } else if (c == toMatch) {
11640 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11641 - if (style == styleToMatch)
11642 - nestDepth++;
11646 - return FALSE;
11650 ** Xt timer procedure for erasing the matching parenthesis marker.
11652 diff --quilt old/source/smartIndent.c new/source/smartIndent.c
11653 --- old/source/smartIndent.c
11654 +++ new/source/smartIndent.c
11655 @@ -980,9 +980,9 @@ void EditSmartIndentMacros(WindowInfo *w
11656 XmNtopPosition, 1,
11657 XmNrightAttachment, XmATTACH_POSITION,
11658 XmNrightPosition, 99, NULL);
11660 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
11661 SmartIndentDialog.lmPulldown = CreateLanguageModeMenu(lmForm, langModeCB,
11662 - NULL);
11663 + NULL, FALSE);
11664 n = 0;
11665 XtSetArg(args[n], XmNspacing, 0); n++;
11666 XtSetArg(args[n], XmNmarginWidth, 0); n++;
11667 @@ -2152,8 +2152,9 @@ void UpdateLangModeMenuSmartIndent(void)
11668 return;
11670 oldMenu = SmartIndentDialog.lmPulldown;
11671 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
11672 SmartIndentDialog.lmPulldown = CreateLanguageModeMenu(
11673 - XtParent(XtParent(oldMenu)), langModeCB, NULL);
11674 + XtParent(XtParent(oldMenu)), langModeCB, NULL, FALSE);
11675 XtVaSetValues(XmOptionButtonGadget(SmartIndentDialog.lmOptMenu),
11676 XmNsubMenuId, SmartIndentDialog.lmPulldown, NULL);
11677 SetLangModeMenu(SmartIndentDialog.lmOptMenu, SmartIndentDialog.langModeName);
11678 diff --quilt old/source/window.c new/source/window.c
11679 --- old/source/window.c
11680 +++ new/source/window.c
11681 @@ -55,6 +55,7 @@ static const char CVSID[] = "$Id: window
11682 #include "windowTitle.h"
11683 #include "interpret.h"
11684 #include "rangeset.h"
11685 +#include "patternMatchData.h"
11686 #include "../util/clearcase.h"
11687 #include "../util/misc.h"
11688 #include "../util/fileUtils.h"
11689 @@ -277,7 +278,6 @@ WindowInfo *CreateWindow(const char *nam
11690 window->showWrapMargin = GetPrefShowWrapMargin();
11691 window->overstrike = False;
11692 window->showMatchingStyle = GetPrefShowMatching();
11693 - window->matchSyntaxBased = GetPrefMatchSyntaxBased();
11694 window->showStats = GetPrefStatsLine();
11695 window->showISearchLine = GetPrefISearchLine();
11696 window->showLineNumbers = GetPrefLineNums();
11697 @@ -316,6 +316,10 @@ WindowInfo *CreateWindow(const char *nam
11698 window->macroCmdData = NULL;
11699 window->smartIndentData = NULL;
11700 window->languageMode = PLAIN_LANGUAGE_MODE;
11702 + /* Pattern Match Feature: assign "PLAIN" string match table*/
11703 + window->stringMatchTable = FindStringMatchTable(NULL);
11705 window->iSearchHistIndex = 0;
11706 window->iSearchStartPos = -1;
11707 window->replaceLastRegexCase = TRUE;
11708 @@ -3453,7 +3457,6 @@ WindowInfo* CreateDocument(WindowInfo* s
11709 window->showWrapMargin = GetPrefShowWrapMargin();
11710 window->overstrike = False;
11711 window->showMatchingStyle = GetPrefShowMatching();
11712 - window->matchSyntaxBased = GetPrefMatchSyntaxBased();
11713 window->highlightSyntax = GetPrefHighlightSyntax();
11714 window->backlightCharTypes = NULL;
11715 window->backlightChars = GetPrefBacklightChars();
11716 @@ -3488,6 +3491,12 @@ WindowInfo* CreateDocument(WindowInfo* s
11717 window->macroCmdData = NULL;
11718 window->smartIndentData = NULL;
11719 window->languageMode = PLAIN_LANGUAGE_MODE;
11721 + /*
11722 + * Pattern Match Feature:
11723 + */
11724 + window->stringMatchTable = FindStringMatchTable(NULL);
11726 window->iSearchHistIndex = 0;
11727 window->iSearchStartPos = -1;
11728 window->replaceLastRegexCase = TRUE;
11729 @@ -3885,7 +3894,6 @@ void RefreshMenuToggleStates(WindowInfo
11730 #endif
11731 XmToggleButtonSetState(window->autoSaveItem, window->autoSave, False);
11732 XmToggleButtonSetState(window->overtypeModeItem, window->overstrike, False);
11733 - XmToggleButtonSetState(window->matchSyntaxBasedItem, window->matchSyntaxBased, False);
11734 XmToggleButtonSetState(window->readOnlyItem, IS_USER_LOCKED(window->lockReasons), False);
11735 XmToggleButtonSetState(window->transientItem, window->transient, False);
11737 @@ -4449,6 +4457,9 @@ static void cloneDocument(WindowInfo *wi
11738 if (window->highlightSyntax)
11739 StartHighlighting(window, False);
11741 + /* recycle the pattern match data */
11742 + window->stringMatchTable = orgWin->stringMatchTable;
11744 /* copy states of original document */
11745 window->filenameSet = orgWin->filenameSet;
11746 window->fileFormat = orgWin->fileFormat;
11747 @@ -4467,7 +4478,6 @@ static void cloneDocument(WindowInfo *wi
11748 window->wrapMode = orgWin->wrapMode;
11749 SetOverstrike(window, orgWin->overstrike);
11750 window->showMatchingStyle = orgWin->showMatchingStyle;
11751 - window->matchSyntaxBased = orgWin->matchSyntaxBased;
11752 #if 0
11753 window->showStats = orgWin->showStats;
11754 window->showISearchLine = orgWin->showISearchLine;