disable OM2.3.1 by default, enable with make bertw OM231=1
[nedit-bw.git] / matching_patterns.patch
blobb3a2dc5d5e7067b16e0bf3be19dc50c6605cba15
1 From: Uwe Lehnert <ulehnert@users.sourceforge.net>
2 Subject: Matching patterns (keyword matching)
4 Short feature description:
6 'Matching patterns' - in context of the patch - are defined as groups of single
7 characters (like '(', ')'), literal strings (like '#ifdef', '#endif') or even a
8 regular expression (like '\</.*\>', which match to each other.
10 A matching pattern set is a collection of such matching patterns.
12 'Opposite pattern highlighting' (aka 'flashing') or 'Goto Matching' feature are
13 adapted by above patch to use user defineable matching pattern sets i.s.o. a
14 constant table.
16 Alternative start / end patterns as well as 'middle' patterns are allowed
17 (Example 'C preprocessor conditional statement': Start = '#if' or '#ifndef' or
18 '#ifdef'; middle = '#elif' or '#else'; end = '#endif').
20 More info about the 'matching pattern' feature can be found
22 a.) 'FEATURE.txt' document (included in patch tar ball)
23 b.) by selecting menu item
25 'Help' -> 'Features for Programming' -> 'Matching Parentheses'
29 'Help' -> 'Customizing' -> 'Matching Patterns'
31 after patch was applied and NEdit was compiled of course :-)
33 File 'mp041114-V3-0.tar.gz' holds version 3.0 of the matching patterns (keyword
34 matching) patch.
36 Version 3.0 of the patch is based on nedit-5.5 (available at
37 ftp://ftp.nedit.org/pub/NEdit/v5_5/). README.txt (included in patch tar ball)
38 holds hints about how to apply the patch.
40 Changes since Version 2.1:
41 * Adaption of this patch to 'Tabbed Editing Interface'.
42 * New built-in macro subroutine 'get_matching' added.
43 * Bug fixes: NULL pointer exception corrected, if pull-down menu child widgets
44 were already destroyed.
45 * C / C++ pattern: #ifdef statement adapted - whitespaces after '#' are now
46 recognized.
47 * CSS pattern introduced.
48 * Sh Ksh Bash pattern: back quotes added.
49 * XML pattern completely revised.
50 * NEdit Macro pattern: single quotes & '/* .. */' comment removed.
52 ---
54 doc/help.etx | 258 +
55 source/Makefile.common | 6
56 source/Makefile.dependencies | 11
57 source/highlightData.c | 13
58 source/macro.c | 107
59 source/menu.c | 63
60 source/nedit.h | 6
61 source/patternMatch.c | 2202 ++++++++++++
62 source/patternMatch.h | 170
63 source/patternMatchData.c | 7780 +++++++++++++++++++++++++++++++++++++++++++
64 source/patternMatchData.h | 24
65 source/preferences.c | 170
66 source/preferences.h | 4
67 source/search.c | 231 -
68 source/smartIndent.c | 7
69 source/window.c | 18
70 16 files changed, 10773 insertions(+), 297 deletions(-)
72 diff --quilt old/doc/help.etx new/doc/help.etx
73 --- old/doc/help.etx
74 +++ new/doc/help.etx
75 @@ -864,12 +864,13 @@ Programming with NEdit
76 ----------------------
78 Though general in appearance, NEdit has many features intended specifically
79 for programmers. Major programming-related topics are listed in separate
80 sections under the heading: "Features for Programming": Syntax_Highlighting_,
81 - Tabs/Emulated_Tabs_, Finding_Declarations_(ctags)_, Calltips_, and
82 - Auto/Smart_Indent_. Minor topics related to programming are discussed below:
83 + Tabs/Emulated_Tabs_, Matching_Parentheses_, Finding_Declarations_(ctags)_,
84 + Calltips_, and Auto/Smart_Indent_. Minor topics related to programming are
85 + discussed below:
87 3>Language Modes
89 When NEdit initially reads a file, it attempts to determine whether the file
90 is in one of the computer languages that it knows about. Knowing what language
91 @@ -923,30 +924,10 @@ Programming with NEdit
92 Search menu and enter a line number and a column number separated by a
93 comma. (e.g. Enter "100,12" for line 100 column 12.) If you want to go to
94 a column on the current line just leave out the line number. (e.g. Enter
95 ",45" to go the column 45 on the current line.)
97 -3>Matching Parentheses
99 - To help you inspect nested parentheses, brackets, braces, quotes, and other
100 - characters, NEdit has both an automatic parenthesis matching mode, and a Goto
101 - Matching command. Automatic parenthesis matching is activated when you type,
102 - or move the insertion cursor after a parenthesis, bracket, or brace. It
103 - momentarily highlights either the opposite character ('Delimiter') or the
104 - entire expression ('Range') when the opposite character is visible in the
105 - window. To find a matching character anywhere in the file, select it or
106 - position the cursor after it, and choose Goto Matching from the Search menu.
107 - If the character matches itself, such as a quote or slash, select the first
108 - character of the pair. NEdit will match {, (, [, <, ", ', `, /, and \.
109 - Holding the Shift key while typing the accelerator key (Shift+Ctrl+M, by
110 - default), will select all of the text between the matching characters.
112 - When syntax highlighting is enabled, the matching routines can optionally
113 - make use of the syntax information for improved accuracy. In that case,
114 - a brace inside a highlighted string will not match a brace inside a comment,
115 - for instance.
117 3>Opening Included Files
119 The Open Selected command in the File menu understands the C preprocessor's
120 #include syntax, so selecting an #include line and invoking Open Selected will
121 generally find the file referred to, unless doing so depends on the settings of
122 @@ -1220,10 +1201,43 @@ Syntax Highlighting
123 is scrolled in to view. Depending on your system, and the highlight patterns
124 you are using, this may or may not be noticeable. A typing delay is also
125 possible, but unlikely if you are only using the built-in patterns.
126 ----------------------------------------------------------------------
128 +Matching Parentheses
129 +--------------------
131 +3>Matching Parentheses (Patterns)
133 + To help you inspect nested parentheses (e.g. brackets, braces, quotes
134 + etc.) or nested constructs (e.g. "begin" .. "end"), NEdit has both an
135 + automatic parenthesis matching mode, and a Goto Matching command.
137 + A matching pattern can be a single character (like '(', ')'), a literal
138 + string (like '#ifdef', '#endif') or a regular expression (like
139 + '\</.*\>').
141 + Automatic parenthesis matching is activated when you type, or move the
142 + insertion cursor after a parenthesis, bracket, or brace. It momentarily
143 + highlights either the opposite pattern ('Delimiter') or the entire expression
144 + ('Range') when the opposite pattern is visible in the window. To find a
145 + matching pattern anywhere in the file, select it or position the cursor after
146 + it, and choose Goto Matching from the Search menu. If the pattern matches
147 + itself, such as a quote or slash, select the first pattern of the pair.
148 + Holding the Shift key while typing the accelerator key (Shift+Ctrl+M, by
149 + default), will select all of the text between the matching patterns.
151 + When syntax highlighting is enabled, the matching routines can optionally
152 + make use of the syntax information for improved accuracy. In that case,
153 + a brace inside a highlighted string will not match a brace inside a comment,
154 + for instance.
156 + Matching patterns are language dependent. Matching patterns can be
157 + configured by the user. If no matching patterns are available for the
158 + language that you want to use, you can create new patterns relatively quickly.
159 + The Help section "Matching_Patterns_" under "Customizing", has details.
161 Finding Declarations (ctags)
162 ----------------------------
164 NEdit can process tags files generated using the Unix _ctags command or the
165 Exuberant Ctags program. Ctags creates index files correlating names of
166 @@ -2578,13 +2592,10 @@ Macro Subroutines
168 **$show_matching**
169 Contains the current preference for showing matching pairs,
170 such as "[]" and "{}" pairs. Can be "off", "delimiter", or "range".
172 -**$match_syntax_based**
173 - Whether pair matching should use syntax information, if available.
175 **$statistics_line**
176 Has a value of 1 if the statistics line is shown, otherwise 0.
178 **$sub_sep**
179 Contains the value of the array sub-script separation string.
180 @@ -2695,10 +2706,19 @@ Macro Subroutines
182 **get_character( position )**
183 Returns the single character at the position
184 indicated by the first argument to the routine from the current window.
186 +**get_matching( position )**
187 + Find a matching pattern string related to the given position.
188 + Returns info about matching pattern within an array. The array has
189 + the following keys: **pos** (position of the first character of the
190 + matching pattern), **len** (length of the matching pattern), **direction**
191 + (direction where the matching pattern was found: ~0~ = forward;
192 + ~1~ = backward). If no matching pattern was found, then array element
193 + of **pos** holds ~-1~, **len** holds ~0~ and **direction** holds ~-1~.
195 **get_range( start, end )**
196 Returns the text between a starting and ending position from the current
197 window.
199 **get_selection()**
200 @@ -3404,13 +3424,10 @@ Action Routines
201 If no parameters are supplied the option is toggled.
203 **set_show_matching( "off" | "delimiter" | "range" )**
204 Set show matching (...) mode for the current window.
206 -**set_match_syntax_based( [0 | 1] )**
207 - Set whether matching should be syntax based for the current window.
209 **set_statistics_line( [0 | 1] )**
210 Show or hide the statistics line for the current window.
211 A value of 0 turns it off and a value of 1 turns it on.
212 If no parameters are supplied the option is toggled.
214 @@ -3938,14 +3955,10 @@ Preferences
215 range between them, when one of these characters is typed, or when the
216 insertion cursor is positioned after it. Delimiter only highlights the
217 matching delimiter, while Range highlights the whole range of text between
218 the matching delimiters.
220 - Optionally, the matching can make use of syntax information if syntax
221 - highlighting is enabled. Alternatively, the matching is purely character
222 - based. In general, syntax based matching results in fewer false matches.
224 **Overtype**
225 In overtype mode, new characters entered replace the characters in front of
226 the insertion cursor, rather than being inserted before them.
228 **Read Only**
229 @@ -5047,10 +5060,189 @@ Smart Indent Macros
230 before the character is inserted into the buffer. You can do just about
231 anything here, but keep in mind that this macro is executed for every
232 keystroke typed, so if you try to get too fancy, you may degrade performance.
233 ----------------------------------------------------------------------
235 +Matching Patterns
236 +-----------------
238 +3>Writing Matching Pattern Sets
240 + Matching Patterns Sets are groups of single characters (like '(', ')'),
241 + literal strings (like '#ifdef', '#endif') or a regular expressions (like
242 + '\</.*\>'), which match to each other.
244 + Examples: An open bracket '(' belongs a closing one ')'.
245 + Or: '#ifdef'(start), '#ifndef'(alternative start), '#ifndef' (another
246 + alternative start),'#elif' (optional), '#else' (optional), '#endif' (end)
247 + define a "#ifdef statement matching pattern".
249 + "Opposite pattern highlighting" or "Goto Matching" features are implemented
250 + in NEdit using this matching pattern sets (see Matching_Parentheses_ under
251 + the heading of Features for Programming).
253 + During definition of a new language mode a standard matching pattern set
254 + is assigned to this new language mode.
256 + To modify a matching pattern set, select "Matching Patterns ..." from
257 + "Show Matching (..)" sub-section of the "Default Settings" sub-menu
258 + of the "Preferences" menu.
260 + A matching pattern set is a collection of matching patterns.
262 + A matching pattern usually consists out of string patterns.
264 + The name of a matching pattern set needs to be defined within field "Matching
265 + Pattern Name".
267 +4>Attributes of matching pattern
269 + A matching pattern holds two types of attributes:
271 +* "Matching Pattern Type" and
272 +* "Global Attributes"
274 + The matching pattern type specifies the kind of the matching pattern
275 + entry:
277 +* "Individual" or
278 +* "Sub-pattern" or
279 +* "Context group"
281 + Each matching pattern can be defined as "Individual" or as "Sub-pattern".
282 + A "Sub-pattern" belongs to a context group. A context group is simply a
283 + collection of sub-patterns.
285 + During search for a corresponding pattern, an "Individual" matching pattern
286 + does not care about nesting of other matching patterns.
288 + If a matching pattern out of a "Context group" is searched, then all
289 + sub-pattern sets defined in this group are taken into account during the
290 + search.
292 + In fact, "Individual" matching pattern search is faster than "Context group" /
293 + "Sub-pattern" search. "Context group" / "Sub-pattern" search results in fewer
294 + false matches.
296 + To define a context group, set "Matching Pattern Type" to "Context group".
297 + Select out of "Sub-Pattern Name" pop-up field all sub-patterns, which
298 + should be placed into this group. **Note**: all "Sub-pattern" used by a context
299 + group must be defined **before** the context group itself.
301 + "Global Attributes" of a matching pattern are
303 +* "Skip content between start / end pattern"
304 +* "Flash matching pattern"
305 +* "Syntax based"
307 + If "Skip content between start / end pattern" is checked, then all text
308 + between the first / last string pattern of the related matching pattern is
309 + not scanned for other string patterns. This is useful for specifying comments.
311 + "Flash matching pattern" indicates, if the string patterns are flashed during
312 + typing. If not checked, then only the "Goto Matching" feature works for the
313 + related matching pattern. Note: if lots of "Flash matching pattern" are
314 + specified, then this may slow down the performance of NEdit: after each
315 + character typed all "Flash matching pattern" are scanned for being
316 + applicable ...
318 + "Syntax based" defines, if the matching pattern can make use of syntax
319 + information if syntax highlighting is enabled. Alternatively, the matching is
320 + purely character based. In general, syntax based matching results in fewer
321 + false matches.
323 +4>Content of matching pattern
325 + An "Individual" pattern or a "Sub-pattern" may consist out of only one string
326 + pattern (e.g. double quotes '"'). Such a pattern is called "mono pattern".
327 + You can imagine, that a match for a mono pattern is hard to find. A matching
328 + mono pattern search is always started in forward direction. If no match is
329 + found in forward direction, a backward search is started. If the "Global
330 + Attribute" "Syntax based" is selected for a mono pattern, then the character
331 + before / after the match is checked to have the same highlighting style than
332 + the pattern itself. This may help to determine the correct match for a mono
333 + pattern.
335 + Usually a matching pattern holds two string patterns (e.g. 'begin' and
336 + 'end'). One ('begin') is the start pattern. The other one ('end') is the
337 + end pattern. If the cursor is located behind the start pattern, then a
338 + corresponding end pattern is searched (in forward direction). If the
339 + cursor is located behind the end pattern, then a start pattern is search
340 + (in backward direction):
342 +! +--> start ---> end --+
343 +! +-----------<---------+
345 + Alternative start / end patterns can be defined. In this case one of the
346 + start / end patterns must be in front of the cursor to detect one of the
347 + related end / start patterns:
349 +! +-> start1 -+ +-> end1 -+
350 +! +-+-> start2 -+---+ +--+
351 +! + +-> start3 -+ +-> end2 -+ |
352 +! +---------------<-------------+
354 + At least also "middle" patterns can be defined (e.g. middle patterns
355 + 'elif' or 'else'). If the cursor is located behind a middle pattern then a
356 + next middle pattern or the end pattern is searched in forward direction:
358 +! +-----<-----+
359 +! +--> start -+-> middle -+-> end --+
360 +! +-----------<---------------------+
362 +4>String pattern
364 + A string pattern holds three attributes:
366 +* "String Pattern Type"
367 +* "Word Boundary"
368 +* "String Attributes"
370 + String Pattern Type specifies if the related string pattern is
371 + a "start", middle, or "end" pattern (see above).
373 + Word boundary defines, if before / after a string pattern a delimiter must be
374 + located ("Both" = pattern is framed by delimiters. "Left" = before pattern
375 + must be a delimiter. "Right" = after pattern must be a delimiter. "None" =
376 + there must be no delimiter before or after pattern).
378 + There are two "String Attributes":
380 +* "Case Sensitive"
381 +* "Regular Expression"
383 + If "Case Sensitive" is checked (= default), then the matching pattern search
384 + concerning this string pattern differs between upper / lower case of the
385 + characters. If "Case Sensitive" is not set, then the case of the checked
386 + characters is not considered.
388 + "Regular Expression" indicates, that string pattern is treated as
389 + regular expression (if "Regular Expression" is checked) or as literal
390 + string (if "Regular Expression" is not checked).
392 +4>Regular Expression String Pattern
394 + Syntax of regular expression is described by NEdit Help menu item
395 + Regular_Expressions_. Following deviations from this syntax are
396 + existing concerning string patterns:
398 +5>Capturing Parentheses
400 + Capturing Parentheses inside string patterns are of the form `(*n<regex>)',
401 + where n = 1 .. 9. Standard "capturing parentheses" of form `(<regex>)' are
402 + treated as "non-capturing parentheses" by the matching pattern feature.
403 + "n" defines the **global** backreference number, which can be used inside any string
404 + pattern of the same matching pattern (= set of string patterns). So
405 + matching patterns like "\<(*1[^/>])\>" (start string pattern) and "\</\1\>"
406 + (end string pattern) are possible. This matching pattern will match e.g.
407 + <body> .. </body> but will not match <body> .. </head>.
409 +5>Non-Capturing Parentheses
411 + As described above: parentheses constructs like (<regex>) are treated
412 + as `(?:<regex>)' (non-capturing parentheses) by the matching pattern feature.
414 NEdit Command Line
415 ------------------
417 .. ? help !!#ifndef VMS
418 **nedit** [-**read**] [-**create**] [-**line** n | +n] [-**server**]
419 @@ -6077,10 +6269,11 @@ Problems/Defects
420 .. Menu: Features for Programming # features
421 .. Menu: Programming with NEdit # programmer
422 .. Menu: Tabs/Emulated Tabs # tabs
423 .. Menu: Auto/Smart Indent # indent
424 .. Menu: Syntax Highlighting # syntax
425 +.. Menu: Matching Parentheses # pattern_matching
426 .. Menu: Finding Declarations (ctags) # tags
427 .. Menu: Calltips # calltips
429 .. Menu: Regular Expressions # regex
430 .. Menu: Basic Regular Expression Syntax # basicSyntax
431 @@ -6104,10 +6297,11 @@ Problems/Defects
432 .. Menu: Preferences # preferences
433 .. Menu: X Resources # resources
434 .. Menu: Key Binding # binding
435 .. Menu: Highlighting Patterns # patterns
436 .. Menu: Smart Indent Macros # smart_indent
437 +.. Menu: Matching Patterns # matching_patterns
439 .. Menu: NEdit Command Line # command_line
440 .. Menu: Client/Server Mode # server
441 .. Menu: Cr_a_sh Recovery # recovery
442 .. Menu: ---------------------------------- # separator1
443 diff --quilt old/source/Makefile.common new/source/Makefile.common
444 --- old/source/Makefile.common
445 +++ new/source/Makefile.common
446 @@ -5,11 +5,12 @@
448 OBJS = nedit.o file.o menu.o window.o selection.o search.o undo.o shift.o \
449 help.o preferences.o tags.o userCmds.o shell.o regularExp.o macro.o \
450 text.o textSel.o textDisp.o textBuf.o textDrag.o server.o highlight.o \
451 highlightData.o interpret.o parse.o smartIndent.o regexConvert.o \
452 - rbTree.o windowTitle.o calltips.o server_common.o rangeset.o
453 + rbTree.o windowTitle.o calltips.o server_common.o rangeset.o \
454 + patternMatch.o patternMatchData.o
456 XLTLIB = ../Xlt/libXlt.a
457 XMLLIB = ../Microline/XmL/libXmL.a
459 .c.o:
460 @@ -35,10 +36,13 @@ smartIndent.o: smartIndent.c
461 $(CC) $(CFLAGS) $(BIGGER_STRINGS) -c smartIndent.c -o $@
463 highlightData.o: highlightData.c
464 $(CC) $(CFLAGS) $(BIGGER_STRINGS) -c highlightData.c -o $@
466 +patternMatchData.o: patternMatchData.c
467 + $(CC) $(CFLAGS) $(BIGGER_STRINGS) -c patternMatchData.c -o $@
469 help_topic.h help_data.h: ../doc/help.etx
470 (cd ..; $(MAKE) docs)
472 clean:
473 rm -f $(OBJS) nedit nc nc.o parse.c linkdate.o
474 diff --quilt old/source/Makefile.dependencies new/source/Makefile.dependencies
475 --- old/source/Makefile.dependencies
476 +++ new/source/Makefile.dependencies
477 @@ -85,5 +85,16 @@ window.o: window.c window.h nedit.h text
478 windowTitle.o: windowTitle.c windowTitle.h nedit.h textBuf.h \
479 preferences.h help.h help_topic.h ../util/prefFile.h ../util/misc.h \
480 ../util/DialogF.h ../util/utils.h ../util/fileUtils.h \
481 ../util/clearcase.h
482 parse.c: parse.h textBuf.h nedit.h rbTree.h interpret.h ops.h
483 +patternMatch.o: patternMatch.c regularExp.h \
484 + textBuf.h search.h window.h preferences.h highlight.h\
485 + patternMatch.h patternMatchData.h
486 +patternMatchData.o: patternMatchData.c ../util/DialogF.h ../util/misc.h \
487 + ../util/managedList.h regularExp.h textBuf.h nedit.h window.h \
488 + preferences.h help.h file.h textP.h patternMatch.h patternMatchData.h
489 +macro.o: patternMatch.h regularExp.h
490 +menu.o: patternMatchData.h
491 +preferences.o: patternMatchData.h
492 +search.o: patternMatch.h
493 +window.o: patternMatchData.h
494 diff --quilt old/source/highlightData.c new/source/highlightData.c
495 --- old/source/highlightData.c
496 +++ new/source/highlightData.c
497 @@ -549,11 +549,11 @@ static char *DefaultPatternSets[] = {
498 README:\"NEdit Macro syntax highlighting patterns, version 2.6, maintainer Thorsten Haude, nedit at thorstenhau.de\":::Flag::D\n\
499 Comment:\"#\":\"$\"::Comment::\n\
500 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\
501 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\
502 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\
503 - 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\
504 + 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\
505 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\
506 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\
507 Macro Hooks:\"<(?:(?:pre|post)_(?:open|save)|cursor_moved|modified|(?:losing_)?focus)_hook(?=\\s*\\()\":::Subroutine1::\n\
508 Keyword:\"<(?:break|continue|define|delete|else|for|if|in|return|while)>\":::Keyword::\n\
509 Braces:\"[{}\\[\\]]\":::Keyword::\n\
510 @@ -2344,12 +2344,13 @@ void EditHighlightPatterns(WindowInfo *w
511 XmNtopPosition, 1,
512 XmNrightAttachment, XmATTACH_POSITION,
513 XmNrightPosition, 99,
514 NULL);
516 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
517 HighlightDialog.lmPulldown = CreateLanguageModeMenu(lmForm, langModeCB,
518 - NULL);
519 + NULL, FALSE);
520 n = 0;
521 XtSetArg(args[n], XmNspacing, 0); n++;
522 XtSetArg(args[n], XmNmarginWidth, 0); n++;
523 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
524 XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
525 @@ -2879,12 +2880,13 @@ void UpdateLanguageModeMenu(void)
527 if (HighlightDialog.shell == NULL)
528 return;
530 oldMenu = HighlightDialog.lmPulldown;
531 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
532 HighlightDialog.lmPulldown = CreateLanguageModeMenu(
533 - XtParent(XtParent(oldMenu)), langModeCB, NULL);
534 + XtParent(XtParent(oldMenu)), langModeCB, NULL, FALSE);
535 XtVaSetValues(XmOptionButtonGadget(HighlightDialog.lmOptMenu),
536 XmNsubMenuId, HighlightDialog.lmPulldown, NULL);
537 SetLangModeMenu(HighlightDialog.lmOptMenu, HighlightDialog.langModeName);
539 XtDestroyWidget(oldMenu);
540 @@ -2939,10 +2941,13 @@ static void langModeCB(Widget w, XtPoint
541 "Discard Changes", "Cancel", HighlightDialog.langModeName);
542 if (resp == 3)
544 SetLangModeMenu(HighlightDialog.lmOptMenu,
545 HighlightDialog.langModeName);
547 + freePatternSet(newPatSet);
549 return;
551 if (resp == 1)
553 updatePatternSet();
554 @@ -3038,10 +3043,12 @@ static void restoreCB(Widget w, XtPointe
555 "Are you sure you want to discard\n"
556 "all changes to syntax highlighting\n"
557 "patterns for language mode %s?", "Discard", "Cancel",
558 HighlightDialog.langModeName) == 2)
560 + freePatternSet(defaultPatSet);
562 return;
565 /* if a stored version of the pattern set exists, replace it, if it
566 doesn't, add a new one */
567 diff --quilt old/source/macro.c new/source/macro.c
568 --- old/source/macro.c
569 +++ new/source/macro.c
570 @@ -55,10 +55,12 @@ static const char CVSID[] = "$Id: macro.
571 #include "../util/utils.h"
572 #include "../util/getfiles.h"
573 #include "highlight.h"
574 #include "highlightData.h"
575 #include "rangeset.h"
576 +#include "patternMatch.h"
577 +#include "regularExp.h"
579 #include <stdio.h>
580 #include <stdlib.h>
581 #include <string.h>
582 #include <ctype.h>
583 @@ -306,12 +308,10 @@ static int makeBackupCopyMV(WindowInfo *
584 DataValue *result, char **errMsg);
585 static int incBackupMV(WindowInfo *window, DataValue *argList, int nArgs,
586 DataValue *result, char **errMsg);
587 static int showMatchingMV(WindowInfo *window, DataValue *argList, int nArgs,
588 DataValue *result, char **errMsg);
589 -static int matchSyntaxBasedMV(WindowInfo *window, DataValue *argList, int nArgs,
590 - DataValue *result, char **errMsg);
591 static int overTypeModeMV(WindowInfo *window, DataValue *argList, int nArgs,
592 DataValue *result, char **errMsg);
593 static int readOnlyMV(WindowInfo *window, DataValue *argList, int nArgs,
594 DataValue *result, char **errMsg);
595 static int lockedMV(WindowInfo *window, DataValue *argList, int nArgs,
596 @@ -423,10 +423,14 @@ static int getStyleAtPosMS(WindowInfo *w
597 static int filenameDialogMS(WindowInfo* window, DataValue* argList, int nArgs,
598 DataValue* result, char** errMsg);
599 static int callMS(WindowInfo *window, DataValue *argList,
600 int nArgs, DataValue *result, char **errMsg);
602 +/* Pattern Match Feature */
603 +static int getMatchingMS(WindowInfo *window, DataValue *argList, int nArgs,
604 + DataValue *result, char **errMsg);
606 /* Built-in subroutines and variables for the macro language */
607 static const BuiltInSubrName MacroSubrs[] = {
608 { "length", lengthMS },
609 { "get_range", getRangeMS },
610 { "t_print", tPrintMS },
611 @@ -483,10 +487,11 @@ static const BuiltInSubrName MacroSubrs[
612 { "get_pattern_at_pos", getPatternAtPosMS },
613 { "get_style_by_name", getStyleByNameMS },
614 { "get_style_at_pos", getStyleAtPosMS },
615 { "filename_dialog", filenameDialogMS },
616 { "call", callMS },
617 + { "get_matching", getMatchingMS },
618 { NULL, NULL } /* sentinel */
621 static const BuiltInSubrName SpecialVars[] = {
622 { "$cursor", cursorMV },
623 @@ -512,11 +517,10 @@ static const BuiltInSubrName SpecialVars
624 { "$wrap_text", wrapTextMV },
625 { "$highlight_syntax", highlightSyntaxMV },
626 { "$make_backup_copy", makeBackupCopyMV },
627 { "$incremental_backup", incBackupMV },
628 { "$show_matching", showMatchingMV },
629 - { "$match_syntax_based", matchSyntaxBasedMV },
630 { "$overtype_mode", overTypeModeMV },
631 { "$read_only", readOnlyMV },
632 { "$locked", lockedMV },
633 { "$file_format", fileFormatMV },
634 { "$font_name", fontNameMV },
635 @@ -4456,20 +4460,10 @@ static int showMatchingMV(WindowInfo *wi
636 result->val.str.rep = res;
637 result->val.str.len = strlen(res);
638 return True;
641 -static int matchSyntaxBasedMV(WindowInfo *window, DataValue *argList, int nArgs,
642 - DataValue *result, char **errMsg)
644 - result->tag = INT_TAG;
645 - result->val.n = window->matchSyntaxBased ? 1 : 0;
646 - return True;
651 static int overTypeModeMV(WindowInfo *window, DataValue *argList, int nArgs,
652 DataValue *result, char **errMsg)
654 result->tag = INT_TAG;
655 result->val.n = window->overstrike ? 1 : 0;
656 @@ -5873,10 +5867,97 @@ static int getPatternAtPosMS(WindowInfo
657 return fillPatternResult(result, errMsg, window,
658 HighlightNameOfCode(window, patCode), False, True,
659 HighlightStyleOfCode(window, patCode), bufferPos);
663 +** Pattern Match Feature:
664 +** Find a matching pattern string related to the given position.
666 +** Syntax:
667 +** get_matching(position)
669 +** Returns info about matching pattern within an array. The array has
670 +** the following keys: "pos" (position of the first character of the
671 +** matching pattern), "len" (length of the matching pattern), "direction"
672 +** (direction where the matching pattern was found: "0" = forward;
673 +** "1" = backward). If no matching pattern was found, then array element
674 +** of "pos" holds "-1", "len" holds "0" and "direction" holds "-1".
677 +static int getMatchingMS(WindowInfo *window, DataValue *argList, int nArgs,
678 + DataValue *result, char **errMsg)
680 + int startPos;
681 + int matchPos, matchLen;
682 + int direction;
683 + textBuffer *buf = window->buffer;
684 + DataValue dv;
686 + /*
687 + * Perform syntax & semantic check
688 + */
689 + if (nArgs != 1 )
690 + return wrongNArgsErr(errMsg);
692 + if (!readIntArg(argList[0], &startPos, errMsg))
693 + return False;
695 + startPos ++;
697 + /*
698 + * do the search; provide default values, if search fails
699 + */
700 + if (!FindMatchingString(window, MT_MACRO, &startPos, 0, buf->length,
701 + &matchPos, &matchLen, &direction))
703 + matchPos = -1;
704 + matchLen = 0;
705 + direction = -1;
708 + /*
709 + * initialize array holding info about matching string
710 + */
711 + result->tag = ARRAY_TAG;
712 + result->val.arrayPtr = ArrayNew();
714 + /*
715 + * the following array entries will be integers
716 + */
717 + dv.tag = INT_TAG;
719 + /*
720 + * insert match position
721 + */
722 + dv.val.n = matchPos;
723 + if (!ArrayInsert(result, PERM_ALLOC_STR("pos"), &dv))
725 + M_ARRAY_INSERT_FAILURE();
728 + /*
729 + * insert length of matching pattern
730 + */
731 + dv.val.n = matchLen;
732 + if (!ArrayInsert(result, PERM_ALLOC_STR("len"), &dv))
734 + M_ARRAY_INSERT_FAILURE();
737 + /*
738 + * insert direction where the matching pattern was found
739 + */
740 + dv.val.n = direction;
741 + if (!ArrayInsert(result, PERM_ALLOC_STR("direction"), &dv))
743 + M_ARRAY_INSERT_FAILURE();
746 + return True;
749 static int wrongNArgsErr(char **errMsg)
751 *errMsg = "Wrong number of arguments to function %s";
752 return False;
754 diff --quilt old/source/menu.c new/source/menu.c
755 --- old/source/menu.c
756 +++ new/source/menu.c
757 @@ -47,10 +47,11 @@ static const char CVSID[] = "$Id: menu.c
758 #include "userCmds.h"
759 #include "shell.h"
760 #include "macro.h"
761 #include "highlight.h"
762 #include "highlightData.h"
763 +#include "patternMatchData.h"
764 #include "interpret.h"
765 #include "smartIndent.h"
766 #include "windowTitle.h"
767 #include "regularExp.h"
768 #include "../util/getfiles.h"
769 @@ -131,11 +132,10 @@ static void fontCB(Widget w, WindowInfo
770 static void tabsCB(Widget w, WindowInfo *window, caddr_t callData);
771 static void backlightCharsCB(Widget w, WindowInfo *window, caddr_t callData);
772 static void showMatchingOffCB(Widget w, WindowInfo *window, caddr_t callData);
773 static void showMatchingDelimitCB(Widget w, WindowInfo *window, caddr_t callData);
774 static void showMatchingRangeCB(Widget w, WindowInfo *window, caddr_t callData);
775 -static void matchSyntaxBasedCB(Widget w, WindowInfo *window, caddr_t callData);
776 static void statsCB(Widget w, WindowInfo *window, caddr_t callData);
777 static void autoIndentOffDefCB(Widget w, WindowInfo *window, caddr_t callData);
778 static void autoIndentDefCB(Widget w, WindowInfo *window, caddr_t callData);
779 static void smartIndentDefCB(Widget w, WindowInfo *window, caddr_t callData);
780 static void autoSaveDefCB(Widget w, WindowInfo *window, caddr_t callData);
781 @@ -158,13 +158,13 @@ static void pathInWindowsMenuDefCB(Widge
782 static void customizeTitleDefCB(Widget w, WindowInfo *window, caddr_t callData);
783 static void tabsDefCB(Widget w, WindowInfo *window, caddr_t callData);
784 static void showMatchingOffDefCB(Widget w, WindowInfo *window, caddr_t callData);
785 static void showMatchingDelimitDefCB(Widget w, WindowInfo *window, caddr_t callData);
786 static void showMatchingRangeDefCB(Widget w, WindowInfo *window, caddr_t callData);
787 -static void matchSyntaxBasedDefCB(Widget w, WindowInfo *window, caddr_t callData);
788 static void highlightOffDefCB(Widget w, WindowInfo *window, caddr_t callData);
789 static void highlightDefCB(Widget w, WindowInfo *window, caddr_t callData);
790 +static void matchPatternsDefCB(Widget w, WindowInfo *window, caddr_t callData);
791 static void backlightCharsDefCB(Widget w, WindowInfo *window, caddr_t callData);
792 static void fontDefCB(Widget w, WindowInfo *window, caddr_t callData);
793 static void colorDefCB(Widget w, WindowInfo *window, caddr_t callData);
794 static void smartTagsDefCB(Widget parent, XtPointer client_data, XtPointer call_data);
795 static void showAllTagsDefCB(Widget parent, XtPointer client_data, XtPointer call_data);
796 @@ -407,12 +407,10 @@ static void setMakeBackupCopyAP(Widget w
797 Cardinal *nArgs);
798 static void setIncrementalBackupAP(Widget w, XEvent *event, String *args,
799 Cardinal *nArgs);
800 static void setShowMatchingAP(Widget w, XEvent *event, String *args,
801 Cardinal *nArgs);
802 -static void setMatchSyntaxBasedAP(Widget w, XEvent *event, String *args,
803 - Cardinal *nArgs);
804 static void setOvertypeModeAP(Widget w, XEvent *event, String *args,
805 Cardinal *nArgs);
806 static void setLockedAP(Widget w, XEvent *event, String *args,
807 Cardinal *nArgs);
808 static void setTransientAP(Widget text, XEvent *event, String *args,
809 @@ -582,11 +580,10 @@ static XtActionsRec Actions[] = {
810 #ifndef VMS
811 {"set_make_backup_copy", setMakeBackupCopyAP},
812 #endif
813 {"set_incremental_backup", setIncrementalBackupAP},
814 {"set_show_matching", setShowMatchingAP},
815 - {"set_match_syntax_based", setMatchSyntaxBasedAP},
816 {"set_overtype_mode", setOvertypeModeAP},
817 {"set_locked", setLockedAP},
818 {"set_transient", setTransientAP},
819 {"set_tab_dist", setTabDistAP},
820 {"set_em_tab_dist", setEmTabDistAP},
821 @@ -1028,13 +1025,12 @@ Widget CreateMenuBar(Widget parent, Wind
822 GetPrefShowMatching() == FLASH_DELIMIT, SHORT);
823 window->showMatchingRangeDefItem = createMenuRadioToggle(subSubPane,
824 "range", "Range", 'R', showMatchingRangeDefCB, window,
825 GetPrefShowMatching() == FLASH_RANGE, SHORT);
826 createMenuSeparator(subSubPane, "sep", SHORT);
827 - window->matchSyntaxBasedDefItem = createMenuToggle(subSubPane,
828 - "matchSyntax", "Syntax Based", 'S', matchSyntaxBasedDefCB, window,
829 - GetPrefMatchSyntaxBased(), SHORT);
830 + createMenuItem(subSubPane, "matchPatterns", "Matching Patterns...",
831 + 'M', matchPatternsDefCB, window, FULL);
833 /* Show Cursorline */
834 window->showCursorlineItem = createMenuToggle(subPane,
835 "showCursorlineItem", "Show Cursorline", 'x', showCursorlineCB,
836 NULL, GetPrefShowCursorline(), FULL);
837 @@ -1152,14 +1148,10 @@ Widget CreateMenuBar(Widget parent, Wind
838 "delimiter", "Delimiter", 'D', showMatchingDelimitCB, window,
839 window->showMatchingStyle == FLASH_DELIMIT, SHORT);
840 window->showMatchingRangeItem = createMenuRadioToggle(subPane, "range",
841 "Range", 'R', showMatchingRangeCB, window,
842 window->showMatchingStyle == FLASH_RANGE, SHORT);
843 - createMenuSeparator(subPane, "sep", SHORT);
844 - window->matchSyntaxBasedItem = createMenuToggle(subPane, "matchSyntax",
845 - "Syntax Based", 'S', matchSyntaxBasedCB, window,
846 - window->matchSyntaxBased, SHORT);
848 #ifndef SGI_CUSTOM
849 createMenuSeparator(menuPane, "sep2", SHORT);
850 window->overtypeModeItem = createMenuToggle(menuPane, "overtype", "Overtype", 'O',
851 doActionCB, "set_overtype_mode", False, SHORT);
852 @@ -1687,28 +1679,10 @@ static void showMatchingRangeCB(Widget w
853 ((XmAnyCallbackStruct *)callData)->event);
854 XtCallActionProc(WidgetToWindow(menu)->lastFocus, "set_show_matching",
855 ((XmAnyCallbackStruct *)callData)->event, params, 1);
858 -static void matchSyntaxBasedCB(Widget w, WindowInfo *window, caddr_t callData)
860 - Widget menu = MENU_WIDGET(w);
862 - window = WidgetToWindow(menu);
864 -#ifdef SGI_CUSTOM
865 - if (shortPrefAskDefault(window->shell, w, "Match Syntax Based")) {
866 - matchSyntaxBasedDefCB(w, window, callData);
867 - SaveNEditPrefs(window->shell, GetPrefShortMenus());
869 -#endif
870 - HidePointerOnKeyedEvent(WidgetToWindow(menu)->lastFocus,
871 - ((XmAnyCallbackStruct *)callData)->event);
872 - XtCallActionProc(WidgetToWindow(menu)->lastFocus, "set_match_syntax_based",
873 - ((XmAnyCallbackStruct *)callData)->event, NULL, 0);
876 static void fontCB(Widget w, WindowInfo *window, caddr_t callData)
878 ChooseFonts(WidgetToWindow(MENU_WIDGET(w)), True);
881 @@ -2032,22 +2006,18 @@ static void showMatchingRangeDefCB(Widge
882 XmToggleButtonSetState(win->showMatchingDelimitDefItem, False, False);
883 XmToggleButtonSetState(win->showMatchingRangeDefItem, True, False);
887 -static void matchSyntaxBasedDefCB(Widget w, WindowInfo *window, caddr_t callData)
888 +static void matchPatternsDefCB(Widget w, WindowInfo *window, caddr_t callData)
890 - WindowInfo *win;
892 - int state = XmToggleButtonGetState(w);
893 + Widget menu = MENU_WIDGET(w);
894 + WindowInfo *activeWindow = WidgetToWindow(menu);
896 - /* Set the preference and make the other windows' menus agree */
897 - SetPrefMatchSyntaxBased(state);
898 - for (win=WindowList; win!=NULL; win=win->next) {
899 - if (IsTopDocument(win))
900 - XmToggleButtonSetState(win->matchSyntaxBasedDefItem, state, False);
902 + HidePointerOnKeyedEvent(activeWindow->lastFocus,
903 + ((XmAnyCallbackStruct *)callData)->event);
904 + EditMatchPatterns(activeWindow);
907 static void backlightCharsDefCB(Widget w, WindowInfo *window, caddr_t callData)
909 WindowInfo *win;
910 @@ -4286,23 +4256,10 @@ static void setShowMatchingAP(Widget w,
911 else {
912 fprintf(stderr, "nedit: set_show_matching requires argument\n");
916 -static void setMatchSyntaxBasedAP(Widget w, XEvent *event, String *args,
917 - Cardinal *nArgs)
919 - WindowInfo *window = WidgetToWindow(w);
920 - Boolean newState;
922 - ACTION_BOOL_PARAM_OR_TOGGLE(newState, *nArgs, args, window->matchSyntaxBased, "set_match_syntax_based");
924 - if (IsTopDocument(window))
925 - XmToggleButtonSetState(window->matchSyntaxBasedItem, newState, False);
926 - window->matchSyntaxBased = newState;
929 static void setOvertypeModeAP(Widget w, XEvent *event, String *args,
930 Cardinal *nArgs)
932 WindowInfo *window = WidgetToWindow(w);
933 Boolean newState;
934 diff --quilt old/source/nedit.h new/source/nedit.h
935 --- old/source/nedit.h
936 +++ new/source/nedit.h
937 @@ -364,11 +364,10 @@ typedef struct _WindowInfo {
938 Widget iSearchLineItem;
939 Widget lineNumsItem;
940 Widget showMatchingOffItem;
941 Widget showMatchingDelimitItem;
942 Widget showMatchingRangeItem;
943 - Widget matchSyntaxBasedItem;
944 Widget overtypeModeItem;
945 Widget highlightItem;
946 Widget windowMenuPane;
947 Widget shellMenuPane;
948 Widget macroMenuPane;
949 @@ -390,11 +389,10 @@ typedef struct _WindowInfo {
950 Widget newlineWrapDefItem;
951 Widget contWrapDefItem;
952 Widget showMatchingOffDefItem;
953 Widget showMatchingDelimitDefItem;
954 Widget showMatchingRangeDefItem;
955 - Widget matchSyntaxBasedDefItem;
956 Widget highlightOffDefItem;
957 Widget highlightDefItem;
958 Widget backlightCharsItem;
959 Widget backlightCharsDefItem;
960 Widget searchDlogsDefItem;
961 @@ -510,11 +508,10 @@ typedef struct _WindowInfo {
962 ALWAYS, ON-WRAP as enums */
963 Boolean overstrike; /* is overstrike mode turned on ? */
964 char showMatchingStyle; /* How to show matching parens:
965 NO_FLASH, FLASH_DELIMIT, or
966 FLASH_RANGE */
967 - char matchSyntaxBased; /* Use syntax info to show matching */
968 Boolean showStats; /* is stats line supposed to be shown */
969 Boolean showISearchLine; /* is incr. search line to be shown */
970 Boolean showLineNumbers; /* is the line number display shown */
971 Boolean highlightSyntax; /* is syntax highlighting turned on? */
972 Boolean backlightChars; /* is char backlighting turned on? */
973 @@ -556,10 +553,13 @@ typedef struct _WindowInfo {
974 incremental search bar */
975 Bool iSearchLastLiteralCase; /* idem, for literal mode */
976 Bool findLastRegexCase; /* idem, for regex mode in find dialog */
977 Bool findLastLiteralCase; /* idem, for literal mode */
979 + /* Pattern Match Feature */
980 + void *stringMatchTable; /* match pattern info related to this window */
982 #ifdef REPLACE_SCOPE
983 int replaceScope; /* Current scope for replace dialog */
984 Widget replaceScopeWinToggle; /* Scope for replace = window */
985 Widget replaceScopeSelToggle; /* Scope for replace = selection */
986 Widget replaceScopeMultiToggle;/* Scope for replace = multiple files */
987 diff --quilt /dev/null new/source/patternMatch.c
988 --- /dev/null
989 +++ new/source/patternMatch.c
990 @@ -0,0 +1,2202 @@
991 +static const char CVSID[] = "$Id: patternMatch.c,v 1.4 2003/10/27 21:59:14 uleh Exp $";
992 +/*******************************************************************************
993 +* *
994 +* patternMatch.c -- Nirvana Editor pattern matching functions *
995 +* *
996 +* Copyright (C) 2003-2004, Uwe Lehnert *
997 +* *
998 +* This is free software; you can redistribute it and/or modify it under the *
999 +* terms of the GNU General Public License as published by the Free Software *
1000 +* Foundation; either version 2 of the License, or (at your option) any later *
1001 +* version. In addition, you may distribute versions of this program linked to *
1002 +* Motif or Open Motif. See README for details. *
1003 +* *
1004 +* This software is distributed in the hope that it will be useful, but WITHOUT *
1005 +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
1006 +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
1007 +* for more details. *
1008 +* *
1009 +* You should have received a copy of the GNU General Public License along with *
1010 +* software; if not, write to the Free Software Foundation, Inc., 59 Temple *
1011 +* Place, Suite 330, Boston, MA 02111-1307 USA *
1012 +* *
1013 +* Nirvana Text Editor *
1014 +* October 27, 2004 *
1015 +* *
1016 +* Written by Uwe Lehnert *
1017 +* *
1018 +*******************************************************************************/
1020 +#ifdef HAVE_CONFIG_H
1021 +#include "../config.h"
1022 +#endif
1024 +#include <stdlib.h>
1025 +#include <stdio.h>
1026 +#include <limits.h>
1027 +#include <string.h>
1028 +#include <ctype.h>
1030 +#ifdef VMS
1031 +#include "../util/VMSparam.h"
1032 +#else
1033 +#ifndef __MVS__
1034 +#include <sys/param.h>
1035 +#endif
1036 +#endif /*VMS*/
1038 +#include "regularExp.h"
1039 +#include "textBuf.h"
1040 +#include "search.h"
1041 +#include "window.h"
1042 +#include "preferences.h"
1043 +#include "highlight.h"
1045 +#include "patternMatch.h"
1046 +#include "patternMatchData.h"
1048 +#ifdef HAVE_DEBUG_H
1049 +#include "../debug.h"
1050 +#endif
1052 +#define MAX_NESTED_PATTERNS 100
1054 +#define IGNORE_HIGHLIGHT_CODE -1
1056 +typedef struct _SearchRegionInfo {
1057 + WindowInfo *sriWindow;
1058 + char *sriText;
1059 + char sriPrevChar;
1060 + char sriSuccChar;
1061 + int sriStartOfTextPos;
1062 +} SearchRegionInfo;
1064 +typedef struct _FoundStringInfo {
1065 + char *fsiStartPtr;
1066 + char *fsiEndPtr;
1067 + int fsiLength;
1068 + char fsiPrevChar;
1069 + char fsiSuccChar;
1070 + const char *fsiDelimiters;
1071 +} FoundStringInfo;
1073 +typedef struct _BackRefInfo {
1074 + int briAvailable;
1075 + int briCaseInsensitive;
1076 + char *briStartPtr[MAX_GLOBAL_BACK_REF_ID];
1077 + char *briEndPtr[MAX_GLOBAL_BACK_REF_ID];
1078 +} BackRefInfo;
1080 +typedef struct _MatchingElementInfo {
1081 + MatchPatternTableElement *meiElement;
1082 + PatternReference meiPatRef;
1083 + int meiDirection;
1084 + int meiHighLightCode;
1085 + int meiAbsStartPos;
1086 + int meiLength;
1087 + BackRefInfo meiBackRefInfo;
1088 +} MatchingElementInfo;
1090 +typedef struct _PatternStackElement {
1091 + PatternReference psePatRef;
1092 + int pseHighLightCode;
1093 + BackRefInfo pseBackRefInfo;
1094 +} PatternStackElement;
1097 + * Prototypes of local functions
1098 + */
1099 +void adaptPatternPositions(
1100 + MatchingType matchingType,
1101 + int direction,
1102 + int *charPos,
1103 + int startPatternLength,
1104 + int *matchPos,
1105 + int matchedPatternLength);
1107 +static int findMatchingStringElement(
1108 + StringMatchTable *smTable,
1109 + SearchRegionInfo *searchRegion,
1110 + MatchingElementInfo *matchInfo,
1111 + int *charPos,
1112 + const char *delimiters);
1114 +static PatternElementMonoInfo determineMonoPatInfo(
1115 + WindowInfo *window,
1116 + int patHighLightCode,
1117 + int leftPos,
1118 + int rightPos,
1119 + PatternElementKind *patElementKind);
1121 +static void assignBackRefInfo(
1122 + StringPattern *strPat,
1123 + BackRefInfo *backRefInfo);
1124 +static int doesBackRefInfoMatch(
1125 + BackRefInfo *backRefInfo1,
1126 + BackRefInfo *backRefInfo2);
1127 +static int compareBackRef(
1128 + char *startPtr1,
1129 + char *endPtr1,
1130 + char *startPtr2,
1131 + char *endPtr2,
1132 + int caseInsensitive);
1134 +static int doesPatternElementMatch(
1135 + PatternElement *patElement,
1136 + FoundStringInfo *foundStringInfo,
1137 + BackRefInfo *backRefInfo);
1138 +static int doesMPTableElementMatch(
1139 + MatchPatternTableElement *element,
1140 + FoundStringInfo *foundStringInfo,
1141 + PatternElementKind *patternElementKind,
1142 + int *patternElementIdx,
1143 + BackRefInfo *backRefInfo);
1144 +static int getPatternInfo(
1145 + MatchPatternTable *table,
1146 + FoundStringInfo *foundStringInfo,
1147 + PatternReference *patRef,
1148 + BackRefInfo *backRefInfo);
1150 +static int isPartOfPattern(
1151 + MatchPatternTable *table,
1152 + int parentElementIdx,
1153 + int childElementIdx,
1154 + PatternElementKind patElementKind);
1155 +static int isPartOfPatternElementSet(
1156 + PatternElementSet *patElementSet,
1157 + int patternElementIdx);
1158 +static int isPartOfMiddlePatternElementSet(
1159 + PatternElementSet *patElementSet,
1160 + int patternElementIdx);
1161 +static void considerNextPatternReference(
1162 + MatchPatternTable *table,
1163 + PatternReference *startPatRef,
1164 + PatternReference nxtPatRef,
1165 + int groupIdx);
1167 +static int searchPatternForward(
1168 + MatchPatternTable *table,
1169 + regexp *compiledRE,
1170 + SearchRegionInfo *searchRegion,
1171 + const char *delimiters,
1172 + int beginPos,
1173 + int *matchEndPos,
1174 + PatternReference *patRef,
1175 + int *highLightCode,
1176 + BackRefInfo *backRefInfo);
1177 +static int searchPatternBackward(
1178 + MatchPatternTable *table,
1179 + regexp *compiledRE,
1180 + SearchRegionInfo *searchRegion,
1181 + const char *delimiters,
1182 + int beginPos,
1183 + PatternReference *patRef,
1184 + int *highLightCode,
1185 + int *matchedPatternLength,
1186 + BackRefInfo *backRefInfo);
1188 +static int parseStringElementForward(
1189 + MatchingElementInfo *matchInfo,
1190 + SearchRegionInfo *searchRegion,
1191 + int relCharPos,
1192 + int *matchPos,
1193 + int *matchedPatternLength,
1194 + const char *delimiters);
1195 +static int findRelatedForwardPattern(
1196 + StringMatchTable *table,
1197 + SearchRegionInfo *searchRegion,
1198 + const char *delimiters,
1199 + PatternReference beginPatRef,
1200 + int beginPatHighLightCode,
1201 + BackRefInfo *beginPatBackRefInfo,
1202 + int beginPos,
1203 + int *matchEndPos);
1205 +static int parseStringElementBackward(
1206 + MatchingElementInfo *matchInfo,
1207 + SearchRegionInfo *searchRegion,
1208 + int relCharPos,
1209 + int *matchPos,
1210 + int *matchedPatternLength,
1211 + const char *delimiters);
1212 +static int findRelatedStartPattern(
1213 + StringMatchTable *table,
1214 + SearchRegionInfo *searchRegion,
1215 + const char *delimiters,
1216 + PatternReference beginPatRef,
1217 + int beginPatHighLightCode,
1218 + BackRefInfo *beginPatBackRefInfo,
1219 + int beginPos,
1220 + int *matchedPatternLength);
1221 +static void considerStackPatReference(
1222 + PatternElementSet *patSet,
1223 + int stackElementIdx,
1224 + int *foundElementIdx);
1226 +static int getPatternLocatedAtPos(
1227 + regexp *usedPatRE,
1228 + MatchPatternTable *table,
1229 + SearchRegionInfo *searchRegion,
1230 + int *relBeginPos,
1231 + MatchingElementInfo *matchInfo,
1232 + const char *delimiters);
1233 +static int getMatchedElementInfo(
1234 + WindowInfo *window,
1235 + MatchPatternTable *table,
1236 + FoundStringInfo *foundStringInfo,
1237 + MatchingElementInfo *matchInfo);
1239 +static PatternElement *getPatternOfReference(
1240 + MatchPatternTable *table,
1241 + PatternReference patRef);
1243 +#ifdef DEBUG_FIND
1244 +static char *getPatternForDebug(
1245 + MatchPatternTable *table,
1246 + PatternReference patRef );
1247 +static char *patElemKindToString(
1248 + PatternElementKind patElemKind);
1249 +static void printFoundStringForDebug(
1250 + WindowInfo *window,
1251 + int absStartPos,
1252 + int length);
1253 +#endif
1256 +** Try to find a matching pattern string related to the given "charPos"
1257 +** inside the given range (defined by startLimit & endLimit).
1258 +** Determine the matching position & the match pattern length (depending
1259 +** on given matchingType), if a matching pattern was found.
1260 +** Returns true, if a matching pattern string was found.
1262 +int FindMatchingString(
1263 + WindowInfo *window,
1264 + MatchingType matchingType,
1265 + int *charPos,
1266 + int startLimit,
1267 + int endLimit,
1268 + int *matchPos,
1269 + int *matchedPatternLength,
1270 + int *direction)
1272 + StringMatchTable *smTable = (StringMatchTable *)window->stringMatchTable;
1273 + const char *delimiters;
1274 + SearchRegionInfo searchRegion;
1275 + MatchingElementInfo matchInfo;
1276 + int matchingPatternFound = FALSE;
1277 + int relCharPos;
1279 + if (smTable == NULL || smTable->smtAllPatRE == NULL)
1281 + /*
1282 + * No match pattern table available:
1283 + */
1284 + return FALSE;
1287 + /*
1288 + * Get delimiters related to window
1289 + */
1290 + delimiters = GetWindowDelimiters(window);
1291 + if (delimiters == NULL)
1292 + delimiters = GetPrefDelimiters();
1294 + /*
1295 + * Select the start pattern reg. exp. to use
1296 + */
1297 + if (matchingType == MT_FLASH_RANGE ||
1298 + matchingType == MT_FLASH_DELIMIT)
1300 + smTable->smtUsedPatRE = smTable->smtFlashPatRE;
1302 + else
1304 + smTable->smtUsedPatRE = smTable->smtAllPatRE;
1307 + /*
1308 + * Get a copy of the text buffer area to parse
1309 + */
1310 + searchRegion.sriWindow = window;
1311 + searchRegion.sriText = BufGetRange(window->buffer, startLimit, endLimit);
1312 + searchRegion.sriPrevChar = BufGetCharacter(window->buffer, startLimit - 1);
1313 + searchRegion.sriSuccChar = BufGetCharacter(window->buffer, endLimit);
1314 + searchRegion.sriStartOfTextPos = startLimit;
1316 + relCharPos = *charPos - startLimit;
1318 + /*
1319 + * Try to find a matching pattern string using string match table
1320 + * of window
1321 + */
1322 + if (findMatchingStringElement(
1323 + smTable,
1324 + &searchRegion,
1325 + &matchInfo,
1326 + &relCharPos,
1327 + delimiters ))
1329 +#ifdef DEBUG_FIND
1330 + printf("--- Start at : ");
1331 + printFoundStringForDebug(
1332 + window,
1333 + matchInfo.meiAbsStartPos,
1334 + matchInfo.meiLength);
1335 + printf(" ---\n");
1336 +#endif
1337 + if (matchInfo.meiDirection == SEARCH_FORWARD)
1339 + matchingPatternFound =
1340 + parseStringElementForward(
1341 + &matchInfo,
1342 + &searchRegion,
1343 + relCharPos,
1344 + matchPos,
1345 + matchedPatternLength,
1346 + delimiters );
1348 + else
1350 + matchingPatternFound =
1351 + parseStringElementBackward(
1352 + &matchInfo,
1353 + &searchRegion,
1354 + relCharPos,
1355 + matchPos,
1356 + matchedPatternLength,
1357 + delimiters );
1360 + if (matchingPatternFound)
1362 + /*
1363 + * Calc. abs. start char pos. (may have been changed if
1364 + * cursor was located inside a string pattern). Adapt
1365 + * pattern positions depending on matchingType.
1366 + */
1367 + *charPos = relCharPos + startLimit;
1368 + *direction = matchInfo.meiDirection;
1370 + adaptPatternPositions(
1371 + matchingType,
1372 + matchInfo.meiDirection,
1373 + charPos,
1374 + matchInfo.meiLength,
1375 + matchPos,
1376 + *matchedPatternLength);
1380 + XtFree(searchRegion.sriText);
1382 + return matchingPatternFound;
1386 +** Adapt match pattern position / start position depending on the
1387 +** given matching type.
1389 +void adaptPatternPositions(
1390 + MatchingType matchingType,
1391 + int direction,
1392 + int *charPos,
1393 + int startPatternLength,
1394 + int *matchPos,
1395 + int matchedPatternLength)
1397 + switch (matchingType)
1399 + case MT_FLASH_DELIMIT:
1400 + case MT_MACRO:
1401 + if (direction == SEARCH_FORWARD)
1403 + (*matchPos) -= matchedPatternLength - 1;
1405 + break;
1407 + case MT_FLASH_RANGE:
1408 + case MT_SELECT:
1409 + if (direction == SEARCH_FORWARD)
1411 + (*charPos) -= startPatternLength;
1413 + else
1415 + (*charPos) --;
1417 + break;
1419 + case MT_GOTO:
1420 + if (direction == SEARCH_FORWARD)
1422 + (*matchPos) ++;
1424 + else
1426 + (*matchPos) += matchedPatternLength;
1428 + break;
1433 +** Try to find a string pattern at given buffer position 'charPos'.
1434 +** A string pattern is found, if pattern is located before 'charPos' or
1435 +** 'charPos' is located within a pattern.
1436 +** If a string pattern is found, then search direction and string pattern
1437 +** reference / properties are determined.
1438 +** Returns true, if a string pattern was found.
1440 +static int findMatchingStringElement(
1441 + StringMatchTable *smTable,
1442 + SearchRegionInfo *searchRegion,
1443 + MatchingElementInfo *matchInfo,
1444 + int *charPos,
1445 + const char *delimiters)
1447 + if (getPatternLocatedAtPos(
1448 + smTable->smtUsedPatRE,
1449 + smTable->smtAllPatterns,
1450 + searchRegion,
1451 + charPos,
1452 + matchInfo,
1453 + delimiters))
1455 + /*
1456 + * Pattern found -> define search direction:
1457 + * - START & MIDDLE pattern: matching pattern is searched in
1458 + * forward direction
1459 + * - END pattern: matching pattern is searched in backward
1460 + * direction
1461 + */
1462 + if (matchInfo->meiPatRef.prKind == PEK_END)
1463 + matchInfo->meiDirection = SEARCH_BACKWARD;
1464 + else
1465 + matchInfo->meiDirection = SEARCH_FORWARD;
1467 + return TRUE;
1470 + return FALSE;
1474 +** Return mono pattern info depending on highlight codes
1475 +** of left / right side of string pattern. Update pattern
1476 +** kind if applicable.
1478 +static PatternElementMonoInfo determineMonoPatInfo(
1479 + WindowInfo *window,
1480 + int patHighLightCode,
1481 + int leftPos,
1482 + int rightPos,
1483 + PatternElementKind *patElementKind)
1485 + int leftSideHasSameHC;
1486 + int rightSideHasSameHC;
1488 + /*
1489 + * Determine, if left side holds same highlight code than
1490 + * found string pattern
1491 + */
1492 + if (leftPos >= 0)
1493 + leftSideHasSameHC =
1494 + (HighlightCodeOfPos(window, leftPos) == patHighLightCode);
1495 + else
1496 + leftSideHasSameHC = FALSE;
1498 + /*
1499 + * Determine, if right side holds same highlight code than
1500 + * found string pattern
1501 + */
1502 + if (rightPos < window->buffer->length)
1503 + rightSideHasSameHC =
1504 + (HighlightCodeOfPos(window, rightPos) == patHighLightCode);
1505 + else
1506 + rightSideHasSameHC = FALSE;
1508 + if ((rightSideHasSameHC && leftSideHasSameHC) ||
1509 + (!rightSideHasSameHC && !leftSideHasSameHC))
1511 + return PEMI_MONO_AMBIGUOUS_SYNTAX;
1513 + else if (leftSideHasSameHC)
1515 + *patElementKind = PEK_END;
1516 + return PEMI_MONO_DEFINITE_SYNTAX;
1518 + else
1520 + *patElementKind = PEK_START;
1521 + return PEMI_MONO_DEFINITE_SYNTAX;
1526 +** Get backref info out of found string pattern and
1527 +** put it into given backRefInfo.
1529 +static void assignBackRefInfo(
1530 + StringPattern *strPat,
1531 + BackRefInfo *backRefInfo)
1533 + int i;
1534 + int localId;
1535 + regexp *patRE = strPat->spTextRE;
1537 + backRefInfo->briAvailable = FALSE;
1538 + backRefInfo->briCaseInsensitive = strPat->spCaseInsensitive;
1540 + for (i=0; i<MAX_GLOBAL_BACK_REF_ID; i++)
1542 + localId = strPat->spGlobalToLocalBackRef[i];
1544 + if (localId != NO_LOCAL_BACK_REF_ID)
1546 + backRefInfo->briAvailable = TRUE;
1548 + backRefInfo->briStartPtr[i] = patRE->startp[localId];
1549 + backRefInfo->briEndPtr[i] = patRE->endp[localId];
1551 + else
1553 + backRefInfo->briStartPtr[i] = NULL;
1554 + backRefInfo->briEndPtr[i] = NULL;
1560 +** Check, if given backref infos match.
1561 +** Returns true, if backref infos match.
1563 +static int doesBackRefInfoMatch(
1564 + BackRefInfo *backRefInfo1,
1565 + BackRefInfo *backRefInfo2)
1567 + int i;
1569 + /*
1570 + * if min. one string pattern doesn't hold backref info, then nothing
1571 + * could be compared -> both string pattern are matching.
1572 + */
1573 + if (!backRefInfo1->briAvailable || !backRefInfo2->briAvailable)
1574 + return TRUE;
1576 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
1578 + if (!compareBackRef(
1579 + backRefInfo1->briStartPtr[i],
1580 + backRefInfo1->briEndPtr[i],
1581 + backRefInfo2->briStartPtr[i],
1582 + backRefInfo2->briEndPtr[i],
1583 + backRefInfo1->briCaseInsensitive || backRefInfo2->briCaseInsensitive))
1585 + return FALSE;
1589 + return TRUE;
1593 +** Compares two backref content.
1594 +** Returns true, if backref contents match.
1596 +static int compareBackRef(
1597 + char *startPtr1,
1598 + char *endPtr1,
1599 + char *startPtr2,
1600 + char *endPtr2,
1601 + int caseInsensitive)
1603 + char *s1;
1604 + char *s2;
1606 + if (startPtr1 == NULL && startPtr2 == NULL)
1607 + return TRUE;
1609 + if (startPtr1 == NULL || startPtr2 == NULL)
1610 + return FALSE;
1612 + if ((endPtr1 - startPtr1) != (endPtr2 - startPtr2))
1613 + return FALSE;
1615 + s1 = startPtr1;
1616 + s2 = startPtr2;
1618 + if (caseInsensitive)
1620 + while (s1 != endPtr1)
1622 + if (tolower((unsigned char)*s1++) != tolower((unsigned char)*s2++))
1623 + return FALSE;
1626 + else
1628 + while (s1 != endPtr1)
1630 + if (*s1++ != *s2++)
1631 + return FALSE;
1634 + return TRUE;
1638 +** Verify if given pattern element is located between given
1639 +** start / end pointer of "foundStringInfo". Assign backreference
1640 +** information, if pattern element matches.
1641 +** Returns true, if given pattern element matches.
1643 +static int doesPatternElementMatch(
1644 + PatternElement *patElement,
1645 + FoundStringInfo *foundStringInfo,
1646 + BackRefInfo *backRefInfo)
1648 + char *s;
1649 + char *p;
1650 + StringPattern *strPat;
1651 + int elementMatch;
1653 + switch (patElement->peType)
1655 + case PET_SINGLE:
1656 + strPat = &patElement->peVal.peuSingle;
1657 + break;
1658 + case PET_MULTIPLE:
1659 + strPat = &patElement->peVal.peuMulti.mpStringPattern;
1660 + break;
1661 + default:
1662 + return FALSE;
1665 + if (strPat->spRegularExpression)
1667 + /*
1668 + * check reg. expression:
1669 + */
1670 + elementMatch =
1671 + ExecRE(
1672 + strPat->spTextRE,
1673 + foundStringInfo->fsiStartPtr,
1674 + foundStringInfo->fsiEndPtr,
1675 + FALSE,
1676 + foundStringInfo->fsiPrevChar,
1677 + foundStringInfo->fsiSuccChar,
1678 + foundStringInfo->fsiDelimiters,
1679 + NULL,
1680 + NULL);
1682 + if (elementMatch)
1683 + assignBackRefInfo(strPat, backRefInfo);
1685 + return elementMatch;
1687 + else
1689 + backRefInfo->briAvailable = FALSE;
1691 + /*
1692 + * check literal string:
1693 + */
1694 + p = strPat->spText;
1696 + /*
1697 + * if length of found string is different from length of
1698 + * given string pattern, then there is no match.
1699 + */
1700 + if (strPat->spLength != foundStringInfo->fsiLength)
1701 + return FALSE;
1703 + s = foundStringInfo->fsiStartPtr;
1705 + if (strPat->spCaseInsensitive)
1707 + while (s != foundStringInfo->fsiEndPtr)
1709 + if (tolower((unsigned char)*s++) != *p++)
1710 + return FALSE;
1713 + else
1715 + while (s != foundStringInfo->fsiEndPtr)
1717 + if (*s++ != *p++)
1718 + return FALSE;
1723 + return TRUE;
1727 +** Verify if a pattern element of given MatchPatternTableElement is
1728 +** located between given start / end pointer of "foundStringInfo".
1729 +** Returns true, if so.
1731 +static int doesMPTableElementMatch(
1732 + MatchPatternTableElement *element,
1733 + FoundStringInfo *foundStringInfo,
1734 + PatternElementKind *patternElementKind,
1735 + int *patternElementIdx,
1736 + BackRefInfo *backRefInfo)
1738 + int i;
1740 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i ++)
1742 + if (doesPatternElementMatch(
1743 + element->mpteAll.pesPattern[i],
1744 + foundStringInfo,
1745 + backRefInfo))
1747 + *patternElementKind = element->mpteAll.pesPattern[i]->peKind;
1748 + *patternElementIdx = i;
1750 + return TRUE;
1754 + return FALSE;
1758 +** Determine the pattern element of given MatchPatternTable, which is
1759 +** located between given start / end pointer of "foundStringInfo".
1760 +** Setup related pattern element reference.
1761 +** Returns true, if a pattern element was found.
1763 +static int getPatternInfo(
1764 + MatchPatternTable *table,
1765 + FoundStringInfo *foundStringInfo,
1766 + PatternReference *patRef,
1767 + BackRefInfo *backRefInfo)
1769 + int i;
1771 + for (i=0; i<table->mptNumberOfElements; i++)
1773 + if (doesMPTableElementMatch(
1774 + table->mptElements[i],
1775 + foundStringInfo,
1776 + &patRef->prKind,
1777 + &patRef->prPatternIdx,
1778 + backRefInfo))
1780 + patRef->prElementIdx = i;
1782 + return TRUE;
1786 + /*
1787 + * Should never been reached !
1788 + */
1789 + patRef->prElementIdx = NO_ELEMENT_IDX;
1790 + patRef->prKind = PEK_UNKNOWN;
1791 + patRef->prPatternIdx = NO_PATTERN_IDX;
1793 + return FALSE;
1797 +** Check, if given child pattern element is part of given
1798 +** parent pattern element.
1799 +** Returns true, if child is part of parent.
1801 +static int isPartOfPattern(
1802 + MatchPatternTable *table,
1803 + int parentElementIdx,
1804 + int childElementIdx,
1805 + PatternElementKind patElementKind)
1807 + MatchPatternTableElement *parent = table->mptElements[parentElementIdx];
1808 + MatchPatternTableElement *child = table->mptElements[childElementIdx];
1810 + if (childElementIdx == parentElementIdx)
1811 + return TRUE;
1813 + if (patElementKind == PEK_START)
1815 + if (isPartOfPatternElementSet(&parent->mpteStart, childElementIdx))
1816 + return TRUE;
1818 + return( isPartOfPatternElementSet(&child->mpteStart, parentElementIdx) );
1820 + else if (patElementKind == PEK_END)
1822 + if (isPartOfPatternElementSet(&parent->mpteEnd, childElementIdx))
1823 + return TRUE;
1825 + return( isPartOfPatternElementSet(&child->mpteEnd, parentElementIdx) );
1827 + else
1829 + /*
1830 + * Given child pattern element is middle pattern: the given pattern element
1831 + * is part of parent pattern, if it's a reference of a middle pattern
1832 + */
1833 + if (isPartOfMiddlePatternElementSet(&parent->mpteMiddle, childElementIdx))
1834 + return TRUE;
1836 + return( isPartOfMiddlePatternElementSet(&child->mpteMiddle, parentElementIdx) );
1841 +** Check, if given pattern element is part of given pattern element set.
1842 +** Returns true, if so.
1844 +static int isPartOfPatternElementSet(
1845 + PatternElementSet *patElementSet,
1846 + int patternElementIdx)
1848 + PatternElement *patElement;
1849 + int i;
1851 + for (i=0; i<patElementSet->pesNumberOfPattern; i++)
1853 + if (patElementSet->pesPattern[i]->peType == PET_REFERENCE)
1855 + patElement = patElementSet->pesPattern[i];
1857 + if (patElement->peVal.peuRef.prElementIdx == patternElementIdx)
1859 + return TRUE;
1864 + return FALSE;
1868 +** Verify, if given pattern element is part of middle pattern set.
1869 +** That's the case, if an element of the pattern set is reference
1870 +** of a middle pattern, which fits to given pattern element.
1871 +** Returns true, if pattern element is part of middle pattern set.
1872 + */
1873 +static int isPartOfMiddlePatternElementSet(
1874 + PatternElementSet *patElementSet,
1875 + int patternElementIdx)
1877 + PatternElement *patElement;
1878 + int i;
1880 + for (i=0; i<patElementSet->pesNumberOfPattern; i++)
1882 + if (patElementSet->pesPattern[i]->peType == PET_REFERENCE)
1884 + patElement = patElementSet->pesPattern[i];
1886 + if (patElement->peVal.peuRef.prElementIdx == patternElementIdx &&
1887 + patElement->peKind == PEK_MIDDLE)
1889 + return TRUE;
1894 + return FALSE;
1898 +** Update start pattern reference depending on next pattern located
1899 +** after start pattern.
1901 +static void considerNextPatternReference(
1902 + MatchPatternTable *table,
1903 + PatternReference *startPatRef,
1904 + PatternReference nxtPatRef,
1905 + int groupIdx)
1907 + MatchPatternTableElement *tabElement;
1908 + PatternElement *startPat;
1909 + MultiPattern *multiStartPat;
1910 + PatternReference patRef;
1911 + int i;
1913 + /*
1914 + * startPatRef needs no adaption, if element index of start pattern
1915 + * and next pattern are equal (i.e. start and next pattern belong
1916 + * to same pattern element).
1917 + */
1918 + if (startPatRef->prElementIdx == nxtPatRef.prElementIdx)
1919 + return;
1921 + /*
1922 + * Verify, if start pattern belongs to multiple pattern elements
1923 + * (like "ELSE .. FI" & "ELSE .. ESAC").
1924 + */
1925 + startPat = getPatternOfReference( table, *startPatRef );
1927 + if (startPat->peType == PET_MULTIPLE)
1929 + /*
1930 + * Check, if next pattern fits to one of the references of
1931 + * the start multi pattern. If so: adapt start pattern reference.
1932 + */
1933 + multiStartPat = &startPat->peVal.peuMulti;
1935 + for (i=0; i<multiStartPat->mpNumberOfReferences; i ++)
1937 + patRef = multiStartPat->mpRefList[i];
1938 + tabElement = table->mptElements[patRef.prElementIdx];
1940 + if (nxtPatRef.prElementIdx == patRef.prElementIdx &&
1941 + tabElement->mpteGroup == groupIdx)
1943 + *startPatRef = patRef;
1944 + return;
1951 +** Search for a string pattern in forward direction, starting at
1952 +** given beginPos. Determine related pattern reference of a found
1953 +** string pattern.
1954 +** Returns true, if a next string pattern was found.
1956 +static int searchPatternForward(
1957 + MatchPatternTable *table,
1958 + regexp *compiledRE,
1959 + SearchRegionInfo *searchRegion,
1960 + const char *delimiters,
1961 + int beginPos,
1962 + int *matchEndPos,
1963 + PatternReference *patRef,
1964 + int *highLightCode,
1965 + BackRefInfo *backRefInfo)
1967 + FoundStringInfo foundStringInfo;
1968 + int matchStartPos;
1969 + int absMatchStartPos;
1970 + MatchPatternTableElement *matchedElement;
1972 + *matchEndPos = -1;
1974 + patRef->prElementIdx = NO_ELEMENT_IDX;
1975 + patRef->prKind = PEK_UNKNOWN;
1976 + patRef->prPatternIdx = NO_PATTERN_IDX;
1978 + *highLightCode = IGNORE_HIGHLIGHT_CODE;
1980 + if (ExecRE(
1981 + compiledRE,
1982 + searchRegion->sriText + beginPos,
1983 + NULL,
1984 + FALSE,
1985 + beginPos==0 ? searchRegion->sriPrevChar : searchRegion->sriText[beginPos-1],
1986 + searchRegion->sriSuccChar,
1987 + delimiters,
1988 + searchRegion->sriText,
1989 + NULL))
1991 + foundStringInfo.fsiStartPtr = compiledRE->startp[0];
1992 + foundStringInfo.fsiEndPtr = compiledRE->endp[0];
1993 + foundStringInfo.fsiLength =
1994 + foundStringInfo.fsiEndPtr - foundStringInfo.fsiStartPtr;
1996 + foundStringInfo.fsiPrevChar =
1997 + foundStringInfo.fsiStartPtr == searchRegion->sriText ?
1998 + searchRegion->sriPrevChar : *(foundStringInfo.fsiStartPtr - 1);
2000 + foundStringInfo.fsiSuccChar =
2001 + *(foundStringInfo.fsiEndPtr) == '\0' ?
2002 + searchRegion->sriSuccChar : *(foundStringInfo.fsiEndPtr);
2004 + foundStringInfo.fsiDelimiters = delimiters;
2006 + if (getPatternInfo(
2007 + table,
2008 + &foundStringInfo,
2009 + patRef,
2010 + backRefInfo))
2012 + /*
2013 + * Next string pattern was found in forward direction and
2014 + * a pattern reference could be assigned to: calculate
2015 + * relative & absolute match positions.
2016 + */
2017 + matchStartPos = foundStringInfo.fsiStartPtr - searchRegion->sriText;
2018 + *matchEndPos = foundStringInfo.fsiEndPtr - searchRegion->sriText;
2020 + absMatchStartPos = matchStartPos + searchRegion->sriStartOfTextPos;
2022 + matchedElement = table->mptElements[patRef->prElementIdx];
2024 + /*
2025 + * get highlight code of found string pattern, if applicable
2026 + */
2027 + if (!matchedElement->mpteIgnoreHighLightInfo)
2029 + *highLightCode =
2030 + HighlightCodeOfPos(searchRegion->sriWindow, absMatchStartPos);
2033 + /*
2034 + * setup mono pattern info of found string pattern
2035 + */
2036 + if (matchedElement->mpteIsMonoPattern)
2038 + if (matchedElement->mpteIgnoreHighLightInfo)
2040 + patRef->prMonoInfo = PEMI_MONO_NOT_SYNTAX_BASED;
2042 + else
2044 + /*
2045 + * determine mono pattern info depending on highLightCodes
2046 + * before / after found string pattern.
2047 + */
2048 + patRef->prMonoInfo =
2049 + determineMonoPatInfo(
2050 + searchRegion->sriWindow,
2051 + *highLightCode,
2052 + absMatchStartPos - 1,
2053 + *matchEndPos + searchRegion->sriStartOfTextPos,
2054 + &patRef->prKind);
2057 + else
2059 + patRef->prMonoInfo = PEMI_NOT_MONO;
2062 + return matchStartPos;
2064 + else
2066 + /*
2067 + * Found string can't be assigned to a pattern element
2068 + * (should never occur).
2069 + */
2070 + return -1;
2073 + else
2075 + /*
2076 + * No next string pattern is found in forward direction.
2077 + */
2078 + return -1;
2083 +** Search for a string pattern in backward direction, starting at
2084 +** given beginPos. Determine related pattern reference of a found
2085 +** string pattern.
2086 +** Returns true, if a next string pattern was found.
2088 +static int searchPatternBackward(
2089 + MatchPatternTable *table,
2090 + regexp *compiledRE,
2091 + SearchRegionInfo *searchRegion,
2092 + const char *delimiters,
2093 + int beginPos,
2094 + PatternReference *patRef,
2095 + int *highLightCode,
2096 + int *matchedPatternLength,
2097 + BackRefInfo *backRefInfo)
2099 + FoundStringInfo foundStringInfo;
2100 + int matchStartPos;
2101 + int absMatchStartPos;
2102 + MatchPatternTableElement *matchedElement;
2104 + patRef->prElementIdx = NO_ELEMENT_IDX;
2105 + patRef->prKind = PEK_UNKNOWN;
2106 + patRef->prPatternIdx = NO_PATTERN_IDX;
2108 + *highLightCode = IGNORE_HIGHLIGHT_CODE;
2110 + if (ExecRE(
2111 + compiledRE,
2112 + searchRegion->sriText,
2113 + searchRegion->sriText + beginPos,
2114 + TRUE,
2115 + searchRegion->sriPrevChar,
2116 + searchRegion->sriText[beginPos] == '\0' ?
2117 + searchRegion->sriSuccChar : searchRegion->sriText[beginPos + 1],
2118 + delimiters,
2119 + searchRegion->sriText,
2120 + NULL))
2122 + foundStringInfo.fsiStartPtr = compiledRE->startp[0];
2123 + foundStringInfo.fsiEndPtr = compiledRE->endp[0];
2124 + foundStringInfo.fsiLength =
2125 + foundStringInfo.fsiEndPtr - foundStringInfo.fsiStartPtr;
2127 + foundStringInfo.fsiPrevChar =
2128 + foundStringInfo.fsiStartPtr == searchRegion->sriText ?
2129 + searchRegion->sriPrevChar : *(foundStringInfo.fsiStartPtr - 1);
2131 + foundStringInfo.fsiSuccChar =
2132 + *(foundStringInfo.fsiEndPtr) == '\0' ?
2133 + searchRegion->sriSuccChar : *(foundStringInfo.fsiEndPtr);
2135 + foundStringInfo.fsiDelimiters = delimiters;
2137 + if (getPatternInfo(
2138 + table,
2139 + &foundStringInfo,
2140 + patRef,
2141 + backRefInfo))
2143 + /*
2144 + * Next string pattern was found in backward direction and
2145 + * a pattern reference could be assigned to: calculate
2146 + * relative & absolute match positions.
2147 + */
2148 + matchStartPos = foundStringInfo.fsiStartPtr - searchRegion->sriText;
2149 + *matchedPatternLength = foundStringInfo.fsiLength;
2151 + absMatchStartPos = matchStartPos + searchRegion->sriStartOfTextPos;
2153 + matchedElement = table->mptElements[patRef->prElementIdx];
2155 + /*
2156 + * get highlight code of found string pattern, if applicable
2157 + */
2158 + if (!matchedElement->mpteIgnoreHighLightInfo)
2160 + *highLightCode =
2161 + HighlightCodeOfPos(searchRegion->sriWindow, absMatchStartPos);
2164 + /*
2165 + * setup mono pattern info of found string pattern
2166 + */
2167 + if (matchedElement->mpteIsMonoPattern)
2169 + if (matchedElement->mpteIgnoreHighLightInfo)
2171 + patRef->prMonoInfo = PEMI_MONO_NOT_SYNTAX_BASED;
2173 + else
2175 + /*
2176 + * determine mono pattern info depending on highLightCodes
2177 + * before / after found string pattern.
2178 + */
2179 + patRef->prMonoInfo =
2180 + determineMonoPatInfo(
2181 + searchRegion->sriWindow,
2182 + *highLightCode,
2183 + absMatchStartPos - 1,
2184 + absMatchStartPos + *matchedPatternLength,
2185 + &patRef->prKind);
2188 + else
2190 + patRef->prMonoInfo = PEMI_NOT_MONO;
2193 + return matchStartPos;
2195 + else
2197 + /*
2198 + * Found string can't be assigned to a pattern element
2199 + * (should never occur).
2200 + */
2201 + return -1;
2204 + else
2206 + /*
2207 + * No next string pattern is found in backward direction.
2208 + */
2209 + return -1;
2214 +** Find matching pattern related to given pattern (stored in
2215 +** 'matchInfo') in forward direction by considering the rules stored in
2216 +** string match table of given window. Determine match position (= abs.
2217 +** pos. of last character of matching string) and length of matching
2218 +** string. If a mono matching pattern couldn't be found in forward
2219 +** direction, then try finding it in backward direction (if found in
2220 +** backward direction, then match position indicates the 1st char. of
2221 +** matching string).
2222 +** Returns true, if a matching pattern was found.
2224 +static int parseStringElementForward(
2225 + MatchingElementInfo *matchInfo,
2226 + SearchRegionInfo *searchRegion,
2227 + int relCharPos,
2228 + int *matchPos,
2229 + int *matchedPatternLength,
2230 + const char *delimiters)
2232 + StringMatchTable *smTable =
2233 + (StringMatchTable *)searchRegion->sriWindow->stringMatchTable;
2234 + MatchPatternTableElement *matchElement = matchInfo->meiElement;
2235 + int beginPos = relCharPos;
2236 + int endStartPos;
2237 + int startStartPos;
2238 + int endEndPos;
2239 + int matchingPatternFound = FALSE;
2241 + /*
2242 + * Find matching pattern within text buffer area to parse in
2243 + * forward direction.
2244 + */
2245 + endStartPos =
2246 + findRelatedForwardPattern(
2247 + smTable,
2248 + searchRegion,
2249 + delimiters,
2250 + matchInfo->meiPatRef,
2251 + matchInfo->meiHighLightCode,
2252 + &matchInfo->meiBackRefInfo,
2253 + beginPos,
2254 + &endEndPos);
2256 + if (endEndPos != -1)
2258 + *matchPos = endEndPos - 1 + searchRegion->sriStartOfTextPos;
2259 + *matchedPatternLength = endEndPos - endStartPos;
2261 + matchingPatternFound = TRUE;
2263 + else if (matchElement->mpteIsMonoPattern)
2265 + /*
2266 + * mono pattern: forward find fails -> try backward direction.
2267 + * Calc. relative position of 1st char. before found string pattern.
2268 + */
2269 + beginPos = beginPos - matchInfo->meiLength - 1;
2271 + if (beginPos > 0)
2273 + startStartPos =
2274 + findRelatedStartPattern(
2275 + smTable,
2276 + searchRegion,
2277 + delimiters,
2278 + matchInfo->meiPatRef,
2279 + matchInfo->meiHighLightCode,
2280 + &matchInfo->meiBackRefInfo,
2281 + beginPos,
2282 + matchedPatternLength);
2284 + if (startStartPos != -1)
2286 + matchInfo->meiDirection = SEARCH_BACKWARD;
2288 + *matchPos = startStartPos + searchRegion->sriStartOfTextPos;
2290 + matchingPatternFound = TRUE;
2295 + return matchingPatternFound;
2299 +** Find matching pattern related to given begin pattern reference
2300 +** in forward direction by considering the rules stored in given
2301 +** string match table. Determine match position (= relative
2302 +** pos. of last character of matching string).
2303 +** Returns -1, if no matching pattern was found. Else the relative
2304 +** position of 1st char. of matching string is returned.
2306 +static int findRelatedForwardPattern(
2307 + StringMatchTable *table,
2308 + SearchRegionInfo *searchRegion,
2309 + const char *delimiters,
2310 + PatternReference beginPatRef,
2311 + int beginPatHighLightCode,
2312 + BackRefInfo *beginPatBackRefInfo,
2313 + int beginPos,
2314 + int *matchEndPos)
2316 + MatchPatternTable *patTable = table->smtAllPatterns;
2317 + int startPos = beginPos;
2318 + int nxtPatStartPos = 0;
2319 + int nxtPatEndPos = 0;
2320 + PatternReference nxtPatRef;
2321 + int nxtPatHighLightCode;
2322 + BackRefInfo nxtPatBackRefInfo;
2323 + PatternStackElement stack[MAX_NESTED_PATTERNS];
2324 + int stackIdx = 0;
2325 + PatternReference startPatRef;
2326 + MatchPatternTableElement *currentElement;
2327 + int groupIdx;
2328 + regexp *groupPatRE;
2329 + regexp *currentPatRE;
2330 + int skipToEnd = FALSE;
2331 + int beginPatternIsMono;
2333 +#ifdef DEBUG_FIND
2334 + printf("Forward Start Pos: %d K: %s EI: %d PI: %d HC: %d <%s>\n",
2335 + startPos,
2336 + patElemKindToString(beginPatRef.prKind),
2337 + beginPatRef.prElementIdx,
2338 + beginPatRef.prPatternIdx,
2339 + beginPatHighLightCode,
2340 + getPatternForDebug(patTable, beginPatRef) );
2341 +#endif
2343 + /*
2344 + * put begin pattern info on stack
2345 + */
2346 + stack[stackIdx].psePatRef = beginPatRef;
2347 + stack[stackIdx].pseHighLightCode = beginPatHighLightCode;
2348 + stack[stackIdx].pseBackRefInfo = *beginPatBackRefInfo;
2349 + stackIdx ++;
2351 + currentElement = patTable->mptElements[beginPatRef.prElementIdx];
2353 + beginPatternIsMono = currentElement->mpteIsMonoPattern;
2355 + groupIdx = currentElement->mpteGroup;
2357 + /*
2358 + * no next pattern can be found, if there is no group assigned
2359 + * to begin pattern (should never occur)
2360 + */
2361 + if (groupIdx == NO_GROUP_IDX)
2363 + *matchEndPos = -1;
2365 + return -1;
2368 + /*
2369 + * Remember pattern (= keywords) regular expression of context
2370 + * group related to begin pattern. Use it for forward search.
2371 + */
2372 + groupPatRE = table->smtGroups[groupIdx]->mpgeKeywordRE;
2373 + currentPatRE = groupPatRE;
2375 + /*
2376 + * Use start / end pattern regular expression if skip to end is
2377 + * set for begin pattern.
2378 + */
2379 + if (currentElement->mpteSkipBtwnStartEnd)
2381 + currentPatRE = currentElement->mpteStartEndRE;
2382 + skipToEnd = TRUE;
2385 + while (stackIdx > 0 && nxtPatStartPos != -1)
2387 + /*
2388 + * Search for next string pattern in forward direction.
2389 + */
2390 + nxtPatStartPos =
2391 + searchPatternForward(
2392 + patTable,
2393 + currentPatRE,
2394 + searchRegion,
2395 + delimiters,
2396 + startPos,
2397 + &nxtPatEndPos,
2398 + &nxtPatRef,
2399 + &nxtPatHighLightCode,
2400 + &nxtPatBackRefInfo );
2402 + startPatRef = stack[stackIdx-1].psePatRef;
2404 + if (nxtPatStartPos == -1)
2406 + /*
2407 + * no next pattern found -> leave loop
2408 + */
2409 +#ifdef DEBUG_FIND
2410 + printf(" SI: %d [start K: %s EI: %d PI %d] Pos: %d --> no next pat. found\n",
2411 + stackIdx,
2412 + patElemKindToString(startPatRef.prKind),
2413 + startPatRef.prElementIdx,
2414 + startPatRef.prPatternIdx,
2415 + startPos);
2416 +#endif
2417 + break;
2420 + /*
2421 + * Update start pattern reference depending on next pattern
2422 + * located after start pattern.
2423 + */
2424 + considerNextPatternReference(
2425 + patTable,
2426 + &startPatRef,
2427 + nxtPatRef,
2428 + groupIdx );
2430 + /*
2431 + * If current found match pattern table element is a mono pattern and
2432 + * skip to start pattern is active, then the found pattern string is
2433 + * a END one in case of ambiguous or no syntax was detected.
2434 + */
2435 + if (skipToEnd &&
2436 + (nxtPatRef.prMonoInfo == PEMI_MONO_AMBIGUOUS_SYNTAX ||
2437 + nxtPatRef.prMonoInfo == PEMI_MONO_NOT_SYNTAX_BASED))
2439 + nxtPatRef.prKind = PEK_END;
2442 +#ifdef DEBUG_FIND
2443 + printf(" SI: %d [start K: %s EI: %d PI %d] Pos: %d-%d K: %s EI: %d PI: %d HC: %d f=<%s> ",
2444 + stackIdx,
2445 + patElemKindToString(startPatRef.prKind),
2446 + startPatRef.prElementIdx,
2447 + startPatRef.prPatternIdx,
2448 + nxtPatStartPos,
2449 + nxtPatEndPos,
2450 + patElemKindToString(nxtPatRef.prKind),
2451 + nxtPatRef.prElementIdx,
2452 + nxtPatRef.prPatternIdx,
2453 + nxtPatHighLightCode,
2454 + getPatternForDebug(patTable, nxtPatRef) );
2455 + printFoundStringForDebug(
2456 + searchRegion->sriWindow,
2457 + nxtPatStartPos + searchRegion->sriStartOfTextPos,
2458 + nxtPatEndPos - nxtPatStartPos);
2459 + printf("\n");
2460 +#endif
2462 + if (nxtPatRef.prKind == PEK_START)
2464 + if (stackIdx >= MAX_NESTED_PATTERNS)
2466 +#ifdef DEBUG_FIND
2467 + printf("FORWARD: MAX. NESTED PATTERN DEPTH REACHED !\n");
2468 +#endif
2469 + nxtPatStartPos = -1;
2470 + nxtPatEndPos = -1;
2472 + else if (!skipToEnd)
2474 + /*
2475 + * Put next pattern on stack, if contents between start /
2476 + * end shouldn't be skipped (if "skipToEnd" is set,
2477 + * a (usually illegal) start pattern to skip inside the
2478 + * skipped one is found (e.g. \* \* ..)
2479 + */
2480 + stack[stackIdx].psePatRef = nxtPatRef;
2481 + stack[stackIdx].pseHighLightCode = nxtPatHighLightCode;
2482 + stack[stackIdx].pseBackRefInfo = nxtPatBackRefInfo;
2483 + stackIdx ++;
2485 + currentElement = patTable->mptElements[nxtPatRef.prElementIdx];
2487 + /*
2488 + * Use start / end pattern regular expression if skip to
2489 + * end is set for found start pattern.
2490 + */
2491 + if (currentElement->mpteSkipBtwnStartEnd)
2493 + currentPatRE = currentElement->mpteStartEndRE;
2494 + skipToEnd = TRUE;
2497 + else if (beginPatternIsMono)
2499 + /*
2500 + * skip to end is set and a mono pattern start is reached:
2501 + * trigger backward search by returning "not found"
2502 + */
2503 +#ifdef DEBUG_FIND
2504 + printf(" ---> mono pattern (re-)start -> trigger backward search\n");
2505 +#endif
2506 + nxtPatStartPos = -1;
2507 + nxtPatEndPos = -1;
2509 +#ifdef DEBUG_FIND
2510 + else
2512 + printf(" ---> skip to end: illegal (re-)start pattern !\n");
2514 +#endif
2516 + else if (nxtPatRef.prKind == PEK_END)
2518 + /*
2519 + * ignore current found pattern, if it doesn't fit to the prev.
2520 + * opened one.
2521 + */
2522 + if (isPartOfPattern(
2523 + patTable,
2524 + nxtPatRef.prElementIdx,
2525 + startPatRef.prElementIdx,
2526 + PEK_END) &&
2527 + (stack[stackIdx - 1].pseHighLightCode == nxtPatHighLightCode ||
2528 + stack[stackIdx - 1].pseHighLightCode == IGNORE_HIGHLIGHT_CODE ||
2529 + nxtPatHighLightCode == IGNORE_HIGHLIGHT_CODE) &&
2530 + doesBackRefInfoMatch(
2531 + &stack[stackIdx - 1].pseBackRefInfo,
2532 + &nxtPatBackRefInfo))
2534 + /*
2535 + * use context group pattern again, if end pattern to skip
2536 + * to was found.
2537 + */
2538 + if (skipToEnd)
2540 + currentPatRE = groupPatRE;
2541 + skipToEnd = FALSE;
2544 + /*
2545 + * pop. related start pattern from stack.
2546 + */
2547 + stackIdx --;
2550 + else if (!skipToEnd)
2552 + /*
2553 + * middle pattern was found: ignore it, if found middle pattern
2554 + * doesn't belong to begin pattern.
2555 + */
2556 + if (stackIdx == 1 &&
2557 + isPartOfPattern(
2558 + patTable,
2559 + startPatRef.prElementIdx,
2560 + nxtPatRef.prElementIdx,
2561 + nxtPatRef.prKind) &&
2562 + (beginPatHighLightCode == nxtPatHighLightCode ||
2563 + beginPatHighLightCode == IGNORE_HIGHLIGHT_CODE ||
2564 + nxtPatHighLightCode == IGNORE_HIGHLIGHT_CODE) &&
2565 + doesBackRefInfoMatch(
2566 + beginPatBackRefInfo,
2567 + &nxtPatBackRefInfo))
2570 + stackIdx --;
2574 + startPos = nxtPatEndPos;
2577 + *matchEndPos = nxtPatEndPos;
2579 + return nxtPatStartPos;
2583 +** Find matching pattern related to given pattern (stored in
2584 +** 'matchInfo') in backward direction by considering the rules stored in
2585 +** string match table of given window. Determine match position (= abs.
2586 +** pos. of 1st character of matching string) and length of matching
2587 +** string.
2588 +** Returns true, if a matching pattern was found.
2590 +static int parseStringElementBackward(
2591 + MatchingElementInfo *matchInfo,
2592 + SearchRegionInfo *searchRegion,
2593 + int relCharPos,
2594 + int *matchPos,
2595 + int *matchedPatternLength,
2596 + const char *delimiters)
2598 + StringMatchTable *smTable =
2599 + (StringMatchTable *)searchRegion->sriWindow->stringMatchTable;
2600 + int beginPos;
2601 + int startStartPos;
2602 + int matchingPatternFound = FALSE;
2604 + /*
2605 + * determine begin of search in string buffer (= relative position
2606 + * of 1st char. before found string pattern.)
2607 + */
2608 + beginPos = relCharPos - matchInfo->meiLength - 1;
2610 + if (beginPos < 0)
2611 + return FALSE;
2613 + /*
2614 + * Find matching pattern within text buffer area to parse in
2615 + * backward direction.
2616 + */
2617 + startStartPos =
2618 + findRelatedStartPattern(
2619 + smTable,
2620 + searchRegion,
2621 + delimiters,
2622 + matchInfo->meiPatRef,
2623 + matchInfo->meiHighLightCode,
2624 + &matchInfo->meiBackRefInfo,
2625 + beginPos,
2626 + matchedPatternLength);
2628 + if (startStartPos != -1)
2630 + *matchPos = startStartPos + searchRegion->sriStartOfTextPos;
2631 + matchingPatternFound = TRUE;
2634 + return matchingPatternFound;
2638 +** Find matching pattern related to given begin pattern reference
2639 +** in backward direction by considering the rules stored in given
2640 +** string match table. Determine match position (= relative
2641 +** pos. of 1st character of matching string).
2642 +** Returns -1, if no matching pattern was found. Else the relative
2643 +** position of 1st char. of matching string is returned.
2645 +static int findRelatedStartPattern(
2646 + StringMatchTable *table,
2647 + SearchRegionInfo *searchRegion,
2648 + const char *delimiters,
2649 + PatternReference beginPatRef,
2650 + int beginPatHighLightCode,
2651 + BackRefInfo *beginPatBackRefInfo,
2652 + int beginPos,
2653 + int *matchedPatternLength)
2655 + MatchPatternTable *patTable = table->smtAllPatterns;
2656 + int startPos = beginPos;
2657 + int prevStartPos = 0;
2658 + PatternReference prevPatRef;
2659 + int prevPatHighLightCode;
2660 + BackRefInfo prevPatBackRefInfo;
2661 + PatternStackElement stack[MAX_NESTED_PATTERNS];
2662 + int stackIdx = 0;
2663 + MatchPatternTableElement *currentElement;
2664 + int groupIdx;
2665 + regexp *groupPatRE;
2666 + regexp *currentPatRE;
2667 + int skipToStart = FALSE;
2669 + /*
2670 + * put begin pattern info on stack
2671 + */
2672 + stack[stackIdx].psePatRef = beginPatRef;
2673 + stack[stackIdx].pseHighLightCode = beginPatHighLightCode;
2674 + stack[stackIdx].pseBackRefInfo = *beginPatBackRefInfo;
2675 + stackIdx ++;
2677 + currentElement = patTable->mptElements[beginPatRef.prElementIdx];
2679 +#ifdef DEBUG_FIND
2680 + printf("Backward Start Pos: %d K: %s EI: %d PI: %d HC: %d <%s>\n",
2681 + startPos,
2682 + patElemKindToString(beginPatRef.prKind),
2683 + beginPatRef.prElementIdx,
2684 + beginPatRef.prPatternIdx,
2685 + beginPatHighLightCode,
2686 + getPatternForDebug(patTable, beginPatRef) );
2687 +#endif
2689 + groupIdx = currentElement->mpteGroup;
2691 + /*
2692 + * no start pattern can be found, if there is no group assigned
2693 + * to begin pattern (should never occur)
2694 + */
2695 + if (groupIdx == NO_GROUP_IDX)
2697 + return -1;
2700 + /*
2701 + * Remember pattern (= keywords) regular expression of context
2702 + * group related to begin pattern. Use it for backward search.
2703 + */
2704 + groupPatRE = table->smtGroups[groupIdx]->mpgeKeywordRE;
2705 + currentPatRE = groupPatRE;
2707 + /*
2708 + * Use start / end pattern regular expression if skip to start is
2709 + * set for begin pattern.
2710 + */
2711 + if (currentElement->mpteSkipBtwnStartEnd)
2713 + currentPatRE = currentElement->mpteStartEndRE;
2714 + skipToStart = TRUE;
2717 + while (stackIdx > 0 && prevStartPos != -1)
2719 + /*
2720 + * Search for previous string pattern in backward direction.
2721 + */
2722 + prevStartPos =
2723 + searchPatternBackward(
2724 + patTable,
2725 + currentPatRE,
2726 + searchRegion,
2727 + delimiters,
2728 + startPos,
2729 + &prevPatRef,
2730 + &prevPatHighLightCode,
2731 + matchedPatternLength,
2732 + &prevPatBackRefInfo );
2734 + if (prevStartPos == -1)
2736 + /*
2737 + * no previous pattern found -> leave loop
2738 + */
2739 +#ifdef DEBUG_FIND
2740 + printf(" SI: %d [K: %s start EI: %d PI %d] Pos: %d --> no next pat. found\n",
2741 + stackIdx,
2742 + patElemKindToString(stack[stackIdx -1].psePatRef.prKind),
2743 + stack[stackIdx -1].psePatRef.prElementIdx,
2744 + stack[stackIdx -1].psePatRef.prPatternIdx,
2745 + startPos);
2746 +#endif
2747 + break;
2750 + /*
2751 + * Update previous pattern reference depending on last stack
2752 + * pattern, which is located in text puffer after previous
2753 + * start pattern.
2754 + */
2755 + considerNextPatternReference(
2756 + patTable,
2757 + &prevPatRef,
2758 + stack[stackIdx - 1].psePatRef,
2759 + groupIdx);
2761 + /*
2762 + * If current found match pattern table element is a mono pattern and
2763 + * skip to start pattern is active, then the found pattern string is
2764 + * a START one in case of ambiguous or no syntax was detected.
2765 + */
2766 + if (skipToStart &&
2767 + (prevPatRef.prMonoInfo == PEMI_MONO_AMBIGUOUS_SYNTAX ||
2768 + prevPatRef.prMonoInfo == PEMI_MONO_NOT_SYNTAX_BASED))
2770 + prevPatRef.prKind = PEK_START;
2773 +#ifdef DEBUG_FIND
2774 + printf(" SI: %d [K: %s start EI: %d PI %d] Pos: %d K: %s EI: %d PI: %d HC: %d f=<%s> ",
2775 + stackIdx,
2776 + patElemKindToString(stack[stackIdx -1].psePatRef.prKind),
2777 + stack[stackIdx -1].psePatRef.prElementIdx,
2778 + stack[stackIdx -1].psePatRef.prPatternIdx,
2779 + prevStartPos,
2780 + patElemKindToString(prevPatRef.prKind),
2781 + prevPatRef.prElementIdx,
2782 + prevPatRef.prPatternIdx,
2783 + prevPatHighLightCode,
2784 + getPatternForDebug(patTable, prevPatRef) );
2785 + printFoundStringForDebug(
2786 + searchRegion->sriWindow,
2787 + prevStartPos + searchRegion->sriStartOfTextPos,
2788 + *matchedPatternLength);
2789 + printf("\n");
2790 +#endif
2792 + if (prevPatRef.prKind == PEK_START)
2794 + /*
2795 + * If the end pattern of the previous pattern set is a reference,
2796 + * then the prev. element index is the one of the ref. (due to this
2797 + * string was found before and was stored on stack)
2798 + */
2799 + if (patTable->mptElements[prevPatRef.prElementIdx]->mpteGroup == groupIdx)
2801 + considerStackPatReference(
2802 + &patTable->mptElements[prevPatRef.prElementIdx]->mpteEnd,
2803 + stack[stackIdx - 1].psePatRef.prElementIdx,
2804 + &prevPatRef.prElementIdx);
2807 + /*
2808 + * Ignore current found pattern, if it doesn't fit to the prev.
2809 + * opened one.
2810 + */
2811 + if (stack[stackIdx - 1].psePatRef.prElementIdx == prevPatRef.prElementIdx &&
2812 + (stack[stackIdx - 1].pseHighLightCode == prevPatHighLightCode ||
2813 + stack[stackIdx - 1].pseHighLightCode == IGNORE_HIGHLIGHT_CODE ||
2814 + prevPatHighLightCode == IGNORE_HIGHLIGHT_CODE) &&
2815 + doesBackRefInfoMatch(
2816 + &stack[stackIdx - 1].pseBackRefInfo,
2817 + &prevPatBackRefInfo))
2819 + /*
2820 + * use context group pattern again, if start pattern
2821 + * to skip to was found.
2822 + */
2823 + if (skipToStart)
2825 + currentPatRE = groupPatRE;
2826 + skipToStart = FALSE;
2829 + /*
2830 + * pop. related end pattern from stack.
2831 + */
2832 + stackIdx --;
2835 + else if (prevPatRef.prKind == PEK_END)
2837 + if (stackIdx >= MAX_NESTED_PATTERNS)
2839 +#ifdef DEBUG_FIND
2840 + printf("BACKWARD: MAX. NESTED PATTERN DEPTH REACHED !\n");
2841 +#endif
2842 + prevStartPos = -1;
2844 + else if (!skipToStart)
2846 + /*
2847 + * Put prev. pattern on stack, if contents between start /
2848 + * end shouldn't be skipped (if "skipToStart" is set,
2849 + * a (usually illegal) end pattern to skip inside the
2850 + * skipped one is found (e.g. *\ *\ ..)
2851 + */
2852 + stack[stackIdx].psePatRef = prevPatRef;
2853 + stack[stackIdx].pseHighLightCode = prevPatHighLightCode;
2854 + stack[stackIdx].pseBackRefInfo = prevPatBackRefInfo;
2855 + stackIdx ++;
2857 + currentElement =
2858 + patTable->mptElements[prevPatRef.prElementIdx];
2860 + /*
2861 + * Use start / end pattern regular expression if skip to
2862 + * end is set for found end pattern.
2863 + */
2864 + if (currentElement->mpteSkipBtwnStartEnd)
2866 + currentPatRE = currentElement->mpteStartEndRE;
2867 + skipToStart = TRUE;
2871 + startPos = prevStartPos - 1;
2874 + return prevStartPos;
2878 +** Adapt found pattern element index depending on
2879 +** the info stored on (last) stack element and
2880 +** a given pattern set (belonging to the found pattern).
2882 +static void considerStackPatReference(
2883 + PatternElementSet *patSet,
2884 + int stackElementIdx,
2885 + int *foundElementIdx)
2887 + PatternElement *patElement;
2888 + int i;
2890 + /*
2891 + * If found pattern index already indicates, that found pattern
2892 + * belongs to pattern set stored on stack, then no adaption is needed
2893 + */
2894 + if (*foundElementIdx == stackElementIdx)
2895 + return;
2897 + /*
2898 + * Check all elements of given pattern element set:
2899 + */
2900 + for (i=0; i < patSet->pesNumberOfPattern; i++)
2902 + patElement = patSet->pesPattern[i];
2904 + /*
2905 + * If this set element is a reference and this reference fits
2906 + * to the element stored on stack, then adapt found element index:
2907 + * indicate, that found pattern belongs to pattern set stored on stack
2908 + */
2909 + if (patElement->peType == PET_REFERENCE &&
2910 + patElement->peVal.peuRef.prElementIdx == stackElementIdx)
2912 + *foundElementIdx = stackElementIdx;
2914 + return;
2920 +** Determines, if a string pattern is located at the given position
2921 +** "relBeginPos" in the given "searchRegion". A string pattern is
2922 +** found, if the pattern is located just before given position
2923 +** "relBeginPos" OR if "relBeginPos" is located within a string pattern.
2925 +** Returns true, if the given "pattern" is located at
2926 +** "relBeginPos". "matchInfo" holds all info needed about matched
2927 +** "start" string pattern.
2929 +static int getPatternLocatedAtPos(
2930 + regexp *usedPatRE,
2931 + MatchPatternTable *table,
2932 + SearchRegionInfo *searchRegion,
2933 + int *relBeginPos,
2934 + MatchingElementInfo *matchInfo,
2935 + const char *delimiters)
2937 + int searchStartPos = *relBeginPos;
2938 + PatternReference *patRef = &matchInfo->meiPatRef;
2939 + FoundStringInfo foundStringInfo;
2940 + int relMatchStartPos;
2941 + int relMatchEndPos;
2943 + patRef->prElementIdx = NO_ELEMENT_IDX;
2944 + patRef->prKind = PEK_UNKNOWN;
2945 + patRef->prPatternIdx = NO_PATTERN_IDX;
2947 + matchInfo->meiHighLightCode = IGNORE_HIGHLIGHT_CODE;
2948 + matchInfo->meiAbsStartPos = -1;
2949 + matchInfo->meiLength = 0;
2951 + /*
2952 + * No backward search possible, if we are at beginning of
2953 + * search region
2954 + */
2955 + if (searchStartPos == 0)
2956 + return FALSE;
2958 + /*
2959 + * Search in backward direction for 1st occurance of a string pattern
2960 + * starting one char before "searchStartPos".
2961 + */
2962 + if (ExecRE(
2963 + usedPatRE,
2964 + searchRegion->sriText,
2965 + searchRegion->sriText + searchStartPos - 1,
2966 + TRUE,
2967 + searchRegion->sriPrevChar,
2968 + searchRegion->sriText[searchStartPos],
2969 + delimiters,
2970 + searchRegion->sriText,
2971 + NULL))
2973 + /*
2974 + * String pattern was found:
2975 + */
2976 + foundStringInfo.fsiStartPtr = usedPatRE->startp[0];
2977 + foundStringInfo.fsiEndPtr = usedPatRE->endp[0];
2978 + foundStringInfo.fsiLength =
2979 + foundStringInfo.fsiEndPtr - foundStringInfo.fsiStartPtr;
2981 + relMatchEndPos = foundStringInfo.fsiEndPtr - searchRegion->sriText;
2982 + relMatchStartPos = foundStringInfo.fsiStartPtr - searchRegion->sriText;
2984 + /*
2985 + * Is found pattern located exactly one char before "relBeginPos" OR
2986 + * is "relBeginPos" located within found string pattern ?
2987 + * Note: "relMatchEndPos" indicates 1st pos. in "sriText"
2988 + * which does *not* belong to found string anymore.
2989 + */
2990 + if ((*relBeginPos == relMatchEndPos) ||
2991 + (*relBeginPos >= relMatchStartPos &&
2992 + *relBeginPos < relMatchEndPos))
2994 + *relBeginPos = relMatchEndPos;
2996 + /*
2997 + * Determine match element info related to found string.
2998 + */
2999 + matchInfo->meiAbsStartPos =
3000 + foundStringInfo.fsiStartPtr - searchRegion->sriText +
3001 + searchRegion->sriStartOfTextPos;
3002 + matchInfo->meiLength = foundStringInfo.fsiLength;
3004 + foundStringInfo.fsiPrevChar =
3005 + foundStringInfo.fsiStartPtr == searchRegion->sriText ?
3006 + searchRegion->sriPrevChar : *(foundStringInfo.fsiStartPtr - 1);
3008 + foundStringInfo.fsiSuccChar =
3009 + *(foundStringInfo.fsiEndPtr) == '\0' ?
3010 + searchRegion->sriSuccChar : *(foundStringInfo.fsiEndPtr);
3012 + foundStringInfo.fsiDelimiters = delimiters;
3014 + return(
3015 + getMatchedElementInfo(
3016 + searchRegion->sriWindow,
3017 + table,
3018 + &foundStringInfo,
3019 + matchInfo));
3023 + return FALSE;
3027 +** Get all needed info related to matched "start" string pattern
3028 +** (given by parameter "foundStringInfo").
3030 +** Returns true, if info was determined successfully.
3032 +static int getMatchedElementInfo(
3033 + WindowInfo *window,
3034 + MatchPatternTable *table,
3035 + FoundStringInfo *foundStringInfo,
3036 + MatchingElementInfo *matchInfo)
3038 + PatternReference *patRef = &matchInfo->meiPatRef;
3039 + int absMatchStartPos = matchInfo->meiAbsStartPos;
3040 + MatchPatternTableElement *matchedElement;
3042 + if (getPatternInfo(
3043 + table,
3044 + foundStringInfo,
3045 + patRef,
3046 + &matchInfo->meiBackRefInfo))
3048 + /*
3049 + * A pattern reference could be assigned to found string:
3050 + */
3051 + matchedElement = table->mptElements[patRef->prElementIdx];
3053 + matchInfo->meiElement = matchedElement;
3055 + /*
3056 + * get highlight code of found string pattern, if applicable
3057 + */
3058 + if (!matchedElement->mpteIgnoreHighLightInfo)
3060 + matchInfo->meiHighLightCode =
3061 + HighlightCodeOfPos(window, absMatchStartPos);
3064 + /*
3065 + * setup mono pattern info of found string pattern
3066 + */
3067 + if (matchedElement->mpteIsMonoPattern)
3069 + if (matchedElement->mpteIgnoreHighLightInfo)
3071 + patRef->prMonoInfo = PEMI_MONO_NOT_SYNTAX_BASED;
3073 + else
3075 + /*
3076 + * determine mono pattern info depending on highLightCodes
3077 + * before / after found string pattern.
3078 + */
3079 + patRef->prMonoInfo =
3080 + determineMonoPatInfo(
3081 + window,
3082 + matchInfo->meiHighLightCode,
3083 + absMatchStartPos - 1,
3084 + absMatchStartPos + matchInfo->meiLength,
3085 + &patRef->prKind);
3088 + else
3090 + patRef->prMonoInfo = PEMI_NOT_MONO;
3093 + return TRUE;
3095 + else
3097 + /*
3098 + * Found string can't be assigned to a pattern element
3099 + * (should never occur).
3100 + */
3101 + return FALSE;
3106 +** Returns string pattern of given pattern element.
3108 +StringPattern *GetStringPattern(
3109 + MatchPatternTable *table,
3110 + PatternElement *pattern )
3112 + switch (pattern->peType)
3114 + case PET_SINGLE:
3115 + return &pattern->peVal.peuSingle;
3116 + break;
3118 + case PET_MULTIPLE:
3119 + return &pattern->peVal.peuMulti.mpStringPattern;
3120 + break;
3122 + case PET_REFERENCE:
3123 + return GetStringPattern(
3124 + table,
3125 + getPatternOfReference(table, pattern->peVal.peuRef));
3126 + break;
3129 + /*
3130 + * never reached; just to make compiler happy
3131 + */
3132 + return NULL;
3136 +** Returns pattern element of given pattern reference.
3138 +static PatternElement *getPatternOfReference(
3139 + MatchPatternTable *table,
3140 + PatternReference patRef)
3142 + MatchPatternTableElement **element = table->mptElements;
3144 + return element[ patRef.prElementIdx ]->mpteAll.pesPattern[patRef.prPatternIdx];
3147 +#ifdef DEBUG_FIND
3148 +static char *getPatternForDebug(
3149 + MatchPatternTable *table,
3150 + PatternReference patRef )
3152 + if (patRef.prElementIdx < 0)
3154 + return "---";
3157 + return
3158 + GetStringPattern(
3159 + table,
3160 + getPatternOfReference(table, patRef))->spText;
3163 +static char *patElemKindToString(
3164 + PatternElementKind patElemKind)
3166 + if (patElemKind == PEK_START)
3167 + return "START";
3168 + else if (patElemKind == PEK_MIDDLE)
3169 + return "MIDDLE";
3170 + else if (patElemKind == PEK_END)
3171 + return "END";
3172 + else
3173 + return "UNKNOWN";
3176 +static void printFoundStringForDebug(
3177 + WindowInfo *window,
3178 + int absStartPos,
3179 + int length)
3181 + char *foundStr =
3182 + BufGetRange( window->buffer, absStartPos, absStartPos + length);
3184 + printf("%d (abs.) <%s>",
3185 + absStartPos,
3186 + foundStr);
3188 + XtFree(foundStr);
3190 +#endif
3193 diff --quilt /dev/null new/source/patternMatch.h
3194 --- /dev/null
3195 +++ new/source/patternMatch.h
3196 @@ -0,0 +1,170 @@
3197 +/* $Id: patternMatch.h,v 1.2 2003/10/11 16:45:25 uleh Exp $ */
3199 +#ifndef NEDIT_PATTERNMATCH_H_INCLUDED
3200 +#define NEDIT_PATTERNMATCH_H_INCLUDED
3202 +#include "regularExp.h"
3204 +#define NO_GROUP_IDX -1
3205 +#define NO_ELEMENT_IDX -1
3206 +#define NO_PATTERN_IDX -1
3208 +#define MAX_GLOBAL_BACK_REF_ID 9
3209 +#define NO_LOCAL_BACK_REF_ID -1
3211 +typedef enum {
3212 + PEK_UNKNOWN,
3213 + PEK_START,
3214 + PEK_END,
3215 + PEK_MIDDLE
3216 +} PatternElementKind;
3218 +typedef enum {
3219 + PEMI_NOT_MONO,
3220 + PEMI_MONO_NOT_SYNTAX_BASED,
3221 + PEMI_MONO_AMBIGUOUS_SYNTAX,
3222 + PEMI_MONO_DEFINITE_SYNTAX
3223 +} PatternElementMonoInfo;
3225 +typedef struct _PatternReference {
3226 + PatternElementKind prKind;
3227 + PatternElementMonoInfo prMonoInfo;
3228 + int prElementIdx;
3229 + int prPatternIdx;
3230 +} PatternReference;
3232 +typedef enum {
3233 + MPT_INDIVIDUAL,
3234 + MPT_SUB,
3235 + MPT_GROUP
3236 +} MatchPatternType;
3238 +typedef struct _MatchPatternSequenceElement {
3239 + char *mpseName;
3240 + MatchPatternType mpseType;
3241 + int mpseIndex;
3242 +} MatchPatternSequenceElement;
3244 +typedef struct _MatchPatternGroupElement {
3245 + char *mpgeName;
3246 + int mpgeNumberOfSubPatterns;
3247 + char **mpgeSubPatternIds;
3248 + regexp *mpgeKeywordRE;
3249 +} MatchPatternGroupElement;
3251 +typedef enum {
3252 + PWB_NONE,
3253 + PWB_LEFT,
3254 + PWB_RIGHT,
3255 + PWB_BOTH
3256 +} PatternWordBoundary;
3258 +typedef struct _StrPatBackRefElement{
3259 + int spbreLocalBackRefID;
3260 + char *spbreRegExpText;
3261 +} StrPatBackRefElement;
3263 +typedef struct _StringPattern {
3264 + char *spText;
3265 + int spLength;
3266 + PatternWordBoundary spWordBoundary;
3267 + int spCaseInsensitive;
3268 + int spRegularExpression;
3269 + regexp *spTextRE;
3270 + char *spOrigText;
3271 + int spBackRefParsed;
3272 + int spBackRefResolved;
3273 + StrPatBackRefElement spOwnGlobalBackRef[MAX_GLOBAL_BACK_REF_ID];
3274 + int spGlobalToLocalBackRef[MAX_GLOBAL_BACK_REF_ID];
3275 +} StringPattern;
3277 +typedef struct _MultiPattern {
3278 + StringPattern mpStringPattern;
3279 + int mpNumberOfReferences;
3280 + PatternReference *mpRefList;
3281 +} MultiPattern;
3283 +typedef enum {
3284 + PET_SINGLE,
3285 + PET_MULTIPLE,
3286 + PET_REFERENCE
3287 +} PatternElementType;
3289 +typedef struct _PatternElement {
3290 + int peIndex;
3291 + PatternElementKind peKind;
3292 + PatternElementType peType;
3293 + union {
3294 + StringPattern peuSingle;
3295 + MultiPattern peuMulti;
3296 + PatternReference peuRef;
3297 + } peVal;
3298 +} PatternElement;
3300 +typedef struct _PatternElementSet {
3301 + int pesNumberOfPattern;
3302 + PatternElement **pesPattern;
3303 +} PatternElementSet;
3305 +typedef struct _GlobalBackRefElement{
3306 + StringPattern *gbreDefByStrPat;
3307 + char *gbreRegExpText;
3308 +} GlobalBackRefElement;
3310 +typedef struct _MatchPatternTableElement {
3311 + char *mpteName;
3312 + int mpteIndex;
3313 + MatchPatternType mpteType;
3314 + int mpteGroup;
3315 + PatternElementSet mpteAll;
3316 + PatternElementSet mpteStart;
3317 + PatternElementSet mpteMiddle;
3318 + PatternElementSet mpteEnd;
3319 + int mpteFlash;
3320 + int mpteIsMonoPattern;
3321 + int mpteSkipBtwnStartEnd;
3322 + int mpteIgnoreHighLightInfo;
3323 + regexp *mpteStartEndRE;
3324 + GlobalBackRefElement mpteGlobalBackRef[MAX_GLOBAL_BACK_REF_ID];
3325 +} MatchPatternTableElement;
3327 +typedef struct _MatchPatternTable {
3328 + int mptNumberOfElements;
3329 + MatchPatternTableElement **mptElements;
3330 +} MatchPatternTable;
3332 +typedef struct _StringMatchTable {
3333 + char *smtLanguageMode;
3334 + MatchPatternTable *smtAllPatterns;
3335 + regexp *smtAllPatRE;
3336 + regexp *smtFlashPatRE;
3337 + regexp *smtUsedPatRE;
3338 + int smtNumberOfGroups;
3339 + MatchPatternGroupElement **smtGroups;
3340 + int smtNumberOfSeqElements;
3341 + MatchPatternSequenceElement **smtSequence;
3342 +} StringMatchTable;
3344 +typedef enum {
3345 + MT_FLASH_DELIMIT,
3346 + MT_FLASH_RANGE,
3347 + MT_SELECT,
3348 + MT_GOTO,
3349 + MT_MACRO
3350 +} MatchingType;
3352 +int FindMatchingString(
3353 + WindowInfo *window,
3354 + MatchingType matchingType,
3355 + int *charPos,
3356 + int startLimit,
3357 + int endLimit,
3358 + int *matchPos,
3359 + int *matchLength,
3360 + int *direction);
3362 +StringPattern *GetStringPattern(
3363 + MatchPatternTable *table,
3364 + PatternElement *pattern);
3366 +#endif /* NEDIT_PATTERNMATCH_H_INCLUDED */
3367 diff --quilt /dev/null new/source/patternMatchData.c
3368 --- /dev/null
3369 +++ new/source/patternMatchData.c
3370 @@ -0,0 +1,7780 @@
3371 +static const char CVSID[] = "$Id: patternMatchData.c,v 1.4 2004/10/27 21:57:12 uleh Exp $";
3372 +/*******************************************************************************
3373 +* *
3374 +* patternMatchData.c -- Maintain and allow user to edit a matching pattern list*
3375 +* used for pattern matching *
3376 +* *
3377 +* Copyright (C) 2003-2004, Uwe Lehnert *
3378 +* *
3379 +* This is free software; you can redistribute it and/or modify it under the *
3380 +* terms of the GNU General Public License as published by the Free Software *
3381 +* Foundation; either version 2 of the License, or (at your option) any later *
3382 +* version. In addition, you may distribute versions of this program linked to *
3383 +* Motif or Open Motif. See README for details. *
3384 +* *
3385 +* This software is distributed in the hope that it will be useful, but WITHOUT *
3386 +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
3387 +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
3388 +* for more details. *
3389 +* *
3390 +* You should have received a copy of the GNU General Public License along with *
3391 +* software; if not, write to the Free Software Foundation, Inc., 59 Temple *
3392 +* Place, Suite 330, Boston, MA 02111-1307 USA *
3393 +* *
3394 +* Nirvana Text Editor *
3395 +* October 27, 2004 *
3396 +* *
3397 +* Written by Uwe Lehnert *
3398 +* *
3399 +*******************************************************************************/
3400 +#ifdef HAVE_CONFIG_H
3401 +#include "../config.h"
3402 +#endif
3404 +#include <stdlib.h>
3405 +#include <stdio.h>
3406 +#include <limits.h>
3407 +#include <string.h>
3408 +#include <ctype.h>
3410 +#ifdef VMS
3411 +#include "../util/VMSparam.h"
3412 +#else
3413 +#ifndef __MVS__
3414 +#include <sys/param.h>
3415 +#endif
3416 +#endif /*VMS*/
3418 +#include <Xm/Xm.h>
3419 +#include <Xm/Form.h>
3420 +#include <Xm/Frame.h>
3421 +#include <Xm/Text.h>
3422 +#include <Xm/LabelG.h>
3423 +#include <Xm/PushB.h>
3424 +#include <Xm/PushBG.h>
3425 +#include <Xm/ToggleB.h>
3426 +#include <Xm/RowColumn.h>
3427 +#include <Xm/SeparatoG.h>
3429 +#include "../util/misc.h"
3430 +#include "../util/DialogF.h"
3431 +#include "../util/managedList.h"
3433 +#include "regularExp.h"
3434 +#include "textBuf.h"
3435 +#include "nedit.h"
3436 +#include "window.h"
3437 +#include "preferences.h"
3438 +#include "help.h"
3439 +#include "file.h"
3440 +#include "textP.h"
3442 +#include "patternMatch.h"
3443 +#include "patternMatchData.h"
3445 +#ifdef HAVE_DEBUG_H
3446 +#include "../debug.h"
3447 +#endif
3450 + * local synonyms
3451 + */
3452 +#define MAX_LOCAL_BACK_REF_ID 9
3453 +#define LOCAL_BACK_REF_ID_USED -2
3455 +#define MAX_NUMBER_MIDDLE_PATTERN 10
3456 +#define MAX_STRING_PATTERNS 30
3457 +#define MAX_NBR_MATCH_PATTERNS 50
3458 +#define MAX_NBR_MATCH_PATTERN_GROUPS 50
3459 +#define MAX_NBR_SEQ_ELEMENTS MAX_NBR_MATCH_PATTERNS + MAX_NBR_MATCH_PATTERN_GROUPS
3461 +#define MATCH_PAT_NAME_LBL_TXT "Matching Pattern Name"
3462 +#define STRING_PATTERNS_LBL_TXT "String Patterns"
3464 +#define BORDER 4
3465 +#define LIST_RIGHT 41
3466 +#define PLAIN_LM_STRING "PLAIN"
3468 +#define SPNM_NONE_SELECTED "none selected"
3470 +#define KEEP_LANGUAGE_MODE True
3471 +#define DISCARD_LANGUAGE_MODE False
3473 +#define STRING_PATTERN_DIALOG True
3474 +#define CONTEXT_GROUP_DIALOG False
3477 + * local data definitions
3478 + */
3479 +typedef struct _ErrorInfo {
3480 + char *eiDetail;
3481 + char *eiLanguageMode;
3482 + char *eiMPTabElementName;
3483 + char *eiStringPatText;
3484 + char *eiRegExpCompileMsg;
3485 + int eiBackRefNbr;
3486 +} ErrorInfo;
3488 +typedef struct _BackRefBracketInfo {
3489 + int brbiGlobalId;
3490 + char *brbiContentStart;
3491 + int brbiNestingLevel;
3492 +} BackRefBracketInfo;
3494 +typedef struct _RegExpStringInfo {
3495 + int resiNbrOfAddedMultiPat;
3496 + PatternReference **resiAddedMultiPat;
3497 + char *resiNoneWBRegExpString;
3498 + char *resiLeftWBRegExpString;
3499 + char *resiRightWBRegExpString;
3500 + char *resiBothWBRegExpString;
3501 + int resiLocalBackRefID;
3502 +} RegExpStringInfo;
3504 +typedef struct _ReadMatchPatternInfo {
3505 + int rmpiNbrOfElements;
3506 + MatchPatternTableElement *rmpiElement[MAX_NBR_MATCH_PATTERNS];
3507 + int rmpiNbrOfGroups;
3508 + MatchPatternGroupElement *rmpiGroup[MAX_NBR_MATCH_PATTERN_GROUPS];
3509 + int rmpiNbrOfSeqElements;
3510 + MatchPatternSequenceElement *rmpiSequence[MAX_NBR_SEQ_ELEMENTS];
3511 + regexp *rmpiAllPatRE;
3512 + regexp *rmpiFlashPatRE;
3513 +} ReadMatchPatternInfo;
3515 +typedef struct _DialogStringPatternElement {
3516 + char *dspeText;
3517 + PatternElementKind dspeKind;
3518 + PatternWordBoundary dspeWordBoundary;
3519 + int dspeCaseInsensitive;
3520 + int dspeRegularExpression;
3521 +} DialogStringPatternElement;
3523 +typedef struct _DialogStringPatterns {
3524 + int dspNumberOfPatterns;
3525 + DialogStringPatternElement *dspElements[MAX_STRING_PATTERNS];
3526 +} DialogStringPatterns;
3528 +typedef struct _DialogMatchPatternTableElement {
3529 + char *dmpteName;
3530 + MatchPatternType dmpteType;
3531 + DialogStringPatterns dmptePatterns;
3532 + int dmpteSkipBtwnStartEnd;
3533 + int dmpteIgnoreHighLightInfo;
3534 + int dmpteFlash;
3535 +} DialogMatchPatternTableElement;
3537 +typedef struct _DialogMatchPatternGroupElement {
3538 + char *dmpgeName;
3539 + int dmpgeNumberOfSubPatterns;
3540 + char *dmpgeSubPatternIds[MAX_NBR_MATCH_PATTERNS];
3541 +} DialogMatchPatternGroupElement;
3543 +typedef struct _DialogMatchPatternSequenceElement {
3544 + char *dmpseName;
3545 + MatchPatternType dmpseType;
3546 + int dmpseValid;
3547 + void *dmpsePtr;
3548 +} DialogMatchPatternSequenceElement;
3550 +typedef struct _DialogMatchPatternInfo {
3551 + int dmpiNbrOfSeqElements;
3552 + DialogMatchPatternSequenceElement *dmpiSequence[MAX_NBR_SEQ_ELEMENTS];
3553 +} DialogMatchPatternInfo;
3555 +typedef enum {
3556 + DMPTR_OK,
3557 + DMPTR_EMPTY,
3558 + DMPTR_INCOMPLETE
3559 +} DMPTranslationResult;
3561 +typedef struct _NameList {
3562 + int nlNumber;
3563 + char *nlId[MAX_NBR_SEQ_ELEMENTS + 1];
3564 +} NameList;
3567 + * prototypes of local functions
3568 + */
3569 +static void treatDuplicatedPattern(
3570 + MatchPatternTable *table,
3571 + PatternElement *prevPattern,
3572 + PatternReference prevPatRef,
3573 + PatternElement *lastPattern,
3574 + PatternReference lastPatRef);
3575 +static void treatDuplicatedPatternElements(
3576 + MatchPatternTable *table,
3577 + MatchPatternTableElement *prevElement,
3578 + int prevElementIdx,
3579 + PatternElement *lastPattern,
3580 + PatternReference lastPatRef);
3581 +static void treatDuplicatedMTElements(
3582 + MatchPatternTable *table,
3583 + MatchPatternTableElement *prevElement,
3584 + int prevElementIdx,
3585 + MatchPatternTableElement *lastElement,
3586 + int lastElementIdx);
3587 +static void treatDuplicatedMTEntries(
3588 + MatchPatternTableElement **element,
3589 + int nbrOfElements);
3591 +static int createStrPatRegExpOfElement(
3592 + ReadMatchPatternInfo *readPatInfo,
3593 + MatchPatternTableElement *element,
3594 + ErrorInfo *errInfo);
3595 +static int createStrPatRegExp(
3596 + StringPattern *strPat,
3597 + ErrorInfo *errInfo);
3598 +static void adaptCompileMsg(
3599 + char *compileMsg,
3600 + int *globalToLocalBackRef);
3601 +static int localToGlobalBackRef(
3602 + int *globalToLocalBackRef,
3603 + int localId);
3604 +static int createStartEndRegExp(
3605 + ReadMatchPatternInfo *readMatchPatternInfo,
3606 + MatchPatternTableElement *element,
3607 + ErrorInfo *errInfo);
3608 +static int createGroupRegExp(
3609 + ReadMatchPatternInfo *readPatInfo,
3610 + MatchPatternGroupElement *group,
3611 + ErrorInfo *errInfo);
3612 +static void setupRegExpStringBuffers(
3613 + ReadMatchPatternInfo *readMatchPatternInfo,
3614 + RegExpStringInfo *regExpStringInfo);
3615 +static void addSMTRegExpString(
3616 + char *result,
3617 + char *partToAdd,
3618 + const char *postfix);
3619 +static void composeStartEndRegExpString(
3620 + ReadMatchPatternInfo *readMatchPatternInfo,
3621 + MatchPatternTableElement *element,
3622 + char **regExpString);
3623 +static void addElementToRegExpString(
3624 + MatchPatternTableElement *element,
3625 + ReadMatchPatternInfo *readMatchPatternInfo,
3626 + RegExpStringInfo *regExpStringInfo);
3627 +static void addUniquePatternToRegExpString(
3628 + PatternElement *patElement,
3629 + PatternReference *patElementReference,
3630 + ReadMatchPatternInfo *readMatchPatternInfo,
3631 + RegExpStringInfo *regExpStringInfo);
3632 +static void addPatternToRegExpString(
3633 + StringPattern *pattern,
3634 + RegExpStringInfo *regExpStringInfo);
3635 +static char *adaptLocalBackRefs(
3636 + char *regExpText,
3637 + int *commonLocalId);
3638 +static void scanForLocalBackRefs(
3639 + char *regExpText,
3640 + int *localBackRefList);
3641 +static int isMultiPatternNotAdded(
3642 + RegExpStringInfo *regExpStringInfo,
3643 + PatternReference *toBeAddedPR);
3644 +static void catSMTRegExpStrings(
3645 + RegExpStringInfo *regExpStringInfo,
3646 + char **regExpString);
3647 +static void freeRegExpStringInfo(
3648 + RegExpStringInfo *regExpStringInfo);
3649 +static int totalKeywordOfTableLen(
3650 + ReadMatchPatternInfo *info,
3651 + int *nbrOfMultiPatterns);
3652 +static int totalMatchPatternTableElementLen(
3653 + ReadMatchPatternInfo *info,
3654 + MatchPatternTableElement *element,
3655 + int *nbrOfMultiPatterns);
3656 +static int patternElementLen(
3657 + ReadMatchPatternInfo *info,
3658 + PatternElement *patElement,
3659 + int *nbrOfMultiPatterns);
3661 +static void parseMatchingPatternSetError(
3662 + const char *stringStart,
3663 + const char *stoppedAt,
3664 + ErrorInfo *errInfo);
3665 +static void dialogMatchingPatternSetError(
3666 + char *title,
3667 + ErrorInfo *errInfo);
3669 +static char *createMatchPatternsString(
3670 + StringMatchTable *table,
3671 + char *indentStr);
3672 +static char *createPatternElementString(
3673 + MatchPatternTable *table,
3674 + PatternElement *pat);
3676 +static StringMatchTable *readDefaultStringMatchTable(const char *langModeName);
3677 +static int isDefaultMatchPatternTable(StringMatchTable *table);
3679 +static void freeReadMatchPatternInfo( ReadMatchPatternInfo *readPatInfo );
3680 +static void freeStringMatchTable( StringMatchTable *table );
3681 +static void freeMatchPatternTableElement( MatchPatternTableElement *element );
3682 +static void freePatternElement( PatternElement *element );
3683 +static void freeStringPattern( StringPattern *strPat );
3684 +static void freeMatchPatternGroupElement( MatchPatternGroupElement *group );
3685 +static void freeMatchPatternSequenceElement( MatchPatternSequenceElement *sequence );
3687 +static StringMatchTable *readMatchPatternSet(char **inPtr);
3688 +static StringMatchTable *readMatchPatternSetContent(
3689 + char **inPtr,
3690 + char *stringStart,
3691 + char *languageMode);
3692 +static int createRegExpOfPatterns(
3693 + ReadMatchPatternInfo *readPatInfo,
3694 + ErrorInfo *errInfo);
3695 +static int createRegExpOfAllPatterns(
3696 + ReadMatchPatternInfo *readPatInfo,
3697 + ErrorInfo *errInfo);
3698 +static int createRegExpOfStrPatterns(
3699 + ReadMatchPatternInfo *readPatInfo,
3700 + ErrorInfo *errInfo);
3701 +static StringMatchTable *createStringMatchTable(
3702 + ReadMatchPatternInfo *readPatInfo,
3703 + char *languageMode);
3704 +static int readMatchPatternEntry(
3705 + char **inPtr,
3706 + ErrorInfo *errInfo,
3707 + ReadMatchPatternInfo *info);
3708 +static void recordPatternSequence(
3709 + ReadMatchPatternInfo *info,
3710 + char *name,
3711 + MatchPatternType type,
3712 + int index);
3713 +static int assignIndividualGroup(
3714 + ReadMatchPatternInfo *info,
3715 + char **errMsg,
3716 + MatchPatternTableElement *element);
3717 +static MatchPatternTableElement *getPatternOfName(
3718 + ReadMatchPatternInfo *info,
3719 + char *subPatToSearch);
3720 +static MatchPatternGroupElement *readMatchPatternGroup(
3721 + char **inPtr,
3722 + ErrorInfo *errInfo,
3723 + char *name,
3724 + ReadMatchPatternInfo *info);
3725 +static int readPatternElement(
3726 + char **inPtr,
3727 + char **errMsg,
3728 + PatternElement **pattern);
3729 +static PatternElement *createPatternElement(
3730 + char *patternText,
3731 + PatternElementKind patternKind,
3732 + PatternWordBoundary wordBoundary,
3733 + int caseInsensitive,
3734 + int regularExpression);
3736 +static int createGlobalBackRefList(
3737 + ReadMatchPatternInfo *readPatInfo,
3738 + MatchPatternTableElement *element,
3739 + ErrorInfo *errInfo);
3740 +StringPattern *getReadStringPattern(
3741 + ReadMatchPatternInfo *readPatInfo,
3742 + PatternElement *pattern );
3743 +static PatternElement *getReadPatternOfReference(
3744 + ReadMatchPatternInfo *readPatInfo,
3745 + PatternReference *patRef);
3746 +static char *replaceCapturingParentheses(
3747 + const char *source);
3748 +static int parseGlobalBackRefs(
3749 + StringPattern *strPat,
3750 + GlobalBackRefElement *backRefList,
3751 + ErrorInfo *errInfo);
3752 +static int updateGlobalBackRefs(
3753 + StringPattern *strPat,
3754 + GlobalBackRefElement *backRefList,
3755 + ErrorInfo *errInfo);
3756 +static char *createBackRefRegExpText(
3757 + const char *start,
3758 + const char *end);
3759 +static int resolveGlobalBackRefs(
3760 + ReadMatchPatternInfo *readPatInfo,
3761 + MatchPatternTableElement *element,
3762 + ErrorInfo *errInfo);
3763 +static int resolveGlobalBackRefsOfStrPat(
3764 + StringPattern *strPat,
3765 + GlobalBackRefElement *backRefList,
3766 + ErrorInfo *errInfo);
3767 +static char *substituteGlobalBackRef(
3768 + StringPattern *strPat,
3769 + char *subsPtr,
3770 + int globalId,
3771 + int *localId,
3772 + GlobalBackRefElement *backRefList,
3773 + ErrorInfo *errInfo);
3774 +static char *replaceBackRefIdByRegExp(
3775 + StringPattern *strPat,
3776 + char *replaceStartPtr,
3777 + char *regExp);
3778 +static char *convertGlobalToLocalBackRef(
3779 + StringPattern *strPat,
3780 + char *convertPtr);
3782 +static MatchPatternTableElement *readMatchPatternTableElement(
3783 + char **inPtr,
3784 + char **errMsg,
3785 + char *name,
3786 + MatchPatternType type);
3787 +static int sortReadPatternElementSet(
3788 + PatternElementSet *allPat,
3789 + char **errMsg,
3790 + MatchPatternTableElement *result);
3791 +static void countPatternElementKind(
3792 + PatternElementSet *allPat,
3793 + MatchPatternTableElement *result);
3794 +static void sortPatternElementSet(
3795 + PatternElementSet *allPat,
3796 + MatchPatternTableElement *result);
3797 +static void copyPatternSet(
3798 + PatternElementSet *sourcePS,
3799 + PatternElementSet *destPS);
3801 +static int getMPSName(
3802 + char **inPtr,
3803 + ErrorInfo *errInfo,
3804 + char **name );
3805 +static int getMPSTypeAttribute(
3806 + char **inPtr,
3807 + ErrorInfo *errInfo,
3808 + MatchPatternType *type);
3809 +static int getMPSGlobalAttribute(
3810 + char **inPtr,
3811 + char **errMsg,
3812 + int *isMonoPattern,
3813 + int *comment,
3814 + int *flash,
3815 + int *ignoreHighLightInfo);
3816 +static int getMPSPatternAttribute(
3817 + char **inPtr,
3818 + char **errMsg,
3819 + PatternElementKind *patternKind,
3820 + PatternWordBoundary *wordBoundary,
3821 + int *caseInsensitive,
3822 + int *regularExpression);
3824 +static void copyStringMatchTableForDialog(
3825 + StringMatchTable *sourceTable,
3826 + DialogMatchPatternInfo *dialogTable );
3827 +static void *copyMatchPatternElementForDialog(
3828 + MatchPatternTable *table,
3829 + int sourceElementIdx);
3830 +static void copyPatternForDialog(
3831 + MatchPatternTable *table,
3832 + PatternElement *sourcePattern,
3833 + DialogStringPatternElement **dialogPattern );
3834 +static void *copyGroupElementForDialog(
3835 + MatchPatternGroupElement *sourceGroup);
3836 +static void copySequenceElementForDialog(
3837 + StringMatchTable *sourceTable,
3838 + MatchPatternSequenceElement *sourceSeqElement,
3839 + DialogMatchPatternSequenceElement **dialogSeqElement );
3840 +static DialogMatchPatternSequenceElement *copyDialogSequenceElement(
3841 + DialogMatchPatternSequenceElement *sourceSeq);
3842 +static void freeDialogMatchPatternElement(
3843 + DialogMatchPatternTableElement *dialogElement );
3844 +static void freeDialogStringPatternElement(
3845 + DialogStringPatternElement *element);
3846 +static void freeDialogGroupElement(
3847 + DialogMatchPatternGroupElement *dialogGroup );
3848 +static void freeDialogSequenceElement(
3849 + DialogMatchPatternSequenceElement *dialogSeq );
3851 +static void copyDialogStringPatternsFromTable(
3852 + DialogMatchPatternTableElement *tableElement,
3853 + DialogStringPatterns *destPatterns);
3854 +static void copyDialogStringPatterns(
3855 + DialogStringPatterns *sourcePatterns,
3856 + DialogStringPatterns *destPatterns);
3857 +static void freeDialogStringPatterns(
3858 + DialogStringPatterns *patterns);
3860 +static DialogStringPatternElement *copyDialogStringPatternElement(
3861 + DialogStringPatternElement *sourceElement);
3863 +static void copyDialogPatternNamesFromGroup(
3864 + DialogMatchPatternGroupElement *group,
3865 + DialogStringPatterns *destPatterns);
3866 +static DialogStringPatternElement *copyDialogPatternName(
3867 + char *sourcePatternId);
3868 +static void copyDialogPatternNamesToGroup(
3869 + DialogStringPatterns *sourceNames,
3870 + DialogMatchPatternGroupElement *destGroup);
3872 +static void setDialogType(int dialogShowsStringPattern);
3873 +static void setSensitiveWordBoundaryBox(int enable);
3875 +static void *getStringPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
3876 + void *cbArg);
3877 +static void setStringPatternDisplayedCB(void *item, void *cbArg);
3878 +static void freeStringPatternItemCB(void *item);
3880 +static void *getMatchPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
3881 + void *cbArg);
3882 +static void setMatchPatternDisplayedCB(void *item, void *cbArg);
3883 +static void freeMatchPatternItemCB(void *item);
3884 +static int deleteMatchPatternItemCB(int itemIndex, void *cbArg);
3886 +static void matchPatternLangModeCB(Widget w, XtPointer clientData, XtPointer callData);
3887 +static void pmLanguageModeDialogCB(Widget w, XtPointer clientData, XtPointer callData);
3889 +static void destroyCB(Widget w, XtPointer clientData, XtPointer callData);
3890 +static void okCB(Widget w, XtPointer clientData, XtPointer callData);
3891 +static void applyCB(Widget w, XtPointer clientData, XtPointer callData);
3892 +static void checkCB(Widget w, XtPointer clientData, XtPointer callData);
3893 +static void restoreCB(Widget w, XtPointer clientData, XtPointer callData);
3894 +static void deleteCB(Widget w, XtPointer clientData, XtPointer callData);
3895 +static void closeCB(Widget w, XtPointer clientData, XtPointer callData);
3896 +static void helpCB(Widget w, XtPointer clientData, XtPointer callData);
3898 +static void matchPatTypeCB(Widget w, XtPointer clientData, XtPointer callData);
3899 +static void strPatRegExpressionCB(Widget w, XtPointer clientData, XtPointer callData);
3900 +static void changeExistingSubPattern(char *warnTitle);
3901 +static void changeStringPatternToGroup(void);
3902 +static void changeGroupToStringPattern(char *warnTitle);
3904 +static Widget createSubPatternNameMenu(
3905 + Widget parent,
3906 + char *currentSubPatName,
3907 + int allSubPatterns);
3908 +static void setupSubPatternNameList(
3909 + char *currentSubPatName,
3910 + int allSubPatterns,
3911 + NameList *nameList);
3912 +static void createSubPatNameMenuEntry(
3913 + Widget menu,
3914 + char *subPatName);
3915 +static void setSubPatternNameMenu(
3916 + const char *subPatName);
3917 +static void updateSubPatternNameMenu(
3918 + char *currentSubPatName,
3919 + int allSubPatterns);
3920 +static char *getSelectedSubPatternName(void);
3921 +static int isSubPatternNameInCurStrPat(
3922 + char *subPatName);
3924 +static DialogMatchPatternSequenceElement *readMatchPatternFields(int silent);
3925 +static int isStartPatternElementAvailable(
3926 + DialogStringPatterns *dialogPatterns);
3927 +static DialogStringPatternElement *readStringPatternFrameFields(int silent);
3929 +static int matchPatternDialogEmpty(void);
3930 +static int stringPatternFrameEmpty(void);
3931 +static int stringPatternFieldsEmpty(
3932 + int strPatIsRelatedToGroup);
3934 +static int getAndUpdateStringMatchTable(void);
3935 +static void updateStringMatchTable(
3936 + StringMatchTable *newTable);
3938 +static StringMatchTable *getDialogStringMatchTable(
3939 + DMPTranslationResult *result);
3940 +static StringMatchTable *translateDialogStringMatchTable(
3941 + DialogMatchPatternInfo *dialogTable,
3942 + DMPTranslationResult *result);
3943 +static MatchPatternTableElement *translateDialogMatchPatternTableElement(
3944 + DialogMatchPatternTableElement *dialogElement);
3945 +static void translateDialogPatterns(
3946 + DialogStringPatterns *dialogPatterns,
3947 + MatchPatternTableElement *newElement);
3948 +static MatchPatternGroupElement *translateDialogMatchPatternGroupElement(
3949 + ReadMatchPatternInfo *info,
3950 + DialogMatchPatternGroupElement *dialogGroup);
3951 +static void sortDialogPatternElementSet(
3952 + PatternElementSet *allPat,
3953 + MatchPatternTableElement *result);
3955 +static int stringMatchTableDiffer(
3956 + StringMatchTable *oldTable,
3957 + StringMatchTable *newTable);
3959 +static int patternElementDiffer(
3960 + PatternElement *oldPE,
3961 + MatchPatternTable *oldTab,
3962 + PatternElement *newPE,
3963 + MatchPatternTable *newTab);
3965 +static DialogMatchPatternGroupElement *getDialogGroupUsingMatchPattern(
3966 + char *matchPatternName);
3967 +static void removeMatchPatternFromGroup(
3968 + char *matchPatternName,
3969 + DialogMatchPatternGroupElement *group);
3970 +static void removeMatchPatternFromAllGroups(
3971 + char *matchPatternName);
3972 +static void renameMatchPatternInGroup(
3973 + char *oldMatchPatternName,
3974 + char *newMatchPatternName,
3975 + DialogMatchPatternGroupElement *group);
3976 +static void renameMatchPatternInAllGroups(
3977 + char *oldMatchPatternName,
3978 + char *newMatchPatternName);
3980 +static void freeVariableDialogData(
3981 + int keepLanguageModeName);
3983 +static void initGlobalBackRefList(
3984 + GlobalBackRefElement *list);
3985 +static void initStrPatBackRefList(
3986 + StringPattern *strPat);
3988 +StringPattern *getUniqueStringPattern(
3989 + PatternElement *pattern );
3991 +static void initErrorInfo(
3992 + ErrorInfo *errInfo);
3993 +static void freeErrorInfo(
3994 + ErrorInfo *errInfo);
3996 +static void freeXtPtr(void **ptr);
3997 +static void freePtr(void **ptr);
4000 + * matching pattern dialog information
4001 + */
4002 +static struct {
4003 + Widget mpdShell;
4004 + Widget mpdLmOptMenu;
4005 + Widget mpdLmPulldown;
4006 + Widget mpdMatchPatternNamesListW;
4007 + Widget mpdMatchPatternNameLbl;
4008 + Widget mpdMatchPatternNameW;
4009 + Widget mptbIndividualW;
4010 + Widget mptbSubPatternW;
4011 + Widget mptbContextGroupW;
4012 + Widget mpdGlobalAttributesLbl;
4013 + Widget gabSkipBtwStartEndW;
4014 + Widget gabFlashW;
4015 + Widget gabSyntaxBasedW;
4016 + Widget mpdStringPatternsLbl;
4017 + Widget mpdStringPatternsListW;
4018 + Widget mpdStringPatternTypeLbl;
4019 + Widget sptStartW;
4020 + Widget sptMiddleW;
4021 + Widget sptEndW;
4022 + Widget mpdWordBoundaryLbl;
4023 + Widget wbbBothW;
4024 + Widget wbbLeftW;
4025 + Widget wbbRightW;
4026 + Widget wbbNoneW;
4027 + Widget mpdStringAttributesLbl;
4028 + Widget sabCaseSensitiveW;
4029 + Widget sabRegularExpressionW;
4030 + Widget mpdStringPatternLbl;
4031 + Widget mpdStringPatternW;
4032 + Widget mpdSubPatNamesLbl;
4033 + Widget mpdSubPatNamesOptMenu;
4034 + Widget mpdSubPatNamesPulldown;
4035 + char *mpdLangModeName;
4036 + DialogMatchPatternSequenceElement *currentDmptSeqElement;
4037 + DialogMatchPatternTableElement *currentDmptElement;
4038 + DialogMatchPatternGroupElement *currentDmptGroup;
4039 + DialogStringPatterns currentStringPatterns;
4040 + DialogMatchPatternInfo mpdTable;
4041 + int mpdStringPatternIsDisplayed;
4042 +} MatchPatternDialog =
4043 + {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
4044 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
4045 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
4046 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
4047 + NULL, NULL, NULL, NULL,
4048 + {0, {NULL}},
4049 + {0, {NULL}},
4050 + True
4051 + };
4054 + * Matching pattern sources loaded from the nedit resources file or set
4055 + * by the user
4056 + */
4057 +static int NbrMatchTables = 0;
4058 +static StringMatchTable *MatchTables[MAX_LANGUAGE_MODES];
4061 + * Syntax:
4062 + * LanguagePatternSet ::=
4063 + * LanguageName{PatternStatement..}
4065 + * PatternStatement ::=
4066 + * name:[s]:[c][f][m][p][u]:([s|m|e][w|l|r][i]:"pattern":)..)\n)|
4067 + * name:g:"sub-pattern name":..\n..
4069 + * TypeAttribute:
4070 + * s : sub-pattern (pattern is only matched, if part of a pattern group).
4071 + * g : pattern (context) group (i.e. a sequence of sub-patterns).
4072 + * default: individual pattern (pattern is matched individually).
4073 + * GlobalAttribute:
4074 + * c : the content between start and end pattern is skipped
4075 + * during parsing (e.g. pattern encloses a comment).
4076 + * f : flash matching pattern (if not set, then only jump
4077 + * to matching pattern is supported).
4078 + * m : mono pattern - set exist out of only one single pattern
4079 + * (start pattern = end pattern; e.g. quotes like ")
4080 + * p : ignore highlight info code of single patterns of this set
4081 + * ("plain").
4082 + * StringPatternKind:
4083 + * s : start string pattern.
4084 + * m : middle string pattern.
4085 + * e : end string pattern.
4086 + * WordBoundaryAttribute:
4087 + * w : pattern is word (i.e. before and after pattern
4088 + * there must be a delimiter).
4089 + * l : before pattern must be a delimiter (left side).
4090 + * r : after pattern must be a delimiter (right side).
4091 + * default: neither before nor after pattern must be a delimiter.
4092 + * StringAttribute:
4093 + * i : pattern is case insensitive (if not set: pattern is
4094 + * case sensitive).
4095 + * x : pattern is regular expression (if not set: pattern is
4096 + * literal string).
4098 + * \n : end of pattern
4099 + */
4101 +static char *DefaultStringMatchTable[] = {
4102 + "PLAIN{"
4103 + "Round braces::fp:s:\"(\":e:\")\":\n"
4104 + "Curly braces::fp:s:\"{\":e:\"}\":\n"
4105 + "Squared braces::fp:s:\"[\":e:\"]\":\n"
4106 + "Sharp braces::fp:s:\"<\":e:\">\":\n}",
4107 + "C++{"
4108 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
4109 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4110 + "Single Quotes:s:cmf:s:\"'\":\n"
4111 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4112 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4113 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4114 + "#ifdef statement:s:f:sx:\"#\\s*ifdef\":sx:\"#\\s*ifndef\":sx:\"#\\s*if\":mx:\"#\\s*elif\":mx:\"#\\s*else\":ex:\"#\\s*endif\":\n"
4115 + "#if group:g:Comment:Double Quotes:Single Quotes:#ifdef statement:\n"
4116 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
4117 + "C{"
4118 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
4119 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4120 + "Single Quotes:s:cmf:s:\"'\":\n"
4121 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4122 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4123 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4124 + "#ifdef statement:s:f:sx:\"#\\s*ifdef\":sx:\"#\\s*ifndef\":sx:\"#\\s*if\":mx:\"#\\s*elif\":mx:\"#\\s*else\":ex:\"#\\s*endif\":\n"
4125 + "#if group:g:Comment:Double Quotes:Single Quotes:#ifdef statement:\n"
4126 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
4127 + "CSS{"
4128 + "comment:s:cf:s:\"/*\":e:\"*/\":\n"
4129 + "curly braces:s:f:s:\"{\":e:\"}\":\n"
4130 + "round braces:s:f:s:\"(\":e:\")\":\n"
4131 + "double quotes:s:cfm:s:\"\"\"\":\n"
4132 + "single quotes:s:cfm:s:\"'\":\n"
4133 + "braces:g:comment:single quotes:double quotes:curly braces:round braces:\n}",
4134 + "Csh{"
4135 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4136 + "Single Quotes:s:cmf:s:\"'\":\n"
4137 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4138 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4139 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4140 + "if statement:s:f:sw:\"if\":mw:\"else\":ew:\"endif\":\n"
4141 + "switch statement:s:f:sw:\"switch\":mw:\"case\":mw:\"default\":ew:\"endsw\":\n"
4142 + "foreach statement:s:f:sw:\"for\":ew:\"end\":\n"
4143 + "while statement:s:f:sw:\"while\":ew:\"end\":\n"
4144 + "statement group:g:Double Quotes:Single Quotes:if statement:switch statement:foreach statement:while statement:\n"
4145 + "Braces:g:Double Quotes:Single Quotes:Squared braces:Round braces:Curly braces:\n}",
4146 + "Java{"
4147 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
4148 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4149 + "Single Quotes:s:cmf:s:\"'\":\n"
4150 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4151 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4152 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4153 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
4154 + "JavaScript{"
4155 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
4156 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4157 + "Single Quotes:s:cmf:s:\"'\":\n"
4158 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4159 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4160 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4161 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
4162 + "Makefile{"
4163 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4164 + "Single Quotes:s:cmf:s:\"'\":\n"
4165 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4166 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4167 + "Braces:g:Double Quotes:Single Quotes:Curly braces:Round braces:\n}",
4168 + "NEdit Macro{"
4169 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4170 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4171 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4172 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4173 + "Braces:g:Double Quotes:Curly braces:Round braces:Squared braces:\n}",
4174 + "Pascal{"
4175 + "Single Quotes:s:cmf:s:\"'\":\n"
4176 + "Comment1:s:cf:s:\"(*\":e:\"*)\":\n"
4177 + "Comment2:s:cf:s:\"{\":e:\"}\":\n"
4178 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4179 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4180 + "Block:s:f:swi:\"begin\":ewi:\"end\":\n"
4181 + "Case:s:fp:swi:\"case\":ewi:\"end\":\n"
4182 + "Record:s:f:swi:\"record\":ewi:\"end\":\n"
4183 + "Statement:g:Comment1:Comment2:Single Quotes:Block:Case:Record:\n"
4184 + "Braces:g:Comment1:Comment2:Single Quotes:Round braces:Squared braces:\n}",
4185 + "Perl{"
4186 + "Comment:s:cf:s:\"/*\":e:\"*/\":\n"
4187 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4188 + "Single Quotes:s:cmf:s:\"'\":\n"
4189 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4190 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4191 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4192 + "Braces:g:Comment:Double Quotes:Single Quotes:Curly braces:Round braces:Squared braces:\n}",
4193 + "SGML HTML{"
4194 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4195 + "Single Quotes:s:cmf:s:\"'\":\n"
4196 + "Sharp braces:s:f:s:\"<\":e:\">\":\n"
4197 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4198 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4199 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4200 + "Braces:g:Double Quotes:Single Quotes:Sharp braces:Curly braces:Round braces:Squared braces:\n}",
4201 + "Sh Ksh Bash{"
4202 + "Double Quotes:s:cmf:s:\"\"\"\":\n"
4203 + "Single Quotes:s:cmf:s:\"'\":\n"
4204 + "Back Quotes:s:cfm:s:\"`\":\n"
4205 + "Round braces:s:f:s:\"(\":e:\")\":\n"
4206 + "Curly braces:s:f:s:\"{\":e:\"}\":\n"
4207 + "Squared braces:s:f:s:\"[\":e:\"]\":\n"
4208 + "if statement:s:f:sw:\"if\":mw:\"elif\":mw:\"else\":ew:\"fi\":\n"
4209 + "case statement:s:f:sw:\"case\":ew:\"esac\":\n"
4210 + "for statement:s:f:sw:\"for\":mw:\"do\":ew:\"done\":\n"
4211 + "while statement:s:f:sw:\"while\":mw:\"do\":ew:\"done\":\n"
4212 + "statement group:g:Double Quotes:Single Quotes:if statement:case statement:for statement:while statement:\n"
4213 + "Braces:g:Double Quotes:Single Quotes:Back Quotes:Squared braces:Round braces:Curly braces:\n}",
4214 + "XML{"
4215 + "round braces:s:f:s:\"(\":e:\")\":\n"
4216 + "comment:s:cf:s:\"<!--\":e:\"-->\":\n"
4217 + "cdata + ignore:s:cf:sx:\"\\<!\\[((?icdata)|(\\s*IGNORE\\s*))\\[\":ex:\"\\]\\]\\>\":\n"
4218 + "short element:s:cf:sx:\"(?n\\<[\\l_][^@$%/\"\"';!>\\s]*(?=[^>]*/\\>))\":ex:\"/\\>\":\n"
4219 + "element pair:s:f:sx:\"(?n\\<(*1[\\l|_][^@$%/\"\"';!>\\s]*)\\>)\":sx:\"(?n\\<(*1[\\l|_][^@$%/\"\"';!>\\s]*)(?=[^>]*[^/]\\>))\":eix:\"\\</\\1\\>\":\n"
4220 + "processing instruction:s:f:sx:\"\\<\\?\\S+\":ex:\"\\?\\>\":\n"
4221 + "double quotes:s:cmf:s:\"\"\"\":\n"
4222 + "single quotes:s:cmf:s:\"'\":\n"
4223 + "tags:g:comment:double quotes:single quotes:round braces:cdata + ignore:element pair:short element:processing instruction:\n}",
4224 + };
4226 +static char *StandardStringMatchTable =
4227 + "{Round braces::fp:s:\"(\":e:\")\":\n"
4228 + "Curly braces::fp:s:\"{\":e:\"}\":\n"
4229 + "Squared braces::fp:s:\"[\":e:\"]\":\n}";
4232 +** Return string match table related to given language mode name.
4233 +** Return NULL, if no table is found.
4235 +void *FindStringMatchTable(const char *langModeName)
4237 + const char *nameToSearch;
4238 + int i;
4240 + if (langModeName == NULL)
4241 + nameToSearch = PLAIN_LM_STRING;
4242 + else
4243 + nameToSearch = langModeName;
4245 + for (i=0; i<NbrMatchTables; i++)
4246 + if (!strcmp(nameToSearch, MatchTables[i]->smtLanguageMode))
4247 + return (void *)MatchTables[i];
4248 + return NULL;
4252 +** Change the language mode name of string match tables for language
4253 +** "oldName" to "newName" in both the stored tables, and the table
4254 +** currently being edited in the dialog.
4256 +void RenameStringMatchTable(const char *oldName, const char *newName)
4258 + int i;
4260 + for (i=0; i<NbrMatchTables; i++)
4262 + if (!strcmp(oldName, MatchTables[i]->smtLanguageMode))
4264 + XtFree(MatchTables[i]->smtLanguageMode);
4265 + MatchTables[i]->smtLanguageMode = XtNewString(newName);
4268 + if (MatchPatternDialog.mpdShell != NULL)
4270 + if (!strcmp(MatchPatternDialog.mpdLangModeName, oldName))
4272 + XtFree(MatchPatternDialog.mpdLangModeName);
4273 + MatchPatternDialog.mpdLangModeName = XtNewString(newName);
4279 +** Delete string match table related to given language mode name.
4281 +void DeleteStringMatchTable(const char *langModeName)
4283 + int i;
4285 + for (i=0; i<NbrMatchTables; i++)
4287 + if (!strcmp(langModeName, MatchTables[i]->smtLanguageMode))
4289 + /*
4290 + * free (delete) existing matching pattern
4291 + */
4292 + freeStringMatchTable(MatchTables[i]);
4293 + memmove(
4294 + &MatchTables[i],
4295 + &MatchTables[i+1],
4296 + (NbrMatchTables-1 - i) * sizeof(StringMatchTable *));
4297 + NbrMatchTables--;
4298 + break;
4304 +** Assign a standard string match table to a given new language mode.
4306 +void AssignStandardStringMatchTable(const char *langModeName)
4308 + char *list;
4309 + StringMatchTable *newTable;
4311 + /*
4312 + * assign standard table for new language mode
4313 + * add table to end
4314 + */
4315 + list = StandardStringMatchTable;
4316 + newTable =
4317 + readMatchPatternSetContent(&list, list, XtNewString(langModeName));
4319 + /*
4320 + * add table to end
4321 + */
4322 + MatchTables[NbrMatchTables++] = newTable;
4326 +** Returns True if there is a string match table, or potential table
4327 +** not yet committed in the match pattern dialog for a language mode,
4329 +int LMHasStringMatchTable(const char *languageMode)
4331 + StringMatchTable *table = FindStringMatchTable(languageMode);
4333 + if (table != NULL && table->smtNumberOfSeqElements != 0)
4334 + return True;
4335 + return MatchPatternDialog.mpdShell != NULL &&
4336 + !strcmp(MatchPatternDialog.mpdLangModeName, languageMode) &&
4337 + MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements != 0;
4341 +** Read a string representing string matching pattern sets and add them
4342 +** to the StringMatchTable list of loaded string match patterns.
4343 +** Returns true, if read of string was successful.
4345 +int LoadMatchPatternString(char *inString)
4347 + char *inPtr = inString;
4348 + StringMatchTable *table;
4349 + int i;
4351 + for (;;)
4353 + /*
4354 + * read each matching pattern set
4355 + */
4356 + table = readMatchPatternSet(&inPtr);
4358 + if (table != NULL)
4360 + /*
4361 + * add/change the pattern set in the list
4362 + */
4363 + for (i=0; i<NbrMatchTables; i++)
4365 + if (!strcmp(MatchTables[i]->smtLanguageMode, table->smtLanguageMode))
4367 + freeStringMatchTable(MatchTables[i]);
4368 + MatchTables[i] = table;
4369 + break;
4372 + if (i == NbrMatchTables)
4374 + MatchTables[NbrMatchTables++] = table;
4375 + if (NbrMatchTables > MAX_LANGUAGE_MODES)
4377 + return False;
4382 + /*
4383 + * find end of this pattern. if the string ends here, we're done
4384 + */
4385 + inPtr = strstr(inPtr, "\n");
4386 + if (inPtr == NULL)
4388 + return True;
4391 + /*
4392 + * skip newline, tabs & spaces in front of next pattern.
4393 + * if the string ends here, we're done
4394 + */
4395 + inPtr += strspn(inPtr, " \t\n");
4396 + if (*inPtr == '\0')
4398 + return True;
4404 +** Create a string in the correct format for the matchPatterns resource,
4405 +** containing all of the matching pattern information from the stored
4406 +** matching pattern sets for this NEdit session.
4408 +char *WriteMatchPatternString(void)
4410 + char *outStr, *str, *escapedStr;
4411 + textBuffer *outBuf;
4412 + int i, written = False;
4413 + StringMatchTable *table;
4415 + outBuf = BufCreate();
4417 + for (i=0; i<NbrMatchTables; i++)
4419 + table = MatchTables[i];
4421 + written = True;
4423 + BufInsert(outBuf, outBuf->length, table->smtLanguageMode);
4424 + BufInsert(outBuf, outBuf->length, ":");
4426 + if (isDefaultMatchPatternTable(table))
4428 + BufInsert(outBuf, outBuf->length, "Default\n\t");
4430 + else
4432 + BufInsert(outBuf, outBuf->length, "{\n");
4433 + BufInsert(outBuf, outBuf->length,
4434 + str = createMatchPatternsString(table, "\t\t"));
4435 + XtFree(str);
4436 + BufInsert(outBuf, outBuf->length, "\t}\n\t");
4440 + /*
4441 + * Get the output string, and lop off the trailing newline and tab
4442 + */
4443 + outStr = BufGetRange(outBuf, 0, outBuf->length - (written?2:0));
4444 + BufFree(outBuf);
4446 + /*
4447 + * Protect newlines and backslashes from translation by the resource
4448 + * reader
4449 + */
4450 + escapedStr = EscapeSensitiveChars(outStr);
4452 + XtFree(outStr);
4454 + return escapedStr;
4458 +** Check, if last pattern is a duplicate of a previous pattern.
4459 +** Convert last pattern to a reference, if so.
4461 +static void treatDuplicatedPattern(
4462 + MatchPatternTable *table,
4463 + PatternElement *prevPattern,
4464 + PatternReference prevPatRef,
4465 + PatternElement *lastPattern,
4466 + PatternReference lastPatRef)
4468 + StringPattern *prevStringPat;
4469 + StringPattern *lastStringPat;
4470 + StringPattern *stringPat;
4471 + PatternReference *oldList;
4472 + int nbrOfRef;
4474 + /*
4475 + * No duplicate check needed, if previous pattern is a reference,
4476 + * due to the related multi pattern element is checked before.
4477 + */
4478 + if (prevPattern->peType == PET_REFERENCE)
4479 + return;
4481 + prevStringPat = GetStringPattern(table, prevPattern);
4482 + lastStringPat = GetStringPattern(table, lastPattern);
4484 + if (!AllocatedStringsDiffer(prevStringPat->spText, lastStringPat->spText) &&
4485 + !AllocatedStringsDiffer(prevStringPat->spOrigText, lastStringPat->spOrigText) &&
4486 + prevStringPat->spWordBoundary == lastStringPat->spWordBoundary &&
4487 + prevStringPat->spCaseInsensitive == lastStringPat->spCaseInsensitive &&
4488 + prevStringPat->spRegularExpression == lastStringPat->spRegularExpression)
4490 + /*
4491 + * Patterns are identical: Is prevPattern already a multi pattern ?
4492 + */
4493 + if (prevPattern->peType == PET_MULTIPLE)
4495 + /*
4496 + * just add ref. to "lastPattern" to the ref. list
4497 + */
4498 + (prevPattern->peVal.peuMulti.mpNumberOfReferences) ++;
4499 + nbrOfRef = prevPattern->peVal.peuMulti.mpNumberOfReferences;
4500 + oldList = prevPattern->peVal.peuMulti.mpRefList;
4501 + prevPattern->peVal.peuMulti.mpRefList =
4502 + (PatternReference *)XtMalloc( nbrOfRef * sizeof(PatternReference) );
4503 + memcpy(
4504 + prevPattern->peVal.peuMulti.mpRefList,
4505 + oldList,
4506 + (nbrOfRef-1) * sizeof(PatternReference) );
4507 + prevPattern->peVal.peuMulti.mpRefList[nbrOfRef-1] = lastPatRef;
4508 + XtFree( (char *)oldList );
4510 + else
4512 + /*
4513 + * convert prev. single pattern to multi pattern
4514 + */
4515 + stringPat = &prevPattern->peVal.peuSingle;
4516 + prevPattern->peType = PET_MULTIPLE;
4517 + prevPattern->peVal.peuMulti.mpStringPattern = *stringPat;
4518 + prevPattern->peVal.peuMulti.mpNumberOfReferences = 1;
4519 + prevPattern->peVal.peuMulti.mpRefList =
4520 + (PatternReference *)XtMalloc( sizeof(PatternReference) );
4521 + prevPattern->peVal.peuMulti.mpRefList[0] = lastPatRef;
4524 + /*
4525 + * convert last single pattern to reference
4526 + */
4527 + freeStringPattern( &(lastPattern->peVal.peuSingle) );
4528 + lastPattern->peType = PET_REFERENCE;
4529 + lastPattern->peVal.peuRef = prevPatRef;
4534 +** Check, if last pattern is a duplicate of a pattern stored within a
4535 +** previous match pattern table element.
4536 +** Convert last pattern to a reference, if so.
4538 +static void treatDuplicatedPatternElements(
4539 + MatchPatternTable *table,
4540 + MatchPatternTableElement *prevElement,
4541 + int prevElementIdx,
4542 + PatternElement *lastPattern,
4543 + PatternReference lastPatRef)
4545 + int i;
4546 + PatternReference prevPatRef;
4548 + prevPatRef.prElementIdx = prevElementIdx;
4550 + for (i=0; i<prevElement->mpteAll.pesNumberOfPattern; i++)
4552 + prevPatRef.prPatternIdx = i;
4553 + treatDuplicatedPattern(
4554 + table,
4555 + prevElement->mpteAll.pesPattern[i],
4556 + prevPatRef,
4557 + lastPattern,
4558 + lastPatRef);
4563 +** Check, if a pattern of last match pattern table element is a
4564 +** duplicate of a pattern stored within a previous match pattern table
4565 +** element.
4566 +** Convert duplicated last patterns to references, if so.
4568 +static void treatDuplicatedMTElements(
4569 + MatchPatternTable *table,
4570 + MatchPatternTableElement *prevElement,
4571 + int prevElementIdx,
4572 + MatchPatternTableElement *lastElement,
4573 + int lastElementIdx)
4575 + int i;
4576 + PatternReference lastPatRef;
4578 + lastPatRef.prElementIdx = lastElementIdx;
4580 + for (i=0; i<lastElement->mpteAll.pesNumberOfPattern; i++)
4582 + lastPatRef.prPatternIdx = i;
4583 + treatDuplicatedPatternElements(
4584 + table,
4585 + prevElement,
4586 + prevElementIdx,
4587 + lastElement->mpteAll.pesPattern[i],
4588 + lastPatRef);
4593 +** Convert all duplicated patterns of given match pattern table to
4594 +** references.
4596 +static void treatDuplicatedMTEntries(
4597 + MatchPatternTableElement **element,
4598 + int nbrOfElements)
4600 + int i;
4601 + MatchPatternTableElement *lastElement;
4602 + int lastElementIdx;
4603 + MatchPatternTable table;
4605 + if (nbrOfElements < 2)
4606 + return;
4608 + lastElementIdx = nbrOfElements - 1;
4609 + lastElement = element[lastElementIdx];
4611 + table.mptElements = element;
4612 + table.mptNumberOfElements = nbrOfElements;
4614 + for (i=0; i<nbrOfElements-1; i ++)
4616 + treatDuplicatedMTElements( &table, element[i], i, lastElement, lastElementIdx );
4621 +** Compile regular expressions of all string patterns of given
4622 +** match pattern table element.
4623 +** Returns true, if compilation fails.
4625 +static int createStrPatRegExpOfElement(
4626 + ReadMatchPatternInfo *readPatInfo,
4627 + MatchPatternTableElement *element,
4628 + ErrorInfo *errInfo)
4630 + int i;
4631 + StringPattern *strPat;
4633 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
4635 + strPat = getReadStringPattern(readPatInfo, element->mpteAll.pesPattern[i]);
4637 + /*
4638 + * if current string pattern holds a regular expression, then
4639 + * compile it
4640 + */
4641 + if (strPat->spRegularExpression)
4643 + if (createStrPatRegExp(strPat, errInfo))
4645 + /*
4646 + * compilation was not successful
4647 + */
4648 + errInfo->eiMPTabElementName = XtNewString(element->mpteName);
4649 + return True;
4654 + return False;
4658 +** Compile regular expressions of given string pattern.
4659 +** Returns true, if compilation fails.
4661 +static int createStrPatRegExp(
4662 + StringPattern *strPat,
4663 + ErrorInfo *errInfo)
4665 + char *regExpString;
4666 + char *compileMsg;
4668 + /*
4669 + * compose regular expression for start string pattern.
4670 + */
4671 + if( strPat->spCaseInsensitive)
4673 + /*
4674 + * Add '(?i .. )' to given text for case insensitive search.
4675 + * Allocate buffer to hold 5 more char than text length
4676 + * (4 char '(?i)' + \0 char.
4677 + */
4678 + regExpString = XtMalloc(strPat->spLength + 5);
4679 + strcpy(regExpString, "(?i");
4680 + strcat(regExpString, strPat->spText);
4681 + strcat(regExpString, ")");
4683 + else
4685 + regExpString = strPat->spText;
4688 + /*
4689 + * compile regular expression & free allocated string buffer,
4690 + * if applicable.
4691 + */
4692 + strPat->spTextRE =
4693 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
4695 + if (strPat->spTextRE == NULL)
4697 + /*
4698 + * compilation was not successful: adapt error reason by
4699 + * converting local backrefs to global ones.
4700 + */
4701 + adaptCompileMsg(compileMsg, strPat->spGlobalToLocalBackRef);
4703 + errInfo->eiRegExpCompileMsg = compileMsg;
4704 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
4707 + if (strPat->spCaseInsensitive)
4708 + XtFree( regExpString );
4710 + return (strPat->spTextRE == NULL);
4714 +** adapt regular expression compilation message by converting local
4715 +** backrefs to global ones.
4717 +static void adaptCompileMsg(
4718 + char *compileMsg,
4719 + int *globalToLocalBackRef)
4721 + int localId;
4722 + int globalId;
4723 + char *s = compileMsg;
4725 + while (*s != '\0')
4727 + if (*s == '\\')
4729 + if (isdigit((unsigned char)*(s+1)))
4731 + /*
4732 + * \n (n=1..9) found: substitute local by global back ref.
4733 + */
4734 + s ++;
4736 + localId =
4737 + (int)((unsigned char)*s - (unsigned char)'0');
4739 + globalId = localToGlobalBackRef(globalToLocalBackRef, localId);
4741 + *s = (char)((int)('0') + globalId);
4743 + else if (*(s+1) != '\0')
4744 + s ++;
4746 + s ++;
4751 +** translate given local backref to global backref by using
4752 +** given globalToLocalBackRef list.
4754 +static int localToGlobalBackRef(
4755 + int *globalToLocalBackRef,
4756 + int localId)
4758 + int i;
4760 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
4762 + if (globalToLocalBackRef[i] == localId)
4763 + return i+1;
4766 + return 0;
4770 +** Create a regular expression holding keywords of given start & end
4771 +** pattern set.
4772 +** Returns true, if creation of regular expression has failed.
4774 +static int createStartEndRegExp(
4775 + ReadMatchPatternInfo *readMatchPatternInfo,
4776 + MatchPatternTableElement *element,
4777 + ErrorInfo *errInfo)
4779 + char *regExpString;
4780 + char *compileMsg;
4782 + /*
4783 + * compose regular expression for start / end pattern.
4784 + */
4785 + composeStartEndRegExpString(
4786 + readMatchPatternInfo,
4787 + element,
4788 + &regExpString);
4790 + /*
4791 + * compile regular expression & free allocated string buffer.
4792 + */
4793 + element->mpteStartEndRE =
4794 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
4796 + XtFree( regExpString );
4798 + if( element->mpteStartEndRE == NULL)
4800 + errInfo->eiRegExpCompileMsg = compileMsg;
4801 + errInfo->eiDetail = "Error compiling start / end reg. exp.";
4804 + return (element->mpteStartEndRE == NULL);
4808 +** Create a regular expression holding keywords of given group element.
4809 +** Returns true, if creation of regular expression has failed.
4811 +static int createGroupRegExp(
4812 + ReadMatchPatternInfo *readPatInfo,
4813 + MatchPatternGroupElement *group,
4814 + ErrorInfo *errInfo)
4816 + int i;
4817 + MatchPatternTableElement *element;
4818 + RegExpStringInfo regExpStringInfo;
4819 + char *regExpString;
4820 + regexp *keywordRE;
4821 + char *compileMsg;
4823 + /*
4824 + * Allocate buffers for keyword regular expression of this group.
4825 + */
4826 + setupRegExpStringBuffers(
4827 + readPatInfo,
4828 + &regExpStringInfo);
4830 + for (i=0; i<group->mpgeNumberOfSubPatterns; i++)
4832 + element = getPatternOfName(readPatInfo, group->mpgeSubPatternIds[i]);
4833 + /*
4834 + * Add the keywords of the sub pattern to the keyword regular
4835 + * expression string buffer of new group.
4836 + */
4837 + addElementToRegExpString(
4838 + element,
4839 + readPatInfo,
4840 + &regExpStringInfo);
4843 + /*
4844 + * Assemble and compile the resulting keyword regular expression string.
4845 + */
4846 + catSMTRegExpStrings(
4847 + &regExpStringInfo,
4848 + &regExpString);
4850 + keywordRE = CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
4852 + XtFree( regExpString );
4854 + if (keywordRE == NULL)
4856 + errInfo->eiMPTabElementName = XtNewString(group->mpgeName);
4857 + errInfo->eiRegExpCompileMsg = compileMsg;
4858 + errInfo->eiDetail = "Group: Compile reg. exp. error";
4861 + group->mpgeKeywordRE = keywordRE;
4863 + return (keywordRE == NULL);
4867 +** Allocate memory for regular expression strings to be
4868 +** created out of read match pattern info.
4870 +static void setupRegExpStringBuffers(
4871 + ReadMatchPatternInfo *readMatchPatternInfo,
4872 + RegExpStringInfo *regExpStringInfo)
4874 + int totalLen;
4875 + int nbrOfMultiPatterns;
4876 + int sizeOfPatRefs;
4878 + /*
4879 + * determine total length of pattern characters to determine
4880 + * the size of a string buffer for the regular expression to
4881 + * compose. Count number of total multi patterns, too.
4882 + */
4883 + totalLen =
4884 + totalKeywordOfTableLen( readMatchPatternInfo, &nbrOfMultiPatterns );
4886 + /*
4887 + * allocate memory to store added multi pattern references (to avoid
4888 + * duplicated keywords strings later on).
4889 + */
4890 + sizeOfPatRefs = sizeof(PatternReference *) * nbrOfMultiPatterns;
4892 + regExpStringInfo->resiAddedMultiPat =
4893 + (PatternReference **)XtMalloc( sizeOfPatRefs );
4895 + regExpStringInfo->resiNbrOfAddedMultiPat = 0;
4897 + /*
4898 + * init. ID of capturing local backrefs
4899 + */
4900 + regExpStringInfo->resiLocalBackRefID = 1;
4902 + /*
4903 + * allocate & init. string buffers for regular expression:
4904 + * 3 times the size + x of all pattern characters (due to
4905 + * a.) each char may need to be escaped
4906 + * b.) '<(?:', ')>', ')' and '|' need to be added.
4907 + */
4908 + regExpStringInfo->resiNoneWBRegExpString = XtMalloc( 3 * totalLen );
4909 + regExpStringInfo->resiLeftWBRegExpString = XtMalloc( 3 * totalLen + 5 );
4910 + regExpStringInfo->resiRightWBRegExpString = XtMalloc( 3 * totalLen + 5 );
4911 + regExpStringInfo->resiBothWBRegExpString = XtMalloc( 3 * totalLen + 6 );
4913 + strcpy( regExpStringInfo->resiNoneWBRegExpString, "" );
4914 + strcpy( regExpStringInfo->resiLeftWBRegExpString, "" );
4915 + strcpy( regExpStringInfo->resiRightWBRegExpString, "" );
4916 + strcpy( regExpStringInfo->resiBothWBRegExpString, "" );
4920 +** Concatenate given 'partToAdd' string to result string, separated
4921 +** by an OR ('|'). Add 'postfix' at end of result string.
4923 +static void addSMTRegExpString(
4924 + char *result,
4925 + char *partToAdd,
4926 + const char *postfix)
4928 + if (strlen(partToAdd) != 0)
4930 + if (strlen(result) != 0)
4932 + strcat( result, "|" );
4935 + strcat( result, partToAdd );
4937 + strcat( result, postfix );
4943 +** Return a string representing given string match table.
4945 +static char *createMatchPatternsString(
4946 + StringMatchTable *table,
4947 + char *indentStr)
4949 + char *outStr, *str;
4950 + textBuffer *outBuf;
4951 + int i, j;
4952 + MatchPatternSequenceElement *seq;
4953 + MatchPatternTableElement *element;
4954 + MatchPatternGroupElement *group;
4956 + outBuf = BufCreate();
4958 + for (i=0; i<table->smtNumberOfSeqElements; i++)
4960 + seq = table->smtSequence[i];
4962 + BufInsert(outBuf, outBuf->length, indentStr);
4963 + BufInsert(outBuf, outBuf->length, seq->mpseName);
4964 + BufInsert(outBuf, outBuf->length, ":");
4966 + if (seq->mpseType == MPT_GROUP)
4968 + BufInsert(outBuf, outBuf->length, "g:");
4970 + group = table->smtGroups[seq->mpseIndex];
4972 + for (j=0; j < group->mpgeNumberOfSubPatterns; j ++)
4974 + BufInsert(outBuf, outBuf->length, group->mpgeSubPatternIds[j]);
4975 + BufInsert(outBuf, outBuf->length, ":");
4978 + else
4980 + if (seq->mpseType == MPT_SUB)
4982 + BufInsert(outBuf, outBuf->length, "s");
4984 + BufInsert(outBuf, outBuf->length, ":");
4986 + element = table->smtAllPatterns->mptElements[seq->mpseIndex];
4988 + /*
4989 + * write global attributes
4990 + */
4991 + if (element->mpteSkipBtwnStartEnd)
4992 + BufInsert(outBuf, outBuf->length, "c");
4993 + if (element->mpteFlash)
4994 + BufInsert(outBuf, outBuf->length, "f");
4995 + if (element->mpteIsMonoPattern)
4996 + BufInsert(outBuf, outBuf->length, "m");
4997 + if (element->mpteIgnoreHighLightInfo)
4998 + BufInsert(outBuf, outBuf->length, "p");
4999 + BufInsert(outBuf, outBuf->length, ":");
5001 + /*
5002 + * write string patterns
5003 + */
5004 + for (j=0; j < element->mpteAll.pesNumberOfPattern; j ++)
5006 + BufInsert(
5007 + outBuf,
5008 + outBuf->length,
5009 + str =
5010 + createPatternElementString(
5011 + table->smtAllPatterns,
5012 + element->mpteAll.pesPattern[j]));
5013 + XtFree(str);
5017 + BufInsert(outBuf, outBuf->length, "\n");
5020 + outStr = BufGetAll(outBuf);
5021 + BufFree(outBuf);
5023 + return outStr;
5027 +** Return a string representing given pattern element.
5029 +static char *createPatternElementString(
5030 + MatchPatternTable *table,
5031 + PatternElement *pat)
5033 + char *outStr, *str;
5034 + textBuffer *outBuf;
5035 + StringPattern *strPat;
5037 + outBuf = BufCreate();
5039 + strPat = GetStringPattern(table, pat);
5041 + /*
5042 + * write string pattern kind
5043 + */
5044 + if (pat->peKind == PEK_START)
5045 + BufInsert(outBuf, outBuf->length, "s");
5046 + else if (pat->peKind == PEK_MIDDLE)
5047 + BufInsert(outBuf, outBuf->length, "m");
5048 + else if (pat->peKind == PEK_END)
5049 + BufInsert(outBuf, outBuf->length, "e");
5051 + /*
5052 + * write word boundary
5053 + */
5054 + if (strPat->spWordBoundary == PWB_BOTH)
5055 + BufInsert(outBuf, outBuf->length, "w");
5056 + else if (strPat->spWordBoundary == PWB_LEFT)
5057 + BufInsert(outBuf, outBuf->length, "l");
5058 + else if (strPat->spWordBoundary == PWB_RIGHT)
5059 + BufInsert(outBuf, outBuf->length, "r");
5061 + /*
5062 + * write case insensitive flag
5063 + */
5064 + if (strPat->spCaseInsensitive)
5065 + BufInsert(outBuf, outBuf->length, "i");
5067 + /*
5068 + * write regular expression flag
5069 + */
5070 + if (strPat->spRegularExpression)
5071 + BufInsert(outBuf, outBuf->length, "x");
5073 + BufInsert(outBuf, outBuf->length, ":");
5075 + /*
5076 + * write pattern string
5077 + */
5078 + if( strPat->spOrigText != NULL)
5079 + BufInsert(
5080 + outBuf,
5081 + outBuf->length,
5082 + str = MakeQuotedString(strPat->spOrigText));
5083 + else
5084 + BufInsert(
5085 + outBuf,
5086 + outBuf->length,
5087 + str = MakeQuotedString(strPat->spText));
5088 + XtFree(str);
5090 + BufInsert(outBuf, outBuf->length, ":");
5092 + outStr = BufGetAll(outBuf);
5093 + BufFree(outBuf);
5095 + return outStr;
5099 +** Given a language mode name, determine if there is a default (built-in)
5100 +** string match table available for that language mode, and if so, read it and
5101 +** return a new allocated copy of it. The returned pattern set should be
5102 +** freed by the caller with freeStringMatchTable().
5104 +static StringMatchTable *readDefaultStringMatchTable(const char *langModeName)
5106 + int i, modeNameLen;
5107 + char *list;
5109 + modeNameLen = strlen(langModeName);
5111 + for (i=0; i<(int)XtNumber(DefaultStringMatchTable); i++)
5113 + if (!strncmp(langModeName, DefaultStringMatchTable[i], modeNameLen) &&
5114 + DefaultStringMatchTable[i][modeNameLen] == '{')
5116 + list = DefaultStringMatchTable[i];
5117 + return readMatchPatternSet(&list);
5121 + list = StandardStringMatchTable;
5122 + return readMatchPatternSetContent(&list, list, XtNewString(langModeName));
5126 +** Return true, if table exactly matches one of the default matching
5127 +** pattern tables.
5129 +static int isDefaultMatchPatternTable(StringMatchTable *table)
5131 + StringMatchTable *defaultTable;
5132 + int retVal;
5134 + defaultTable = readDefaultStringMatchTable(table->smtLanguageMode);
5136 + if (defaultTable == NULL)
5137 + return False;
5139 + retVal = !stringMatchTableDiffer(table, defaultTable);
5141 + freeStringMatchTable(defaultTable);
5143 + return retVal;
5147 +** Read in a string match pattern table character string,
5148 +** and advance *inPtr beyond it.
5149 +** Returns NULL and outputs an error to stderr on failure.
5151 +static StringMatchTable *readMatchPatternSet(char **inPtr)
5153 + char *languageMode;
5154 + StringMatchTable *table = NULL;
5155 + char *stringStart = *inPtr;
5156 + ErrorInfo errInfo;
5158 + initErrorInfo(&errInfo);
5160 + /*
5161 + * remove leading whitespace
5162 + */
5163 + *inPtr += strspn(*inPtr, " \t\n");
5165 + /*
5166 + * read language mode field
5167 + */
5168 + languageMode = ReadSymbolicField(inPtr);
5170 + /*
5171 + * look for initial brace
5172 + */
5173 + if (**inPtr == ':')
5175 + (*inPtr) ++;
5176 + /*
5177 + * look for "Default" keyword, and if it's there, return the default
5178 + * pattern set
5179 + */
5180 + if (!strncmp(*inPtr, "Default", 7))
5182 + *inPtr += 7;
5183 + table = readDefaultStringMatchTable(languageMode);
5184 + XtFree(languageMode);
5186 + return table;
5190 + table = readMatchPatternSetContent(inPtr, stringStart, languageMode);
5192 + if (table == NULL)
5193 + XtFree(languageMode);
5195 + return table;
5199 +** Read in a content string ("{..}") of match pattern table,
5200 +** and advance *inPtr beyond it.
5201 +** Returns NULL and outputs an error to stderr on failure.
5203 +static StringMatchTable *readMatchPatternSetContent(
5204 + char **inPtr,
5205 + char *stringStart,
5206 + char *languageMode)
5208 + ReadMatchPatternInfo readPatInfo;
5209 + StringMatchTable *table = NULL;
5210 + ErrorInfo errInfo;
5211 + int successful = True;
5212 + int endOfPatternSet = False;
5214 + initErrorInfo(&errInfo);
5216 + /*
5217 + * look for initial brace
5218 + */
5219 + if (**inPtr != '{')
5221 + errInfo.eiLanguageMode = XtNewString(languageMode);
5222 + errInfo.eiDetail = "pattern list must begin with \"{\"";
5223 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo );
5225 + return NULL;
5228 + (*inPtr)++;
5230 + readPatInfo.rmpiNbrOfElements = 0;
5231 + readPatInfo.rmpiNbrOfGroups = 0;
5232 + readPatInfo.rmpiNbrOfSeqElements = 0;
5233 + readPatInfo.rmpiAllPatRE = NULL;
5234 + readPatInfo.rmpiFlashPatRE = NULL;
5236 + /*
5237 + * parse each pattern in the list
5238 + */
5239 + while (successful && !endOfPatternSet)
5241 + *inPtr += strspn(*inPtr, " \t\n");
5242 + if (**inPtr == '\0')
5244 + errInfo.eiLanguageMode = XtNewString(languageMode);
5245 + errInfo.eiDetail = "end of pattern list not found";
5246 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo);
5247 + successful = False;
5249 + else if (**inPtr == '}')
5251 + (*inPtr)++;
5252 + endOfPatternSet = True;
5254 + else
5256 + if (!readMatchPatternEntry(inPtr, &errInfo, &readPatInfo))
5258 + errInfo.eiLanguageMode = XtNewString(languageMode);
5259 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo);
5260 + successful = False;
5265 + if (successful)
5267 + /*
5268 + * compile regular expressions of read patterns
5269 + */
5270 + if (createRegExpOfPatterns(&readPatInfo, &errInfo))
5272 + parseMatchingPatternSetError(stringStart, *inPtr, &errInfo);
5273 + successful = False;
5277 + if (successful)
5279 + return createStringMatchTable(&readPatInfo, languageMode);
5281 + else
5283 + /*
5284 + * free memory of already read patterns
5285 + */
5286 + freeReadMatchPatternInfo(&readPatInfo);
5288 + return NULL;
5291 + return table;
5295 +** Create a reg. exp. of all patterns contained
5296 +** in given read match pattern info.
5298 +static int createRegExpOfPatterns(
5299 + ReadMatchPatternInfo *readPatInfo,
5300 + ErrorInfo *errInfo)
5302 + if (createRegExpOfStrPatterns(readPatInfo, errInfo))
5303 + return True;
5305 + if (createRegExpOfAllPatterns(readPatInfo, errInfo))
5306 + return True;
5308 + return False;
5312 +** Create a "total pattern reg. exp." of all patterns / flash patterns
5313 +** contained in given read match pattern info.
5314 +** Returns true, if create of reg. exp. has failed.
5316 +static int createRegExpOfAllPatterns(
5317 + ReadMatchPatternInfo *readPatInfo,
5318 + ErrorInfo *errInfo)
5320 + int i;
5321 + RegExpStringInfo allPatRegExpSI;
5322 + RegExpStringInfo flashPatRegExpSI;
5323 + MatchPatternTableElement *element;
5324 + char *regExpString;
5325 + char *compileMsg;
5327 + /*
5328 + * Allocate buffers for keyword regular expressions.
5329 + */
5330 + setupRegExpStringBuffers(readPatInfo, &allPatRegExpSI);
5331 + setupRegExpStringBuffers(readPatInfo, &flashPatRegExpSI);
5333 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5335 + element = readPatInfo->rmpiElement[i];
5337 + /*
5338 + * Add the keywords of the matching pattern to the keyword
5339 + * regular expression string buffer of all patterns.
5340 + */
5341 + addElementToRegExpString(
5342 + element,
5343 + readPatInfo,
5344 + &allPatRegExpSI);
5346 + /*
5347 + * If flash attribute is set, then add the keywords of the
5348 + * matching pattern also to the keyword regular expression
5349 + * string buffer of flash patterns.
5350 + */
5351 + if (element->mpteFlash)
5353 + addElementToRegExpString(
5354 + element,
5355 + readPatInfo,
5356 + &flashPatRegExpSI);
5360 + /*
5361 + * Assemble and compile the resulting all keywords reg. exp. string.
5362 + */
5363 + catSMTRegExpStrings(
5364 + &allPatRegExpSI,
5365 + &regExpString);
5367 + readPatInfo->rmpiAllPatRE =
5368 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
5370 + XtFree( regExpString );
5372 + if (readPatInfo->rmpiAllPatRE == NULL)
5374 + errInfo->eiRegExpCompileMsg = compileMsg;
5375 + errInfo->eiDetail = "All patterns: compile reg. exp. error";
5376 + return True;
5379 + /*
5380 + * Assemble and compile the resulting flash keywords reg. exp. string.
5381 + */
5382 + catSMTRegExpStrings(
5383 + &flashPatRegExpSI,
5384 + &regExpString);
5386 + readPatInfo->rmpiFlashPatRE =
5387 + CompileRE(regExpString, &compileMsg, REDFLT_STANDARD);
5389 + XtFree( regExpString );
5391 + if (readPatInfo->rmpiFlashPatRE == NULL)
5393 + errInfo->eiRegExpCompileMsg = compileMsg;
5394 + errInfo->eiDetail = "Flash patterns: compile reg. exp. error";
5395 + return True;
5398 + /*
5399 + * Pattern reg. exp. successful created:
5400 + */
5401 + return False;
5405 +** Create reg. exp. of single patterns contained in given
5406 +** read match pattern info.
5407 +** Returns true, if create of reg. exp. has failed.
5409 +static int createRegExpOfStrPatterns(
5410 + ReadMatchPatternInfo *readPatInfo,
5411 + ErrorInfo *errInfo)
5413 + int i;
5414 + MatchPatternTableElement *element;
5415 + MatchPatternGroupElement *group;
5417 + /*
5418 + * create global backref list of all elements of read info
5419 + */
5420 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5422 + element = readPatInfo->rmpiElement[i];
5424 + if (!createGlobalBackRefList(readPatInfo, element, errInfo))
5425 + return True;
5428 + /*
5429 + * resolve global backrefs of all elements of read info
5430 + */
5431 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5433 + element = readPatInfo->rmpiElement[i];
5435 + if (!resolveGlobalBackRefs(readPatInfo, element, errInfo))
5436 + return True;
5439 + /*
5440 + * compile reg. exp. of all elements of read info
5441 + */
5442 + for (i=0; i < readPatInfo->rmpiNbrOfElements; i ++)
5444 + element = readPatInfo->rmpiElement[i];
5446 + if (createStrPatRegExpOfElement(readPatInfo, element, errInfo))
5447 + return True;
5449 + /*
5450 + * create start / end reg. exp. if applicable.
5451 + */
5452 + if (element->mpteSkipBtwnStartEnd)
5454 + if (createStartEndRegExp(readPatInfo, element, errInfo))
5455 + return True;
5459 + /*
5460 + * compile reg. exp. of all groups of read info
5461 + */
5462 + for (i=0; i < readPatInfo->rmpiNbrOfGroups; i ++)
5464 + group = readPatInfo->rmpiGroup[i];
5466 + if (createGroupRegExp(readPatInfo, group, errInfo))
5468 + return True;
5472 + return False;
5476 +** Create a string match table out of read match pattern info.
5478 +static StringMatchTable *createStringMatchTable(
5479 + ReadMatchPatternInfo *readPatInfo,
5480 + char *languageMode)
5482 + StringMatchTable *table;
5483 + MatchPatternTable *patTable;
5484 + int sizeOfElements;
5486 + table = (StringMatchTable *)XtMalloc(sizeof(StringMatchTable));
5487 + table->smtLanguageMode = languageMode;
5489 + /*
5490 + * allocate a more appropriately sized list to return matching patterns
5491 + */
5492 + patTable = (MatchPatternTable *)XtMalloc(sizeof(MatchPatternTable));
5493 + patTable->mptNumberOfElements = readPatInfo->rmpiNbrOfElements;
5495 + if (readPatInfo->rmpiNbrOfElements > 0)
5497 + sizeOfElements =
5498 + sizeof(MatchPatternTableElement *) * readPatInfo->rmpiNbrOfElements;
5499 + patTable->mptElements =
5500 + (MatchPatternTableElement **)XtMalloc(sizeOfElements);
5501 + memcpy(patTable->mptElements, readPatInfo->rmpiElement, sizeOfElements);
5503 + else
5505 + patTable->mptElements = NULL;
5508 + table->smtAllPatterns = patTable;
5510 + table->smtAllPatRE = readPatInfo->rmpiAllPatRE;
5511 + table->smtFlashPatRE = readPatInfo->rmpiFlashPatRE;
5512 + table->smtUsedPatRE = NULL;
5514 + /*
5515 + * allocate a more appropriately sized list to return matching pattern groups
5516 + */
5517 + table->smtNumberOfGroups = readPatInfo->rmpiNbrOfGroups;
5518 + if (readPatInfo->rmpiNbrOfGroups > 0)
5520 + sizeOfElements =
5521 + sizeof(MatchPatternGroupElement *) * readPatInfo->rmpiNbrOfGroups;
5522 + table->smtGroups =
5523 + (MatchPatternGroupElement **)XtMalloc(sizeOfElements);
5524 + memcpy(table->smtGroups, readPatInfo->rmpiGroup, sizeOfElements);
5526 + else
5528 + table->smtGroups = NULL;
5530 + /*
5531 + * allocate a more appropriately sized list to return matching pattern sequence
5532 + */
5533 + table->smtNumberOfSeqElements = readPatInfo->rmpiNbrOfSeqElements;
5534 + if (readPatInfo->rmpiNbrOfSeqElements > 0)
5536 + sizeOfElements =
5537 + sizeof(MatchPatternSequenceElement *) * readPatInfo->rmpiNbrOfSeqElements;
5538 + table->smtSequence =
5539 + (MatchPatternSequenceElement **)XtMalloc(sizeOfElements);
5540 + memcpy(table->smtSequence, readPatInfo->rmpiSequence, sizeOfElements);
5542 + else
5544 + table->smtSequence = NULL;
5547 + return table;
5551 +** Read one match pattern entry of a match pattern string.
5552 +** Returns true, if read was successful.
5554 +static int readMatchPatternEntry(
5555 + char **inPtr,
5556 + ErrorInfo *errInfo,
5557 + ReadMatchPatternInfo *info)
5559 + char *name;
5560 + MatchPatternType type;
5561 + MatchPatternGroupElement *readGroup;
5562 + MatchPatternTableElement *readElement;
5564 + if (!getMPSName( inPtr, errInfo, &name ))
5566 + return False;
5569 + if (!getMPSTypeAttribute( inPtr, errInfo, &type ))
5571 + errInfo->eiMPTabElementName = XtNewString(name);
5572 + return False;
5575 + if (type == MPT_GROUP)
5577 + if (info->rmpiNbrOfGroups >= MAX_NBR_MATCH_PATTERN_GROUPS)
5579 + errInfo->eiMPTabElementName = XtNewString(name);
5580 + errInfo->eiDetail = "max number of match pattern groups exceeded";
5581 + return False;
5584 + readGroup = readMatchPatternGroup( inPtr, errInfo, name, info );
5586 + if (readGroup == NULL)
5588 + errInfo->eiMPTabElementName = XtNewString(name);
5589 + XtFree( name );
5591 + else
5593 + info->rmpiGroup[info->rmpiNbrOfGroups ++] = readGroup;
5595 + recordPatternSequence( info, name, type, info->rmpiNbrOfGroups-1 );
5598 + return (readGroup != NULL);
5600 + else
5602 + if (info->rmpiNbrOfElements >= MAX_NBR_MATCH_PATTERNS)
5604 + errInfo->eiMPTabElementName = XtNewString(name);
5605 + errInfo->eiDetail = "max number of match patterns exceeded";
5606 + XtFree( name );
5607 + return False;
5610 + readElement =
5611 + readMatchPatternTableElement( inPtr, &errInfo->eiDetail, name, type );
5613 + if (readElement == NULL)
5615 + errInfo->eiMPTabElementName = XtNewString(name);
5616 + XtFree( name );
5618 + else
5620 + readElement->mpteIndex = info->rmpiNbrOfElements;
5622 + info->rmpiElement[info->rmpiNbrOfElements ++] = readElement;
5624 + if (type == MPT_INDIVIDUAL)
5626 + if (!assignIndividualGroup( info, &errInfo->eiDetail, readElement ))
5628 + errInfo->eiMPTabElementName = XtNewString(name);
5629 + return False;
5633 + treatDuplicatedMTEntries(
5634 + info->rmpiElement, info->rmpiNbrOfElements );
5636 + recordPatternSequence( info, name, type, info->rmpiNbrOfElements-1 );
5639 + return (readElement != NULL);
5644 +** Record match pattern sequence for display of match pattern dialog.
5646 +static void recordPatternSequence(
5647 + ReadMatchPatternInfo *info,
5648 + char *name,
5649 + MatchPatternType type,
5650 + int index)
5652 + MatchPatternSequenceElement *sequence;
5654 + sequence =
5655 + (MatchPatternSequenceElement *)XtMalloc( sizeof(MatchPatternSequenceElement) );
5657 + sequence->mpseName = XtNewString(name);
5658 + sequence->mpseType = type;
5659 + sequence->mpseIndex = index;
5661 + info->rmpiSequence[info->rmpiNbrOfSeqElements ++] = sequence;
5665 +** Assign a new group to an individual match pattern.
5666 +** Returns true, if assignment was successful.
5668 +static int assignIndividualGroup(
5669 + ReadMatchPatternInfo *info,
5670 + char **errMsg,
5671 + MatchPatternTableElement *element)
5673 + MatchPatternGroupElement *group = NULL;
5675 + if (info->rmpiNbrOfGroups >= MAX_NBR_MATCH_PATTERN_GROUPS)
5677 + *errMsg = "max. number of matching pattern groups exceeded\n";
5678 + return False;
5681 + /*
5682 + * Assign the index of new group to the individual matching pattern
5683 + */
5684 + element->mpteGroup = info->rmpiNbrOfGroups;
5686 + /*
5687 + * Allocate memory for the matching pattern group and copy the
5688 + * info into this group element.
5689 + */
5690 + group =
5691 + (MatchPatternGroupElement *)XtMalloc( sizeof(MatchPatternGroupElement) );
5693 + group->mpgeName = NULL;
5694 + group->mpgeKeywordRE = NULL;
5696 + /*
5697 + * remember name of match pattern table element, which is
5698 + * represented by this group.
5699 + */
5700 + group->mpgeNumberOfSubPatterns = 1;
5701 + group->mpgeSubPatternIds = (char **)XtMalloc( sizeof(char *) );
5702 + group->mpgeSubPatternIds[0] = XtNewString(element->mpteName);
5704 + info->rmpiGroup[info->rmpiNbrOfGroups ++] = group;
5706 + return True;
5710 +** Get the match pattern table element of given 'patToSearch'
5711 +** name.
5712 +** Returns NULL, if no element was found.
5714 +static MatchPatternTableElement *getPatternOfName(
5715 + ReadMatchPatternInfo *info,
5716 + char *patToSearch)
5718 + int i;
5719 + MatchPatternTableElement *element;
5721 + for (i=0; i<info->rmpiNbrOfElements; i ++)
5723 + element = info->rmpiElement[i];
5725 + if (strcmp( element->mpteName, patToSearch ) == 0)
5727 + /*
5728 + * Related sub-pattern found:
5729 + */
5730 + return element;
5734 + /*
5735 + * No sub-pattern found:
5736 + */
5737 + return NULL;
5741 +** Read match pattern group of given match pattern string.
5742 +** Returns NULL, if read fails.
5744 +static MatchPatternGroupElement *readMatchPatternGroup(
5745 + char **inPtr,
5746 + ErrorInfo *errInfo,
5747 + char *name,
5748 + ReadMatchPatternInfo *info)
5750 + int i;
5751 + int error = False;
5752 + char *patNameInPtr;
5753 + char *subPatName;
5754 + MatchPatternTableElement *subPatElement;
5755 + int numberOfRelatedSubPattern = 0;
5756 + char *relatedSubPatternId[MAX_NBR_MATCH_PATTERNS];
5757 + int sizeOfIds;
5758 + MatchPatternGroupElement *group = NULL;
5760 + /*
5761 + * Read sub-matching patterns of this group.
5762 + */
5763 + while (**inPtr != '\n' && !error)
5765 + /*
5766 + * Read next pattern name from inPtr.
5767 + */
5768 + patNameInPtr = *inPtr;
5769 + subPatName = ReadSymbolicField(inPtr);
5771 + if (subPatName == NULL)
5773 + errInfo->eiDetail = "Sub-Matching Pattern Name expected";
5774 + error = True;
5776 + else
5778 + /*
5779 + * Get matching pattern related to sub-matching pattern name.
5780 + */
5781 + subPatElement =
5782 + getPatternOfName( info, subPatName );
5784 + if (subPatElement == NULL)
5786 + errInfo->eiStringPatText = XtNewString(subPatName);
5787 + errInfo->eiDetail = "Sub-Matching Pattern not defined before";
5788 + error = True;
5790 + else if (numberOfRelatedSubPattern >= MAX_NBR_MATCH_PATTERNS)
5792 + errInfo->eiDetail = "Group holds too many Sub-Matching Patterns";
5793 + error = True;
5795 + else if (subPatElement->mpteType != MPT_SUB)
5797 + errInfo->eiStringPatText = XtNewString(subPatName);
5798 + errInfo->eiDetail = "Not a Sub-Matching Pattern";
5799 + error = True;
5801 + else
5803 + /*
5804 + * Remember sub-matching pattern ID
5805 + */
5806 + relatedSubPatternId[numberOfRelatedSubPattern ++] = subPatName;
5808 + /*
5809 + * Assign the index of this group to the sub-matching pattern
5810 + * if no group index was assigned before.
5811 + */
5812 + if (subPatElement->mpteGroup == NO_GROUP_IDX)
5814 + subPatElement->mpteGroup = info->rmpiNbrOfGroups;
5818 + /*
5819 + * Skip to the start of the next matching pattern name.
5820 + */
5821 + if (!error && !SkipDelimiter(inPtr, &errInfo->eiDetail))
5823 + error = True;
5828 + if (error)
5830 + for (i=0; i < numberOfRelatedSubPattern; i++)
5832 + XtFree( relatedSubPatternId[i] );
5835 + return NULL;
5837 + else
5839 + /*
5840 + * Allocate memory for the matching pattern group and copy the
5841 + * info into this group element.
5842 + */
5843 + group =
5844 + (MatchPatternGroupElement *)XtMalloc( sizeof(MatchPatternGroupElement) );
5846 + group->mpgeName = name;
5847 + group->mpgeKeywordRE = NULL;
5849 + /*
5850 + * Allocate memory for the sub-matching pattern IDs & copy
5851 + * related sub-matching pattern into the group element.
5852 + */
5853 + sizeOfIds = sizeof(char *) * numberOfRelatedSubPattern;
5854 + group->mpgeSubPatternIds = (char **)XtMalloc( sizeOfIds );
5856 + memcpy(group->mpgeSubPatternIds, relatedSubPatternId, sizeOfIds);
5858 + group->mpgeNumberOfSubPatterns = numberOfRelatedSubPattern;
5860 + return group;
5865 +** Read one match pattern element from given match pattern string.
5866 +** Returns true, if read was successful.
5868 +static int readPatternElement(
5869 + char **inPtr,
5870 + char **errMsg,
5871 + PatternElement **pattern)
5873 + PatternElementKind patternKind;
5874 + PatternWordBoundary wordBoundary;
5875 + int caseInsensitive;
5876 + int regularExpression;
5877 + char *string;
5879 + if (!getMPSPatternAttribute(
5880 + inPtr,
5881 + errMsg,
5882 + &patternKind,
5883 + &wordBoundary,
5884 + &caseInsensitive,
5885 + &regularExpression ))
5887 + return False;
5890 + if (!ReadQuotedString(inPtr, errMsg, &string))
5892 + return False;
5895 + if (!SkipDelimiter(inPtr, errMsg))
5897 + XtFree( string );
5898 + return False;
5901 + *pattern =
5902 + createPatternElement(
5903 + string,
5904 + patternKind,
5905 + wordBoundary,
5906 + caseInsensitive,
5907 + regularExpression);
5909 + return True;
5913 +** Create a pattern element.
5915 +static PatternElement *createPatternElement(
5916 + char *patternText,
5917 + PatternElementKind patternKind,
5918 + PatternWordBoundary wordBoundary,
5919 + int caseInsensitive,
5920 + int regularExpression)
5922 + PatternElement *pattern;
5923 + char *s;
5925 + /*
5926 + * Convert pattern text to lower case, if case insensitive
5927 + * attribute is set.
5928 + */
5929 + if (caseInsensitive)
5931 + for (s = patternText; *s != '\0'; s ++)
5933 + *s = tolower(*s);
5937 + /*
5938 + * Allocate memory for the new pattern element and init. / copy
5939 + * related info into this pattern element.
5940 + */
5941 + pattern = (PatternElement *)XtMalloc( sizeof(PatternElement) );
5943 + initStrPatBackRefList(&pattern->peVal.peuSingle);
5945 + pattern->peKind = patternKind;
5946 + pattern->peIndex = NO_PATTERN_IDX;
5947 + pattern->peType = PET_SINGLE;
5949 + pattern->peVal.peuSingle.spLength = strlen(patternText);
5950 + pattern->peVal.peuSingle.spBackRefParsed = False;
5951 + pattern->peVal.peuSingle.spBackRefResolved = False;
5953 + pattern->peVal.peuSingle.spCaseInsensitive = caseInsensitive;
5954 + pattern->peVal.peuSingle.spRegularExpression = regularExpression;
5955 + pattern->peVal.peuSingle.spTextRE = NULL;
5957 + /*
5958 + * Store original string of regular expression patterns due to
5959 + * it may be later adapted (e.g. due to global backrefs etc.).
5960 + */
5961 + if (regularExpression)
5963 + pattern->peVal.peuSingle.spOrigText = patternText;
5964 + pattern->peVal.peuSingle.spText = NULL;
5965 + pattern->peVal.peuSingle.spWordBoundary = PWB_NONE;
5967 + else
5969 + pattern->peVal.peuSingle.spOrigText = NULL;
5970 + pattern->peVal.peuSingle.spText = patternText;
5971 + pattern->peVal.peuSingle.spWordBoundary = wordBoundary;
5974 + return pattern;
5978 +** Create a list holding all global backref definitions of given
5979 +** match pattern table element. The list is stored in this given
5980 +** element.
5981 +** Returns true, if list was successfully created.
5983 +static int createGlobalBackRefList(
5984 + ReadMatchPatternInfo *readPatInfo,
5985 + MatchPatternTableElement *element,
5986 + ErrorInfo *errInfo)
5988 + int i;
5989 + StringPattern *strPat;
5991 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
5993 + strPat = getReadStringPattern(readPatInfo, element->mpteAll.pesPattern[i]);
5995 + if (strPat->spRegularExpression)
5997 + if (strPat->spBackRefParsed)
5999 + /*
6000 + * Global backrefs or this string pattern already parsed:
6001 + * just merge string pattern list with elements one.
6002 + */
6003 + if (!updateGlobalBackRefs(
6004 + strPat,
6005 + element->mpteGlobalBackRef,
6006 + errInfo))
6008 + return False;
6011 + else
6013 + /*
6014 + * parse string pattern for global backrefs and
6015 + * merge string pattern list with elements one.
6016 + */
6017 + if (!parseGlobalBackRefs(
6018 + strPat,
6019 + element->mpteGlobalBackRef,
6020 + errInfo))
6022 + return False;
6028 + return True;
6032 +** Returns read string pattern of given pattern element.
6034 +StringPattern *getReadStringPattern(
6035 + ReadMatchPatternInfo *readPatInfo,
6036 + PatternElement *pattern )
6038 + switch (pattern->peType)
6040 + case PET_SINGLE:
6041 + return &pattern->peVal.peuSingle;
6042 + break;
6044 + case PET_MULTIPLE:
6045 + return &pattern->peVal.peuMulti.mpStringPattern;
6046 + break;
6048 + case PET_REFERENCE:
6049 + return getReadStringPattern(
6050 + readPatInfo,
6051 + getReadPatternOfReference(readPatInfo, &pattern->peVal.peuRef));
6052 + break;
6055 + /*
6056 + * never reached; just to make compiler happy
6057 + */
6058 + return NULL;
6062 +** Returns read pattern element of given pattern reference.
6064 +static PatternElement *getReadPatternOfReference(
6065 + ReadMatchPatternInfo *readPatInfo,
6066 + PatternReference *patRef)
6068 + MatchPatternTableElement **element = readPatInfo->rmpiElement;
6070 + return element[ patRef->prElementIdx ]->mpteAll.pesPattern[patRef->prPatternIdx];
6074 +** Allocate a new copy of given string and substitute each capturing
6075 +** parentheses inside given string by a non-capturing one.
6076 +** Returns resulting string.
6078 +static char *replaceCapturingParentheses(
6079 + const char *source)
6081 + char *destination;
6082 + const char *s;
6083 + char *d;
6084 + int nbrOfOpenBraces = 0;
6086 + s = source;
6088 + /*
6089 + * count number of open braces
6090 + */
6091 + while (*s != '\0')
6093 + if (*s++ == '(')
6094 + nbrOfOpenBraces ++;
6097 + /*
6098 + * allocate memory for substitued reg. exp. text
6099 + */
6100 + destination = XtMalloc(strlen(source) + 2*nbrOfOpenBraces);
6102 + /*
6103 + * substitute each capturing open brace by a non-capturing one
6104 + */
6105 + s = source;
6106 + d = destination;
6108 + while (*s != '\0')
6110 + if (*s == '\\')
6112 + *d++ = *s++;
6114 + if (*s != '\0')
6115 + *d++ = *s++;
6117 + else if (*s == '(')
6119 + *d++ = *s++;
6121 + if (*s != '?' && *s != '*')
6123 + *d++ = '?';
6124 + *d++ = ':';
6127 + else
6129 + *d++ = *s++;
6133 + *d = '\0';
6135 + return destination;
6139 +** Parse given string pattern for global backrefs definitions
6140 +** (syntax: "(*n", where n=1..9). Add found global backrefs to
6141 +** given backRefList.
6142 +** Returns false, if parse fails.
6144 +static int parseGlobalBackRefs(
6145 + StringPattern *strPat,
6146 + GlobalBackRefElement *backRefList,
6147 + ErrorInfo *errInfo)
6149 + char *s;
6150 + char *backRefContent;
6151 + int nestingLevel = 0;
6152 + int stackIdx = -1;
6153 + BackRefBracketInfo backRefInfo[MAX_GLOBAL_BACK_REF_ID+1];
6154 + StrPatBackRefElement *curStrPatBRE;
6156 + strPat->spText = replaceCapturingParentheses(strPat->spOrigText);
6157 + strPat->spLength = strlen(strPat->spText);
6158 + strPat->spBackRefParsed = True;
6160 + s = strPat->spText;
6162 + while (*s != '\0')
6164 + if (*s == '\\')
6166 + /*
6167 + * Ignore escaped characters
6168 + */
6169 + if (*(s+1) != '\0')
6170 + s ++;
6172 + else if (*s == '(')
6174 + if (*(s+1) == '*')
6176 + if (isdigit((unsigned char)*(s+2)))
6178 + /*
6179 + * Global backref. definition start found:
6180 + */
6181 + stackIdx ++;
6183 + backRefInfo[stackIdx].brbiGlobalId =
6184 + (int)((unsigned char)*(s+2) - (unsigned char)'0') - 1;
6186 + if(backRefInfo[stackIdx].brbiGlobalId < 0)
6188 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6189 + errInfo->eiDetail = "Backref '0' not allowed";
6190 + return False;
6193 + backRefInfo[stackIdx].brbiContentStart = s+3;
6194 + backRefInfo[stackIdx].brbiNestingLevel = nestingLevel;
6195 + s ++;
6197 + s ++;
6199 + nestingLevel ++;
6201 + else if (*s == ')')
6203 + nestingLevel --;
6204 + if (stackIdx != -1 &&
6205 + backRefInfo[stackIdx].brbiNestingLevel == nestingLevel)
6207 + /*
6208 + * Global backref. definition end found: add it to
6209 + * backref. list of string pattern.
6210 + */
6211 + curStrPatBRE =
6212 + &strPat->spOwnGlobalBackRef[backRefInfo[stackIdx].brbiGlobalId];
6214 + backRefContent =
6215 + createBackRefRegExpText(
6216 + backRefInfo[stackIdx].brbiContentStart,
6217 + s);
6219 + if (curStrPatBRE->spbreRegExpText != NULL)
6221 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6222 + errInfo->eiBackRefNbr = backRefInfo[stackIdx].brbiGlobalId + 1;
6223 + errInfo->eiDetail = "already defined before";
6224 + XtFree(backRefContent);
6225 + return False;
6227 + else
6229 + curStrPatBRE->spbreRegExpText = backRefContent;
6232 + stackIdx --;
6235 + s ++;
6238 + /*
6239 + * Merge global backref. list of string pattern with given backRefList.
6240 + */
6241 + return updateGlobalBackRefs(
6242 + strPat,
6243 + backRefList,
6244 + errInfo);
6248 +** Merge global backref. list of given string pattern with given backRefList.
6249 +** Returns false, if merge fails.
6251 +static int updateGlobalBackRefs(
6252 + StringPattern *strPat,
6253 + GlobalBackRefElement *backRefList,
6254 + ErrorInfo *errInfo)
6256 + int i;
6257 + StrPatBackRefElement *curStrPatBRE;
6258 + GlobalBackRefElement *curGlobalBRE;
6260 + for (i=0;i < MAX_GLOBAL_BACK_REF_ID; i ++)
6262 + curStrPatBRE = &strPat->spOwnGlobalBackRef[i];
6264 + if (curStrPatBRE->spbreRegExpText != NULL)
6266 + curGlobalBRE = &backRefList[i];
6268 + if (curGlobalBRE->gbreDefByStrPat != NULL)
6270 + if (strcmp(curGlobalBRE->gbreRegExpText, curStrPatBRE->spbreRegExpText) != 0)
6272 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6273 + errInfo->eiBackRefNbr = i+1;
6274 + errInfo->eiDetail = "already defined before";
6276 + return False;
6279 + else
6281 + curGlobalBRE->gbreDefByStrPat = strPat;
6282 + curGlobalBRE->gbreRegExpText = curStrPatBRE->spbreRegExpText;
6287 + return True;
6291 +** Allocate and return a new string holding content of
6292 +** global backref. definition.
6294 +static char *createBackRefRegExpText(
6295 + const char *start,
6296 + const char *end)
6298 + int len = end - start;
6299 + char *regExpText = XtMalloc( len+1 );
6301 + memcpy( regExpText, start, len );
6303 + regExpText[len] = '\0';
6305 + return regExpText;
6309 +** Resolve all global backrefs of given match pattern table element.
6310 +** Returns false, if resolve fails.
6312 +static int resolveGlobalBackRefs(
6313 + ReadMatchPatternInfo *readPatInfo,
6314 + MatchPatternTableElement *element,
6315 + ErrorInfo *errInfo)
6317 + int i;
6318 + StringPattern *strPat;
6320 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
6322 + strPat = getReadStringPattern(readPatInfo, element->mpteAll.pesPattern[i]);
6324 + if (strPat->spRegularExpression && !strPat->spBackRefResolved)
6326 + if (!resolveGlobalBackRefsOfStrPat(strPat, element->mpteGlobalBackRef, errInfo))
6327 + return False;
6329 + strPat->spBackRefResolved = True;
6333 + return True;
6337 +** Resolve global backrefs of given string pattern.
6338 +** Returns false, if resolve fails.
6340 +static int resolveGlobalBackRefsOfStrPat(
6341 + StringPattern *strPat,
6342 + GlobalBackRefElement *backRefList,
6343 + ErrorInfo *errInfo)
6345 + char *s;
6346 + int globalId;
6347 + int localId = 1;
6349 + s = strPat->spText;
6351 + while (*s != '\0')
6353 + if (*s == '\\')
6355 + if (isdigit((unsigned char)*(s+1)))
6357 + /*
6358 + * \n (n=1..9) found: substitute global backref.
6359 + */
6360 + globalId =
6361 + (int)((unsigned char)*(s+1) - (unsigned char)'0') - 1;
6363 + if(globalId < 0)
6365 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6366 + errInfo->eiDetail = "backref '\\0' not allowed";
6367 + return False;
6370 + s = substituteGlobalBackRef(strPat, s, globalId, &localId, backRefList, errInfo);
6372 + if (s == NULL)
6373 + return False;
6375 + else if (*(s+1) != '\0')
6376 + s ++;
6378 + else if (*s == '(')
6380 + if (*(s+1) == '*')
6382 + if (isdigit((unsigned char)*(s+2)))
6384 + /*
6385 + * "(*n" (n=1..9) found: substitute global backref. definition.
6386 + */
6387 + globalId =
6388 + (int)((unsigned char)*(s+2) - (unsigned char)'0') - 1;
6390 + strPat->spOwnGlobalBackRef[globalId].spbreLocalBackRefID = localId;
6391 + strPat->spGlobalToLocalBackRef[globalId] = localId;
6393 + localId ++;
6395 + s = convertGlobalToLocalBackRef(strPat, s);
6397 + else
6399 + s ++;
6403 + s ++;
6406 + return True;
6410 +** Substitute global backref (\n, n=1..9) located at given "subsPtr"
6411 +** by its definition or by a local backref.
6412 +** Returns
6413 +** - NULL, if substitute fails or
6414 +** - substituted string pointer, where scan shall continue with.
6416 +static char *substituteGlobalBackRef(
6417 + StringPattern *strPat,
6418 + char *subsPtr,
6419 + int globalId,
6420 + int *localId,
6421 + GlobalBackRefElement *backRefList,
6422 + ErrorInfo *errInfo)
6424 + StrPatBackRefElement *strPatBackRef = &strPat->spOwnGlobalBackRef[globalId];
6425 + char *s;
6427 + if (strPatBackRef->spbreRegExpText == NULL)
6429 + /*
6430 + * given global backref definition is not located in given
6431 + * string pattern -> replace backref ID by backref reg. exp.
6432 + */
6433 + if (backRefList[globalId].gbreRegExpText == NULL)
6435 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6436 + errInfo->eiBackRefNbr = globalId + 1;
6437 + errInfo->eiDetail = "not defined within any string pattern";
6438 + return NULL;
6441 + if (strPat->spGlobalToLocalBackRef[globalId] == NO_LOCAL_BACK_REF_ID)
6443 + /*
6444 + * 1st occurence of global backref ID in this pattern ->
6445 + * replace global backref ID by backref reg. exp.
6446 + */
6447 + s = replaceBackRefIdByRegExp(strPat, subsPtr, backRefList[globalId].gbreRegExpText);
6449 + strPat->spGlobalToLocalBackRef[globalId] = *localId;
6450 + (*localId) ++;
6452 + else
6454 + /*
6455 + * next occurence of global backref ID in this pattern ->
6456 + * replace global backref ID by local one
6457 + */
6458 + s = subsPtr + 1;
6459 + *s = (char)((int)('0') + strPat->spGlobalToLocalBackRef[globalId]);
6462 + else
6464 + /*
6465 + * given global backref definition is located in given string pattern
6466 + */
6467 + if (strPatBackRef->spbreLocalBackRefID == NO_LOCAL_BACK_REF_ID)
6469 + errInfo->eiStringPatText = XtNewString(strPat->spOrigText);
6470 + errInfo->eiBackRefNbr = globalId + 1;
6471 + errInfo->eiDetail = "not defined before";
6472 + return NULL;
6475 + /*
6476 + * replace global backref ID by local one
6477 + */
6478 + s = subsPtr + 1;
6479 + *s = (char)((int)('0') + strPatBackRef->spbreLocalBackRefID);
6482 + return s;
6486 +** Replace global backref ID ("\n", n=1..9), located at given
6487 +** replaceStartPtr, by its definition (given by regExp parameter).
6488 +** Returns string pointer, where scan shall continue with
6490 +static char *replaceBackRefIdByRegExp(
6491 + StringPattern *strPat,
6492 + char *replaceStartPtr,
6493 + char *regExp)
6495 + char *oldText = strPat->spText;
6496 + char *newText;
6497 + char *n;
6498 + char *continueScanPtr;
6499 + int oldLen = strlen(oldText);
6500 + int regExpLen = strlen(regExp);
6501 + int replacePos = replaceStartPtr - oldText;
6502 + int remainingLen = oldLen-replacePos-2;
6504 + /*
6505 + * replace "\n" - located at replaceStartPtr - by "(regExp)"
6506 + */
6507 + newText = XtMalloc(oldLen + regExpLen + 3);
6509 + memcpy(newText, oldText, replacePos);
6510 + n = newText + replacePos;
6511 + *n = '(';
6512 + continueScanPtr = n;
6513 + n ++;
6514 + memcpy(n, regExp, regExpLen);
6515 + n += regExpLen;
6516 + *n = ')';
6517 + n ++;
6518 + memcpy(n, replaceStartPtr+2, remainingLen);
6519 + *(n + remainingLen) = '\0';
6521 + XtFree(oldText);
6523 + strPat->spText = newText;
6524 + strPat->spLength = strlen(newText);
6526 + return continueScanPtr;
6530 +** Convert global backref definition ("(*n", n=1..9), located at given
6531 +** convertPtr, by capturing parentheses "(".
6532 +** Returns string pointer, where scan shall continue with
6534 +static char *convertGlobalToLocalBackRef(
6535 + StringPattern *strPat,
6536 + char *convertPtr)
6538 + char *oldText = strPat->spText;
6539 + char *newText;
6540 + int oldLen = strlen(oldText);
6541 + int convertPos = convertPtr - oldText;
6543 + /*
6544 + * replace "(*n" - located at convertPtr - by "("
6545 + */
6546 + newText = XtMalloc(oldLen - 1);
6548 + memcpy(newText, oldText, convertPos+1);
6549 + memcpy(newText+convertPos+1, convertPtr+3, oldLen-convertPos-3);
6551 + *(newText + oldLen - 2) = '\0';
6553 + XtFree(oldText);
6555 + strPat->spText = newText;
6556 + strPat->spLength = strlen(newText);
6558 + return newText + convertPos;
6562 +** Read a match pattern table element from given input string.
6563 +** Return NULL, if read fails.
6565 +static MatchPatternTableElement *readMatchPatternTableElement(
6566 + char **inPtr,
6567 + char **errMsg,
6568 + char *name,
6569 + MatchPatternType type)
6571 + int error = False;
6572 + PatternElement *pattern;
6573 + PatternElement *allPat[MAX_STRING_PATTERNS];
6574 + int nbrOfPat = 0;
6575 + int sizeOfPat;
6576 + MatchPatternTableElement *result;
6577 + int isMonoPattern;
6578 + int skipBtwStartEnd;
6579 + int flash;
6580 + int ignoreHighLightInfo;
6581 + int i;
6583 + if (!getMPSGlobalAttribute(
6584 + inPtr,
6585 + errMsg,
6586 + &isMonoPattern,
6587 + &skipBtwStartEnd,
6588 + &flash,
6589 + &ignoreHighLightInfo ))
6591 + return NULL;
6594 + /*
6595 + * read all patterns
6596 + */
6597 + while (**inPtr != '\n' && !error)
6599 + if (!readPatternElement( inPtr, errMsg, &pattern ))
6601 + error = True;
6603 + else if (nbrOfPat >= MAX_STRING_PATTERNS)
6605 + *errMsg = "max. number of string patterns exceeded";
6606 + error = True;
6608 + else
6610 + pattern->peIndex = nbrOfPat;
6612 + allPat[nbrOfPat ++] = pattern;
6616 + if (error)
6618 + for (i=0; i < nbrOfPat; i ++)
6619 + freePatternElement( allPat[i] );
6621 + return NULL;
6624 + if (nbrOfPat == 0)
6626 + *errMsg = "min. one string pattern needed";
6627 + return NULL;
6630 + /*
6631 + * allocate & init. MatchPatternTableElement
6632 + */
6633 + result =
6634 + (MatchPatternTableElement *)XtMalloc(sizeof(MatchPatternTableElement));
6636 + result->mpteName = name;
6637 + result->mpteIndex = NO_ELEMENT_IDX;
6638 + result->mpteType = type;
6639 + result->mpteGroup = NO_GROUP_IDX;
6641 + sizeOfPat = sizeof(PatternElement *) * nbrOfPat;
6642 + result->mpteAll.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6644 + memcpy(result->mpteAll.pesPattern, allPat, sizeOfPat);
6646 + result->mpteAll.pesNumberOfPattern = nbrOfPat;
6648 + result->mpteIsMonoPattern = isMonoPattern;
6649 + result->mpteSkipBtwnStartEnd = skipBtwStartEnd;
6650 + result->mpteFlash = flash;
6651 + result->mpteIgnoreHighLightInfo = ignoreHighLightInfo;
6653 + result->mpteStartEndRE = NULL;
6655 + initGlobalBackRefList( result->mpteGlobalBackRef );
6657 + /*
6658 + * sort start / end / middle pattern
6659 + */
6660 + error = !sortReadPatternElementSet( &result->mpteAll, errMsg, result );
6662 + if (error)
6664 + freeMatchPatternTableElement( result );
6665 + return NULL;
6667 + else
6669 + return result;
6674 + * Sort read pattern element set into start, middle & end arrays.
6675 + * Validate "monopattern" attribute.
6676 + * Returns true, if validation was successful.
6677 + */
6678 +static int sortReadPatternElementSet(
6679 + PatternElementSet *allPat,
6680 + char **errMsg,
6681 + MatchPatternTableElement *result)
6683 + int sizeOfPat;
6684 + int isMonoPattern = result->mpteIsMonoPattern;
6686 + /*
6687 + * count number of start, middle & end pattern elements.
6688 + */
6689 + countPatternElementKind( allPat, result );
6691 + /*
6692 + * validate and allocate pattern elements.
6693 + */
6694 + if (result->mpteStart.pesNumberOfPattern != 0)
6696 + sizeOfPat = sizeof(PatternElement *) * result->mpteStart.pesNumberOfPattern;
6697 + result->mpteStart.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6699 + else
6701 + *errMsg = "min. one start pattern needed";
6702 + return False;
6705 + if (isMonoPattern &&
6706 + (result->mpteMiddle.pesNumberOfPattern != 0 ||
6707 + result->mpteEnd.pesNumberOfPattern !=0))
6709 + *errMsg = "mono pattern: only start pattern(s) allowed due to attribute [m]";
6710 + return False;
6713 + if (result->mpteMiddle.pesNumberOfPattern != 0)
6715 + sizeOfPat = sizeof(PatternElement *) * result->mpteMiddle.pesNumberOfPattern;
6716 + result->mpteMiddle.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6719 + if (result->mpteEnd.pesNumberOfPattern != 0)
6721 + sizeOfPat = sizeof(PatternElement *) * result->mpteEnd.pesNumberOfPattern;
6722 + result->mpteEnd.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6724 + else
6726 + if (!isMonoPattern)
6728 + *errMsg = "min. one end pattern needed";
6729 + return False;
6733 + /*
6734 + * sort pattern elements into start, middle & end arrays.
6735 + */
6736 + sortPatternElementSet( allPat, result );
6738 + if (isMonoPattern)
6740 + copyPatternSet( &result->mpteStart, &result->mpteEnd );
6743 + return True;
6747 + * Count number of start, middle & end patterns stored in "allPat".
6748 + */
6749 +static void countPatternElementKind(
6750 + PatternElementSet *allPat,
6751 + MatchPatternTableElement *result)
6753 + int i;
6755 + result->mpteStart.pesNumberOfPattern = 0;
6756 + result->mpteEnd.pesNumberOfPattern = 0;
6757 + result->mpteMiddle.pesNumberOfPattern = 0;
6759 + result->mpteStart.pesPattern = NULL;
6760 + result->mpteEnd.pesPattern = NULL;
6761 + result->mpteMiddle.pesPattern = NULL;
6763 + for (i=0; i < allPat->pesNumberOfPattern; i ++)
6765 + switch (allPat->pesPattern[i]->peKind)
6767 + case PEK_START:
6768 + result->mpteStart.pesNumberOfPattern ++;
6769 + break;
6770 + case PEK_MIDDLE:
6771 + result->mpteMiddle.pesNumberOfPattern ++;
6772 + break;
6773 + case PEK_END:
6774 + result->mpteEnd.pesNumberOfPattern ++;
6775 + break;
6776 + default:;
6782 + * Sort start, middle & end pattern elements into related arrays.
6783 + */
6784 +static void sortPatternElementSet(
6785 + PatternElementSet *allPat,
6786 + MatchPatternTableElement *result)
6788 + int i;
6789 + int s,m,e;
6791 + for (i=0, s=0, m=0, e=0; i < allPat->pesNumberOfPattern; i ++)
6793 + switch (allPat->pesPattern[i]->peKind)
6795 + case PEK_START:
6796 + result->mpteStart.pesPattern[s ++] = allPat->pesPattern[i];
6797 + break;
6798 + case PEK_MIDDLE:
6799 + result->mpteMiddle.pesPattern[m ++] = allPat->pesPattern[i];
6800 + break;
6801 + case PEK_END:
6802 + result->mpteEnd.pesPattern[e ++] = allPat->pesPattern[i];
6803 + break;
6804 + default:;
6809 +static void copyPatternSet(
6810 + PatternElementSet *sourcePS,
6811 + PatternElementSet *destPS)
6813 + int sizeOfPat;
6815 + destPS->pesNumberOfPattern = sourcePS->pesNumberOfPattern;
6817 + sizeOfPat = sizeof(PatternElement *) * destPS->pesNumberOfPattern;
6818 + destPS->pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
6820 + memcpy(destPS->pesPattern, sourcePS->pesPattern, sizeOfPat);
6824 +** Free the allocated memory contained in a ReadMatchPatternInfo data structure
6826 +static void freeReadMatchPatternInfo( ReadMatchPatternInfo *readPatInfo )
6828 + int i;
6830 + for (i=0; i<readPatInfo->rmpiNbrOfElements; i++)
6831 + freeMatchPatternTableElement(readPatInfo->rmpiElement[i]);
6833 + for (i=0; i<readPatInfo->rmpiNbrOfGroups; i++)
6834 + freeMatchPatternGroupElement(readPatInfo->rmpiGroup[i]);
6836 + for (i=0; i<readPatInfo->rmpiNbrOfSeqElements; i++)
6837 + freeMatchPatternSequenceElement(readPatInfo->rmpiSequence[i]);
6839 + freePtr((void **)&readPatInfo->rmpiAllPatRE);
6841 + freePtr((void **)&readPatInfo->rmpiFlashPatRE);
6845 +** Free the allocated memory contained in a StringMatchTable data structure
6847 +static void freeStringMatchTable( StringMatchTable *table )
6849 + MatchPatternTable *patTable;
6850 + int i;
6852 + if (table == NULL)
6853 + return;
6855 + XtFree(table->smtLanguageMode);
6857 + /*
6858 + * Free all matching patterns
6859 + */
6860 + patTable = table->smtAllPatterns;
6862 + for (i=0; i<patTable->mptNumberOfElements; i++)
6863 + freeMatchPatternTableElement(patTable->mptElements[i]);
6865 + XtFree((char *)patTable);
6867 + /*
6868 + * Free matching pattern group elements
6869 + */
6870 + for (i=0; i<table->smtNumberOfGroups; i++)
6871 + freeMatchPatternGroupElement(table->smtGroups[i]);
6873 + /*
6874 + * Free matching pattern sequence elements
6875 + */
6876 + for (i=0; i<table->smtNumberOfSeqElements; i++)
6877 + freeMatchPatternSequenceElement(table->smtSequence[i]);
6879 + /*
6880 + * Free keyword reg. expressions
6881 + */
6882 + freePtr((void **)&table->smtAllPatRE);
6884 + freePtr((void **)&table->smtFlashPatRE);
6886 + XtFree((char *)table);
6890 +** Free the allocated memory contained in a MatchPatternTableElement data structure
6892 +static void freeMatchPatternTableElement( MatchPatternTableElement *element )
6894 + int i;
6896 + XtFree(element->mpteName);
6898 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i++)
6900 + freePatternElement(element->mpteAll.pesPattern[i]);
6903 + freePtr((void **)&element->mpteStartEndRE);
6905 + freeXtPtr((void **)&element->mpteStart.pesPattern);
6907 + freeXtPtr((void **)&element->mpteMiddle.pesPattern);
6909 + freeXtPtr((void **)&element->mpteEnd.pesPattern);
6911 + XtFree((char *)element);
6915 +** Free the allocated memory contained in a PatternElement data structure
6917 +static void freePatternElement( PatternElement *element )
6919 + if (element->peType == PET_SINGLE)
6920 + freeStringPattern( &(element->peVal.peuSingle) );
6921 + else if (element->peType == PET_MULTIPLE)
6923 + freeStringPattern( &(element->peVal.peuMulti.mpStringPattern) );
6924 + XtFree( (char *)element->peVal.peuMulti.mpRefList );
6927 + XtFree( (char *)element );
6931 +** Free the allocated memory contained in a StringPattern data structure
6933 +static void freeStringPattern( StringPattern *strPat )
6935 + int i;
6937 + freeXtPtr((void **)&strPat->spText);
6938 + freeXtPtr((void **)&strPat->spOrigText);
6940 + freePtr((void **)&strPat->spTextRE);
6942 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
6943 + freeXtPtr((void **)&strPat->spOwnGlobalBackRef[i].spbreRegExpText);
6947 +** Free the allocated memory contained in a MatchPatternGroupElement data structure
6949 +static void freeMatchPatternGroupElement( MatchPatternGroupElement *group )
6951 + int i;
6953 + freeXtPtr((void **)&group->mpgeName);
6955 + freePtr((void **)&group->mpgeKeywordRE);
6957 + if (group->mpgeSubPatternIds != NULL)
6959 + for (i=0; i < group->mpgeNumberOfSubPatterns; i++)
6961 + XtFree(group->mpgeSubPatternIds[i]);
6963 + XtFree((char *)group->mpgeSubPatternIds);
6966 + XtFree((char *)group);
6970 +** Free the allocated memory contained in a MatchPatternSequenceElement data structure
6972 +static void freeMatchPatternSequenceElement( MatchPatternSequenceElement *sequence )
6974 + XtFree( sequence->mpseName );
6976 + XtFree( (char *)sequence );
6981 +** Format a matching pattern set parse error.
6983 +static void parseMatchingPatternSetError(
6984 + const char *stringStart,
6985 + const char *stoppedAt,
6986 + ErrorInfo *errInfo)
6988 + char *message = "";
6989 + int msgLen;
6990 + char *errorInForm = "matching pattern of \"%s\"";
6991 + char *errorIn;
6993 + if (errInfo->eiLanguageMode == NULL)
6995 + errorIn = "matching pattern";
6997 + else
6999 + errorIn = XtMalloc(strlen(errorInForm) + strlen(errInfo->eiLanguageMode)+1);
7000 + sprintf(errorIn, "matching pattern of \"%s\"", errInfo->eiLanguageMode);
7003 + if (errInfo->eiRegExpCompileMsg != NULL)
7005 + /*
7006 + * Error message of form:
7007 + * "MP \"eiMPTabElementName\", SP \"eiStringPatText\": eiRegExpCompileMsg" or
7008 + * "MP \"eiMPTabElementName\" - eiDetail: eiRegExpCompileMsg"
7009 + */
7011 + msgLen = strlen(errInfo->eiRegExpCompileMsg) + 1;
7013 + if (errInfo->eiMPTabElementName != NULL)
7014 + msgLen += strlen(errInfo->eiMPTabElementName) + 10;
7016 + if (errInfo->eiDetail != NULL)
7018 + msgLen += strlen(errInfo->eiDetail + 2);
7020 + else
7022 + if (errInfo->eiStringPatText != NULL)
7023 + msgLen += strlen(errInfo->eiStringPatText) + 9;
7026 + message = XtMalloc(msgLen);
7028 + strcpy(message, "");
7030 + if (errInfo->eiMPTabElementName != NULL)
7031 + sprintf( message, "MP \"%s\"", errInfo->eiMPTabElementName);
7033 + if (errInfo->eiDetail == NULL)
7035 + if (errInfo->eiStringPatText != NULL)
7036 + sprintf( message, "%s, SP \"%s\"", message, errInfo->eiStringPatText);
7038 + else
7040 + if (strlen(message) != 0)
7041 + strcat(message, " - ");
7043 + strcat(message, errInfo->eiDetail);
7046 + if (strlen(message) != 0)
7047 + strcat(message, ": ");
7049 + strcat(message, errInfo->eiRegExpCompileMsg);
7051 + else if (errInfo->eiDetail != NULL)
7053 + /*
7054 + * Error message of form:
7055 + * "MP \"eiMPTabElementName\", SP \"eiStringPatText\": Backref %d eiDetail
7056 + */
7057 + msgLen = strlen(errInfo->eiDetail) + 1;
7059 + if (errInfo->eiMPTabElementName != NULL)
7060 + msgLen += strlen(errInfo->eiMPTabElementName) + 7;
7061 + if (errInfo->eiStringPatText != NULL)
7062 + msgLen += strlen(errInfo->eiStringPatText) + 9;
7063 + if (errInfo->eiBackRefNbr != 0)
7064 + msgLen += 15;
7066 + message = XtMalloc(msgLen);
7068 + strcpy(message, "");
7070 + if (errInfo->eiMPTabElementName != NULL)
7071 + sprintf( message, "MP \"%s\"", errInfo->eiMPTabElementName);
7072 + if (errInfo->eiStringPatText != NULL)
7073 + sprintf( message, "%s, SP \"%s\"", message, errInfo->eiStringPatText);
7075 + if (strlen(message) != 0)
7076 + strcat(message, ": ");
7078 + if (errInfo->eiBackRefNbr != 0)
7079 + sprintf( message, "%s Backref %d ", message, errInfo->eiBackRefNbr);
7081 + strcat(message, errInfo->eiDetail);
7084 + ParseError(NULL, stringStart, stoppedAt, errorIn, message);
7086 + if (errInfo->eiRegExpCompileMsg != NULL || errInfo->eiDetail != NULL)
7088 + XtFree(message);
7091 + if (errInfo->eiLanguageMode != NULL)
7093 + XtFree(errorIn);
7096 + freeErrorInfo(errInfo);
7097 + initErrorInfo(errInfo);
7101 + * Pop-up a warning dialog showing a matching pattern set error.
7102 + */
7103 +static void dialogMatchingPatternSetError(
7104 + char *title,
7105 + ErrorInfo *errInfo)
7107 + char *message;
7108 + int msgLen = 1;
7110 + /*
7111 + * Error message of form:
7112 + * "Name : \"eiMPTabElementName\"\n
7113 + * "String: \"eiStringPatText\"\n
7114 + * eiDetail\n
7115 + * eiRegExpCompileMsg\n"
7116 + */
7118 + if (errInfo->eiMPTabElementName != NULL)
7119 + msgLen += strlen(errInfo->eiMPTabElementName) + 15;
7120 + if (errInfo->eiStringPatText != NULL)
7121 + msgLen += strlen(errInfo->eiStringPatText) + 15;
7122 + if (errInfo->eiDetail != NULL)
7123 + msgLen += strlen(errInfo->eiDetail) + 15;
7124 + if (errInfo->eiBackRefNbr != 0)
7125 + msgLen += 15;
7126 + if (errInfo->eiRegExpCompileMsg != NULL)
7127 + msgLen += strlen(errInfo->eiRegExpCompileMsg) + 15;
7129 + message = XtMalloc(msgLen);
7131 + strcpy(message, "");
7133 + if (errInfo->eiMPTabElementName != NULL)
7134 + sprintf( message, "%sName : \"%s\"\n", message, errInfo->eiMPTabElementName);
7135 + if (errInfo->eiStringPatText != NULL)
7136 + sprintf( message, "%sPattern: \"%s\"\n", message, errInfo->eiStringPatText);
7137 + if (errInfo->eiBackRefNbr != 0)
7138 + sprintf( message, "%sBackref %d ", message, errInfo->eiBackRefNbr);
7139 + if (errInfo->eiDetail != NULL)
7140 + sprintf( message, "%s%s\n", message, errInfo->eiDetail);
7141 + if (errInfo->eiRegExpCompileMsg != NULL)
7142 + sprintf( message, "%s%s\n", message, errInfo->eiRegExpCompileMsg);
7144 + DialogF(
7145 + DF_WARN, MatchPatternDialog.mpdShell, 1,
7146 + title,
7147 + "%s(language mode '%s')",
7148 + "OK",
7149 + message,
7150 + errInfo->eiLanguageMode);
7152 + XtFree(message);
7154 + freeErrorInfo(errInfo);
7155 + initErrorInfo(errInfo);
7159 +** Get matching pattern set name.
7160 +** Syntax:
7161 +** patternName ::= "name:"
7162 +** Returns true, if get was successful.
7164 +static int getMPSName(
7165 + char **inPtr,
7166 + ErrorInfo *errInfo,
7167 + char **name )
7169 + char *dummy;
7170 + char *field = ReadSymbolicField(inPtr);
7172 + if (field == NULL)
7174 + errInfo->eiDetail = "matching pattern name missing";
7175 + return False;
7178 + if (!SkipDelimiter(inPtr, &dummy))
7180 + errInfo->eiMPTabElementName = XtNewString(field);
7181 + errInfo->eiDetail = "':' missing after matching pattern name";
7182 + XtFree( field );
7183 + return False;
7186 + *name = field;
7188 + return True;
7192 +** Get matching pattern set type attribute.
7193 +** TypeAttribute ::=
7194 +** [s|g]:
7196 +** s : sub-pattern (pattern is only matched, if part of a pattern group).
7197 +** g : pattern (context) group (i.e. a sequence of sub-patterns).
7198 +** default: individual pattern (pattern is not part of a group and is
7199 +** matched individually.
7200 +** Returns true, if get was successful.
7202 +static int getMPSTypeAttribute(
7203 + char **inPtr,
7204 + ErrorInfo *errInfo,
7205 + MatchPatternType *type)
7207 + char *field = ReadSymbolicField(inPtr);
7208 + int successful = True;
7210 + *type = MPT_INDIVIDUAL;
7212 + if (field != NULL)
7214 + switch (*field)
7216 + case 'g':
7217 + *type = MPT_GROUP;
7218 + break;
7219 + case 's':
7220 + *type = MPT_SUB;
7221 + break;
7222 + default:
7223 + errInfo->eiDetail = "unknown matching pattern type attribute";
7224 + successful = False;
7228 + if (successful)
7230 + if (!SkipDelimiter(inPtr, &errInfo->eiDetail))
7232 + successful = False;
7236 + freeXtPtr((void **)&field);
7238 + return successful;
7242 +** Syntax:
7244 +** GlobalAttribute ::=
7245 +** [c][f][m][p][u]:
7247 +** c : the content between start and end pattern is skipped
7248 +** during parsing (e.g. pattern encloses a comment).
7249 +** f : flash matching pattern (if not set, then only jump
7250 +** to matching pattern is supported).
7251 +** m : mono pattern - set exist out of only one single pattern
7252 +** (start pattern = end pattern; e.g. quotes like ")
7253 +** p : ignore highlight info code of single patterns of this set
7254 +** ("plain").
7256 +** Returns TRUE, if global attribute was successful read.
7258 +static int getMPSGlobalAttribute(
7259 + char **inPtr,
7260 + char **errMsg,
7261 + int *isMonoPattern,
7262 + int *comment,
7263 + int *flash,
7264 + int *ignoreHighLightInfo)
7266 + char *field = ReadSymbolicField(inPtr);
7267 + char *attribute;
7268 + int successful = True;
7270 + *isMonoPattern = False;
7271 + *comment = False;
7272 + *flash = False;
7273 + *ignoreHighLightInfo = False;
7275 + if (field != NULL)
7277 + attribute = field;
7278 + while (*attribute != '\0' && successful)
7280 + switch (*attribute)
7282 + case 'c':
7283 + *comment = True;
7284 + break;
7285 + case 'f':
7286 + *flash = True;
7287 + break;
7288 + case 'm':
7289 + *isMonoPattern = True;
7290 + break;
7291 + case 'p':
7292 + *ignoreHighLightInfo = True;
7293 + break;
7294 + default:
7295 + *errMsg = "unknown global attribute";
7296 + successful = False;
7298 + attribute ++;
7302 + if (successful)
7304 + if (!SkipDelimiter(inPtr, errMsg))
7306 + successful = False;
7310 + freeXtPtr((void **)&field);
7312 + return successful;
7316 +** Get matching pattern set attribute.
7318 +** Syntax:
7320 +** patternAttribute ::=
7321 +** [s|m|e][w|l|r][i]:
7323 +** StringPatternKind:
7324 +** s : start string pattern.
7325 +** m : middle string pattern.
7326 +** e : end string pattern.
7327 +** WordBoundaryAttribute:
7328 +** w : pattern is word (i.e. before and after pattern
7329 +** there must be a delimiter).
7330 +** l : before pattern must be a delimiter (left side).
7331 +** r : after pattern must be a delimiter (right side).
7332 +** default: neither before nor after pattern must be a delimiter.
7333 +** StringAttribute:
7334 +** i : pattern is case insensitive (if not set: pattern is
7335 +** case sensitive).
7336 +** x : pattern is regular expression (if not set: pattern is
7337 +** literal string).
7339 +** Returns TRUE, if pattern attribute was successful read.
7341 +static int getMPSPatternAttribute(
7342 + char **inPtr,
7343 + char **errMsg,
7344 + PatternElementKind *patternKind,
7345 + PatternWordBoundary *wordBoundary,
7346 + int *caseInsensitive,
7347 + int *regularExpression)
7349 + char *field = ReadSymbolicField(inPtr);
7350 + char *attribute;
7351 + int successful = True;
7353 + *patternKind = PEK_UNKNOWN;
7354 + *wordBoundary = PWB_NONE;
7355 + *caseInsensitive = False;
7356 + *regularExpression = False;
7358 + if (field != NULL)
7360 + attribute = field;
7361 + while (*attribute != '\0' && successful)
7363 + switch (*attribute)
7365 + case 'e':
7366 + *patternKind = PEK_END;
7367 + break;
7368 + case 'i':
7369 + *caseInsensitive = True;
7370 + break;
7371 + case 'l':
7372 + *wordBoundary = PWB_LEFT;
7373 + break;
7374 + case 'm':
7375 + *patternKind = PEK_MIDDLE;
7376 + break;
7377 + case 'r':
7378 + *wordBoundary = PWB_RIGHT;
7379 + break;
7380 + case 's':
7381 + *patternKind = PEK_START;
7382 + break;
7383 + case 'w':
7384 + *wordBoundary = PWB_BOTH;
7385 + break;
7386 + case 'x':
7387 + *regularExpression = True;
7388 + break;
7389 + default:
7390 + *errMsg = "unknown string pattern attribute";
7391 + successful = False;
7393 + attribute ++;
7397 + if (successful)
7399 + if (!SkipDelimiter(inPtr, errMsg))
7401 + successful = False;
7405 + freeXtPtr((void **)&field);
7407 + return successful;
7411 +** Returns the (to be reserved) reg. ex. length of an pattern element.
7412 +** Update total number of multi patterns, too.
7414 +static int patternElementLen(
7415 + ReadMatchPatternInfo *info,
7416 + PatternElement *patElement,
7417 + int *nbrOfMultiPatterns)
7419 + PatternElement *referredElement;
7420 + StringPattern *strPat = NULL;
7421 + int patElementLen;
7423 + switch (patElement->peType)
7425 + case PET_SINGLE:
7426 + strPat = &patElement->peVal.peuSingle;
7427 + break;
7429 + case PET_MULTIPLE:
7430 + strPat = &patElement->peVal.peuMulti.mpStringPattern;
7432 + (*nbrOfMultiPatterns) ++;
7434 + break;
7436 + case PET_REFERENCE:
7437 + referredElement =
7438 + info->rmpiElement[patElement->peVal.peuRef.prElementIdx]->
7439 + mpteAll.pesPattern[patElement->peVal.peuRef.prPatternIdx];
7441 + strPat = &referredElement->peVal.peuMulti.mpStringPattern;
7442 + break;
7445 + /*
7446 + * reserve additional 4 characters ("(?i)") for case insensitive search
7447 + */
7448 + if (strPat->spCaseInsensitive)
7449 + patElementLen = strPat->spLength + 4;
7450 + else
7451 + patElementLen = strPat->spLength;
7453 + /*
7454 + * reserve additional 4 characters ("(?:)") for regular expression
7455 + */
7456 + if (strPat->spRegularExpression)
7457 + patElementLen += 4;
7459 + return patElementLen;
7463 +** Returns the (to be reserved) total reg. ex. length of given
7464 +** MatchPatternTableElement. Update total number of multi patterns, too.
7466 +static int totalMatchPatternTableElementLen(
7467 + ReadMatchPatternInfo *info,
7468 + MatchPatternTableElement *element,
7469 + int *nbrOfMultiPatterns)
7471 + int i;
7472 + int totalLen = 0;
7474 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i ++)
7476 + totalLen +=
7477 + patternElementLen(
7478 + info,
7479 + element->mpteAll.pesPattern[i],
7480 + nbrOfMultiPatterns );
7483 + return totalLen;
7487 +** Returns the (to be reserved) total reg. ex. length of given
7488 +** read match pattern info. Counts total number of multi patterns, too.
7490 +static int totalKeywordOfTableLen(
7491 + ReadMatchPatternInfo *info,
7492 + int *nbrOfMultiPatterns)
7494 + int i;
7495 + int totalLen = 0;
7497 + *nbrOfMultiPatterns = 0;
7499 + for (i=0; i<info->rmpiNbrOfElements; i ++)
7501 + totalLen +=
7502 + totalMatchPatternTableElementLen(
7503 + info,
7504 + info->rmpiElement[i],
7505 + nbrOfMultiPatterns);
7508 + return totalLen;
7512 +** Add given StringPattern to given reg. ex. strings
7514 +static void addPatternToRegExpString(
7515 + StringPattern *pattern,
7516 + RegExpStringInfo *regExpStringInfo)
7518 + char *r = NULL, *s;
7519 + char *adaptedRegExpText = NULL;
7520 + int prevLen = 0;
7522 + /*
7523 + * Select the buffer, where the pattern needs to be added
7524 + * to (depending on its word boundary). Prepare the buffer
7525 + * by evtl. adding a prefix, if related buffer is empty.
7526 + */
7527 + switch (pattern->spWordBoundary)
7529 + case PWB_NONE:
7530 + prevLen = strlen( regExpStringInfo->resiNoneWBRegExpString );
7532 + r = regExpStringInfo->resiNoneWBRegExpString + strlen( regExpStringInfo->resiNoneWBRegExpString );
7533 + break;
7534 + case PWB_LEFT:
7535 + prevLen = strlen( regExpStringInfo->resiLeftWBRegExpString );
7536 + if (prevLen == 0)
7538 + strcpy( regExpStringInfo->resiLeftWBRegExpString, "<(?:" );
7540 + r = regExpStringInfo->resiLeftWBRegExpString + strlen( regExpStringInfo->resiLeftWBRegExpString );
7541 + break;
7542 + case PWB_RIGHT:
7543 + prevLen = strlen( regExpStringInfo->resiRightWBRegExpString );
7544 + if (prevLen == 0)
7546 + strcpy( regExpStringInfo->resiRightWBRegExpString, "(?:" );
7548 + r = regExpStringInfo->resiRightWBRegExpString + strlen( regExpStringInfo->resiRightWBRegExpString );
7549 + break;
7550 + case PWB_BOTH:
7551 + prevLen = strlen( regExpStringInfo->resiBothWBRegExpString );
7552 + if (prevLen == 0)
7554 + strcpy( regExpStringInfo->resiBothWBRegExpString, "<(?:" );
7556 + r = regExpStringInfo->resiBothWBRegExpString + strlen( regExpStringInfo->resiBothWBRegExpString );
7557 + break;
7560 + /*
7561 + * add an "or" if there is already a pattern in the buffer
7562 + */
7563 + if (prevLen != 0)
7565 + *r++ = '|';
7568 + /*
7569 + * add "(?i" to order case insensitive search
7570 + */
7571 + if (pattern->spCaseInsensitive)
7573 + *r++ = '(';
7574 + *r++ = '?';
7575 + *r++ = 'i';
7578 + /*
7579 + * add "(?:" to group this regular expression
7580 + */
7581 + if (pattern->spRegularExpression)
7583 + *r++ = '(';
7584 + *r++ = '?';
7585 + *r++ = ':';
7587 + adaptedRegExpText =
7588 + adaptLocalBackRefs(
7589 + pattern->spText,
7590 + &regExpStringInfo->resiLocalBackRefID);
7592 + s = adaptedRegExpText;
7594 + else
7596 + s = pattern->spText;
7599 + /*
7600 + * add the pattern characters - evtl. escaped, if special
7601 + * regular expression symbols & pattern is no reg. exp. -
7602 + * to the buffer:
7603 + */
7605 + while (*s != '\0')
7607 + if (!pattern->spRegularExpression)
7609 + switch (*s)
7611 + case '(':
7612 + case ')':
7613 + case '-':
7614 + case '[':
7615 + case ']':
7616 + case '<':
7617 + case '>':
7618 + case '{':
7619 + case '}':
7620 + case '.':
7621 + case '\\':
7622 + case '|':
7623 + case '^':
7624 + case '$':
7625 + case '*':
7626 + case '+':
7627 + case '?':
7628 + case '&':
7629 + *r++ = '\\';
7630 + break;
7631 + };
7634 + *r++ = *s++;
7637 + /*
7638 + * close "reg. exp. group" bracket
7639 + */
7640 + if (pattern->spRegularExpression)
7642 + *r++ = ')';
7644 + XtFree(adaptedRegExpText);
7647 + /*
7648 + * close case insensitive search bracket
7649 + */
7650 + if (pattern->spCaseInsensitive)
7652 + *r++ = ')';
7655 + /*
7656 + * terminate added string
7657 + */
7658 + *r = '\0';
7662 +** Adapt local backrefs inside given regExpText by common local IDs.
7663 +** Returns new allocated reg. exp. string holding common local backrefs.
7665 +static char *adaptLocalBackRefs(
7666 + char *regExpText,
7667 + int *commonLocalId)
7669 + int id;
7670 + int ownLocalId = 0;
7671 + char *s = regExpText;
7672 + char *newRegExpText = XtMalloc(strlen(regExpText)*3);
7673 + char *n = newRegExpText;
7674 + int localBackRefList[MAX_LOCAL_BACK_REF_ID];
7676 + /*
7677 + * put all local backrefs into "localBackRefList".
7678 + */
7679 + scanForLocalBackRefs(regExpText, localBackRefList);
7681 + while (*s != '\0')
7683 + *n++ = *s;
7685 + if (*s == '\\')
7687 + s++;
7689 + if (isdigit((unsigned char)*s))
7691 + /*
7692 + * \n (n=1..9) found: replace local backref.
7693 + * by "common local ID"
7694 + */
7695 + id =
7696 + (int)((unsigned char)*s - (unsigned char)'0') - 1;
7698 + if (localBackRefList[id] != NO_LOCAL_BACK_REF_ID &&
7699 + localBackRefList[id] != LOCAL_BACK_REF_ID_USED)
7701 + *n++ = (char)((int)('0') + localBackRefList[id]);
7703 + else
7705 + *n++ = '0';
7708 + s ++;
7710 + else if (*s != '\0')
7712 + /*
7713 + * copy escaped character
7714 + */
7715 + *n++ = *s++;
7718 + else if (*s == '(')
7720 + s ++;
7722 + if (*s == '?')
7724 + /*
7725 + * non capturing parentheses found -> just copy it
7726 + */
7727 + *n++ = *s++;
7729 + else
7731 + /*
7732 + * capturing parentheses found:
7733 + */
7734 + if (localBackRefList[ownLocalId] == LOCAL_BACK_REF_ID_USED)
7736 + /*
7737 + * backref used within given reg. exp. text:
7738 + * remember common local id for replacement later on
7739 + */
7740 + localBackRefList[ownLocalId] = *commonLocalId;
7741 + (*commonLocalId) ++;
7742 + ownLocalId ++;
7744 + else
7746 + /*
7747 + * backref not used within given reg. exp. text:
7748 + * replace capturing parentheses by non capturing one
7749 + */
7750 + *n++ = '?';
7751 + *n++ = ':';
7755 + else
7757 + s ++;
7761 + /*
7762 + * terminate adapted string
7763 + */
7764 + *n = '\0';
7766 + return newRegExpText;
7770 +** Get all local backrefs of given regExpText and put them into
7771 +** given localBackRefList.
7773 +static void scanForLocalBackRefs(
7774 + char *regExpText,
7775 + int *localBackRefList)
7777 + int i;
7778 + int localId;
7779 + char *s = regExpText;
7781 + for (i=0; i<MAX_LOCAL_BACK_REF_ID; i++)
7783 + localBackRefList[i] = NO_LOCAL_BACK_REF_ID;
7786 + while (*s != '\0')
7788 + if (*s == '\\')
7790 + if (isdigit((unsigned char)*(s+1)))
7792 + /*
7793 + * \n (n=1..9) found: flag usage in local backref list
7794 + */
7795 + localId =
7796 + (int)((unsigned char)*(s+1) - (unsigned char)'0') - 1;
7798 + localBackRefList[localId] = LOCAL_BACK_REF_ID_USED;
7800 + s ++;
7802 + else if (*(s+1) != '\0')
7803 + s ++;
7805 + s ++;
7810 +** Returns true, if string of given multi pattern reference was
7811 +** not added to regExpStringInfo.
7813 +static int isMultiPatternNotAdded(
7814 + RegExpStringInfo *regExpStringInfo,
7815 + PatternReference *toBeAddedPR)
7817 + int i;
7818 + PatternReference *addedPR;
7819 + PatternReference *newPR;
7821 + for (i=0; i < regExpStringInfo->resiNbrOfAddedMultiPat; i++)
7823 + addedPR = regExpStringInfo->resiAddedMultiPat[i];
7825 + if (addedPR->prElementIdx == toBeAddedPR->prElementIdx &&
7826 + addedPR->prPatternIdx == toBeAddedPR->prPatternIdx)
7828 + return False;
7832 + newPR = (PatternReference *)XtMalloc(sizeof(PatternReference));
7834 + *newPR = *toBeAddedPR;
7836 + regExpStringInfo->resiAddedMultiPat[regExpStringInfo->resiNbrOfAddedMultiPat ++] = newPR;
7838 + return True;
7842 +** add given PatternElement to given reg. exp. strings
7844 +static void addUniquePatternToRegExpString(
7845 + PatternElement *patElement,
7846 + PatternReference *patElementReference,
7847 + ReadMatchPatternInfo *readMatchPatternInfo,
7848 + RegExpStringInfo *regExpStringInfo)
7850 + PatternElement *referredElement;
7851 + PatternReference referredPatReference;
7853 + switch (patElement->peType)
7855 + case PET_SINGLE:
7856 + addPatternToRegExpString(
7857 + &(patElement->peVal.peuSingle),
7858 + regExpStringInfo);
7859 + break;
7861 + case PET_MULTIPLE:
7862 + /*
7863 + * add element to reg. exp. string only, if it was
7864 + * not added before.
7865 + */
7866 + if (isMultiPatternNotAdded(regExpStringInfo, patElementReference))
7868 + addPatternToRegExpString(
7869 + &(patElement->peVal.peuMulti.mpStringPattern),
7870 + regExpStringInfo);
7872 + break;
7874 + case PET_REFERENCE:
7875 + /*
7876 + * add referred element to reg. exp. string only, if related
7877 + * multi pattern was not added before.
7878 + */
7879 + referredPatReference = patElement->peVal.peuRef;
7881 + referredElement =
7882 + readMatchPatternInfo->rmpiElement[referredPatReference.prElementIdx]->
7883 + mpteAll.pesPattern[referredPatReference.prPatternIdx];
7885 + if (isMultiPatternNotAdded(regExpStringInfo, &referredPatReference))
7887 + addPatternToRegExpString(
7888 + &(referredElement->peVal.peuMulti.mpStringPattern),
7889 + regExpStringInfo);
7891 + break;
7896 +** add given MatchPatternTableElement to given reg. ex. strings
7898 +static void addElementToRegExpString(
7899 + MatchPatternTableElement *element,
7900 + ReadMatchPatternInfo *readMatchPatternInfo,
7901 + RegExpStringInfo *regExpStringInfo)
7903 + int i;
7904 + PatternReference elementRef;
7906 + elementRef.prElementIdx = element->mpteIndex;
7908 + for (i=0; i<element->mpteAll.pesNumberOfPattern; i ++)
7910 + elementRef.prPatternIdx = i;
7912 + addUniquePatternToRegExpString(
7913 + element->mpteAll.pesPattern[i],
7914 + &elementRef,
7915 + readMatchPatternInfo,
7916 + regExpStringInfo);
7921 +** Concatenate strings stored by regExpStringInfo.
7922 +** Free given regExpStringInfo afterwards.
7923 +** Returns resulting string.
7925 +static void catSMTRegExpStrings(
7926 + RegExpStringInfo *regExpStringInfo,
7927 + char **regExpString)
7929 + int resultingLen;
7931 + /*
7932 + * allocate & init. a buffer for the resulting regular expression
7933 + */
7934 + resultingLen =
7935 + strlen( regExpStringInfo->resiNoneWBRegExpString ) +
7936 + strlen( regExpStringInfo->resiLeftWBRegExpString ) +
7937 + strlen( regExpStringInfo->resiRightWBRegExpString ) +
7938 + strlen( regExpStringInfo->resiBothWBRegExpString ) + 5;
7940 + *regExpString = XtMalloc( resultingLen );
7942 + strcpy( *regExpString, "" );
7944 + /*
7945 + * add the single parts to the resulting regular expression
7946 + * (= cat of parts separated by an "or")
7947 + */
7948 + addSMTRegExpString( *regExpString, regExpStringInfo->resiNoneWBRegExpString, "" );
7949 + addSMTRegExpString( *regExpString, regExpStringInfo->resiLeftWBRegExpString, ")" );
7950 + addSMTRegExpString( *regExpString, regExpStringInfo->resiRightWBRegExpString, ")>" );
7951 + addSMTRegExpString( *regExpString, regExpStringInfo->resiBothWBRegExpString, ")>" );
7953 + /*
7954 + * free buffers
7955 + */
7956 + freeRegExpStringInfo( regExpStringInfo );
7960 +** Free the allocated memory contained in a RegExpStringInfo data structure
7962 +static void freeRegExpStringInfo(
7963 + RegExpStringInfo *regExpStringInfo)
7965 + int i;
7967 + XtFree( regExpStringInfo->resiNoneWBRegExpString );
7968 + XtFree( regExpStringInfo->resiLeftWBRegExpString );
7969 + XtFree( regExpStringInfo->resiRightWBRegExpString );
7970 + XtFree( regExpStringInfo->resiBothWBRegExpString );
7972 + for (i=0; i < regExpStringInfo->resiNbrOfAddedMultiPat; i ++)
7973 + XtFree( (char *)regExpStringInfo->resiAddedMultiPat[i] );
7975 + XtFree( (char *)regExpStringInfo->resiAddedMultiPat);
7979 +** Compose regular expression for start / end pattern.
7981 +static void composeStartEndRegExpString(
7982 + ReadMatchPatternInfo *readMatchPatternInfo,
7983 + MatchPatternTableElement *element,
7984 + char **regExpString)
7986 + int i;
7987 + RegExpStringInfo regExpStringInfo;
7988 + PatternReference elementRef;
7989 + PatternElementSet startPat = element->mpteStart;
7990 + PatternElementSet endPat = element->mpteEnd;
7992 + /*
7993 + * Allocate buffers for keyword regular expression.
7994 + */
7995 + setupRegExpStringBuffers(
7996 + readMatchPatternInfo,
7997 + &regExpStringInfo);
7999 + /*
8000 + * Treat start / end element of MatchPatternTableElement
8001 + */
8003 + elementRef.prElementIdx = element->mpteIndex;
8005 + for (i=0; i < startPat.pesNumberOfPattern; i ++)
8007 + elementRef.prPatternIdx = startPat.pesPattern[i]->peIndex;
8009 + addUniquePatternToRegExpString(
8010 + startPat.pesPattern[i],
8011 + &elementRef,
8012 + readMatchPatternInfo,
8013 + &regExpStringInfo);
8016 + for (i=0; i < endPat.pesNumberOfPattern; i ++)
8018 + elementRef.prPatternIdx = endPat.pesPattern[i]->peIndex;
8020 + addUniquePatternToRegExpString(
8021 + endPat.pesPattern[i],
8022 + &elementRef,
8023 + readMatchPatternInfo,
8024 + &regExpStringInfo);
8027 + /*
8028 + * Assemble the resulting regular expression
8029 + */
8030 + catSMTRegExpStrings(
8031 + &regExpStringInfo,
8032 + regExpString);
8035 +static void copyStringMatchTableForDialog(
8036 + StringMatchTable *sourceTable,
8037 + DialogMatchPatternInfo *dialogTable )
8039 + int i;
8041 + /*
8042 + * if no source table exist (yet), then set nbr. of elements / groups to 0
8043 + */
8044 + if (sourceTable == NULL)
8046 + dialogTable->dmpiNbrOfSeqElements = 0;
8048 + return;
8051 + /*
8052 + * copy matching pattern sequence
8053 + */
8054 + dialogTable->dmpiNbrOfSeqElements = sourceTable->smtNumberOfSeqElements;
8056 + for (i=0; i < sourceTable->smtNumberOfSeqElements; i ++)
8058 + copySequenceElementForDialog(
8059 + sourceTable,
8060 + sourceTable->smtSequence[i],
8061 + &dialogTable->dmpiSequence[i] );
8065 +static void *copyMatchPatternElementForDialog(
8066 + MatchPatternTable *table,
8067 + int sourceElementIdx)
8069 + int i;
8070 + int patIdx = 0;
8071 + MatchPatternTableElement *sourceElement;
8072 + DialogMatchPatternTableElement *destination;
8074 + sourceElement = table->mptElements[sourceElementIdx];
8076 + destination =
8077 + (DialogMatchPatternTableElement *)XtMalloc( sizeof(DialogMatchPatternTableElement) );
8079 + destination->dmpteName = XtNewString(sourceElement->mpteName);
8080 + destination->dmpteType = sourceElement->mpteType;
8081 + destination->dmpteSkipBtwnStartEnd = sourceElement->mpteSkipBtwnStartEnd;
8082 + destination->dmpteIgnoreHighLightInfo = sourceElement->mpteIgnoreHighLightInfo;
8083 + destination->dmpteFlash = sourceElement->mpteFlash;
8085 + for (i=0; i<sourceElement->mpteAll.pesNumberOfPattern; i++)
8087 + copyPatternForDialog(
8088 + table,
8089 + sourceElement->mpteAll.pesPattern[i],
8090 + &destination->dmptePatterns.dspElements[patIdx ++]);
8093 + destination->dmptePatterns.dspNumberOfPatterns = patIdx;
8095 + return (void *)destination;
8098 +static void copyPatternForDialog(
8099 + MatchPatternTable *table,
8100 + PatternElement *sourcePattern,
8101 + DialogStringPatternElement **dialogPattern )
8103 + DialogStringPatternElement *newPat;
8104 + StringPattern *strSourcePat = GetStringPattern( table, sourcePattern );
8106 + newPat = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
8107 + *dialogPattern = newPat;
8109 + if( strSourcePat->spOrigText != NULL)
8110 + newPat->dspeText = XtNewString(strSourcePat->spOrigText);
8111 + else
8112 + newPat->dspeText = XtNewString(strSourcePat->spText);
8114 + newPat->dspeKind = sourcePattern->peKind;
8115 + newPat->dspeWordBoundary = strSourcePat->spWordBoundary;
8116 + newPat->dspeCaseInsensitive = strSourcePat->spCaseInsensitive;
8117 + newPat->dspeRegularExpression = strSourcePat->spRegularExpression;
8120 +static void *copyGroupElementForDialog(
8121 + MatchPatternGroupElement *sourceGroup)
8123 + int i;
8124 + DialogMatchPatternGroupElement *destination;
8126 + destination =
8127 + (DialogMatchPatternGroupElement *)XtMalloc( sizeof(DialogMatchPatternGroupElement) );
8129 + destination->dmpgeName = XtNewString(sourceGroup->mpgeName);
8130 + destination->dmpgeNumberOfSubPatterns = sourceGroup->mpgeNumberOfSubPatterns;
8132 + for ( i=0; i<destination->dmpgeNumberOfSubPatterns; i ++)
8134 + destination->dmpgeSubPatternIds[i] =
8135 + XtNewString(sourceGroup->mpgeSubPatternIds[i]);
8138 + return destination;
8141 +static void copySequenceElementForDialog(
8142 + StringMatchTable *sourceTable,
8143 + MatchPatternSequenceElement *sourceSeqElement,
8144 + DialogMatchPatternSequenceElement **dialogSeqElement )
8146 + DialogMatchPatternSequenceElement *destSeqElement;
8148 + destSeqElement =
8149 + (DialogMatchPatternSequenceElement *)XtMalloc( sizeof(DialogMatchPatternSequenceElement) );
8151 + *dialogSeqElement = destSeqElement;
8153 + destSeqElement->dmpseName = XtNewString(sourceSeqElement->mpseName);
8154 + destSeqElement->dmpseType = sourceSeqElement->mpseType;
8155 + destSeqElement->dmpseValid = True;
8157 + if (destSeqElement->dmpseType == MPT_GROUP)
8159 + destSeqElement->dmpsePtr =
8160 + copyGroupElementForDialog(
8161 + sourceTable->smtGroups[sourceSeqElement->mpseIndex]);
8163 + else
8165 + destSeqElement->dmpsePtr =
8166 + copyMatchPatternElementForDialog(
8167 + sourceTable->smtAllPatterns,
8168 + sourceSeqElement->mpseIndex);
8172 +static DialogMatchPatternSequenceElement *copyDialogSequenceElement(
8173 + DialogMatchPatternSequenceElement *sourceSeq)
8175 + DialogMatchPatternSequenceElement *destSeq;
8177 + destSeq =
8178 + (DialogMatchPatternSequenceElement *)XtMalloc(sizeof(DialogMatchPatternSequenceElement));
8180 + destSeq->dmpseName = XtNewString(sourceSeq->dmpseName);
8181 + destSeq->dmpseType = sourceSeq->dmpseType;
8182 + destSeq->dmpseValid = True;
8184 + destSeq->dmpsePtr = sourceSeq->dmpsePtr;
8186 + return destSeq;
8189 +static void freeDialogMatchPatternElement(
8190 + DialogMatchPatternTableElement *dialogElement )
8192 + int i;
8194 + for (i=0; i<dialogElement->dmptePatterns.dspNumberOfPatterns; i ++)
8196 + freeDialogStringPatternElement(
8197 + dialogElement->dmptePatterns.dspElements[i]);
8200 + freeXtPtr((void **)&dialogElement->dmpteName);
8202 + freeXtPtr((void **)&dialogElement);
8205 +static void freeDialogStringPatternElement(
8206 + DialogStringPatternElement *element)
8208 + freeXtPtr((void **)&element->dspeText);
8210 + freeXtPtr((void **)&element);
8213 +static void freeDialogGroupElement(
8214 + DialogMatchPatternGroupElement *dialogGroup )
8216 + int i;
8218 + for (i=0; i<dialogGroup->dmpgeNumberOfSubPatterns; i ++)
8220 + freeXtPtr((void **)&dialogGroup->dmpgeSubPatternIds[i]);
8223 + freeXtPtr((void **)&dialogGroup->dmpgeName);
8225 + freeXtPtr((void **)&dialogGroup);
8228 +static void freeDialogSequenceElement(
8229 + DialogMatchPatternSequenceElement *dialogSeq )
8231 + freeXtPtr((void **)&dialogSeq->dmpseName);
8233 + if (dialogSeq->dmpseType == MPT_GROUP)
8235 + freeDialogGroupElement(
8236 + (DialogMatchPatternGroupElement *)dialogSeq->dmpsePtr );
8238 + else
8240 + freeDialogMatchPatternElement(
8241 + (DialogMatchPatternTableElement *)dialogSeq->dmpsePtr );
8244 + freeXtPtr((void **)&dialogSeq);
8247 +static void copyDialogStringPatternsFromTable(
8248 + DialogMatchPatternTableElement *tableElement,
8249 + DialogStringPatterns *destPatterns)
8251 + int i;
8253 + destPatterns->dspNumberOfPatterns =
8254 + tableElement->dmptePatterns.dspNumberOfPatterns;
8256 + for (i=0; i<destPatterns->dspNumberOfPatterns; i++)
8258 + destPatterns->dspElements[i] =
8259 + copyDialogStringPatternElement(
8260 + tableElement->dmptePatterns.dspElements[i] );
8264 +static void copyDialogStringPatterns(
8265 + DialogStringPatterns *sourcePatterns,
8266 + DialogStringPatterns *destPatterns)
8268 + int i;
8270 + destPatterns->dspNumberOfPatterns =
8271 + sourcePatterns->dspNumberOfPatterns;
8273 + for (i=0; i<destPatterns->dspNumberOfPatterns; i++)
8275 + destPatterns->dspElements[i] =
8276 + copyDialogStringPatternElement(
8277 + sourcePatterns->dspElements[i] );
8281 +static void freeDialogStringPatterns(
8282 + DialogStringPatterns *patterns)
8284 + int i;
8286 + for (i=0; i<patterns->dspNumberOfPatterns; i++)
8288 + freeDialogStringPatternElement(patterns->dspElements[i]);
8291 + patterns->dspNumberOfPatterns = 0;
8294 +static DialogStringPatternElement *copyDialogStringPatternElement(
8295 + DialogStringPatternElement *sourceElement)
8297 + DialogStringPatternElement *newPatElement;
8299 + newPatElement = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
8301 + newPatElement->dspeText = XtNewString(sourceElement->dspeText);
8302 + newPatElement->dspeKind = sourceElement->dspeKind;
8303 + newPatElement->dspeWordBoundary = sourceElement->dspeWordBoundary;
8304 + newPatElement->dspeCaseInsensitive = sourceElement->dspeCaseInsensitive;
8305 + newPatElement->dspeRegularExpression = sourceElement->dspeRegularExpression;
8307 + return newPatElement;
8310 +static void copyDialogPatternNamesFromGroup(
8311 + DialogMatchPatternGroupElement *group,
8312 + DialogStringPatterns *destPatterns)
8314 + int i;
8316 + destPatterns->dspNumberOfPatterns =
8317 + group->dmpgeNumberOfSubPatterns;
8319 + for (i=0; i<destPatterns->dspNumberOfPatterns; i++)
8321 + destPatterns->dspElements[i] =
8322 + copyDialogPatternName(
8323 + group->dmpgeSubPatternIds[i] );
8327 +static DialogStringPatternElement *copyDialogPatternName(
8328 + char *sourcePatternId)
8330 + DialogStringPatternElement *newPatElement;
8332 + newPatElement = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
8334 + newPatElement->dspeText = XtNewString(sourcePatternId);
8335 + newPatElement->dspeKind = PEK_START;
8336 + newPatElement->dspeWordBoundary = PWB_NONE;
8337 + newPatElement->dspeCaseInsensitive = False;
8338 + newPatElement->dspeRegularExpression = False;
8340 + return newPatElement;
8343 +static void copyDialogPatternNamesToGroup(
8344 + DialogStringPatterns *sourceNames,
8345 + DialogMatchPatternGroupElement *destGroup)
8347 + int i;
8349 + destGroup->dmpgeNumberOfSubPatterns =
8350 + sourceNames->dspNumberOfPatterns;
8352 + for (i=0; i<destGroup->dmpgeNumberOfSubPatterns; i++)
8354 + destGroup->dmpgeSubPatternIds[i] =
8355 + XtNewString(
8356 + sourceNames->dspElements[i]->dspeText);
8362 +** Present a dialog for editing matching pattern information
8364 +void EditMatchPatterns(WindowInfo *window)
8366 + Widget form, lmOptMenu;
8367 + Widget lmForm;
8368 + Widget okBtn, applyBtn, checkBtn, deleteBtn, closeBtn, helpBtn;
8369 + Widget restoreBtn, lmBtn;
8370 + Widget matchPatternsForm, matchPatternsFrame, matchPatternsLbl;
8371 + Widget matchPatternTypeBox, matchPatternTypeLbl;
8372 + Widget globalAttributesBox;
8373 + Widget stringPatternsFrame, stringPatternsForm;
8374 + Widget stringPatternTypeBox;
8375 + Widget wordBoundaryBox;
8376 + Widget stringAttributesBox;
8377 + StringMatchTable *table;
8378 + XmString s1;
8379 + int n;
8380 + Arg args[20];
8382 + /*
8383 + * if the dialog is already displayed, just pop it to the top and return
8384 + */
8385 + if (MatchPatternDialog.mpdShell != NULL)
8387 + RaiseDialogWindow(MatchPatternDialog.mpdShell);
8388 + return;
8391 + /*
8392 + * decide on an initial language mode
8393 + */
8394 + MatchPatternDialog.mpdLangModeName =
8395 + XtNewString(
8396 + window->languageMode == PLAIN_LANGUAGE_MODE ?
8397 + PLAIN_LM_STRING : LanguageModeName(window->languageMode));
8399 + /*
8400 + * find the associated matching pattern table to edit
8401 + */
8402 + table = (StringMatchTable *)FindStringMatchTable(MatchPatternDialog.mpdLangModeName);
8404 + /*
8405 + * copy the list of patterns to one that the user can freely edit
8406 + */
8407 + copyStringMatchTableForDialog( table, &MatchPatternDialog.mpdTable );
8409 + /*
8410 + * init. status information of dialog
8411 + */
8412 + MatchPatternDialog.currentDmptSeqElement = NULL;
8413 + MatchPatternDialog.currentDmptElement = NULL;
8414 + MatchPatternDialog.currentDmptGroup = NULL;
8416 + MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns = 0;
8417 + MatchPatternDialog.mpdStringPatternIsDisplayed = True;
8419 + /*
8420 + * Create a form widget in an application shell
8421 + */
8422 + n = 0;
8423 + XtSetArg(args[n], XmNdeleteResponse, XmDO_NOTHING); n++;
8424 + XtSetArg(args[n], XmNiconName, "Matching Patterns"); n++;
8425 + XtSetArg(args[n], XmNtitle, "Matching (Parenthesis) Patterns"); n++;
8426 + MatchPatternDialog.mpdShell = CreateShellWithBestVis(APP_NAME, APP_CLASS,
8427 + applicationShellWidgetClass, TheDisplay, args, n);
8428 + AddSmallIcon(MatchPatternDialog.mpdShell);
8429 + form = XtVaCreateManagedWidget("editMatchPatterns", xmFormWidgetClass,
8430 + MatchPatternDialog.mpdShell, XmNautoUnmanage, False,
8431 + XmNresizePolicy, XmRESIZE_NONE, NULL);
8432 + XtAddCallback(form, XmNdestroyCallback, destroyCB, NULL);
8433 + AddMotifCloseCallback(MatchPatternDialog.mpdShell, closeCB, NULL);
8435 + lmForm = XtVaCreateManagedWidget("lmForm", xmFormWidgetClass,
8436 + form,
8437 + XmNleftAttachment, XmATTACH_POSITION,
8438 + XmNleftPosition, 1,
8439 + XmNtopAttachment, XmATTACH_POSITION,
8440 + XmNtopPosition, 1,
8441 + XmNrightAttachment, XmATTACH_POSITION,
8442 + XmNrightPosition, 99, NULL);
8444 + MatchPatternDialog.mpdLmPulldown =
8445 + CreateLanguageModeMenu(lmForm, matchPatternLangModeCB, NULL, True);
8447 + n = 0;
8448 + XtSetArg(args[n], XmNspacing, 0); n++;
8449 + XtSetArg(args[n], XmNmarginWidth, 0); n++;
8450 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
8451 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8452 + XtSetArg(args[n], XmNleftPosition, 50); n++;
8453 + XtSetArg(args[n], XmNsubMenuId, MatchPatternDialog.mpdLmPulldown); n++;
8454 + lmOptMenu = XmCreateOptionMenu(lmForm, "langModeOptMenu", args, n);
8455 + XtManageChild(lmOptMenu);
8456 + MatchPatternDialog.mpdLmOptMenu = lmOptMenu;
8458 + XtVaCreateManagedWidget("lmLbl", xmLabelGadgetClass, lmForm,
8459 + XmNlabelString, s1=XmStringCreateSimple("Language Mode:"),
8460 + XmNmnemonic, 'M',
8461 + XmNuserData, XtParent(MatchPatternDialog.mpdLmOptMenu),
8462 + XmNalignment, XmALIGNMENT_END,
8463 + XmNrightAttachment, XmATTACH_POSITION,
8464 + XmNrightPosition, 50,
8465 + XmNtopAttachment, XmATTACH_FORM,
8466 + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
8467 + XmNbottomWidget, lmOptMenu, NULL);
8468 + XmStringFree(s1);
8470 + lmBtn = XtVaCreateManagedWidget("lmBtn", xmPushButtonWidgetClass, lmForm,
8471 + XmNlabelString, s1=MKSTRING("Add / Modify\nLanguage Mode..."),
8472 + XmNmnemonic, 'A',
8473 + XmNrightAttachment, XmATTACH_FORM,
8474 + XmNtopAttachment, XmATTACH_FORM, NULL);
8475 + XtAddCallback(lmBtn, XmNactivateCallback, pmLanguageModeDialogCB, NULL);
8476 + XmStringFree(s1);
8478 + okBtn = XtVaCreateManagedWidget("ok", xmPushButtonWidgetClass, form,
8479 + XmNlabelString, s1=XmStringCreateSimple("OK"),
8480 + XmNleftAttachment, XmATTACH_POSITION,
8481 + XmNleftPosition, 1,
8482 + XmNrightAttachment, XmATTACH_POSITION,
8483 + XmNrightPosition, 13,
8484 + XmNbottomAttachment, XmATTACH_FORM,
8485 + XmNbottomOffset, BORDER, NULL);
8486 + XtAddCallback(okBtn, XmNactivateCallback, okCB, NULL);
8487 + XmStringFree(s1);
8489 + applyBtn = XtVaCreateManagedWidget("apply", xmPushButtonWidgetClass, form,
8490 + XmNlabelString, s1=XmStringCreateSimple("Apply"),
8491 + XmNmnemonic, 'y',
8492 + XmNleftAttachment, XmATTACH_POSITION,
8493 + XmNleftPosition, 13,
8494 + XmNrightAttachment, XmATTACH_POSITION,
8495 + XmNrightPosition, 26,
8496 + XmNbottomAttachment, XmATTACH_FORM,
8497 + XmNbottomOffset, BORDER, NULL);
8498 + XtAddCallback(applyBtn, XmNactivateCallback, applyCB, NULL);
8499 + XmStringFree(s1);
8501 + checkBtn = XtVaCreateManagedWidget("check", xmPushButtonWidgetClass, form,
8502 + XmNlabelString, s1=XmStringCreateSimple("Check"),
8503 + XmNmnemonic, 'k',
8504 + XmNleftAttachment, XmATTACH_POSITION,
8505 + XmNleftPosition, 26,
8506 + XmNrightAttachment, XmATTACH_POSITION,
8507 + XmNrightPosition, 39,
8508 + XmNbottomAttachment, XmATTACH_FORM,
8509 + XmNbottomOffset, BORDER, NULL);
8510 + XtAddCallback(checkBtn, XmNactivateCallback, checkCB, NULL);
8511 + XmStringFree(s1);
8513 + deleteBtn = XtVaCreateManagedWidget("delete", xmPushButtonWidgetClass, form,
8514 + XmNlabelString, s1=XmStringCreateSimple("Delete"),
8515 + XmNmnemonic, 'D',
8516 + XmNleftAttachment, XmATTACH_POSITION,
8517 + XmNleftPosition, 39,
8518 + XmNrightAttachment, XmATTACH_POSITION,
8519 + XmNrightPosition, 52,
8520 + XmNbottomAttachment, XmATTACH_FORM,
8521 + XmNbottomOffset, BORDER, NULL);
8522 + XtAddCallback(deleteBtn, XmNactivateCallback, deleteCB, NULL);
8523 + XmStringFree(s1);
8525 + restoreBtn = XtVaCreateManagedWidget("restore", xmPushButtonWidgetClass, form,
8526 + XmNlabelString, s1=XmStringCreateSimple("Restore Defaults"),
8527 + XmNmnemonic, 'f',
8528 + XmNleftAttachment, XmATTACH_POSITION,
8529 + XmNleftPosition, 52,
8530 + XmNrightAttachment, XmATTACH_POSITION,
8531 + XmNrightPosition, 73,
8532 + XmNbottomAttachment, XmATTACH_FORM,
8533 + XmNbottomOffset, BORDER, NULL);
8534 + XtAddCallback(restoreBtn, XmNactivateCallback, restoreCB, NULL);
8535 + XmStringFree(s1);
8537 + closeBtn = XtVaCreateManagedWidget("close", xmPushButtonWidgetClass,
8538 + form,
8539 + XmNlabelString, s1=XmStringCreateSimple("Close"),
8540 + XmNleftAttachment, XmATTACH_POSITION,
8541 + XmNleftPosition, 73,
8542 + XmNrightAttachment, XmATTACH_POSITION,
8543 + XmNrightPosition, 86,
8544 + XmNbottomAttachment, XmATTACH_FORM,
8545 + XmNbottomOffset, BORDER, NULL);
8546 + XtAddCallback(closeBtn, XmNactivateCallback, closeCB, NULL);
8547 + XmStringFree(s1);
8549 + helpBtn = XtVaCreateManagedWidget("help", xmPushButtonWidgetClass,
8550 + form,
8551 + XmNlabelString, s1=XmStringCreateSimple("Help"),
8552 + XmNmnemonic, 'H',
8553 + XmNleftAttachment, XmATTACH_POSITION,
8554 + XmNleftPosition, 86,
8555 + XmNrightAttachment, XmATTACH_POSITION,
8556 + XmNrightPosition, 99,
8557 + XmNbottomAttachment, XmATTACH_FORM,
8558 + XmNbottomOffset, BORDER, NULL);
8559 + XtAddCallback(helpBtn, XmNactivateCallback, helpCB, NULL);
8560 + XmStringFree(s1);
8562 + stringPatternsFrame = XtVaCreateManagedWidget("stringPatternsFrame", xmFrameWidgetClass,
8563 + form,
8564 + XmNleftAttachment, XmATTACH_POSITION,
8565 + XmNleftPosition, 1,
8566 + XmNrightAttachment, XmATTACH_POSITION,
8567 + XmNrightPosition, 99,
8568 + XmNbottomAttachment, XmATTACH_WIDGET,
8569 + XmNbottomWidget, okBtn,
8570 + XmNbottomOffset, BORDER, NULL);
8571 + stringPatternsForm = XtVaCreateManagedWidget("stringPatternsForm", xmFormWidgetClass,
8572 + stringPatternsFrame, NULL);
8573 + MatchPatternDialog.mpdStringPatternsLbl = XtVaCreateManagedWidget("mpdStringPatternsLbl", xmLabelGadgetClass,
8574 + stringPatternsFrame,
8575 + XmNlabelString, s1=XmStringCreateSimple(STRING_PATTERNS_LBL_TXT),
8576 + XmNmarginHeight, 0,
8577 + XmNchildType, XmFRAME_TITLE_CHILD, NULL);
8578 + XmStringFree(s1);
8580 + n = 0;
8581 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
8582 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8583 + XtSetArg(args[n], XmNleftPosition, 1); n++;
8584 + XtSetArg(args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
8585 + XtSetArg(args[n], XmNrightPosition, LIST_RIGHT-1); n++;
8586 + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
8587 + XtSetArg(args[n], XmNbottomOffset, BORDER); n++;
8588 + MatchPatternDialog.mpdStringPatternsListW =
8589 + CreateManagedList(stringPatternsForm, "stringPatternsList", args,
8590 + n, (void **)MatchPatternDialog.currentStringPatterns.dspElements,
8591 + &MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns,
8592 + MAX_STRING_PATTERNS, 18,
8593 + getStringPatternDisplayedCB, NULL,
8594 + setStringPatternDisplayedCB, NULL,
8595 + freeStringPatternItemCB);
8596 + XtVaSetValues(MatchPatternDialog.mpdStringPatternsLbl, XmNuserData, MatchPatternDialog.mpdStringPatternsListW, NULL);
8598 + MatchPatternDialog.mpdStringPatternTypeLbl = XtVaCreateManagedWidget("mpdStringPatternTypeLbl", xmLabelGadgetClass,
8599 + stringPatternsForm,
8600 + XmNlabelString, s1=XmStringCreateSimple("String Pattern Type:"),
8601 + XmNmarginHeight, 0,
8602 + XmNalignment, XmALIGNMENT_BEGINNING,
8603 + XmNleftAttachment, XmATTACH_POSITION,
8604 + XmNleftPosition, LIST_RIGHT,
8605 + XmNtopAttachment, XmATTACH_FORM, NULL);
8606 + XmStringFree(s1);
8608 + stringPatternTypeBox = XtVaCreateManagedWidget("stringPatternTypeBox", xmRowColumnWidgetClass,
8609 + stringPatternsForm,
8610 + XmNorientation, XmHORIZONTAL,
8611 + XmNpacking, XmPACK_TIGHT,
8612 + XmNradioBehavior, True,
8613 + XmNleftAttachment, XmATTACH_POSITION,
8614 + XmNleftPosition, LIST_RIGHT,
8615 + XmNtopAttachment, XmATTACH_WIDGET,
8616 + XmNtopWidget, MatchPatternDialog.mpdStringPatternTypeLbl, NULL);
8617 + MatchPatternDialog.sptStartW = XtVaCreateManagedWidget("sptStartW",
8618 + xmToggleButtonWidgetClass, stringPatternTypeBox,
8619 + XmNset, True,
8620 + XmNmarginHeight, 0,
8621 + XmNlabelString, s1=XmStringCreateSimple(
8622 + "Start"),
8623 + NULL);
8624 + XmStringFree(s1);
8625 + MatchPatternDialog.sptMiddleW = XtVaCreateManagedWidget("sptMiddleW",
8626 + xmToggleButtonWidgetClass, stringPatternTypeBox,
8627 + XmNmarginHeight, 0,
8628 + XmNlabelString, s1=XmStringCreateSimple(
8629 + "Middle"),
8630 + NULL);
8631 + XmStringFree(s1);
8632 + MatchPatternDialog.sptEndW = XtVaCreateManagedWidget("sptEndW",
8633 + xmToggleButtonWidgetClass, stringPatternTypeBox,
8634 + XmNmarginHeight, 0,
8635 + XmNlabelString, s1=XmStringCreateSimple(
8636 + "End"),
8637 + NULL);
8638 + XmStringFree(s1);
8640 + MatchPatternDialog.mpdWordBoundaryLbl = XtVaCreateManagedWidget("mpdWordBoundaryLbl", xmLabelGadgetClass,
8641 + stringPatternsForm,
8642 + XmNlabelString, s1=XmStringCreateSimple("Word boundary:"),
8643 + XmNmarginHeight, 0,
8644 + XmNalignment, XmALIGNMENT_BEGINNING,
8645 + XmNleftAttachment, XmATTACH_POSITION,
8646 + XmNleftPosition, LIST_RIGHT,
8647 + XmNtopAttachment, XmATTACH_WIDGET,
8648 + XmNtopWidget, stringPatternTypeBox,
8649 + NULL);
8650 + XmStringFree(s1);
8652 + wordBoundaryBox = XtVaCreateManagedWidget("wordBoundaryBox", xmRowColumnWidgetClass,
8653 + stringPatternsForm,
8654 + XmNorientation, XmHORIZONTAL,
8655 + XmNpacking, XmPACK_TIGHT,
8656 + XmNradioBehavior, True,
8657 + XmNleftAttachment, XmATTACH_POSITION,
8658 + XmNleftPosition, LIST_RIGHT,
8659 + XmNtopAttachment, XmATTACH_WIDGET,
8660 + XmNtopWidget, MatchPatternDialog.mpdWordBoundaryLbl, NULL);
8661 + MatchPatternDialog.wbbBothW = XtVaCreateManagedWidget("wbbBothW",
8662 + xmToggleButtonWidgetClass, wordBoundaryBox,
8663 + XmNset, True,
8664 + XmNmarginHeight, 0,
8665 + XmNlabelString, s1=XmStringCreateSimple(
8666 + "Both (pattern is word)"),
8667 + NULL);
8668 + XmStringFree(s1);
8669 + MatchPatternDialog.wbbLeftW = XtVaCreateManagedWidget("wbbLeftW",
8670 + xmToggleButtonWidgetClass, wordBoundaryBox,
8671 + XmNmarginHeight, 0,
8672 + XmNlabelString, s1=XmStringCreateSimple(
8673 + "Left"),
8674 + NULL);
8675 + XmStringFree(s1);
8676 + MatchPatternDialog.wbbRightW = XtVaCreateManagedWidget("wbbRightW",
8677 + xmToggleButtonWidgetClass, wordBoundaryBox,
8678 + XmNmarginHeight, 0,
8679 + XmNlabelString, s1=XmStringCreateSimple(
8680 + "Right"),
8681 + NULL);
8682 + XmStringFree(s1);
8683 + MatchPatternDialog.wbbNoneW = XtVaCreateManagedWidget("wbbNoneW",
8684 + xmToggleButtonWidgetClass, wordBoundaryBox,
8685 + XmNmarginHeight, 0,
8686 + XmNlabelString, s1=XmStringCreateSimple(
8687 + "None"),
8688 + NULL);
8689 + XmStringFree(s1);
8691 + MatchPatternDialog.mpdStringAttributesLbl = XtVaCreateManagedWidget("mpdStringAttributesLbl", xmLabelGadgetClass,
8692 + stringPatternsForm,
8693 + XmNlabelString, s1=XmStringCreateSimple("String Attributes:"),
8694 + XmNmarginHeight, 0,
8695 + XmNalignment, XmALIGNMENT_BEGINNING,
8696 + XmNleftAttachment, XmATTACH_POSITION,
8697 + XmNleftPosition, LIST_RIGHT,
8698 + XmNtopAttachment, XmATTACH_WIDGET,
8699 + XmNtopWidget, wordBoundaryBox, NULL);
8700 + XmStringFree(s1);
8702 + stringAttributesBox = XtVaCreateManagedWidget("stringAttributesBox", xmRowColumnWidgetClass,
8703 + stringPatternsForm,
8704 + XmNorientation, XmHORIZONTAL,
8705 + XmNpacking, XmPACK_TIGHT,
8706 + XmNleftAttachment, XmATTACH_POSITION,
8707 + XmNleftPosition, LIST_RIGHT,
8708 + XmNtopAttachment, XmATTACH_WIDGET,
8709 + XmNtopWidget, MatchPatternDialog.mpdStringAttributesLbl, NULL);
8710 + MatchPatternDialog.sabRegularExpressionW = XtVaCreateManagedWidget("sabRegularExpressionW",
8711 + xmToggleButtonWidgetClass, stringAttributesBox,
8712 + XmNset, False,
8713 + XmNmarginHeight, 0,
8714 + XmNlabelString, s1=XmStringCreateSimple(
8715 + "Regular Expression"),
8716 + NULL);
8717 + XmStringFree(s1);
8718 + XtAddCallback(MatchPatternDialog.sabRegularExpressionW, XmNvalueChangedCallback,
8719 + strPatRegExpressionCB, NULL);
8720 + MatchPatternDialog.sabCaseSensitiveW = XtVaCreateManagedWidget("sabCaseSensitiveW",
8721 + xmToggleButtonWidgetClass, stringAttributesBox,
8722 + XmNset, True,
8723 + XmNmarginHeight, 0,
8724 + XmNlabelString, s1=XmStringCreateSimple(
8725 + "Case Sensitive"),
8726 + NULL);
8727 + XmStringFree(s1);
8729 + MatchPatternDialog.mpdStringPatternLbl = XtVaCreateManagedWidget("mpdStringPatternLbl", xmLabelGadgetClass,
8730 + stringPatternsForm,
8731 + XmNlabelString, s1=XmStringCreateSimple("String Pattern"),
8732 + XmNmnemonic, 'S',
8733 + XmNalignment, XmALIGNMENT_BEGINNING,
8734 + XmNleftAttachment, XmATTACH_POSITION,
8735 + XmNleftPosition, LIST_RIGHT,
8736 + XmNtopAttachment, XmATTACH_WIDGET,
8737 + XmNtopWidget, stringAttributesBox,
8738 + XmNtopOffset, BORDER,
8739 + NULL);
8740 + XmStringFree(s1);
8742 + MatchPatternDialog.mpdStringPatternW = XtVaCreateManagedWidget("mpdStringPatternW", xmTextWidgetClass,
8743 + stringPatternsForm,
8744 + XmNleftAttachment, XmATTACH_POSITION,
8745 + XmNleftPosition, LIST_RIGHT,
8746 + XmNtopAttachment, XmATTACH_WIDGET,
8747 + XmNtopWidget, MatchPatternDialog.mpdStringPatternLbl,
8748 + XmNrightAttachment, XmATTACH_FORM,
8749 + XmNrightOffset, BORDER,
8750 + NULL);
8751 + RemapDeleteKey(MatchPatternDialog.mpdStringPatternW);
8752 + XtVaSetValues(MatchPatternDialog.mpdStringPatternLbl, XmNuserData, MatchPatternDialog.mpdStringPatternW, NULL);
8754 + MatchPatternDialog.mpdSubPatNamesLbl = XtVaCreateManagedWidget("mpdSubPatNamesLbl", xmLabelGadgetClass,
8755 + stringPatternsForm,
8756 + XmNlabelString, s1=XmStringCreateSimple("Sub-Pattern Name"),
8757 + XmNmnemonic, 't',
8758 + XmNalignment, XmALIGNMENT_BEGINNING,
8759 + XmNleftAttachment, XmATTACH_POSITION,
8760 + XmNleftPosition, LIST_RIGHT,
8761 + XmNtopAttachment, XmATTACH_WIDGET,
8762 + XmNtopWidget, MatchPatternDialog.mpdStringPatternW,
8763 + XmNtopOffset, BORDER,
8764 + NULL);
8765 + XmStringFree(s1);
8767 + MatchPatternDialog.mpdSubPatNamesPulldown =
8768 + createSubPatternNameMenu(stringPatternsForm, NULL, False);
8770 + n = 0;
8771 + XtSetArg(args[n], XmNspacing, 0); n++;
8772 + XtSetArg(args[n], XmNmarginWidth, 0); n++;
8773 + XtSetArg(args[n], XmNresizeWidth, True); n++;
8774 + XtSetArg(args[n], XmNresizeHeight, True); n++;
8775 + XtSetArg(args[n], XmNnavigationType, XmTAB_GROUP); n++;
8776 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
8777 + XtSetArg(args[n], XmNtopWidget, MatchPatternDialog.mpdSubPatNamesLbl); n++;
8778 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8779 + XtSetArg(args[n], XmNleftPosition, LIST_RIGHT); n++;
8780 + XtSetArg(args[n], XmNsubMenuId, MatchPatternDialog.mpdSubPatNamesPulldown); n++;
8781 + MatchPatternDialog.mpdSubPatNamesOptMenu =
8782 + XmCreateOptionMenu(stringPatternsForm, "subPatNamesOptMenu", args, n);
8783 + XtManageChild(MatchPatternDialog.mpdSubPatNamesOptMenu);
8785 + XtVaSetValues(
8786 + MatchPatternDialog.mpdSubPatNamesLbl,
8787 + XmNuserData, XtParent(MatchPatternDialog.mpdSubPatNamesOptMenu),
8788 + NULL);
8790 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesLbl, False);
8791 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesOptMenu, False);
8793 + matchPatternsFrame = XtVaCreateManagedWidget("matchPatternsFrame", xmFrameWidgetClass,
8794 + form,
8795 + XmNleftAttachment, XmATTACH_POSITION,
8796 + XmNleftPosition, 1,
8797 + XmNtopAttachment, XmATTACH_WIDGET,
8798 + XmNtopWidget, lmForm,
8799 + XmNrightAttachment, XmATTACH_POSITION,
8800 + XmNrightPosition, 99,
8801 + XmNbottomAttachment, XmATTACH_WIDGET,
8802 + XmNbottomWidget, stringPatternsFrame,
8803 + XmNbottomOffset, BORDER, NULL);
8804 + matchPatternsForm = XtVaCreateManagedWidget("matchPatternsForm", xmFormWidgetClass,
8805 + matchPatternsFrame, NULL);
8806 + matchPatternsLbl = XtVaCreateManagedWidget("matchPatternsLbl", xmLabelGadgetClass,
8807 + matchPatternsFrame,
8808 + XmNlabelString, s1=XmStringCreateSimple("Matching Patterns"),
8809 + XmNmnemonic, 'P',
8810 + XmNmarginHeight, 0,
8811 + XmNchildType, XmFRAME_TITLE_CHILD, NULL);
8812 + XmStringFree(s1);
8814 + matchPatternTypeLbl = XtVaCreateManagedWidget("matchPatternTypeLbl", xmLabelGadgetClass,
8815 + matchPatternsForm,
8816 + XmNlabelString, s1=XmStringCreateSimple("Matching Pattern Type:"),
8817 + XmNmarginHeight, 0,
8818 + XmNalignment, XmALIGNMENT_BEGINNING,
8819 + XmNleftAttachment, XmATTACH_POSITION,
8820 + XmNleftPosition, LIST_RIGHT,
8821 + XmNtopAttachment, XmATTACH_FORM, NULL);
8822 + XmStringFree(s1);
8824 + matchPatternTypeBox = XtVaCreateManagedWidget("matchPatternTypeBox", xmRowColumnWidgetClass,
8825 + matchPatternsForm,
8826 + XmNpacking, XmPACK_COLUMN,
8827 + XmNradioBehavior, True,
8828 + XmNleftAttachment, XmATTACH_POSITION,
8829 + XmNleftPosition, LIST_RIGHT,
8830 + XmNtopAttachment, XmATTACH_WIDGET,
8831 + XmNtopWidget, matchPatternTypeLbl, NULL);
8832 + MatchPatternDialog.mptbIndividualW = XtVaCreateManagedWidget("mptbIndividualW",
8833 + xmToggleButtonWidgetClass, matchPatternTypeBox,
8834 + XmNset, True,
8835 + XmNmarginHeight, 0,
8836 + XmNlabelString, s1=XmStringCreateSimple(
8837 + "Individual"),
8838 + XmNmnemonic, 'I', NULL);
8839 + XmStringFree(s1);
8840 + XtAddCallback(MatchPatternDialog.mptbIndividualW, XmNvalueChangedCallback,
8841 + matchPatTypeCB, NULL);
8842 + MatchPatternDialog.mptbSubPatternW = XtVaCreateManagedWidget("mptbSubPatternW",
8843 + xmToggleButtonWidgetClass, matchPatternTypeBox,
8844 + XmNmarginHeight, 0,
8845 + XmNlabelString, s1=XmStringCreateSimple(
8846 + "Sub-pattern (belongs to context group)"),
8847 + XmNmnemonic, 'u', NULL);
8848 + XmStringFree(s1);
8849 + XtAddCallback(MatchPatternDialog.mptbSubPatternW, XmNvalueChangedCallback,
8850 + matchPatTypeCB, NULL);
8851 + MatchPatternDialog.mptbContextGroupW = XtVaCreateManagedWidget("mptbContextGroupW",
8852 + xmToggleButtonWidgetClass, matchPatternTypeBox,
8853 + XmNmarginHeight, 0,
8854 + XmNlabelString, s1=XmStringCreateSimple(
8855 + "Context group"),
8856 + XmNmnemonic, 'g', NULL);
8857 + XmStringFree(s1);
8858 + XtAddCallback(MatchPatternDialog.mptbContextGroupW, XmNvalueChangedCallback,
8859 + matchPatTypeCB, NULL);
8861 + MatchPatternDialog.mpdGlobalAttributesLbl = XtVaCreateManagedWidget("mpdGlobalAttributesLbl",
8862 + xmLabelGadgetClass, matchPatternsForm,
8863 + XmNlabelString, s1=XmStringCreateSimple("Global Attributes:"),
8864 + XmNmarginHeight, 0,
8865 + XmNalignment, XmALIGNMENT_BEGINNING,
8866 + XmNleftAttachment, XmATTACH_POSITION,
8867 + XmNleftPosition, LIST_RIGHT,
8868 + XmNtopAttachment, XmATTACH_WIDGET,
8869 + XmNtopOffset, BORDER,
8870 + XmNtopWidget, matchPatternTypeBox, NULL);
8871 + XmStringFree(s1);
8873 + globalAttributesBox = XtVaCreateManagedWidget("globalAttributesBox", xmRowColumnWidgetClass,
8874 + matchPatternsForm,
8875 + XmNpacking, XmPACK_COLUMN,
8876 + XmNleftAttachment, XmATTACH_POSITION,
8877 + XmNleftPosition, LIST_RIGHT,
8878 + XmNtopAttachment, XmATTACH_WIDGET,
8879 + XmNtopWidget, MatchPatternDialog.mpdGlobalAttributesLbl, NULL);
8880 + MatchPatternDialog.gabSkipBtwStartEndW = XtVaCreateManagedWidget("gabSkipBtwStartEndW",
8881 + xmToggleButtonWidgetClass, globalAttributesBox,
8882 + XmNmarginHeight, 0,
8883 + XmNlabelString, s1=XmStringCreateSimple(
8884 + "Skip content between start / end pattern"),
8885 + XmNmnemonic, 'c', NULL);
8886 + XmStringFree(s1);
8887 + MatchPatternDialog.gabFlashW = XtVaCreateManagedWidget("gabFlashW",
8888 + xmToggleButtonWidgetClass, globalAttributesBox,
8889 + XmNset, True,
8890 + XmNmarginHeight, 0,
8891 + XmNlabelString, s1=XmStringCreateSimple(
8892 + "Flash matching pattern"),
8893 + XmNmnemonic, 'l', NULL);
8894 + XmStringFree(s1);
8895 + MatchPatternDialog.gabSyntaxBasedW = XtVaCreateManagedWidget("gabSyntaxBasedW",
8896 + xmToggleButtonWidgetClass, globalAttributesBox,
8897 + XmNset, True,
8898 + XmNmarginHeight, 0,
8899 + XmNlabelString, s1=XmStringCreateSimple(
8900 + "Syntax based"),
8901 + XmNmnemonic, 'b', NULL);
8902 + XmStringFree(s1);
8904 + MatchPatternDialog.mpdMatchPatternNameLbl = XtVaCreateManagedWidget("mpdMatchPatternNameLbl", xmLabelGadgetClass,
8905 + matchPatternsForm,
8906 + XmNlabelString, s1=XmStringCreateSimple(MATCH_PAT_NAME_LBL_TXT),
8907 + XmNmnemonic, 'N',
8908 + XmNalignment, XmALIGNMENT_BEGINNING,
8909 + XmNleftAttachment, XmATTACH_POSITION,
8910 + XmNleftPosition, LIST_RIGHT,
8911 + XmNtopAttachment, XmATTACH_WIDGET,
8912 + XmNtopWidget, globalAttributesBox,
8913 + XmNtopOffset, BORDER, NULL);
8914 + XmStringFree(s1);
8916 + MatchPatternDialog.mpdMatchPatternNameW = XtVaCreateManagedWidget("mpdMatchPatternNameW", xmTextWidgetClass,
8917 + matchPatternsForm,
8918 + XmNleftAttachment, XmATTACH_POSITION,
8919 + XmNleftPosition, LIST_RIGHT,
8920 + XmNtopAttachment, XmATTACH_WIDGET,
8921 + XmNtopWidget, MatchPatternDialog.mpdMatchPatternNameLbl,
8922 + XmNrightAttachment, XmATTACH_FORM,
8923 + XmNrightOffset, BORDER,
8924 + XmNbottomAttachment, XmATTACH_FORM,
8925 + XmNbottomOffset, BORDER,
8926 + NULL);
8927 + RemapDeleteKey(MatchPatternDialog.mpdMatchPatternNameW);
8928 + XtVaSetValues(MatchPatternDialog.mpdMatchPatternNameLbl, XmNuserData, MatchPatternDialog.mpdMatchPatternNameW, NULL);
8930 + n = 0;
8931 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
8932 + XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
8933 + XtSetArg(args[n], XmNleftPosition, 1); n++;
8934 + XtSetArg(args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
8935 + XtSetArg(args[n], XmNrightPosition, LIST_RIGHT-1); n++;
8936 + XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
8938 + XtSetArg(args[n], XmNbottomOffset, BORDER); n++;
8939 + MatchPatternDialog.mpdMatchPatternNamesListW =
8940 + CreateManagedList(
8941 + matchPatternsForm, "mpdMatchPatternNamesListW",
8942 + args, n,
8943 + (void **)MatchPatternDialog.mpdTable.dmpiSequence, &MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements,
8944 + MAX_NBR_MATCH_PATTERNS, 18,
8945 + getMatchPatternDisplayedCB, NULL,
8946 + setMatchPatternDisplayedCB, NULL,
8947 + freeMatchPatternItemCB);
8948 + AddDeleteConfirmCB(MatchPatternDialog.mpdMatchPatternNamesListW, deleteMatchPatternItemCB, NULL);
8950 + XtVaSetValues(matchPatternsLbl, XmNuserData, MatchPatternDialog.mpdMatchPatternNamesListW, NULL);
8952 + /*
8953 + * set initial default button
8954 + */
8955 + XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
8956 + XtVaSetValues(form, XmNcancelButton, closeBtn, NULL);
8958 + /*
8959 + * handle mnemonic selection of buttons and focus to dialog
8960 + */
8961 + AddDialogMnemonicHandler(form, False);
8963 + /*
8964 + * fill in the dialog information for the selected language mode
8965 + */
8966 + SetLangModeMenu(MatchPatternDialog.mpdLmOptMenu, MatchPatternDialog.mpdLangModeName);
8968 + /*
8969 + * realize all of the widgets in the new dialog
8970 + */
8971 + RealizeWithoutForcingPosition(MatchPatternDialog.mpdShell);
8975 +** Modify match pattern dialog depending on showing a string pattern
8976 +** or a context group.
8978 +static void setDialogType(int dialogShowsStringPattern)
8980 + char *matchPatternNameText;
8981 + char *strPatCxtGrpListText;
8982 + XmString s1;
8983 + int regularExpression =
8984 + XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
8986 + /*
8987 + * check, if dialog mode needs to be switched
8988 + */
8989 + if (MatchPatternDialog.mpdStringPatternIsDisplayed == dialogShowsStringPattern)
8991 + return;
8994 + if (dialogShowsStringPattern)
8996 + matchPatternNameText = MATCH_PAT_NAME_LBL_TXT;
8997 + strPatCxtGrpListText = STRING_PATTERNS_LBL_TXT;
8999 + else
9001 + matchPatternNameText = "Context Group Name";
9002 + strPatCxtGrpListText = "Related Sub-Patterns";
9005 + XtSetSensitive(MatchPatternDialog.mpdGlobalAttributesLbl, dialogShowsStringPattern);
9006 + XtSetSensitive(MatchPatternDialog.gabSkipBtwStartEndW, dialogShowsStringPattern);
9007 + XtSetSensitive(MatchPatternDialog.gabFlashW, dialogShowsStringPattern);
9008 + XtSetSensitive(MatchPatternDialog.gabSyntaxBasedW, dialogShowsStringPattern);
9010 + XtSetSensitive(MatchPatternDialog.mpdStringPatternTypeLbl, dialogShowsStringPattern);
9011 + XtSetSensitive(MatchPatternDialog.sptStartW, dialogShowsStringPattern);
9012 + XtSetSensitive(MatchPatternDialog.sptMiddleW, dialogShowsStringPattern);
9013 + XtSetSensitive(MatchPatternDialog.sptEndW, dialogShowsStringPattern);
9015 + setSensitiveWordBoundaryBox( dialogShowsStringPattern && !regularExpression );
9017 + XtSetSensitive(MatchPatternDialog.mpdStringAttributesLbl, dialogShowsStringPattern);
9018 + XtSetSensitive(MatchPatternDialog.sabCaseSensitiveW, dialogShowsStringPattern);
9019 + XtSetSensitive(MatchPatternDialog.sabRegularExpressionW, dialogShowsStringPattern);
9021 + XtSetSensitive(MatchPatternDialog.mpdStringPatternLbl, dialogShowsStringPattern);
9022 + XtSetSensitive(MatchPatternDialog.mpdStringPatternW, dialogShowsStringPattern);
9024 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesLbl, !dialogShowsStringPattern);
9025 + XtSetSensitive(MatchPatternDialog.mpdSubPatNamesOptMenu, !dialogShowsStringPattern);
9027 + XtVaSetValues(
9028 + MatchPatternDialog.mpdMatchPatternNameLbl,
9029 + XmNlabelString, s1=XmStringCreateSimple(matchPatternNameText),
9030 + NULL);
9031 + XmStringFree(s1);
9033 + XtVaSetValues(
9034 + MatchPatternDialog.mpdStringPatternsLbl,
9035 + XmNlabelString, s1=XmStringCreateSimple(strPatCxtGrpListText),
9036 + NULL);
9037 + XmStringFree(s1);
9039 + MatchPatternDialog.mpdStringPatternIsDisplayed = dialogShowsStringPattern;
9042 +static void setSensitiveWordBoundaryBox(int enable)
9044 + XtSetSensitive(MatchPatternDialog.mpdWordBoundaryLbl, enable);
9045 + XtSetSensitive(MatchPatternDialog.wbbBothW , enable);
9046 + XtSetSensitive(MatchPatternDialog.wbbLeftW , enable);
9047 + XtSetSensitive(MatchPatternDialog.wbbRightW, enable);
9048 + XtSetSensitive(MatchPatternDialog.wbbNoneW , enable);
9051 +static void matchPatternLangModeCB(Widget w, XtPointer clientData, XtPointer callData)
9053 + char *modeName;
9054 + StringMatchTable *oldTable, *newTable;
9055 + StringMatchTable emptyTable = {"", NULL, NULL, NULL, NULL, 0, NULL, 0, NULL};
9056 + StringMatchTable *table;
9057 + DMPTranslationResult translResult;
9058 + int resp;
9060 + /*
9061 + * Get the newly selected mode name. If it's the same, do nothing
9062 + */
9063 + XtVaGetValues(w, XmNuserData, &modeName, NULL);
9064 + if (!strcmp(modeName, MatchPatternDialog.mpdLangModeName))
9065 + return;
9067 + /*
9068 + * Look up the original version of the patterns being edited
9069 + */
9070 + oldTable = (StringMatchTable *)FindStringMatchTable(MatchPatternDialog.mpdLangModeName);
9071 + if (oldTable == NULL)
9072 + oldTable = &emptyTable;
9074 + /*
9075 + * Get the current information displayed by the dialog. If it's bad,
9076 + * give the user the chance to throw it out or go back and fix it. If
9077 + * it has changed, give the user the chance to apply discard or cancel.
9078 + */
9079 + newTable = getDialogStringMatchTable(&translResult);
9081 + if (translResult == DMPTR_EMPTY)
9083 + newTable = &emptyTable;
9086 + if (newTable == NULL)
9088 + if (DialogF(
9089 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9090 + "Incomplete Matching Patterns for Language Mode",
9091 + "Discard incomplete entry for language mode '%s'?",
9092 + "Keep", "Discard",
9093 + MatchPatternDialog.mpdLangModeName) == 1)
9095 + SetLangModeMenu(
9096 + MatchPatternDialog.mpdLmOptMenu,
9097 + MatchPatternDialog.mpdLangModeName);
9099 + return;
9102 + else if (stringMatchTableDiffer(oldTable, newTable))
9104 + if (newTable == &emptyTable)
9105 + newTable = NULL;
9107 + resp =
9108 + DialogF(
9109 + DF_WARN, MatchPatternDialog.mpdShell, 3,
9110 + "Change Language Mode",
9111 + "Apply changes for language mode '%s'?",
9112 + "Apply Changes", "Discard Changes", "Cancel",
9113 + MatchPatternDialog.mpdLangModeName);
9115 + if (resp == 3)
9117 + SetLangModeMenu(
9118 + MatchPatternDialog.mpdLmOptMenu,
9119 + MatchPatternDialog.mpdLangModeName);
9121 + freeStringMatchTable( newTable );
9123 + return;
9125 + else if (resp == 1)
9127 + updateStringMatchTable( newTable );
9129 + /*
9130 + * Don't free the new table due to it's stored in MatchTables now
9131 + */
9132 + newTable = NULL;
9136 + if (newTable != NULL && newTable != &emptyTable)
9137 + freeStringMatchTable(newTable);
9139 + /*
9140 + * Free the old dialog information
9141 + */
9142 + freeVariableDialogData(DISCARD_LANGUAGE_MODE);
9144 + /*
9145 + * Fill the dialog with the new language mode information
9146 + */
9147 + MatchPatternDialog.mpdLangModeName = XtNewString(modeName);
9149 + /*
9150 + * Find the associated matching pattern table to edit
9151 + */
9152 + table = (StringMatchTable *)FindStringMatchTable(MatchPatternDialog.mpdLangModeName);
9154 + /*
9155 + * Copy the list of patterns to one that the user can freely edit
9156 + */
9157 + copyStringMatchTableForDialog( table, &MatchPatternDialog.mpdTable );
9159 + /*
9160 + * Update dialog fields
9161 + */
9162 + ChangeManagedListData(MatchPatternDialog.mpdMatchPatternNamesListW);
9163 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9166 +static void pmLanguageModeDialogCB(Widget w, XtPointer clientData, XtPointer callData)
9168 + EditLanguageModes();
9172 +** If a matching pattern dialog is up, ask to have the option menu for
9173 +** chosing language mode updated (via a call to CreateLanguageModeMenu)
9175 +void UpdateLanguageModeMenuMatchPattern(void)
9177 + Widget oldMenu;
9179 + if (MatchPatternDialog.mpdShell == NULL)
9180 + return;
9182 + oldMenu = MatchPatternDialog.mpdLmPulldown;
9183 + /*
9184 + * don't include "PLAIN" (4th parameter) in LM menu
9185 + */
9186 + MatchPatternDialog.mpdLmPulldown = CreateLanguageModeMenu(
9187 + XtParent(XtParent(oldMenu)), matchPatternLangModeCB, NULL, False);
9188 + XtVaSetValues(XmOptionButtonGadget(MatchPatternDialog.mpdLmOptMenu),
9189 + XmNsubMenuId, MatchPatternDialog.mpdLmPulldown, NULL);
9190 + SetLangModeMenu(MatchPatternDialog.mpdLmOptMenu, MatchPatternDialog.mpdLangModeName);
9192 + XtDestroyWidget(oldMenu);
9195 +static void *getMatchPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
9196 + void *cbArg)
9198 + DialogMatchPatternSequenceElement *newSeq;
9200 + /*
9201 + * If the dialog is currently displaying the "new" entry and the
9202 + * fields are empty, that's just fine
9203 + */
9204 + if (oldItem == NULL && matchPatternDialogEmpty())
9205 + return NULL;
9207 + /*
9208 + * Read string patterns / sub-pattern names area first
9209 + */
9210 + UpdateManagedList(MatchPatternDialog.mpdStringPatternsListW, True);
9212 + /*
9213 + * If there are no problems reading the data, just return it
9214 + */
9215 + newSeq = readMatchPatternFields(True);
9216 + if (newSeq != NULL)
9217 + return (void *)newSeq;
9219 + /*
9220 + * If there are problems, and the user didn't ask for the fields to be
9221 + * read, give more warning
9222 + */
9223 + if (!explicitRequest)
9225 + if (DialogF(
9226 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9227 + "Discard Matching Pattern Entry",
9228 + "Discard incomplete entry\nfor current matching pattern?",
9229 + "Keep", "Discard") == 2)
9231 + return oldItem == NULL
9232 + ? NULL
9233 + : (void *)copyDialogSequenceElement(
9234 + (DialogMatchPatternSequenceElement *)oldItem);
9238 + /*
9239 + * read data again without "silent" mode to display warning
9240 + */
9241 + newSeq = readMatchPatternFields(False);
9242 + *abort = True;
9244 + return NULL;
9247 +static void setMatchPatternDisplayedCB(void *item, void *cbArg)
9249 + DialogMatchPatternSequenceElement *seqElement;
9250 + DialogMatchPatternTableElement *element;
9251 + DialogMatchPatternGroupElement *group;
9252 + int isGroup;
9254 + seqElement = (DialogMatchPatternSequenceElement *)item;
9256 + MatchPatternDialog.currentDmptSeqElement = seqElement;
9258 + if (item == NULL)
9260 + MatchPatternDialog.currentDmptElement = NULL;
9261 + MatchPatternDialog.currentDmptGroup = NULL;
9263 + XmTextSetString(MatchPatternDialog.mpdMatchPatternNameW, "");
9264 + RadioButtonChangeState(MatchPatternDialog.mptbIndividualW, True, True);
9265 + RadioButtonChangeState(MatchPatternDialog.gabSkipBtwStartEndW, False, False);
9266 + RadioButtonChangeState(MatchPatternDialog.gabFlashW, True, False);
9267 + RadioButtonChangeState(MatchPatternDialog.gabSyntaxBasedW, True, False);
9269 + freeDialogStringPatterns(
9270 + &MatchPatternDialog.currentStringPatterns);
9272 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9274 + setDialogType( STRING_PATTERN_DIALOG );
9276 + else
9278 + isGroup = (seqElement->dmpseType == MPT_GROUP);
9280 + XmTextSetString(MatchPatternDialog.mpdMatchPatternNameW, seqElement->dmpseName);
9282 + if (seqElement->dmpseType == MPT_INDIVIDUAL)
9283 + RadioButtonChangeState(MatchPatternDialog.mptbIndividualW, True, True);
9284 + else if (seqElement->dmpseType == MPT_SUB)
9285 + RadioButtonChangeState(MatchPatternDialog.mptbSubPatternW, True, True);
9286 + else
9287 + RadioButtonChangeState(MatchPatternDialog.mptbContextGroupW, True, True);
9289 + freeDialogStringPatterns(
9290 + &MatchPatternDialog.currentStringPatterns);
9292 + if (isGroup)
9294 + group = (DialogMatchPatternGroupElement *)seqElement->dmpsePtr;
9295 + MatchPatternDialog.currentDmptElement = NULL;
9296 + MatchPatternDialog.currentDmptGroup = group;
9298 + copyDialogPatternNamesFromGroup(
9299 + group,
9300 + &MatchPatternDialog.currentStringPatterns);
9302 + else
9304 + element = (DialogMatchPatternTableElement *)seqElement->dmpsePtr;
9305 + MatchPatternDialog.currentDmptElement = element;
9306 + MatchPatternDialog.currentDmptGroup = NULL;
9308 + RadioButtonChangeState(
9309 + MatchPatternDialog.gabSkipBtwStartEndW,
9310 + element->dmpteSkipBtwnStartEnd,
9311 + False);
9312 + RadioButtonChangeState(
9313 + MatchPatternDialog.gabFlashW,
9314 + element->dmpteFlash,
9315 + False);
9316 + RadioButtonChangeState(
9317 + MatchPatternDialog.gabSyntaxBasedW,
9318 + !element->dmpteIgnoreHighLightInfo,
9319 + False);
9321 + copyDialogStringPatternsFromTable(
9322 + element,
9323 + &MatchPatternDialog.currentStringPatterns);
9326 + setDialogType( !isGroup );
9328 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9332 +static void freeMatchPatternItemCB(void *item)
9334 + freeDialogSequenceElement((DialogMatchPatternSequenceElement *)item);
9338 +** Use "delete confirm" to delete matching pattern name from
9339 +** any group of this matching pattern set, in case of sub-pattern.
9340 +** Always confirm the delete.
9342 +static int deleteMatchPatternItemCB(int itemIndex, void *cbArg)
9344 + DialogMatchPatternSequenceElement *seqElement;
9346 + seqElement = MatchPatternDialog.mpdTable.dmpiSequence[itemIndex];
9348 + if (seqElement->dmpseType == MPT_SUB)
9350 + removeMatchPatternFromAllGroups( seqElement->dmpseName );
9353 + return True;
9356 +static void *getStringPatternDisplayedCB(void *oldItem, int explicitRequest, int *abort,
9357 + void *cbArg)
9359 + DialogStringPatternElement *newPat;
9360 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
9362 + /*
9363 + * If the string pattern frame is currently displaying the "new" entry and the
9364 + * fields are empty, that's just fine
9365 + */
9366 + if (oldItem == NULL && stringPatternFieldsEmpty(isRelatedToGroup))
9367 + return NULL;
9369 + /*
9370 + * If there are no problems reading the data, just return it
9371 + */
9372 + newPat = readStringPatternFrameFields(True);
9373 + if (newPat != NULL)
9374 + return (void *)newPat;
9376 + /*
9377 + * If there are problems, and the user didn't ask for the fields to be
9378 + * read, give more warning
9379 + */
9381 + if (!explicitRequest)
9383 + if (DialogF(
9384 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9385 + "Discard String Pattern Entry",
9386 + "Discard incomplete entry\nfor current string pattern?",
9387 + "Keep", "Discard") == 2)
9389 + return oldItem == NULL
9390 + ? NULL
9391 + : (void *)copyDialogStringPatternElement(
9392 + (DialogStringPatternElement *)oldItem);
9396 + /*
9397 + * read data again without "silent" mode to display warning
9398 + */
9399 + newPat = readStringPatternFrameFields(False);
9400 + *abort = True;
9402 + return NULL;
9405 +static void setStringPatternDisplayedCB(void *item, void *cbArg)
9407 + DialogStringPatternElement *element = (DialogStringPatternElement *)item;
9408 + PatternElementKind peKind;
9409 + PatternWordBoundary wordBoundary;
9410 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
9412 + if (item == NULL)
9414 + if (isRelatedToGroup)
9416 + updateSubPatternNameMenu(NULL, False);
9418 + else
9420 + XmTextSetString(MatchPatternDialog.mpdStringPatternW, "");
9422 + setSensitiveWordBoundaryBox( True );
9424 + RadioButtonChangeState(MatchPatternDialog.wbbBothW, True, True);
9426 + /*
9427 + * type of "new" string pattern:
9428 + * preset "start", if no string pattern exists at all;
9429 + * else select "end"
9430 + */
9431 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0)
9432 + RadioButtonChangeState(MatchPatternDialog.sptStartW, True, True);
9433 + else
9434 + RadioButtonChangeState(MatchPatternDialog.sptEndW, True, True);
9436 + RadioButtonChangeState(MatchPatternDialog.sabCaseSensitiveW, True, False);
9437 + RadioButtonChangeState(MatchPatternDialog.sabRegularExpressionW, False, False);
9440 + else
9442 + if (isRelatedToGroup)
9444 + updateSubPatternNameMenu(element->dspeText, False);
9446 + else
9448 + XmTextSetString(MatchPatternDialog.mpdStringPatternW, element->dspeText);
9450 + peKind = element->dspeKind;
9451 + wordBoundary = element->dspeWordBoundary;
9453 + if (peKind == PEK_START)
9454 + RadioButtonChangeState(MatchPatternDialog.sptStartW, True, True);
9455 + else if (peKind == PEK_MIDDLE)
9456 + RadioButtonChangeState(MatchPatternDialog.sptMiddleW, True, True);
9457 + else
9458 + RadioButtonChangeState(MatchPatternDialog.sptEndW, True, True);
9460 + if (wordBoundary == PWB_BOTH)
9461 + RadioButtonChangeState(MatchPatternDialog.wbbBothW, True, True);
9462 + else if (wordBoundary == PWB_LEFT)
9463 + RadioButtonChangeState(MatchPatternDialog.wbbLeftW, True, True);
9464 + else if (wordBoundary == PWB_RIGHT)
9465 + RadioButtonChangeState(MatchPatternDialog.wbbRightW, True, True);
9466 + else
9467 + RadioButtonChangeState(MatchPatternDialog.wbbNoneW, True, True);
9469 + RadioButtonChangeState(
9470 + MatchPatternDialog.sabCaseSensitiveW,
9471 + !element->dspeCaseInsensitive,
9472 + False);
9474 + RadioButtonChangeState(
9475 + MatchPatternDialog.sabRegularExpressionW,
9476 + element->dspeRegularExpression,
9477 + False);
9479 + setSensitiveWordBoundaryBox( !element->dspeRegularExpression );
9484 +static void freeStringPatternItemCB(void *item)
9486 + DialogStringPatternElement *patElement;
9488 + patElement = (DialogStringPatternElement *)item;
9490 + freeDialogStringPatternElement(patElement);
9493 +static void destroyCB(Widget w, XtPointer clientData, XtPointer callData)
9495 + freeVariableDialogData(DISCARD_LANGUAGE_MODE);
9497 + MatchPatternDialog.mpdShell = NULL;
9500 +static void okCB(Widget w, XtPointer clientData, XtPointer callData)
9502 + /*
9503 + * change the matching pattern
9504 + */
9505 + if (!getAndUpdateStringMatchTable())
9506 + return;
9508 + /*
9509 + * pop down and destroy the dialog
9510 + */
9511 + XtDestroyWidget(MatchPatternDialog.mpdShell);
9514 +static void applyCB(Widget w, XtPointer clientData, XtPointer callData)
9516 + /*
9517 + * change the matching pattern
9518 + */
9519 + getAndUpdateStringMatchTable();
9522 +static void checkCB(Widget w, XtPointer clientData, XtPointer callData)
9524 + StringMatchTable *newTable;
9525 + DMPTranslationResult translResult;
9527 + /*
9528 + * Get the current information displayed by the dialog.
9529 + * If a new table is available, then the test is passed successfully.
9530 + */
9531 + newTable = getDialogStringMatchTable(&translResult);
9533 + if (newTable != NULL)
9535 + DialogF(
9536 + DF_INF, MatchPatternDialog.mpdShell, 1,
9537 + "Matching Patterns Checked",
9538 + "Matching Patterns checked without error",
9539 + "OK");
9541 + freeStringMatchTable(newTable);
9545 +static void restoreCB(Widget w, XtPointer clientData, XtPointer callData)
9547 + StringMatchTable *defaultTable;
9549 + defaultTable = readDefaultStringMatchTable(MatchPatternDialog.mpdLangModeName);
9551 + if (defaultTable == NULL)
9553 + DialogF(
9554 + DF_WARN, MatchPatternDialog.mpdShell, 1,
9555 + "No Default Matching Pattern",
9556 + "There is no default matching pattern set\nfor language mode %s",
9557 + "OK",
9558 + MatchPatternDialog.mpdLangModeName);
9560 + return;
9563 + if (DialogF(
9564 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9565 + "Discard Changes",
9566 + "Are you sure you want to discard\n"
9567 + "all changes to matching patterns\n"
9568 + "for language mode %s?",
9569 + "Discard", "Cancel",
9570 + MatchPatternDialog.mpdLangModeName) == 2)
9572 + freeStringMatchTable(defaultTable);
9574 + return;
9577 + /*
9578 + * if a stored version of the matching pattern set exists, replace it.
9579 + * if it doesn't, add a new one.
9580 + */
9581 + updateStringMatchTable( defaultTable );
9583 + /*
9584 + * free the old dialog information
9585 + */
9586 + freeVariableDialogData(KEEP_LANGUAGE_MODE);
9588 + /*
9589 + * update the dialog
9590 + */
9591 + copyStringMatchTableForDialog( defaultTable, &MatchPatternDialog.mpdTable );
9593 + ChangeManagedListData(MatchPatternDialog.mpdMatchPatternNamesListW);
9594 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9597 +static void deleteCB(Widget w, XtPointer clientData, XtPointer callData)
9599 + if (DialogF(
9600 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9601 + "Delete Matching Patterns",
9602 + "Are you sure you want to delete\n"
9603 + "all matching patterns for\n"
9604 + "language mode %s?",
9605 + "Yes, Delete", "Cancel",
9606 + MatchPatternDialog.mpdLangModeName) == 2)
9608 + return;
9611 + /*
9612 + * if a stored version of the matching pattern exists, delete it from the list
9613 + */
9614 + DeleteStringMatchTable(MatchPatternDialog.mpdLangModeName);
9616 + /*
9617 + * free the old dialog information
9618 + */
9619 + freeVariableDialogData(KEEP_LANGUAGE_MODE);
9621 + /*
9622 + * clear out the dialog
9623 + */
9624 + ChangeManagedListData(MatchPatternDialog.mpdMatchPatternNamesListW);
9625 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9628 +static void closeCB(Widget w, XtPointer clientData, XtPointer callData)
9630 + /*
9631 + * pop down and destroy the dialog
9632 + */
9633 + XtDestroyWidget(MatchPatternDialog.mpdShell);
9636 +static void helpCB(Widget w, XtPointer clientData, XtPointer callData)
9639 + Help(HELP_MATCHING_PATTERNS);
9643 +static void strPatRegExpressionCB(Widget w, XtPointer clientData, XtPointer callData)
9645 + int regularExpression =
9646 + XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
9648 + setSensitiveWordBoundaryBox( !regularExpression );
9650 + if (regularExpression)
9651 + RadioButtonChangeState(MatchPatternDialog.sabCaseSensitiveW, True, False);
9654 +static void matchPatTypeCB(Widget w, XtPointer clientData, XtPointer callData)
9656 + if (MatchPatternDialog.currentDmptSeqElement != NULL)
9658 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW))
9660 + if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_SUB)
9662 + changeExistingSubPattern("Change to Context Group");
9665 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW) &&
9666 + MatchPatternDialog.currentDmptSeqElement->dmpseType != MPT_GROUP)
9668 + changeStringPatternToGroup();
9671 + else if (XmToggleButtonGetState(MatchPatternDialog.mptbIndividualW))
9673 + if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_SUB)
9675 + changeExistingSubPattern("Change to Individual Matching Pattern");
9677 + else if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_GROUP)
9679 + changeGroupToStringPattern("Change to Individual Matching Pattern");
9682 + else if (XmToggleButtonGetState(MatchPatternDialog.mptbSubPatternW))
9684 + if (MatchPatternDialog.currentDmptSeqElement->dmpseType == MPT_GROUP)
9686 + changeGroupToStringPattern("Change to Sub-Matching Pattern");
9691 + /*
9692 + * if context group button is (still) selected, then update labels etc.
9693 + */
9694 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW))
9696 + setDialogType(CONTEXT_GROUP_DIALOG);
9698 + else
9700 + setDialogType(STRING_PATTERN_DIALOG);
9703 + /*
9704 + * if a "new" entry is selected in matching patterns names list, then provide a
9705 + * list of all sub-pattern names
9706 + */
9707 + if (MatchPatternDialog.currentDmptSeqElement == NULL)
9709 + updateSubPatternNameMenu(NULL, True);
9713 +static void changeExistingSubPattern(
9714 + char *warnTitle)
9716 + DialogMatchPatternGroupElement *group;
9717 + int resp;
9719 + group =
9720 + getDialogGroupUsingMatchPattern(
9721 + MatchPatternDialog.currentDmptElement->dmpteName );
9723 + while ( group != NULL )
9725 + resp =
9726 + DialogF(
9727 + DF_WARN, MatchPatternDialog.mpdShell, 3,
9728 + warnTitle,
9729 + "Sub-pattern '%s' is used at least\n"
9730 + "by context group '%s'.\n\n"
9731 + "Remove this sub-pattern from this resp. all context group(s) ?",
9732 + "No, Keep", "Yes, Remove", "Yes, Remove All",
9733 + MatchPatternDialog.currentDmptElement->dmpteName,
9734 + group->dmpgeName);
9736 + if (resp == 1)
9738 + RadioButtonChangeState(MatchPatternDialog.mptbSubPatternW, True, True);
9740 + return;
9742 + else if (resp == 2)
9744 + removeMatchPatternFromGroup(
9745 + MatchPatternDialog.currentDmptElement->dmpteName,
9746 + group);
9748 + /*
9749 + * look for evtl. next context group holding this matching pattern
9750 + */
9751 + group =
9752 + getDialogGroupUsingMatchPattern(
9753 + MatchPatternDialog.currentDmptElement->dmpteName );
9755 + else
9757 + /*
9758 + * remove this matching pattern form all context groups
9759 + */
9760 + removeMatchPatternFromAllGroups(
9761 + MatchPatternDialog.currentDmptElement->dmpteName);
9763 + return;
9768 +static void changeStringPatternToGroup(void)
9770 + int resp;
9771 + int isSubPattern;
9773 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns != 0)
9775 + resp =
9776 + DialogF(
9777 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9778 + "Change to Context Group",
9779 + "All string patterns of '%s'\n"
9780 + "need to be discarded.\n\n"
9781 + "Discard related string patterns ?",
9782 + "No, Keep", "Yes, Discard",
9783 + MatchPatternDialog.currentDmptElement->dmpteName);
9785 + if (resp == 1)
9787 + isSubPattern = (MatchPatternDialog.currentDmptElement->dmpteType == MPT_SUB);
9789 + if (isSubPattern)
9790 + RadioButtonChangeState(MatchPatternDialog.mptbSubPatternW, True, True);
9791 + else
9792 + RadioButtonChangeState(MatchPatternDialog.mptbIndividualW, True, True);
9794 + return;
9797 + /*
9798 + * remove string patterns & update dialog fields
9799 + */
9800 + freeDialogStringPatterns(&MatchPatternDialog.currentStringPatterns);
9802 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9805 + /*
9806 + * invalidate this sub-/individual pattern
9807 + */
9808 + MatchPatternDialog.currentDmptSeqElement->dmpseValid = False;
9810 + /*
9811 + * update sub-pattern menu due to change to context group
9812 + */
9813 + updateSubPatternNameMenu(NULL, True);
9816 +static void changeGroupToStringPattern(
9817 + char *warnTitle)
9819 + int resp;
9821 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0)
9822 + return;
9824 + resp =
9825 + DialogF(
9826 + DF_WARN, MatchPatternDialog.mpdShell, 2,
9827 + warnTitle,
9828 + "Content of context group '%s'\n"
9829 + "needs to be discarded.\n\n"
9830 + "Discard content ?",
9831 + "No, Keep", "Yes, Discard",
9832 + MatchPatternDialog.currentDmptGroup->dmpgeName);
9834 + if (resp == 1)
9836 + RadioButtonChangeState(MatchPatternDialog.mptbContextGroupW, True, True);
9838 + else
9840 + /*
9841 + * remove string patterns & update dialog fields
9842 + */
9843 + freeDialogStringPatterns(&MatchPatternDialog.currentStringPatterns);
9845 + ChangeManagedListData(MatchPatternDialog.mpdStringPatternsListW);
9850 +** Create a pulldown menu pane with the names of the sub-patterns of
9851 +** the current matching pattern set.
9853 +static Widget createSubPatternNameMenu(
9854 + Widget parent,
9855 + char *currentSubPatName,
9856 + int allSubPatterns)
9858 + NameList nameList;
9859 + Widget menu;
9860 + int i;
9862 + setupSubPatternNameList(currentSubPatName, allSubPatterns, &nameList);
9864 + menu = CreatePulldownMenu(parent, "subPatternNames", NULL, 0);
9866 + for (i=0; i<nameList.nlNumber; i++)
9868 + createSubPatNameMenuEntry(menu, nameList.nlId[i]);
9871 + return menu;
9874 +static void setupSubPatternNameList(
9875 + char *currentSubPatName,
9876 + int allSubPatterns,
9877 + NameList *nameList)
9879 + int n = 0;
9880 + int i;
9881 + DialogMatchPatternSequenceElement *seq;
9882 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
9884 + if (isRelatedToGroup || allSubPatterns)
9886 + /*
9887 + * add "none selected" (default) item
9888 + */
9889 + nameList->nlId[n ++] = SPNM_NONE_SELECTED;
9891 + /*
9892 + * add one item for each (not assigned) sub-pattern name
9893 + */
9894 + for (i=0; i<MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i++)
9896 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
9898 + if (seq->dmpseType == MPT_SUB &&
9899 + seq->dmpseValid &&
9900 + (allSubPatterns ||
9901 + (!isSubPatternNameInCurStrPat(seq->dmpseName) ||
9902 + (currentSubPatName != NULL &&
9903 + (strcmp(seq->dmpseName, currentSubPatName) == 0))) ))
9905 + nameList->nlId[n ++] = seq->dmpseName;
9909 + else
9911 + nameList->nlId[n ++] = "none available ";
9914 + nameList->nlNumber = n;
9918 +** Create a menu entry with the names of one sub-pattern.
9919 +** XmNuserData of this item contains the sub-pattern name.
9921 +static void createSubPatNameMenuEntry(
9922 + Widget menu,
9923 + char *subPatName)
9925 + Widget btn;
9926 + XmString s1;
9928 + btn = XtVaCreateManagedWidget("subPattern", xmPushButtonGadgetClass,
9929 + menu,
9930 + XmNlabelString, s1=XmStringCreateSimple(subPatName),
9931 + XmNmarginHeight, 0,
9932 + XmNuserData, (void *)subPatName, NULL);
9933 + XmStringFree(s1);
9937 +** Set the sub-patterns menu to show a particular sub-pattern name
9939 +static void setSubPatternNameMenu(
9940 + const char *subPatName)
9942 + int i;
9943 + Cardinal nItems;
9944 + WidgetList items;
9945 + Widget pulldown, selectedItem;
9946 + char *itemName;
9948 + XtVaGetValues(MatchPatternDialog.mpdSubPatNamesOptMenu, XmNsubMenuId, &pulldown, NULL);
9949 + XtVaGetValues(pulldown, XmNchildren, &items, XmNnumChildren, &nItems, NULL);
9951 + if (nItems == 0)
9952 + return;
9954 + selectedItem = items[0];
9956 + /*
9957 + * if no subPatName is given, then select first item of option menu
9958 + */
9959 + if (subPatName != NULL)
9961 + for (i=0; i<(int)nItems; i++)
9963 + if (items[i] != NULL && !items[i]->core.being_destroyed)
9965 + XtVaGetValues(items[i], XmNuserData, &itemName, NULL);
9966 + if (!strcmp(itemName, subPatName))
9968 + selectedItem = items[i];
9969 + break;
9975 + XtVaSetValues(MatchPatternDialog.mpdSubPatNamesOptMenu, XmNmenuHistory, selectedItem, NULL);
9979 +** Update sub-pattern names menu, e.g. when a new sub-pattern is defined
9981 +static void updateSubPatternNameMenu(
9982 + char *currentSubPatName,
9983 + int allSubPatterns)
9985 + NameList nameList;
9986 + WidgetList items;
9987 + Cardinal nItems;
9988 + int n;
9989 + XmString st1;
9991 + setupSubPatternNameList(currentSubPatName, allSubPatterns, &nameList);
9993 + /*
9994 + * Go thru all of the items in the sub-pattern names menu
9995 + * and rename them to match the current sub-patterns.
9996 + * Delete any extras.
9997 + */
9998 + XtVaGetValues(
9999 + MatchPatternDialog.mpdSubPatNamesPulldown,
10000 + XmNchildren, &items,
10001 + XmNnumChildren, &nItems,
10002 + NULL);
10004 + for (n=0; n<(int)nItems; n++)
10006 + if (n >= nameList.nlNumber)
10008 + /*
10009 + * unmanaging before destroying stops parent from displaying
10010 + */
10011 + XtUnmanageChild(items[n]);
10012 + XtDestroyWidget(items[n]);
10014 + else
10016 + if (items[n] == NULL || items[n]->core.being_destroyed)
10018 + /*
10019 + * create a new entry (widget) if this one is not existing or
10020 + * if it is marked as to be destroyed
10021 + */
10022 + createSubPatNameMenuEntry(
10023 + MatchPatternDialog.mpdSubPatNamesPulldown, nameList.nlId[n]);
10025 + else
10027 + XtVaSetValues(
10028 + items[n],
10029 + XmNlabelString, st1=XmStringCreateSimple(nameList.nlId[n]),
10030 + XmNuserData, (void *)nameList.nlId[n],
10031 + NULL);
10033 + XmStringFree(st1);
10038 + /*
10039 + * add new items for remaining sub-patterns names
10040 + */
10041 + for (n=(int)nItems; n<nameList.nlNumber; n++)
10043 + createSubPatNameMenuEntry(
10044 + MatchPatternDialog.mpdSubPatNamesPulldown, nameList.nlId[n]);
10047 + /*
10048 + * select entry shown in sub-pattern name option menu
10049 + */
10050 + setSubPatternNameMenu(currentSubPatName);
10053 +static char *getSelectedSubPatternName(void)
10055 + Widget selectedItem;
10056 + char *itemName;
10058 + XtVaGetValues(MatchPatternDialog.mpdSubPatNamesOptMenu, XmNmenuHistory, &selectedItem, NULL);
10059 + XtVaGetValues(selectedItem, XmNuserData, &itemName, NULL);
10061 + return itemName;
10064 +static int isSubPatternNameInCurStrPat(
10065 + char *subPatName)
10067 + int i;
10068 + DialogStringPatterns *curPatNames = &MatchPatternDialog.currentStringPatterns;
10070 + for (i=0; i<curPatNames->dspNumberOfPatterns; i++)
10072 + if (strcmp(curPatNames->dspElements[i]->dspeText, subPatName) == 0)
10073 + return True;
10076 + return False;
10080 +** Read the matching pattern fields of the matching pattern dialog and produce an
10081 +** allocated DialogMatchPatternSequenceElement structure reflecting the contents.
10082 +** Pop up dialogs telling the user what's wrong (Passing "silent" as True,
10083 +** suppresses these dialogs).
10084 +** Returns NULL on error.
10086 +static DialogMatchPatternSequenceElement *readMatchPatternFields(int silent)
10088 + int isGroup;
10089 + char *name;
10090 + char *nameLabel;
10091 + char *nameTitle;
10092 + char *contentTitle;
10093 + char *contentWarningText;
10094 + DialogMatchPatternSequenceElement *newSeq;
10095 + DialogMatchPatternTableElement *newElement;
10096 + DialogMatchPatternGroupElement *newGroup;
10098 + if (XmToggleButtonGetState(MatchPatternDialog.mptbContextGroupW))
10100 + nameLabel = "context group name";
10101 + nameTitle = "Context Group Name";
10102 + contentTitle = "Context Group Content";
10103 + contentWarningText = "Please assign min. 1\nsub-pattern";
10104 + isGroup = True;
10106 + else
10108 + nameLabel = "matching pattern name";
10109 + nameTitle = "Matching Pattern Name";
10110 + contentTitle = "Matching Pattern Content";
10111 + contentWarningText = "Please specify min. 1\nstring pattern";
10112 + isGroup = False;
10115 + name =
10116 + ReadSymbolicFieldTextWidget(
10117 + MatchPatternDialog.mpdMatchPatternNameW,
10118 + nameLabel,
10119 + silent);
10121 + if (name == NULL)
10123 + return NULL;
10125 + else if (*name == '\0')
10127 + if (!silent)
10129 + DialogF(
10130 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10131 + nameTitle,
10132 + "Please specify a valid name",
10133 + "OK");
10134 + XmProcessTraversal(MatchPatternDialog.mpdMatchPatternNameW, XmTRAVERSE_CURRENT);
10136 + XtFree(name);
10137 + return NULL;
10140 + if (MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0)
10142 + if (!silent)
10144 + DialogF(
10145 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10146 + contentTitle,
10147 + contentWarningText,
10148 + "OK");
10150 + XtFree(name);
10151 + return NULL;
10153 + else
10155 + if (!isGroup &&
10156 + !isStartPatternElementAvailable(&MatchPatternDialog.currentStringPatterns))
10158 + if (!silent)
10160 + DialogF(
10161 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10162 + contentTitle,
10163 + "Please specify min. 1 string pattern\nof type 'start'",
10164 + "OK");
10166 + XtFree(name);
10167 + return NULL;
10171 + if (MatchPatternDialog.currentDmptElement != NULL &&
10172 + MatchPatternDialog.currentDmptElement->dmpteType == MPT_SUB &&
10173 + strcmp(MatchPatternDialog.currentDmptElement->dmpteName, name) != 0)
10175 + renameMatchPatternInAllGroups(
10176 + MatchPatternDialog.currentDmptElement->dmpteName,
10177 + name);
10180 + newSeq =
10181 + (DialogMatchPatternSequenceElement *)XtMalloc(sizeof(DialogMatchPatternSequenceElement));
10183 + newSeq->dmpseName = name;
10184 + newSeq->dmpseValid = True;
10186 + if (isGroup)
10188 + newSeq->dmpseType = MPT_GROUP;
10190 + newGroup =
10191 + (DialogMatchPatternGroupElement *)XtMalloc(sizeof(DialogMatchPatternGroupElement));
10193 + newGroup->dmpgeName = XtNewString(name);
10195 + copyDialogPatternNamesToGroup(
10196 + &MatchPatternDialog.currentStringPatterns,
10197 + newGroup);
10199 + newSeq->dmpsePtr = (void *)newGroup;
10201 + else
10203 + if (XmToggleButtonGetState(MatchPatternDialog.mptbIndividualW))
10204 + newSeq->dmpseType = MPT_INDIVIDUAL;
10205 + else
10206 + newSeq->dmpseType = MPT_SUB;
10208 + newElement =
10209 + (DialogMatchPatternTableElement *)XtMalloc(sizeof(DialogMatchPatternTableElement));
10211 + newElement->dmpteName = XtNewString(name);
10212 + newElement->dmpteType = newSeq->dmpseType;
10214 + newElement->dmpteSkipBtwnStartEnd =
10215 + XmToggleButtonGetState(MatchPatternDialog.gabSkipBtwStartEndW);
10217 + newElement->dmpteFlash =
10218 + XmToggleButtonGetState(MatchPatternDialog.gabFlashW);
10220 + newElement->dmpteIgnoreHighLightInfo =
10221 + !XmToggleButtonGetState(MatchPatternDialog.gabSyntaxBasedW);
10223 + copyDialogStringPatterns(
10224 + &MatchPatternDialog.currentStringPatterns,
10225 + &newElement->dmptePatterns);
10227 + newSeq->dmpsePtr = (void *)newElement;
10230 + return newSeq;
10234 +** Check, if min. 1 string pattern of type 'start' is
10235 +** available within dialog.
10236 +** Returns True, if min. 1 start string pattern is
10237 +** populated in dialog.
10239 +static int isStartPatternElementAvailable(
10240 + DialogStringPatterns *dialogPatterns)
10242 + int i;
10244 + for (i=0; i < dialogPatterns->dspNumberOfPatterns; i++)
10246 + if (dialogPatterns->dspElements[i]->dspeKind == PEK_START)
10247 + return True;
10250 + return False;
10254 +** Read the string pattern fields of the string pattern frame and produce an
10255 +** allocated DialogStringPatternElement structure reflecting the contents.
10256 +** Pop up dialogs telling the user what's wrong (Passing "silent" as True,
10257 +** suppresses these dialogs).
10258 +** Returns NULL on error.
10260 +static DialogStringPatternElement *readStringPatternFrameFields(int silent)
10262 + char *stringPatText;
10263 + DialogStringPatternElement *newPatElement;
10264 + int isRelatedToGroup = !MatchPatternDialog.mpdStringPatternIsDisplayed;
10266 + if (isRelatedToGroup)
10268 + stringPatText = getSelectedSubPatternName();
10269 + if (strcmp(stringPatText, SPNM_NONE_SELECTED) == 0)
10271 + return NULL;
10274 + stringPatText = XtNewString(stringPatText);
10276 + else
10278 + stringPatText =
10279 + XmTextGetString(MatchPatternDialog.mpdStringPatternW);
10281 + if (stringPatText == NULL)
10283 + return NULL;
10285 + else if (*stringPatText == '\0')
10287 + if (!silent)
10289 + DialogF(
10290 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10291 + "String Pattern",
10292 + "Please specify string\npattern content",
10293 + "OK");
10294 + XmProcessTraversal(MatchPatternDialog.mpdStringPatternW, XmTRAVERSE_CURRENT);
10296 + XtFree(stringPatText);
10297 + return NULL;
10301 + newPatElement = (DialogStringPatternElement *)XtMalloc(sizeof(DialogStringPatternElement));
10303 + newPatElement->dspeText = stringPatText;
10305 + if (isRelatedToGroup)
10307 + newPatElement->dspeKind = PEK_START;
10308 + newPatElement->dspeWordBoundary = PWB_NONE;
10309 + newPatElement->dspeCaseInsensitive = False;
10310 + newPatElement->dspeRegularExpression = False;
10312 + else
10314 + newPatElement->dspeRegularExpression =
10315 + XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
10317 + if (XmToggleButtonGetState(MatchPatternDialog.sptStartW))
10318 + newPatElement->dspeKind = PEK_START;
10319 + else if (XmToggleButtonGetState(MatchPatternDialog.sptMiddleW))
10320 + newPatElement->dspeKind = PEK_MIDDLE;
10321 + else
10322 + newPatElement->dspeKind = PEK_END;
10324 + if (newPatElement->dspeRegularExpression)
10325 + newPatElement->dspeWordBoundary = PWB_NONE;
10326 + else if (XmToggleButtonGetState(MatchPatternDialog.wbbBothW))
10327 + newPatElement->dspeWordBoundary = PWB_BOTH;
10328 + else if (XmToggleButtonGetState(MatchPatternDialog.wbbLeftW))
10329 + newPatElement->dspeWordBoundary = PWB_LEFT;
10330 + else if (XmToggleButtonGetState(MatchPatternDialog.wbbRightW))
10331 + newPatElement->dspeWordBoundary = PWB_RIGHT;
10332 + else
10333 + newPatElement->dspeWordBoundary = PWB_NONE;
10335 + newPatElement->dspeCaseInsensitive =
10336 + !XmToggleButtonGetState(MatchPatternDialog.sabCaseSensitiveW);
10339 + return newPatElement;
10343 +** Returns true if the pattern fields of the matching pattern dialog are set to
10344 +** the default ("New" pattern) state.
10346 +static int matchPatternDialogEmpty(void)
10348 + return
10349 + TextWidgetIsBlank(MatchPatternDialog.mpdMatchPatternNameW) &&
10350 + XmToggleButtonGetState(MatchPatternDialog.mptbIndividualW) &&
10351 + XmToggleButtonGetState(MatchPatternDialog.gabFlashW) &&
10352 + XmToggleButtonGetState(MatchPatternDialog.gabSyntaxBasedW) &&
10353 + stringPatternFrameEmpty();
10357 +** Returns true if the string pattern frame of the matching pattern dialog is set to
10358 +** the default state.
10360 +static int stringPatternFrameEmpty(void)
10362 + return
10363 + stringPatternFieldsEmpty(False) &&
10364 + MatchPatternDialog.currentStringPatterns.dspNumberOfPatterns == 0;
10368 +** Returns true if the string pattern fields of the string pattern frame are set to
10369 +** the default state.
10371 +static int stringPatternFieldsEmpty(
10372 + int strPatIsRelatedToGroup)
10374 + if (strPatIsRelatedToGroup)
10376 + return(
10377 + strcmp( getSelectedSubPatternName(), SPNM_NONE_SELECTED ) == 0);
10379 + else
10381 + return
10382 + TextWidgetIsBlank(MatchPatternDialog.mpdStringPatternW) &&
10383 + XmToggleButtonGetState(MatchPatternDialog.wbbBothW) &&
10384 + XmToggleButtonGetState(MatchPatternDialog.sabCaseSensitiveW) &&
10385 + !XmToggleButtonGetState(MatchPatternDialog.sabRegularExpressionW);
10390 +** Get the current content of the matching pattern dialog.
10391 +** If the matching pattern is o.k., then update & apply it
10392 +** to any window which is currently using the matching pattern.
10393 +** If it's bad, then only report it.
10395 +static int getAndUpdateStringMatchTable(void)
10397 + StringMatchTable *newTable;
10398 + DMPTranslationResult translResult;
10400 + /*
10401 + * Get the current information displayed by the dialog. If it's bad,
10402 + * report it to the user & return.
10403 + */
10404 + newTable = getDialogStringMatchTable(&translResult);
10406 + if (newTable == NULL && translResult != DMPTR_EMPTY)
10408 + DialogF(
10409 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10410 + "Incomplete Matching Patterns for Language Mode",
10411 + "Incomplete matching patterns for language mode '%s'.\n"
10412 + "Please complete them first",
10413 + "OK",
10414 + MatchPatternDialog.mpdLangModeName);
10416 + return False;
10419 + /*
10420 + * change the matching pattern
10421 + */
10422 + updateStringMatchTable( newTable );
10424 + return True;
10428 +** Update the matching pattern set being edited in the matching pattern dialog
10429 +** with the information that the dialog is currently displaying, and
10430 +** apply changes to any window which is currently using the matching pattern.
10432 +static void updateStringMatchTable(
10433 + StringMatchTable *newTable)
10435 + WindowInfo *window;
10436 + int i;
10438 + /*
10439 + * Find the matching pattern being modified
10440 + */
10441 + for (i=0; i<NbrMatchTables; i++)
10443 + if (!strcmp(MatchPatternDialog.mpdLangModeName, MatchTables[i]->smtLanguageMode))
10445 + /*
10446 + * replace existing matching pattern
10447 + */
10448 + freeStringMatchTable(MatchTables[i]);
10449 + MatchTables[i] = newTable;
10450 + break;
10454 + if (i == NbrMatchTables)
10456 + /*
10457 + * new match table for language mode -> add it to end
10458 + */
10459 + MatchTables[NbrMatchTables++] = newTable;
10462 + /*
10463 + * Find windows that are currently using this matching pattern set and
10464 + * update this windows
10465 + */
10466 + for (window=WindowList; window!=NULL; window=window->next)
10468 + if ((window->languageMode == PLAIN_LANGUAGE_MODE &&
10469 + !strcmp(PLAIN_LM_STRING, newTable->smtLanguageMode)) ||
10470 + (window->languageMode != PLAIN_LANGUAGE_MODE &&
10471 + !strcmp(LanguageModeName(window->languageMode), newTable->smtLanguageMode)))
10473 + window->stringMatchTable = newTable;
10477 + /*
10478 + * Note that preferences have been changed
10479 + */
10480 + MarkPrefsChanged();
10483 +static StringMatchTable *getDialogStringMatchTable(
10484 + DMPTranslationResult *result)
10486 + int matchPatListIdx =
10487 + ManagedListSelectedIndex(MatchPatternDialog.mpdMatchPatternNamesListW);
10488 + int stringPatListIdx =
10489 + ManagedListSelectedIndex(MatchPatternDialog.mpdStringPatternsListW);
10491 + /*
10492 + * Get the current content of the matching pattern dialog fields
10493 + */
10494 + if (!UpdateManagedList(MatchPatternDialog.mpdStringPatternsListW, True))
10496 + *result = DMPTR_INCOMPLETE;
10498 + return NULL;
10501 + if (!UpdateManagedList(MatchPatternDialog.mpdMatchPatternNamesListW, True))
10503 + *result = DMPTR_INCOMPLETE;
10505 + return NULL;
10508 + SelectManagedListItem(MatchPatternDialog.mpdMatchPatternNamesListW, matchPatListIdx);
10509 + SelectManagedListItem(MatchPatternDialog.mpdStringPatternsListW, stringPatListIdx);
10511 + /*
10512 + * Translate dialog match table to string match table
10513 + */
10514 + return translateDialogStringMatchTable(&MatchPatternDialog.mpdTable, result);
10517 +static StringMatchTable *translateDialogStringMatchTable(
10518 + DialogMatchPatternInfo *dialogTable,
10519 + DMPTranslationResult *result)
10521 + ReadMatchPatternInfo readPatInfo;
10522 + DialogMatchPatternSequenceElement *seq;
10523 + MatchPatternTableElement *newPatElement;
10524 + MatchPatternGroupElement *newGroupElement;
10525 + char *errMsg;
10526 + ErrorInfo errInfo;
10527 + int i;
10529 + initErrorInfo(&errInfo);
10531 + readPatInfo.rmpiNbrOfElements = 0;
10532 + readPatInfo.rmpiNbrOfGroups = 0;
10533 + readPatInfo.rmpiNbrOfSeqElements = 0;
10534 + readPatInfo.rmpiAllPatRE = NULL;
10535 + readPatInfo.rmpiFlashPatRE = NULL;
10537 + /*
10538 + * if no dialog patterns are defined, return "empty" table
10539 + */
10540 + if (dialogTable->dmpiNbrOfSeqElements == 0)
10542 + *result = DMPTR_EMPTY;
10544 + return createStringMatchTable(
10545 + &readPatInfo,
10546 + XtNewString(MatchPatternDialog.mpdLangModeName));
10549 + /*
10550 + * translate dialog matching pattern elements
10551 + */
10552 + for (i=0; i < dialogTable->dmpiNbrOfSeqElements; i++)
10554 + seq = dialogTable->dmpiSequence[i];
10556 + if (seq->dmpseType == MPT_GROUP)
10558 + newGroupElement =
10559 + translateDialogMatchPatternGroupElement(
10560 + &readPatInfo,
10561 + (DialogMatchPatternGroupElement *)seq->dmpsePtr);
10563 + if (newGroupElement == NULL)
10565 + freeReadMatchPatternInfo(&readPatInfo);
10567 + *result = DMPTR_INCOMPLETE;
10569 + return NULL;
10572 + readPatInfo.rmpiGroup[readPatInfo.rmpiNbrOfGroups ++] =
10573 + newGroupElement;
10575 + recordPatternSequence(
10576 + &readPatInfo,
10577 + seq->dmpseName,
10578 + seq->dmpseType,
10579 + readPatInfo.rmpiNbrOfGroups-1 );
10581 + else
10583 + newPatElement =
10584 + translateDialogMatchPatternTableElement(
10585 + (DialogMatchPatternTableElement *)seq->dmpsePtr);
10587 + newPatElement->mpteIndex = readPatInfo.rmpiNbrOfElements;
10589 + readPatInfo.rmpiElement[readPatInfo.rmpiNbrOfElements ++] =
10590 + newPatElement;
10592 + if (newPatElement->mpteType == MPT_INDIVIDUAL)
10594 + if (!assignIndividualGroup(&readPatInfo, &errMsg, newPatElement))
10596 + DialogF(
10597 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10598 + "Assign reg. exp.",
10599 + "%s\n(Pattern: '%s')",
10600 + "OK",
10601 + errMsg,
10602 + newPatElement->mpteName);
10604 + freeReadMatchPatternInfo(&readPatInfo);
10606 + *result = DMPTR_INCOMPLETE;
10608 + return NULL;
10612 + treatDuplicatedMTEntries(readPatInfo.rmpiElement, readPatInfo.rmpiNbrOfElements);
10614 + recordPatternSequence(
10615 + &readPatInfo,
10616 + seq->dmpseName,
10617 + seq->dmpseType,
10618 + newPatElement->mpteIndex );
10622 + /*
10623 + * compile reg. expressions of "read" patterns
10624 + */
10625 + if (createRegExpOfPatterns( &readPatInfo, &errInfo ))
10627 + errInfo.eiLanguageMode = XtNewString(MatchPatternDialog.mpdLangModeName);
10628 + dialogMatchingPatternSetError(
10629 + "Assign all patterns reg. exp.",
10630 + &errInfo);
10632 + freeReadMatchPatternInfo(&readPatInfo);
10634 + *result = DMPTR_INCOMPLETE;
10636 + return NULL;
10639 + *result = DMPTR_OK;
10641 + return createStringMatchTable(
10642 + &readPatInfo,
10643 + XtNewString(MatchPatternDialog.mpdLangModeName));
10646 +static MatchPatternTableElement *translateDialogMatchPatternTableElement(
10647 + DialogMatchPatternTableElement *dialogElement)
10649 + MatchPatternTableElement *newElement;
10651 + newElement =
10652 + (MatchPatternTableElement *)XtMalloc(sizeof(MatchPatternTableElement));
10654 + newElement->mpteName = XtNewString(dialogElement->dmpteName);
10655 + newElement->mpteIndex = NO_ELEMENT_IDX;
10656 + newElement->mpteType = dialogElement->dmpteType;
10657 + newElement->mpteGroup = NO_GROUP_IDX;
10659 + translateDialogPatterns(&dialogElement->dmptePatterns, newElement);
10661 + newElement->mpteSkipBtwnStartEnd = dialogElement->dmpteSkipBtwnStartEnd;
10662 + newElement->mpteFlash = dialogElement->dmpteFlash;
10663 + newElement->mpteIgnoreHighLightInfo = dialogElement->dmpteIgnoreHighLightInfo;
10664 + newElement->mpteStartEndRE = NULL;
10666 + initGlobalBackRefList( newElement->mpteGlobalBackRef );
10668 + return newElement;
10671 +static void translateDialogPatterns(
10672 + DialogStringPatterns *dialogPatterns,
10673 + MatchPatternTableElement *newElement)
10675 + int sizeOfPat;
10676 + int i;
10678 + /*
10679 + * allocate memory for patterns
10680 + */
10681 + newElement->mpteAll.pesNumberOfPattern = dialogPatterns->dspNumberOfPatterns;
10683 + sizeOfPat =
10684 + sizeof(PatternElement *) * dialogPatterns->dspNumberOfPatterns;
10686 + newElement->mpteAll.pesPattern = (PatternElement **)XtMalloc(sizeOfPat);
10688 + /*
10689 + * assign dialog patterns to patterns of MatchPatternTableElement
10690 + */
10691 + for (i=0; i < dialogPatterns->dspNumberOfPatterns; i++)
10693 + newElement->mpteAll.pesPattern[i] =
10694 + createPatternElement(
10695 + XtNewString(dialogPatterns->dspElements[i]->dspeText),
10696 + dialogPatterns->dspElements[i]->dspeKind,
10697 + dialogPatterns->dspElements[i]->dspeWordBoundary,
10698 + dialogPatterns->dspElements[i]->dspeCaseInsensitive,
10699 + dialogPatterns->dspElements[i]->dspeRegularExpression);
10701 + newElement->mpteAll.pesPattern[i]->peIndex = i;
10704 + /*
10705 + * sort pattern elements into start, middle & end arrays
10706 + */
10707 + sortDialogPatternElementSet( &newElement->mpteAll, newElement );
10709 + /*
10710 + * determine mono pattern
10711 + */
10712 + if (newElement->mpteEnd.pesNumberOfPattern == 0)
10714 + newElement->mpteIsMonoPattern = True;
10716 + copyPatternSet( &newElement->mpteStart, &newElement->mpteEnd );
10718 + else
10720 + newElement->mpteIsMonoPattern = False;
10725 + * Sort dialog pattern element set into start, middle & end arrays.
10726 + */
10727 +static void sortDialogPatternElementSet(
10728 + PatternElementSet *allPat,
10729 + MatchPatternTableElement *result)
10731 + int sizeOfPat;
10733 + /*
10734 + * count number of start, middle & end pattern elements
10735 + */
10736 + countPatternElementKind( allPat, result );
10738 + /*
10739 + * allocate pattern elements
10740 + */
10741 + sizeOfPat = sizeof(PatternElement *) * result->mpteStart.pesNumberOfPattern;
10742 + result->mpteStart.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
10744 + if (result->mpteMiddle.pesNumberOfPattern != 0)
10746 + sizeOfPat = sizeof(PatternElement *) * result->mpteMiddle.pesNumberOfPattern;
10747 + result->mpteMiddle.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
10750 + if (result->mpteEnd.pesNumberOfPattern != 0)
10752 + sizeOfPat = sizeof(PatternElement *) * result->mpteEnd.pesNumberOfPattern;
10753 + result->mpteEnd.pesPattern = (PatternElement **)XtMalloc( sizeOfPat );
10756 + /*
10757 + * sort pattern elements into start, middle & end arrays
10758 + */
10759 + sortPatternElementSet( allPat, result );
10762 +static MatchPatternGroupElement *translateDialogMatchPatternGroupElement(
10763 + ReadMatchPatternInfo *info,
10764 + DialogMatchPatternGroupElement *dialogGroup)
10766 + int i;
10767 + int error = False;
10768 + MatchPatternTableElement *subPatElement;
10769 + int sizeOfIds;
10770 + MatchPatternGroupElement *group;
10772 + /*
10773 + * Allocate memory for the matching pattern group. Copy name & number of
10774 + * sub patterns.
10775 + */
10776 + group =
10777 + (MatchPatternGroupElement *)XtMalloc( sizeof(MatchPatternGroupElement) );
10779 + group->mpgeName = XtNewString(dialogGroup->dmpgeName);
10780 + group->mpgeNumberOfSubPatterns = dialogGroup->dmpgeNumberOfSubPatterns;
10781 + group->mpgeKeywordRE = NULL;
10783 + /*
10784 + * Allocate memory for the sub-matching pattern IDs
10785 + */
10786 + sizeOfIds = sizeof(char *) * group->mpgeNumberOfSubPatterns;
10787 + group->mpgeSubPatternIds = (char **)XtMalloc( sizeOfIds );
10789 + for (i=0; i < group->mpgeNumberOfSubPatterns; i ++)
10791 + /*
10792 + * Remember sub-matching pattern ID
10793 + */
10794 + group->mpgeSubPatternIds[i] = XtNewString(dialogGroup->dmpgeSubPatternIds[i]);
10796 + /*
10797 + * Assign the index of this group to the sub-matching pattern
10798 + * if no group index was assigned before.
10799 + */
10800 + subPatElement =
10801 + getPatternOfName( info, dialogGroup->dmpgeSubPatternIds[i]);
10803 + if (subPatElement == NULL)
10805 + DialogF(
10806 + DF_WARN, MatchPatternDialog.mpdShell, 1,
10807 + "Group Compilation",
10808 + "Group '%s':\nsub-matching pattern '%s' not defined before",
10809 + "OK",
10810 + group->mpgeName,
10811 + dialogGroup->dmpgeSubPatternIds[i]);
10813 + error = True;
10815 + else
10817 + if (subPatElement->mpteGroup == NO_GROUP_IDX)
10819 + subPatElement->mpteGroup = info->rmpiNbrOfGroups;
10824 + if (error)
10826 + freeMatchPatternGroupElement(group);
10828 + return NULL;
10831 + return group;
10834 +static int stringMatchTableDiffer(
10835 + StringMatchTable *oldTable,
10836 + StringMatchTable *newTable)
10838 + int i, j;
10839 + MatchPatternTable *oldPatTab = oldTable->smtAllPatterns;
10840 + MatchPatternTable *newPatTab = newTable->smtAllPatterns;
10841 + MatchPatternTableElement *oldPat;
10842 + MatchPatternTableElement *newPat;
10843 + MatchPatternGroupElement *oldGroup;
10844 + MatchPatternGroupElement *newGroup;
10845 + MatchPatternSequenceElement *oldSeq;
10846 + MatchPatternSequenceElement *newSeq;
10848 + if (oldTable->smtNumberOfSeqElements != newTable->smtNumberOfSeqElements)
10849 + return True;
10851 + for (i=0; i < oldTable->smtNumberOfSeqElements; i++)
10853 + oldSeq = oldTable->smtSequence[i];
10854 + newSeq = newTable->smtSequence[i];
10856 + if (AllocatedStringsDiffer(oldSeq->mpseName, newSeq->mpseName))
10857 + return True;
10858 + if (oldSeq->mpseType != newSeq->mpseType)
10859 + return True;
10861 + if (oldSeq->mpseType == MPT_GROUP)
10863 + oldGroup = oldTable->smtGroups[oldSeq->mpseIndex];
10864 + newGroup = newTable->smtGroups[newSeq->mpseIndex];
10866 + if (AllocatedStringsDiffer(oldGroup->mpgeName, newGroup->mpgeName))
10867 + return True;
10869 + if (oldGroup->mpgeNumberOfSubPatterns != newGroup->mpgeNumberOfSubPatterns)
10870 + return True;
10872 + for (j=0; j < oldGroup->mpgeNumberOfSubPatterns; j++)
10874 + if (AllocatedStringsDiffer(
10875 + oldGroup->mpgeSubPatternIds[j],
10876 + newGroup->mpgeSubPatternIds[j]))
10877 + return True;
10880 + else
10882 + oldPat = oldPatTab->mptElements[oldSeq->mpseIndex];
10883 + newPat = newPatTab->mptElements[newSeq->mpseIndex];
10885 + if (AllocatedStringsDiffer(oldPat->mpteName, newPat->mpteName))
10886 + return True;
10888 + if (oldPat->mpteType != newPat->mpteType)
10889 + return True;
10891 + if (oldPat->mpteGroup != newPat->mpteGroup)
10892 + return True;
10894 + if (oldPat->mpteAll.pesNumberOfPattern != newPat->mpteAll.pesNumberOfPattern)
10895 + return True;
10897 + for (j=0; j < oldPat->mpteAll.pesNumberOfPattern; j ++)
10899 + if (patternElementDiffer(
10900 + oldPat->mpteAll.pesPattern[j], oldPatTab,
10901 + newPat->mpteAll.pesPattern[j], newPatTab ) )
10902 + return True;
10905 + if (oldPat->mpteIsMonoPattern != newPat->mpteIsMonoPattern)
10906 + return True;
10908 + if (oldPat->mpteSkipBtwnStartEnd != newPat->mpteSkipBtwnStartEnd)
10909 + return True;
10911 + if (oldPat->mpteIgnoreHighLightInfo != newPat->mpteIgnoreHighLightInfo)
10912 + return True;
10914 + if (oldPat->mpteFlash != newPat->mpteFlash)
10915 + return True;
10919 + return False;
10922 +static int patternElementDiffer(
10923 + PatternElement *oldPE,
10924 + MatchPatternTable *oldTab,
10925 + PatternElement *newPE,
10926 + MatchPatternTable *newTab)
10928 + StringPattern *oldSP;
10929 + StringPattern *newSP;
10931 + oldSP = GetStringPattern(oldTab, oldPE);
10932 + newSP = GetStringPattern(newTab, newPE);
10934 + if (AllocatedStringsDiffer(oldSP->spText, newSP->spText))
10935 + return True;
10936 + if (AllocatedStringsDiffer(oldSP->spOrigText, newSP->spOrigText))
10937 + return True;
10938 + if (oldPE->peKind != newPE->peKind)
10939 + return True;
10940 + if (oldSP->spWordBoundary != newSP->spWordBoundary)
10941 + return True;
10942 + if (oldSP->spCaseInsensitive != newSP->spCaseInsensitive)
10943 + return True;
10944 + if (oldSP->spRegularExpression != newSP->spRegularExpression)
10945 + return True;
10947 + return False;
10950 +static DialogMatchPatternGroupElement *getDialogGroupUsingMatchPattern(
10951 + char *matchPatternName)
10953 + DialogMatchPatternSequenceElement *seq;
10954 + DialogMatchPatternGroupElement *group;
10955 + int i, j;
10957 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
10959 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
10961 + if (seq->dmpseType == MPT_GROUP)
10963 + group = (DialogMatchPatternGroupElement *)seq->dmpsePtr;
10965 + for (j=0; j < group->dmpgeNumberOfSubPatterns; j ++)
10967 + if (strcmp(group->dmpgeSubPatternIds[j], matchPatternName) == 0)
10968 + return group;
10973 + return NULL;
10976 +static void removeMatchPatternFromGroup(
10977 + char *matchPatternName,
10978 + DialogMatchPatternGroupElement *group)
10980 + int i;
10982 + for (i=0; i < group->dmpgeNumberOfSubPatterns; i ++)
10984 + if (strcmp(group->dmpgeSubPatternIds[i], matchPatternName) == 0)
10986 + /*
10987 + * remove existing matching pattern name from sub-pattern list
10988 + */
10989 + freeXtPtr((void **)&group->dmpgeSubPatternIds[i]);
10990 + memmove(
10991 + &group->dmpgeSubPatternIds[i],
10992 + &group->dmpgeSubPatternIds[i+1],
10993 + (group->dmpgeNumberOfSubPatterns-1 - i) * sizeof(char *));
10994 + group->dmpgeNumberOfSubPatterns --;
10996 + return;
11001 +static void removeMatchPatternFromAllGroups(
11002 + char *matchPatternName)
11004 + DialogMatchPatternSequenceElement *seq;
11005 + DialogMatchPatternGroupElement *group;
11006 + int i;
11008 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
11010 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
11012 + if (seq->dmpseType == MPT_GROUP)
11014 + group = (DialogMatchPatternGroupElement *)seq->dmpsePtr;
11016 + removeMatchPatternFromGroup(matchPatternName, group);
11021 +static void renameMatchPatternInGroup(
11022 + char *oldMatchPatternName,
11023 + char *newMatchPatternName,
11024 + DialogMatchPatternGroupElement *group)
11026 + int i;
11028 + for (i=0; i < group->dmpgeNumberOfSubPatterns; i ++)
11030 + if (strcmp(group->dmpgeSubPatternIds[i], oldMatchPatternName) == 0)
11032 + /*
11033 + * rename existing matching pattern name in sub-pattern list
11034 + */
11035 + freeXtPtr((void **)&group->dmpgeSubPatternIds[i]);
11037 + group->dmpgeSubPatternIds[i] =
11038 + XtNewString(newMatchPatternName);
11040 + return;
11045 +static void renameMatchPatternInAllGroups(
11046 + char *oldMatchPatternName,
11047 + char *newMatchPatternName)
11049 + DialogMatchPatternSequenceElement *seq;
11050 + DialogMatchPatternGroupElement *group;
11051 + int i;
11053 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
11055 + seq = MatchPatternDialog.mpdTable.dmpiSequence[i];
11057 + if (seq->dmpseType == MPT_GROUP)
11059 + group = (DialogMatchPatternGroupElement *)seq->dmpsePtr;
11061 + renameMatchPatternInGroup(
11062 + oldMatchPatternName,
11063 + newMatchPatternName,
11064 + group);
11069 +static void freeVariableDialogData(
11070 + int keepLanguageModeName)
11072 + int i;
11074 + if (!keepLanguageModeName)
11075 + freeXtPtr((void **)&MatchPatternDialog.mpdLangModeName);
11077 + for (i=0; i < MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements; i ++)
11079 + freeDialogSequenceElement(
11080 + MatchPatternDialog.mpdTable.dmpiSequence[i] );
11083 + MatchPatternDialog.mpdTable.dmpiNbrOfSeqElements = 0;
11085 + freeDialogStringPatterns(
11086 + &MatchPatternDialog.currentStringPatterns);
11089 +static void initGlobalBackRefList(
11090 + GlobalBackRefElement *list)
11092 + int i;
11094 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
11096 + list[i].gbreDefByStrPat = NULL;
11097 + list[i].gbreRegExpText = NULL;
11101 +static void initStrPatBackRefList(
11102 + StringPattern *strPat)
11104 + int i;
11106 + for (i=0; i < MAX_GLOBAL_BACK_REF_ID; i++)
11108 + strPat->spOwnGlobalBackRef[i].spbreRegExpText = NULL;
11109 + strPat->spOwnGlobalBackRef[i].spbreLocalBackRefID = NO_LOCAL_BACK_REF_ID;
11111 + strPat->spGlobalToLocalBackRef[i] = NO_LOCAL_BACK_REF_ID;
11115 +static void initErrorInfo(
11116 + ErrorInfo *errInfo)
11118 + errInfo->eiDetail = NULL;
11119 + errInfo->eiLanguageMode = NULL;
11120 + errInfo->eiMPTabElementName = NULL;
11121 + errInfo->eiStringPatText = NULL;
11122 + errInfo->eiRegExpCompileMsg = NULL;
11123 + errInfo->eiBackRefNbr = 0;
11126 +static void freeErrorInfo(
11127 + ErrorInfo *errInfo)
11129 + freeXtPtr((void **)&errInfo->eiLanguageMode);
11130 + freeXtPtr((void **)&errInfo->eiMPTabElementName);
11131 + freeXtPtr((void **)&errInfo->eiStringPatText);
11134 +static void freeXtPtr(void **ptr)
11136 + if (*ptr != NULL)
11138 + XtFree((char *)*ptr);
11139 + *ptr = NULL;
11143 +static void freePtr(void **ptr)
11145 + if (*ptr != NULL)
11147 + free((char *)*ptr);
11148 + *ptr = NULL;
11151 diff --quilt /dev/null new/source/patternMatchData.h
11152 --- /dev/null
11153 +++ new/source/patternMatchData.h
11154 @@ -0,0 +1,24 @@
11155 +/* $Id: patternMatchData.h,v 1.3 2003/12/12 16:45:25 uleh Exp $ */
11157 +#ifndef NEDIT_PATTERNMATCHDATA_H_INCLUDED
11158 +#define NEDIT_PATTERNMATCHDATA_H_INCLUDED
11160 +void *FindStringMatchTable(const char *langModeName);
11162 +void RenameStringMatchTable(const char *oldName, const char *newName);
11164 +void DeleteStringMatchTable(const char *langModeName);
11166 +void AssignStandardStringMatchTable(const char *langModeName);
11168 +int LMHasStringMatchTable(const char *languageMode);
11170 +int LoadMatchPatternString(char *inString);
11172 +char *WriteMatchPatternString(void);
11174 +void EditMatchPatterns(WindowInfo *window);
11176 +void UpdateLanguageModeMenuMatchPattern(void);
11178 +#endif /* NEDIT_PATTERNMATCHDATA_H_INCLUDED */
11179 diff --quilt old/source/preferences.c new/source/preferences.c
11180 --- old/source/preferences.c
11181 +++ new/source/preferences.c
11182 @@ -45,10 +45,14 @@ static const char CVSID[] = "$Id: prefer
11183 #include "regularExp.h"
11184 #include "smartIndent.h"
11185 #include "windowTitle.h"
11186 #include "server.h"
11187 #include "tags.h"
11189 +/* Pattern Match Feature */
11190 +#include "patternMatchData.h"
11192 #include "../util/prefFile.h"
11193 #include "../util/misc.h"
11194 #include "../util/DialogF.h"
11195 #include "../util/managedList.h"
11196 #include "../util/fontsel.h"
11197 @@ -278,11 +282,10 @@ static struct prefData {
11198 int textCols; /* initial window width in characters */
11199 int tabDist; /* number of characters between tab stops */
11200 int emTabDist; /* non-zero tab dist. if emulated tabs are on */
11201 int insertTabs; /* whether to use tabs for padding */
11202 int showMatchingStyle; /* how to flash matching parenthesis */
11203 - int matchSyntaxBased; /* use syntax info to match parenthesis */
11204 int highlightSyntax; /* whether to highlight syntax by default */
11205 int smartTags; /* look for tag in current window first */
11206 int alwaysCheckRelativeTagsSpecs; /* for every new opened file of session */
11207 int stickyCaseSenseBtn; /* whether Case Word Btn is sticky to Regex Btn */
11208 int prefFileRead; /* detects whether a .nedit existed */
11209 @@ -348,10 +351,11 @@ static struct {
11210 char *language;
11211 char *styles;
11212 char *smartIndent;
11213 char *smartIndentCommon;
11214 char *shell;
11215 + char *matchPattern;
11216 } TempStringPrefs;
11218 /* preference descriptions for SavePreferences and RestorePreferences. */
11219 static PrefDescripRec PrefDescrip[] = {
11220 {"fileVersion", "FileVersion" , PREF_STRING, "", PrefData.fileVersion,
11221 @@ -853,10 +857,76 @@ static PrefDescripRec PrefDescrip[] = {
11222 C++:Default\n\
11223 Python:Default\n\
11224 Matlab:Default", &TempStringPrefs.smartIndent, NULL, True},
11225 {"smartIndentInitCommon", "SmartIndentInitCommon", PREF_ALLOC_STRING,
11226 "Default", &TempStringPrefs.smartIndentCommon, NULL, True},
11227 +/* Pattern Match Feature: matchPatterns resource added */
11228 +#ifdef VMS
11229 +/* The VAX compiler can't compile Java-Script's definition in highlightData.c */
11230 + {"matchPatterns", "MatchPatterns", PREF_ALLOC_STRING,
11231 + "PLAIN:Default\n\
11232 + Ada:Default\n\
11233 + Awk:Default\n\
11234 + C++:Default\n\
11235 + C:Default\n\
11236 + CSS:Default\n\
11237 + Csh:Default\n\
11238 + Fortran:Default\n\
11239 + Java:Default\n\
11240 + LaTeX:Default\n\
11241 + Lex:Default\n\
11242 + Makefile:Default\n\
11243 + Matlab:Default\n\
11244 + NEdit Macro:Default\n\
11245 + Pascal:Default\n\
11246 + Perl:Default\n\
11247 + PostScript:Default\n\
11248 + Python:Default\n\
11249 + Regex:Default\n\
11250 + SGML HTML:Default\n\
11251 + SQL:Default\n\
11252 + Sh Ksh Bash:Default\n\
11253 + Tcl:Default\n\
11254 + VHDL:Default\n\
11255 + Verilog:Default\n\
11256 + XML:Default\n\
11257 + X Resources:Default\n\
11258 + Yacc:Default\n",
11259 + &TempStringPrefs.matchPattern, NULL, True},
11260 +#else
11261 + {"matchPatterns", "MatchPatterns", PREF_ALLOC_STRING,
11262 + "PLAIN:Default\n\
11263 + Ada:Default\n\
11264 + Awk:Default\n\
11265 + C++:Default\n\
11266 + C:Default\n\
11267 + CSS:Default\n\
11268 + Csh:Default\n\
11269 + Fortran:Default\n\
11270 + Java:Default\n\
11271 + JavaScript:Default\n\
11272 + LaTeX:Default\n\
11273 + Lex:Default\n\
11274 + Makefile:Default\n\
11275 + Matlab:Default\n\
11276 + NEdit Macro:Default\n\
11277 + Pascal:Default\n\
11278 + Perl:Default\n\
11279 + PostScript:Default\n\
11280 + Python:Default\n\
11281 + Regex:Default\n\
11282 + SGML HTML:Default\n\
11283 + SQL:Default\n\
11284 + Sh Ksh Bash:Default\n\
11285 + Tcl:Default\n\
11286 + VHDL:Default\n\
11287 + Verilog:Default\n\
11288 + XML:Default\n\
11289 + X Resources:Default\n\
11290 + Yacc:Default\n",
11291 + &TempStringPrefs.matchPattern, NULL, True},
11292 +#endif
11293 {"autoWrap", "AutoWrap", PREF_ENUM, "Continuous",
11294 &PrefData.wrapStyle, AutoWrapTypes, True},
11295 {"wrapMargin", "WrapMargin", PREF_INT, "0",
11296 &PrefData.wrapMargin, NULL, True},
11297 {"showWrapMargin", "ShowWrapMargin", PREF_ENUM, "Never",
11298 @@ -869,12 +939,10 @@ static PrefDescripRec PrefDescrip[] = {
11299 &PrefData.openInTab, NULL, True},
11300 {"saveOldVersion", "SaveOldVersion", PREF_BOOLEAN, "False",
11301 &PrefData.saveOldVersion, NULL, True},
11302 {"showMatching", "ShowMatching", PREF_ENUM, "Delimiter",
11303 &PrefData.showMatchingStyle, ShowMatchingTypes, True},
11304 - {"matchSyntaxBased", "MatchSyntaxBased", PREF_BOOLEAN, "True",
11305 - &PrefData.matchSyntaxBased, NULL, True},
11306 {"highlightSyntax", "HighlightSyntax", PREF_BOOLEAN, "True",
11307 &PrefData.highlightSyntax, NULL, True},
11308 {"backlightChars", "BacklightChars", PREF_BOOLEAN, "False",
11309 &PrefData.backlightChars, NULL, True},
11310 {"backlightCharTypes", "BacklightCharTypes", PREF_ALLOC_STRING,
11311 @@ -1243,10 +1311,11 @@ static void lmDestroyCB(Widget w, XtPoin
11312 static void lmOkCB(Widget w, XtPointer clientData, XtPointer callData);
11313 static void lmApplyCB(Widget w, XtPointer clientData, XtPointer callData);
11314 static void lmCloseCB(Widget w, XtPointer clientData, XtPointer callData);
11315 static int lmDeleteConfirmCB(int itemIndex, void *cbArg);
11316 static int updateLMList(void);
11317 +static int isOldLanguageMode(const char *lmDialogName, const char *oldModeName);
11318 static languageModeRec *copyLanguageModeRec(languageModeRec *lm);
11319 static void *lmGetDisplayedCB(void *oldItem, int explicitRequest, int *abort,
11320 void *cbArg);
11321 static void lmSetDisplayedCB(void *item, void *cbArg);
11322 static languageModeRec *readLMDialogFields(int silent);
11323 @@ -1425,10 +1494,15 @@ static void translatePrefFormats(int con
11324 if (TempStringPrefs.smartIndentCommon != NULL) {
11325 LoadSmartIndentCommonString(TempStringPrefs.smartIndentCommon);
11326 XtFree(TempStringPrefs.smartIndentCommon);
11327 TempStringPrefs.smartIndentCommon = NULL;
11329 + if (TempStringPrefs.matchPattern != NULL) {
11330 + LoadMatchPatternString(TempStringPrefs.matchPattern);
11331 + XtFree(TempStringPrefs.matchPattern);
11332 + TempStringPrefs.matchPattern = NULL;
11335 /* translate the font names into fontLists suitable for the text widget */
11336 font = XLoadQueryFont(TheDisplay, PrefData.fontString);
11337 PrefData.fontList = font==NULL ? NULL :
11338 XmFontListCreate(font, XmSTRING_DEFAULT_CHARSET);
11339 @@ -1504,10 +1578,11 @@ void SaveNEditPrefs(Widget parent, int q
11340 TempStringPrefs.highlight = WriteHighlightString();
11341 TempStringPrefs.language = writeLanguageModesString();
11342 TempStringPrefs.styles = WriteStylesString();
11343 TempStringPrefs.smartIndent = WriteSmartIndentString();
11344 TempStringPrefs.smartIndentCommon = WriteSmartIndentCommonString();
11345 + TempStringPrefs.matchPattern = WriteMatchPatternString();
11346 strcpy(PrefData.fileVersion, PREF_FILE_VERSION);
11348 if (!SavePreferences(XtDisplay(parent), prefFileName, HeaderText,
11349 PrefDescrip, XtNumber(PrefDescrip)))
11351 @@ -1523,10 +1598,11 @@ void SaveNEditPrefs(Widget parent, int q
11352 XtFree(TempStringPrefs.highlight);
11353 XtFree(TempStringPrefs.language);
11354 XtFree(TempStringPrefs.styles);
11355 XtFree(TempStringPrefs.smartIndent);
11356 XtFree(TempStringPrefs.smartIndentCommon);
11357 + XtFree(TempStringPrefs.matchPattern);
11359 PrefsHaveChanged = False;
11363 @@ -1919,20 +1995,10 @@ int GetPrefShowMatching(void)
11364 if (PrefData.showMatchingStyle >= N_SHOW_MATCHING_STYLES)
11365 PrefData.showMatchingStyle -= N_SHOW_MATCHING_STYLES;
11366 return PrefData.showMatchingStyle;
11369 -void SetPrefMatchSyntaxBased(int state)
11371 - setIntPref(&PrefData.matchSyntaxBased, state);
11374 -int GetPrefMatchSyntaxBased(void)
11376 - return PrefData.matchSyntaxBased;
11379 void SetPrefHighlightSyntax(Boolean state)
11381 setIntPref(&PrefData.highlightSyntax, state);
11384 @@ -3478,10 +3544,25 @@ static int lmDeleteConfirmCB(int itemInd
11385 "Auto Indent -> Program Smart Indent,\n"
11386 "before proceeding here.", "OK");
11387 return False;
11390 + /* Pattern Match Feature: don't allow deletion if data will be lost */
11391 + if (LMHasStringMatchTable(LMDialog.languageModeList[itemIndex]->name))
11393 + DialogF(DF_WARN, LMDialog.shell, 1, "Matching Patterns exist",
11394 + "This language mode has matching patterns\n"
11395 + "defined. Please delete the patterns first,\n"
11396 + "in Preferences -> Default Settings ->\n"
11397 + "Show Matching (..) -> Matching Patterns ..,\n"
11398 + "before proceeding here.", "Dismiss");
11399 + return False;
11402 + /* delete "empty" string match table related to language mode to be deleted */
11403 + DeleteStringMatchTable(LMDialog.languageModeList[itemIndex]->name);
11405 return True;
11409 ** Apply the changes that the user has made in the language modes dialog to the
11410 @@ -3498,19 +3579,19 @@ static int updateLMList(void)
11411 /* Get the current contents of the dialog fields */
11412 if (!UpdateManagedList(LMDialog.managedListW, True))
11413 return False;
11415 /* Fix up language mode indices in all open windows (which may change
11416 - if the currently selected mode is deleted or has changed position),
11417 - and update word delimiters */
11418 + if the currently selected mode is renamed, deleted or has changed
11419 + position), and update word delimiters */
11420 for (window=WindowList; window!=NULL; window=window->next) {
11421 if (window->languageMode != PLAIN_LANGUAGE_MODE) {
11422 oldLanguageMode = window->languageMode;
11423 oldModeName = LanguageModes[window->languageMode]->name;
11424 window->languageMode = PLAIN_LANGUAGE_MODE;
11425 for (i=0; i<LMDialog.nLanguageModes; i++) {
11426 - if (!strcmp(oldModeName, LMDialog.languageModeList[i]->name)) {
11427 + if (isOldLanguageMode(LMDialog.languageModeList[i]->name, oldModeName)) {
11428 newDelimiters = LMDialog.languageModeList[i]->delimiters;
11429 if (newDelimiters == NULL)
11430 newDelimiters = GetPrefDelimiters();
11431 XtVaSetValues(window->textArea, textNwordDelimiters,
11432 newDelimiters, NULL);
11433 @@ -3536,10 +3617,11 @@ static int updateLMList(void)
11434 if (strchr(LMDialog.languageModeList[i]->name, ':') != NULL) {
11435 char *newName = strrchr(LMDialog.languageModeList[i]->name, ':')+1;
11436 *strchr(LMDialog.languageModeList[i]->name, ':') = '\0';
11437 RenameHighlightPattern(LMDialog.languageModeList[i]->name, newName);
11438 RenameSmartIndentMacros(LMDialog.languageModeList[i]->name, newName);
11439 + RenameStringMatchTable(LMDialog.languageModeList[i]->name, newName);
11440 memmove(LMDialog.languageModeList[i]->name, newName,
11441 strlen(newName) + 1);
11442 ChangeManagedListData(LMDialog.managedListW);
11445 @@ -3553,31 +3635,62 @@ static int updateLMList(void)
11447 /* Update user menu info to update language mode dependencies of
11448 user menu items */
11449 UpdateUserMenuInfo();
11451 + /* Pattern Match Feature: assign standard string match table to new
11452 + language modes */
11453 + for (i=0; i<NLanguageModes; i++) {
11454 + if (FindStringMatchTable(LanguageModeName(i)) == NULL)
11455 + AssignStandardStringMatchTable(LanguageModeName(i));
11458 /* Update the menus in the window menu bars and load any needed
11459 - calltips files */
11460 + calltips files and reassign string match tables */
11461 for (window=WindowList; window!=NULL; window=window->next) {
11462 updateLanguageModeSubmenu(window);
11463 if (window->languageMode != PLAIN_LANGUAGE_MODE &&
11464 LanguageModes[window->languageMode]->defTipsFile != NULL)
11465 AddTagsFile(LanguageModes[window->languageMode]->defTipsFile, TIP);
11467 + window->stringMatchTable =
11468 + FindStringMatchTable(LanguageModeName(window->languageMode));
11470 /* cache user menus: Rebuild all user menus of this window */
11471 RebuildAllMenus(window);
11474 /* If a syntax highlighting dialog is up, update its menu */
11475 UpdateLanguageModeMenu();
11476 /* The same for the smart indent macro dialog */
11477 UpdateLangModeMenuSmartIndent();
11478 + /* The same for the match pattern dialog */
11479 + UpdateLanguageModeMenuMatchPattern();
11480 /* Note that preferences have been changed */
11481 MarkPrefsChanged();
11483 return True;
11487 +** Returns true, if the given old language mode name matches the
11488 +** given (new) language mode dialog name.
11490 +static int isOldLanguageMode(const char *lmDialogName, const char *oldModeName)
11492 + char *c = strchr(lmDialogName, ':');
11493 + int isOldMode = !strcmp(oldModeName, lmDialogName);
11495 + if (!isOldMode && c != NULL) {
11496 + *c = '\0';
11497 + isOldMode = !strcmp(lmDialogName, oldModeName);
11498 + *c = ':';
11501 + return isOldMode;
11504 static void *lmGetDisplayedCB(void *oldItem, int explicitRequest, int *abort,
11505 void *cbArg)
11507 languageModeRec *lm, *oldLM = (languageModeRec *)oldItem;
11508 char *tempName;
11509 @@ -4567,10 +4680,14 @@ static void reapplyLanguageMode(WindowIn
11510 /* Decref oldMode's default calltips file if needed */
11511 if (oldMode != PLAIN_LANGUAGE_MODE && LanguageModes[oldMode]->defTipsFile) {
11512 DeleteTagsFile( LanguageModes[oldMode]->defTipsFile, TIP, False );
11515 + /* Pattern Match Feature: Assign the match pattern related to
11516 + the language mode */
11517 + window->stringMatchTable = FindStringMatchTable(LanguageModeName(mode));
11519 /* Set delimiters for all text widgets */
11520 if (mode == PLAIN_LANGUAGE_MODE || LanguageModes[mode]->delimiters == NULL)
11521 delimiters = GetPrefDelimiters();
11522 else
11523 delimiters = LanguageModes[mode]->delimiters;
11524 @@ -5184,18 +5301,35 @@ char *ReadSymbolicFieldTextWidget(Widget
11528 ** Create a pulldown menu pane with the names of the current language modes.
11529 ** XmNuserData for each item contains the language mode name.
11530 +** Pattern Match Feature: if "includePlain" is set, then 1st menu entry
11531 +** holds "PLAIN".
11533 -Widget CreateLanguageModeMenu(Widget parent, XtCallbackProc cbProc, void *cbArg)
11534 +Widget CreateLanguageModeMenu(
11535 + Widget parent,
11536 + XtCallbackProc cbProc,
11537 + void *cbArg,
11538 + int includePlain)
11540 Widget menu, btn;
11541 int i;
11542 XmString s1;
11544 menu = CreatePulldownMenu(parent, "languageModes", NULL, 0);
11546 + if (includePlain) {
11547 + btn = XtVaCreateManagedWidget("languageMode", xmPushButtonGadgetClass,
11548 + menu,
11549 + XmNlabelString, s1=XmStringCreateSimple("PLAIN"),
11550 + XmNmarginHeight, 0,
11551 + XmNuserData, (void *)"PLAIN", NULL);
11552 + XmStringFree(s1);
11553 + XtAddCallback(btn, XmNactivateCallback, cbProc, cbArg);
11556 for (i=0; i<NLanguageModes; i++) {
11557 btn = XtVaCreateManagedWidget("languageMode", xmPushButtonGadgetClass,
11558 menu,
11559 XmNlabelString, s1=XmStringCreateSimple(LanguageModes[i]->name),
11560 XmNmarginHeight, 0,
11561 diff --quilt old/source/preferences.h new/source/preferences.h
11562 --- old/source/preferences.h
11563 +++ new/source/preferences.h
11564 @@ -109,12 +109,10 @@ void SetPrefEmTabDist(int tabDist);
11565 int GetPrefEmTabDist(int langMode);
11566 void SetPrefInsertTabs(int state);
11567 int GetPrefInsertTabs(void);
11568 void SetPrefShowMatching(int state);
11569 int GetPrefShowMatching(void);
11570 -void SetPrefMatchSyntaxBased(int state);
11571 -int GetPrefMatchSyntaxBased(void);
11572 void SetPrefHighlightSyntax(Boolean state);
11573 Boolean GetPrefHighlightSyntax(void);
11574 void SetPrefBacklightChars(int state);
11575 int GetPrefBacklightChars(void);
11576 void SetPrefBacklightCharTypes(char *types);
11577 @@ -190,11 +188,11 @@ int AllocatedStringsDiffer(const char *s
11578 void SetLanguageMode(WindowInfo *window, int mode, int forceNewDefaults);
11579 int FindLanguageMode(const char *languageName);
11580 void UnloadLanguageModeTipsFile(WindowInfo *window);
11581 void DetermineLanguageMode(WindowInfo *window, int forceNewDefaults);
11582 Widget CreateLanguageModeMenu(Widget parent, XtCallbackProc cbProc,
11583 - void *cbArg);
11584 + void *cbArg, int includePlain);
11585 void SetLangModeMenu(Widget optMenu, const char *modeName);
11586 void CreateLanguageModeSubMenu(WindowInfo* window, const Widget parent,
11587 const char* name, const char* label, const char mnemonic);
11588 void SetPrefFindReplaceUsesSelection(int state);
11589 int GetPrefFindReplaceUsesSelection(void);
11590 diff --quilt old/source/search.c new/source/search.c
11591 --- old/source/search.c
11592 +++ new/source/search.c
11593 @@ -83,10 +83,11 @@ static const char CVSID[] = "$Id: search
11595 #ifdef HAVE_DEBUG_H
11596 #include "../debug.h"
11597 #endif
11599 +#include "patternMatch.h"
11601 int NHist = 0;
11603 typedef struct _SelectionInfo {
11604 int done;
11605 @@ -171,10 +172,11 @@ static void freeWritableWindowsCB(Widget
11606 XmAnyCallbackStruct *callData);
11607 static void checkMultiReplaceListForDoomedW(WindowInfo* window,
11608 WindowInfo* doomedWindow);
11609 static void removeDoomedWindowFromList(WindowInfo* window, int index);
11610 static void unmanageReplaceDialogs(const WindowInfo *window);
11611 +static int getPosForMatchingCharacter(WindowInfo *window);
11612 static void flashTimeoutProc(XtPointer clientData, XtIntervalId *id);
11613 static void eraseFlash(WindowInfo *window);
11614 static int getReplaceDlogInfo(WindowInfo *window, int *direction,
11615 char *searchString, char *replaceString, int *searchType);
11616 static int getFindDlogInfo(WindowInfo *window, int *direction,
11617 @@ -211,13 +213,10 @@ static void downCaseString(char *outStri
11618 static void resetFindTabGroup(WindowInfo *window);
11619 static void resetReplaceTabGroup(WindowInfo *window);
11620 static int searchMatchesSelection(WindowInfo *window, const char *searchString,
11621 int searchType, int *left, int *right, int *searchExtentBW,
11622 int *searchExtentFW);
11623 -static int findMatchingChar(WindowInfo *window, char toMatch,
11624 - void *toMatchStyle, int charPos, int startLimit, int endLimit,
11625 - int *matchPos);
11626 static Boolean replaceUsingRE(const char* searchStr, const char* replaceStr,
11627 const char* sourceStr, int beginPos, char* destStr, int maxDestLen,
11628 int prevChar, const char* delimiters, int defaultFlags);
11629 static void saveSearchHistory(const char *searchString,
11630 const char *replaceString, int searchType, int isIncremental);
11631 @@ -251,28 +250,10 @@ typedef struct _charMatchTable {
11632 char c;
11633 char match;
11634 char direction;
11635 } charMatchTable;
11637 -#define N_MATCH_CHARS 13
11638 -#define N_FLASH_CHARS 6
11639 -static charMatchTable MatchingChars[N_MATCH_CHARS] = {
11640 - {'{', '}', SEARCH_FORWARD},
11641 - {'}', '{', SEARCH_BACKWARD},
11642 - {'(', ')', SEARCH_FORWARD},
11643 - {')', '(', SEARCH_BACKWARD},
11644 - {'[', ']', SEARCH_FORWARD},
11645 - {']', '[', SEARCH_BACKWARD},
11646 - {'<', '>', SEARCH_FORWARD},
11647 - {'>', '<', SEARCH_BACKWARD},
11648 - {'/', '/', SEARCH_FORWARD},
11649 - {'"', '"', SEARCH_FORWARD},
11650 - {'\'', '\'', SEARCH_FORWARD},
11651 - {'`', '`', SEARCH_FORWARD},
11652 - {'\\', '\\', SEARCH_FORWARD},
11656 ** Definitions for the search method strings, used as arguments for
11657 ** macro search subroutines and search action routines
11659 static char *searchTypeStrings[] = {
11660 @@ -3336,22 +3317,22 @@ static void iSearchTextKeyEH(Widget w, W
11661 XmTextSetInsertionPosition(window->iSearchText,
11662 XmTextGetLastPosition(window->iSearchText));
11666 -** Check the character before the insertion cursor of textW and flash
11667 -** matching parenthesis, brackets, or braces, by temporarily highlighting
11668 -** the matching character (a timer procedure is scheduled for removing the
11669 -** highlights)
11670 +** Check the characters before the insertion cursor of textW and flash
11671 +** matching patterns (parenthesis e.g. brackets, braces ..) by temporarily
11672 +** highlighting matching characters (a timer procedure is scheduled for
11673 +** removing the highlights)
11675 void FlashMatching(WindowInfo *window, Widget textW)
11677 - char c;
11678 - void *style;
11679 - int pos, matchIndex;
11680 - int startPos, endPos, searchPos, matchPos;
11681 + int pos;
11682 + int direction;
11683 + int startPos, endPos, matchPos, matchLen;
11684 int constrain;
11685 + MatchingType matchingType;
11687 /* if a marker is already drawn, erase it and cancel the timeout */
11688 if (window->flashTimeoutID != 0) {
11689 eraseFlash(window);
11690 XtRemoveTimeOut(window->flashTimeoutID);
11691 @@ -3365,52 +3346,47 @@ void FlashMatching(WindowInfo *window, W
11693 /* don't flash matching characters if there's a selection */
11694 if (window->buffer->primary.selected)
11695 return;
11697 - /* get the character to match and the position to start from */
11698 - pos = TextGetCursorPos(textW) - 1;
11699 + /* get the position to start from */
11700 + pos = TextGetCursorPos(textW);
11701 if (pos < 0)
11702 return;
11703 - c = BufGetCharacter(window->buffer, pos);
11704 - style = GetHighlightInfo(window, pos);
11706 - /* is the character one we want to flash? */
11707 - for (matchIndex = 0; matchIndex<N_FLASH_CHARS; matchIndex++) {
11708 - if (MatchingChars[matchIndex].c == c)
11709 - break;
11711 - if (matchIndex == N_FLASH_CHARS)
11712 - return;
11714 /* constrain the search to visible text only when in single-pane mode
11715 AND using delimiter flashing (otherwise search the whole buffer) */
11716 constrain = ((window->nPanes == 0) &&
11717 (window->showMatchingStyle == FLASH_DELIMIT));
11719 - if (MatchingChars[matchIndex].direction == SEARCH_BACKWARD) {
11720 startPos = constrain ? TextFirstVisiblePos(textW) : 0;
11721 - endPos = pos;
11722 - searchPos = endPos;
11723 - } else {
11724 - startPos = pos;
11725 endPos = constrain ? TextLastVisiblePos(textW) :
11726 window->buffer->length;
11727 - searchPos = startPos;
11729 + /* cursor pos. must be between start / end pos. */
11730 + if (pos < startPos || pos > endPos)
11731 + return;
11733 + /* Pattern Match Feature: determine matching type
11734 + (here: flash delimiter or range) */
11735 + if (window->showMatchingStyle == FLASH_DELIMIT) {
11736 + matchingType = MT_FLASH_DELIMIT;
11737 + } else {
11738 + matchingType = MT_FLASH_RANGE;
11741 - /* do the search */
11742 - if (!findMatchingChar(window, c, style, searchPos, startPos, endPos,
11743 - &matchPos))
11744 + /* Pattern Match Feature: do the search */
11745 + if (!FindMatchingString(window, matchingType, &pos, startPos, endPos,
11746 + &matchPos, &matchLen, &direction))
11747 return;
11749 if (window->showMatchingStyle == FLASH_DELIMIT) {
11750 - /* Highlight either the matching character ... */
11751 - BufHighlight(window->buffer, matchPos, matchPos+1);
11752 + /* Highlight either the matching characters ... */
11753 + BufHighlight(window->buffer, matchPos, matchPos + matchLen);
11754 } else {
11755 /* ... or the whole range. */
11756 - if (MatchingChars[matchIndex].direction == SEARCH_BACKWARD) {
11757 + if (direction == SEARCH_BACKWARD) {
11758 BufHighlight(window->buffer, matchPos, pos+1);
11759 } else {
11760 BufHighlight(window->buffer, matchPos+1, pos);
11763 @@ -3420,42 +3396,50 @@ void FlashMatching(WindowInfo *window, W
11764 XtWidgetToApplicationContext(window->shell), 1500,
11765 flashTimeoutProc, window);
11766 window->flashPos = matchPos;
11769 -void SelectToMatchingCharacter(WindowInfo *window)
11771 +** Pattern Match Feature:
11772 +** get position of the character to match from the selection, or
11773 +** the character before the insert point if nothing is selected.
11776 +static int getPosForMatchingCharacter(WindowInfo *window)
11778 + int pos;
11779 int selStart, selEnd;
11780 - int startPos, endPos, matchPos;
11781 textBuffer *buf = window->buffer;
11783 - /* get the character to match and its position from the selection, or
11784 - the character before the insert point if nothing is selected.
11785 - Give up if too many characters are selected */
11786 - if (!GetSimpleSelection(buf, &selStart, &selEnd)) {
11787 - selEnd = TextGetCursorPos(window->lastFocus);
11788 - if (window->overstrike)
11789 - selEnd += 1;
11790 - selStart = selEnd - 1;
11791 - if (selStart < 0) {
11792 - XBell(TheDisplay, 0);
11793 - return;
11795 + if (GetSimpleSelection(buf, &selStart, &selEnd)) {
11796 + pos = selEnd;
11798 - if ((selEnd - selStart) != 1) {
11799 - XBell(TheDisplay, 0);
11800 - return;
11801 + else {
11802 + pos = TextGetCursorPos(window->lastFocus);
11806 + return pos;
11809 +void SelectToMatchingCharacter(WindowInfo *window)
11811 + int pos;
11812 + int startPos, endPos, matchPos, matchLen;
11813 + int direction;
11814 + textBuffer *buf = window->buffer;
11816 + /* Pattern Match Feature: get position of the character to match */
11817 + pos = getPosForMatchingCharacter(window);
11819 /* Search for it in the buffer */
11820 - if (!findMatchingChar(window, BufGetCharacter(buf, selStart),
11821 - GetHighlightInfo(window, selStart), selStart, 0, buf->length, &matchPos)) {
11822 + if (!FindMatchingString(window, MT_SELECT, &pos, 0,
11823 + buf->length, &matchPos, &matchLen, &direction)) {
11824 XBell(TheDisplay, 0);
11825 return;
11827 - startPos = (matchPos > selStart) ? selStart : matchPos;
11828 - endPos = (matchPos > selStart) ? matchPos : selStart;
11829 + startPos = (matchPos > pos) ? pos : matchPos;
11830 + endPos = (matchPos > pos) ? matchPos : pos;
11832 /* temporarily shut off autoShowInsertPos before setting the cursor
11833 position so MakeSelectionVisible gets a chance to place the cursor
11834 string at a pleasing position on the screen (otherwise, the cursor would
11835 be automatically scrolled on screen and MakeSelectionVisible would do
11836 @@ -3467,117 +3451,36 @@ void SelectToMatchingCharacter(WindowInf
11837 XtVaSetValues(window->lastFocus, textNautoShowInsertPos, True, NULL);
11840 void GotoMatchingCharacter(WindowInfo *window)
11842 - int selStart, selEnd;
11843 - int matchPos;
11844 + int pos;
11845 + int matchPos, matchLen;
11846 + int direction;
11847 textBuffer *buf = window->buffer;
11849 - /* get the character to match and its position from the selection, or
11850 - the character before the insert point if nothing is selected.
11851 - Give up if too many characters are selected */
11852 - if (!GetSimpleSelection(buf, &selStart, &selEnd)) {
11853 - selEnd = TextGetCursorPos(window->lastFocus);
11854 - if (window->overstrike)
11855 - selEnd += 1;
11856 - selStart = selEnd - 1;
11857 - if (selStart < 0) {
11858 - XBell(TheDisplay, 0);
11859 - return;
11862 - if ((selEnd - selStart) != 1) {
11863 - XBell(TheDisplay, 0);
11864 - return;
11866 + /* Pattern Match Feature: get position of the character to match */
11867 + pos = getPosForMatchingCharacter(window);
11869 /* Search for it in the buffer */
11870 - if (!findMatchingChar(window, BufGetCharacter(buf, selStart),
11871 - GetHighlightInfo(window, selStart), selStart, 0,
11872 - buf->length, &matchPos)) {
11873 + if (!FindMatchingString(window, MT_GOTO, &pos, 0,
11874 + buf->length, &matchPos, &matchLen, &direction)) {
11875 XBell(TheDisplay, 0);
11876 return;
11879 /* temporarily shut off autoShowInsertPos before setting the cursor
11880 position so MakeSelectionVisible gets a chance to place the cursor
11881 string at a pleasing position on the screen (otherwise, the cursor would
11882 be automatically scrolled on screen and MakeSelectionVisible would do
11883 nothing) */
11884 XtVaSetValues(window->lastFocus, textNautoShowInsertPos, False, NULL);
11885 - TextSetCursorPos(window->lastFocus, matchPos+1);
11886 + TextSetCursorPos(window->lastFocus, matchPos);
11887 MakeSelectionVisible(window, window->lastFocus);
11888 XtVaSetValues(window->lastFocus, textNautoShowInsertPos, True, NULL);
11891 -static int findMatchingChar(WindowInfo *window, char toMatch,
11892 - void* styleToMatch, int charPos, int startLimit, int endLimit,
11893 - int *matchPos)
11895 - int nestDepth, matchIndex, direction, beginPos, pos;
11896 - char matchChar, c;
11897 - void *style = NULL;
11898 - textBuffer *buf = window->buffer;
11899 - int matchSyntaxBased = window->matchSyntaxBased;
11901 - /* If we don't match syntax based, fake a matching style. */
11902 - if (!matchSyntaxBased) style = styleToMatch;
11904 - /* Look up the matching character and match direction */
11905 - for (matchIndex = 0; matchIndex<N_MATCH_CHARS; matchIndex++) {
11906 - if (MatchingChars[matchIndex].c == toMatch)
11907 - break;
11909 - if (matchIndex == N_MATCH_CHARS)
11910 - return FALSE;
11911 - matchChar = MatchingChars[matchIndex].match;
11912 - direction = MatchingChars[matchIndex].direction;
11914 - /* find it in the buffer */
11915 - beginPos = (direction==SEARCH_FORWARD) ? charPos+1 : charPos-1;
11916 - nestDepth = 1;
11917 - if (direction == SEARCH_FORWARD) {
11918 - for (pos=beginPos; pos<endLimit; pos++) {
11919 - c=BufGetCharacter(buf, pos);
11920 - if (c == matchChar) {
11921 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11922 - if (style == styleToMatch) {
11923 - nestDepth--;
11924 - if (nestDepth == 0) {
11925 - *matchPos = pos;
11926 - return TRUE;
11929 - } else if (c == toMatch) {
11930 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11931 - if (style == styleToMatch)
11932 - nestDepth++;
11935 - } else { /* SEARCH_BACKWARD */
11936 - for (pos=beginPos; pos>=startLimit; pos--) {
11937 - c=BufGetCharacter(buf, pos);
11938 - if (c == matchChar) {
11939 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11940 - if (style == styleToMatch) {
11941 - nestDepth--;
11942 - if (nestDepth == 0) {
11943 - *matchPos = pos;
11944 - return TRUE;
11947 - } else if (c == toMatch) {
11948 - if (matchSyntaxBased) style = GetHighlightInfo(window, pos);
11949 - if (style == styleToMatch)
11950 - nestDepth++;
11954 - return FALSE;
11958 ** Xt timer procedure for erasing the matching parenthesis marker.
11960 static void flashTimeoutProc(XtPointer clientData, XtIntervalId *id)
11962 diff --quilt old/source/smartIndent.c new/source/smartIndent.c
11963 --- old/source/smartIndent.c
11964 +++ new/source/smartIndent.c
11965 @@ -978,13 +978,13 @@ void EditSmartIndentMacros(WindowInfo *w
11966 XmNleftPosition, 1,
11967 XmNtopAttachment, XmATTACH_POSITION,
11968 XmNtopPosition, 1,
11969 XmNrightAttachment, XmATTACH_POSITION,
11970 XmNrightPosition, 99, NULL);
11972 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
11973 SmartIndentDialog.lmPulldown = CreateLanguageModeMenu(lmForm, langModeCB,
11974 - NULL);
11975 + NULL, FALSE);
11976 n = 0;
11977 XtSetArg(args[n], XmNspacing, 0); n++;
11978 XtSetArg(args[n], XmNmarginWidth, 0); n++;
11979 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
11980 XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
11981 @@ -2150,12 +2150,13 @@ void UpdateLangModeMenuSmartIndent(void)
11983 if (SmartIndentDialog.shell == NULL)
11984 return;
11986 oldMenu = SmartIndentDialog.lmPulldown;
11987 + /* Pattern Match Feature: don't include "PLAIN" (4th parameter) */
11988 SmartIndentDialog.lmPulldown = CreateLanguageModeMenu(
11989 - XtParent(XtParent(oldMenu)), langModeCB, NULL);
11990 + XtParent(XtParent(oldMenu)), langModeCB, NULL, FALSE);
11991 XtVaSetValues(XmOptionButtonGadget(SmartIndentDialog.lmOptMenu),
11992 XmNsubMenuId, SmartIndentDialog.lmPulldown, NULL);
11993 SetLangModeMenu(SmartIndentDialog.lmOptMenu, SmartIndentDialog.langModeName);
11995 XtDestroyWidget(oldMenu);
11996 diff --quilt old/source/window.c new/source/window.c
11997 --- old/source/window.c
11998 +++ new/source/window.c
11999 @@ -53,10 +53,11 @@ static const char CVSID[] = "$Id: window
12000 #include "nedit.bm"
12001 #include "n.bm"
12002 #include "windowTitle.h"
12003 #include "interpret.h"
12004 #include "rangeset.h"
12005 +#include "patternMatchData.h"
12006 #include "../util/clearcase.h"
12007 #include "../util/misc.h"
12008 #include "../util/fileUtils.h"
12009 #include "../util/utils.h"
12010 #include "../util/fileUtils.h"
12011 @@ -275,11 +276,10 @@ WindowInfo *CreateWindow(const char *nam
12012 window->saveOldVersion = GetPrefSaveOldVersion();
12013 window->wrapMode = GetPrefWrap(PLAIN_LANGUAGE_MODE);
12014 window->showWrapMargin = GetPrefShowWrapMargin();
12015 window->overstrike = False;
12016 window->showMatchingStyle = GetPrefShowMatching();
12017 - window->matchSyntaxBased = GetPrefMatchSyntaxBased();
12018 window->showStats = GetPrefStatsLine();
12019 window->showISearchLine = GetPrefISearchLine();
12020 window->showLineNumbers = GetPrefLineNums();
12021 window->highlightSyntax = GetPrefHighlightSyntax();
12022 window->backlightCharTypes = NULL;
12023 @@ -314,10 +314,14 @@ WindowInfo *CreateWindow(const char *nam
12024 window->highlightData = NULL;
12025 window->shellCmdData = NULL;
12026 window->macroCmdData = NULL;
12027 window->smartIndentData = NULL;
12028 window->languageMode = PLAIN_LANGUAGE_MODE;
12030 + /* Pattern Match Feature: assign "PLAIN" string match table*/
12031 + window->stringMatchTable = FindStringMatchTable(NULL);
12033 window->iSearchHistIndex = 0;
12034 window->iSearchStartPos = -1;
12035 window->replaceLastRegexCase = TRUE;
12036 window->replaceLastLiteralCase = FALSE;
12037 window->iSearchLastRegexCase = TRUE;
12038 @@ -3451,11 +3455,10 @@ WindowInfo* CreateDocument(WindowInfo* s
12039 window->saveOldVersion = GetPrefSaveOldVersion();
12040 window->wrapMode = GetPrefWrap(PLAIN_LANGUAGE_MODE);
12041 window->showWrapMargin = GetPrefShowWrapMargin();
12042 window->overstrike = False;
12043 window->showMatchingStyle = GetPrefShowMatching();
12044 - window->matchSyntaxBased = GetPrefMatchSyntaxBased();
12045 window->highlightSyntax = GetPrefHighlightSyntax();
12046 window->backlightCharTypes = NULL;
12047 window->backlightChars = GetPrefBacklightChars();
12048 if (window->backlightChars) {
12049 char *cTypes = GetPrefBacklightCharTypes();
12050 @@ -3486,10 +3489,16 @@ WindowInfo* CreateDocument(WindowInfo* s
12051 window->highlightData = NULL;
12052 window->shellCmdData = NULL;
12053 window->macroCmdData = NULL;
12054 window->smartIndentData = NULL;
12055 window->languageMode = PLAIN_LANGUAGE_MODE;
12057 + /*
12058 + * Pattern Match Feature:
12059 + */
12060 + window->stringMatchTable = FindStringMatchTable(NULL);
12062 window->iSearchHistIndex = 0;
12063 window->iSearchStartPos = -1;
12064 window->replaceLastRegexCase = TRUE;
12065 window->replaceLastLiteralCase = FALSE;
12066 window->iSearchLastRegexCase = TRUE;
12067 @@ -3883,11 +3892,10 @@ void RefreshMenuToggleStates(WindowInfo
12068 #ifndef VMS
12069 XmToggleButtonSetState(window->saveLastItem, window->saveOldVersion, False);
12070 #endif
12071 XmToggleButtonSetState(window->autoSaveItem, window->autoSave, False);
12072 XmToggleButtonSetState(window->overtypeModeItem, window->overstrike, False);
12073 - XmToggleButtonSetState(window->matchSyntaxBasedItem, window->matchSyntaxBased, False);
12074 XmToggleButtonSetState(window->readOnlyItem, IS_USER_LOCKED(window->lockReasons), False);
12075 XmToggleButtonSetState(window->transientItem, window->transient, False);
12077 XtSetSensitive(window->smartIndentItem,
12078 SmartIndentMacrosAvailable(LanguageModeName(window->languageMode)));
12079 @@ -4447,10 +4455,13 @@ static void cloneDocument(WindowInfo *wi
12080 window->languageMode = orgWin->languageMode;
12081 window->highlightSyntax = orgWin->highlightSyntax;
12082 if (window->highlightSyntax)
12083 StartHighlighting(window, False);
12085 + /* recycle the pattern match data */
12086 + window->stringMatchTable = orgWin->stringMatchTable;
12088 /* copy states of original document */
12089 window->filenameSet = orgWin->filenameSet;
12090 window->fileFormat = orgWin->fileFormat;
12091 window->lastModTime = orgWin->lastModTime;
12092 window->fileChanged = orgWin->fileChanged;
12093 @@ -4465,11 +4476,10 @@ static void cloneDocument(WindowInfo *wi
12094 window->autoSave = orgWin->autoSave;
12095 window->saveOldVersion = orgWin->saveOldVersion;
12096 window->wrapMode = orgWin->wrapMode;
12097 SetOverstrike(window, orgWin->overstrike);
12098 window->showMatchingStyle = orgWin->showMatchingStyle;
12099 - window->matchSyntaxBased = orgWin->matchSyntaxBased;
12100 #if 0
12101 window->showStats = orgWin->showStats;
12102 window->showISearchLine = orgWin->showISearchLine;
12103 window->showLineNumbers = orgWin->showLineNumbers;
12104 window->modeMessageDisplayed = orgWin->modeMessageDisplayed;