Added bugs #559902, 561659, 526981, and 582469.
[nedit.git] / source / preferences.c
blobe2ae61e22cf88b9e6beae2cbcaa3561112ad0a54
1 static const char CVSID[] = "$Id: preferences.c,v 1.94 2003/05/25 15:55:36 edg Exp $";
2 /*******************************************************************************
3 * *
4 * preferences.c -- Nirvana Editor preferences processing *
5 * *
6 * Copyright (C) 1999 Mark Edel *
7 * *
8 * This is free software; you can redistribute it and/or modify it under the *
9 * terms of the GNU General Public License as published by the Free Software *
10 * Foundation; either version 2 of the License, or (at your option) any later *
11 * version. *
12 * *
13 * This software is distributed in the hope that it will be useful, but WITHOUT *
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
16 * for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License along with *
19 * software; if not, write to the Free Software Foundation, Inc., 59 Temple *
20 * Place, Suite 330, Boston, MA 02111-1307 USA *
21 * *
22 * Nirvana Text Editor *
23 * April 20, 1993 *
24 * *
25 * Written by Mark Edel *
26 * *
27 *******************************************************************************/
29 #ifdef HAVE_CONFIG_H
30 #include "../config.h"
31 #endif
33 #include "preferences.h"
34 #include "textBuf.h"
35 #include "nedit.h"
36 #include "text.h"
37 #include "search.h"
38 #include "window.h"
39 #include "userCmds.h"
40 #include "highlight.h"
41 #include "highlightData.h"
42 #include "help.h"
43 #include "regularExp.h"
44 #include "smartIndent.h"
45 #include "windowTitle.h"
46 #include "server.h"
47 #include "tags.h"
48 #include "../util/prefFile.h"
49 #include "../util/misc.h"
50 #include "../util/DialogF.h"
51 #include "../util/managedList.h"
52 #include "../util/fontsel.h"
53 #include "../util/fileUtils.h"
54 #include "../util/utils.h"
56 #include <stdlib.h>
57 #include <string.h>
58 #include <stdio.h>
59 #include <ctype.h>
60 #ifdef VMS
61 #include "../util/VMSparam.h"
62 #else
63 #ifndef __MVS__
64 #include <sys/param.h>
65 #endif
66 #include "../util/clearcase.h"
67 #endif /*VMS*/
69 #include <Xm/Xm.h>
70 #include <Xm/SelectioB.h>
71 #include <Xm/Form.h>
72 #include <Xm/List.h>
73 #include <Xm/SeparatoG.h>
74 #include <Xm/LabelG.h>
75 #include <Xm/Label.h>
76 #include <Xm/PushBG.h>
77 #include <Xm/PushB.h>
78 #include <Xm/ToggleBG.h>
79 #include <Xm/ToggleB.h>
80 #include <Xm/RowColumn.h>
81 #include <Xm/CascadeBG.h>
82 #include <Xm/Frame.h>
83 #include <Xm/Text.h>
85 #ifdef HAVE_DEBUG_H
86 #include "../debug.h"
87 #endif
89 #define PREF_FILE_VERSION "5.4"
91 /* New styles added in 5.2 for auto-upgrade */
92 #define ADD_5_2_STYLES " Pointer:#660000:Bold\nRegex:#009944:Bold\nWarning:brown2:Italic"
94 /* maximum number of word delimiters allowed (256 allows whole character set) */
95 #define MAX_WORD_DELIMITERS 256
97 /* maximum number of file extensions allowed in a language mode */
98 #define MAX_FILE_EXTENSIONS 20
100 /* Return values for checkFontStatus */
101 enum fontStatus {GOOD_FONT, BAD_PRIMARY, BAD_FONT, BAD_SIZE, BAD_SPACING};
103 /* enumerated type preference strings
104 ** The order of the elements in this array must be exactly the same
105 ** as the order of the corresponding integers of the enum SearchType
106 ** defined in search.h (!!)
108 static char *SearchMethodStrings[] = {
109 "Literal", "CaseSense", "RegExp",
110 "LiteralWord", "CaseSenseWord", "RegExpNoCase",
111 NULL
114 #ifdef REPLACE_SCOPE
115 /* enumerated default scope for replace dialog if a selection exists when
116 ** the dialog is popped up.
118 static char *ReplaceDefScopeStrings[] = {
119 "Window", "Selection", "Smart", NULL
121 #endif
123 #define N_WRAP_STYLES 3
124 static char *AutoWrapTypes[N_WRAP_STYLES+3] = {"None", "Newline", "Continuous",
125 "True", "False", NULL};
126 #define N_INDENT_STYLES 3
127 static char *AutoIndentTypes[N_INDENT_STYLES+3] = {"None", "Auto",
128 "Smart", "True", "False", NULL};
129 #define N_VIRTKEY_OVERRIDE_MODES 3
130 static char *VirtKeyOverrideModes[N_VIRTKEY_OVERRIDE_MODES+1] = { "Never",
131 "Auto", "Always", NULL};
133 #define N_SHOW_MATCHING_STYLES 3
134 /* For backward compatibility, "False" and "True" are still accepted.
135 They are internally converted to "Off" and "Delimiter" respectively.
136 NOTE: N_SHOW_MATCHING_STYLES must correspond to the number of
137 _real_ matching styles, not counting False & True.
138 False and True should also be the last ones in the list. */
139 static char *ShowMatchingTypes[] = {"Off", "Delimiter", "Range",
140 "False", "True", NULL};
142 /* suplement wrap and indent styles w/ a value meaning "use default" for
143 the override fields in the language modes dialog */
144 #define DEFAULT_WRAP -1
145 #define DEFAULT_INDENT -1
146 #define DEFAULT_TAB_DIST -1
147 #define DEFAULT_EM_TAB_DIST -1
149 /* list of available language modes and language specific preferences */
150 static int NLanguageModes = 0;
151 typedef struct {
152 char *name;
153 int nExtensions;
154 char **extensions;
155 char *recognitionExpr;
156 char *defTipsFile;
157 char *delimiters;
158 int wrapStyle;
159 int indentStyle;
160 int tabDist;
161 int emTabDist;
162 } languageModeRec;
163 static languageModeRec *LanguageModes[MAX_LANGUAGE_MODES];
165 /* Language mode dialog information */
166 static struct {
167 Widget shell;
168 Widget nameW;
169 Widget extW;
170 Widget recogW;
171 Widget defTipsW;
172 Widget delimitW;
173 Widget managedListW;
174 Widget tabW;
175 Widget emTabW;
176 Widget defaultIndentW;
177 Widget noIndentW;
178 Widget autoIndentW;
179 Widget smartIndentW;
180 Widget defaultWrapW;
181 Widget noWrapW;
182 Widget newlineWrapW;
183 Widget contWrapW;
184 languageModeRec **languageModeList;
185 int nLanguageModes;
186 } LMDialog = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
187 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0};
189 /* Font dialog information */
190 typedef struct {
191 Widget shell;
192 Widget primaryW;
193 Widget fillW;
194 Widget italicW;
195 Widget italicErrW;
196 Widget boldW;
197 Widget boldErrW;
198 Widget boldItalicW;
199 Widget boldItalicErrW;
200 WindowInfo *window;
201 int forWindow;
202 } fontDialog;
204 /* Color dialog information */
205 typedef struct {
206 Widget shell;
207 Widget textFgW;
208 Widget textFgErrW;
209 Widget textBgW;
210 Widget textBgErrW;
211 Widget selectFgW;
212 Widget selectFgErrW;
213 Widget selectBgW;
214 Widget selectBgErrW;
215 Widget hiliteFgW;
216 Widget hiliteFgErrW;
217 Widget hiliteBgW;
218 Widget hiliteBgErrW;
219 Widget lineNoFgW;
220 Widget lineNoFgErrW;
221 Widget cursorFgW;
222 Widget cursorFgErrW;
223 WindowInfo *window;
224 } colorDialog;
226 /* Repository for simple preferences settings */
227 static struct prefData {
228 int wrapStyle; /* what kind of wrapping to do */
229 int wrapMargin; /* 0=wrap at window width, other=wrap margin */
230 int autoIndent; /* style for auto-indent */
231 int autoSave; /* whether automatic backup feature is on */
232 int saveOldVersion; /* whether to preserve a copy of last version */
233 int searchDlogs; /* whether to show explanatory search dialogs */
234 int searchWrapBeep; /* 1=beep when search restarts at begin/end */
235 int keepSearchDlogs; /* whether to retain find and replace dialogs */
236 int searchWraps; /* whether to attempt search again if reach bof or eof */
237 int statsLine; /* whether to show the statistics line */
238 int iSearchLine; /* whether to show the incremental search line*/
239 int lineNums; /* whether to show line numbers */
240 int pathInWindowsMenu; /* whether to show path in windows menu */
241 int warnFileMods; /* warn user if files externally modified */
242 int warnRealFileMods; /* only warn if file contents modified */
243 int warnExit; /* whether to warn on exit */
244 int searchMethod; /* initial search method as a text string */
245 #ifdef REPLACE_SCOPE
246 int replaceDefScope; /* default replace scope if selection exists */
247 #endif
248 int textRows; /* initial window height in characters */
249 int textCols; /* initial window width in characters */
250 int tabDist; /* number of characters between tab stops */
251 int emTabDist; /* non-zero tab dist. if emulated tabs are on */
252 int insertTabs; /* whether to use tabs for padding */
253 int showMatchingStyle; /* how to flash matching parenthesis */
254 int matchSyntaxBased; /* use syntax info to match parenthesis */
255 int highlightSyntax; /* whether to highlight syntax by default */
256 int smartTags; /* look for tag in current window first */
257 int alwaysCheckRelativeTagsSpecs; /* for every new opened file of session */
258 int stickyCaseSenseBtn; /* whether Case Word Btn is sticky to Regex Btn */
259 int prefFileRead; /* detects whether a .nedit existed */
260 int backlightChars; /* whether to apply character "backlighting" */
261 char *backlightCharTypes; /* the backlighting color definitions */
262 #ifdef SGI_CUSTOM
263 int shortMenus; /* short menu mode */
264 #endif
265 char fontString[MAX_FONT_LEN]; /* names of fonts for text widget */
266 char boldFontString[MAX_FONT_LEN];
267 char italicFontString[MAX_FONT_LEN];
268 char boldItalicFontString[MAX_FONT_LEN];
269 XmFontList fontList; /* XmFontLists corresp. to above named fonts */
270 XFontStruct *boldFontStruct;
271 XFontStruct *italicFontStruct;
272 XFontStruct *boldItalicFontStruct;
273 int repositionDialogs; /* w. to reposition dialogs under the pointer */
274 int sortOpenPrevMenu; /* whether to sort the "Open Previous" menu */
275 int appendLF; /* Whether to append LF at the end of each file */
276 int mapDelete; /* whether to map delete to backspace */
277 int stdOpenDialog; /* w. to retain redundant text field in Open */
278 char tagFile[MAXPATHLEN]; /* name of tags file to look for at startup */
279 int maxPrevOpenFiles; /* limit to size of Open Previous menu */
280 int typingHidesPointer; /* hide mouse pointer when typing */
281 char delimiters[MAX_WORD_DELIMITERS]; /* punctuation characters */
282 char shell[MAXPATHLEN]; /* shell to use for executing commands */
283 char geometry[MAX_GEOM_STRING_LEN]; /* per-application geometry string,
284 only for the clueless */
285 char serverName[MAXPATHLEN];/* server name for multiple servers per disp. */
286 char bgMenuBtn[MAX_ACCEL_LEN]; /* X event description for triggering
287 posting of background menu */
288 char fileVersion[6]; /* Version of nedit which wrote the .nedit
289 file we're reading */
290 int findReplaceUsesSelection; /* whether the find replace dialog is automatically
291 loaded with the primary selection */
292 int virtKeyOverride; /* Override Motif default virtual key bindings
293 never, if invalid, or always */
294 char titleFormat[MAX_TITLE_FORMAT_LEN];
295 char helpFontNames[NUM_HELP_FONTS][MAX_FONT_LEN];/* fonts for help system */
296 char helpLinkColor[MAX_COLOR_LEN]; /* Color for hyperlinks in the help system */
297 char colorNames[NUM_COLORS][MAX_COLOR_LEN];
298 int undoModifiesSelection;
299 } PrefData;
301 /* Temporary storage for preferences strings which are discarded after being
302 read */
303 static struct {
304 char *shellCmds;
305 char *macroCmds;
306 char *bgMenuCmds;
307 char *highlight;
308 char *language;
309 char *styles;
310 char *smartIndent;
311 char *smartIndentCommon;
312 } TempStringPrefs;
314 /* preference descriptions for SavePreferences and RestorePreferences. */
315 static PrefDescripRec PrefDescrip[] = {
316 {"fileVersion", "FileVersion" , PREF_STRING, "", PrefData.fileVersion,
317 (void *)sizeof(PrefData.fileVersion), True},
318 #ifndef VMS
319 #ifdef linux
320 {"shellCommands", "ShellCommands", PREF_ALLOC_STRING, "spell:Alt+B:s:EX:\n\
321 cat>spellTmp; xterm -e ispell -x spellTmp; cat spellTmp; rm spellTmp\n\
322 wc::w:ED:\nset wc=`wc`; echo $wc[1] \"lines,\" $wc[2] \"words,\" $wc[3] \"characters\"\n\
323 sort::o:EX:\nsort\nnumber lines::n:AW:\nnl -ba\nmake:Alt+Z:m:W:\nmake\n\
324 expand::p:EX:\nexpand\nunexpand::u:EX:\nunexpand\n",
325 &TempStringPrefs.shellCmds, NULL, True},
326 #elif __FreeBSD__
327 {"shellCommands", "ShellCommands", PREF_ALLOC_STRING, "spell:Alt+B:s:EX:\n\
328 cat>spellTmp; xterm -e ispell -x spellTmp; cat spellTmp; rm spellTmp\n\
329 wc::w:ED:\nset wc=`wc`; echo $wc[1] \"words,\" $wc[2] \"lines,\" $wc[3] \"characters\"\n\
330 sort::o:EX:\nsort\nnumber lines::n:AW:\npr -tn\nmake:Alt+Z:m:W:\nmake\n\
331 expand::p:EX:\nexpand\nunexpand::u:EX:\nunexpand\n",
332 &TempStringPrefs.shellCmds, NULL, True},
333 #else
334 {"shellCommands", "ShellCommands", PREF_ALLOC_STRING, "spell:Alt+B:s:ED:\n\
335 (cat;echo \"\") | spell\nwc::w:ED:\nset wc=`wc`; echo $wc[1] \"lines,\" $wc[2] \"words,\" $wc[3] \"characters\"\n\
336 \nsort::o:EX:\nsort\nnumber lines::n:AW:\nnl -ba\nmake:Alt+Z:m:W:\nmake\n\
337 expand::p:EX:\nexpand\nunexpand::u:EX:\nunexpand\n",
338 &TempStringPrefs.shellCmds, NULL, True},
339 #endif /* linux, __FreeBSD__ */
340 #endif /* VMS */
341 {"macroCommands", "MacroCommands", PREF_ALLOC_STRING,
342 "Complete Word:Alt+D::: {\n\
343 # Tuning parameters\n\
344 ScanDistance = 200\n\
346 # Search back to a word boundary to find the word to complete\n\
347 startScan = max(0, $cursor - ScanDistance)\n\
348 endScan = min($text_length, $cursor + ScanDistance)\n\
349 scanString = get_range(startScan, endScan)\n\
350 keyEnd = $cursor-startScan\n\
351 keyStart = search_string(scanString, \"<\", keyEnd, \"backward\", \"regex\")\n\
352 if (keyStart == -1)\n\
353 return\n\
354 keyString = \"<\" substring(scanString, keyStart, keyEnd)\n\
356 # search both forward and backward from the cursor position. Note that\n\
357 # using a regex search can lead to incorrect results if any of the special\n\
358 # regex characters is encountered, which is not considered a delimiter\n\
359 backwardSearchResult = search_string(scanString, keyString, keyStart-1, \\\n\
360 \"backward\", \"regex\")\n\
361 forwardSearchResult = search_string(scanString, keyString, keyEnd, \"regex\")\n\
362 if (backwardSearchResult == -1 && forwardSearchResult == -1) {\n\
363 beep()\n\
364 return\n\
365 }\n\
367 # if only one direction matched, use that, otherwise use the nearest\n\
368 if (backwardSearchResult == -1)\n\
369 matchStart = forwardSearchResult\n\
370 else if (forwardSearchResult == -1)\n\
371 matchStart = backwardSearchResult\n\
372 else {\n\
373 if (keyStart - backwardSearchResult <= forwardSearchResult - keyEnd)\n\
374 matchStart = backwardSearchResult\n\
375 else\n\
376 matchStart = forwardSearchResult\n\
377 }\n\
379 # find the complete word\n\
380 matchEnd = search_string(scanString, \">\", matchStart, \"regex\")\n\
381 completedWord = substring(scanString, matchStart, matchEnd)\n\
383 # replace it in the window\n\
384 replace_range(startScan + keyStart, $cursor, completedWord)\n\
385 }\n\
386 Fill Sel. w/Char:::R: {\n\
387 if ($selection_start == -1) {\n\
388 beep()\n\
389 return\n\
390 }\n\
392 # Ask the user what character to fill with\n\
393 fillChar = string_dialog(\"Fill selection with what character?\", \"OK\", \"Cancel\")\n\
394 if ($string_dialog_button == 2 || $string_dialog_button == 0)\n\
395 return\n\
397 # Count the number of lines in the selection\n\
398 nLines = 0\n\
399 for (i=$selection_start; i<$selection_end; i++)\n\
400 if (get_character(i) == \"\\n\")\n\
401 nLines++\n\
403 # Create the fill text\n\
404 rectangular = $selection_left != -1\n\
405 line = \"\"\n\
406 fillText = \"\"\n\
407 if (rectangular) {\n\
408 for (i=0; i<$selection_right-$selection_left; i++)\n\
409 line = line fillChar\n\
410 for (i=0; i<nLines; i++)\n\
411 fillText = fillText line \"\\n\"\n\
412 fillText = fillText line\n\
413 } else {\n\
414 if (nLines == 0) {\n\
415 for (i=$selection_start; i<$selection_end; i++)\n\
416 fillText = fillText fillChar\n\
417 } else {\n\
418 startIndent = 0\n\
419 for (i=$selection_start-1; i>=0 && get_character(i)!=\"\\n\"; i--)\n\
420 startIndent++\n\
421 for (i=0; i<$wrap_margin-startIndent; i++)\n\
422 fillText = fillText fillChar\n\
423 fillText = fillText \"\\n\"\n\
424 for (i=0; i<$wrap_margin; i++)\n\
425 line = line fillChar\n\
426 for (i=0; i<nLines-1; i++)\n\
427 fillText = fillText line \"\\n\"\n\
428 for (i=$selection_end-1; i>=$selection_start && get_character(i)!=\"\\n\"; \\\n\
429 i--)\n\
430 fillText = fillText fillChar\n\
431 }\n\
432 }\n\
434 # Replace the selection with the fill text\n\
435 replace_selection(fillText)\n\
436 }\n\
437 Quote Mail Reply:::: {\n\
438 if ($selection_start == -1)\n\
439 replace_all(\"^.*$\", \"\\\\> &\", \"regex\")\n\
440 else\n\
441 replace_in_selection(\"^.*$\", \"\\\\> &\", \"regex\")\n\
442 }\n\
443 Unquote Mail Reply:::: {\n\
444 if ($selection_start == -1)\n\
445 replace_all(\"(^\\\\> )(.*)$\", \"\\\\2\", \"regex\")\n\
446 else\n\
447 replace_in_selection(\"(^\\\\> )(.*)$\", \"\\\\2\", \"regex\")\n\
448 }\n\
449 Comments>/* Comment */@C@C++@Java@CSS@JavaScript@Lex:::R: {\n\
450 selStart = $selection_start\n\
451 selEnd = $selection_end\n\
452 replace_range(selStart, selEnd, \"/* \" get_selection() \" */\")\n\
453 select(selStart, selEnd + 6)\n\
454 }\n\
455 Comments>/* Uncomment */@C@C++@Java@CSS@JavaScript@Lex:::R: {\n\
456 sel = get_selection()\n\
457 selStart = $selection_start\n\
458 selEnd = $selection_end\n\
459 commentStart = search_string(sel, \"/*\", 0)\n\
460 if (substring(sel, commentStart + 2, commentStart + 3) == \" \")\n\
461 keepStart = commentStart + 3\n\
462 else\n\
463 keepStart = commentStart + 2\n\
464 keepEnd = search_string(sel, \"*/\", length(sel), \"backward\")\n\
465 commentEnd = keepEnd + 2\n\
466 if (substring(sel, keepEnd - 1, keepEnd == \" \"))\n\
467 keepEnd = keepEnd - 1\n\
468 replace_range(selStart + commentStart, selStart + commentEnd, \\\n\
469 substring(sel, keepStart, keepEnd))\n\
470 select(selStart, selEnd - (keepStart-commentStart) - \\\n\
471 (commentEnd - keepEnd))\n\
472 }\n\
473 Comments>// Comment@C@C++@Java@JavaScript:::R: {\n\
474 replace_in_selection(\"^.*$\", \"// &\", \"regex\")\n\
475 }\n\
476 Comments>// Uncomment@C@C++@Java@JavaScript:::R: {\n\
477 replace_in_selection(\"(^[ \\\\t]*// ?)(.*)$\", \"\\\\2\", \"regex\")\n\
478 }\n\
479 Comments># Comment@Perl@Sh Ksh Bash@NEdit Macro@Makefile@Awk@Csh@Python@Tcl:::R: {\n\
480 replace_in_selection(\"^.*$\", \"#&\", \"regex\")\n\
481 }\n\
482 Comments># Uncomment@Perl@Sh Ksh Bash@NEdit Macro@Makefile@Awk@Csh@Python@Tcl:::R: {\n\
483 replace_in_selection(\"(^[ \\\\t]*#)(.*)$\", \"\\\\2\", \"regex\")\n\
484 }\n\
485 Comments>-- Comment@SQL:::R: {\n\
486 replace_in_selection(\"^.*$\", \"--&\", \"regex\")\n\
487 }\n\
488 Comments>-- Uncomment@SQL:::R: {\n\
489 replace_in_selection(\"(^[ \\\\t]*--)(.*)$\", \"\\\\2\", \"regex\")\n\
490 }\n\
491 Comments>! Comment@X Resources:::R: {\n\
492 replace_in_selection(\"^.*$\", \"!&\", \"regex\")\n\
493 }\n\
494 Comments>! Uncomment@X Resources:::R: {\n\
495 replace_in_selection(\"(^[ \\\\t]*!)(.*)$\", \"\\\\2\", \"regex\")\n\
496 }\n\
497 Comments>Bar Comment@C:::R: {\n\
498 if ($selection_left != -1) {\n\
499 dialog(\"Selection must not be rectangular\")\n\
500 return\n\
501 }\n\
502 start = $selection_start\n\
503 end = $selection_end-1\n\
504 origText = get_range($selection_start, $selection_end-1)\n\
505 newText = \"/*\\n\" replace_in_string(get_range(start, end), \\\n\
506 \"^\", \" * \", \"regex\") \"\\n */\\n\"\n\
507 replace_selection(newText)\n\
508 select(start, start + length(newText))\n\
509 }\n\
510 Comments>Bar Uncomment@C:::R: {\n\
511 selStart = $selection_start\n\
512 selEnd = $selection_end\n\
513 newText = get_range(selStart+3, selEnd-4)\n\
514 newText = replace_in_string(newText, \"^ \\\\* \", \"\", \"regex\")\n\
515 replace_range(selStart, selEnd, newText)\n\
516 select(selStart, selStart + length(newText))\n\
517 }\n\
518 Make C Prototypes@C@C++:::: {\n\
519 if ($selection_start == -1) {\n\
520 start = 0\n\
521 end = $text_length\n\
522 } else {\n\
523 start = $selection_start\n\
524 end = $selection_end\n\
525 }\n\
526 string = get_range(start, end)\n\
527 nDefs = 0\n\
528 searchPos = 0\n\
529 prototypes = \"\"\n\
530 staticPrototypes = \"\"\n\
531 for (;;) {\n\
532 headerStart = search_string(string, \\\n\
533 \"^[a-zA-Z]([^;#\\\"'{}=><!/]|\\n)*\\\\)[ \\t]*\\n?[ \\t]*\\\\{\", \\\n\
534 searchPos, \"regex\")\n\
535 if (headerStart == -1)\n\
536 break\n\
537 headerEnd = search_string(string, \")\", $search_end,\"backward\") + 1\n\
538 prototype = substring(string, headerStart, headerEnd) \";\\n\"\n\
539 if (substring(string, headerStart, headerStart+6) == \"static\")\n\
540 staticPrototypes = staticPrototypes prototype\n\
541 else\n\
542 prototypes = prototypes prototype\n\
543 searchPos = headerEnd\n\
544 nDefs++\n\
545 }\n\
546 if (nDefs == 0) {\n\
547 dialog(\"No function declarations found\")\n\
548 return\n\
549 }\n\
550 new()\n\
551 focus_window(\"last\")\n\
552 replace_range(0, 0, prototypes staticPrototypes)\n\
553 }", &TempStringPrefs.macroCmds, NULL, True},
554 {"bgMenuCommands", "BGMenuCommands", PREF_ALLOC_STRING,
555 "Undo:::: {\nundo()\n}\n\
556 Redo:::: {\nredo()\n}\n\
557 Cut:::R: {\ncut_clipboard()\n}\n\
558 Copy:::R: {\ncopy_clipboard()\n}\n\
559 Paste:::: {\npaste_clipboard()\n}", &TempStringPrefs.bgMenuCmds,
560 NULL, True},
561 #ifdef VMS
562 /* The VAX compiler can't compile Java-Script's definition in highlightData.c */
563 {"highlightPatterns", "HighlightPatterns", PREF_ALLOC_STRING,
564 "Ada:Default\n\
565 Awk:Default\n\
566 C++:Default\n\
567 C:Default\n\
568 CSS:Default\n\
569 Csh:Default\n\
570 Fortran:Default\n\
571 Java:Default\n\
572 LaTeX:Default\n\
573 Lex:Default\n\
574 Makefile:Default\n\
575 Matlab:Default\n\
576 NEdit Macro:Default\n\
577 Pascal:Default\n\
578 Perl:Default\n\
579 PostScript:Default\n\
580 Python:Default\n\
581 Regex:Default\n\
582 SGML HTML:Default\n\
583 SQL:Default\n\
584 Sh Ksh Bash:Default\n\
585 Tcl:Default\n\
586 VHDL:Default\n\
587 Verilog:Default\n\
588 XML:Default\n\
589 X Resources:Default\n\
590 Yacc:Default",
591 &TempStringPrefs.highlight, NULL, True},
592 {"languageModes", "LanguageModes", PREF_ALLOC_STRING,
593 #else
594 {"highlightPatterns", "HighlightPatterns", PREF_ALLOC_STRING,
595 "Ada:Default\n\
596 Awk:Default\n\
597 C++:Default\n\
598 C:Default\n\
599 CSS:Default\n\
600 Csh:Default\n\
601 Fortran:Default\n\
602 Java:Default\n\
603 JavaScript:Default\n\
604 LaTeX:Default\n\
605 Lex:Default\n\
606 Makefile:Default\n\
607 Matlab:Default\n\
608 NEdit Macro:Default\n\
609 Pascal:Default\n\
610 Perl:Default\n\
611 PostScript:Default\n\
612 Python:Default\n\
613 Regex:Default\n\
614 SGML HTML:Default\n\
615 SQL:Default\n\
616 Sh Ksh Bash:Default\n\
617 Tcl:Default\n\
618 VHDL:Default\n\
619 Verilog:Default\n\
620 XML:Default\n\
621 X Resources:Default\n\
622 Yacc:Default",
623 &TempStringPrefs.highlight, NULL, True},
624 {"languageModes", "LanguageModes", PREF_ALLOC_STRING,
625 #endif /*VMS*/
626 #ifdef VMS
627 "Ada:.ADA .AD .ADS .ADB .A:::::::\n\
628 Awk:.AWK:::::::\n\
629 C++:.CC .HH .C .H .I .CXX .HXX .CPP::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\":\n\
630 C:.C .H::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\":\n\
631 CSS:CSS::Auto:None:::\".,/\\`'!|@#%^&*()=+{}[]\"\":;<>?~\":\n\
632 Csh:.csh .cshrc .login .logout:\"^[ \\t]*#[ \\t]*![ \\t]*/bin/csh\"::::::\n\
633 Fortran:.F .F77 .FOR:::::::\n\
634 Java:.JAVA:::::::\n\
635 LaTeX:.TEX .STY .CLS .DTX .INS:::::::\n\
636 Lex:.lex:::::::\n\
637 Makefile:MAKEFILE:::None:8:8::\n\
638 Matlab:.m .oct .sci:::::::\n\
639 NEdit Macro:.NM .NEDITMACRO:::::::\n\
640 Pascal:.PAS .P .INT:::::::\n\
641 Perl:.PL .PM .P5:\"^[ \\t]*#[ \\t]*!.*perl\":Auto:None:::\".,/\\\\`'!$@#%^&*()-=+{}[]\"\":;<>?~|\":\n\
642 PostScript:.ps .PS .eps .EPS .epsf .epsi:\"^%!\":::::\"/%(){}[]<>\":\n\
643 Python:.PY:\"^#!.*python\":Auto:None:::\"!\"\"#$%&'()*+,-./:;<=>?@[\\\\]^`{|}~\":\n\
644 Regex:.reg .regex:\"\\(\\?[:#=!iInN].+\\)\":None:Continuous::::\n\
645 SGML HTML:.sgml .sgm .html .htm:\"\\<[Hh][Tt][Mm][Ll]\\>\"::::::\n\
646 SQL:.sql:::::::\n\
647 Sh Ksh Bash:.sh .bash .ksh .profile .bashrc .bash_logout .bash_login .bash_profile:\"^[ \\t]*#[ \\t]*![ \\t]*/.*bin/(sh|ksh|bash)\"::::::\n\
648 Tcl:.TCL::Smart:None::::\n\
649 VHDL:.VHD .VHDL .VDL:::::::\n\
650 Verilog:.V:::::::\n\
651 XML:.xml .xsl .dtd:\"\\<(?i\\?xml|!doctype)\"::None:::\"<>/=\"\"'()+*?|\":\n\
652 X Resources:.XRESOURCES .XDEFAULTS .NEDIT:\"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults\"::::::\n\
653 Yacc:.Y::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\":",
654 #else
655 "Ada:.ada .ad .ads .adb .a:::::::\n\
656 Awk:.awk:::::::\n\
657 C++:.cc .hh .C .H .i .cxx .hxx .cpp::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\":\n\
658 C:.c .h::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\":\n\
659 CSS:css::Auto:None:::\".,/\\`'!|@#%^&*()=+{}[]\"\":;<>?~\":\n\
660 Csh:.csh .cshrc .login .logout:\"^[ \\t]*#[ \\t]*![ \\t]*/bin/csh\"::::::\n\
661 Fortran:.f .f77 .for:::::::\n\
662 Java:.java:::::::\n\
663 JavaScript:.js:::::::\n\
664 LaTeX:.tex .sty .cls .dtx .ins:::::::\n\
665 Lex:.lex:::::::\n\
666 Makefile:Makefile makefile .gmk:::None:8:8::\n\
667 Matlab:.m .oct .sci:::::::\n\
668 NEdit Macro:.nm .neditmacro:::::::\n\
669 Pascal:.pas .p .int:::::::\n\
670 Perl:.pl .pm .p5 .PL:\"^[ \\t]*#[ \\t]*!.*perl\":Auto:None:::\".,/\\\\`'!$@#%^&*()-=+{}[]\"\":;<>?~|\":\n\
671 PostScript:.ps .eps .epsf .epsi:\"^%!\":::::\"/%(){}[]<>\":\n\
672 Python:.py:\"^#!.*python\":Auto:None:::\"!\"\"#$%&'()*+,-./:;<=>?@[\\\\]^`{|}~\":\n\
673 Regex:.reg .regex:\"\\(\\?[:#=!iInN].+\\)\":None:Continuous::::\n\
674 SGML HTML:.sgml .sgm .html .htm:\"\\<[Hh][Tt][Mm][Ll]\\>\"::::::\n\
675 SQL:.sql:::::::\n\
676 Sh Ksh Bash:.sh .bash .ksh .profile .bashrc .bash_logout .bash_login .bash_profile:\"^[ \\t]*#[ \\t]*![ \\t]*/.*bin/(sh|ksh|bash)\"::::::\n\
677 Tcl:.tcl .tk .itcl .itk::Smart:None::::\n\
678 VHDL:.vhd .vhdl .vdl:::::::\n\
679 Verilog:.v:::::::\n\
680 XML:.xml .xsl .dtd:\"\\<(?i\\?xml|!doctype)\"::None:::\"<>/=\"\"'()+*?|\":\n\
681 X Resources:.Xresources .Xdefaults .nedit:\"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults\"::::::\n\
682 Yacc:.y::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\":",
683 #endif
684 &TempStringPrefs.language, NULL, True},
685 {"styles", "Styles", PREF_ALLOC_STRING, "Plain:black:Plain\n\
686 Comment:gray20:Italic\n\
687 Keyword:black:Bold\n\
688 Storage Type:brown:Bold\n\
689 Storage Type1:saddle brown:Bold\n\
690 String:darkGreen:Plain\n\
691 String1:SeaGreen:Plain\n\
692 String2:darkGreen:Bold\n\
693 Preprocessor:RoyalBlue4:Plain\n\
694 Preprocessor1:blue:Plain\n\
695 Character Const:darkGreen:Plain\n\
696 Numeric Const:darkGreen:Plain\n\
697 Identifier:brown:Plain\n\
698 Identifier1:RoyalBlue4:Plain\n\
699 Identifier2:SteelBlue:Plain\n\
700 Subroutine:brown:Plain\n\
701 Subroutine1:chocolate:Plain\n\
702 Ada Attributes:plum:Bold\n\
703 Label:red:Italic\n\
704 Flag:red:Bold\n\
705 Text Comment:SteelBlue4:Italic\n\
706 Text Key:VioletRed4:Bold\n\
707 Text Key1:VioletRed4:Plain\n\
708 Text Arg:RoyalBlue4:Bold\n\
709 Text Arg1:SteelBlue4:Bold\n\
710 Text Arg2:RoyalBlue4:Plain\n\
711 Text Escape:gray30:Bold\n\
712 LaTeX Math:darkGreen:Plain\n"
713 ADD_5_2_STYLES,
714 &TempStringPrefs.styles, NULL, True},
715 {"smartIndentInit", "SmartIndentInit", PREF_ALLOC_STRING,
716 "C:Default\n\
717 C++:Default\n\
718 Python:Default\n\
719 Matlab:Default", &TempStringPrefs.smartIndent, NULL, True},
720 {"smartIndentInitCommon", "SmartIndentInitCommon", PREF_ALLOC_STRING,
721 "Default", &TempStringPrefs.smartIndentCommon, NULL, True},
722 {"autoWrap", "AutoWrap", PREF_ENUM, "Newline",
723 &PrefData.wrapStyle, AutoWrapTypes, True},
724 {"wrapMargin", "WrapMargin", PREF_INT, "0",
725 &PrefData.wrapMargin, NULL, True},
726 {"autoIndent", "AutoIndent", PREF_ENUM, "Auto",
727 &PrefData.autoIndent, AutoIndentTypes, True},
728 {"autoSave", "AutoSave", PREF_BOOLEAN, "True",
729 &PrefData.autoSave, NULL, True},
730 {"saveOldVersion", "SaveOldVersion", PREF_BOOLEAN, "False",
731 &PrefData.saveOldVersion, NULL, True},
732 {"showMatching", "ShowMatching", PREF_ENUM, "Delimiter",
733 &PrefData.showMatchingStyle, ShowMatchingTypes, True},
734 {"matchSyntaxBased", "MatchSyntaxBased", PREF_BOOLEAN, "True",
735 &PrefData.matchSyntaxBased, NULL, True},
736 {"highlightSyntax", "HighlightSyntax", PREF_BOOLEAN, "True",
737 &PrefData.highlightSyntax, NULL, True},
738 {"backlightChars", "BacklightChars", PREF_BOOLEAN, "False",
739 &PrefData.backlightChars, NULL, True},
740 {"backlightCharTypes", "BacklightCharTypes", PREF_ALLOC_STRING,
741 "0-8,10-31,127:red;9:#dedede;32-126,160-255:#f0f0f0;128-159:orange",
742 /* gray87 gray94 */
743 &PrefData.backlightCharTypes, NULL, False},
744 {"searchDialogs", "SearchDialogs", PREF_BOOLEAN, "False",
745 &PrefData.searchDlogs, NULL, True},
746 {"beepOnSearchWrap", "BeepOnSearchWrap", PREF_BOOLEAN, "False",
747 &PrefData.searchWrapBeep, NULL, True},
748 {"retainSearchDialogs", "RetainSearchDialogs", PREF_BOOLEAN, "False",
749 &PrefData.keepSearchDlogs, NULL, True},
750 {"searchWraps", "SearchWraps", PREF_BOOLEAN, "True",
751 &PrefData.searchWraps, NULL, True},
752 {"stickyCaseSenseButton", "StickyCaseSenseButton", PREF_BOOLEAN, "True",
753 &PrefData.stickyCaseSenseBtn, NULL, True},
754 #if XmVersion < 1002 /* Flashing is annoying in 1.1 versions */
755 {"repositionDialogs", "RepositionDialogs", PREF_BOOLEAN, "False",
756 &PrefData.repositionDialogs, NULL, True},
757 #else
758 {"repositionDialogs", "RepositionDialogs", PREF_BOOLEAN, "True",
759 &PrefData.repositionDialogs, NULL, True},
760 #endif
761 {"appendLF", "AppendLF", PREF_BOOLEAN, "True",
762 &PrefData.appendLF, NULL, True},
763 {"sortOpenPrevMenu", "SortOpenPrevMenu", PREF_BOOLEAN, "True",
764 &PrefData.sortOpenPrevMenu, NULL, True},
765 {"statisticsLine", "StatisticsLine", PREF_BOOLEAN, "False",
766 &PrefData.statsLine, NULL, True},
767 {"iSearchLine", "ISearchLine", PREF_BOOLEAN, "False",
768 &PrefData.iSearchLine, NULL, True},
769 {"lineNumbers", "LineNumbers", PREF_BOOLEAN, "False",
770 &PrefData.lineNums, NULL, True},
771 {"pathInWindowsMenu", "PathInWindowsMenu", PREF_BOOLEAN, "True",
772 &PrefData.pathInWindowsMenu, NULL, True},
773 {"warnFileMods", "WarnFileMods", PREF_BOOLEAN, "True",
774 &PrefData.warnFileMods, NULL, True},
775 {"warnRealFileMods", "WarnRealFileMods", PREF_BOOLEAN, "True",
776 &PrefData.warnRealFileMods, NULL, True},
777 {"warnExit", "WarnExit", PREF_BOOLEAN, "True",
778 &PrefData.warnExit, NULL, True},
779 {"searchMethod", "SearchMethod", PREF_ENUM, "Literal",
780 &PrefData.searchMethod, SearchMethodStrings, True},
781 #ifdef REPLACE_SCOPE
782 {"replaceDefaultScope", "ReplaceDefaultAllScope", PREF_ENUM, "Smart",
783 &PrefData.replaceDefScope, ReplaceDefScopeStrings, True},
784 #endif
785 {"textRows", "TextRows", PREF_INT, "24",
786 &PrefData.textRows, NULL, True},
787 {"textCols", "TextCols", PREF_INT, "80",
788 &PrefData.textCols, NULL, True},
789 {"tabDistance", "TabDistance", PREF_INT, "8",
790 &PrefData.tabDist, NULL, True},
791 {"emulateTabs", "EmulateTabs", PREF_INT, "0",
792 &PrefData.emTabDist, NULL, True},
793 {"insertTabs", "InsertTabs", PREF_BOOLEAN, "True",
794 &PrefData.insertTabs, NULL, True},
795 {"textFont", "TextFont", PREF_STRING,
796 "-*-courier-medium-r-normal--*-120-*-*-*-iso8859-1",
797 PrefData.fontString, (void *)sizeof(PrefData.fontString), True},
798 {"boldHighlightFont", "BoldHighlightFont", PREF_STRING,
799 "-*-courier-bold-r-normal--*-120-*-*-*-iso8859-1",
800 PrefData.boldFontString, (void *)sizeof(PrefData.boldFontString), True},
801 {"italicHighlightFont", "ItalicHighlightFont", PREF_STRING,
802 "-*-courier-medium-o-normal--*-120-*-*-*-iso8859-1",
803 PrefData.italicFontString,
804 (void *)sizeof(PrefData.italicFontString), True},
805 {"boldItalicHighlightFont", "BoldItalicHighlightFont", PREF_STRING,
806 "-*-courier-bold-o-normal--*-120-*-*-*-iso8859-1",
807 PrefData.boldItalicFontString,
808 (void *)sizeof(PrefData.boldItalicFontString), True},
809 {"helpFont", "helpFont", PREF_STRING,
810 "-*-helvetica-medium-r-normal--*-120-*-*-*-iso8859-1",
811 PrefData.helpFontNames[HELP_FONT],
812 (void *)sizeof(PrefData.helpFontNames[HELP_FONT]), False},
813 {"boldHelpFont", "BoldHelpFont", PREF_STRING,
814 "-*-helvetica-bold-r-normal--*-120-*-*-*-iso8859-1",
815 PrefData.helpFontNames[BOLD_HELP_FONT],
816 (void *)sizeof(PrefData.helpFontNames[BOLD_HELP_FONT]), False},
817 {"italicHelpFont", "ItalicHelpFont", PREF_STRING,
818 "-*-helvetica-medium-o-normal--*-120-*-*-*-iso8859-1",
819 PrefData.helpFontNames[ITALIC_HELP_FONT],
820 (void *)sizeof(PrefData.helpFontNames[ITALIC_HELP_FONT]), False},
821 {"boldItalicHelpFont", "BoldItalicHelpFont", PREF_STRING,
822 "-*-helvetica-bold-o-normal--*-120-*-*-*-iso8859-1",
823 PrefData.helpFontNames[BOLD_ITALIC_HELP_FONT],
824 (void *)sizeof(PrefData.helpFontNames[BOLD_ITALIC_HELP_FONT]), False},
825 {"fixedHelpFont", "fixedHelpFont", PREF_STRING,
826 "-*-courier-medium-r-normal--*-120-*-*-*-iso8859-1",
827 PrefData.helpFontNames[FIXED_HELP_FONT],
828 (void *)sizeof(PrefData.helpFontNames[FIXED_HELP_FONT]), False},
829 {"boldFixedHelpFont", "BoldFixedHelpFont", PREF_STRING,
830 "-*-courier-bold-r-normal--*-120-*-*-*-iso8859-1",
831 PrefData.helpFontNames[BOLD_FIXED_HELP_FONT],
832 (void *)sizeof(PrefData.helpFontNames[BOLD_FIXED_HELP_FONT]), False},
833 {"italicFixedHelpFont", "ItalicFixedHelpFont", PREF_STRING,
834 "-*-courier-medium-o-normal--*-120-*-*-*-iso8859-1",
835 PrefData.helpFontNames[ITALIC_FIXED_HELP_FONT],
836 (void *)sizeof(PrefData.helpFontNames[ITALIC_FIXED_HELP_FONT]), False},
837 {"boldItalicFixedHelpFont", "BoldItalicFixedHelpFont", PREF_STRING,
838 "-*-courier-bold-o-normal--*-120-*-*-*-iso8859-1",
839 PrefData.helpFontNames[BOLD_ITALIC_FIXED_HELP_FONT],
840 (void *)sizeof(PrefData.helpFontNames[BOLD_ITALIC_FIXED_HELP_FONT]), False},
841 {"helpLinkFont", "helpLinkFont", PREF_STRING,
842 "-*-helvetica-medium-r-normal--*-120-*-*-*-iso8859-1",
843 PrefData.helpFontNames[HELP_LINK_FONT],
844 (void *)sizeof(PrefData.helpFontNames[HELP_LINK_FONT]), False},
845 {"h1HelpFont", "H1HelpFont", PREF_STRING,
846 "-*-helvetica-bold-r-normal--*-140-*-*-*-iso8859-1",
847 PrefData.helpFontNames[H1_HELP_FONT],
848 (void *)sizeof(PrefData.helpFontNames[H1_HELP_FONT]), False},
849 {"h2HelpFont", "H2HelpFont", PREF_STRING,
850 "-*-helvetica-bold-o-normal--*-120-*-*-*-iso8859-1",
851 PrefData.helpFontNames[H2_HELP_FONT],
852 (void *)sizeof(PrefData.helpFontNames[H2_HELP_FONT]), False},
853 {"h3HelpFont", "H3HelpFont", PREF_STRING,
854 "-*-courier-bold-r-normal--*-120-*-*-*-iso8859-1",
855 PrefData.helpFontNames[H3_HELP_FONT],
856 (void *)sizeof(PrefData.helpFontNames[H3_HELP_FONT]), False},
857 {"helpLinkColor", "helpLinkColor", PREF_STRING, "#009900",
858 PrefData.helpLinkColor,
859 (void *)sizeof(PrefData.helpLinkColor), False},
861 {"textFgColor", "textFgColor", PREF_STRING, NEDIT_DEFAULT_FG,
862 PrefData.colorNames[TEXT_FG_COLOR],
863 (void *)sizeof(PrefData.colorNames[TEXT_FG_COLOR]), True},
864 {"textBgColor", "textBgColor", PREF_STRING, NEDIT_DEFAULT_TEXT_BG,
865 PrefData.colorNames[TEXT_BG_COLOR],
866 (void *)sizeof(PrefData.colorNames[TEXT_BG_COLOR]), True},
867 {"selectFgColor", "selectFgColor", PREF_STRING, NEDIT_DEFAULT_SEL_FG,
868 PrefData.colorNames[SELECT_FG_COLOR],
869 (void *)sizeof(PrefData.colorNames[SELECT_FG_COLOR]), True},
870 {"selectBgColor", "selectBgColor", PREF_STRING, NEDIT_DEFAULT_SEL_BG,
871 PrefData.colorNames[SELECT_BG_COLOR],
872 (void *)sizeof(PrefData.colorNames[SELECT_BG_COLOR]), True},
873 {"hiliteFgColor", "hiliteFgColor", PREF_STRING, NEDIT_DEFAULT_HI_FG,
874 PrefData.colorNames[HILITE_FG_COLOR],
875 (void *)sizeof(PrefData.colorNames[HILITE_FG_COLOR]), True},
876 {"hiliteBgColor", "hiliteBgColor", PREF_STRING, NEDIT_DEFAULT_HI_BG,
877 PrefData.colorNames[HILITE_BG_COLOR],
878 (void *)sizeof(PrefData.colorNames[HILITE_BG_COLOR]), True},
879 {"lineNoFgColor", "lineNoFgColor", PREF_STRING, NEDIT_DEFAULT_LINENO_FG,
880 PrefData.colorNames[LINENO_FG_COLOR],
881 (void *)sizeof(PrefData.colorNames[LINENO_FG_COLOR]), True},
882 {"cursorFgColor", "cursorFgColor", PREF_STRING, NEDIT_DEFAULT_CURSOR_FG,
883 PrefData.colorNames[CURSOR_FG_COLOR],
884 (void *)sizeof(PrefData.colorNames[CURSOR_FG_COLOR]), True},
886 {"shell", "Shell", PREF_STRING,
887 #if defined(__MVS__) || defined(__EMX__)
888 "/bin/sh",
889 #else
890 "/bin/csh",
891 #endif
892 PrefData.shell, (void *)sizeof(PrefData.shell), False},
893 {"geometry", "Geometry", PREF_STRING, "",
894 PrefData.geometry, (void *)sizeof(PrefData.geometry), False},
895 {"remapDeleteKey", "RemapDeleteKey", PREF_BOOLEAN, "False",
896 &PrefData.mapDelete, NULL, False},
897 {"stdOpenDialog", "StdOpenDialog", PREF_BOOLEAN, "False",
898 &PrefData.stdOpenDialog, NULL, False},
899 {"tagFile", "TagFile", PREF_STRING,
900 "", PrefData.tagFile, (void *)sizeof(PrefData.tagFile), False},
901 {"wordDelimiters", "WordDelimiters", PREF_STRING,
902 ".,/\\`'!|@#%^&*()-=+{}[]\":;<>?",
903 PrefData.delimiters, (void *)sizeof(PrefData.delimiters), False},
904 {"serverName", "serverName", PREF_STRING, "", PrefData.serverName,
905 (void *)sizeof(PrefData.serverName), False},
906 {"maxPrevOpenFiles", "MaxPrevOpenFiles", PREF_INT, "30",
907 &PrefData.maxPrevOpenFiles, NULL, False},
908 {"bgMenuButton", "BGMenuButton" , PREF_STRING,
909 "~Shift~Ctrl~Meta~Alt<Btn3Down>", PrefData.bgMenuBtn,
910 (void *)sizeof(PrefData.bgMenuBtn), False},
911 {"smartTags", "SmartTags", PREF_BOOLEAN, "True",
912 &PrefData.smartTags, NULL, True},
913 {"typingHidesPointer", "TypingHidesPointer", PREF_BOOLEAN, "False",
914 &PrefData.typingHidesPointer, NULL, False},
915 {"alwaysCheckRelativeTagsSpecs", "AlwaysCheckRelativeTagsSpecs",
916 PREF_BOOLEAN, "True", &PrefData.alwaysCheckRelativeTagsSpecs, NULL, False},
917 {"prefFileRead", "PrefFileRead", PREF_BOOLEAN, "False",
918 &PrefData.prefFileRead, NULL, True},
919 #ifdef SGI_CUSTOM
920 {"shortMenus", "ShortMenus", PREF_BOOLEAN, "False", &PrefData.shortMenus,
921 NULL, True},
922 #endif
923 {"findReplaceUsesSelection", "FindReplaceUsesSelection", PREF_BOOLEAN, "False",
924 &PrefData.findReplaceUsesSelection, NULL, False},
925 {"overrideDefaultVirtualKeyBindings", "OverrideDefaultVirtualKeyBindings",
926 PREF_ENUM, "Auto", &PrefData.virtKeyOverride, VirtKeyOverrideModes, False},
927 {"titleFormat", "TitleFormat", PREF_STRING, "{%c} [%s] %f (%S) - %d",
928 PrefData.titleFormat, (void *)sizeof(PrefData.titleFormat), True},
929 {"undoModifiesSelection", "UndoModifiesSelection", PREF_BOOLEAN,
930 "True", &PrefData.undoModifiesSelection, NULL, True},
933 static XrmOptionDescRec OpTable[] = {
934 {"-wrap", ".autoWrap", XrmoptionNoArg, (caddr_t)"Continuous"},
935 {"-nowrap", ".autoWrap", XrmoptionNoArg, (caddr_t)"None"},
936 {"-autowrap", ".autoWrap", XrmoptionNoArg, (caddr_t)"Newline"},
937 {"-noautowrap", ".autoWrap", XrmoptionNoArg, (caddr_t)"None"},
938 {"-autoindent", ".autoIndent", XrmoptionNoArg, (caddr_t)"Auto"},
939 {"-noautoindent", ".autoIndent", XrmoptionNoArg, (caddr_t)"False"},
940 {"-autosave", ".autoSave", XrmoptionNoArg, (caddr_t)"True"},
941 {"-noautosave", ".autoSave", XrmoptionNoArg, (caddr_t)"False"},
942 {"-rows", ".textRows", XrmoptionSepArg, (caddr_t)NULL},
943 {"-columns", ".textCols", XrmoptionSepArg, (caddr_t)NULL},
944 {"-tabs", ".tabDistance", XrmoptionSepArg, (caddr_t)NULL},
945 {"-font", ".textFont", XrmoptionSepArg, (caddr_t)NULL},
946 {"-fn", ".textFont", XrmoptionSepArg, (caddr_t)NULL},
947 {"-svrname", ".serverName", XrmoptionSepArg, (caddr_t)NULL},
950 static const char HeaderText[] = "\
951 ! Preferences file for NEdit\n\
952 !\n\
953 ! This file is overwritten by the \"Save Defaults...\" command in NEdit \n\
954 ! and serves only the interactively settable options presented in the NEdit\n\
955 ! \"Preferences\" menu. To modify other options, such as key bindings, use \n\
956 ! the .Xdefaults file in your home directory (or the X resource \n\
957 ! specification method appropriate to your system). The contents of this \n\
958 ! file can be moved into an X resource file, but since resources in this file\n\
959 ! override their corresponding X resources, either this file should be \n\
960 ! deleted or individual resource lines in the file should be deleted for the\n\
961 ! moved lines to take effect.\n";
963 /* Module-global variable set when any preference changes (for asking the
964 user about re-saving on exit) */
965 static int PrefsHaveChanged = False;
967 /* Module-global variable set when user uses -import to load additional
968 preferences on top of the defaults. Contains name of file loaded */
969 static char *ImportedFile = NULL;
971 /* Module-global variables to support Initial Window Size... dialog */
972 static int DoneWithSizeDialog;
973 static Widget RowText, ColText;
975 /* Module-global variables for Tabs dialog */
976 static int DoneWithTabsDialog;
977 static WindowInfo *TabsDialogForWindow;
978 static Widget TabDistText, EmTabText, EmTabToggle, UseTabsToggle, EmTabLabel;
980 /* Module-global variables for Wrap Margin dialog */
981 static int DoneWithWrapDialog;
982 static WindowInfo *WrapDialogForWindow;
983 static Widget WrapText, WrapTextLabel, WrapWindowToggle;
985 static void translatePrefFormats(int convertOld, int fileVer);
986 static void setIntPref(int *prefDataField, int newValue);
987 static void setStringPref(char *prefDataField, const char *newValue);
988 static void sizeOKCB(Widget w, XtPointer clientData, XtPointer callData);
989 static void setStringAllocPref(char **pprefDataField, char *newValue);
990 static void sizeCancelCB(Widget w, XtPointer clientData, XtPointer callData);
991 static void tabsOKCB(Widget w, XtPointer clientData, XtPointer callData);
992 static void tabsCancelCB(Widget w, XtPointer clientData, XtPointer callData);
993 static void tabsHelpCB(Widget w, XtPointer clientData, XtPointer callData);
994 static void emTabsCB(Widget w, XtPointer clientData, XtPointer callData);
995 static void wrapOKCB(Widget w, XtPointer clientData, XtPointer callData);
996 static void wrapCancelCB(Widget w, XtPointer clientData, XtPointer callData);
997 static void wrapWindowCB(Widget w, XtPointer clientData, XtPointer callData);
998 static void reapplyLanguageMode(WindowInfo *window, int mode,int forceDefaults);
1001 static void fillFromPrimaryCB(Widget w, XtPointer clientData,
1002 XtPointer callData);
1003 static int checkFontStatus(fontDialog *fd, Widget fontTextFieldW);
1004 static int showFontStatus(fontDialog *fd, Widget fontTextFieldW,
1005 Widget errorLabelW);
1006 static void primaryModifiedCB(Widget w, XtPointer clientData,
1007 XtPointer callData);
1008 static void italicModifiedCB(Widget w, XtPointer clientData,
1009 XtPointer callData);
1010 static void boldModifiedCB(Widget w, XtPointer clientData, XtPointer callData);
1011 static void boldItalicModifiedCB(Widget w, XtPointer clientData,
1012 XtPointer callData);
1013 static void primaryBrowseCB(Widget w, XtPointer clientData, XtPointer callData);
1014 static void italicBrowseCB(Widget w, XtPointer clientData, XtPointer callData);
1015 static void boldBrowseCB(Widget w, XtPointer clientData, XtPointer callData);
1016 static void boldItalicBrowseCB(Widget w, XtPointer clientData,
1017 XtPointer callData);
1018 static void browseFont(Widget parent, Widget fontTextW, fontDialog *fd);
1019 static void fontDestroyCB(Widget w, XtPointer clientData, XtPointer callData);
1020 static void fontOkCB(Widget w, XtPointer clientData, XtPointer callData);
1021 static void fontApplyCB(Widget w, XtPointer clientData, XtPointer callData);
1022 static void fontDismissCB(Widget w, XtPointer clientData, XtPointer callData);
1023 static void updateFonts(fontDialog *fd);
1025 static Boolean checkColorStatus(colorDialog *cd, Widget colorFieldW);
1026 static int verifyAllColors (colorDialog *cd);
1027 static void showColorStatus (colorDialog *cd, Widget colorFieldW,
1028 Widget errorLabelW);
1029 static void updateColors(colorDialog *cd);
1030 static void colorDestroyCB(Widget w, XtPointer clientData, XtPointer callData);
1031 static void colorOkCB (Widget w, XtPointer clientData, XtPointer callData);
1032 static void colorApplyCB (Widget w, XtPointer clientData, XtPointer callData);
1033 static void colorDismissCB(Widget w, XtPointer clientData, XtPointer callData);
1034 static void textFgModifiedCB (Widget w, XtPointer clientData,
1035 XtPointer callData);
1036 static void textBgModifiedCB (Widget w, XtPointer clientData,
1037 XtPointer callData);
1038 static void selectFgModifiedCB(Widget w, XtPointer clientData,
1039 XtPointer callData);
1040 static void selectBgModifiedCB(Widget w, XtPointer clientData,
1041 XtPointer callData);
1042 static void hiliteFgModifiedCB(Widget w, XtPointer clientData,
1043 XtPointer callData);
1044 static void hiliteBgModifiedCB(Widget w, XtPointer clientData,
1045 XtPointer callData);
1046 static void lineNoFgModifiedCB(Widget w, XtPointer clientData,
1047 XtPointer callData);
1048 static void cursorFgModifiedCB(Widget w, XtPointer clientData,
1049 XtPointer callData);
1051 static int matchLanguageMode(WindowInfo *window);
1052 static int loadLanguageModesString(char *inString, int fileVer);
1053 static char *writeLanguageModesString(void);
1054 static char *createExtString(char **extensions, int nExtensions);
1055 static char **readExtensionList(char **inPtr, int *nExtensions);
1056 static void updateLanguageModeSubmenu(WindowInfo *window);
1057 static void setLangModeCB(Widget w, XtPointer clientData, XtPointer callData);
1058 static int modeError(languageModeRec *lm, const char *stringStart,
1059 const char *stoppedAt, const char *message);
1060 static void lmDestroyCB(Widget w, XtPointer clientData, XtPointer callData);
1061 static void lmOkCB(Widget w, XtPointer clientData, XtPointer callData);
1062 static void lmApplyCB(Widget w, XtPointer clientData, XtPointer callData);
1063 static void lmDismissCB(Widget w, XtPointer clientData, XtPointer callData);
1064 static int lmDeleteConfirmCB(int itemIndex, void *cbArg);
1065 static int updateLMList(void);
1066 static languageModeRec *copyLanguageModeRec(languageModeRec *lm);
1067 static void *lmGetDisplayedCB(void *oldItem, int explicitRequest, int *abort,
1068 void *cbArg);
1069 static void lmSetDisplayedCB(void *item, void *cbArg);
1070 static languageModeRec *readLMDialogFields(int silent);
1071 static void lmFreeItemCB(void *item);
1072 static void freeLanguageModeRec(languageModeRec *lm);
1073 static int lmDialogEmpty(void);
1074 static void updatePatternsTo5dot1(void);
1075 static void updatePatternsTo5dot2(void);
1076 static void updatePatternsTo5dot3(void);
1077 static void updatePatternsTo5dot4(void);
1078 static void updateShellCmdsTo5dot3(void);
1079 static void migrateColorResources(XrmDatabase prefDB, XrmDatabase appDB);
1080 static void spliceString(char **intoString, const char *insertString, const char *atExpr);
1081 static int regexFind(const char *inString, const char *expr);
1082 static int regexReplace(char **inString, const char *expr,
1083 const char *replaceWith);
1085 #ifdef SGI_CUSTOM
1086 static int shortPrefToDefault(Widget parent, const char *settingName, int *setDefault);
1087 #endif
1089 XrmDatabase CreateNEditPrefDB(int *argcInOut, char **argvInOut)
1091 return CreatePreferencesDatabase(GetRCFileName(NEDIT_RC), APP_NAME,
1092 OpTable, XtNumber(OpTable), (unsigned int *)argcInOut, argvInOut);
1095 void RestoreNEditPrefs(XrmDatabase prefDB, XrmDatabase appDB)
1097 int requiresConversion;
1098 int major; /* The integral part of version number */
1099 int minor; /* fractional part of version number */
1100 int fileVer = 0; /* Both combined into an integer */
1101 int nparsed;
1103 /* Load preferences */
1104 RestorePreferences(prefDB, appDB, APP_NAME,
1105 APP_CLASS, PrefDescrip, XtNumber(PrefDescrip));
1107 /* If the preferences file was written by an older version of NEdit,
1108 warn the user that it will be converted. */
1109 requiresConversion = PrefData.prefFileRead &&
1110 PrefData.fileVersion[0] == '\0';
1111 if (requiresConversion) {
1112 updatePatternsTo5dot1();
1115 if (PrefData.prefFileRead) {
1116 if (PrefData.fileVersion[0] == '\0') {
1117 fileVer = 0; /* Pre-5.1 */
1119 else {
1120 /* Note: do not change the format of this. Older executables
1121 need to read this field for forward compatability. */
1122 nparsed = sscanf(PrefData.fileVersion, "%d.%d", &major, &minor);
1123 if (nparsed >= 2) {
1124 /* Use OSF-style numbering scheme */
1125 fileVer = major * 1000 + minor;
1130 if (PrefData.prefFileRead && fileVer < 5002) {
1131 updatePatternsTo5dot2();
1134 if (PrefData.prefFileRead && fileVer < 5003) {
1135 updateShellCmdsTo5dot3();
1136 updatePatternsTo5dot3();
1139 /* Note that we don't care about unreleased file versions. Anyone
1140 who is running a CVS or alpha version of NEdit is resposnbile
1141 for managing the preferences file themselves. Otherwise, it
1142 gets impossible to track the number of "in-between" file formats.
1143 We only do auto-upgrading for a real release. */
1145 if (PrefData.prefFileRead && (fileVer < 5004)) {
1146 /* There are some implict conversions done later - show this
1147 message even if there's no explicit call to upgrade. */
1148 fprintf(stderr, "NEdit: Converting .nedit file to 5.4 version.\n"
1149 " To keep, use Preferences -> Save Defaults\n");
1151 /* XXX: When 5.4 is released we should move the following lines into
1152 the above if stmt. It's here now for developers who have been using CVS
1153 versions and want their colors and patterns migrated. */
1154 migrateColorResources(prefDB, appDB);
1155 updatePatternsTo5dot4();
1157 /* Do further parsing on resource types which RestorePreferences does
1158 not understand and reads as strings, to put them in the final form
1159 in which nedit stores and uses. If the preferences file was
1160 written by an older version of NEdit, update regular expressions in
1161 highlight patterns to quote braces and use & instead of \0 */
1162 translatePrefFormats(requiresConversion, fileVer);
1166 ** Many of of NEdit's preferences are much more complicated than just simple
1167 ** integers or strings. These are read as strings, but must be parsed and
1168 ** translated into something meaningful. This routine does the translation,
1169 ** and, in most cases, frees the original string, which is no longer useful.
1171 ** The argument convertOld attempts a conversion from pre 5.1 format .nedit
1172 ** files (which means patterns and macros may contain regular expressions
1173 ** which are of the older syntax where braces were not quoted, and \0 was a
1174 ** legal substitution character). Macros, so far can not be automatically
1175 ** converted, unfortunately.
1177 static void translatePrefFormats(int convertOld, int fileVer)
1179 XFontStruct *font;
1181 /* Parse the strings which represent types which are not decoded by
1182 the standard resource manager routines */
1183 #ifndef VMS
1184 if (TempStringPrefs.shellCmds != NULL) {
1185 LoadShellCmdsString(TempStringPrefs.shellCmds);
1186 XtFree(TempStringPrefs.shellCmds);
1187 TempStringPrefs.shellCmds = NULL;
1189 #endif /* VMS */
1190 if (TempStringPrefs.macroCmds != NULL) {
1191 LoadMacroCmdsString(TempStringPrefs.macroCmds);
1192 XtFree(TempStringPrefs.macroCmds);
1193 TempStringPrefs.macroCmds = NULL;
1195 if (TempStringPrefs.bgMenuCmds != NULL) {
1196 LoadBGMenuCmdsString(TempStringPrefs.bgMenuCmds);
1197 XtFree(TempStringPrefs.bgMenuCmds);
1198 TempStringPrefs.bgMenuCmds = NULL;
1200 if (TempStringPrefs.highlight != NULL) {
1201 LoadHighlightString(TempStringPrefs.highlight, convertOld);
1202 XtFree(TempStringPrefs.highlight);
1203 TempStringPrefs.highlight = NULL;
1205 if (TempStringPrefs.styles != NULL) {
1206 LoadStylesString(TempStringPrefs.styles);
1207 XtFree(TempStringPrefs.styles);
1208 TempStringPrefs.styles = NULL;
1210 if (TempStringPrefs.language != NULL) {
1211 loadLanguageModesString(TempStringPrefs.language, fileVer);
1212 XtFree(TempStringPrefs.language);
1213 TempStringPrefs.language = NULL;
1215 if (TempStringPrefs.smartIndent != NULL) {
1216 LoadSmartIndentString(TempStringPrefs.smartIndent);
1217 XtFree(TempStringPrefs.smartIndent);
1218 TempStringPrefs.smartIndent = NULL;
1220 if (TempStringPrefs.smartIndentCommon != NULL) {
1221 LoadSmartIndentCommonString(TempStringPrefs.smartIndentCommon);
1222 XtFree(TempStringPrefs.smartIndentCommon);
1223 TempStringPrefs.smartIndentCommon = NULL;
1226 /* translate the font names into fontLists suitable for the text widget */
1227 font = XLoadQueryFont(TheDisplay, PrefData.fontString);
1228 PrefData.fontList = font==NULL ? NULL :
1229 XmFontListCreate(font, XmSTRING_DEFAULT_CHARSET);
1230 PrefData.boldFontStruct = XLoadQueryFont(TheDisplay,
1231 PrefData.boldFontString);
1232 PrefData.italicFontStruct = XLoadQueryFont(TheDisplay,
1233 PrefData.italicFontString);
1234 PrefData.boldItalicFontStruct = XLoadQueryFont(TheDisplay,
1235 PrefData.boldItalicFontString);
1237 /* For compatability with older (4.0.3 and before) versions, the autoWrap
1238 and autoIndent resources can accept values of True and False. Translate
1239 them into acceptable wrap and indent styles */
1240 if (PrefData.wrapStyle == 3) PrefData.wrapStyle = NEWLINE_WRAP;
1241 if (PrefData.wrapStyle == 4) PrefData.wrapStyle = NO_WRAP;
1242 if (PrefData.autoIndent == 3) PrefData.autoIndent = AUTO_INDENT;
1243 if (PrefData.autoIndent == 4) PrefData.autoIndent = NO_AUTO_INDENT;
1246 void SaveNEditPrefs(Widget parent, int quietly)
1248 const char* prefFileName = GetRCFileName(NEDIT_RC);
1249 if (prefFileName == NULL)
1251 /* GetRCFileName() might return NULL if an error occurs during
1252 creation of the preference file directory. */
1253 DialogF(DF_WARN, parent, 1, "Error saving Preferences",
1254 "Unable to save preferences: Cannot determine filename.",
1255 "Dismiss");
1256 return;
1259 if (!quietly) {
1260 if (DialogF(DF_INF, parent, 2, "Save imported Settings",
1261 ImportedFile == NULL ?
1262 "Default preferences will be saved in the file:\n"
1263 "%s\n"
1264 "NEdit automatically loads this file\n"
1265 "each time it is started." :
1266 "Default preferences will be saved in the file:\n"
1267 "%s\n"
1268 "SAVING WILL INCORPORATE SETTINGS\n"
1269 "FROM FILE: %s", "OK", "Cancel",
1270 prefFileName, ImportedFile) == 2)
1271 return;
1273 #ifndef VMS
1274 TempStringPrefs.shellCmds = WriteShellCmdsString();
1275 #endif /* VMS */
1276 TempStringPrefs.macroCmds = WriteMacroCmdsString();
1277 TempStringPrefs.bgMenuCmds = WriteBGMenuCmdsString();
1278 TempStringPrefs.highlight = WriteHighlightString();
1279 TempStringPrefs.language = writeLanguageModesString();
1280 TempStringPrefs.styles = WriteStylesString();
1281 TempStringPrefs.smartIndent = WriteSmartIndentString();
1282 TempStringPrefs.smartIndentCommon = WriteSmartIndentCommonString();
1283 strcpy(PrefData.fileVersion, PREF_FILE_VERSION);
1284 if (!SavePreferences(XtDisplay(parent), prefFileName, HeaderText,
1285 PrefDescrip, XtNumber(PrefDescrip)))
1287 DialogF(DF_WARN, parent, 1, "Save Preferences",
1288 "Unable to save preferences in %s", "Dismiss", prefFileName);
1291 #ifndef VMS
1292 XtFree(TempStringPrefs.shellCmds);
1293 #endif /* VMS */
1294 XtFree(TempStringPrefs.macroCmds);
1295 XtFree(TempStringPrefs.bgMenuCmds);
1296 XtFree(TempStringPrefs.highlight);
1297 XtFree(TempStringPrefs.language);
1298 XtFree(TempStringPrefs.styles);
1299 XtFree(TempStringPrefs.smartIndent);
1300 XtFree(TempStringPrefs.smartIndentCommon);
1302 PrefsHaveChanged = False;
1306 ** Load an additional preferences file on top of the existing preferences
1307 ** derived from defaults, the .nedit file, and X resources.
1309 void ImportPrefFile(const char *filename, int convertOld)
1311 XrmDatabase db;
1312 char *fileString;
1314 fileString = ReadAnyTextFile(filename);
1315 if (fileString != NULL){
1316 db = XrmGetStringDatabase(fileString);
1317 XtFree(fileString);
1318 OverlayPreferences(db, APP_NAME, APP_CLASS, PrefDescrip,
1319 XtNumber(PrefDescrip));
1320 translatePrefFormats(convertOld, -1);
1321 ImportedFile = XtNewString(filename);
1322 } else
1324 fprintf(stderr, "Could not read additional preferences file: ");
1325 fprintf(stderr, filename);
1326 fprintf(stderr, "\n");
1330 void SetPrefWrap(int state)
1332 setIntPref(&PrefData.wrapStyle, state);
1335 int GetPrefWrap(int langMode)
1337 if (langMode == PLAIN_LANGUAGE_MODE ||
1338 LanguageModes[langMode]->wrapStyle == DEFAULT_WRAP)
1339 return PrefData.wrapStyle;
1340 return LanguageModes[langMode]->wrapStyle;
1343 void SetPrefWrapMargin(int margin)
1345 setIntPref(&PrefData.wrapMargin, margin);
1348 int GetPrefWrapMargin(void)
1350 return PrefData.wrapMargin;
1353 void SetPrefSearch(int searchType)
1355 setIntPref(&PrefData.searchMethod, searchType);
1358 int GetPrefSearch(void)
1360 return PrefData.searchMethod;
1363 #ifdef REPLACE_SCOPE
1364 void SetPrefReplaceDefScope(int scope)
1366 setIntPref(&PrefData.replaceDefScope, scope);
1369 int GetPrefReplaceDefScope(void)
1371 return PrefData.replaceDefScope;
1373 #endif
1375 void SetPrefAutoIndent(int state)
1377 setIntPref(&PrefData.autoIndent, state);
1380 int GetPrefAutoIndent(int langMode)
1382 if (langMode == PLAIN_LANGUAGE_MODE ||
1383 LanguageModes[langMode]->indentStyle == DEFAULT_INDENT)
1384 return PrefData.autoIndent;
1385 return LanguageModes[langMode]->indentStyle;
1388 void SetPrefAutoSave(int state)
1390 setIntPref(&PrefData.autoSave, state);
1393 int GetPrefAutoSave(void)
1395 return PrefData.autoSave;
1398 void SetPrefSaveOldVersion(int state)
1400 setIntPref(&PrefData.saveOldVersion, state);
1403 int GetPrefSaveOldVersion(void)
1405 return PrefData.saveOldVersion;
1408 void SetPrefSearchDlogs(int state)
1410 setIntPref(&PrefData.searchDlogs, state);
1413 int GetPrefSearchDlogs(void)
1415 return PrefData.searchDlogs;
1418 void SetPrefBeepOnSearchWrap(int state)
1420 setIntPref(&PrefData.searchWrapBeep, state);
1423 int GetPrefBeepOnSearchWrap(void)
1425 return PrefData.searchWrapBeep;
1428 void SetPrefKeepSearchDlogs(int state)
1430 setIntPref(&PrefData.keepSearchDlogs, state);
1433 int GetPrefKeepSearchDlogs(void)
1435 return PrefData.keepSearchDlogs;
1438 void SetPrefSearchWraps(int state)
1440 setIntPref(&PrefData.searchWraps, state);
1443 int GetPrefStickyCaseSenseBtn(void)
1445 return PrefData.stickyCaseSenseBtn;
1448 void SetPrefStickyCaseSenseBtn(int state)
1450 setIntPref(&PrefData.stickyCaseSenseBtn, state);
1453 int GetPrefSearchWraps(void)
1455 return PrefData.searchWraps;
1458 void SetPrefStatsLine(int state)
1460 setIntPref(&PrefData.statsLine, state);
1463 int GetPrefStatsLine(void)
1465 return PrefData.statsLine;
1468 void SetPrefISearchLine(int state)
1470 setIntPref(&PrefData.iSearchLine, state);
1473 int GetPrefISearchLine(void)
1475 return PrefData.iSearchLine;
1478 void SetPrefLineNums(int state)
1480 setIntPref(&PrefData.lineNums, state);
1483 int GetPrefLineNums(void)
1485 return PrefData.lineNums;
1488 void SetPrefShowPathInWindowsMenu(int state)
1490 setIntPref(&PrefData.pathInWindowsMenu, state);
1493 int GetPrefShowPathInWindowsMenu(void)
1495 return PrefData.pathInWindowsMenu;
1498 void SetPrefWarnFileMods(int state)
1500 setIntPref(&PrefData.warnFileMods, state);
1503 int GetPrefWarnFileMods(void)
1505 return PrefData.warnFileMods;
1508 void SetPrefWarnRealFileMods(int state)
1510 setIntPref(&PrefData.warnRealFileMods, state);
1513 int GetPrefWarnRealFileMods(void)
1515 return PrefData.warnRealFileMods;
1518 void SetPrefWarnExit(int state)
1520 setIntPref(&PrefData.warnExit, state);
1523 int GetPrefWarnExit(void)
1525 return PrefData.warnExit;
1528 void SetPrefv(int state)
1530 setIntPref(&PrefData.findReplaceUsesSelection, state);
1533 int GetPrefFindReplaceUsesSelection(void)
1535 return PrefData.findReplaceUsesSelection;
1538 void SetPrefMapDelete(int state)
1540 setIntPref(&PrefData.mapDelete, state);
1543 int GetPrefMapDelete(void)
1545 return PrefData.mapDelete;
1548 void SetPrefStdOpenDialog(int state)
1550 setIntPref(&PrefData.stdOpenDialog, state);
1553 int GetPrefStdOpenDialog(void)
1555 return PrefData.stdOpenDialog;
1558 void SetPrefRows(int nRows)
1560 setIntPref(&PrefData.textRows, nRows);
1563 int GetPrefRows(void)
1565 return PrefData.textRows;
1568 void SetPrefCols(int nCols)
1570 setIntPref(&PrefData.textCols, nCols);
1573 int GetPrefCols(void)
1575 return PrefData.textCols;
1578 void SetPrefTabDist(int tabDist)
1580 setIntPref(&PrefData.tabDist, tabDist);
1583 int GetPrefTabDist(int langMode)
1585 int tabDist;
1586 if (langMode == PLAIN_LANGUAGE_MODE ||
1587 LanguageModes[langMode]->tabDist == DEFAULT_TAB_DIST) {
1588 tabDist = PrefData.tabDist;
1589 } else {
1590 tabDist = LanguageModes[langMode]->tabDist;
1592 /* Make sure that the tab distance is in range (garbage may have
1593 been entered via the command line or the X resources, causing
1594 errors later on, like division by zero). */
1595 if (tabDist <= 0) return 1;
1596 if (tabDist > MAX_EXP_CHAR_LEN) return MAX_EXP_CHAR_LEN;
1597 return tabDist;
1600 void SetPrefEmTabDist(int tabDist)
1602 setIntPref(&PrefData.emTabDist, tabDist);
1605 int GetPrefEmTabDist(int langMode)
1607 if (langMode == PLAIN_LANGUAGE_MODE ||
1608 LanguageModes[langMode]->emTabDist == DEFAULT_EM_TAB_DIST)
1609 return PrefData.emTabDist;
1610 return LanguageModes[langMode]->emTabDist;
1613 void SetPrefInsertTabs(int state)
1615 setIntPref(&PrefData.insertTabs, state);
1618 int GetPrefInsertTabs(void)
1620 return PrefData.insertTabs;
1623 void SetPrefShowMatching(int state)
1625 setIntPref(&PrefData.showMatchingStyle, state);
1628 int GetPrefShowMatching(void)
1631 * For backwards compatibility with pre-5.2 versions, the boolean
1632 * False/True matching behavior is converted to NO_FLASH/FLASH_DELIMIT.
1634 if (PrefData.showMatchingStyle >= N_SHOW_MATCHING_STYLES)
1635 PrefData.showMatchingStyle -= N_SHOW_MATCHING_STYLES;
1636 return PrefData.showMatchingStyle;
1639 void SetPrefMatchSyntaxBased(int state)
1641 setIntPref(&PrefData.matchSyntaxBased, state);
1644 int GetPrefMatchSyntaxBased(void)
1646 return PrefData.matchSyntaxBased;
1649 void SetPrefHighlightSyntax(int state)
1651 setIntPref(&PrefData.highlightSyntax, state);
1654 int GetPrefHighlightSyntax(void)
1656 return PrefData.highlightSyntax;
1659 void SetPrefBacklightChars(int state)
1661 setIntPref(&PrefData.backlightChars, state);
1664 int GetPrefBacklightChars(void)
1666 return PrefData.backlightChars;
1669 void SetPrefBacklightCharTypes(char *types)
1671 setStringAllocPref(&PrefData.backlightCharTypes, types);
1674 char *GetPrefBacklightCharTypes(void)
1676 return PrefData.backlightCharTypes;
1679 void SetPrefRepositionDialogs(int state)
1681 setIntPref(&PrefData.repositionDialogs, state);
1684 int GetPrefRepositionDialogs(void)
1686 return PrefData.repositionDialogs;
1689 void SetPrefAppendLF(int state)
1691 setIntPref(&PrefData.appendLF, state);
1694 int GetPrefAppendLF(void)
1696 return PrefData.appendLF;
1699 void SetPrefSortOpenPrevMenu(int state)
1701 setIntPref(&PrefData.sortOpenPrevMenu, state);
1704 int GetPrefSortOpenPrevMenu(void)
1706 return PrefData.sortOpenPrevMenu;
1709 void SetPrefTagFile(const char *tagFileName)
1711 setStringPref(PrefData.tagFile, tagFileName);
1714 char *GetPrefTagFile(void)
1716 return PrefData.tagFile;
1719 void SetPrefSmartTags(int state)
1721 setIntPref(&PrefData.smartTags, state);
1724 int GetPrefSmartTags(void)
1726 return PrefData.smartTags;
1729 int GetPrefAlwaysCheckRelTagsSpecs(void)
1731 return PrefData.alwaysCheckRelativeTagsSpecs;
1734 char *GetPrefDelimiters(void)
1736 return PrefData.delimiters;
1739 char *GetPrefColorName(int index)
1741 return PrefData.colorNames[index];
1744 void SetPrefColorName(int index, const char *name)
1746 setStringPref(PrefData.colorNames[index], name);
1750 ** Set the font preferences using the font name (the fontList is generated
1751 ** in this call). Note that this leaks memory and server resources each
1752 ** time the default font is re-set. See note on SetFontByName in window.c
1753 ** for more information.
1755 void SetPrefFont(char *fontName)
1757 XFontStruct *font;
1759 setStringPref(PrefData.fontString, fontName);
1760 font = XLoadQueryFont(TheDisplay, fontName);
1761 PrefData.fontList = font==NULL ? NULL :
1762 XmFontListCreate(font, XmSTRING_DEFAULT_CHARSET);
1765 void SetPrefBoldFont(char *fontName)
1767 setStringPref(PrefData.boldFontString, fontName);
1768 PrefData.boldFontStruct = XLoadQueryFont(TheDisplay, fontName);
1771 void SetPrefItalicFont(char *fontName)
1773 setStringPref(PrefData.italicFontString, fontName);
1774 PrefData.italicFontStruct = XLoadQueryFont(TheDisplay, fontName);
1776 void SetPrefBoldItalicFont(char *fontName)
1778 setStringPref(PrefData.boldItalicFontString, fontName);
1779 PrefData.boldItalicFontStruct = XLoadQueryFont(TheDisplay, fontName);
1782 char *GetPrefFontName(void)
1784 return PrefData.fontString;
1787 char *GetPrefBoldFontName(void)
1789 return PrefData.boldFontString;
1792 char *GetPrefItalicFontName(void)
1794 return PrefData.italicFontString;
1797 char *GetPrefBoldItalicFontName(void)
1799 return PrefData.boldItalicFontString;
1802 XmFontList GetPrefFontList(void)
1804 return PrefData.fontList;
1807 XFontStruct *GetPrefBoldFont(void)
1809 return PrefData.boldFontStruct;
1812 XFontStruct *GetPrefItalicFont(void)
1814 return PrefData.italicFontStruct;
1817 XFontStruct *GetPrefBoldItalicFont(void)
1819 return PrefData.boldItalicFontStruct;
1822 char *GetPrefHelpFontName(int index)
1824 return PrefData.helpFontNames[index];
1827 char *GetPrefHelpLinkColor(void)
1829 return PrefData.helpLinkColor;
1832 void SetPrefShell(const char *shell)
1834 setStringPref(PrefData.shell, shell);
1837 char *GetPrefShell(void)
1839 return PrefData.shell;
1842 void SetPrefGeometry(const char *geometry)
1844 setStringPref(PrefData.geometry, geometry);
1847 char *GetPrefGeometry(void)
1849 return PrefData.geometry;
1852 char *GetPrefServerName(void)
1854 return PrefData.serverName;
1857 char *GetPrefBGMenuBtn(void)
1859 return PrefData.bgMenuBtn;
1862 int GetPrefMaxPrevOpenFiles(void)
1864 return PrefData.maxPrevOpenFiles;
1867 int GetPrefTypingHidesPointer(void)
1869 return(PrefData.typingHidesPointer);
1872 #ifdef SGI_CUSTOM
1873 void SetPrefShortMenus(int state)
1875 setIntPref(&PrefData.shortMenus, state);
1878 int GetPrefShortMenus(void)
1880 return PrefData.shortMenus;
1882 #endif
1884 void SetPrefTitleFormat(const char* format)
1886 const WindowInfo* window;
1888 setStringPref(PrefData.titleFormat, format);
1890 /* update all windows */
1891 for (window=WindowList; window!=NULL; window=window->next) {
1892 UpdateWindowTitle(window);
1895 const char* GetPrefTitleFormat(void)
1897 return PrefData.titleFormat;
1900 void SetPrefUndoModifiesSelection(Boolean value)
1902 setIntPref(&PrefData.undoModifiesSelection, value);
1905 Boolean GetPrefUndoModifiesSelection(void)
1907 return (Boolean)PrefData.undoModifiesSelection;
1910 int GetPrefOverrideVirtKeyBindings(void)
1912 return PrefData.virtKeyOverride;
1916 ** If preferences don't get saved, ask the user on exit whether to save
1918 void MarkPrefsChanged(void)
1920 PrefsHaveChanged = True;
1924 ** Check if preferences have changed, and if so, ask the user if he wants
1925 ** to re-save. Returns False if user requests cancelation of Exit (or whatever
1926 ** operation triggered this call to be made).
1928 int CheckPrefsChangesSaved(Widget dialogParent)
1930 int resp;
1932 if (!PrefsHaveChanged)
1933 return True;
1935 resp = DialogF(DF_WARN, dialogParent, 3, "Default Preferences",
1936 ImportedFile == NULL ?
1937 "Default Preferences have changed.\n"
1938 "Save changes to NEdit preference file?" :
1939 "Default Preferences have changed. SAVING \n"
1940 "CHANGES WILL INCORPORATE ADDITIONAL\nSETTINGS FROM FILE: %s",
1941 "Save", "Don't Save", "Cancel", ImportedFile);
1942 if (resp == 2)
1943 return True;
1944 if (resp == 3)
1945 return False;
1947 SaveNEditPrefs(dialogParent, True);
1948 return True;
1952 ** set *prefDataField to newValue, but first check if they're different
1953 ** and update PrefsHaveChanged if a preference setting has now changed.
1955 static void setIntPref(int *prefDataField, int newValue)
1957 if (newValue != *prefDataField)
1958 PrefsHaveChanged = True;
1959 *prefDataField = newValue;
1962 static void setStringPref(char *prefDataField, const char *newValue)
1964 if (strcmp(prefDataField, newValue))
1965 PrefsHaveChanged = True;
1966 strcpy(prefDataField, newValue);
1969 static void setStringAllocPref(char **pprefDataField, char *newValue)
1971 char *p_newField;
1973 /* treat empty strings as nulls */
1974 if (newValue && *newValue == '\0')
1975 newValue = NULL;
1976 if (*pprefDataField && **pprefDataField == '\0')
1977 *pprefDataField = NULL; /* assume statically alloc'ed "" */
1979 /* check changes */
1980 if (!*pprefDataField && !newValue)
1981 return;
1982 else if (!*pprefDataField && newValue)
1983 PrefsHaveChanged = True;
1984 else if (*pprefDataField && !newValue)
1985 PrefsHaveChanged = True;
1986 else if (strcmp(*pprefDataField, newValue))
1987 PrefsHaveChanged = True;
1989 /* get rid of old preference */
1990 if (*pprefDataField)
1991 XtFree(*pprefDataField);
1993 /* store new preference */
1994 if (newValue) {
1995 p_newField = XtMalloc(strlen(newValue) + 1);
1996 strcpy(p_newField, newValue);
1998 *pprefDataField = newValue;
2002 ** Set the language mode for the window, update the menu and trigger language
2003 ** mode specific actions (turn on/off highlighting). If forceNewDefaults is
2004 ** true, re-establish default settings for language-specific preferences
2005 ** regardless of whether they were previously set by the user.
2007 void SetLanguageMode(WindowInfo *window, int mode, int forceNewDefaults)
2009 Widget menu;
2010 WidgetList items;
2011 int n;
2012 Cardinal nItems;
2013 void *userData;
2015 /* Do mode-specific actions */
2016 reapplyLanguageMode(window, mode, forceNewDefaults);
2018 /* Select the correct language mode in the sub-menu */
2019 XtVaGetValues(window->langModeCascade, XmNsubMenuId, &menu, NULL);
2020 XtVaGetValues(menu, XmNchildren, &items, XmNnumChildren, &nItems, NULL);
2021 for (n=0; n<(int)nItems; n++) {
2022 XtVaGetValues(items[n], XmNuserData, &userData, NULL);
2023 XmToggleButtonSetState(items[n], (int)userData == mode, False);
2028 ** Lookup a language mode by name, returning the index of the language
2029 ** mode or PLAIN_LANGUAGE_MODE if the name is not found
2031 int FindLanguageMode(const char *languageName)
2033 int i;
2035 /* Compare each language mode to the one we were presented */
2036 for (i=0; i<NLanguageModes; i++)
2037 if (!strcmp(languageName, LanguageModes[i]->name))
2038 return i;
2040 return PLAIN_LANGUAGE_MODE;
2045 ** Apply language mode matching criteria and set window->languageMode to
2046 ** the appropriate mode for the current file, trigger language mode
2047 ** specific actions (turn on/off highlighting), and update the language
2048 ** mode menu item. If forceNewDefaults is true, re-establish default
2049 ** settings for language-specific preferences regardless of whether
2050 ** they were previously set by the user.
2052 void DetermineLanguageMode(WindowInfo *window, int forceNewDefaults)
2054 SetLanguageMode(window, matchLanguageMode(window), forceNewDefaults);
2058 ** Return the name of the current language mode set in "window", or NULL
2059 ** if the current mode is "Plain".
2061 char *LanguageModeName(int mode)
2063 if (mode == PLAIN_LANGUAGE_MODE)
2064 return NULL;
2065 else
2066 return LanguageModes[mode]->name;
2070 ** Get the set of word delimiters for the language mode set in the current
2071 ** window. Returns NULL when no language mode is set (it would be easy to
2072 ** return the default delimiter set when the current language mode is "Plain",
2073 ** or the mode doesn't have its own delimiters, but this is usually used
2074 ** to supply delimiters for RE searching, and ExecRE can skip compiling a
2075 ** delimiter table when delimiters is NULL).
2077 char *GetWindowDelimiters(WindowInfo *window)
2079 if (window->languageMode == PLAIN_LANGUAGE_MODE)
2080 return NULL;
2081 else
2082 return LanguageModes[window->languageMode]->delimiters;
2086 ** Put up a dialog for selecting a custom initial window size
2088 void RowColumnPrefDialog(Widget parent)
2090 Widget form, selBox, topLabel;
2091 Arg selBoxArgs[2];
2092 XmString s1;
2094 XtSetArg(selBoxArgs[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
2095 XtSetArg(selBoxArgs[1], XmNautoUnmanage, False);
2096 selBox = CreatePromptDialog(parent, "customSize", selBoxArgs, 2);
2097 XtAddCallback(selBox, XmNokCallback, (XtCallbackProc)sizeOKCB, NULL);
2098 XtAddCallback(selBox, XmNcancelCallback, (XtCallbackProc)sizeCancelCB,NULL);
2099 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_TEXT));
2100 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_SELECTION_LABEL));
2101 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_HELP_BUTTON));
2102 XtVaSetValues(XtParent(selBox), XmNtitle, "Initial Window Size", NULL);
2104 form = XtVaCreateManagedWidget("form", xmFormWidgetClass, selBox, NULL);
2106 topLabel = XtVaCreateManagedWidget("topLabel", xmLabelGadgetClass, form,
2107 XmNlabelString, s1=MKSTRING(
2108 "Enter desired size in rows\nand columns of characters:"), NULL);
2109 XmStringFree(s1);
2111 RowText = XtVaCreateManagedWidget("rows", xmTextWidgetClass, form,
2112 XmNcolumns, 3,
2113 XmNtopAttachment, XmATTACH_WIDGET,
2114 XmNleftAttachment, XmATTACH_POSITION,
2115 XmNrightAttachment, XmATTACH_POSITION,
2116 XmNtopWidget, topLabel,
2117 XmNleftPosition, 5,
2118 XmNrightPosition, 45, NULL);
2119 RemapDeleteKey(RowText);
2121 XtVaCreateManagedWidget("xLabel", xmLabelGadgetClass, form,
2122 XmNlabelString, s1=MKSTRING("x"),
2123 XmNtopAttachment, XmATTACH_WIDGET,
2124 XmNleftAttachment, XmATTACH_POSITION,
2125 XmNrightAttachment, XmATTACH_POSITION,
2126 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2127 XmNtopWidget, topLabel,
2128 XmNbottomWidget, RowText,
2129 XmNleftPosition, 45,
2130 XmNrightPosition, 55, NULL);
2131 XmStringFree(s1);
2133 ColText = XtVaCreateManagedWidget("cols", xmTextWidgetClass, form,
2134 XmNcolumns, 3,
2135 XmNtopAttachment, XmATTACH_WIDGET,
2136 XmNleftAttachment, XmATTACH_POSITION,
2137 XmNrightAttachment, XmATTACH_POSITION,
2138 XmNtopWidget, topLabel,
2139 XmNleftPosition, 55,
2140 XmNrightPosition, 95, NULL);
2141 RemapDeleteKey(ColText);
2143 /* put up dialog and wait for user to press ok or cancel */
2144 DoneWithSizeDialog = False;
2145 ManageDialogCenteredOnPointer(selBox);
2146 while (!DoneWithSizeDialog)
2148 XEvent event;
2149 XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
2150 ServerDispatchEvent(&event);
2153 XtDestroyWidget(selBox);
2156 static void sizeOKCB(Widget w, XtPointer clientData, XtPointer callData)
2158 int rowValue, colValue, stat;
2160 /* get the values that the user entered and make sure they're ok */
2161 stat = GetIntTextWarn(RowText, &rowValue, "number of rows", True);
2162 if (stat != TEXT_READ_OK)
2163 return;
2164 stat = GetIntTextWarn(ColText, &colValue, "number of columns", True);
2165 if (stat != TEXT_READ_OK)
2166 return;
2168 /* set the corresponding preferences and dismiss the dialog */
2169 SetPrefRows(rowValue);
2170 SetPrefCols(colValue);
2171 DoneWithSizeDialog = True;
2174 static void sizeCancelCB(Widget w, XtPointer clientData, XtPointer callData)
2176 DoneWithSizeDialog = True;
2180 ** Present the user a dialog for setting tab related preferences, either as
2181 ** defaults, or for a specific window (pass "forWindow" as NULL to set default
2182 ** preference, or a window to set preferences for the specific window.
2184 void TabsPrefDialog(Widget parent, WindowInfo *forWindow)
2186 Widget form, selBox;
2187 Arg selBoxArgs[2];
2188 XmString s1;
2189 int emulate, emTabDist, useTabs, tabDist;
2191 XtSetArg(selBoxArgs[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
2192 XtSetArg(selBoxArgs[1], XmNautoUnmanage, False);
2193 selBox = CreatePromptDialog(parent, "customSize", selBoxArgs, 2);
2194 XtAddCallback(selBox, XmNokCallback, (XtCallbackProc)tabsOKCB, NULL);
2195 XtAddCallback(selBox, XmNcancelCallback, (XtCallbackProc)tabsCancelCB,NULL);
2196 XtAddCallback(selBox, XmNhelpCallback, (XtCallbackProc)tabsHelpCB,NULL);
2197 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_TEXT));
2198 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_SELECTION_LABEL));
2199 XtVaSetValues(XtParent(selBox), XmNtitle, "Tabs", NULL);
2201 form = XtVaCreateManagedWidget("form", xmFormWidgetClass, selBox, NULL);
2203 TabDistText = XtVaCreateManagedWidget("tabDistText", xmTextWidgetClass,
2204 form, XmNcolumns, 7,
2205 XmNtopAttachment, XmATTACH_FORM,
2206 XmNrightAttachment, XmATTACH_FORM, NULL);
2207 RemapDeleteKey(TabDistText);
2208 XtVaCreateManagedWidget("tabDistLabel", xmLabelGadgetClass, form,
2209 XmNlabelString, s1=XmStringCreateSimple(
2210 "Tab spacing (for hardware tab characters)"),
2211 XmNmnemonic, 'T',
2212 XmNuserData, TabDistText,
2213 XmNtopAttachment, XmATTACH_FORM,
2214 XmNleftAttachment, XmATTACH_FORM,
2215 XmNrightAttachment, XmATTACH_WIDGET,
2216 XmNrightWidget, TabDistText,
2217 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2218 XmNbottomWidget, TabDistText, NULL);
2219 XmStringFree(s1);
2221 EmTabText = XtVaCreateManagedWidget("emTabText", xmTextWidgetClass, form,
2222 XmNcolumns, 7,
2223 XmNtopAttachment, XmATTACH_WIDGET,
2224 XmNtopWidget, TabDistText,
2225 XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET,
2226 XmNrightWidget, TabDistText, NULL);
2227 RemapDeleteKey(EmTabText);
2228 EmTabLabel = XtVaCreateManagedWidget("emTabLabel", xmLabelGadgetClass, form,
2229 XmNlabelString, s1=XmStringCreateSimple("Emulated tab spacing"),
2230 XmNmnemonic, 's',
2231 XmNuserData, EmTabText,
2232 XmNtopAttachment, XmATTACH_WIDGET,
2233 XmNtopWidget, TabDistText,
2234 XmNrightAttachment, XmATTACH_WIDGET,
2235 XmNrightWidget, EmTabText,
2236 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2237 XmNbottomWidget, EmTabText, NULL);
2238 XmStringFree(s1);
2239 EmTabToggle = XtVaCreateManagedWidget("emTabToggle",
2240 xmToggleButtonWidgetClass, form, XmNlabelString,
2241 s1=XmStringCreateSimple("Emulate tabs"),
2242 XmNmnemonic, 'E',
2243 XmNtopAttachment, XmATTACH_WIDGET,
2244 XmNtopWidget, TabDistText,
2245 XmNleftAttachment, XmATTACH_FORM,
2246 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2247 XmNbottomWidget, EmTabText, NULL);
2248 XmStringFree(s1);
2249 XtAddCallback(EmTabToggle, XmNvalueChangedCallback, emTabsCB, NULL);
2250 UseTabsToggle = XtVaCreateManagedWidget("useTabsToggle",
2251 xmToggleButtonWidgetClass, form,
2252 XmNlabelString, s1=XmStringCreateSimple(
2253 "Use tab characters in padding and emulated tabs"),
2254 XmNmnemonic, 'U',
2255 XmNtopAttachment, XmATTACH_WIDGET,
2256 XmNtopWidget, EmTabText,
2257 XmNtopOffset, 5,
2258 XmNleftAttachment, XmATTACH_FORM, NULL);
2259 XmStringFree(s1);
2261 /* Set default values */
2262 if (forWindow == NULL) {
2263 emTabDist = GetPrefEmTabDist(PLAIN_LANGUAGE_MODE);
2264 useTabs = GetPrefInsertTabs();
2265 tabDist = GetPrefTabDist(PLAIN_LANGUAGE_MODE);
2266 } else {
2267 XtVaGetValues(forWindow->textArea, textNemulateTabs, &emTabDist, NULL);
2268 useTabs = forWindow->buffer->useTabs;
2269 tabDist = BufGetTabDistance(forWindow->buffer);
2271 emulate = emTabDist != 0;
2272 SetIntText(TabDistText, tabDist);
2273 XmToggleButtonSetState(EmTabToggle, emulate, True);
2274 if (emulate)
2275 SetIntText(EmTabText, emTabDist);
2276 XmToggleButtonSetState(UseTabsToggle, useTabs, False);
2277 XtSetSensitive(EmTabText, emulate);
2278 XtSetSensitive(EmTabLabel, emulate);
2280 /* Handle mnemonic selection of buttons and focus to dialog */
2281 AddDialogMnemonicHandler(form, FALSE);
2283 /* Set the widget to get focus */
2284 #if XmVersion >= 1002
2285 XtVaSetValues(form, XmNinitialFocus, TabDistText, NULL);
2286 #endif
2288 /* put up dialog and wait for user to press ok or cancel */
2289 TabsDialogForWindow = forWindow;
2290 DoneWithTabsDialog = False;
2291 ManageDialogCenteredOnPointer(selBox);
2292 while (!DoneWithTabsDialog)
2294 XEvent event;
2295 XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
2296 ServerDispatchEvent(&event);
2299 XtDestroyWidget(selBox);
2302 static void tabsOKCB(Widget w, XtPointer clientData, XtPointer callData)
2304 int emulate, useTabs, stat, tabDist, emTabDist;
2305 WindowInfo *window = TabsDialogForWindow;
2307 /* get the values that the user entered and make sure they're ok */
2308 emulate = XmToggleButtonGetState(EmTabToggle);
2309 useTabs = XmToggleButtonGetState(UseTabsToggle);
2310 stat = GetIntTextWarn(TabDistText, &tabDist, "tab spacing", True);
2311 if (stat != TEXT_READ_OK)
2312 return;
2314 if (tabDist <= 0 || tabDist > MAX_EXP_CHAR_LEN)
2316 DialogF(DF_WARN, TabDistText, 1, "Tab Spacing",
2317 "Tab spacing out of range", "Dismiss");
2318 return;
2321 if (emulate) {
2322 stat = GetIntTextWarn(EmTabText, &emTabDist, "emulated tab spacing",True);
2323 if (stat != TEXT_READ_OK)
2324 return;
2326 if (emTabDist <= 0 || tabDist >= 1000)
2328 DialogF(DF_WARN, EmTabText, 1, "Tab Spacing",
2329 "Emulated tab spacing out of range", "Dismiss");
2330 return;
2332 } else
2333 emTabDist = 0;
2335 #ifdef SGI_CUSTOM
2336 /* Ask the user about saving as a default preference */
2337 if (TabsDialogForWindow != NULL) {
2338 int setDefault;
2339 if (!shortPrefToDefault(window->shell, "Tab Settings", &setDefault)) {
2340 DoneWithTabsDialog = True;
2341 return;
2343 if (setDefault) {
2344 SetPrefTabDist(tabDist);
2345 SetPrefEmTabDist(emTabDist);
2346 SetPrefInsertTabs(useTabs);
2347 SaveNEditPrefs(window->shell, GetPrefShortMenus());
2350 #endif
2352 /* Set the value in either the requested window or default preferences */
2353 if (TabsDialogForWindow == NULL) {
2354 SetPrefTabDist(tabDist);
2355 SetPrefEmTabDist(emTabDist);
2356 SetPrefInsertTabs(useTabs);
2357 } else {
2358 char *params[1];
2359 char numStr[25];
2361 params[0] = numStr;
2362 sprintf(numStr, "%d", tabDist);
2363 XtCallActionProc(window->textArea, "set_tab_dist", NULL, params, 1);
2364 params[0] = numStr;
2365 sprintf(numStr, "%d", emTabDist);
2366 XtCallActionProc(window->textArea, "set_em_tab_dist", NULL, params, 1);
2367 params[0] = numStr;
2368 sprintf(numStr, "%d", useTabs);
2369 XtCallActionProc(window->textArea, "set_use_tabs", NULL, params, 1);
2371 setTabDist(window, tabDist);
2372 setEmTabDist(window, emTabDist);
2373 window->buffer->useTabs = useTabs;
2376 DoneWithTabsDialog = True;
2379 static void tabsCancelCB(Widget w, XtPointer clientData, XtPointer callData)
2381 DoneWithTabsDialog = True;
2384 static void tabsHelpCB(Widget w, XtPointer clientData, XtPointer callData)
2386 Help(HELP_TABS_DIALOG);
2389 static void emTabsCB(Widget w, XtPointer clientData, XtPointer callData)
2391 int state = XmToggleButtonGetState(w);
2393 XtSetSensitive(EmTabLabel, state);
2394 XtSetSensitive(EmTabText, state);
2398 ** Present the user a dialog for setting wrap margin.
2400 void WrapMarginDialog(Widget parent, WindowInfo *forWindow)
2402 Widget form, selBox;
2403 Arg selBoxArgs[2];
2404 XmString s1;
2405 int margin;
2407 XtSetArg(selBoxArgs[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
2408 XtSetArg(selBoxArgs[1], XmNautoUnmanage, False);
2409 selBox = CreatePromptDialog(parent, "wrapMargin", selBoxArgs, 2);
2410 XtAddCallback(selBox, XmNokCallback, (XtCallbackProc)wrapOKCB, NULL);
2411 XtAddCallback(selBox, XmNcancelCallback, (XtCallbackProc)wrapCancelCB,NULL);
2412 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_TEXT));
2413 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_SELECTION_LABEL));
2414 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_HELP_BUTTON));
2415 XtVaSetValues(XtParent(selBox), XmNtitle, "Wrap Margin", NULL);
2417 form = XtVaCreateManagedWidget("form", xmFormWidgetClass, selBox, NULL);
2419 WrapWindowToggle = XtVaCreateManagedWidget("wrapWindowToggle",
2420 xmToggleButtonWidgetClass, form, XmNlabelString,
2421 s1=XmStringCreateSimple("Wrap and Fill at width of window"),
2422 XmNmnemonic, 'W',
2423 XmNtopAttachment, XmATTACH_FORM,
2424 XmNleftAttachment, XmATTACH_FORM, NULL);
2425 XmStringFree(s1);
2426 XtAddCallback(WrapWindowToggle, XmNvalueChangedCallback, wrapWindowCB,NULL);
2427 WrapText = XtVaCreateManagedWidget("wrapText", xmTextWidgetClass, form,
2428 XmNcolumns, 5,
2429 XmNtopAttachment, XmATTACH_WIDGET,
2430 XmNtopWidget, WrapWindowToggle,
2431 XmNrightAttachment, XmATTACH_FORM, NULL);
2432 RemapDeleteKey(WrapText);
2433 WrapTextLabel = XtVaCreateManagedWidget("wrapMarginLabel",
2434 xmLabelGadgetClass, form,
2435 XmNlabelString, s1=XmStringCreateSimple(
2436 "Margin for Wrap and Fill"),
2437 XmNmnemonic, 'M',
2438 XmNuserData, WrapText,
2439 XmNtopAttachment, XmATTACH_WIDGET,
2440 XmNtopWidget, WrapWindowToggle,
2441 XmNleftAttachment, XmATTACH_FORM,
2442 XmNrightAttachment, XmATTACH_WIDGET,
2443 XmNrightWidget, WrapText,
2444 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2445 XmNbottomWidget, WrapText, NULL);
2446 XmStringFree(s1);
2448 /* Set default value */
2449 if (forWindow == NULL)
2450 margin = GetPrefWrapMargin();
2451 else
2452 XtVaGetValues(forWindow->textArea, textNwrapMargin, &margin, NULL);
2453 XmToggleButtonSetState(WrapWindowToggle, margin==0, True);
2454 if (margin != 0)
2455 SetIntText(WrapText, margin);
2456 XtSetSensitive(WrapText, margin!=0);
2457 XtSetSensitive(WrapTextLabel, margin!=0);
2459 /* Handle mnemonic selection of buttons and focus to dialog */
2460 AddDialogMnemonicHandler(form, FALSE);
2462 /* put up dialog and wait for user to press ok or cancel */
2463 WrapDialogForWindow = forWindow;
2464 DoneWithWrapDialog = False;
2465 ManageDialogCenteredOnPointer(selBox);
2466 while (!DoneWithWrapDialog)
2468 XEvent event;
2469 XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
2470 ServerDispatchEvent(&event);
2473 XtDestroyWidget(selBox);
2476 static void wrapOKCB(Widget w, XtPointer clientData, XtPointer callData)
2478 int wrapAtWindow, margin, stat;
2479 WindowInfo *window = WrapDialogForWindow;
2481 /* get the values that the user entered and make sure they're ok */
2482 wrapAtWindow = XmToggleButtonGetState(WrapWindowToggle);
2483 if (wrapAtWindow)
2484 margin = 0;
2485 else {
2486 stat = GetIntTextWarn(WrapText, &margin, "wrap Margin", True);
2487 if (stat != TEXT_READ_OK)
2488 return;
2490 if (margin <= 0 || margin >= 1000)
2492 DialogF(DF_WARN, WrapText, 1, "Wrap Margin",
2493 "Wrap margin out of range", "Dismiss");
2494 return;
2499 #ifdef SGI_CUSTOM
2500 /* Ask the user about saving as a default preference */
2501 if (WrapDialogForWindow != NULL) {
2502 int setDefault;
2503 if (!shortPrefToDefault(window->shell, "Wrap Margin Settings",
2504 &setDefault)) {
2505 DoneWithWrapDialog = True;
2506 return;
2508 if (setDefault) {
2509 SetPrefWrapMargin(margin);
2510 SaveNEditPrefs(window->shell, GetPrefShortMenus());
2513 #endif
2515 /* Set the value in either the requested window or default preferences */
2516 if (WrapDialogForWindow == NULL)
2517 SetPrefWrapMargin(margin);
2518 else {
2519 char *params[1];
2520 char marginStr[25];
2521 sprintf(marginStr, "%d", margin);
2522 params[0] = marginStr;
2523 XtCallActionProc(window->textArea, "set_wrap_margin", NULL, params, 1);
2525 DoneWithWrapDialog = True;
2528 static void wrapCancelCB(Widget w, XtPointer clientData, XtPointer callData)
2530 DoneWithWrapDialog = True;
2533 static void wrapWindowCB(Widget w, XtPointer clientData, XtPointer callData)
2535 int wrapAtWindow = XmToggleButtonGetState(w);
2537 XtSetSensitive(WrapTextLabel, !wrapAtWindow);
2538 XtSetSensitive(WrapText, !wrapAtWindow);
2542 ** Present a dialog for editing language mode information
2544 void EditLanguageModes()
2546 #define LIST_RIGHT 40
2547 #define LEFT_MARGIN_POS 1
2548 #define RIGHT_MARGIN_POS 99
2549 #define H_MARGIN 5
2550 Widget form, nameLbl, topLbl, extLbl, recogLbl, delimitLbl, defTipsLbl;
2551 Widget okBtn, applyBtn, dismissBtn;
2552 Widget overrideFrame, overrideForm, delimitForm;
2553 Widget tabForm, tabLbl, indentBox, wrapBox;
2554 XmString s1;
2555 int i, ac;
2556 Arg args[20];
2558 /* if the dialog is already displayed, just pop it to the top and return */
2559 if (LMDialog.shell != NULL) {
2560 RaiseShellWindow(LMDialog.shell);
2561 return;
2564 LMDialog.languageModeList = (languageModeRec **)XtMalloc(
2565 sizeof(languageModeRec *) * MAX_LANGUAGE_MODES);
2566 for (i=0; i<NLanguageModes; i++)
2567 LMDialog.languageModeList[i] = copyLanguageModeRec(LanguageModes[i]);
2568 LMDialog.nLanguageModes = NLanguageModes;
2570 /* Create a form widget in an application shell */
2571 ac = 0;
2572 XtSetArg(args[ac], XmNdeleteResponse, XmDO_NOTHING); ac++;
2573 XtSetArg(args[ac], XmNiconName, "NEdit Language Modes"); ac++;
2574 XtSetArg(args[ac], XmNtitle, "Language Modes"); ac++;
2575 LMDialog.shell = CreateShellWithBestVis(APP_NAME, APP_CLASS,
2576 applicationShellWidgetClass, TheDisplay, args, ac);
2577 AddSmallIcon(LMDialog.shell);
2578 form = XtVaCreateManagedWidget("editLanguageModes", xmFormWidgetClass,
2579 LMDialog.shell, XmNautoUnmanage, False,
2580 XmNresizePolicy, XmRESIZE_NONE, NULL);
2581 XtAddCallback(form, XmNdestroyCallback, lmDestroyCB, NULL);
2582 AddMotifCloseCallback(LMDialog.shell, lmDismissCB, NULL);
2584 topLbl = XtVaCreateManagedWidget("topLabel", xmLabelGadgetClass, form,
2585 XmNlabelString, s1=MKSTRING(
2586 "To modify the properties of an existing language mode, select the name from\n\
2587 the list on the left. To add a new language, select \"New\" from the list."),
2588 XmNmnemonic, 'N',
2589 XmNtopAttachment, XmATTACH_POSITION,
2590 XmNtopPosition, 2,
2591 XmNleftAttachment, XmATTACH_POSITION,
2592 XmNleftPosition, LEFT_MARGIN_POS,
2593 XmNrightAttachment, XmATTACH_POSITION,
2594 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
2595 XmStringFree(s1);
2597 nameLbl = XtVaCreateManagedWidget("nameLbl", xmLabelGadgetClass, form,
2598 XmNlabelString, s1=XmStringCreateSimple("Name"),
2599 XmNmnemonic, 'm',
2600 XmNalignment, XmALIGNMENT_BEGINNING,
2601 XmNleftAttachment, XmATTACH_POSITION,
2602 XmNleftPosition, LIST_RIGHT,
2603 XmNtopAttachment, XmATTACH_WIDGET,
2604 XmNtopOffset, H_MARGIN,
2605 XmNtopWidget, topLbl, NULL);
2606 XmStringFree(s1);
2608 LMDialog.nameW = XtVaCreateManagedWidget("name", xmTextWidgetClass, form,
2609 XmNcolumns, 15,
2610 XmNleftAttachment, XmATTACH_POSITION,
2611 XmNleftPosition, LIST_RIGHT,
2612 XmNtopAttachment, XmATTACH_WIDGET,
2613 XmNtopWidget, nameLbl,
2614 XmNrightAttachment, XmATTACH_POSITION,
2615 XmNrightPosition, (RIGHT_MARGIN_POS + LIST_RIGHT)/2, NULL);
2616 RemapDeleteKey(LMDialog.nameW);
2617 XtVaSetValues(nameLbl, XmNuserData, LMDialog.nameW, NULL);
2619 extLbl = XtVaCreateManagedWidget("extLbl", xmLabelGadgetClass, form,
2620 XmNlabelString,
2621 s1=XmStringCreateSimple("File extensions (separate w/ space)"),
2622 XmNmnemonic, 'F',
2623 XmNalignment, XmALIGNMENT_BEGINNING,
2624 XmNleftAttachment, XmATTACH_POSITION,
2625 XmNleftPosition, LIST_RIGHT,
2626 XmNtopAttachment, XmATTACH_WIDGET,
2627 XmNtopOffset, H_MARGIN,
2628 XmNtopWidget, LMDialog.nameW, NULL);
2629 XmStringFree(s1);
2631 LMDialog.extW = XtVaCreateManagedWidget("ext", xmTextWidgetClass, form,
2632 XmNleftAttachment, XmATTACH_POSITION,
2633 XmNleftPosition, LIST_RIGHT,
2634 XmNtopAttachment, XmATTACH_WIDGET,
2635 XmNtopWidget, extLbl,
2636 XmNrightAttachment, XmATTACH_POSITION,
2637 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
2638 RemapDeleteKey(LMDialog.extW);
2639 XtVaSetValues(extLbl, XmNuserData, LMDialog.extW, NULL);
2641 recogLbl = XtVaCreateManagedWidget("recogLbl", xmLabelGadgetClass, form,
2642 XmNlabelString, s1=MKSTRING(
2643 "Recognition regular expression (applied to first 200\n\
2644 characters of file to determine type from content)"),
2645 XmNalignment, XmALIGNMENT_BEGINNING,
2646 XmNmnemonic, 'R',
2647 XmNleftAttachment, XmATTACH_POSITION,
2648 XmNleftPosition, LIST_RIGHT,
2649 XmNtopAttachment, XmATTACH_WIDGET,
2650 XmNtopOffset, H_MARGIN,
2651 XmNtopWidget, LMDialog.extW, NULL);
2652 XmStringFree(s1);
2654 LMDialog.recogW = XtVaCreateManagedWidget("recog", xmTextWidgetClass, form,
2655 XmNleftAttachment, XmATTACH_POSITION,
2656 XmNleftPosition, LIST_RIGHT,
2657 XmNtopAttachment, XmATTACH_WIDGET,
2658 XmNtopWidget, recogLbl,
2659 XmNrightAttachment, XmATTACH_POSITION,
2660 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
2661 RemapDeleteKey(LMDialog.recogW);
2662 XtVaSetValues(recogLbl, XmNuserData, LMDialog.recogW, NULL);
2664 defTipsLbl = XtVaCreateManagedWidget("defTipsLbl", xmLabelGadgetClass, form,
2665 XmNlabelString, s1=MKSTRING(
2666 "Default calltips file(s) (separate w/colons)"),
2667 XmNalignment, XmALIGNMENT_BEGINNING,
2668 XmNmnemonic, 'c',
2669 XmNleftAttachment, XmATTACH_POSITION,
2670 XmNleftPosition, LIST_RIGHT,
2671 XmNtopAttachment, XmATTACH_WIDGET,
2672 XmNtopOffset, H_MARGIN,
2673 XmNtopWidget, LMDialog.recogW, NULL);
2674 XmStringFree(s1);
2676 LMDialog.defTipsW = XtVaCreateManagedWidget("defTips", xmTextWidgetClass,
2677 form,
2678 XmNleftAttachment, XmATTACH_POSITION,
2679 XmNleftPosition, LIST_RIGHT,
2680 XmNtopAttachment, XmATTACH_WIDGET,
2681 XmNtopWidget, defTipsLbl,
2682 XmNrightAttachment, XmATTACH_POSITION,
2683 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
2684 RemapDeleteKey(LMDialog.defTipsW);
2685 XtVaSetValues(defTipsLbl, XmNuserData, LMDialog.defTipsW, NULL);
2687 okBtn = XtVaCreateManagedWidget("ok", xmPushButtonWidgetClass, form,
2688 XmNlabelString, s1=XmStringCreateSimple("OK"),
2689 XmNleftAttachment, XmATTACH_POSITION,
2690 XmNleftPosition, 10,
2691 XmNrightAttachment, XmATTACH_POSITION,
2692 XmNrightPosition, 30,
2693 XmNbottomAttachment, XmATTACH_POSITION,
2694 XmNbottomPosition, 99, NULL);
2695 XtAddCallback(okBtn, XmNactivateCallback, lmOkCB, NULL);
2696 XmStringFree(s1);
2698 applyBtn = XtVaCreateManagedWidget("apply", xmPushButtonWidgetClass, form,
2699 XmNlabelString, s1=XmStringCreateSimple("Apply"),
2700 XmNmnemonic, 'A',
2701 XmNleftAttachment, XmATTACH_POSITION,
2702 XmNleftPosition, 40,
2703 XmNrightAttachment, XmATTACH_POSITION,
2704 XmNrightPosition, 60,
2705 XmNbottomAttachment, XmATTACH_POSITION,
2706 XmNbottomPosition, 99, NULL);
2707 XtAddCallback(applyBtn, XmNactivateCallback, lmApplyCB, NULL);
2708 XmStringFree(s1);
2710 dismissBtn = XtVaCreateManagedWidget("dismiss",xmPushButtonWidgetClass,form,
2711 XmNlabelString, s1=XmStringCreateSimple("Dismiss"),
2712 XmNleftAttachment, XmATTACH_POSITION,
2713 XmNleftPosition, 70,
2714 XmNrightAttachment, XmATTACH_POSITION,
2715 XmNrightPosition, 90,
2716 XmNbottomAttachment, XmATTACH_POSITION,
2717 XmNbottomPosition, 99, NULL);
2718 XtAddCallback(dismissBtn, XmNactivateCallback, lmDismissCB, NULL);
2719 XmStringFree(s1);
2721 overrideFrame = XtVaCreateManagedWidget("overrideFrame",
2722 xmFrameWidgetClass, form,
2723 XmNleftAttachment, XmATTACH_POSITION,
2724 XmNleftPosition, LEFT_MARGIN_POS,
2725 XmNrightAttachment, XmATTACH_POSITION,
2726 XmNrightPosition, RIGHT_MARGIN_POS,
2727 XmNbottomAttachment, XmATTACH_WIDGET,
2728 XmNbottomWidget, dismissBtn,
2729 XmNbottomOffset, H_MARGIN, NULL);
2730 overrideForm = XtVaCreateManagedWidget("overrideForm", xmFormWidgetClass,
2731 overrideFrame, NULL);
2732 XtVaCreateManagedWidget("overrideLbl", xmLabelGadgetClass, overrideFrame,
2733 XmNlabelString, s1=XmStringCreateSimple("Override Defaults"),
2734 XmNchildType, XmFRAME_TITLE_CHILD,
2735 XmNchildHorizontalAlignment, XmALIGNMENT_CENTER, NULL);
2736 XmStringFree(s1);
2738 delimitForm = XtVaCreateManagedWidget("delimitForm", xmFormWidgetClass,
2739 overrideForm,
2740 XmNleftAttachment, XmATTACH_POSITION,
2741 XmNleftPosition, LEFT_MARGIN_POS,
2742 XmNtopAttachment, XmATTACH_FORM,
2743 XmNtopOffset, H_MARGIN,
2744 XmNrightAttachment, XmATTACH_POSITION,
2745 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
2746 delimitLbl = XtVaCreateManagedWidget("delimitLbl", xmLabelGadgetClass,
2747 delimitForm,
2748 XmNlabelString, s1=XmStringCreateSimple("Word delimiters"),
2749 XmNmnemonic, 'W',
2750 XmNleftAttachment, XmATTACH_FORM,
2751 XmNtopAttachment, XmATTACH_FORM,
2752 XmNbottomAttachment, XmATTACH_FORM, NULL);
2753 XmStringFree(s1);
2754 LMDialog.delimitW = XtVaCreateManagedWidget("delimit", xmTextWidgetClass,
2755 delimitForm,
2756 XmNtopAttachment, XmATTACH_FORM,
2757 XmNleftAttachment, XmATTACH_WIDGET,
2758 XmNleftWidget, delimitLbl,
2759 XmNrightAttachment, XmATTACH_FORM,
2760 XmNbottomAttachment, XmATTACH_FORM, NULL);
2761 RemapDeleteKey(LMDialog.delimitW);
2762 XtVaSetValues(delimitLbl, XmNuserData, LMDialog.delimitW, NULL);
2764 tabForm = XtVaCreateManagedWidget("tabForm", xmFormWidgetClass,
2765 overrideForm,
2766 XmNleftAttachment, XmATTACH_POSITION,
2767 XmNleftPosition, LEFT_MARGIN_POS,
2768 XmNtopAttachment, XmATTACH_WIDGET,
2769 XmNtopWidget, delimitForm,
2770 XmNtopOffset, H_MARGIN,
2771 XmNrightAttachment, XmATTACH_POSITION,
2772 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
2773 tabLbl = XtVaCreateManagedWidget("tabLbl", xmLabelGadgetClass, tabForm,
2774 XmNlabelString, s1=XmStringCreateSimple(
2775 "Alternative hardware tab spacing"),
2776 XmNmnemonic, 't',
2777 XmNleftAttachment, XmATTACH_FORM,
2778 XmNtopAttachment, XmATTACH_FORM,
2779 XmNbottomAttachment, XmATTACH_FORM, NULL);
2780 XmStringFree(s1);
2781 LMDialog.tabW = XtVaCreateManagedWidget("delimit", xmTextWidgetClass,
2782 tabForm,
2783 XmNcolumns, 3,
2784 XmNtopAttachment, XmATTACH_FORM,
2785 XmNleftAttachment, XmATTACH_WIDGET,
2786 XmNleftWidget, tabLbl,
2787 XmNbottomAttachment, XmATTACH_FORM, NULL);
2788 RemapDeleteKey(LMDialog.tabW);
2789 XtVaSetValues(tabLbl, XmNuserData, LMDialog.tabW, NULL);
2790 LMDialog.emTabW = XtVaCreateManagedWidget("delimit", xmTextWidgetClass,
2791 tabForm,
2792 XmNcolumns, 3,
2793 XmNtopAttachment, XmATTACH_FORM,
2794 XmNrightAttachment, XmATTACH_FORM,
2795 XmNbottomAttachment, XmATTACH_FORM, NULL);
2796 RemapDeleteKey(LMDialog.emTabW);
2797 XtVaCreateManagedWidget("emTabLbl", xmLabelGadgetClass, tabForm,
2798 XmNlabelString,
2799 s1=XmStringCreateSimple("Alternative emulated tab spacing"),
2800 XmNalignment, XmALIGNMENT_END,
2801 XmNmnemonic, 'e',
2802 XmNuserData, LMDialog.emTabW,
2803 XmNleftAttachment, XmATTACH_WIDGET,
2804 XmNleftWidget, LMDialog.tabW,
2805 XmNrightAttachment, XmATTACH_WIDGET,
2806 XmNrightWidget, LMDialog.emTabW,
2807 XmNtopAttachment, XmATTACH_FORM,
2808 XmNbottomAttachment, XmATTACH_FORM, NULL);
2809 XmStringFree(s1);
2811 indentBox = XtVaCreateManagedWidget("indentBox", xmRowColumnWidgetClass,
2812 overrideForm,
2813 XmNorientation, XmHORIZONTAL,
2814 XmNpacking, XmPACK_TIGHT,
2815 XmNradioBehavior, True,
2816 XmNleftAttachment, XmATTACH_POSITION,
2817 XmNleftPosition, LEFT_MARGIN_POS,
2818 XmNtopAttachment, XmATTACH_WIDGET,
2819 XmNtopWidget, tabForm,
2820 XmNtopOffset, H_MARGIN, NULL);
2821 LMDialog.defaultIndentW = XtVaCreateManagedWidget("defaultIndent",
2822 xmToggleButtonWidgetClass, indentBox,
2823 XmNset, True,
2824 XmNmarginHeight, 0,
2825 XmNlabelString, s1=XmStringCreateSimple("Default indent style"),
2826 XmNmnemonic, 'D', NULL);
2827 XmStringFree(s1);
2828 LMDialog.noIndentW = XtVaCreateManagedWidget("noIndent",
2829 xmToggleButtonWidgetClass, indentBox,
2830 XmNmarginHeight, 0,
2831 XmNlabelString, s1=XmStringCreateSimple("No automatic indent"),
2832 XmNmnemonic, 'N', NULL);
2833 XmStringFree(s1);
2834 LMDialog.autoIndentW = XtVaCreateManagedWidget("autoIndent",
2835 xmToggleButtonWidgetClass, indentBox,
2836 XmNmarginHeight, 0,
2837 XmNlabelString, s1=XmStringCreateSimple("Auto-indent"),
2838 XmNmnemonic, 'A', NULL);
2839 XmStringFree(s1);
2840 LMDialog.smartIndentW = XtVaCreateManagedWidget("smartIndent",
2841 xmToggleButtonWidgetClass, indentBox,
2842 XmNmarginHeight, 0,
2843 XmNlabelString, s1=XmStringCreateSimple("Smart-indent"),
2844 XmNmnemonic, 'S', NULL);
2845 XmStringFree(s1);
2847 wrapBox = XtVaCreateManagedWidget("wrapBox", xmRowColumnWidgetClass,
2848 overrideForm,
2849 XmNorientation, XmHORIZONTAL,
2850 XmNpacking, XmPACK_TIGHT,
2851 XmNradioBehavior, True,
2852 XmNleftAttachment, XmATTACH_POSITION,
2853 XmNleftPosition, LEFT_MARGIN_POS,
2854 XmNtopAttachment, XmATTACH_WIDGET,
2855 XmNtopWidget, indentBox,
2856 XmNtopOffset, H_MARGIN,
2857 XmNbottomAttachment, XmATTACH_FORM,
2858 XmNbottomOffset, H_MARGIN, NULL);
2859 LMDialog.defaultWrapW = XtVaCreateManagedWidget("defaultWrap",
2860 xmToggleButtonWidgetClass, wrapBox,
2861 XmNset, True,
2862 XmNmarginHeight, 0,
2863 XmNlabelString, s1=XmStringCreateSimple("Default wrap style"),
2864 XmNmnemonic, 'D', NULL);
2865 XmStringFree(s1);
2866 LMDialog.noWrapW = XtVaCreateManagedWidget("noWrap",
2867 xmToggleButtonWidgetClass, wrapBox,
2868 XmNmarginHeight, 0,
2869 XmNlabelString, s1=XmStringCreateSimple("No wrapping"),
2870 XmNmnemonic, 'N', NULL);
2871 XmStringFree(s1);
2872 LMDialog.newlineWrapW = XtVaCreateManagedWidget("newlineWrap",
2873 xmToggleButtonWidgetClass, wrapBox,
2874 XmNmarginHeight, 0,
2875 XmNlabelString, s1=XmStringCreateSimple("Auto newline wrap"),
2876 XmNmnemonic, 'A', NULL);
2877 XmStringFree(s1);
2878 LMDialog.contWrapW = XtVaCreateManagedWidget("contWrap",
2879 xmToggleButtonWidgetClass, wrapBox,
2880 XmNmarginHeight, 0,
2881 XmNlabelString, s1=XmStringCreateSimple("Continuous wrap"),
2882 XmNmnemonic, 'C', NULL);
2883 XmStringFree(s1);
2885 XtVaCreateManagedWidget("stretchForm", xmFormWidgetClass, form,
2886 XmNtopAttachment, XmATTACH_WIDGET,
2887 XmNtopWidget, LMDialog.defTipsW,
2888 XmNleftAttachment, XmATTACH_POSITION,
2889 XmNleftPosition, LIST_RIGHT,
2890 XmNrightAttachment, XmATTACH_POSITION,
2891 XmNrightPosition, RIGHT_MARGIN_POS,
2892 XmNbottomAttachment, XmATTACH_WIDGET,
2893 XmNbottomWidget, overrideFrame,
2894 XmNbottomOffset, H_MARGIN*2, NULL);
2896 ac = 0;
2897 XtSetArg(args[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
2898 XtSetArg(args[ac], XmNtopOffset, H_MARGIN); ac++;
2899 XtSetArg(args[ac], XmNtopWidget, topLbl); ac++;
2900 XtSetArg(args[ac], XmNleftAttachment, XmATTACH_POSITION); ac++;
2901 XtSetArg(args[ac], XmNleftPosition, LEFT_MARGIN_POS); ac++;
2902 XtSetArg(args[ac], XmNrightAttachment, XmATTACH_POSITION); ac++;
2903 XtSetArg(args[ac], XmNrightPosition, LIST_RIGHT-1); ac++;
2904 XtSetArg(args[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
2905 XtSetArg(args[ac], XmNbottomWidget, overrideFrame); ac++;
2906 XtSetArg(args[ac], XmNbottomOffset, H_MARGIN*2); ac++;
2907 LMDialog.managedListW = CreateManagedList(form, "list", args, ac,
2908 (void **)LMDialog.languageModeList, &LMDialog.nLanguageModes,
2909 MAX_LANGUAGE_MODES, 15, lmGetDisplayedCB, NULL, lmSetDisplayedCB,
2910 NULL, lmFreeItemCB);
2911 AddDeleteConfirmCB(LMDialog.managedListW, lmDeleteConfirmCB, NULL);
2912 XtVaSetValues(topLbl, XmNuserData, LMDialog.managedListW, NULL);
2914 /* Set initial default button */
2915 XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
2916 XtVaSetValues(form, XmNcancelButton, dismissBtn, NULL);
2918 /* Handle mnemonic selection of buttons and focus to dialog */
2919 AddDialogMnemonicHandler(form, FALSE);
2921 /* Realize all of the widgets in the new dialog */
2922 RealizeWithoutForcingPosition(LMDialog.shell);
2925 static void lmDestroyCB(Widget w, XtPointer clientData, XtPointer callData)
2927 int i;
2929 for (i=0; i<LMDialog.nLanguageModes; i++)
2930 freeLanguageModeRec(LMDialog.languageModeList[i]);
2931 XtFree((char *)LMDialog.languageModeList);
2934 static void lmOkCB(Widget w, XtPointer clientData, XtPointer callData)
2936 if (!updateLMList())
2937 return;
2939 /* pop down and destroy the dialog */
2940 XtDestroyWidget(LMDialog.shell);
2941 LMDialog.shell = NULL;
2944 static void lmApplyCB(Widget w, XtPointer clientData, XtPointer callData)
2946 updateLMList();
2949 static void lmDismissCB(Widget w, XtPointer clientData, XtPointer callData)
2951 /* pop down and destroy the dialog */
2952 XtDestroyWidget(LMDialog.shell);
2953 LMDialog.shell = NULL;
2956 static int lmDeleteConfirmCB(int itemIndex, void *cbArg)
2958 int i;
2960 /* Allow duplicate names to be deleted regardless of dependencies */
2961 for (i=0; i<LMDialog.nLanguageModes; i++)
2962 if (i != itemIndex && !strcmp(LMDialog.languageModeList[i]->name,
2963 LMDialog.languageModeList[itemIndex]->name))
2964 return True;
2966 /* don't allow deletion if data will be lost */
2967 if (LMHasHighlightPatterns(LMDialog.languageModeList[itemIndex]->name))
2969 DialogF(DF_WARN, LMDialog.shell, 1, "Patterns exist",
2970 "This language mode has syntax highlighting\n"
2971 "patterns defined. Please delete the patterns\n"
2972 "first, in Preferences -> Default Settings ->\n"
2973 "Syntax Highlighting, before proceeding here.", "Dismiss");
2974 return False;
2977 /* don't allow deletion if data will be lost */
2978 if (LMHasSmartIndentMacros(LMDialog.languageModeList[itemIndex]->name))
2980 DialogF(DF_WARN, LMDialog.shell, 1, "Smart Indent Macros exist",
2981 "This language mode has smart indent macros\n"
2982 "defined. Please delete the macros first,\n"
2983 "in Preferences -> Default Settings ->\n"
2984 "Auto Indent -> Program Smart Indent,\n"
2985 "before proceeding here.", "Dismiss");
2986 return False;
2989 return True;
2993 ** Apply the changes that the user has made in the language modes dialog to the
2994 ** stored language mode information for this NEdit session (the data array
2995 ** LanguageModes)
2997 static int updateLMList(void)
2999 WindowInfo *window;
3000 char *oldModeName, *newDelimiters;
3001 int i, j;
3003 /* Get the current contents of the dialog fields */
3004 if (!UpdateManagedList(LMDialog.managedListW, True))
3005 return False;
3007 /* Fix up language mode indices in all open windows (which may change
3008 if the currently selected mode is deleted or has changed position),
3009 and update word delimiters */
3010 for (window=WindowList; window!=NULL; window=window->next) {
3011 if (window->languageMode != PLAIN_LANGUAGE_MODE) {
3012 oldModeName = LanguageModes[window->languageMode]->name;
3013 window->languageMode = PLAIN_LANGUAGE_MODE;
3014 for (i=0; i<LMDialog.nLanguageModes; i++) {
3015 if (!strcmp(oldModeName, LMDialog.languageModeList[i]->name)) {
3016 newDelimiters = LMDialog.languageModeList[i]->delimiters;
3017 if (newDelimiters == NULL)
3018 newDelimiters = GetPrefDelimiters();
3019 XtVaSetValues(window->textArea, textNwordDelimiters,
3020 newDelimiters, NULL);
3021 for (j=0; j<window->nPanes; j++)
3022 XtVaSetValues(window->textPanes[j],
3023 textNwordDelimiters, newDelimiters, NULL);
3024 window->languageMode = i;
3025 break;
3031 /* If there were any name changes, re-name dependent highlight patterns
3032 and smart-indent macros and fix up the weird rename-format names */
3033 for (i=0; i<LMDialog.nLanguageModes; i++) {
3034 if (strchr(LMDialog.languageModeList[i]->name, ':') != NULL) {
3035 char *newName = strrchr(LMDialog.languageModeList[i]->name, ':')+1;
3036 *strchr(LMDialog.languageModeList[i]->name, ':') = '\0';
3037 RenameHighlightPattern(LMDialog.languageModeList[i]->name, newName);
3038 RenameSmartIndentMacros(LMDialog.languageModeList[i]->name, newName);
3039 memmove(LMDialog.languageModeList[i]->name, newName,
3040 strlen(newName) + 1);
3041 ChangeManagedListData(LMDialog.managedListW);
3045 /* Unload any default calltips file that is no longer a default. */
3046 for (i=0; i<NLanguageModes; i++) {
3047 if (!LanguageModes[i]->defTipsFile)
3048 continue;
3049 for (j=0; j<LMDialog.nLanguageModes; j++) {
3050 if (!LMDialog.languageModeList[j]->defTipsFile)
3051 continue;
3052 if (!strcmp(LanguageModes[i]->defTipsFile,
3053 LMDialog.languageModeList[j]->defTipsFile))
3054 break;
3056 if ( j==LMDialog.nLanguageModes )
3057 DeleteTagsFile(LanguageModes[i]->defTipsFile, TIP);
3060 /* Replace the old language mode list with the new one from the dialog */
3061 for (i=0; i<NLanguageModes; i++)
3062 freeLanguageModeRec(LanguageModes[i]);
3063 for (i=0; i<LMDialog.nLanguageModes; i++)
3064 LanguageModes[i] = copyLanguageModeRec(LMDialog.languageModeList[i]);
3065 NLanguageModes = LMDialog.nLanguageModes;
3067 /* Update the menus in the window menu bars and load any needed
3068 calltips files */
3069 for (window=WindowList; window!=NULL; window=window->next) {
3070 updateLanguageModeSubmenu(window);
3071 if (window->languageMode != PLAIN_LANGUAGE_MODE &&
3072 LanguageModes[window->languageMode]->defTipsFile != NULL)
3073 AddTagsFile(LanguageModes[window->languageMode]->defTipsFile, TIP);
3076 /* If a syntax highlighting dialog is up, update its menu */
3077 UpdateLanguageModeMenu();
3078 /* The same for the smart indent macro dialog */
3079 UpdateLangModeMenuSmartIndent();
3080 /* Note that preferences have been changed */
3081 MarkPrefsChanged();
3083 return True;
3086 static void *lmGetDisplayedCB(void *oldItem, int explicitRequest, int *abort,
3087 void *cbArg)
3089 languageModeRec *lm, *oldLM = (languageModeRec *)oldItem;
3090 char *tempName;
3091 int i, nCopies, oldLen;
3093 /* If the dialog is currently displaying the "new" entry and the
3094 fields are empty, that's just fine */
3095 if (oldItem == NULL && lmDialogEmpty())
3096 return NULL;
3098 /* Read the data the user has entered in the dialog fields */
3099 lm = readLMDialogFields(True);
3101 /* If there was a name change of a non-duplicate language mode, modify the
3102 name to the weird format of: ":old name:new name". This signals that a
3103 name change is necessary in lm dependent data such as highlight
3104 patterns. Duplicate language modes may be re-named at will, since no
3105 data will be lost due to the name change. */
3106 if (lm != NULL && oldLM != NULL && strcmp(oldLM->name, lm->name)) {
3107 nCopies = 0;
3108 for (i=0; i<LMDialog.nLanguageModes; i++)
3109 if (!strcmp(oldLM->name, LMDialog.languageModeList[i]->name))
3110 nCopies++;
3111 if (nCopies <= 1) {
3112 oldLen = strchr(oldLM->name, ':') == NULL ? strlen(oldLM->name) :
3113 strchr(oldLM->name, ':') - oldLM->name;
3114 tempName = XtMalloc(oldLen + strlen(lm->name) + 2);
3115 strncpy(tempName, oldLM->name, oldLen);
3116 sprintf(&tempName[oldLen], ":%s", lm->name);
3117 XtFree(lm->name);
3118 lm->name = tempName;
3122 /* If there are no problems reading the data, just return it */
3123 if (lm != NULL)
3124 return (void *)lm;
3126 /* If there are problems, and the user didn't ask for the fields to be
3127 read, give more warning */
3128 if (!explicitRequest)
3130 if (DialogF(DF_WARN, LMDialog.shell, 2, "Discard Language Mode",
3131 "Discard incomplete entry\nfor current language mode?", "Keep",
3132 "Discard") == 2)
3134 return oldItem == NULL
3135 ? NULL
3136 : (void *)copyLanguageModeRec((languageModeRec *)oldItem);
3140 /* Do readLMDialogFields again without "silent" mode to display warning */
3141 lm = readLMDialogFields(False);
3142 *abort = True;
3143 return NULL;
3146 static void lmSetDisplayedCB(void *item, void *cbArg)
3148 languageModeRec *lm = (languageModeRec *)item;
3149 char *extStr;
3151 if (item == NULL) {
3152 XmTextSetString(LMDialog.nameW, "");
3153 XmTextSetString(LMDialog.extW, "");
3154 XmTextSetString(LMDialog.recogW, "");
3155 XmTextSetString(LMDialog.defTipsW, "");
3156 XmTextSetString(LMDialog.delimitW, "");
3157 XmTextSetString(LMDialog.tabW, "");
3158 XmTextSetString(LMDialog.emTabW, "");
3159 XmToggleButtonSetState(LMDialog.defaultIndentW, True, True);
3160 XmToggleButtonSetState(LMDialog.defaultWrapW, True, True);
3161 } else {
3162 XmTextSetString(LMDialog.nameW, strchr(lm->name, ':') == NULL ?
3163 lm->name : strchr(lm->name, ':')+1);
3164 extStr = createExtString(lm->extensions, lm->nExtensions);
3165 XmTextSetString(LMDialog.extW, extStr);
3166 XtFree(extStr);
3167 XmTextSetString(LMDialog.recogW, lm->recognitionExpr);
3168 XmTextSetString(LMDialog.defTipsW, lm->defTipsFile);
3169 XmTextSetString(LMDialog.delimitW, lm->delimiters);
3170 if (lm->tabDist == DEFAULT_TAB_DIST)
3171 XmTextSetString(LMDialog.tabW, "");
3172 else
3173 SetIntText(LMDialog.tabW, lm->tabDist);
3174 if (lm->emTabDist == DEFAULT_EM_TAB_DIST)
3175 XmTextSetString(LMDialog.emTabW, "");
3176 else
3177 SetIntText(LMDialog.emTabW, lm->emTabDist);
3178 XmToggleButtonSetState(LMDialog.defaultIndentW,
3179 lm->indentStyle == DEFAULT_INDENT, False);
3180 XmToggleButtonSetState(LMDialog.noIndentW,
3181 lm->indentStyle == NO_AUTO_INDENT, False);
3182 XmToggleButtonSetState(LMDialog.autoIndentW,
3183 lm->indentStyle == AUTO_INDENT, False);
3184 XmToggleButtonSetState(LMDialog.smartIndentW,
3185 lm->indentStyle == SMART_INDENT, False);
3186 XmToggleButtonSetState(LMDialog.defaultWrapW,
3187 lm->wrapStyle == DEFAULT_WRAP, False);
3188 XmToggleButtonSetState(LMDialog.noWrapW,
3189 lm->wrapStyle == NO_WRAP, False);
3190 XmToggleButtonSetState(LMDialog.newlineWrapW,
3191 lm->wrapStyle == NEWLINE_WRAP, False);
3192 XmToggleButtonSetState(LMDialog.contWrapW,
3193 lm->wrapStyle == CONTINUOUS_WRAP, False);
3197 static void lmFreeItemCB(void *item)
3199 freeLanguageModeRec((languageModeRec *)item);
3202 static void freeLanguageModeRec(languageModeRec *lm)
3204 int i;
3206 XtFree(lm->name);
3207 if (lm->recognitionExpr != NULL)
3208 XtFree(lm->recognitionExpr);
3209 if (lm->defTipsFile != NULL)
3210 XtFree(lm->defTipsFile);
3211 if (lm->delimiters != NULL)
3212 XtFree(lm->delimiters);
3213 for (i=0; i<lm->nExtensions; i++)
3214 XtFree(lm->extensions[i]);
3215 if (lm->nExtensions != 0)
3216 XtFree((char *)lm->extensions);
3217 XtFree((char *)lm);
3221 ** Copy a languageModeRec data structure and all of the allocated data it contains
3223 static languageModeRec *copyLanguageModeRec(languageModeRec *lm)
3225 languageModeRec *newLM;
3226 int i;
3228 newLM = (languageModeRec *)XtMalloc(sizeof(languageModeRec));
3229 newLM->name = XtMalloc(strlen(lm->name)+1);
3230 strcpy(newLM->name, lm->name);
3231 newLM->nExtensions = lm->nExtensions;
3232 newLM->extensions = (char **)XtMalloc(sizeof(char *) * lm->nExtensions);
3233 for (i=0; i<lm->nExtensions; i++) {
3234 newLM->extensions[i] = XtMalloc(strlen(lm->extensions[i]) + 1);
3235 strcpy(newLM->extensions[i], lm->extensions[i]);
3237 if (lm->recognitionExpr == NULL)
3238 newLM->recognitionExpr = NULL;
3239 else {
3240 newLM->recognitionExpr = XtMalloc(strlen(lm->recognitionExpr)+1);
3241 strcpy(newLM->recognitionExpr, lm->recognitionExpr);
3243 if (lm->defTipsFile == NULL)
3244 newLM->defTipsFile = NULL;
3245 else {
3246 newLM->defTipsFile = XtMalloc(strlen(lm->defTipsFile)+1);
3247 strcpy(newLM->defTipsFile, lm->defTipsFile);
3249 if (lm->delimiters == NULL)
3250 newLM->delimiters = NULL;
3251 else {
3252 newLM->delimiters = XtMalloc(strlen(lm->delimiters)+1);
3253 strcpy(newLM->delimiters, lm->delimiters);
3255 newLM->wrapStyle = lm->wrapStyle;
3256 newLM->indentStyle = lm->indentStyle;
3257 newLM->tabDist = lm->tabDist;
3258 newLM->emTabDist = lm->emTabDist;
3259 return newLM;
3263 ** Read the fields in the language modes dialog and create a languageModeRec data
3264 ** structure reflecting the current state of the selected language mode in the dialog.
3265 ** If any of the information is incorrect or missing, display a warning dialog and
3266 ** return NULL. Passing "silent" as True, suppresses the warning dialogs.
3268 static languageModeRec *readLMDialogFields(int silent)
3270 languageModeRec *lm;
3271 regexp *compiledRE;
3272 char *compileMsg, *extStr, *extPtr;
3274 /* Allocate a language mode structure to return, set unread fields to
3275 empty so everything can be freed on errors by freeLanguageModeRec */
3276 lm = (languageModeRec *)XtMalloc(sizeof(languageModeRec));
3277 lm->nExtensions = 0;
3278 lm->recognitionExpr = NULL;
3279 lm->defTipsFile = NULL;
3280 lm->delimiters = NULL;
3282 /* read the name field */
3283 lm->name = ReadSymbolicFieldTextWidget(LMDialog.nameW,
3284 "language mode name", silent);
3285 if (lm->name == NULL) {
3286 XtFree((char *)lm);
3287 return NULL;
3290 if (*lm->name == '\0')
3292 if (!silent)
3294 DialogF(DF_WARN, LMDialog.shell, 1, "Language Mode Name",
3295 "Please specify a name\nfor the language mode", "Dismiss");
3296 XmProcessTraversal(LMDialog.nameW, XmTRAVERSE_CURRENT);
3298 freeLanguageModeRec(lm);
3299 return NULL;
3302 /* read the extension list field */
3303 extStr = extPtr = XmTextGetString(LMDialog.extW);
3304 lm->extensions = readExtensionList(&extPtr, &lm->nExtensions);
3305 XtFree(extStr);
3307 /* read recognition expression */
3308 lm->recognitionExpr = XmTextGetString(LMDialog.recogW);
3309 if (*lm->recognitionExpr == '\0') {
3310 XtFree(lm->recognitionExpr);
3311 lm->recognitionExpr = NULL;
3312 } else
3314 compiledRE = CompileRE(lm->recognitionExpr, &compileMsg, REDFLT_STANDARD);
3316 if (compiledRE == NULL)
3318 if (!silent)
3320 DialogF(DF_WARN, LMDialog.shell, 1, "Regex",
3321 "Recognition expression:\n%s", "Dismiss", compileMsg);
3322 XmProcessTraversal(LMDialog.recogW, XmTRAVERSE_CURRENT);
3324 XtFree((char *)compiledRE);
3325 freeLanguageModeRec(lm);
3326 return NULL;
3329 XtFree((char *)compiledRE);
3332 /* Read the default calltips file for the language mode */
3333 lm->defTipsFile = XmTextGetString(LMDialog.defTipsW);
3334 if (*lm->defTipsFile == '\0') {
3335 /* Empty string */
3336 XtFree(lm->defTipsFile);
3337 lm->defTipsFile = NULL;
3338 } else {
3339 /* Ensure that AddTagsFile will work */
3340 if (AddTagsFile(lm->defTipsFile, TIP) == FALSE) {
3341 if (!silent)
3343 DialogF(DF_WARN, LMDialog.shell, 1, "Error reading Calltips",
3344 "Can't read default calltips file(s):\n \"%s\"\n",
3345 "Dismiss", lm->defTipsFile);
3346 XmProcessTraversal(LMDialog.recogW, XmTRAVERSE_CURRENT);
3348 freeLanguageModeRec(lm);
3349 return NULL;
3350 } else
3351 if (DeleteTagsFile(lm->defTipsFile, TIP) == FALSE)
3352 fprintf(stderr, "nedit: Internal error: Trouble deleting "
3353 "calltips file(s):\n \"%s\"\n", lm->defTipsFile);
3356 /* read tab spacing field */
3357 if (TextWidgetIsBlank(LMDialog.tabW))
3358 lm->tabDist = DEFAULT_TAB_DIST;
3359 else {
3360 if (GetIntTextWarn(LMDialog.tabW, &lm->tabDist, "tab spacing", False)
3361 != TEXT_READ_OK) {
3362 freeLanguageModeRec(lm);
3363 return NULL;
3366 if (lm->tabDist <= 0 || lm->tabDist > 100)
3368 if (!silent)
3370 DialogF(DF_WARN, LMDialog.shell, 1, "Invalid Tab Spacing",
3371 "Invalid tab spacing: %d", "Dismiss", lm->tabDist);
3372 XmProcessTraversal(LMDialog.tabW, XmTRAVERSE_CURRENT);
3374 freeLanguageModeRec(lm);
3375 return NULL;
3379 /* read emulated tab field */
3380 if (TextWidgetIsBlank(LMDialog.emTabW))
3382 lm->emTabDist = DEFAULT_EM_TAB_DIST;
3383 } else
3385 if (GetIntTextWarn(LMDialog.emTabW, &lm->emTabDist,
3386 "emulated tab spacing", False) != TEXT_READ_OK)
3388 freeLanguageModeRec(lm);
3389 return NULL;
3392 if (lm->emTabDist < 0 || lm->emTabDist > 100)
3394 if (!silent)
3396 DialogF(DF_WARN, LMDialog.shell, 1, "Invalid Tab Spacing",
3397 "Invalid emulated tab spacing: %d", "Dismiss",
3398 lm->emTabDist);
3399 XmProcessTraversal(LMDialog.emTabW, XmTRAVERSE_CURRENT);
3401 freeLanguageModeRec(lm);
3402 return NULL;
3406 /* read delimiters string */
3407 lm->delimiters = XmTextGetString(LMDialog.delimitW);
3408 if (*lm->delimiters == '\0') {
3409 XtFree(lm->delimiters);
3410 lm->delimiters = NULL;
3413 /* read indent style */
3414 if (XmToggleButtonGetState(LMDialog.noIndentW))
3415 lm->indentStyle = NO_AUTO_INDENT;
3416 else if (XmToggleButtonGetState(LMDialog.autoIndentW))
3417 lm->indentStyle = AUTO_INDENT;
3418 else if (XmToggleButtonGetState(LMDialog.smartIndentW))
3419 lm->indentStyle = SMART_INDENT;
3420 else
3421 lm->indentStyle = DEFAULT_INDENT;
3423 /* read wrap style */
3424 if (XmToggleButtonGetState(LMDialog.noWrapW))
3425 lm->wrapStyle = NO_WRAP;
3426 else if (XmToggleButtonGetState(LMDialog.newlineWrapW))
3427 lm->wrapStyle = NEWLINE_WRAP;
3428 else if (XmToggleButtonGetState(LMDialog.contWrapW))
3429 lm->wrapStyle = CONTINUOUS_WRAP;
3430 else
3431 lm->wrapStyle = DEFAULT_WRAP;
3433 return lm;
3437 ** Return True if the language mode dialog fields are blank (unchanged from the "New"
3438 ** language mode state).
3440 static int lmDialogEmpty(void)
3442 return TextWidgetIsBlank(LMDialog.nameW) &&
3443 TextWidgetIsBlank(LMDialog.extW) &&
3444 TextWidgetIsBlank(LMDialog.recogW) &&
3445 TextWidgetIsBlank(LMDialog.delimitW) &&
3446 TextWidgetIsBlank(LMDialog.tabW) &&
3447 TextWidgetIsBlank(LMDialog.emTabW) &&
3448 XmToggleButtonGetState(LMDialog.defaultIndentW) &&
3449 XmToggleButtonGetState(LMDialog.defaultWrapW);
3453 ** Present a dialog for changing fonts (primary, and for highlighting).
3455 void ChooseFonts(WindowInfo *window, int forWindow)
3457 #define MARGIN_SPACING 10
3458 #define BTN_TEXT_OFFSET 3
3459 Widget form, primaryLbl, primaryBtn, italicLbl, italicBtn;
3460 Widget boldLbl, boldBtn, boldItalicLbl, boldItalicBtn;
3461 Widget primaryFrame, primaryForm, highlightFrame, highlightForm;
3462 Widget okBtn, applyBtn, dismissBtn;
3463 fontDialog *fd;
3464 XmString s1;
3465 int ac;
3466 Arg args[20];
3468 /* if the dialog is already displayed, just pop it to the top and return */
3469 if (window->fontDialog != NULL) {
3470 RaiseShellWindow(((fontDialog *)window->fontDialog)->shell);
3471 return;
3474 /* Create a structure for keeping track of dialog state */
3475 fd = (fontDialog *)XtMalloc(sizeof(fontDialog));
3476 fd->window = window;
3477 fd->forWindow = forWindow;
3478 window->fontDialog = (void*)fd;
3480 /* Create a form widget in a dialog shell */
3481 ac = 0;
3482 XtSetArg(args[ac], XmNautoUnmanage, False); ac++;
3483 XtSetArg(args[ac], XmNresizePolicy, XmRESIZE_NONE); ac++;
3484 form = CreateFormDialog(window->shell, "choose Fonts", args, ac);
3485 XtVaSetValues(form, XmNshadowThickness, 0, NULL);
3486 fd->shell = XtParent(form);
3487 XtVaSetValues(fd->shell, XmNtitle, "Text Fonts", NULL);
3488 AddMotifCloseCallback(XtParent(form), fontDismissCB, fd);
3489 XtAddCallback(form, XmNdestroyCallback, fontDestroyCB, fd);
3491 primaryFrame = XtVaCreateManagedWidget("primaryFrame", xmFrameWidgetClass,
3492 form, XmNmarginHeight, 3,
3493 XmNtopAttachment, XmATTACH_POSITION,
3494 XmNtopPosition, 2,
3495 XmNleftAttachment, XmATTACH_POSITION,
3496 XmNleftPosition, 1,
3497 XmNrightAttachment, XmATTACH_POSITION,
3498 XmNrightPosition, 99, NULL);
3499 primaryForm = XtVaCreateManagedWidget("primaryForm", xmFormWidgetClass,
3500 primaryFrame, NULL);
3501 primaryLbl = XtVaCreateManagedWidget("primaryFont", xmLabelGadgetClass,
3502 primaryFrame,
3503 XmNlabelString, s1=XmStringCreateSimple("Primary Font"),
3504 XmNmnemonic, 'P',
3505 XmNchildType, XmFRAME_TITLE_CHILD,
3506 XmNchildHorizontalAlignment, XmALIGNMENT_CENTER, NULL);
3507 XmStringFree(s1);
3509 primaryBtn = XtVaCreateManagedWidget("primaryBtn",
3510 xmPushButtonWidgetClass, primaryForm,
3511 XmNlabelString, s1=XmStringCreateSimple("Browse..."),
3512 XmNmnemonic, 'r',
3513 XmNtopAttachment, XmATTACH_POSITION,
3514 XmNtopPosition, 2,
3515 XmNtopOffset, BTN_TEXT_OFFSET,
3516 XmNleftAttachment, XmATTACH_POSITION,
3517 XmNleftPosition, 1, NULL);
3518 XmStringFree(s1);
3519 XtAddCallback(primaryBtn, XmNactivateCallback, primaryBrowseCB, fd);
3521 fd->primaryW = XtVaCreateManagedWidget("primary", xmTextWidgetClass,
3522 primaryForm,
3523 XmNcolumns, 70,
3524 XmNmaxLength, MAX_FONT_LEN,
3525 XmNleftAttachment, XmATTACH_WIDGET,
3526 XmNleftWidget, primaryBtn,
3527 XmNtopAttachment, XmATTACH_POSITION,
3528 XmNtopPosition, 2,
3529 XmNrightAttachment, XmATTACH_POSITION,
3530 XmNrightPosition, 99, NULL);
3531 RemapDeleteKey(fd->primaryW);
3532 XtAddCallback(fd->primaryW, XmNvalueChangedCallback,
3533 primaryModifiedCB, fd);
3534 XtVaSetValues(primaryLbl, XmNuserData, fd->primaryW, NULL);
3536 highlightFrame = XtVaCreateManagedWidget("highlightFrame",
3537 xmFrameWidgetClass, form,
3538 XmNmarginHeight, 3,
3539 XmNnavigationType, XmTAB_GROUP,
3540 XmNtopAttachment, XmATTACH_WIDGET,
3541 XmNtopWidget, primaryFrame,
3542 XmNtopOffset, 20,
3543 XmNleftAttachment, XmATTACH_POSITION,
3544 XmNleftPosition, 1,
3545 XmNrightAttachment, XmATTACH_POSITION,
3546 XmNrightPosition, 99, NULL);
3547 highlightForm = XtVaCreateManagedWidget("highlightForm", xmFormWidgetClass,
3548 highlightFrame, NULL);
3549 XtVaCreateManagedWidget("highlightFonts", xmLabelGadgetClass,
3550 highlightFrame,
3551 XmNlabelString,
3552 s1=XmStringCreateSimple("Fonts for Syntax Highlighting"),
3553 XmNchildType, XmFRAME_TITLE_CHILD,
3554 XmNchildHorizontalAlignment, XmALIGNMENT_CENTER, NULL);
3555 XmStringFree(s1);
3557 fd->fillW = XtVaCreateManagedWidget("fillBtn",
3558 xmPushButtonWidgetClass, highlightForm,
3559 XmNlabelString,
3560 s1=XmStringCreateSimple("Fill Highlight Fonts from Primary"),
3561 XmNmnemonic, 'F',
3562 XmNtopAttachment, XmATTACH_POSITION,
3563 XmNtopPosition, 2,
3564 XmNtopOffset, BTN_TEXT_OFFSET,
3565 XmNleftAttachment, XmATTACH_POSITION,
3566 XmNleftPosition, 1, NULL);
3567 XmStringFree(s1);
3568 XtAddCallback(fd->fillW, XmNactivateCallback, fillFromPrimaryCB, fd);
3570 italicLbl = XtVaCreateManagedWidget("italicLbl", xmLabelGadgetClass,
3571 highlightForm,
3572 XmNlabelString, s1=XmStringCreateSimple("Italic Font"),
3573 XmNmnemonic, 'I',
3574 XmNalignment, XmALIGNMENT_BEGINNING,
3575 XmNtopAttachment, XmATTACH_WIDGET,
3576 XmNtopWidget, fd->fillW,
3577 XmNtopOffset, MARGIN_SPACING,
3578 XmNleftAttachment, XmATTACH_POSITION,
3579 XmNleftPosition, 1, NULL);
3580 XmStringFree(s1);
3582 fd->italicErrW = XtVaCreateManagedWidget("italicErrLbl",
3583 xmLabelGadgetClass, highlightForm,
3584 XmNlabelString, s1=XmStringCreateSimple(
3585 "(vvv spacing is inconsistent with primary font vvv)"),
3586 XmNalignment, XmALIGNMENT_END,
3587 XmNtopAttachment, XmATTACH_WIDGET,
3588 XmNtopWidget, fd->fillW,
3589 XmNtopOffset, MARGIN_SPACING,
3590 XmNleftAttachment, XmATTACH_WIDGET,
3591 XmNleftWidget, italicLbl,
3592 XmNrightAttachment, XmATTACH_POSITION,
3593 XmNrightPosition, 99, NULL);
3594 XmStringFree(s1);
3596 italicBtn = XtVaCreateManagedWidget("italicBtn",
3597 xmPushButtonWidgetClass, highlightForm,
3598 XmNlabelString, s1=XmStringCreateSimple("Browse..."),
3599 XmNmnemonic, 'o',
3600 XmNtopAttachment, XmATTACH_WIDGET,
3601 XmNtopWidget, italicLbl,
3602 XmNtopOffset, BTN_TEXT_OFFSET,
3603 XmNleftAttachment, XmATTACH_POSITION,
3604 XmNleftPosition, 1, NULL);
3605 XmStringFree(s1);
3606 XtAddCallback(italicBtn, XmNactivateCallback, italicBrowseCB, fd);
3608 fd->italicW = XtVaCreateManagedWidget("italic", xmTextWidgetClass,
3609 highlightForm,
3610 XmNmaxLength, MAX_FONT_LEN,
3611 XmNleftAttachment, XmATTACH_WIDGET,
3612 XmNleftWidget, italicBtn,
3613 XmNtopAttachment, XmATTACH_WIDGET,
3614 XmNtopWidget, italicLbl,
3615 XmNrightAttachment, XmATTACH_POSITION,
3616 XmNrightPosition, 99, NULL);
3617 RemapDeleteKey(fd->italicW);
3618 XtAddCallback(fd->italicW, XmNvalueChangedCallback,
3619 italicModifiedCB, fd);
3620 XtVaSetValues(italicLbl, XmNuserData, fd->italicW, NULL);
3622 boldLbl = XtVaCreateManagedWidget("boldLbl", xmLabelGadgetClass,
3623 highlightForm,
3624 XmNlabelString, s1=XmStringCreateSimple("Bold Font"),
3625 XmNmnemonic, 'B',
3626 XmNalignment, XmALIGNMENT_BEGINNING,
3627 XmNtopAttachment, XmATTACH_WIDGET,
3628 XmNtopWidget, italicBtn,
3629 XmNtopOffset, MARGIN_SPACING,
3630 XmNleftAttachment, XmATTACH_POSITION,
3631 XmNleftPosition, 1, NULL);
3632 XmStringFree(s1);
3634 fd->boldErrW = XtVaCreateManagedWidget("boldErrLbl",
3635 xmLabelGadgetClass, highlightForm,
3636 XmNlabelString, s1=XmStringCreateSimple(""),
3637 XmNalignment, XmALIGNMENT_END,
3638 XmNtopAttachment, XmATTACH_WIDGET,
3639 XmNtopWidget, italicBtn,
3640 XmNtopOffset, MARGIN_SPACING,
3641 XmNleftAttachment, XmATTACH_WIDGET,
3642 XmNleftWidget, boldLbl,
3643 XmNrightAttachment, XmATTACH_POSITION,
3644 XmNrightPosition, 99, NULL);
3645 XmStringFree(s1);
3647 boldBtn = XtVaCreateManagedWidget("boldBtn",
3648 xmPushButtonWidgetClass, highlightForm,
3649 XmNlabelString, s1=XmStringCreateSimple("Browse..."),
3650 XmNmnemonic, 'w',
3651 XmNtopAttachment, XmATTACH_WIDGET,
3652 XmNtopWidget, boldLbl,
3653 XmNtopOffset, BTN_TEXT_OFFSET,
3654 XmNleftAttachment, XmATTACH_POSITION,
3655 XmNleftPosition, 1, NULL);
3656 XmStringFree(s1);
3657 XtAddCallback(boldBtn, XmNactivateCallback, boldBrowseCB, fd);
3659 fd->boldW = XtVaCreateManagedWidget("bold", xmTextWidgetClass,
3660 highlightForm,
3661 XmNmaxLength, MAX_FONT_LEN,
3662 XmNleftAttachment, XmATTACH_WIDGET,
3663 XmNleftWidget, boldBtn,
3664 XmNtopAttachment, XmATTACH_WIDGET,
3665 XmNtopWidget, boldLbl,
3666 XmNrightAttachment, XmATTACH_POSITION,
3667 XmNrightPosition, 99, NULL);
3668 RemapDeleteKey(fd->boldW);
3669 XtAddCallback(fd->boldW, XmNvalueChangedCallback,
3670 boldModifiedCB, fd);
3671 XtVaSetValues(boldLbl, XmNuserData, fd->boldW, NULL);
3673 boldItalicLbl = XtVaCreateManagedWidget("boldItalicLbl", xmLabelGadgetClass,
3674 highlightForm,
3675 XmNlabelString, s1=XmStringCreateSimple("Bold Italic Font"),
3676 XmNmnemonic, 'l',
3677 XmNalignment, XmALIGNMENT_BEGINNING,
3678 XmNtopAttachment, XmATTACH_WIDGET,
3679 XmNtopWidget, boldBtn,
3680 XmNtopOffset, MARGIN_SPACING,
3681 XmNleftAttachment, XmATTACH_POSITION,
3682 XmNleftPosition, 1, NULL);
3683 XmStringFree(s1);
3685 fd->boldItalicErrW = XtVaCreateManagedWidget("boldItalicErrLbl",
3686 xmLabelGadgetClass, highlightForm,
3687 XmNlabelString, s1=XmStringCreateSimple(""),
3688 XmNalignment, XmALIGNMENT_END,
3689 XmNtopAttachment, XmATTACH_WIDGET,
3690 XmNtopWidget, boldBtn,
3691 XmNtopOffset, MARGIN_SPACING,
3692 XmNleftAttachment, XmATTACH_WIDGET,
3693 XmNleftWidget, boldItalicLbl,
3694 XmNrightAttachment, XmATTACH_POSITION,
3695 XmNrightPosition, 99, NULL);
3696 XmStringFree(s1);
3698 boldItalicBtn = XtVaCreateManagedWidget("boldItalicBtn",
3699 xmPushButtonWidgetClass, highlightForm,
3700 XmNlabelString, s1=XmStringCreateSimple("Browse..."),
3701 XmNmnemonic, 's',
3702 XmNtopAttachment, XmATTACH_WIDGET,
3703 XmNtopWidget, boldItalicLbl,
3704 XmNtopOffset, BTN_TEXT_OFFSET,
3705 XmNleftAttachment, XmATTACH_POSITION,
3706 XmNleftPosition, 1, NULL);
3707 XmStringFree(s1);
3708 XtAddCallback(boldItalicBtn, XmNactivateCallback, boldItalicBrowseCB, fd);
3710 fd->boldItalicW = XtVaCreateManagedWidget("boldItalic",
3711 xmTextWidgetClass, highlightForm,
3712 XmNmaxLength, MAX_FONT_LEN,
3713 XmNleftAttachment, XmATTACH_WIDGET,
3714 XmNleftWidget, boldItalicBtn,
3715 XmNtopAttachment, XmATTACH_WIDGET,
3716 XmNtopWidget, boldItalicLbl,
3717 XmNrightAttachment, XmATTACH_POSITION,
3718 XmNrightPosition, 99, NULL);
3719 RemapDeleteKey(fd->boldItalicW);
3720 XtAddCallback(fd->boldItalicW, XmNvalueChangedCallback,
3721 boldItalicModifiedCB, fd);
3722 XtVaSetValues(boldItalicLbl, XmNuserData, fd->boldItalicW, NULL);
3724 okBtn = XtVaCreateManagedWidget("ok", xmPushButtonWidgetClass, form,
3725 XmNlabelString, s1=XmStringCreateSimple("OK"),
3726 XmNtopAttachment, XmATTACH_WIDGET,
3727 XmNtopWidget, highlightFrame,
3728 XmNtopOffset, MARGIN_SPACING,
3729 XmNleftAttachment, XmATTACH_POSITION,
3730 XmNleftPosition, forWindow ? 13 : 26,
3731 XmNrightAttachment, XmATTACH_POSITION,
3732 XmNrightPosition, forWindow ? 27 : 40, NULL);
3733 XtAddCallback(okBtn, XmNactivateCallback, fontOkCB, fd);
3734 XmStringFree(s1);
3736 if (forWindow) {
3737 applyBtn = XtVaCreateManagedWidget("apply",xmPushButtonWidgetClass,form,
3738 XmNlabelString, s1=XmStringCreateSimple("Apply"),
3739 XmNmnemonic, 'A',
3740 XmNtopAttachment, XmATTACH_WIDGET,
3741 XmNtopWidget, highlightFrame,
3742 XmNtopOffset, MARGIN_SPACING,
3743 XmNleftAttachment, XmATTACH_POSITION,
3744 XmNleftPosition, 43,
3745 XmNrightAttachment, XmATTACH_POSITION,
3746 XmNrightPosition, 57, NULL);
3747 XtAddCallback(applyBtn, XmNactivateCallback, fontApplyCB, fd);
3748 XmStringFree(s1);
3751 dismissBtn = XtVaCreateManagedWidget("dismiss",xmPushButtonWidgetClass,form,
3752 XmNlabelString, s1=XmStringCreateSimple("Dismiss"),
3753 XmNtopAttachment, XmATTACH_WIDGET,
3754 XmNtopWidget, highlightFrame,
3755 XmNtopOffset, MARGIN_SPACING,
3756 XmNleftAttachment, XmATTACH_POSITION,
3757 XmNleftPosition, forWindow ? 73 : 59,
3758 XmNrightAttachment, XmATTACH_POSITION,
3759 XmNrightPosition, forWindow ? 87 : 73, NULL);
3760 XtAddCallback(dismissBtn, XmNactivateCallback, fontDismissCB, fd);
3761 XmStringFree(s1);
3763 /* Set initial default button */
3764 XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
3765 XtVaSetValues(form, XmNcancelButton, dismissBtn, NULL);
3767 /* Set initial values */
3768 if (forWindow) {
3769 XmTextSetString(fd->primaryW, window->fontName);
3770 XmTextSetString(fd->boldW, window->boldFontName);
3771 XmTextSetString(fd->italicW, window->italicFontName);
3772 XmTextSetString(fd->boldItalicW, window->boldItalicFontName);
3773 } else {
3774 XmTextSetString(fd->primaryW, GetPrefFontName());
3775 XmTextSetString(fd->boldW, GetPrefBoldFontName());
3776 XmTextSetString(fd->italicW, GetPrefItalicFontName());
3777 XmTextSetString(fd->boldItalicW, GetPrefBoldItalicFontName());
3780 /* Handle mnemonic selection of buttons and focus to dialog */
3781 AddDialogMnemonicHandler(form, FALSE);
3783 /* put up dialog */
3784 ManageDialogCenteredOnPointer(form);
3787 static void fillFromPrimaryCB(Widget w, XtPointer clientData,
3788 XtPointer callData)
3790 fontDialog *fd = (fontDialog *)clientData;
3791 char *primaryName, *errMsg;
3792 char modifiedFontName[MAX_FONT_LEN];
3793 char *searchString = "(-[^-]*-[^-]*)-([^-]*)-([^-]*)-(.*)";
3794 char *italicReplaceString = "\\1-\\2-o-\\4";
3795 char *boldReplaceString = "\\1-bold-\\3-\\4";
3796 char *boldItalicReplaceString = "\\1-bold-o-\\4";
3797 regexp *compiledRE;
3799 /* Match the primary font agains RE pattern for font names. If it
3800 doesn't match, we can't generate highlight font names, so return */
3801 compiledRE = CompileRE(searchString, &errMsg, REDFLT_STANDARD);
3802 primaryName = XmTextGetString(fd->primaryW);
3803 if (!ExecRE(compiledRE, NULL, primaryName, NULL, False, '\0', '\0', NULL, NULL)) {
3804 XBell(XtDisplay(fd->shell), 0);
3805 free(compiledRE);
3806 XtFree(primaryName);
3807 return;
3810 /* Make up names for new fonts based on RE replace patterns */
3811 SubstituteRE(compiledRE, italicReplaceString, modifiedFontName,
3812 MAX_FONT_LEN);
3813 XmTextSetString(fd->italicW, modifiedFontName);
3814 SubstituteRE(compiledRE, boldReplaceString, modifiedFontName,
3815 MAX_FONT_LEN);
3816 XmTextSetString(fd->boldW, modifiedFontName);
3817 SubstituteRE(compiledRE, boldItalicReplaceString, modifiedFontName,
3818 MAX_FONT_LEN);
3819 XmTextSetString(fd->boldItalicW, modifiedFontName);
3820 XtFree(primaryName);
3821 free(compiledRE);
3824 static void primaryModifiedCB(Widget w, XtPointer clientData,
3825 XtPointer callData)
3827 fontDialog *fd = (fontDialog *)clientData;
3829 showFontStatus(fd, fd->italicW, fd->italicErrW);
3830 showFontStatus(fd, fd->boldW, fd->boldErrW);
3831 showFontStatus(fd, fd->boldItalicW, fd->boldItalicErrW);
3833 static void italicModifiedCB(Widget w, XtPointer clientData, XtPointer callData)
3835 fontDialog *fd = (fontDialog *)clientData;
3837 showFontStatus(fd, fd->italicW, fd->italicErrW);
3839 static void boldModifiedCB(Widget w, XtPointer clientData, XtPointer callData)
3841 fontDialog *fd = (fontDialog *)clientData;
3843 showFontStatus(fd, fd->boldW, fd->boldErrW);
3845 static void boldItalicModifiedCB(Widget w, XtPointer clientData,
3846 XtPointer callData)
3848 fontDialog *fd = (fontDialog *)clientData;
3850 showFontStatus(fd, fd->boldItalicW, fd->boldItalicErrW);
3853 static void primaryBrowseCB(Widget w, XtPointer clientData, XtPointer callData)
3855 fontDialog *fd = (fontDialog *)clientData;
3857 browseFont(fd->shell, fd->primaryW, fd);
3859 static void italicBrowseCB(Widget w, XtPointer clientData, XtPointer callData)
3861 fontDialog *fd = (fontDialog *)clientData;
3863 browseFont(fd->shell, fd->italicW, fd);
3865 static void boldBrowseCB(Widget w, XtPointer clientData, XtPointer callData)
3867 fontDialog *fd = (fontDialog *)clientData;
3869 browseFont(fd->shell, fd->boldW, fd);
3871 static void boldItalicBrowseCB(Widget w, XtPointer clientData,
3872 XtPointer callData)
3874 fontDialog *fd = (fontDialog *)clientData;
3876 browseFont(fd->shell, fd->boldItalicW, fd);
3879 static void fontDestroyCB(Widget w, XtPointer clientData, XtPointer callData)
3881 fontDialog *fd = (fontDialog *)clientData;
3883 fd->window->fontDialog = NULL;
3884 XtFree((char *)fd);
3887 static void fontOkCB(Widget w, XtPointer clientData, XtPointer callData)
3889 fontDialog *fd = (fontDialog *)clientData;
3891 updateFonts(fd);
3893 /* pop down and destroy the dialog */
3894 XtDestroyWidget(fd->shell);
3897 static void fontApplyCB(Widget w, XtPointer clientData, XtPointer callData)
3899 fontDialog *fd = (fontDialog *)clientData;
3901 updateFonts(fd);
3904 static void fontDismissCB(Widget w, XtPointer clientData, XtPointer callData)
3906 fontDialog *fd = (fontDialog *)clientData;
3908 /* pop down and destroy the dialog */
3909 XtDestroyWidget(fd->shell);
3913 ** Check over a font name in a text field to make sure it agrees with the
3914 ** primary font in height and spacing.
3916 static int checkFontStatus(fontDialog *fd, Widget fontTextFieldW)
3918 char *primaryName, *testName;
3919 XFontStruct *primaryFont, *testFont;
3920 Display *display = XtDisplay(fontTextFieldW);
3921 int primaryWidth, primaryHeight, testWidth, testHeight;
3923 /* Get width and height of the font to check. Note the test for empty
3924 name: X11R6 clients freak out X11R5 servers if they ask them to load
3925 an empty font name, and kill the whole application! */
3926 testName = XmTextGetString(fontTextFieldW);
3927 if (testName[0] == '\0') {
3928 XtFree(testName);
3929 return BAD_FONT;
3931 testFont = XLoadQueryFont(display, testName);
3932 if (testFont == NULL) {
3933 XtFree(testName);
3934 return BAD_FONT;
3936 XtFree(testName);
3937 testWidth = testFont->min_bounds.width;
3938 testHeight = testFont->ascent + testFont->descent;
3939 XFreeFont(display, testFont);
3941 /* Get width and height of the primary font */
3942 primaryName = XmTextGetString(fd->primaryW);
3943 if (primaryName[0] == '\0') {
3944 XtFree(primaryName);
3945 return BAD_FONT;
3947 primaryFont = XLoadQueryFont(display, primaryName);
3948 if (primaryFont == NULL) {
3949 XtFree(primaryName);
3950 return BAD_PRIMARY;
3952 XtFree(primaryName);
3953 primaryWidth = primaryFont->min_bounds.width;
3954 primaryHeight = primaryFont->ascent + primaryFont->descent;
3955 XFreeFont(display, primaryFont);
3957 /* Compare font information */
3958 if (testWidth != primaryWidth)
3959 return BAD_SPACING;
3960 if (testHeight != primaryHeight)
3961 return BAD_SIZE;
3962 return GOOD_FONT;
3966 ** Update the error label for a font text field to reflect its validity and degree
3967 ** of agreement with the currently selected primary font
3969 static int showFontStatus(fontDialog *fd, Widget fontTextFieldW,
3970 Widget errorLabelW)
3972 int status;
3973 XmString s;
3974 char *msg;
3976 status = checkFontStatus(fd, fontTextFieldW);
3977 if (status == BAD_PRIMARY)
3978 msg = "(font below may not match primary font)";
3979 else if (status == BAD_FONT)
3980 msg = "(xxx font below is invalid xxx)";
3981 else if (status == BAD_SIZE)
3982 msg = "(height of font below does not match primary)";
3983 else if (status == BAD_SPACING)
3984 msg = "(spacing of font below does not match primary)";
3985 else
3986 msg = "";
3988 XtVaSetValues(errorLabelW, XmNlabelString, s=XmStringCreateSimple(msg),
3989 NULL);
3990 XmStringFree(s);
3991 return status;
3995 ** Put up a font selector panel to set the font name in the text widget "fontTextW"
3997 static void browseFont(Widget parent, Widget fontTextW, fontDialog *fd)
3999 char *origFontName, *newFontName;
4000 Pixel fgPixel, bgPixel;
4001 int dummy;
4003 origFontName = XmTextGetString(fontTextW);
4005 /* Get the values from the defaults */
4006 fgPixel = AllocColor(parent, GetPrefColorName(TEXT_FG_COLOR),
4007 &dummy, &dummy, &dummy);
4008 bgPixel = AllocColor(parent, GetPrefColorName(TEXT_BG_COLOR),
4009 &dummy, &dummy, &dummy);
4011 newFontName = FontSel(parent, PREF_FIXED, origFontName, fgPixel, bgPixel);
4012 XtFree(origFontName);
4013 if (newFontName == NULL)
4014 return;
4015 XmTextSetString(fontTextW, newFontName);
4016 XtFree(newFontName);
4020 ** Accept the changes in the dialog and set the fonts regardless of errors
4022 static void updateFonts(fontDialog *fd)
4024 char *fontName, *italicName, *boldName, *boldItalicName;
4026 fontName = XmTextGetString(fd->primaryW);
4027 italicName = XmTextGetString(fd->italicW);
4028 boldName = XmTextGetString(fd->boldW);
4029 boldItalicName = XmTextGetString(fd->boldItalicW);
4031 if (fd->forWindow) {
4032 char *params[4];
4033 params[0] = fontName;
4034 params[1] = italicName;
4035 params[2] = boldName;
4036 params[3] = boldItalicName;
4037 XtCallActionProc(fd->window->textArea, "set_fonts", NULL, params, 4);
4039 SetFonts(fd->window, fontName, italicName, boldName, boldItalicName);
4042 else {
4043 SetPrefFont(fontName);
4044 SetPrefItalicFont(italicName);
4045 SetPrefBoldFont(boldName);
4046 SetPrefBoldItalicFont(boldItalicName);
4048 XtFree(fontName);
4049 XtFree(italicName);
4050 XtFree(boldName);
4051 XtFree(boldItalicName);
4055 ** Change the language mode to the one indexed by "mode", reseting word
4056 ** delimiters, syntax highlighting and other mode specific parameters
4058 static void reapplyLanguageMode(WindowInfo *window, int mode, int forceDefaults)
4060 char *delimiters;
4061 int i, wrapMode, indentStyle, tabDist, emTabDist, highlight, oldEmTabDist;
4062 int wrapModeIsDef, tabDistIsDef, emTabDistIsDef, indentStyleIsDef;
4063 int highlightIsDef, haveHighlightPatterns, haveSmartIndentMacros;
4064 int oldMode = window->languageMode;
4065 WindowInfo *wi;
4067 /* If the mode is the same, and changes aren't being forced (as might
4068 happen with Save As...), don't mess with already correct settings */
4069 if (window->languageMode == mode && !forceDefaults)
4070 return;
4072 /* Change the mode name stored in the window */
4073 window->languageMode = mode;
4075 /* Unload oldMode's default calltips file if there are no more windows
4076 in that mode and the mode has a default file */
4077 if (oldMode != PLAIN_LANGUAGE_MODE && LanguageModes[oldMode]->defTipsFile) {
4078 for (wi = WindowList; wi; wi = wi->next)
4079 if (wi->languageMode == oldMode) break;
4080 if (!wi) DeleteTagsFile( LanguageModes[oldMode]->defTipsFile, TIP );
4083 /* Make sure we didn't accidentally delete a default calltips file that
4084 also belongs another language mode (also load the tips file for the
4085 new lang. mode) */
4086 for (wi = WindowList; wi; wi = wi->next) {
4087 i = wi->languageMode;
4088 if (i != PLAIN_LANGUAGE_MODE && LanguageModes[i]->defTipsFile)
4089 if (AddTagsFile( LanguageModes[i]->defTipsFile, TIP ) == FALSE)
4090 fprintf( stderr, "Error loading default calltips file:\n"
4091 " \"%s\"\n", LanguageModes[i]->defTipsFile );
4094 /* Set delimiters for all text widgets */
4095 if (mode == PLAIN_LANGUAGE_MODE || LanguageModes[mode]->delimiters == NULL)
4096 delimiters = GetPrefDelimiters();
4097 else
4098 delimiters = LanguageModes[mode]->delimiters;
4099 XtVaSetValues(window->textArea, textNwordDelimiters, delimiters, NULL);
4100 for (i=0; i<window->nPanes; i++)
4101 XtVaSetValues(window->textPanes[i], textNautoIndent, delimiters, NULL);
4103 /* Decide on desired values for language-specific parameters. If a
4104 parameter was set to its default value, set it to the new default,
4105 otherwise, leave it alone */
4106 wrapModeIsDef = window->wrapMode == GetPrefWrap(oldMode);
4107 tabDistIsDef = BufGetTabDistance(window->buffer) == GetPrefTabDist(oldMode);
4108 XtVaGetValues(window->textArea, textNemulateTabs, &oldEmTabDist, NULL);
4109 emTabDistIsDef = oldEmTabDist == GetPrefEmTabDist(oldMode);
4110 indentStyleIsDef = window->indentStyle == GetPrefAutoIndent(oldMode) ||
4111 (GetPrefAutoIndent(oldMode) == SMART_INDENT &&
4112 window->indentStyle == AUTO_INDENT &&
4113 !SmartIndentMacrosAvailable(LanguageModeName(oldMode)));
4114 highlightIsDef = window->highlightSyntax == GetPrefHighlightSyntax()
4115 || (GetPrefHighlightSyntax() &&
4116 FindPatternSet(LanguageModeName(oldMode)) == NULL);
4117 wrapMode = wrapModeIsDef || forceDefaults ?
4118 GetPrefWrap(mode) : window->wrapMode;
4119 tabDist = tabDistIsDef || forceDefaults ?
4120 GetPrefTabDist(mode) : BufGetTabDistance(window->buffer);
4121 emTabDist = emTabDistIsDef || forceDefaults ?
4122 GetPrefEmTabDist(mode) : oldEmTabDist;
4123 indentStyle = indentStyleIsDef || forceDefaults ?
4124 GetPrefAutoIndent(mode) : window->indentStyle;
4125 highlight = highlightIsDef || forceDefaults ?
4126 GetPrefHighlightSyntax() : window->highlightSyntax;
4128 /* Dim/undim smart-indent and highlighting menu items depending on
4129 whether patterns/macros are available */
4130 haveHighlightPatterns = FindPatternSet(LanguageModeName(mode)) != NULL;
4131 haveSmartIndentMacros = SmartIndentMacrosAvailable(LanguageModeName(mode));
4132 XtSetSensitive(window->highlightItem, haveHighlightPatterns);
4133 XtSetSensitive(window->smartIndentItem, haveSmartIndentMacros);
4135 /* Turn off requested options which are not available */
4136 highlight = haveHighlightPatterns && highlight;
4137 if (indentStyle == SMART_INDENT && !haveSmartIndentMacros)
4138 indentStyle = AUTO_INDENT;
4140 /* Change highlighting */
4141 window->highlightSyntax = highlight;
4142 XmToggleButtonSetState(window->highlightItem, highlight, False);
4143 StopHighlighting(window);
4144 if (highlight)
4145 StartHighlighting(window, False);
4147 /* Force a change of smart indent macros (SetAutoIndent will re-start) */
4148 if (window->indentStyle == SMART_INDENT) {
4149 EndSmartIndent(window);
4150 window->indentStyle = AUTO_INDENT;
4153 /* set requested wrap, indent, and tabs */
4154 SetAutoWrap(window, wrapMode);
4155 SetAutoIndent(window, indentStyle);
4156 SetTabDist(window, tabDist);
4157 SetEmTabDist(window, emTabDist);
4159 /* Add/remove language specific menu items */
4160 #ifndef VMS
4161 UpdateShellMenu(window);
4162 #endif
4163 UpdateMacroMenu(window);
4164 UpdateBGMenu(window);
4168 ** Find and return the name of the appropriate languange mode for
4169 ** the file in "window". Returns a pointer to a string, which will
4170 ** remain valid until a change is made to the language modes list.
4172 static int matchLanguageMode(WindowInfo *window)
4174 char *ext, *first200;
4175 int i, j, fileNameLen, extLen, beginPos, endPos, start;
4176 const char *versionExtendedPath;
4178 /*... look for an explicit mode statement first */
4180 /* Do a regular expression search on for recognition pattern */
4181 first200 = BufGetRange(window->buffer, 0, 200);
4182 for (i=0; i<NLanguageModes; i++) {
4183 if (LanguageModes[i]->recognitionExpr != NULL) {
4184 if (SearchString(first200, LanguageModes[i]->recognitionExpr,
4185 SEARCH_FORWARD, SEARCH_REGEX, False, 0, &beginPos,
4186 &endPos, NULL, NULL, NULL))
4188 XtFree(first200);
4189 return i;
4193 XtFree(first200);
4195 /* Look at file extension ("@@/" starts a ClearCase version extended path,
4196 which gets appended after the file extension, and therefore must be
4197 stripped off to recognize the extension to make ClearCase users happy) */
4198 fileNameLen = strlen(window->filename);
4199 #ifdef VMS
4200 if (strchr(window->filename, ';') != NULL)
4201 fileNameLen = strchr(window->filename, ';') - window->filename;
4202 #else
4203 if ((versionExtendedPath = GetClearCaseVersionExtendedPath(window->filename)) != NULL)
4204 fileNameLen = versionExtendedPath - window->filename;
4205 #endif
4206 for (i=0; i<NLanguageModes; i++) {
4207 for (j=0; j<LanguageModes[i]->nExtensions; j++) {
4208 ext = LanguageModes[i]->extensions[j];
4209 extLen = strlen(ext);
4210 start = fileNameLen - extLen;
4211 #if defined(__VMS) && (__VMS_VER >= 70200000)
4212 /* VMS v7.2 has case-preserving filenames */
4213 if (start >= 0 && !strncasecmp(&window->filename[start], ext, extLen))
4214 return i;
4215 #else
4216 if (start >= 0 && !strncmp(&window->filename[start], ext, extLen))
4217 return i;
4218 #endif
4222 /* no appropriate mode was found */
4223 return PLAIN_LANGUAGE_MODE;
4226 static int loadLanguageModesString(char *inString, int fileVer)
4228 char *errMsg, *styleName, *inPtr = inString;
4229 languageModeRec *lm;
4230 int i;
4232 for (;;) {
4234 /* skip over blank space */
4235 inPtr += strspn(inPtr, " \t\n");
4237 /* Allocate a language mode structure to return, set unread fields to
4238 empty so everything can be freed on errors by freeLanguageModeRec */
4239 lm = (languageModeRec *)XtMalloc(sizeof(languageModeRec));
4240 lm->nExtensions = 0;
4241 lm->recognitionExpr = NULL;
4242 lm->defTipsFile = NULL;
4243 lm->delimiters = NULL;
4245 /* read language mode name */
4246 lm->name = ReadSymbolicField(&inPtr);
4247 if (lm->name == NULL) {
4248 XtFree((char *)lm);
4249 return modeError(NULL,inString,inPtr,"language mode name required");
4251 if (!SkipDelimiter(&inPtr, &errMsg))
4252 return modeError(lm, inString, inPtr, errMsg);
4254 /* read list of extensions */
4255 lm->extensions = readExtensionList(&inPtr,
4256 &lm->nExtensions);
4257 if (!SkipDelimiter(&inPtr, &errMsg))
4258 return modeError(lm, inString, inPtr, errMsg);
4260 /* read the recognition regular expression */
4261 if (*inPtr == '\n' || *inPtr == '\0' || *inPtr == ':')
4262 lm->recognitionExpr = NULL;
4263 else if (!ReadQuotedString(&inPtr, &errMsg, &lm->recognitionExpr))
4264 return modeError(lm, inString,inPtr, errMsg);
4265 if (!SkipDelimiter(&inPtr, &errMsg))
4266 return modeError(lm, inString, inPtr, errMsg);
4268 /* read the indent style */
4269 styleName = ReadSymbolicField(&inPtr);
4270 if (styleName == NULL)
4271 lm->indentStyle = DEFAULT_INDENT;
4272 else {
4273 for (i=0; i<N_INDENT_STYLES; i++) {
4274 if (!strcmp(styleName, AutoIndentTypes[i])) {
4275 lm->indentStyle = i;
4276 break;
4279 XtFree(styleName);
4280 if (i == N_INDENT_STYLES)
4281 return modeError(lm,inString,inPtr,"unrecognized indent style");
4283 if (!SkipDelimiter(&inPtr, &errMsg))
4284 return modeError(lm, inString, inPtr, errMsg);
4286 /* read the wrap style */
4287 styleName = ReadSymbolicField(&inPtr);
4288 if (styleName == NULL)
4289 lm->wrapStyle = DEFAULT_WRAP;
4290 else {
4291 for (i=0; i<N_WRAP_STYLES; i++) {
4292 if (!strcmp(styleName, AutoWrapTypes[i])) {
4293 lm->wrapStyle = i;
4294 break;
4297 XtFree(styleName);
4298 if (i == N_WRAP_STYLES)
4299 return modeError(lm, inString, inPtr,"unrecognized wrap style");
4301 if (!SkipDelimiter(&inPtr, &errMsg))
4302 return modeError(lm, inString, inPtr, errMsg);
4304 /* read the tab distance */
4305 if (*inPtr == '\n' || *inPtr == '\0' || *inPtr == ':')
4306 lm->tabDist = DEFAULT_TAB_DIST;
4307 else if (!ReadNumericField(&inPtr, &lm->tabDist))
4308 return modeError(lm, inString, inPtr, "bad tab spacing");
4309 if (!SkipDelimiter(&inPtr, &errMsg))
4310 return modeError(lm, inString, inPtr, errMsg);
4312 /* read emulated tab distance */
4313 if (*inPtr == '\n' || *inPtr == '\0' || *inPtr == ':')
4314 lm->emTabDist = DEFAULT_EM_TAB_DIST;
4315 else if (!ReadNumericField(&inPtr, &lm->emTabDist))
4316 return modeError(lm, inString, inPtr, "bad emulated tab spacing");
4317 if (!SkipDelimiter(&inPtr, &errMsg))
4318 return modeError(lm, inString, inPtr, errMsg);
4320 /* read the delimiters string */
4321 if (*inPtr == '\n' || *inPtr == '\0' || *inPtr == ':')
4322 lm->delimiters = NULL;
4323 else if (!ReadQuotedString(&inPtr, &errMsg, &lm->delimiters))
4324 return modeError(lm, inString, inPtr, errMsg);
4326 /* After 5.3 all language modes need a default tips file field */
4327 if (!SkipDelimiter(&inPtr, &errMsg))
4328 if (fileVer > 5003)
4329 return modeError(lm, inString, inPtr, errMsg);
4331 /* read the default tips file */
4332 if (*inPtr == '\n' || *inPtr == '\0')
4333 lm->defTipsFile = NULL;
4334 else if (!ReadQuotedString(&inPtr, &errMsg, &lm->defTipsFile))
4335 return modeError(lm, inString, inPtr, errMsg);
4337 /* pattern set was read correctly, add/replace it in the list */
4338 for (i=0; i<NLanguageModes; i++) {
4339 if (!strcmp(LanguageModes[i]->name, lm->name)) {
4340 freeLanguageModeRec(LanguageModes[i]);
4341 LanguageModes[i] = lm;
4342 break;
4345 if (i == NLanguageModes) {
4346 LanguageModes[NLanguageModes++] = lm;
4347 if (NLanguageModes > MAX_LANGUAGE_MODES)
4348 return modeError(NULL, inString, inPtr,
4349 "maximum allowable number of language modes exceeded");
4352 /* if the string ends here, we're done */
4353 inPtr += strspn(inPtr, " \t\n");
4354 if (*inPtr == '\0')
4355 return True;
4356 } /* End for(;;) */
4359 static char *writeLanguageModesString(void)
4361 int i;
4362 char *outStr, *escapedStr, *str, numBuf[25];
4363 textBuffer *outBuf;
4365 outBuf = BufCreate();
4366 for (i=0; i<NLanguageModes; i++) {
4367 BufInsert(outBuf, outBuf->length, "\t");
4368 BufInsert(outBuf, outBuf->length, LanguageModes[i]->name);
4369 BufInsert(outBuf, outBuf->length, ":");
4370 BufInsert(outBuf, outBuf->length, str = createExtString(
4371 LanguageModes[i]->extensions, LanguageModes[i]->nExtensions));
4372 XtFree(str);
4373 BufInsert(outBuf, outBuf->length, ":");
4374 if (LanguageModes[i]->recognitionExpr != NULL) {
4375 BufInsert(outBuf, outBuf->length,
4376 str=MakeQuotedString(LanguageModes[i]->recognitionExpr));
4377 XtFree(str);
4379 BufInsert(outBuf, outBuf->length, ":");
4380 if (LanguageModes[i]->indentStyle != DEFAULT_INDENT)
4381 BufInsert(outBuf, outBuf->length,
4382 AutoIndentTypes[LanguageModes[i]->indentStyle]);
4383 BufInsert(outBuf, outBuf->length, ":");
4384 if (LanguageModes[i]->wrapStyle != DEFAULT_WRAP)
4385 BufInsert(outBuf, outBuf->length,
4386 AutoWrapTypes[LanguageModes[i]->wrapStyle]);
4387 BufInsert(outBuf, outBuf->length, ":");
4388 if (LanguageModes[i]->tabDist != DEFAULT_TAB_DIST) {
4389 sprintf(numBuf, "%d", LanguageModes[i]->tabDist);
4390 BufInsert(outBuf, outBuf->length, numBuf);
4392 BufInsert(outBuf, outBuf->length, ":");
4393 if (LanguageModes[i]->emTabDist != DEFAULT_EM_TAB_DIST) {
4394 sprintf(numBuf, "%d", LanguageModes[i]->emTabDist);
4395 BufInsert(outBuf, outBuf->length, numBuf);
4397 BufInsert(outBuf, outBuf->length, ":");
4398 if (LanguageModes[i]->delimiters != NULL) {
4399 BufInsert(outBuf, outBuf->length,
4400 str=MakeQuotedString(LanguageModes[i]->delimiters));
4401 XtFree(str);
4403 BufInsert(outBuf, outBuf->length, ":");
4404 if (LanguageModes[i]->defTipsFile != NULL) {
4405 BufInsert(outBuf, outBuf->length,
4406 str=MakeQuotedString(LanguageModes[i]->defTipsFile));
4407 XtFree(str);
4410 BufInsert(outBuf, outBuf->length, "\n");
4413 /* Get the output, and lop off the trailing newline */
4414 outStr = BufGetRange(outBuf, 0, outBuf->length - 1);
4415 BufFree(outBuf);
4416 escapedStr = EscapeSensitiveChars(outStr);
4417 XtFree(outStr);
4418 return escapedStr;
4421 static char *createExtString(char **extensions, int nExtensions)
4423 int e, length = 1;
4424 char *outStr, *outPtr;
4426 for (e=0; e<nExtensions; e++)
4427 length += strlen(extensions[e]) + 1;
4428 outStr = outPtr = XtMalloc(length);
4429 for (e=0; e<nExtensions; e++) {
4430 strcpy(outPtr, extensions[e]);
4431 outPtr += strlen(extensions[e]);
4432 *outPtr++ = ' ';
4434 if (nExtensions == 0)
4435 *outPtr = '\0';
4436 else
4437 *(outPtr-1) = '\0';
4438 return outStr;
4441 static char **readExtensionList(char **inPtr, int *nExtensions)
4443 char *extensionList[MAX_FILE_EXTENSIONS];
4444 char **retList, *strStart;
4445 int i, len;
4447 /* skip over blank space */
4448 *inPtr += strspn(*inPtr, " \t");
4450 for (i=0; i<MAX_FILE_EXTENSIONS && **inPtr!=':' && **inPtr!='\0'; i++) {
4451 *inPtr += strspn(*inPtr, " \t");
4452 strStart = *inPtr;
4453 while (**inPtr!=' ' && **inPtr!='\t' && **inPtr!=':' && **inPtr!='\0')
4454 (*inPtr)++;
4455 len = *inPtr - strStart;
4456 extensionList[i] = XtMalloc(len + 1);
4457 strncpy(extensionList[i], strStart, len);
4458 extensionList[i][len] = '\0';
4460 *nExtensions = i;
4461 if (i == 0)
4462 return NULL;
4463 retList = (char **)XtMalloc(sizeof(char *) * i);
4464 memcpy(retList, extensionList, sizeof(char *) * i);
4465 return retList;
4468 int ReadNumericField(char **inPtr, int *value)
4470 int charsRead;
4472 /* skip over blank space */
4473 *inPtr += strspn(*inPtr, " \t");
4475 if (sscanf(*inPtr, "%d%n", value, &charsRead) != 1)
4476 return False;
4477 *inPtr += charsRead;
4478 return True;
4482 ** Parse a symbolic field, skipping initial and trailing whitespace,
4483 ** stops on first invalid character or end of string. Valid characters
4484 ** are letters, numbers, _, -, +, $, #, and internal whitespace. Internal
4485 ** whitespace is compressed to single space characters.
4487 char *ReadSymbolicField(char **inPtr)
4489 char *outStr, *outPtr, *strStart, *strPtr;
4490 int len;
4492 /* skip over initial blank space */
4493 *inPtr += strspn(*inPtr, " \t");
4495 /* Find the first invalid character or end of string to know how
4496 much memory to allocate for the returned string */
4497 strStart = *inPtr;
4498 while (isalnum((unsigned char)**inPtr) || **inPtr=='_' || **inPtr=='-' ||
4499 **inPtr=='+' || **inPtr=='$' || **inPtr=='#' || **inPtr==' ' ||
4500 **inPtr=='\t')
4501 (*inPtr)++;
4502 len = *inPtr - strStart;
4503 if (len == 0)
4504 return NULL;
4505 outStr = outPtr = XtMalloc(len + 1);
4507 /* Copy the string, compressing internal whitespace to a single space */
4508 strPtr = strStart;
4509 while (strPtr - strStart < len) {
4510 if (*strPtr == ' ' || *strPtr == '\t') {
4511 strPtr += strspn(strPtr, " \t");
4512 *outPtr++ = ' ';
4513 } else
4514 *outPtr++ = *strPtr++;
4517 /* If there's space on the end, take it back off */
4518 if (outPtr > outStr && *(outPtr-1) == ' ')
4519 outPtr--;
4520 if (outPtr == outStr) {
4521 XtFree(outStr);
4522 return NULL;
4524 *outPtr = '\0';
4525 return outStr;
4529 ** parse an individual quoted string. Anything between
4530 ** double quotes is acceptable, quote characters can be escaped by "".
4531 ** Returns allocated string "string" containing
4532 ** argument minus quotes. If not successful, returns False with
4533 ** (statically allocated) message in "errMsg".
4535 int ReadQuotedString(char **inPtr, char **errMsg, char **string)
4537 char *outPtr, *c;
4539 /* skip over blank space */
4540 *inPtr += strspn(*inPtr, " \t");
4542 /* look for initial quote */
4543 if (**inPtr != '\"') {
4544 *errMsg = "expecting quoted string";
4545 return False;
4547 (*inPtr)++;
4549 /* calculate max length and allocate returned string */
4550 for (c= *inPtr; ; c++) {
4551 if (*c == '\0') {
4552 *errMsg = "string not terminated";
4553 return False;
4554 } else if (*c == '\"') {
4555 if (*(c+1) == '\"')
4556 c++;
4557 else
4558 break;
4562 /* copy string up to end quote, transforming escaped quotes into quotes */
4563 *string = XtMalloc(c - *inPtr + 1);
4564 outPtr = *string;
4565 while (True) {
4566 if (**inPtr == '\"') {
4567 if (*(*inPtr+1) == '\"')
4568 (*inPtr)++;
4569 else
4570 break;
4572 *outPtr++ = *(*inPtr)++;
4574 *outPtr = '\0';
4576 /* skip end quote */
4577 (*inPtr)++;
4578 return True;
4582 ** Replace characters which the X resource file reader considers control
4583 ** characters, such that a string will read back as it appears in "string".
4584 ** (So far, newline characters are replaced with with \n\<newline> and
4585 ** backslashes with \\. This has not been tested exhaustively, and
4586 ** probably should be. It would certainly be more asthetic if other
4587 ** control characters were replaced as well).
4589 ** Returns an allocated string which must be freed by the caller with XtFree.
4591 char *EscapeSensitiveChars(const char *string)
4593 const char *c;
4594 char *outStr, *outPtr;
4595 int length = 0;
4597 /* calculate length and allocate returned string */
4598 for (c=string; *c!='\0'; c++) {
4599 if (*c == '\\')
4600 length++;
4601 else if (*c == '\n')
4602 length += 3;
4603 length++;
4605 outStr = XtMalloc(length + 1);
4606 outPtr = outStr;
4608 /* add backslashes */
4609 for (c=string; *c!='\0'; c++) {
4610 if (*c == '\\')
4611 *outPtr++ = '\\';
4612 else if (*c == '\n') {
4613 *outPtr++ = '\\';
4614 *outPtr++ = 'n';
4615 *outPtr++ = '\\';
4617 *outPtr++ = *c;
4619 *outPtr = '\0';
4620 return outStr;
4624 ** Adds double quotes around a string and escape existing double quote
4625 ** characters with two double quotes. Enables the string to be read back
4626 ** by ReadQuotedString.
4628 char *MakeQuotedString(const char *string)
4630 const char *c;
4631 char *outStr, *outPtr;
4632 int length = 0;
4634 /* calculate length and allocate returned string */
4635 for (c=string; *c!='\0'; c++) {
4636 if (*c == '\"')
4637 length++;
4638 length++;
4640 outStr = XtMalloc(length + 3);
4641 outPtr = outStr;
4643 /* add starting quote */
4644 *outPtr++ = '\"';
4646 /* copy string, escaping quotes with "" */
4647 for (c=string; *c!='\0'; c++) {
4648 if (*c == '\"')
4649 *outPtr++ = '\"';
4650 *outPtr++ = *c;
4653 /* add ending quote */
4654 *outPtr++ = '\"';
4656 /* terminate string and return */
4657 *outPtr = '\0';
4658 return outStr;
4662 ** Read a dialog text field containing a symbolic name (language mode names,
4663 ** style names, highlight pattern names, colors, and fonts), clean the
4664 ** entered text of leading and trailing whitespace, compress all
4665 ** internal whitespace to one space character, and check it over for
4666 ** colons, which interfere with the preferences file reader/writer syntax.
4667 ** Returns NULL on error, and puts up a dialog if silent is False. Returns
4668 ** an empty string if the text field is blank.
4670 char *ReadSymbolicFieldTextWidget(Widget textW, const char *fieldName, int silent)
4672 char *string, *stringPtr, *parsedString;
4674 /* read from the text widget */
4675 string = stringPtr = XmTextGetString(textW);
4677 /* parse it with the same routine used to read symbolic fields from
4678 files. If the string is not read entirely, there are invalid
4679 characters, so warn the user if not in silent mode. */
4680 parsedString = ReadSymbolicField(&stringPtr);
4681 if (*stringPtr != '\0')
4683 if (!silent)
4685 *(stringPtr + 1) = '\0';
4686 DialogF(DF_WARN, textW, 1, "Invalid Character",
4687 "Invalid character \"%s\" in %s", "Dismiss", stringPtr,
4688 fieldName);
4689 XmProcessTraversal(textW, XmTRAVERSE_CURRENT);
4691 XtFree(string);
4692 if (parsedString != NULL)
4693 XtFree(parsedString);
4694 return NULL;
4696 XtFree(string);
4697 if (parsedString == NULL) {
4698 parsedString = XtMalloc(1);
4699 *parsedString = '\0';
4701 return parsedString;
4705 ** Create a pulldown menu pane with the names of the current language modes.
4706 ** XmNuserData for each item contains the language mode name.
4708 Widget CreateLanguageModeMenu(Widget parent, XtCallbackProc cbProc, void *cbArg)
4710 Widget menu, btn;
4711 int i;
4712 XmString s1;
4714 menu = CreatePulldownMenu(parent, "languageModes", NULL, 0);
4715 for (i=0; i<NLanguageModes; i++) {
4716 btn = XtVaCreateManagedWidget("languageMode", xmPushButtonGadgetClass,
4717 menu,
4718 XmNlabelString, s1=XmStringCreateSimple(LanguageModes[i]->name),
4719 XmNmarginHeight, 0,
4720 XmNuserData, (void *)LanguageModes[i]->name, NULL);
4721 XmStringFree(s1);
4722 XtAddCallback(btn, XmNactivateCallback, cbProc, cbArg);
4724 return menu;
4728 ** Set the language mode menu in option menu "optMenu" to
4729 ** show a particular language mode
4731 void SetLangModeMenu(Widget optMenu, const char *modeName)
4733 int i;
4734 Cardinal nItems;
4735 WidgetList items;
4736 Widget pulldown, selectedItem;
4737 char *itemName;
4739 XtVaGetValues(optMenu, XmNsubMenuId, &pulldown, NULL);
4740 XtVaGetValues(pulldown, XmNchildren, &items, XmNnumChildren, &nItems, NULL);
4741 if (nItems == 0)
4742 return;
4743 selectedItem = items[0];
4744 for (i=0; i<(int)nItems; i++) {
4745 XtVaGetValues(items[i], XmNuserData, &itemName, NULL);
4746 if (!strcmp(itemName, modeName)) {
4747 selectedItem = items[i];
4748 break;
4751 XtVaSetValues(optMenu, XmNmenuHistory, selectedItem,NULL);
4755 ** Create a submenu for chosing language mode for the current window.
4757 Widget CreateLanguageModeSubMenu(WindowInfo *window, Widget parent, char *name,
4758 char *label, char mnemonic)
4760 XmString s1=XmStringCreateSimple(label);
4762 window->langModeCascade = XtVaCreateManagedWidget(name,
4763 xmCascadeButtonGadgetClass, parent, XmNlabelString,
4764 s1, XmNmnemonic, mnemonic,
4765 XmNsubMenuId, NULL, NULL);
4766 XmStringFree(s1);
4767 updateLanguageModeSubmenu(window);
4768 return window->langModeCascade;
4772 ** Re-build the language mode sub-menu using the current data stored
4773 ** in the master list: LanguageModes.
4775 static void updateLanguageModeSubmenu(WindowInfo *window)
4777 int i;
4778 XmString s1;
4779 Widget menu, btn;
4780 Arg args[1] = {{XmNradioBehavior, (XtArgVal)True}};
4782 /* Destroy and re-create the menu pane */
4783 XtVaGetValues(window->langModeCascade, XmNsubMenuId, &menu, NULL);
4784 if (menu != NULL)
4785 XtDestroyWidget(menu);
4786 menu = CreatePulldownMenu(XtParent(window->langModeCascade),
4787 "languageModes", args, 1);
4788 btn = XtVaCreateManagedWidget("languageMode",
4789 xmToggleButtonGadgetClass, menu,
4790 XmNlabelString, s1=XmStringCreateSimple("Plain"),
4791 XmNuserData, (void *)PLAIN_LANGUAGE_MODE,
4792 XmNset, window->languageMode==PLAIN_LANGUAGE_MODE, NULL);
4793 XmStringFree(s1);
4794 XtAddCallback(btn, XmNvalueChangedCallback, setLangModeCB, window);
4795 for (i=0; i<NLanguageModes; i++) {
4796 btn = XtVaCreateManagedWidget("languageMode",
4797 xmToggleButtonGadgetClass, menu,
4798 XmNlabelString, s1=XmStringCreateSimple(LanguageModes[i]->name),
4799 XmNmarginHeight, 0,
4800 XmNuserData, (void *)i,
4801 XmNset, window->languageMode==i, NULL);
4802 XmStringFree(s1);
4803 XtAddCallback(btn, XmNvalueChangedCallback, setLangModeCB, window);
4805 XtVaSetValues(window->langModeCascade, XmNsubMenuId, menu, NULL);
4808 static void setLangModeCB(Widget w, XtPointer clientData, XtPointer callData)
4810 WindowInfo *window = (WindowInfo *)clientData;
4811 char *params[1];
4812 void *mode;
4814 if (!XmToggleButtonGetState(w))
4815 return;
4817 /* get name of language mode stored in userData field of menu item */
4818 XtVaGetValues(w, XmNuserData, &mode, NULL);
4820 /* If the mode didn't change, do nothing */
4821 if (window->languageMode == (int)mode)
4822 return;
4824 /* redo syntax highlighting word delimiters, etc. */
4826 reapplyLanguageMode(window, (int)mode, False);
4828 params[0] = (((int)mode) == PLAIN_LANGUAGE_MODE) ? "" : LanguageModes[(int)mode]->name;
4829 XtCallActionProc(window->textArea, "set_language_mode", NULL, params, 1);
4833 ** Skip a delimiter and it's surrounding whitespace
4835 int SkipDelimiter(char **inPtr, char **errMsg)
4837 *inPtr += strspn(*inPtr, " \t");
4838 if (**inPtr != ':') {
4839 *errMsg = "syntax error";
4840 return False;
4842 (*inPtr)++;
4843 *inPtr += strspn(*inPtr, " \t");
4844 return True;
4848 ** Skip an optional separator and its surrounding whitespace
4849 ** return true if delimiter found
4851 int SkipOptSeparator(char separator, char **inPtr, char **errMsg)
4853 *inPtr += strspn(*inPtr, " \t");
4854 if (**inPtr != separator) {
4855 return False;
4857 (*inPtr)++;
4858 *inPtr += strspn(*inPtr, " \t");
4859 return True;
4863 ** Short-hand error processing for language mode parsing errors, frees
4864 ** lm (if non-null), prints a formatted message explaining where the
4865 ** error is, and returns False;
4867 static int modeError(languageModeRec *lm, const char *stringStart,
4868 const char *stoppedAt, const char *message)
4870 if (lm != NULL)
4871 freeLanguageModeRec(lm);
4872 return ParseError(NULL, stringStart, stoppedAt,
4873 "language mode specification", message);
4877 ** Report parsing errors in resource strings or macros, formatted nicely so
4878 ** the user can tell where things became botched. Errors can be sent either
4879 ** to stderr, or displayed in a dialog. For stderr, pass toDialog as NULL.
4880 ** For a dialog, pass the dialog parent in toDialog.
4882 int ParseError(Widget toDialog, const char *stringStart, const char *stoppedAt,
4883 const char *errorIn, const char *message)
4885 int len, nNonWhite = 0;
4886 const char *c;
4887 char *errorLine;
4889 for (c=stoppedAt; c>=stringStart; c--) {
4890 if (c == stringStart)
4891 break;
4892 else if (*c == '\n' && nNonWhite >= 5)
4893 break;
4894 else if (*c != ' ' && *c != '\t')
4895 nNonWhite++;
4897 len = stoppedAt - c + (*stoppedAt == '\0' ? 0 : 1);
4898 errorLine = XtMalloc(len+4);
4899 strncpy(errorLine, c, len);
4900 errorLine[len++] = '<';
4901 errorLine[len++] = '=';
4902 errorLine[len++] = '=';
4903 errorLine[len] = '\0';
4904 if (toDialog == NULL)
4906 fprintf(stderr, "NEdit: %s in %s:\n%s\n", message, errorIn, errorLine);
4907 } else
4909 DialogF(DF_WARN, toDialog, 1, "Parse Error", "%s in %s:\n%s", "Dismiss",
4910 message, errorIn, errorLine);
4912 XtFree(errorLine);
4913 return False;
4917 ** Compare two strings which may be NULL
4919 int AllocatedStringsDiffer(const char *s1, const char *s2)
4921 if (s1 == NULL && s2 == NULL)
4922 return False;
4923 if (s1 == NULL || s2 == NULL)
4924 return True;
4925 return strcmp(s1, s2);
4928 static void updatePatternsTo5dot1(void)
4930 const char *htmlDefaultExpr = "^[ \t]*HTML[ \t]*:[ \t]*Default[ \t]*$";
4931 const char *vhdlAnchorExpr = "^[ \t]*VHDL:";
4933 /* Add new patterns if there aren't already existing patterns with
4934 the same name. If possible, insert before VHDL in language mode
4935 list. If not, just add to end */
4936 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*PostScript:"))
4937 spliceString(&TempStringPrefs.highlight, "PostScript:Default",
4938 vhdlAnchorExpr);
4939 if (!regexFind(TempStringPrefs.language, "^[ \t]*PostScript:"))
4940 spliceString(&TempStringPrefs.language,
4941 "PostScript:.ps .PS .eps .EPS .epsf .epsi::::::",
4942 vhdlAnchorExpr);
4943 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*Lex:"))
4944 spliceString(&TempStringPrefs.highlight, "Lex:Default",
4945 vhdlAnchorExpr);
4946 if (!regexFind(TempStringPrefs.language, "^[ \t]*Lex:"))
4947 spliceString(&TempStringPrefs.language, "Lex:.lex::::::",
4948 vhdlAnchorExpr);
4949 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*SQL:"))
4950 spliceString(&TempStringPrefs.highlight, "SQL:Default",
4951 vhdlAnchorExpr);
4952 if (!regexFind(TempStringPrefs.language, "^[ \t]*SQL:"))
4953 spliceString(&TempStringPrefs.language, "SQL:.sql::::::",
4954 vhdlAnchorExpr);
4955 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*Matlab:"))
4956 spliceString(&TempStringPrefs.highlight, "Matlab:Default",
4957 vhdlAnchorExpr);
4958 if (!regexFind(TempStringPrefs.language, "^[ \t]*Matlab:"))
4959 spliceString(&TempStringPrefs.language, "Matlab:..m .oct .sci::::::",
4960 vhdlAnchorExpr);
4961 if (!regexFind(TempStringPrefs.smartIndent, "^[ \t]*Matlab:"))
4962 spliceString(&TempStringPrefs.smartIndent, "Matlab:Default", NULL);
4963 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Label:"))
4964 spliceString(&TempStringPrefs.styles, "Label:red:Italic",
4965 "^[ \t]*Flag:");
4966 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Storage Type1:"))
4967 spliceString(&TempStringPrefs.styles, "Storage Type1:saddle brown:Bold",
4968 "^[ \t]*String:");
4970 /* Replace html pattern with sgml html pattern, as long as there
4971 isn't an existing html pattern which will be overwritten */
4972 if (regexFind(TempStringPrefs.highlight, htmlDefaultExpr)) {
4973 regexReplace(&TempStringPrefs.highlight, htmlDefaultExpr,
4974 "SGML HTML:Default");
4975 if (!regexReplace(&TempStringPrefs.language, "^[ \t]*HTML:.*$",
4976 "SGML HTML:.sgml .sgm .html .htm:\"\\<(?ihtml)\\>\":::::\n")) {
4977 spliceString(&TempStringPrefs.language,
4978 "SGML HTML:.sgml .sgm .html .htm:\"\\<(?ihtml)\\>\":::::\n",
4979 vhdlAnchorExpr);
4984 static void updatePatternsTo5dot2(void)
4986 #ifdef VMS
4987 const char *cppLm5dot1 =
4988 "^[ \t]*C\\+\\+:\\.CC \\.HH \\.I::::::\"\\.,/\\\\`'!\\|@#%\\^&\\*\\(\\)-=\\+\\{\\}\\[\\]\"\":;\\<\\>\\?~\"";
4989 const char *perlLm5dot1 =
4990 "^[ \t]*Perl:\\.PL \\.PM \\.P5:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\.\\*perl\":::::";
4991 const char *psLm5dot1 =
4992 "^[ \t]*PostScript:\\.ps \\.PS \\.eps \\.EPS \\.epsf \\.epsi:\"\\^%!\":::::\"/%\\(\\)\\{\\}\\[\\]\\<\\>\"";
4993 const char *tclLm5dot1 = "^[ \t]*Tcl:\\.TCL::::::";
4995 const char *cppLm5dot2 =
4996 "C++:.CC .HH .C .H .I .CXX .HXX .CPP::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\"";
4997 const char *perlLm5dot2 =
4998 "Perl:.PL .PM .P5:\"^[ \\t]*#[ \\t]*!.*perl\":Auto:None:::\".,/\\\\`'!$@#%^&*()-=+{}[]\"\":;<>?~|\"";
4999 const char *psLm5dot2 =
5000 "PostScript:.ps .PS .eps .EPS .epsf .epsi:\"^%!\":::::\"/%(){}[]<>\"";
5001 const char *tclLm5dot2 =
5002 "Tcl:.TCL::Smart:None:::";
5003 #else
5004 const char *cppLm5dot1 =
5005 "^[ \t]*C\\+\\+:\\.cc \\.hh \\.C \\.H \\.i \\.cxx \\.hxx::::::\"\\.,/\\\\`'!\\|@#%\\^&\\*\\(\\)-=\\+\\{\\}\\[\\]\"\":;\\<\\>\\?~\"";
5006 const char *perlLm5dot1 =
5007 "^[ \t]*Perl:\\.pl \\.pm \\.p5:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\.\\*perl\":::::";
5008 const char *psLm5dot1 =
5009 "^[ \t]*PostScript:\\.ps \\.PS \\.eps \\.EPS \\.epsf \\.epsi:\"\\^%!\":::::\"/%\\(\\)\\{\\}\\[\\]\\<\\>\"";
5010 const char *shLm5dot1 =
5011 "^[ \t]*Sh Ksh Bash:\\.sh \\.bash \\.ksh \\.profile:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\[ \\\\t\\]\\*/bin/\\(sh\\|ksh\\|bash\\)\":::::";
5012 const char *tclLm5dot1 = "^[ \t]*Tcl:\\.tcl::::::";
5014 const char *cppLm5dot2 =
5015 "C++:.cc .hh .C .H .i .cxx .hxx .cpp::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\"";
5016 const char *perlLm5dot2 =
5017 "Perl:.pl .pm .p5 .PL:\"^[ \\t]*#[ \\t]*!.*perl\":Auto:None:::\".,/\\\\`'!$@#%^&*()-=+{}[]\"\":;<>?~|\"";
5018 const char *psLm5dot2 =
5019 "PostScript:.ps .eps .epsf .epsi:\"^%!\":::::\"/%(){}[]<>\"";
5020 const char *shLm5dot2 =
5021 "Sh Ksh Bash:.sh .bash .ksh .profile .bashrc .bash_logout .bash_login .bash_profile:\"^[ \\t]*#[ \\t]*![ \\t]*/.*bin/(sh|ksh|bash)\":::::";
5022 const char *tclLm5dot2 =
5023 "Tcl:.tcl .tk .itcl .itk::Smart:None:::";
5024 #endif /* VMS */
5026 const char *cssLm5dot2 =
5027 "CSS:css::Auto:None:::\".,/\\`'!|@#%^&*()=+{}[]\"\":;<>?~\"";
5028 const char *reLm5dot2 =
5029 "Regex:.reg .regex:\"\\(\\?[:#=!iInN].+\\)\":None:Continuous:::";
5030 const char *xmlLm5dot2 =
5031 "XML:.xml .xsl .dtd:\"\\<(?i\\?xml|!doctype)\"::None:::\"<>/=\"\"'()+*?|\"";
5033 const char *cssHl5dot2 = "CSS:Default";
5034 const char *reHl5dot2 = "Regex:Default";
5035 const char *xmlHl5dot2 = "XML:Default";
5037 const char *ptrStyle = "Pointer:#660000:Bold";
5038 const char *reStyle = "Regex:#009944:Bold";
5039 const char *wrnStyle = "Warning:brown2:Italic";
5041 /* First upgrade modified language modes, only if the user hasn't
5042 altered the default 5.1 definitions. */
5043 if (regexFind(TempStringPrefs.language, cppLm5dot1))
5044 regexReplace(&TempStringPrefs.language, cppLm5dot1, cppLm5dot2);
5045 if (regexFind(TempStringPrefs.language, perlLm5dot1))
5046 regexReplace(&TempStringPrefs.language, perlLm5dot1, perlLm5dot2);
5047 if (regexFind(TempStringPrefs.language, psLm5dot1))
5048 regexReplace(&TempStringPrefs.language, psLm5dot1, psLm5dot2);
5049 #ifndef VMS
5050 if (regexFind(TempStringPrefs.language, shLm5dot1))
5051 regexReplace(&TempStringPrefs.language, shLm5dot1, shLm5dot2);
5052 #endif
5053 if (regexFind(TempStringPrefs.language, tclLm5dot1))
5054 regexReplace(&TempStringPrefs.language, tclLm5dot1, tclLm5dot2);
5056 /* Then append the new modes (trying to keep them in alphabetical order
5057 makes no sense, since 5.1 didn't use alphabetical order). */
5058 if (!regexFind(TempStringPrefs.language, "^[ \t]*CSS:"))
5059 spliceString(&TempStringPrefs.language, cssLm5dot2, NULL);
5060 if (!regexFind(TempStringPrefs.language, "^[ \t]*Regex:"))
5061 spliceString(&TempStringPrefs.language, reLm5dot2, NULL);
5062 if (!regexFind(TempStringPrefs.language, "^[ \t]*XML:"))
5063 spliceString(&TempStringPrefs.language, xmlLm5dot2, NULL);
5065 /* Enable default highlighting patterns for these modes, unless already
5066 present */
5067 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*CSS:"))
5068 spliceString(&TempStringPrefs.highlight, cssHl5dot2, NULL);
5069 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*Regex:"))
5070 spliceString(&TempStringPrefs.highlight, reHl5dot2, NULL);
5071 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*XML:"))
5072 spliceString(&TempStringPrefs.highlight, xmlHl5dot2, NULL);
5074 /* Finally, append the new highlight styles */
5076 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Warning:"))
5077 spliceString(&TempStringPrefs.styles, wrnStyle, NULL);
5078 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Regex:"))
5079 spliceString(&TempStringPrefs.styles, reStyle, "^[ \t]*Warning:");
5080 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Pointer:"))
5081 spliceString(&TempStringPrefs.styles, ptrStyle, "^[ \t]*Regex:");
5084 static void updatePatternsTo5dot3(void)
5086 /* This is a bogus function on non-VMS */
5087 #ifdef VMS
5088 const char *psLm5dot2 =
5089 "^[ \t]*PostScript:\\.ps \\.PS \\.eps \\.EPS \\.epsf \\.epsi:\"\\^%!\":::::\"/%\\(\\)\\{\\}\\[\\]\\<\\>\"";
5091 const char *psLm5dot3 =
5092 "PostScript:.ps .PS .eps .EPS .epsf .EPSF .epsi .EPSI:\"^%!\":::::\"/%(){}[]<>\"";
5094 /* Upgrade modified language modes, only if the user hasn't
5095 altered the default 5.2 definitions. */
5096 if (regexFind(TempStringPrefs.language, psLm5dot2))
5097 regexReplace(&TempStringPrefs.language, psLm5dot2, psLm5dot3);
5098 #endif
5101 static void updatePatternsTo5dot4(void)
5103 #ifdef VMS
5104 const char *pyLm5dot3 =
5105 "Python:\\.PY:\"\\^#!\\.\\*python\":Auto:None::::?\n";
5106 const char *xrLm5dot3 =
5107 "X Resources:\\.XRESOURCES \\.XDEFAULTS \\.NEDIT:\"\\^\\[!#\\]\\.\\*\\(\\[Aa\\]pp\\|\\[Xx\\]\\)\\.\\*\\[Dd\\]efaults\"::::::?\n";
5109 const char *pyLm5dot4 =
5110 "Python:.PY:\"^#!.*python\":Auto:None:::\"!\"\"#$%&'()*+,-./:;<=>?@[\\\\]^`{|}~\":\n";
5111 const char *xrLm5dot4 =
5112 "X Resources:.XRESOURCES .XDEFAULTS .NEDIT NEDIT.RC:\"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults\"::::::\n";
5113 #else
5114 const char *pyLm5dot3 =
5115 "Python:\\.py:\"\\^#!\\.\\*python\":Auto:None::::?\n";
5116 const char *xrLm5dot3 =
5117 "X Resources:\\.Xresources \\.Xdefaults \\.nedit:\"\\^\\[!#\\]\\.\\*\\(\\[Aa\\]pp\\|\\[Xx\\]\\)\\.\\*\\[Dd\\]efaults\"::::::?\n";
5119 const char *pyLm5dot4 =
5120 "Python:.py:\"^#!.*python\":Auto:None:::\"!\"\"#$%&'()*+,-./:;<=>?@[\\\\]^`{|}~\":\n";
5121 const char *xrLm5dot4 =
5122 "X Resources:.Xresources .Xdefaults .nedit nedit.rc:\"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults\"::::::\n";
5123 #endif
5125 /* Upgrade modified language modes, only if the user hasn't
5126 altered the default 5.3 definitions. */
5127 if (regexFind(TempStringPrefs.language, pyLm5dot3))
5128 regexReplace(&TempStringPrefs.language, pyLm5dot3, pyLm5dot4);
5129 if (regexFind(TempStringPrefs.language, xrLm5dot3))
5130 regexReplace(&TempStringPrefs.language, xrLm5dot3, xrLm5dot4);
5134 * We migrate a color from the X resources to the prefs if:
5135 * 1. The prefs entry is equal to the default entry
5136 * 2. The X resource is not equal to the default entry
5138 static void migrateColor(XrmDatabase prefDB, XrmDatabase appDB,
5139 char *class, char *name, int color_index, char *default_val)
5141 char *type, *valueString;
5142 XrmValue rsrcValue;
5144 /* If this color has been customized in the color dialog then use
5145 that value */
5146 if ( strcmp(default_val, PrefData.colorNames[color_index]) )
5147 return;
5149 /* Retrieve the value of the resource from the DB */
5150 if (XrmGetResource(prefDB, name, class, &type, &rsrcValue)) {
5151 if (strcmp(type, XmRString)) {
5152 fprintf(stderr,"Internal Error: Unexpected resource type, %s\n",
5153 type);
5154 return;
5156 valueString = rsrcValue.addr;
5157 } else if (XrmGetResource(appDB, name, class, &type, &rsrcValue)) {
5158 if (strcmp(type, XmRString)) {
5159 fprintf(stderr,"Internal Error: Unexpected resource type, %s\n",
5160 type);
5161 return;
5163 valueString = rsrcValue.addr;
5164 } else
5165 /* No resources set */
5166 return;
5168 /* An X resource is set. If it's non-default, update the prefs. */
5169 if ( strcmp(valueString, default_val) ) {
5170 strncpy(PrefData.colorNames[color_index], valueString,
5171 MAX_COLOR_LEN);
5176 * In 5.4 we moved color preferences from X resources to a color dialog,
5177 * meaning they're in the normal prefs system. Users who have customized
5178 * their colors with X resources would probably prefer not to have to redo
5179 * the customization in the dialog, so we migrate them to the prefs for them.
5181 static void migrateColorResources(XrmDatabase prefDB, XrmDatabase appDB)
5183 migrateColor(prefDB, appDB, APP_CLASS ".Text.Foreground",
5184 APP_NAME ".text.foreground", TEXT_FG_COLOR,
5185 NEDIT_DEFAULT_FG);
5186 migrateColor(prefDB, appDB, APP_CLASS ".Text.Background",
5187 APP_NAME ".text.background", TEXT_BG_COLOR,
5188 NEDIT_DEFAULT_TEXT_BG);
5189 migrateColor(prefDB, appDB, APP_CLASS ".Text.SelectForeground",
5190 APP_NAME ".text.selectForeground", SELECT_FG_COLOR,
5191 NEDIT_DEFAULT_SEL_FG);
5192 migrateColor(prefDB, appDB, APP_CLASS ".Text.SelectBackground",
5193 APP_NAME ".text.selectBackground", SELECT_BG_COLOR,
5194 NEDIT_DEFAULT_SEL_BG);
5195 migrateColor(prefDB, appDB, APP_CLASS ".Text.HighlightForeground",
5196 APP_NAME ".text.highlightForeground", HILITE_FG_COLOR,
5197 NEDIT_DEFAULT_HI_FG);
5198 migrateColor(prefDB, appDB, APP_CLASS ".Text.HighlightBackground",
5199 APP_NAME ".text.highlightBackground", HILITE_BG_COLOR,
5200 NEDIT_DEFAULT_HI_BG);
5201 migrateColor(prefDB, appDB, APP_CLASS ".Text.LineNumForeground",
5202 APP_NAME ".text.lineNumForeground", LINENO_FG_COLOR,
5203 NEDIT_DEFAULT_LINENO_FG);
5204 migrateColor(prefDB, appDB, APP_CLASS ".Text.CursorForeground",
5205 APP_NAME ".text.cursorForeground", CURSOR_FG_COLOR,
5206 NEDIT_DEFAULT_CURSOR_FG);
5210 ** Inserts a string into intoString, reallocating it with XtMalloc. If
5211 ** regular expression atExpr is found, inserts the string before atExpr
5212 ** followed by a newline. If atExpr is not found, inserts insertString
5213 ** at the end, PRECEDED by a newline.
5215 static void spliceString(char **intoString, const char *insertString, const char *atExpr)
5217 int beginPos, endPos;
5218 int intoLen = strlen(*intoString);
5219 int insertLen = strlen(insertString);
5220 char *newString = XtMalloc(intoLen + insertLen + 2);
5222 if (atExpr != NULL && SearchString(*intoString, atExpr,
5223 SEARCH_FORWARD, SEARCH_REGEX, False, 0, &beginPos, &endPos,
5224 NULL, NULL, NULL)) {
5225 strncpy(newString, *intoString, beginPos);
5226 strncpy(&newString[beginPos], insertString, insertLen);
5227 newString[beginPos+insertLen] = '\n';
5228 strncpy(&newString[beginPos+insertLen+1],
5229 &((*intoString)[beginPos]), intoLen - beginPos);
5230 } else {
5231 strncpy(newString, *intoString, intoLen);
5232 newString[intoLen] = '\n';
5233 strncpy(&newString[intoLen+1], insertString, insertLen);
5235 newString[intoLen + insertLen + 1] = '\0';
5236 XtFree(*intoString);
5237 *intoString = newString;
5241 ** Simplified regular expression search routine which just returns true
5242 ** or false depending on whether inString matches expr
5244 static int regexFind(const char *inString, const char *expr)
5246 int beginPos, endPos;
5247 return SearchString(inString, expr, SEARCH_FORWARD, SEARCH_REGEX, False,
5248 0, &beginPos, &endPos, NULL, NULL, NULL);
5252 ** Simplified regular expression replacement routine which replaces the
5253 ** first occurence of expr in inString with replaceWith, reallocating
5254 ** inString with XtMalloc. If expr is not found, does nothing and
5255 ** returns false.
5257 static int regexReplace(char **inString, const char *expr, const char *replaceWith)
5259 int beginPos, endPos, newLen;
5260 char *newString;
5261 int replaceLen = strlen(replaceWith);
5262 int inLen = strlen(*inString);
5264 if (!SearchString(*inString, expr, SEARCH_FORWARD, SEARCH_REGEX, False,
5265 0, &beginPos, &endPos, NULL, NULL, NULL))
5266 return FALSE;
5267 newLen = inLen + replaceLen - (endPos-beginPos);
5268 newString = XtMalloc(newLen + 1);
5269 strncpy(newString, *inString, beginPos);
5270 strncpy(&newString[beginPos], replaceWith, replaceLen);
5271 strncpy(&newString[beginPos+replaceLen],
5272 &((*inString)[endPos]), inLen - endPos);
5273 newString[newLen] = '\0';
5274 XtFree(*inString);
5275 *inString = newString;
5276 return TRUE;
5280 #ifndef VMS
5282 ** Replace all '#' characters in shell commands by '##' to keep commands
5283 ** containing those working. '#' is a line number placeholder in 5.3 and
5284 ** had no special meaning before.
5286 static void updateShellCmdsTo5dot3(void)
5288 char *cOld, *cNew, *pCol, *pNL;
5289 int nHash, isCmd;
5290 char *newString;
5292 if(!TempStringPrefs.shellCmds)
5293 return;
5295 /* Count number of '#'. If there are '#' characters in the non-command
5296 ** part of the definition we count too much and later allocate too much
5297 ** memory for the new string, but this doesn't hurt.
5299 for(cOld=TempStringPrefs.shellCmds, nHash=0; *cOld; cOld++)
5300 if(*cOld == '#')
5301 nHash++;
5303 /* No '#' -> no conversion necessary. */
5304 if(!nHash)
5305 return;
5307 newString=XtMalloc(strlen(TempStringPrefs.shellCmds) + 1 + nHash);
5309 cOld = TempStringPrefs.shellCmds;
5310 cNew = newString;
5311 isCmd = 0;
5312 pCol = NULL;
5313 pNL = NULL;
5315 /* Copy all characters from TempStringPrefs.shellCmds into newString
5316 ** and duplicate '#' in command parts. A simple check for really beeing
5317 ** inside a command part (starting with '\n', between the the two last
5318 ** '\n' a colon ':' must have been found) is preformed.
5320 while(*cOld) {
5321 /* actually every 2nd line is a command. We additionally
5322 ** check if there is a colon ':' in the previous line.
5324 if(*cOld=='\n') {
5325 if((pCol > pNL) && !isCmd)
5326 isCmd=1;
5327 else
5328 isCmd=0;
5329 pNL=cOld;
5332 if(!isCmd && *cOld ==':')
5333 pCol = cOld;
5335 /* Duplicate hashes if we're in a command part */
5336 if(isCmd && *cOld=='#')
5337 *cNew++ = '#';
5339 /* Copy every character */
5340 *cNew++ = *cOld++;
5344 /* Terminate new preferences string */
5345 *cNew = 0;
5347 /* free the old memory */
5348 XtFree(TempStringPrefs.shellCmds);
5350 /* exchange the string */
5351 TempStringPrefs.shellCmds = newString;
5355 #else
5357 static void updateShellCmdsTo5dot3(void) {
5358 /* No shell commands in VMS ! */
5359 return;
5362 #endif
5364 #ifdef SGI_CUSTOM
5366 ** Present the user a dialog for specifying whether or not a short
5367 ** menu mode preference should be applied toward the default setting.
5368 ** Return False (function value) if operation was canceled, return True
5369 ** in setDefault if requested to reset the default value.
5371 static int shortPrefToDefault(Widget parent, const char *settingName, int *setDefault)
5373 char msg[100] = "";
5375 if (!GetPrefShortMenus()) {
5376 *setDefault = False;
5377 return True;
5380 sprintf(msg, "%s\nSave as default for future windows as well?", settingName);
5381 switch (DialogF (DF_QUES, parent, 3, "Save Default", msg, "Yes", "No",
5382 "Cancel"))
5384 case 1: /* yes */
5385 *setDefault = True;
5386 return True;
5387 case 2: /* no */
5388 *setDefault = False;
5389 return True;
5390 case 3: /* cancel */
5391 return False;
5393 return False; /* not reached */
5395 #endif
5397 /* Unload the default calltips file for this window unless somebody else
5398 is using it */
5399 void UnloadLanguageModeTipsFile(WindowInfo *window) {
5400 int mode;
5401 WindowInfo *wi;
5403 mode = window->languageMode;
5404 if (mode != PLAIN_LANGUAGE_MODE && LanguageModes[mode]->defTipsFile) {
5405 for (wi = WindowList; wi; wi = wi->next)
5406 if (wi->languageMode == mode && wi != window)
5407 break;
5408 if (!wi) /* If we got to end of WindowList... */
5409 DeleteTagsFile( LanguageModes[mode]->defTipsFile, TIP );
5412 /* Make sure we didn't accidentally delete a default calltips file that
5413 also belongs to another language mode */
5414 for (wi = WindowList; wi; wi = wi->next) {
5415 if (wi == window)
5416 continue;
5417 mode = wi->languageMode;
5418 if (mode != PLAIN_LANGUAGE_MODE && LanguageModes[mode]->defTipsFile)
5419 if (AddTagsFile( LanguageModes[mode]->defTipsFile, TIP ) == FALSE)
5420 fprintf( stderr, "Error loading default calltips file:\n"
5421 " \"%s\"\n", LanguageModes[mode]->defTipsFile );
5425 /******************************************************************************
5426 * The Color selection dialog
5427 ******************************************************************************/
5430 There are 8 colors: And 8 indices:
5431 textFg TEXT_FG_COLOR
5432 textBg TEXT_BG_COLOR
5433 selectFg SELECT_FG_COLOR
5434 selectBg SELECT_BG_COLOR
5435 hiliteFg HILITE_FG_COLOR
5436 hiliteBg HILITE_BG_COLOR
5437 lineNoFg LINENO_FG_COLOR
5438 cursorFg CURSOR_FG_COLOR
5441 #define MARGIN_SPACING 10
5444 * Callbacks for field modifications
5446 static void textFgModifiedCB(Widget w, XtPointer clientData,
5447 XtPointer callData)
5449 colorDialog *cd = (colorDialog *)clientData;
5450 showColorStatus(cd, cd->textFgW, cd->textFgErrW);
5453 static void textBgModifiedCB(Widget w, XtPointer clientData,
5454 XtPointer callData)
5456 colorDialog *cd = (colorDialog *)clientData;
5457 showColorStatus(cd, cd->textBgW, cd->textBgErrW);
5460 static void selectFgModifiedCB(Widget w, XtPointer clientData,
5461 XtPointer callData)
5463 colorDialog *cd = (colorDialog *)clientData;
5464 showColorStatus(cd, cd->selectFgW, cd->selectFgErrW);
5467 static void selectBgModifiedCB(Widget w, XtPointer clientData,
5468 XtPointer callData)
5470 colorDialog *cd = (colorDialog *)clientData;
5471 showColorStatus(cd, cd->selectBgW, cd->selectBgErrW);
5474 static void hiliteFgModifiedCB(Widget w, XtPointer clientData,
5475 XtPointer callData)
5477 colorDialog *cd = (colorDialog *)clientData;
5478 showColorStatus(cd, cd->hiliteFgW, cd->hiliteFgErrW);
5481 static void hiliteBgModifiedCB(Widget w, XtPointer clientData,
5482 XtPointer callData)
5484 colorDialog *cd = (colorDialog *)clientData;
5485 showColorStatus(cd, cd->hiliteBgW, cd->hiliteBgErrW);
5488 static void lineNoFgModifiedCB(Widget w, XtPointer clientData,
5489 XtPointer callData)
5491 colorDialog *cd = (colorDialog *)clientData;
5492 showColorStatus(cd, cd->lineNoFgW, cd->lineNoFgErrW);
5495 static void cursorFgModifiedCB(Widget w, XtPointer clientData,
5496 XtPointer callData)
5498 colorDialog *cd = (colorDialog *)clientData;
5499 showColorStatus(cd, cd->cursorFgW, cd->cursorFgErrW);
5504 * Helper functions for validating colors
5506 static int verifyAllColors(colorDialog *cd) {
5507 /* Maybe just check for empty strings in error widgets instead? */
5508 return (checkColorStatus(cd, cd->textFgW) &&
5509 checkColorStatus(cd, cd->textBgW) &&
5510 checkColorStatus(cd, cd->selectFgW) &&
5511 checkColorStatus(cd, cd->selectBgW) &&
5512 checkColorStatus(cd, cd->hiliteFgW) &&
5513 checkColorStatus(cd, cd->hiliteBgW) &&
5514 checkColorStatus(cd, cd->lineNoFgW) &&
5515 checkColorStatus(cd, cd->cursorFgW) );
5518 /* Returns True if the color is valid, False if it's not */
5519 static Boolean checkColorStatus(colorDialog *cd, Widget colorFieldW)
5521 Colormap cMap;
5522 XColor colorDef;
5523 Status status;
5524 Display *display = XtDisplay(cd->shell);
5525 char *text = XmTextGetString(colorFieldW);
5526 XtVaGetValues(cd->shell, XtNcolormap, &cMap, NULL);
5527 status = XParseColor(display, cMap, text, &colorDef);
5528 XtFree(text);
5529 return (status != 0);
5532 /* Show or hide errorLabelW depending on whether or not colorFieldW
5533 contains a valid color name. */
5534 static void showColorStatus(colorDialog *cd, Widget colorFieldW,
5535 Widget errorLabelW)
5537 /* Should set the OK/Apply button sensitivity here, instead
5538 of leaving is sensitive and then complaining if an error. */
5539 XtSetMappedWhenManaged( errorLabelW, !checkColorStatus(cd, colorFieldW) );
5542 /* Update the colors in the window or in the preferences */
5543 static void updateColors(colorDialog *cd)
5545 WindowInfo *window;
5547 char *textFg = XmTextGetString(cd->textFgW),
5548 *textBg = XmTextGetString(cd->textBgW),
5549 *selectFg = XmTextGetString(cd->selectFgW),
5550 *selectBg = XmTextGetString(cd->selectBgW),
5551 *hiliteFg = XmTextGetString(cd->hiliteFgW),
5552 *hiliteBg = XmTextGetString(cd->hiliteBgW),
5553 *lineNoFg = XmTextGetString(cd->lineNoFgW),
5554 *cursorFg = XmTextGetString(cd->cursorFgW);
5556 for (window = WindowList; window != NULL; window = window->next)
5558 SetColors(window, textFg, textBg, selectFg, selectBg, hiliteFg,
5559 hiliteBg, lineNoFg, cursorFg);
5562 SetPrefColorName(TEXT_FG_COLOR , textFg );
5563 SetPrefColorName(TEXT_BG_COLOR , textBg );
5564 SetPrefColorName(SELECT_FG_COLOR, selectFg);
5565 SetPrefColorName(SELECT_BG_COLOR, selectBg);
5566 SetPrefColorName(HILITE_FG_COLOR, hiliteFg);
5567 SetPrefColorName(HILITE_BG_COLOR, hiliteBg);
5568 SetPrefColorName(LINENO_FG_COLOR, lineNoFg);
5569 SetPrefColorName(CURSOR_FG_COLOR, cursorFg);
5571 XtFree(textFg);
5572 XtFree(textBg);
5573 XtFree(selectFg);
5574 XtFree(selectBg);
5575 XtFree(hiliteFg);
5576 XtFree(hiliteBg);
5577 XtFree(lineNoFg);
5578 XtFree(cursorFg);
5583 * Dialog button callbacks
5586 static void colorDestroyCB(Widget w, XtPointer clientData, XtPointer callData)
5588 colorDialog *cd = (colorDialog *)clientData;
5590 cd->window->colorDialog = NULL;
5591 XtFree((char *)cd);
5594 static void colorOkCB(Widget w, XtPointer clientData, XtPointer callData)
5596 colorDialog *cd = (colorDialog *)clientData;
5598 if(!verifyAllColors(cd))
5600 DialogF(DF_ERR, w, 1, "Invalid Colors",
5601 "All colors must be valid to proceed.", "Dismiss");
5602 return;
5604 updateColors(cd);
5606 /* pop down and destroy the dialog */
5607 XtDestroyWidget(cd->shell);
5610 static void colorApplyCB(Widget w, XtPointer clientData, XtPointer callData)
5612 colorDialog *cd = (colorDialog *)clientData;
5614 if(!verifyAllColors(cd))
5616 DialogF(DF_ERR, w, 1, "Invalid Colors",
5617 "All colors must be valid to be applied.", "Dismiss");
5618 return;
5620 updateColors(cd);
5623 static void colorDismissCB(Widget w, XtPointer clientData, XtPointer callData)
5625 colorDialog *cd = (colorDialog *)clientData;
5627 /* pop down and destroy the dialog */
5628 XtDestroyWidget(cd->shell);
5632 /* Add a label, error label, and text entry label with a validation
5633 callback */
5634 static Widget addColorGroup( Widget parent, const char *name, char mnemonic,
5635 char *label, Widget *fieldW, Widget *errW, Widget topWidget,
5636 int leftPos, int rightPos, XtCallbackProc modCallback,
5637 colorDialog *cd )
5639 Widget lblW;
5640 char *longerName;
5641 XmString s1;
5642 int nameLen = strlen(name);
5644 /* The label widget */
5645 longerName = XtMalloc(nameLen+7);
5646 strcpy(longerName, name);
5647 strcat(longerName, "Lbl");
5648 lblW = XtVaCreateManagedWidget(longerName,
5649 xmLabelGadgetClass, parent,
5650 XmNlabelString, s1=XmStringCreateSimple( label ),
5651 XmNmnemonic, mnemonic,
5652 XmNtopAttachment, XmATTACH_WIDGET,
5653 XmNtopWidget, topWidget,
5654 XmNtopOffset, MARGIN_SPACING,
5655 XmNleftAttachment, XmATTACH_POSITION,
5656 XmNleftPosition, leftPos, NULL);
5657 XmStringFree(s1);
5659 /* The error label widget */
5660 strcpy(&(longerName[nameLen]), "ErrLbl");
5661 *errW = XtVaCreateManagedWidget(longerName,
5662 xmLabelWidgetClass, parent,
5663 XmNlabelString, s1=XmStringCreateSimple("(Invalid!)"),
5664 XmNalignment, XmALIGNMENT_END,
5665 XmNtopAttachment, XmATTACH_WIDGET,
5666 XmNtopWidget, topWidget,
5667 XmNtopOffset, MARGIN_SPACING,
5668 XmNleftAttachment, XmATTACH_WIDGET,
5669 XmNleftWidget, lblW,
5670 XmNrightAttachment, XmATTACH_POSITION,
5671 XmNrightPosition, rightPos, NULL);
5672 XmStringFree(s1);
5674 /* The text field entry widget */
5675 *fieldW = XtVaCreateManagedWidget(name, xmTextWidgetClass,
5676 parent,
5677 XmNcolumns, MAX_COLOR_LEN-1,
5678 XmNmaxLength, MAX_COLOR_LEN-1,
5679 XmNleftAttachment, XmATTACH_POSITION,
5680 XmNleftPosition, leftPos,
5681 XmNrightAttachment, XmATTACH_POSITION,
5682 XmNrightPosition, rightPos,
5683 XmNtopAttachment, XmATTACH_WIDGET,
5684 XmNtopWidget, lblW, NULL);
5685 RemapDeleteKey(*fieldW);
5686 XtAddCallback(*fieldW, XmNvalueChangedCallback,
5687 modCallback, cd);
5688 XtVaSetValues(lblW, XmNuserData, *fieldW, NULL);
5690 XtFree(longerName);
5691 return *fieldW;
5696 * Code for the dialog itself
5698 void ChooseColors(WindowInfo *window, int forWindow)
5700 Widget form, tmpW, topW, infoLbl;
5701 Widget okBtn, applyBtn, dismissBtn, fillBtn;
5702 colorDialog *cd;
5703 XmString s1;
5704 int ac;
5705 Arg args[20];
5707 /* if the dialog is already displayed, just pop it to the top and return */
5708 if (window->colorDialog != NULL) {
5709 RaiseShellWindow(((colorDialog *)window->colorDialog)->shell);
5710 return;
5713 /* Create a structure for keeping track of dialog state */
5714 cd = XtNew(colorDialog);
5715 window->colorDialog = (void*)cd;
5717 /* Create a form widget in a dialog shell */
5718 ac = 0;
5719 XtSetArg(args[ac], XmNautoUnmanage, False); ac++;
5720 XtSetArg(args[ac], XmNresizePolicy, XmRESIZE_NONE); ac++;
5721 form = CreateFormDialog(window->shell, "choose colors", args, ac);
5722 XtVaSetValues(form, XmNshadowThickness, 0, NULL);
5723 cd->shell = XtParent(form);
5724 cd->window = window;
5725 XtVaSetValues(cd->shell, XmNtitle, "Colors", NULL);
5726 AddMotifCloseCallback(XtParent(form), colorDismissCB, cd);
5727 XtAddCallback(form, XmNdestroyCallback, colorDestroyCB, cd);
5729 /* Information label */
5730 infoLbl = XtVaCreateManagedWidget("infoLbl",
5731 xmLabelGadgetClass, form,
5732 XmNtopAttachment, XmATTACH_POSITION,
5733 XmNtopPosition, 2,
5734 XmNleftAttachment, XmATTACH_POSITION,
5735 XmNleftPosition, 1,
5736 XmNrightAttachment, XmATTACH_POSITION,
5737 XmNrightPosition, 99,
5738 XmNalignment, XmALIGNMENT_CENTER,
5739 XmNlabelString, s1 = XmStringCreateLtoR(
5740 "Colors can be entered as names (e.g. red, blue) or "
5741 "as RGB triples\nin the format #RRGGBB, where each digit "
5742 "is in the range 0-f.", XmFONTLIST_DEFAULT_TAG),
5743 NULL);
5744 XmStringFree(s1);
5746 topW = infoLbl;
5748 /* The left column (foregrounds) of color entry groups */
5749 tmpW = addColorGroup( form, "textFg", 'P', "Plain Text Foreground",
5750 &(cd->textFgW), &(cd->textFgErrW), topW, 1, 49,
5751 textFgModifiedCB, cd );
5752 tmpW = addColorGroup( form, "selectFg", 'S', "Selection Foreground",
5753 &(cd->selectFgW), &(cd->selectFgErrW), tmpW, 1, 49,
5754 selectFgModifiedCB, cd );
5755 tmpW = addColorGroup( form, "hiliteFg", 'M', "Matching (..) Foreground",
5756 &(cd->hiliteFgW), &(cd->hiliteFgErrW), tmpW, 1, 49,
5757 hiliteFgModifiedCB, cd );
5758 tmpW = addColorGroup( form, "lineNoFg", 'L', "Line Numbers",
5759 &(cd->lineNoFgW), &(cd->lineNoFgErrW), tmpW, 1, 49,
5760 lineNoFgModifiedCB, cd );
5762 /* The right column (backgrounds) */
5763 tmpW = addColorGroup( form, "textBg", 'T', "Text Area Background",
5764 &(cd->textBgW), &(cd->textBgErrW), topW, 51, 99,
5765 textBgModifiedCB, cd );
5766 tmpW = addColorGroup( form, "selectBg", 'B', "Selection Background",
5767 &(cd->selectBgW), &(cd->selectBgErrW), tmpW, 51, 99,
5768 selectBgModifiedCB, cd );
5769 tmpW = addColorGroup( form, "hiliteBg", 'h', "Matching (..) Background",
5770 &(cd->hiliteBgW), &(cd->hiliteBgErrW), tmpW, 51, 99,
5771 hiliteBgModifiedCB, cd );
5772 tmpW = addColorGroup( form, "cursorFg", 'C', "Cursor Color",
5773 &(cd->cursorFgW), &(cd->cursorFgErrW), tmpW, 51, 99,
5774 cursorFgModifiedCB, cd );
5776 tmpW = XtVaCreateManagedWidget("infoLbl",
5777 xmLabelGadgetClass, form,
5778 XmNtopAttachment, XmATTACH_WIDGET,
5779 XmNtopWidget, tmpW,
5780 XmNtopOffset, MARGIN_SPACING,
5781 XmNleftAttachment, XmATTACH_POSITION,
5782 XmNleftPosition, 1,
5783 XmNrightAttachment, XmATTACH_POSITION,
5784 XmNrightPosition, 99,
5785 XmNalignment, XmALIGNMENT_CENTER,
5786 XmNlabelString, s1 = XmStringCreateLtoR(
5787 "NOTE: Foreground colors only apply when syntax highlighting "
5788 "is DISABLED.\n", XmFONTLIST_DEFAULT_TAG),
5789 NULL);
5790 XmStringFree(s1);
5792 /* The OK, Apply, and Cancel buttons */
5793 okBtn = XtVaCreateManagedWidget("ok", xmPushButtonWidgetClass, form,
5794 XmNlabelString, s1=XmStringCreateSimple("OK"),
5795 XmNtopAttachment, XmATTACH_WIDGET,
5796 XmNtopWidget, tmpW,
5797 /* XmNtopOffset, MARGIN_SPACING, */
5798 XmNleftAttachment, XmATTACH_POSITION,
5799 XmNleftPosition, 10,
5800 XmNrightAttachment, XmATTACH_POSITION,
5801 XmNrightPosition, 30,
5802 XmNbottomAttachment, XmATTACH_POSITION,
5803 XmNbottomPosition, 99, NULL);
5804 XtAddCallback(okBtn, XmNactivateCallback, colorOkCB, cd);
5805 XmStringFree(s1);
5807 applyBtn = XtVaCreateManagedWidget(
5808 "apply", xmPushButtonWidgetClass, form,
5809 XmNlabelString, s1=XmStringCreateSimple("Apply"),
5810 XmNtopAttachment, XmATTACH_WIDGET,
5811 XmNtopWidget, tmpW,
5812 /* XmNtopOffset, MARGIN_SPACING, */
5813 XmNmnemonic, 'A',
5814 XmNleftAttachment, XmATTACH_POSITION,
5815 XmNleftPosition, 40,
5816 XmNrightAttachment, XmATTACH_POSITION,
5817 XmNrightPosition, 60,
5818 XmNbottomAttachment, XmATTACH_POSITION,
5819 XmNbottomPosition, 99, NULL);
5820 XtAddCallback(applyBtn, XmNactivateCallback, colorApplyCB, cd);
5821 XmStringFree(s1);
5823 dismissBtn = XtVaCreateManagedWidget(
5824 "dismiss", xmPushButtonWidgetClass, form,
5825 XmNlabelString, s1=XmStringCreateSimple("Dismiss"),
5826 XmNtopAttachment, XmATTACH_WIDGET,
5827 XmNtopWidget, tmpW,
5828 /* XmNtopOffset, MARGIN_SPACING, */
5829 XmNleftAttachment, XmATTACH_POSITION,
5830 XmNleftPosition, 70,
5831 XmNrightAttachment, XmATTACH_POSITION,
5832 XmNrightPosition, 90,
5833 XmNbottomAttachment, XmATTACH_POSITION,
5834 XmNbottomPosition, 99, NULL);
5835 XtAddCallback(dismissBtn, XmNactivateCallback, colorDismissCB, cd);
5836 XmStringFree(s1);
5838 /* Set initial default button */
5839 XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
5840 XtVaSetValues(form, XmNcancelButton, dismissBtn, NULL);
5842 /* Set initial values */
5843 XmTextSetString(cd->textFgW, GetPrefColorName(TEXT_FG_COLOR ));
5844 XmTextSetString(cd->textBgW, GetPrefColorName(TEXT_BG_COLOR ));
5845 XmTextSetString(cd->selectFgW, GetPrefColorName(SELECT_FG_COLOR));
5846 XmTextSetString(cd->selectBgW, GetPrefColorName(SELECT_BG_COLOR));
5847 XmTextSetString(cd->hiliteFgW, GetPrefColorName(HILITE_FG_COLOR));
5848 XmTextSetString(cd->hiliteBgW, GetPrefColorName(HILITE_BG_COLOR));
5849 XmTextSetString(cd->lineNoFgW, GetPrefColorName(LINENO_FG_COLOR));
5850 XmTextSetString(cd->cursorFgW, GetPrefColorName(CURSOR_FG_COLOR));
5852 /* Handle mnemonic selection of buttons and focus to dialog */
5853 AddDialogMnemonicHandler(form, FALSE);
5855 /* put up dialog */
5856 ManageDialogCenteredOnPointer(form);