Simplified the color dialog box so that all colors are global. Plug some
[nedit.git] / source / preferences.c
blob218e724bed3a25bd7be68c6d64860a027aec87f5
1 static const char CVSID[] = "$Id: preferences.c,v 1.93 2003/05/24 19:15:20 tringali 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, True},
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 BacklightUseCurrCharTypesAsPref(WindowInfo *window, int quietly)
1681 if (!quietly)
1683 if (DialogF(DF_INF, window->shell, 2, "Backlighting",
1684 "The default backlighting specifications will be\n"
1685 "changed to those of the current window.", "OK", "Cancel") == 2)
1687 return;
1690 SetPrefBacklightCharTypes(window->backlightCharTypes);
1693 void SetPrefRepositionDialogs(int state)
1695 setIntPref(&PrefData.repositionDialogs, state);
1698 int GetPrefRepositionDialogs(void)
1700 return PrefData.repositionDialogs;
1703 void SetPrefAppendLF(int state)
1705 setIntPref(&PrefData.appendLF, state);
1708 int GetPrefAppendLF(void)
1710 return PrefData.appendLF;
1713 void SetPrefSortOpenPrevMenu(int state)
1715 setIntPref(&PrefData.sortOpenPrevMenu, state);
1718 int GetPrefSortOpenPrevMenu(void)
1720 return PrefData.sortOpenPrevMenu;
1723 void SetPrefTagFile(const char *tagFileName)
1725 setStringPref(PrefData.tagFile, tagFileName);
1728 char *GetPrefTagFile(void)
1730 return PrefData.tagFile;
1733 void SetPrefSmartTags(int state)
1735 setIntPref(&PrefData.smartTags, state);
1738 int GetPrefSmartTags(void)
1740 return PrefData.smartTags;
1743 int GetPrefAlwaysCheckRelTagsSpecs(void)
1745 return PrefData.alwaysCheckRelativeTagsSpecs;
1748 char *GetPrefDelimiters(void)
1750 return PrefData.delimiters;
1753 char *GetPrefColorName(int index)
1755 return PrefData.colorNames[index];
1758 void SetPrefColorName(int index, const char *name)
1760 setStringPref(PrefData.colorNames[index], name);
1764 ** Set the font preferences using the font name (the fontList is generated
1765 ** in this call). Note that this leaks memory and server resources each
1766 ** time the default font is re-set. See note on SetFontByName in window.c
1767 ** for more information.
1769 void SetPrefFont(char *fontName)
1771 XFontStruct *font;
1773 setStringPref(PrefData.fontString, fontName);
1774 font = XLoadQueryFont(TheDisplay, fontName);
1775 PrefData.fontList = font==NULL ? NULL :
1776 XmFontListCreate(font, XmSTRING_DEFAULT_CHARSET);
1779 void SetPrefBoldFont(char *fontName)
1781 setStringPref(PrefData.boldFontString, fontName);
1782 PrefData.boldFontStruct = XLoadQueryFont(TheDisplay, fontName);
1785 void SetPrefItalicFont(char *fontName)
1787 setStringPref(PrefData.italicFontString, fontName);
1788 PrefData.italicFontStruct = XLoadQueryFont(TheDisplay, fontName);
1790 void SetPrefBoldItalicFont(char *fontName)
1792 setStringPref(PrefData.boldItalicFontString, fontName);
1793 PrefData.boldItalicFontStruct = XLoadQueryFont(TheDisplay, fontName);
1796 char *GetPrefFontName(void)
1798 return PrefData.fontString;
1801 char *GetPrefBoldFontName(void)
1803 return PrefData.boldFontString;
1806 char *GetPrefItalicFontName(void)
1808 return PrefData.italicFontString;
1811 char *GetPrefBoldItalicFontName(void)
1813 return PrefData.boldItalicFontString;
1816 XmFontList GetPrefFontList(void)
1818 return PrefData.fontList;
1821 XFontStruct *GetPrefBoldFont(void)
1823 return PrefData.boldFontStruct;
1826 XFontStruct *GetPrefItalicFont(void)
1828 return PrefData.italicFontStruct;
1831 XFontStruct *GetPrefBoldItalicFont(void)
1833 return PrefData.boldItalicFontStruct;
1836 char *GetPrefHelpFontName(int index)
1838 return PrefData.helpFontNames[index];
1841 char *GetPrefHelpLinkColor(void)
1843 return PrefData.helpLinkColor;
1846 void SetPrefShell(const char *shell)
1848 setStringPref(PrefData.shell, shell);
1851 char *GetPrefShell(void)
1853 return PrefData.shell;
1856 void SetPrefGeometry(const char *geometry)
1858 setStringPref(PrefData.geometry, geometry);
1861 char *GetPrefGeometry(void)
1863 return PrefData.geometry;
1866 char *GetPrefServerName(void)
1868 return PrefData.serverName;
1871 char *GetPrefBGMenuBtn(void)
1873 return PrefData.bgMenuBtn;
1876 int GetPrefMaxPrevOpenFiles(void)
1878 return PrefData.maxPrevOpenFiles;
1881 int GetPrefTypingHidesPointer(void)
1883 return(PrefData.typingHidesPointer);
1886 #ifdef SGI_CUSTOM
1887 void SetPrefShortMenus(int state)
1889 setIntPref(&PrefData.shortMenus, state);
1892 int GetPrefShortMenus(void)
1894 return PrefData.shortMenus;
1896 #endif
1898 void SetPrefTitleFormat(const char* format)
1900 const WindowInfo* window;
1902 setStringPref(PrefData.titleFormat, format);
1904 /* update all windows */
1905 for (window=WindowList; window!=NULL; window=window->next) {
1906 UpdateWindowTitle(window);
1909 const char* GetPrefTitleFormat(void)
1911 return PrefData.titleFormat;
1914 void SetPrefUndoModifiesSelection(Boolean value)
1916 setIntPref(&PrefData.undoModifiesSelection, value);
1919 Boolean GetPrefUndoModifiesSelection(void)
1921 return (Boolean)PrefData.undoModifiesSelection;
1924 int GetPrefOverrideVirtKeyBindings(void)
1926 return PrefData.virtKeyOverride;
1930 ** If preferences don't get saved, ask the user on exit whether to save
1932 void MarkPrefsChanged(void)
1934 PrefsHaveChanged = True;
1938 ** Check if preferences have changed, and if so, ask the user if he wants
1939 ** to re-save. Returns False if user requests cancelation of Exit (or whatever
1940 ** operation triggered this call to be made).
1942 int CheckPrefsChangesSaved(Widget dialogParent)
1944 int resp;
1946 if (!PrefsHaveChanged)
1947 return True;
1949 resp = DialogF(DF_WARN, dialogParent, 3, "Default Preferences",
1950 ImportedFile == NULL ?
1951 "Default Preferences have changed.\n"
1952 "Save changes to NEdit preference file?" :
1953 "Default Preferences have changed. SAVING \n"
1954 "CHANGES WILL INCORPORATE ADDITIONAL\nSETTINGS FROM FILE: %s",
1955 "Save", "Don't Save", "Cancel", ImportedFile);
1956 if (resp == 2)
1957 return True;
1958 if (resp == 3)
1959 return False;
1961 SaveNEditPrefs(dialogParent, True);
1962 return True;
1966 ** set *prefDataField to newValue, but first check if they're different
1967 ** and update PrefsHaveChanged if a preference setting has now changed.
1969 static void setIntPref(int *prefDataField, int newValue)
1971 if (newValue != *prefDataField)
1972 PrefsHaveChanged = True;
1973 *prefDataField = newValue;
1976 static void setStringPref(char *prefDataField, const char *newValue)
1978 if (strcmp(prefDataField, newValue))
1979 PrefsHaveChanged = True;
1980 strcpy(prefDataField, newValue);
1983 static void setStringAllocPref(char **pprefDataField, char *newValue)
1985 char *p_newField;
1987 /* treat empty strings as nulls */
1988 if (newValue && *newValue == '\0')
1989 newValue = NULL;
1990 if (*pprefDataField && **pprefDataField == '\0')
1991 *pprefDataField = NULL; /* assume statically alloc'ed "" */
1993 /* check changes */
1994 if (!*pprefDataField && !newValue)
1995 return;
1996 else if (!*pprefDataField && newValue)
1997 PrefsHaveChanged = True;
1998 else if (*pprefDataField && !newValue)
1999 PrefsHaveChanged = True;
2000 else if (strcmp(*pprefDataField, newValue))
2001 PrefsHaveChanged = True;
2003 /* get rid of old preference */
2004 if (*pprefDataField)
2005 XtFree(*pprefDataField);
2007 /* store new preference */
2008 if (newValue) {
2009 p_newField = XtMalloc(strlen(newValue) + 1);
2010 strcpy(p_newField, newValue);
2012 *pprefDataField = newValue;
2016 ** Set the language mode for the window, update the menu and trigger language
2017 ** mode specific actions (turn on/off highlighting). If forceNewDefaults is
2018 ** true, re-establish default settings for language-specific preferences
2019 ** regardless of whether they were previously set by the user.
2021 void SetLanguageMode(WindowInfo *window, int mode, int forceNewDefaults)
2023 Widget menu;
2024 WidgetList items;
2025 int n;
2026 Cardinal nItems;
2027 void *userData;
2029 /* Do mode-specific actions */
2030 reapplyLanguageMode(window, mode, forceNewDefaults);
2032 /* Select the correct language mode in the sub-menu */
2033 XtVaGetValues(window->langModeCascade, XmNsubMenuId, &menu, NULL);
2034 XtVaGetValues(menu, XmNchildren, &items, XmNnumChildren, &nItems, NULL);
2035 for (n=0; n<(int)nItems; n++) {
2036 XtVaGetValues(items[n], XmNuserData, &userData, NULL);
2037 XmToggleButtonSetState(items[n], (int)userData == mode, False);
2042 ** Lookup a language mode by name, returning the index of the language
2043 ** mode or PLAIN_LANGUAGE_MODE if the name is not found
2045 int FindLanguageMode(const char *languageName)
2047 int i;
2049 /* Compare each language mode to the one we were presented */
2050 for (i=0; i<NLanguageModes; i++)
2051 if (!strcmp(languageName, LanguageModes[i]->name))
2052 return i;
2054 return PLAIN_LANGUAGE_MODE;
2059 ** Apply language mode matching criteria and set window->languageMode to
2060 ** the appropriate mode for the current file, trigger language mode
2061 ** specific actions (turn on/off highlighting), and update the language
2062 ** mode menu item. If forceNewDefaults is true, re-establish default
2063 ** settings for language-specific preferences regardless of whether
2064 ** they were previously set by the user.
2066 void DetermineLanguageMode(WindowInfo *window, int forceNewDefaults)
2068 SetLanguageMode(window, matchLanguageMode(window), forceNewDefaults);
2072 ** Return the name of the current language mode set in "window", or NULL
2073 ** if the current mode is "Plain".
2075 char *LanguageModeName(int mode)
2077 if (mode == PLAIN_LANGUAGE_MODE)
2078 return NULL;
2079 else
2080 return LanguageModes[mode]->name;
2084 ** Get the set of word delimiters for the language mode set in the current
2085 ** window. Returns NULL when no language mode is set (it would be easy to
2086 ** return the default delimiter set when the current language mode is "Plain",
2087 ** or the mode doesn't have its own delimiters, but this is usually used
2088 ** to supply delimiters for RE searching, and ExecRE can skip compiling a
2089 ** delimiter table when delimiters is NULL).
2091 char *GetWindowDelimiters(WindowInfo *window)
2093 if (window->languageMode == PLAIN_LANGUAGE_MODE)
2094 return NULL;
2095 else
2096 return LanguageModes[window->languageMode]->delimiters;
2100 ** Put up a dialog for selecting a custom initial window size
2102 void RowColumnPrefDialog(Widget parent)
2104 Widget form, selBox, topLabel;
2105 Arg selBoxArgs[2];
2106 XmString s1;
2108 XtSetArg(selBoxArgs[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
2109 XtSetArg(selBoxArgs[1], XmNautoUnmanage, False);
2110 selBox = CreatePromptDialog(parent, "customSize", selBoxArgs, 2);
2111 XtAddCallback(selBox, XmNokCallback, (XtCallbackProc)sizeOKCB, NULL);
2112 XtAddCallback(selBox, XmNcancelCallback, (XtCallbackProc)sizeCancelCB,NULL);
2113 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_TEXT));
2114 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_SELECTION_LABEL));
2115 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_HELP_BUTTON));
2116 XtVaSetValues(XtParent(selBox), XmNtitle, "Initial Window Size", NULL);
2118 form = XtVaCreateManagedWidget("form", xmFormWidgetClass, selBox, NULL);
2120 topLabel = XtVaCreateManagedWidget("topLabel", xmLabelGadgetClass, form,
2121 XmNlabelString, s1=MKSTRING(
2122 "Enter desired size in rows\nand columns of characters:"), NULL);
2123 XmStringFree(s1);
2125 RowText = XtVaCreateManagedWidget("rows", xmTextWidgetClass, form,
2126 XmNcolumns, 3,
2127 XmNtopAttachment, XmATTACH_WIDGET,
2128 XmNleftAttachment, XmATTACH_POSITION,
2129 XmNrightAttachment, XmATTACH_POSITION,
2130 XmNtopWidget, topLabel,
2131 XmNleftPosition, 5,
2132 XmNrightPosition, 45, NULL);
2133 RemapDeleteKey(RowText);
2135 XtVaCreateManagedWidget("xLabel", xmLabelGadgetClass, form,
2136 XmNlabelString, s1=MKSTRING("x"),
2137 XmNtopAttachment, XmATTACH_WIDGET,
2138 XmNleftAttachment, XmATTACH_POSITION,
2139 XmNrightAttachment, XmATTACH_POSITION,
2140 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2141 XmNtopWidget, topLabel,
2142 XmNbottomWidget, RowText,
2143 XmNleftPosition, 45,
2144 XmNrightPosition, 55, NULL);
2145 XmStringFree(s1);
2147 ColText = XtVaCreateManagedWidget("cols", xmTextWidgetClass, form,
2148 XmNcolumns, 3,
2149 XmNtopAttachment, XmATTACH_WIDGET,
2150 XmNleftAttachment, XmATTACH_POSITION,
2151 XmNrightAttachment, XmATTACH_POSITION,
2152 XmNtopWidget, topLabel,
2153 XmNleftPosition, 55,
2154 XmNrightPosition, 95, NULL);
2155 RemapDeleteKey(ColText);
2157 /* put up dialog and wait for user to press ok or cancel */
2158 DoneWithSizeDialog = False;
2159 ManageDialogCenteredOnPointer(selBox);
2160 while (!DoneWithSizeDialog)
2162 XEvent event;
2163 XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
2164 ServerDispatchEvent(&event);
2167 XtDestroyWidget(selBox);
2170 static void sizeOKCB(Widget w, XtPointer clientData, XtPointer callData)
2172 int rowValue, colValue, stat;
2174 /* get the values that the user entered and make sure they're ok */
2175 stat = GetIntTextWarn(RowText, &rowValue, "number of rows", True);
2176 if (stat != TEXT_READ_OK)
2177 return;
2178 stat = GetIntTextWarn(ColText, &colValue, "number of columns", True);
2179 if (stat != TEXT_READ_OK)
2180 return;
2182 /* set the corresponding preferences and dismiss the dialog */
2183 SetPrefRows(rowValue);
2184 SetPrefCols(colValue);
2185 DoneWithSizeDialog = True;
2188 static void sizeCancelCB(Widget w, XtPointer clientData, XtPointer callData)
2190 DoneWithSizeDialog = True;
2194 ** Present the user a dialog for setting tab related preferences, either as
2195 ** defaults, or for a specific window (pass "forWindow" as NULL to set default
2196 ** preference, or a window to set preferences for the specific window.
2198 void TabsPrefDialog(Widget parent, WindowInfo *forWindow)
2200 Widget form, selBox;
2201 Arg selBoxArgs[2];
2202 XmString s1;
2203 int emulate, emTabDist, useTabs, tabDist;
2205 XtSetArg(selBoxArgs[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
2206 XtSetArg(selBoxArgs[1], XmNautoUnmanage, False);
2207 selBox = CreatePromptDialog(parent, "customSize", selBoxArgs, 2);
2208 XtAddCallback(selBox, XmNokCallback, (XtCallbackProc)tabsOKCB, NULL);
2209 XtAddCallback(selBox, XmNcancelCallback, (XtCallbackProc)tabsCancelCB,NULL);
2210 XtAddCallback(selBox, XmNhelpCallback, (XtCallbackProc)tabsHelpCB,NULL);
2211 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_TEXT));
2212 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_SELECTION_LABEL));
2213 XtVaSetValues(XtParent(selBox), XmNtitle, "Tabs", NULL);
2215 form = XtVaCreateManagedWidget("form", xmFormWidgetClass, selBox, NULL);
2217 TabDistText = XtVaCreateManagedWidget("tabDistText", xmTextWidgetClass,
2218 form, XmNcolumns, 7,
2219 XmNtopAttachment, XmATTACH_FORM,
2220 XmNrightAttachment, XmATTACH_FORM, NULL);
2221 RemapDeleteKey(TabDistText);
2222 XtVaCreateManagedWidget("tabDistLabel", xmLabelGadgetClass, form,
2223 XmNlabelString, s1=XmStringCreateSimple(
2224 "Tab spacing (for hardware tab characters)"),
2225 XmNmnemonic, 'T',
2226 XmNuserData, TabDistText,
2227 XmNtopAttachment, XmATTACH_FORM,
2228 XmNleftAttachment, XmATTACH_FORM,
2229 XmNrightAttachment, XmATTACH_WIDGET,
2230 XmNrightWidget, TabDistText,
2231 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2232 XmNbottomWidget, TabDistText, NULL);
2233 XmStringFree(s1);
2235 EmTabText = XtVaCreateManagedWidget("emTabText", xmTextWidgetClass, form,
2236 XmNcolumns, 7,
2237 XmNtopAttachment, XmATTACH_WIDGET,
2238 XmNtopWidget, TabDistText,
2239 XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET,
2240 XmNrightWidget, TabDistText, NULL);
2241 RemapDeleteKey(EmTabText);
2242 EmTabLabel = XtVaCreateManagedWidget("emTabLabel", xmLabelGadgetClass, form,
2243 XmNlabelString, s1=XmStringCreateSimple("Emulated tab spacing"),
2244 XmNmnemonic, 's',
2245 XmNuserData, EmTabText,
2246 XmNtopAttachment, XmATTACH_WIDGET,
2247 XmNtopWidget, TabDistText,
2248 XmNrightAttachment, XmATTACH_WIDGET,
2249 XmNrightWidget, EmTabText,
2250 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2251 XmNbottomWidget, EmTabText, NULL);
2252 XmStringFree(s1);
2253 EmTabToggle = XtVaCreateManagedWidget("emTabToggle",
2254 xmToggleButtonWidgetClass, form, XmNlabelString,
2255 s1=XmStringCreateSimple("Emulate tabs"),
2256 XmNmnemonic, 'E',
2257 XmNtopAttachment, XmATTACH_WIDGET,
2258 XmNtopWidget, TabDistText,
2259 XmNleftAttachment, XmATTACH_FORM,
2260 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2261 XmNbottomWidget, EmTabText, NULL);
2262 XmStringFree(s1);
2263 XtAddCallback(EmTabToggle, XmNvalueChangedCallback, emTabsCB, NULL);
2264 UseTabsToggle = XtVaCreateManagedWidget("useTabsToggle",
2265 xmToggleButtonWidgetClass, form,
2266 XmNlabelString, s1=XmStringCreateSimple(
2267 "Use tab characters in padding and emulated tabs"),
2268 XmNmnemonic, 'U',
2269 XmNtopAttachment, XmATTACH_WIDGET,
2270 XmNtopWidget, EmTabText,
2271 XmNtopOffset, 5,
2272 XmNleftAttachment, XmATTACH_FORM, NULL);
2273 XmStringFree(s1);
2275 /* Set default values */
2276 if (forWindow == NULL) {
2277 emTabDist = GetPrefEmTabDist(PLAIN_LANGUAGE_MODE);
2278 useTabs = GetPrefInsertTabs();
2279 tabDist = GetPrefTabDist(PLAIN_LANGUAGE_MODE);
2280 } else {
2281 XtVaGetValues(forWindow->textArea, textNemulateTabs, &emTabDist, NULL);
2282 useTabs = forWindow->buffer->useTabs;
2283 tabDist = BufGetTabDistance(forWindow->buffer);
2285 emulate = emTabDist != 0;
2286 SetIntText(TabDistText, tabDist);
2287 XmToggleButtonSetState(EmTabToggle, emulate, True);
2288 if (emulate)
2289 SetIntText(EmTabText, emTabDist);
2290 XmToggleButtonSetState(UseTabsToggle, useTabs, False);
2291 XtSetSensitive(EmTabText, emulate);
2292 XtSetSensitive(EmTabLabel, emulate);
2294 /* Handle mnemonic selection of buttons and focus to dialog */
2295 AddDialogMnemonicHandler(form, FALSE);
2297 /* Set the widget to get focus */
2298 #if XmVersion >= 1002
2299 XtVaSetValues(form, XmNinitialFocus, TabDistText, NULL);
2300 #endif
2302 /* put up dialog and wait for user to press ok or cancel */
2303 TabsDialogForWindow = forWindow;
2304 DoneWithTabsDialog = False;
2305 ManageDialogCenteredOnPointer(selBox);
2306 while (!DoneWithTabsDialog)
2308 XEvent event;
2309 XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
2310 ServerDispatchEvent(&event);
2313 XtDestroyWidget(selBox);
2316 static void tabsOKCB(Widget w, XtPointer clientData, XtPointer callData)
2318 int emulate, useTabs, stat, tabDist, emTabDist;
2319 WindowInfo *window = TabsDialogForWindow;
2321 /* get the values that the user entered and make sure they're ok */
2322 emulate = XmToggleButtonGetState(EmTabToggle);
2323 useTabs = XmToggleButtonGetState(UseTabsToggle);
2324 stat = GetIntTextWarn(TabDistText, &tabDist, "tab spacing", True);
2325 if (stat != TEXT_READ_OK)
2326 return;
2328 if (tabDist <= 0 || tabDist > MAX_EXP_CHAR_LEN)
2330 DialogF(DF_WARN, TabDistText, 1, "Tab Spacing",
2331 "Tab spacing out of range", "Dismiss");
2332 return;
2335 if (emulate) {
2336 stat = GetIntTextWarn(EmTabText, &emTabDist, "emulated tab spacing",True);
2337 if (stat != TEXT_READ_OK)
2338 return;
2340 if (emTabDist <= 0 || tabDist >= 1000)
2342 DialogF(DF_WARN, EmTabText, 1, "Tab Spacing",
2343 "Emulated tab spacing out of range", "Dismiss");
2344 return;
2346 } else
2347 emTabDist = 0;
2349 #ifdef SGI_CUSTOM
2350 /* Ask the user about saving as a default preference */
2351 if (TabsDialogForWindow != NULL) {
2352 int setDefault;
2353 if (!shortPrefToDefault(window->shell, "Tab Settings", &setDefault)) {
2354 DoneWithTabsDialog = True;
2355 return;
2357 if (setDefault) {
2358 SetPrefTabDist(tabDist);
2359 SetPrefEmTabDist(emTabDist);
2360 SetPrefInsertTabs(useTabs);
2361 SaveNEditPrefs(window->shell, GetPrefShortMenus());
2364 #endif
2366 /* Set the value in either the requested window or default preferences */
2367 if (TabsDialogForWindow == NULL) {
2368 SetPrefTabDist(tabDist);
2369 SetPrefEmTabDist(emTabDist);
2370 SetPrefInsertTabs(useTabs);
2371 } else {
2372 char *params[1];
2373 char numStr[25];
2375 params[0] = numStr;
2376 sprintf(numStr, "%d", tabDist);
2377 XtCallActionProc(window->textArea, "set_tab_dist", NULL, params, 1);
2378 params[0] = numStr;
2379 sprintf(numStr, "%d", emTabDist);
2380 XtCallActionProc(window->textArea, "set_em_tab_dist", NULL, params, 1);
2381 params[0] = numStr;
2382 sprintf(numStr, "%d", useTabs);
2383 XtCallActionProc(window->textArea, "set_use_tabs", NULL, params, 1);
2385 setTabDist(window, tabDist);
2386 setEmTabDist(window, emTabDist);
2387 window->buffer->useTabs = useTabs;
2390 DoneWithTabsDialog = True;
2393 static void tabsCancelCB(Widget w, XtPointer clientData, XtPointer callData)
2395 DoneWithTabsDialog = True;
2398 static void tabsHelpCB(Widget w, XtPointer clientData, XtPointer callData)
2400 Help(HELP_TABS_DIALOG);
2403 static void emTabsCB(Widget w, XtPointer clientData, XtPointer callData)
2405 int state = XmToggleButtonGetState(w);
2407 XtSetSensitive(EmTabLabel, state);
2408 XtSetSensitive(EmTabText, state);
2412 ** Present the user a dialog for setting wrap margin.
2414 void WrapMarginDialog(Widget parent, WindowInfo *forWindow)
2416 Widget form, selBox;
2417 Arg selBoxArgs[2];
2418 XmString s1;
2419 int margin;
2421 XtSetArg(selBoxArgs[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
2422 XtSetArg(selBoxArgs[1], XmNautoUnmanage, False);
2423 selBox = CreatePromptDialog(parent, "wrapMargin", selBoxArgs, 2);
2424 XtAddCallback(selBox, XmNokCallback, (XtCallbackProc)wrapOKCB, NULL);
2425 XtAddCallback(selBox, XmNcancelCallback, (XtCallbackProc)wrapCancelCB,NULL);
2426 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_TEXT));
2427 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_SELECTION_LABEL));
2428 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_HELP_BUTTON));
2429 XtVaSetValues(XtParent(selBox), XmNtitle, "Wrap Margin", NULL);
2431 form = XtVaCreateManagedWidget("form", xmFormWidgetClass, selBox, NULL);
2433 WrapWindowToggle = XtVaCreateManagedWidget("wrapWindowToggle",
2434 xmToggleButtonWidgetClass, form, XmNlabelString,
2435 s1=XmStringCreateSimple("Wrap and Fill at width of window"),
2436 XmNmnemonic, 'W',
2437 XmNtopAttachment, XmATTACH_FORM,
2438 XmNleftAttachment, XmATTACH_FORM, NULL);
2439 XmStringFree(s1);
2440 XtAddCallback(WrapWindowToggle, XmNvalueChangedCallback, wrapWindowCB,NULL);
2441 WrapText = XtVaCreateManagedWidget("wrapText", xmTextWidgetClass, form,
2442 XmNcolumns, 5,
2443 XmNtopAttachment, XmATTACH_WIDGET,
2444 XmNtopWidget, WrapWindowToggle,
2445 XmNrightAttachment, XmATTACH_FORM, NULL);
2446 RemapDeleteKey(WrapText);
2447 WrapTextLabel = XtVaCreateManagedWidget("wrapMarginLabel",
2448 xmLabelGadgetClass, form,
2449 XmNlabelString, s1=XmStringCreateSimple(
2450 "Margin for Wrap and Fill"),
2451 XmNmnemonic, 'M',
2452 XmNuserData, WrapText,
2453 XmNtopAttachment, XmATTACH_WIDGET,
2454 XmNtopWidget, WrapWindowToggle,
2455 XmNleftAttachment, XmATTACH_FORM,
2456 XmNrightAttachment, XmATTACH_WIDGET,
2457 XmNrightWidget, WrapText,
2458 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2459 XmNbottomWidget, WrapText, NULL);
2460 XmStringFree(s1);
2462 /* Set default value */
2463 if (forWindow == NULL)
2464 margin = GetPrefWrapMargin();
2465 else
2466 XtVaGetValues(forWindow->textArea, textNwrapMargin, &margin, NULL);
2467 XmToggleButtonSetState(WrapWindowToggle, margin==0, True);
2468 if (margin != 0)
2469 SetIntText(WrapText, margin);
2470 XtSetSensitive(WrapText, margin!=0);
2471 XtSetSensitive(WrapTextLabel, margin!=0);
2473 /* Handle mnemonic selection of buttons and focus to dialog */
2474 AddDialogMnemonicHandler(form, FALSE);
2476 /* put up dialog and wait for user to press ok or cancel */
2477 WrapDialogForWindow = forWindow;
2478 DoneWithWrapDialog = False;
2479 ManageDialogCenteredOnPointer(selBox);
2480 while (!DoneWithWrapDialog)
2482 XEvent event;
2483 XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
2484 ServerDispatchEvent(&event);
2487 XtDestroyWidget(selBox);
2490 static void wrapOKCB(Widget w, XtPointer clientData, XtPointer callData)
2492 int wrapAtWindow, margin, stat;
2493 WindowInfo *window = WrapDialogForWindow;
2495 /* get the values that the user entered and make sure they're ok */
2496 wrapAtWindow = XmToggleButtonGetState(WrapWindowToggle);
2497 if (wrapAtWindow)
2498 margin = 0;
2499 else {
2500 stat = GetIntTextWarn(WrapText, &margin, "wrap Margin", True);
2501 if (stat != TEXT_READ_OK)
2502 return;
2504 if (margin <= 0 || margin >= 1000)
2506 DialogF(DF_WARN, WrapText, 1, "Wrap Margin",
2507 "Wrap margin out of range", "Dismiss");
2508 return;
2513 #ifdef SGI_CUSTOM
2514 /* Ask the user about saving as a default preference */
2515 if (WrapDialogForWindow != NULL) {
2516 int setDefault;
2517 if (!shortPrefToDefault(window->shell, "Wrap Margin Settings",
2518 &setDefault)) {
2519 DoneWithWrapDialog = True;
2520 return;
2522 if (setDefault) {
2523 SetPrefWrapMargin(margin);
2524 SaveNEditPrefs(window->shell, GetPrefShortMenus());
2527 #endif
2529 /* Set the value in either the requested window or default preferences */
2530 if (WrapDialogForWindow == NULL)
2531 SetPrefWrapMargin(margin);
2532 else {
2533 char *params[1];
2534 char marginStr[25];
2535 sprintf(marginStr, "%d", margin);
2536 params[0] = marginStr;
2537 XtCallActionProc(window->textArea, "set_wrap_margin", NULL, params, 1);
2539 DoneWithWrapDialog = True;
2542 static void wrapCancelCB(Widget w, XtPointer clientData, XtPointer callData)
2544 DoneWithWrapDialog = True;
2547 static void wrapWindowCB(Widget w, XtPointer clientData, XtPointer callData)
2549 int wrapAtWindow = XmToggleButtonGetState(w);
2551 XtSetSensitive(WrapTextLabel, !wrapAtWindow);
2552 XtSetSensitive(WrapText, !wrapAtWindow);
2556 ** Present a dialog for editing language mode information
2558 void EditLanguageModes()
2560 #define LIST_RIGHT 40
2561 #define LEFT_MARGIN_POS 1
2562 #define RIGHT_MARGIN_POS 99
2563 #define H_MARGIN 5
2564 Widget form, nameLbl, topLbl, extLbl, recogLbl, delimitLbl, defTipsLbl;
2565 Widget okBtn, applyBtn, dismissBtn;
2566 Widget overrideFrame, overrideForm, delimitForm;
2567 Widget tabForm, tabLbl, indentBox, wrapBox;
2568 XmString s1;
2569 int i, ac;
2570 Arg args[20];
2572 /* if the dialog is already displayed, just pop it to the top and return */
2573 if (LMDialog.shell != NULL) {
2574 RaiseShellWindow(LMDialog.shell);
2575 return;
2578 LMDialog.languageModeList = (languageModeRec **)XtMalloc(
2579 sizeof(languageModeRec *) * MAX_LANGUAGE_MODES);
2580 for (i=0; i<NLanguageModes; i++)
2581 LMDialog.languageModeList[i] = copyLanguageModeRec(LanguageModes[i]);
2582 LMDialog.nLanguageModes = NLanguageModes;
2584 /* Create a form widget in an application shell */
2585 ac = 0;
2586 XtSetArg(args[ac], XmNdeleteResponse, XmDO_NOTHING); ac++;
2587 XtSetArg(args[ac], XmNiconName, "NEdit Language Modes"); ac++;
2588 XtSetArg(args[ac], XmNtitle, "Language Modes"); ac++;
2589 LMDialog.shell = CreateShellWithBestVis(APP_NAME, APP_CLASS,
2590 applicationShellWidgetClass, TheDisplay, args, ac);
2591 AddSmallIcon(LMDialog.shell);
2592 form = XtVaCreateManagedWidget("editLanguageModes", xmFormWidgetClass,
2593 LMDialog.shell, XmNautoUnmanage, False,
2594 XmNresizePolicy, XmRESIZE_NONE, NULL);
2595 XtAddCallback(form, XmNdestroyCallback, lmDestroyCB, NULL);
2596 AddMotifCloseCallback(LMDialog.shell, lmDismissCB, NULL);
2598 topLbl = XtVaCreateManagedWidget("topLabel", xmLabelGadgetClass, form,
2599 XmNlabelString, s1=MKSTRING(
2600 "To modify the properties of an existing language mode, select the name from\n\
2601 the list on the left. To add a new language, select \"New\" from the list."),
2602 XmNmnemonic, 'N',
2603 XmNtopAttachment, XmATTACH_POSITION,
2604 XmNtopPosition, 2,
2605 XmNleftAttachment, XmATTACH_POSITION,
2606 XmNleftPosition, LEFT_MARGIN_POS,
2607 XmNrightAttachment, XmATTACH_POSITION,
2608 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
2609 XmStringFree(s1);
2611 nameLbl = XtVaCreateManagedWidget("nameLbl", xmLabelGadgetClass, form,
2612 XmNlabelString, s1=XmStringCreateSimple("Name"),
2613 XmNmnemonic, 'm',
2614 XmNalignment, XmALIGNMENT_BEGINNING,
2615 XmNleftAttachment, XmATTACH_POSITION,
2616 XmNleftPosition, LIST_RIGHT,
2617 XmNtopAttachment, XmATTACH_WIDGET,
2618 XmNtopOffset, H_MARGIN,
2619 XmNtopWidget, topLbl, NULL);
2620 XmStringFree(s1);
2622 LMDialog.nameW = XtVaCreateManagedWidget("name", xmTextWidgetClass, form,
2623 XmNcolumns, 15,
2624 XmNleftAttachment, XmATTACH_POSITION,
2625 XmNleftPosition, LIST_RIGHT,
2626 XmNtopAttachment, XmATTACH_WIDGET,
2627 XmNtopWidget, nameLbl,
2628 XmNrightAttachment, XmATTACH_POSITION,
2629 XmNrightPosition, (RIGHT_MARGIN_POS + LIST_RIGHT)/2, NULL);
2630 RemapDeleteKey(LMDialog.nameW);
2631 XtVaSetValues(nameLbl, XmNuserData, LMDialog.nameW, NULL);
2633 extLbl = XtVaCreateManagedWidget("extLbl", xmLabelGadgetClass, form,
2634 XmNlabelString,
2635 s1=XmStringCreateSimple("File extensions (separate w/ space)"),
2636 XmNmnemonic, 'F',
2637 XmNalignment, XmALIGNMENT_BEGINNING,
2638 XmNleftAttachment, XmATTACH_POSITION,
2639 XmNleftPosition, LIST_RIGHT,
2640 XmNtopAttachment, XmATTACH_WIDGET,
2641 XmNtopOffset, H_MARGIN,
2642 XmNtopWidget, LMDialog.nameW, NULL);
2643 XmStringFree(s1);
2645 LMDialog.extW = XtVaCreateManagedWidget("ext", xmTextWidgetClass, form,
2646 XmNleftAttachment, XmATTACH_POSITION,
2647 XmNleftPosition, LIST_RIGHT,
2648 XmNtopAttachment, XmATTACH_WIDGET,
2649 XmNtopWidget, extLbl,
2650 XmNrightAttachment, XmATTACH_POSITION,
2651 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
2652 RemapDeleteKey(LMDialog.extW);
2653 XtVaSetValues(extLbl, XmNuserData, LMDialog.extW, NULL);
2655 recogLbl = XtVaCreateManagedWidget("recogLbl", xmLabelGadgetClass, form,
2656 XmNlabelString, s1=MKSTRING(
2657 "Recognition regular expression (applied to first 200\n\
2658 characters of file to determine type from content)"),
2659 XmNalignment, XmALIGNMENT_BEGINNING,
2660 XmNmnemonic, 'R',
2661 XmNleftAttachment, XmATTACH_POSITION,
2662 XmNleftPosition, LIST_RIGHT,
2663 XmNtopAttachment, XmATTACH_WIDGET,
2664 XmNtopOffset, H_MARGIN,
2665 XmNtopWidget, LMDialog.extW, NULL);
2666 XmStringFree(s1);
2668 LMDialog.recogW = XtVaCreateManagedWidget("recog", xmTextWidgetClass, form,
2669 XmNleftAttachment, XmATTACH_POSITION,
2670 XmNleftPosition, LIST_RIGHT,
2671 XmNtopAttachment, XmATTACH_WIDGET,
2672 XmNtopWidget, recogLbl,
2673 XmNrightAttachment, XmATTACH_POSITION,
2674 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
2675 RemapDeleteKey(LMDialog.recogW);
2676 XtVaSetValues(recogLbl, XmNuserData, LMDialog.recogW, NULL);
2678 defTipsLbl = XtVaCreateManagedWidget("defTipsLbl", xmLabelGadgetClass, form,
2679 XmNlabelString, s1=MKSTRING(
2680 "Default calltips file(s) (separate w/colons)"),
2681 XmNalignment, XmALIGNMENT_BEGINNING,
2682 XmNmnemonic, 'c',
2683 XmNleftAttachment, XmATTACH_POSITION,
2684 XmNleftPosition, LIST_RIGHT,
2685 XmNtopAttachment, XmATTACH_WIDGET,
2686 XmNtopOffset, H_MARGIN,
2687 XmNtopWidget, LMDialog.recogW, NULL);
2688 XmStringFree(s1);
2690 LMDialog.defTipsW = XtVaCreateManagedWidget("defTips", xmTextWidgetClass,
2691 form,
2692 XmNleftAttachment, XmATTACH_POSITION,
2693 XmNleftPosition, LIST_RIGHT,
2694 XmNtopAttachment, XmATTACH_WIDGET,
2695 XmNtopWidget, defTipsLbl,
2696 XmNrightAttachment, XmATTACH_POSITION,
2697 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
2698 RemapDeleteKey(LMDialog.defTipsW);
2699 XtVaSetValues(defTipsLbl, XmNuserData, LMDialog.defTipsW, NULL);
2701 okBtn = XtVaCreateManagedWidget("ok", xmPushButtonWidgetClass, form,
2702 XmNlabelString, s1=XmStringCreateSimple("OK"),
2703 XmNleftAttachment, XmATTACH_POSITION,
2704 XmNleftPosition, 10,
2705 XmNrightAttachment, XmATTACH_POSITION,
2706 XmNrightPosition, 30,
2707 XmNbottomAttachment, XmATTACH_POSITION,
2708 XmNbottomPosition, 99, NULL);
2709 XtAddCallback(okBtn, XmNactivateCallback, lmOkCB, NULL);
2710 XmStringFree(s1);
2712 applyBtn = XtVaCreateManagedWidget("apply", xmPushButtonWidgetClass, form,
2713 XmNlabelString, s1=XmStringCreateSimple("Apply"),
2714 XmNmnemonic, 'A',
2715 XmNleftAttachment, XmATTACH_POSITION,
2716 XmNleftPosition, 40,
2717 XmNrightAttachment, XmATTACH_POSITION,
2718 XmNrightPosition, 60,
2719 XmNbottomAttachment, XmATTACH_POSITION,
2720 XmNbottomPosition, 99, NULL);
2721 XtAddCallback(applyBtn, XmNactivateCallback, lmApplyCB, NULL);
2722 XmStringFree(s1);
2724 dismissBtn = XtVaCreateManagedWidget("dismiss",xmPushButtonWidgetClass,form,
2725 XmNlabelString, s1=XmStringCreateSimple("Dismiss"),
2726 XmNleftAttachment, XmATTACH_POSITION,
2727 XmNleftPosition, 70,
2728 XmNrightAttachment, XmATTACH_POSITION,
2729 XmNrightPosition, 90,
2730 XmNbottomAttachment, XmATTACH_POSITION,
2731 XmNbottomPosition, 99, NULL);
2732 XtAddCallback(dismissBtn, XmNactivateCallback, lmDismissCB, NULL);
2733 XmStringFree(s1);
2735 overrideFrame = XtVaCreateManagedWidget("overrideFrame",
2736 xmFrameWidgetClass, form,
2737 XmNleftAttachment, XmATTACH_POSITION,
2738 XmNleftPosition, LEFT_MARGIN_POS,
2739 XmNrightAttachment, XmATTACH_POSITION,
2740 XmNrightPosition, RIGHT_MARGIN_POS,
2741 XmNbottomAttachment, XmATTACH_WIDGET,
2742 XmNbottomWidget, dismissBtn,
2743 XmNbottomOffset, H_MARGIN, NULL);
2744 overrideForm = XtVaCreateManagedWidget("overrideForm", xmFormWidgetClass,
2745 overrideFrame, NULL);
2746 XtVaCreateManagedWidget("overrideLbl", xmLabelGadgetClass, overrideFrame,
2747 XmNlabelString, s1=XmStringCreateSimple("Override Defaults"),
2748 XmNchildType, XmFRAME_TITLE_CHILD,
2749 XmNchildHorizontalAlignment, XmALIGNMENT_CENTER, NULL);
2750 XmStringFree(s1);
2752 delimitForm = XtVaCreateManagedWidget("delimitForm", xmFormWidgetClass,
2753 overrideForm,
2754 XmNleftAttachment, XmATTACH_POSITION,
2755 XmNleftPosition, LEFT_MARGIN_POS,
2756 XmNtopAttachment, XmATTACH_FORM,
2757 XmNtopOffset, H_MARGIN,
2758 XmNrightAttachment, XmATTACH_POSITION,
2759 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
2760 delimitLbl = XtVaCreateManagedWidget("delimitLbl", xmLabelGadgetClass,
2761 delimitForm,
2762 XmNlabelString, s1=XmStringCreateSimple("Word delimiters"),
2763 XmNmnemonic, 'W',
2764 XmNleftAttachment, XmATTACH_FORM,
2765 XmNtopAttachment, XmATTACH_FORM,
2766 XmNbottomAttachment, XmATTACH_FORM, NULL);
2767 XmStringFree(s1);
2768 LMDialog.delimitW = XtVaCreateManagedWidget("delimit", xmTextWidgetClass,
2769 delimitForm,
2770 XmNtopAttachment, XmATTACH_FORM,
2771 XmNleftAttachment, XmATTACH_WIDGET,
2772 XmNleftWidget, delimitLbl,
2773 XmNrightAttachment, XmATTACH_FORM,
2774 XmNbottomAttachment, XmATTACH_FORM, NULL);
2775 RemapDeleteKey(LMDialog.delimitW);
2776 XtVaSetValues(delimitLbl, XmNuserData, LMDialog.delimitW, NULL);
2778 tabForm = XtVaCreateManagedWidget("tabForm", xmFormWidgetClass,
2779 overrideForm,
2780 XmNleftAttachment, XmATTACH_POSITION,
2781 XmNleftPosition, LEFT_MARGIN_POS,
2782 XmNtopAttachment, XmATTACH_WIDGET,
2783 XmNtopWidget, delimitForm,
2784 XmNtopOffset, H_MARGIN,
2785 XmNrightAttachment, XmATTACH_POSITION,
2786 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
2787 tabLbl = XtVaCreateManagedWidget("tabLbl", xmLabelGadgetClass, tabForm,
2788 XmNlabelString, s1=XmStringCreateSimple(
2789 "Alternative hardware tab spacing"),
2790 XmNmnemonic, 't',
2791 XmNleftAttachment, XmATTACH_FORM,
2792 XmNtopAttachment, XmATTACH_FORM,
2793 XmNbottomAttachment, XmATTACH_FORM, NULL);
2794 XmStringFree(s1);
2795 LMDialog.tabW = XtVaCreateManagedWidget("delimit", xmTextWidgetClass,
2796 tabForm,
2797 XmNcolumns, 3,
2798 XmNtopAttachment, XmATTACH_FORM,
2799 XmNleftAttachment, XmATTACH_WIDGET,
2800 XmNleftWidget, tabLbl,
2801 XmNbottomAttachment, XmATTACH_FORM, NULL);
2802 RemapDeleteKey(LMDialog.tabW);
2803 XtVaSetValues(tabLbl, XmNuserData, LMDialog.tabW, NULL);
2804 LMDialog.emTabW = XtVaCreateManagedWidget("delimit", xmTextWidgetClass,
2805 tabForm,
2806 XmNcolumns, 3,
2807 XmNtopAttachment, XmATTACH_FORM,
2808 XmNrightAttachment, XmATTACH_FORM,
2809 XmNbottomAttachment, XmATTACH_FORM, NULL);
2810 RemapDeleteKey(LMDialog.emTabW);
2811 XtVaCreateManagedWidget("emTabLbl", xmLabelGadgetClass, tabForm,
2812 XmNlabelString,
2813 s1=XmStringCreateSimple("Alternative emulated tab spacing"),
2814 XmNalignment, XmALIGNMENT_END,
2815 XmNmnemonic, 'e',
2816 XmNuserData, LMDialog.emTabW,
2817 XmNleftAttachment, XmATTACH_WIDGET,
2818 XmNleftWidget, LMDialog.tabW,
2819 XmNrightAttachment, XmATTACH_WIDGET,
2820 XmNrightWidget, LMDialog.emTabW,
2821 XmNtopAttachment, XmATTACH_FORM,
2822 XmNbottomAttachment, XmATTACH_FORM, NULL);
2823 XmStringFree(s1);
2825 indentBox = XtVaCreateManagedWidget("indentBox", xmRowColumnWidgetClass,
2826 overrideForm,
2827 XmNorientation, XmHORIZONTAL,
2828 XmNpacking, XmPACK_TIGHT,
2829 XmNradioBehavior, True,
2830 XmNleftAttachment, XmATTACH_POSITION,
2831 XmNleftPosition, LEFT_MARGIN_POS,
2832 XmNtopAttachment, XmATTACH_WIDGET,
2833 XmNtopWidget, tabForm,
2834 XmNtopOffset, H_MARGIN, NULL);
2835 LMDialog.defaultIndentW = XtVaCreateManagedWidget("defaultIndent",
2836 xmToggleButtonWidgetClass, indentBox,
2837 XmNset, True,
2838 XmNmarginHeight, 0,
2839 XmNlabelString, s1=XmStringCreateSimple("Default indent style"),
2840 XmNmnemonic, 'D', NULL);
2841 XmStringFree(s1);
2842 LMDialog.noIndentW = XtVaCreateManagedWidget("noIndent",
2843 xmToggleButtonWidgetClass, indentBox,
2844 XmNmarginHeight, 0,
2845 XmNlabelString, s1=XmStringCreateSimple("No automatic indent"),
2846 XmNmnemonic, 'N', NULL);
2847 XmStringFree(s1);
2848 LMDialog.autoIndentW = XtVaCreateManagedWidget("autoIndent",
2849 xmToggleButtonWidgetClass, indentBox,
2850 XmNmarginHeight, 0,
2851 XmNlabelString, s1=XmStringCreateSimple("Auto-indent"),
2852 XmNmnemonic, 'A', NULL);
2853 XmStringFree(s1);
2854 LMDialog.smartIndentW = XtVaCreateManagedWidget("smartIndent",
2855 xmToggleButtonWidgetClass, indentBox,
2856 XmNmarginHeight, 0,
2857 XmNlabelString, s1=XmStringCreateSimple("Smart-indent"),
2858 XmNmnemonic, 'S', NULL);
2859 XmStringFree(s1);
2861 wrapBox = XtVaCreateManagedWidget("wrapBox", xmRowColumnWidgetClass,
2862 overrideForm,
2863 XmNorientation, XmHORIZONTAL,
2864 XmNpacking, XmPACK_TIGHT,
2865 XmNradioBehavior, True,
2866 XmNleftAttachment, XmATTACH_POSITION,
2867 XmNleftPosition, LEFT_MARGIN_POS,
2868 XmNtopAttachment, XmATTACH_WIDGET,
2869 XmNtopWidget, indentBox,
2870 XmNtopOffset, H_MARGIN,
2871 XmNbottomAttachment, XmATTACH_FORM,
2872 XmNbottomOffset, H_MARGIN, NULL);
2873 LMDialog.defaultWrapW = XtVaCreateManagedWidget("defaultWrap",
2874 xmToggleButtonWidgetClass, wrapBox,
2875 XmNset, True,
2876 XmNmarginHeight, 0,
2877 XmNlabelString, s1=XmStringCreateSimple("Default wrap style"),
2878 XmNmnemonic, 'D', NULL);
2879 XmStringFree(s1);
2880 LMDialog.noWrapW = XtVaCreateManagedWidget("noWrap",
2881 xmToggleButtonWidgetClass, wrapBox,
2882 XmNmarginHeight, 0,
2883 XmNlabelString, s1=XmStringCreateSimple("No wrapping"),
2884 XmNmnemonic, 'N', NULL);
2885 XmStringFree(s1);
2886 LMDialog.newlineWrapW = XtVaCreateManagedWidget("newlineWrap",
2887 xmToggleButtonWidgetClass, wrapBox,
2888 XmNmarginHeight, 0,
2889 XmNlabelString, s1=XmStringCreateSimple("Auto newline wrap"),
2890 XmNmnemonic, 'A', NULL);
2891 XmStringFree(s1);
2892 LMDialog.contWrapW = XtVaCreateManagedWidget("contWrap",
2893 xmToggleButtonWidgetClass, wrapBox,
2894 XmNmarginHeight, 0,
2895 XmNlabelString, s1=XmStringCreateSimple("Continuous wrap"),
2896 XmNmnemonic, 'C', NULL);
2897 XmStringFree(s1);
2899 XtVaCreateManagedWidget("stretchForm", xmFormWidgetClass, form,
2900 XmNtopAttachment, XmATTACH_WIDGET,
2901 XmNtopWidget, LMDialog.defTipsW,
2902 XmNleftAttachment, XmATTACH_POSITION,
2903 XmNleftPosition, LIST_RIGHT,
2904 XmNrightAttachment, XmATTACH_POSITION,
2905 XmNrightPosition, RIGHT_MARGIN_POS,
2906 XmNbottomAttachment, XmATTACH_WIDGET,
2907 XmNbottomWidget, overrideFrame,
2908 XmNbottomOffset, H_MARGIN*2, NULL);
2910 ac = 0;
2911 XtSetArg(args[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
2912 XtSetArg(args[ac], XmNtopOffset, H_MARGIN); ac++;
2913 XtSetArg(args[ac], XmNtopWidget, topLbl); ac++;
2914 XtSetArg(args[ac], XmNleftAttachment, XmATTACH_POSITION); ac++;
2915 XtSetArg(args[ac], XmNleftPosition, LEFT_MARGIN_POS); ac++;
2916 XtSetArg(args[ac], XmNrightAttachment, XmATTACH_POSITION); ac++;
2917 XtSetArg(args[ac], XmNrightPosition, LIST_RIGHT-1); ac++;
2918 XtSetArg(args[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
2919 XtSetArg(args[ac], XmNbottomWidget, overrideFrame); ac++;
2920 XtSetArg(args[ac], XmNbottomOffset, H_MARGIN*2); ac++;
2921 LMDialog.managedListW = CreateManagedList(form, "list", args, ac,
2922 (void **)LMDialog.languageModeList, &LMDialog.nLanguageModes,
2923 MAX_LANGUAGE_MODES, 15, lmGetDisplayedCB, NULL, lmSetDisplayedCB,
2924 NULL, lmFreeItemCB);
2925 AddDeleteConfirmCB(LMDialog.managedListW, lmDeleteConfirmCB, NULL);
2926 XtVaSetValues(topLbl, XmNuserData, LMDialog.managedListW, NULL);
2928 /* Set initial default button */
2929 XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
2930 XtVaSetValues(form, XmNcancelButton, dismissBtn, NULL);
2932 /* Handle mnemonic selection of buttons and focus to dialog */
2933 AddDialogMnemonicHandler(form, FALSE);
2935 /* Realize all of the widgets in the new dialog */
2936 RealizeWithoutForcingPosition(LMDialog.shell);
2939 static void lmDestroyCB(Widget w, XtPointer clientData, XtPointer callData)
2941 int i;
2943 for (i=0; i<LMDialog.nLanguageModes; i++)
2944 freeLanguageModeRec(LMDialog.languageModeList[i]);
2945 XtFree((char *)LMDialog.languageModeList);
2948 static void lmOkCB(Widget w, XtPointer clientData, XtPointer callData)
2950 if (!updateLMList())
2951 return;
2953 /* pop down and destroy the dialog */
2954 XtDestroyWidget(LMDialog.shell);
2955 LMDialog.shell = NULL;
2958 static void lmApplyCB(Widget w, XtPointer clientData, XtPointer callData)
2960 updateLMList();
2963 static void lmDismissCB(Widget w, XtPointer clientData, XtPointer callData)
2965 /* pop down and destroy the dialog */
2966 XtDestroyWidget(LMDialog.shell);
2967 LMDialog.shell = NULL;
2970 static int lmDeleteConfirmCB(int itemIndex, void *cbArg)
2972 int i;
2974 /* Allow duplicate names to be deleted regardless of dependencies */
2975 for (i=0; i<LMDialog.nLanguageModes; i++)
2976 if (i != itemIndex && !strcmp(LMDialog.languageModeList[i]->name,
2977 LMDialog.languageModeList[itemIndex]->name))
2978 return True;
2980 /* don't allow deletion if data will be lost */
2981 if (LMHasHighlightPatterns(LMDialog.languageModeList[itemIndex]->name))
2983 DialogF(DF_WARN, LMDialog.shell, 1, "Patterns exist",
2984 "This language mode has syntax highlighting\n"
2985 "patterns defined. Please delete the patterns\n"
2986 "first, in Preferences -> Default Settings ->\n"
2987 "Syntax Highlighting, before proceeding here.", "Dismiss");
2988 return False;
2991 /* don't allow deletion if data will be lost */
2992 if (LMHasSmartIndentMacros(LMDialog.languageModeList[itemIndex]->name))
2994 DialogF(DF_WARN, LMDialog.shell, 1, "Smart Indent Macros exist",
2995 "This language mode has smart indent macros\n"
2996 "defined. Please delete the macros first,\n"
2997 "in Preferences -> Default Settings ->\n"
2998 "Auto Indent -> Program Smart Indent,\n"
2999 "before proceeding here.", "Dismiss");
3000 return False;
3003 return True;
3007 ** Apply the changes that the user has made in the language modes dialog to the
3008 ** stored language mode information for this NEdit session (the data array
3009 ** LanguageModes)
3011 static int updateLMList(void)
3013 WindowInfo *window;
3014 char *oldModeName, *newDelimiters;
3015 int i, j;
3017 /* Get the current contents of the dialog fields */
3018 if (!UpdateManagedList(LMDialog.managedListW, True))
3019 return False;
3021 /* Fix up language mode indices in all open windows (which may change
3022 if the currently selected mode is deleted or has changed position),
3023 and update word delimiters */
3024 for (window=WindowList; window!=NULL; window=window->next) {
3025 if (window->languageMode != PLAIN_LANGUAGE_MODE) {
3026 oldModeName = LanguageModes[window->languageMode]->name;
3027 window->languageMode = PLAIN_LANGUAGE_MODE;
3028 for (i=0; i<LMDialog.nLanguageModes; i++) {
3029 if (!strcmp(oldModeName, LMDialog.languageModeList[i]->name)) {
3030 newDelimiters = LMDialog.languageModeList[i]->delimiters;
3031 if (newDelimiters == NULL)
3032 newDelimiters = GetPrefDelimiters();
3033 XtVaSetValues(window->textArea, textNwordDelimiters,
3034 newDelimiters, NULL);
3035 for (j=0; j<window->nPanes; j++)
3036 XtVaSetValues(window->textPanes[j],
3037 textNwordDelimiters, newDelimiters, NULL);
3038 window->languageMode = i;
3039 break;
3045 /* If there were any name changes, re-name dependent highlight patterns
3046 and smart-indent macros and fix up the weird rename-format names */
3047 for (i=0; i<LMDialog.nLanguageModes; i++) {
3048 if (strchr(LMDialog.languageModeList[i]->name, ':') != NULL) {
3049 char *newName = strrchr(LMDialog.languageModeList[i]->name, ':')+1;
3050 *strchr(LMDialog.languageModeList[i]->name, ':') = '\0';
3051 RenameHighlightPattern(LMDialog.languageModeList[i]->name, newName);
3052 RenameSmartIndentMacros(LMDialog.languageModeList[i]->name, newName);
3053 memmove(LMDialog.languageModeList[i]->name, newName,
3054 strlen(newName) + 1);
3055 ChangeManagedListData(LMDialog.managedListW);
3059 /* Unload any default calltips file that is no longer a default. */
3060 for (i=0; i<NLanguageModes; i++) {
3061 if (!LanguageModes[i]->defTipsFile)
3062 continue;
3063 for (j=0; j<LMDialog.nLanguageModes; j++) {
3064 if (!LMDialog.languageModeList[j]->defTipsFile)
3065 continue;
3066 if (!strcmp(LanguageModes[i]->defTipsFile,
3067 LMDialog.languageModeList[j]->defTipsFile))
3068 break;
3070 if ( j==LMDialog.nLanguageModes )
3071 DeleteTagsFile(LanguageModes[i]->defTipsFile, TIP);
3074 /* Replace the old language mode list with the new one from the dialog */
3075 for (i=0; i<NLanguageModes; i++)
3076 freeLanguageModeRec(LanguageModes[i]);
3077 for (i=0; i<LMDialog.nLanguageModes; i++)
3078 LanguageModes[i] = copyLanguageModeRec(LMDialog.languageModeList[i]);
3079 NLanguageModes = LMDialog.nLanguageModes;
3081 /* Update the menus in the window menu bars and load any needed
3082 calltips files */
3083 for (window=WindowList; window!=NULL; window=window->next) {
3084 updateLanguageModeSubmenu(window);
3085 if (window->languageMode != PLAIN_LANGUAGE_MODE &&
3086 LanguageModes[window->languageMode]->defTipsFile != NULL)
3087 AddTagsFile(LanguageModes[window->languageMode]->defTipsFile, TIP);
3090 /* If a syntax highlighting dialog is up, update its menu */
3091 UpdateLanguageModeMenu();
3092 /* The same for the smart indent macro dialog */
3093 UpdateLangModeMenuSmartIndent();
3094 /* Note that preferences have been changed */
3095 MarkPrefsChanged();
3097 return True;
3100 static void *lmGetDisplayedCB(void *oldItem, int explicitRequest, int *abort,
3101 void *cbArg)
3103 languageModeRec *lm, *oldLM = (languageModeRec *)oldItem;
3104 char *tempName;
3105 int i, nCopies, oldLen;
3107 /* If the dialog is currently displaying the "new" entry and the
3108 fields are empty, that's just fine */
3109 if (oldItem == NULL && lmDialogEmpty())
3110 return NULL;
3112 /* Read the data the user has entered in the dialog fields */
3113 lm = readLMDialogFields(True);
3115 /* If there was a name change of a non-duplicate language mode, modify the
3116 name to the weird format of: ":old name:new name". This signals that a
3117 name change is necessary in lm dependent data such as highlight
3118 patterns. Duplicate language modes may be re-named at will, since no
3119 data will be lost due to the name change. */
3120 if (lm != NULL && oldLM != NULL && strcmp(oldLM->name, lm->name)) {
3121 nCopies = 0;
3122 for (i=0; i<LMDialog.nLanguageModes; i++)
3123 if (!strcmp(oldLM->name, LMDialog.languageModeList[i]->name))
3124 nCopies++;
3125 if (nCopies <= 1) {
3126 oldLen = strchr(oldLM->name, ':') == NULL ? strlen(oldLM->name) :
3127 strchr(oldLM->name, ':') - oldLM->name;
3128 tempName = XtMalloc(oldLen + strlen(lm->name) + 2);
3129 strncpy(tempName, oldLM->name, oldLen);
3130 sprintf(&tempName[oldLen], ":%s", lm->name);
3131 XtFree(lm->name);
3132 lm->name = tempName;
3136 /* If there are no problems reading the data, just return it */
3137 if (lm != NULL)
3138 return (void *)lm;
3140 /* If there are problems, and the user didn't ask for the fields to be
3141 read, give more warning */
3142 if (!explicitRequest)
3144 if (DialogF(DF_WARN, LMDialog.shell, 2, "Discard Language Mode",
3145 "Discard incomplete entry\nfor current language mode?", "Keep",
3146 "Discard") == 2)
3148 return oldItem == NULL
3149 ? NULL
3150 : (void *)copyLanguageModeRec((languageModeRec *)oldItem);
3154 /* Do readLMDialogFields again without "silent" mode to display warning */
3155 lm = readLMDialogFields(False);
3156 *abort = True;
3157 return NULL;
3160 static void lmSetDisplayedCB(void *item, void *cbArg)
3162 languageModeRec *lm = (languageModeRec *)item;
3163 char *extStr;
3165 if (item == NULL) {
3166 XmTextSetString(LMDialog.nameW, "");
3167 XmTextSetString(LMDialog.extW, "");
3168 XmTextSetString(LMDialog.recogW, "");
3169 XmTextSetString(LMDialog.defTipsW, "");
3170 XmTextSetString(LMDialog.delimitW, "");
3171 XmTextSetString(LMDialog.tabW, "");
3172 XmTextSetString(LMDialog.emTabW, "");
3173 XmToggleButtonSetState(LMDialog.defaultIndentW, True, True);
3174 XmToggleButtonSetState(LMDialog.defaultWrapW, True, True);
3175 } else {
3176 XmTextSetString(LMDialog.nameW, strchr(lm->name, ':') == NULL ?
3177 lm->name : strchr(lm->name, ':')+1);
3178 extStr = createExtString(lm->extensions, lm->nExtensions);
3179 XmTextSetString(LMDialog.extW, extStr);
3180 XtFree(extStr);
3181 XmTextSetString(LMDialog.recogW, lm->recognitionExpr);
3182 XmTextSetString(LMDialog.defTipsW, lm->defTipsFile);
3183 XmTextSetString(LMDialog.delimitW, lm->delimiters);
3184 if (lm->tabDist == DEFAULT_TAB_DIST)
3185 XmTextSetString(LMDialog.tabW, "");
3186 else
3187 SetIntText(LMDialog.tabW, lm->tabDist);
3188 if (lm->emTabDist == DEFAULT_EM_TAB_DIST)
3189 XmTextSetString(LMDialog.emTabW, "");
3190 else
3191 SetIntText(LMDialog.emTabW, lm->emTabDist);
3192 XmToggleButtonSetState(LMDialog.defaultIndentW,
3193 lm->indentStyle == DEFAULT_INDENT, False);
3194 XmToggleButtonSetState(LMDialog.noIndentW,
3195 lm->indentStyle == NO_AUTO_INDENT, False);
3196 XmToggleButtonSetState(LMDialog.autoIndentW,
3197 lm->indentStyle == AUTO_INDENT, False);
3198 XmToggleButtonSetState(LMDialog.smartIndentW,
3199 lm->indentStyle == SMART_INDENT, False);
3200 XmToggleButtonSetState(LMDialog.defaultWrapW,
3201 lm->wrapStyle == DEFAULT_WRAP, False);
3202 XmToggleButtonSetState(LMDialog.noWrapW,
3203 lm->wrapStyle == NO_WRAP, False);
3204 XmToggleButtonSetState(LMDialog.newlineWrapW,
3205 lm->wrapStyle == NEWLINE_WRAP, False);
3206 XmToggleButtonSetState(LMDialog.contWrapW,
3207 lm->wrapStyle == CONTINUOUS_WRAP, False);
3211 static void lmFreeItemCB(void *item)
3213 freeLanguageModeRec((languageModeRec *)item);
3216 static void freeLanguageModeRec(languageModeRec *lm)
3218 int i;
3220 XtFree(lm->name);
3221 if (lm->recognitionExpr != NULL)
3222 XtFree(lm->recognitionExpr);
3223 if (lm->defTipsFile != NULL)
3224 XtFree(lm->defTipsFile);
3225 if (lm->delimiters != NULL)
3226 XtFree(lm->delimiters);
3227 for (i=0; i<lm->nExtensions; i++)
3228 XtFree(lm->extensions[i]);
3229 if (lm->nExtensions != 0)
3230 XtFree((char *)lm->extensions);
3231 XtFree((char *)lm);
3235 ** Copy a languageModeRec data structure and all of the allocated data it contains
3237 static languageModeRec *copyLanguageModeRec(languageModeRec *lm)
3239 languageModeRec *newLM;
3240 int i;
3242 newLM = (languageModeRec *)XtMalloc(sizeof(languageModeRec));
3243 newLM->name = XtMalloc(strlen(lm->name)+1);
3244 strcpy(newLM->name, lm->name);
3245 newLM->nExtensions = lm->nExtensions;
3246 newLM->extensions = (char **)XtMalloc(sizeof(char *) * lm->nExtensions);
3247 for (i=0; i<lm->nExtensions; i++) {
3248 newLM->extensions[i] = XtMalloc(strlen(lm->extensions[i]) + 1);
3249 strcpy(newLM->extensions[i], lm->extensions[i]);
3251 if (lm->recognitionExpr == NULL)
3252 newLM->recognitionExpr = NULL;
3253 else {
3254 newLM->recognitionExpr = XtMalloc(strlen(lm->recognitionExpr)+1);
3255 strcpy(newLM->recognitionExpr, lm->recognitionExpr);
3257 if (lm->defTipsFile == NULL)
3258 newLM->defTipsFile = NULL;
3259 else {
3260 newLM->defTipsFile = XtMalloc(strlen(lm->defTipsFile)+1);
3261 strcpy(newLM->defTipsFile, lm->defTipsFile);
3263 if (lm->delimiters == NULL)
3264 newLM->delimiters = NULL;
3265 else {
3266 newLM->delimiters = XtMalloc(strlen(lm->delimiters)+1);
3267 strcpy(newLM->delimiters, lm->delimiters);
3269 newLM->wrapStyle = lm->wrapStyle;
3270 newLM->indentStyle = lm->indentStyle;
3271 newLM->tabDist = lm->tabDist;
3272 newLM->emTabDist = lm->emTabDist;
3273 return newLM;
3277 ** Read the fields in the language modes dialog and create a languageModeRec data
3278 ** structure reflecting the current state of the selected language mode in the dialog.
3279 ** If any of the information is incorrect or missing, display a warning dialog and
3280 ** return NULL. Passing "silent" as True, suppresses the warning dialogs.
3282 static languageModeRec *readLMDialogFields(int silent)
3284 languageModeRec *lm;
3285 regexp *compiledRE;
3286 char *compileMsg, *extStr, *extPtr;
3288 /* Allocate a language mode structure to return, set unread fields to
3289 empty so everything can be freed on errors by freeLanguageModeRec */
3290 lm = (languageModeRec *)XtMalloc(sizeof(languageModeRec));
3291 lm->nExtensions = 0;
3292 lm->recognitionExpr = NULL;
3293 lm->defTipsFile = NULL;
3294 lm->delimiters = NULL;
3296 /* read the name field */
3297 lm->name = ReadSymbolicFieldTextWidget(LMDialog.nameW,
3298 "language mode name", silent);
3299 if (lm->name == NULL) {
3300 XtFree((char *)lm);
3301 return NULL;
3304 if (*lm->name == '\0')
3306 if (!silent)
3308 DialogF(DF_WARN, LMDialog.shell, 1, "Language Mode Name",
3309 "Please specify a name\nfor the language mode", "Dismiss");
3310 XmProcessTraversal(LMDialog.nameW, XmTRAVERSE_CURRENT);
3312 freeLanguageModeRec(lm);
3313 return NULL;
3316 /* read the extension list field */
3317 extStr = extPtr = XmTextGetString(LMDialog.extW);
3318 lm->extensions = readExtensionList(&extPtr, &lm->nExtensions);
3319 XtFree(extStr);
3321 /* read recognition expression */
3322 lm->recognitionExpr = XmTextGetString(LMDialog.recogW);
3323 if (*lm->recognitionExpr == '\0') {
3324 XtFree(lm->recognitionExpr);
3325 lm->recognitionExpr = NULL;
3326 } else
3328 compiledRE = CompileRE(lm->recognitionExpr, &compileMsg, REDFLT_STANDARD);
3330 if (compiledRE == NULL)
3332 if (!silent)
3334 DialogF(DF_WARN, LMDialog.shell, 1, "Regex",
3335 "Recognition expression:\n%s", "Dismiss", compileMsg);
3336 XmProcessTraversal(LMDialog.recogW, XmTRAVERSE_CURRENT);
3338 XtFree((char *)compiledRE);
3339 freeLanguageModeRec(lm);
3340 return NULL;
3343 XtFree((char *)compiledRE);
3346 /* Read the default calltips file for the language mode */
3347 lm->defTipsFile = XmTextGetString(LMDialog.defTipsW);
3348 if (*lm->defTipsFile == '\0') {
3349 /* Empty string */
3350 XtFree(lm->defTipsFile);
3351 lm->defTipsFile = NULL;
3352 } else {
3353 /* Ensure that AddTagsFile will work */
3354 if (AddTagsFile(lm->defTipsFile, TIP) == FALSE) {
3355 if (!silent)
3357 DialogF(DF_WARN, LMDialog.shell, 1, "Error reading Calltips",
3358 "Can't read default calltips file(s):\n \"%s\"\n",
3359 "Dismiss", lm->defTipsFile);
3360 XmProcessTraversal(LMDialog.recogW, XmTRAVERSE_CURRENT);
3362 freeLanguageModeRec(lm);
3363 return NULL;
3364 } else
3365 if (DeleteTagsFile(lm->defTipsFile, TIP) == FALSE)
3366 fprintf(stderr, "nedit: Internal error: Trouble deleting "
3367 "calltips file(s):\n \"%s\"\n", lm->defTipsFile);
3370 /* read tab spacing field */
3371 if (TextWidgetIsBlank(LMDialog.tabW))
3372 lm->tabDist = DEFAULT_TAB_DIST;
3373 else {
3374 if (GetIntTextWarn(LMDialog.tabW, &lm->tabDist, "tab spacing", False)
3375 != TEXT_READ_OK) {
3376 freeLanguageModeRec(lm);
3377 return NULL;
3380 if (lm->tabDist <= 0 || lm->tabDist > 100)
3382 if (!silent)
3384 DialogF(DF_WARN, LMDialog.shell, 1, "Invalid Tab Spacing",
3385 "Invalid tab spacing: %d", "Dismiss", lm->tabDist);
3386 XmProcessTraversal(LMDialog.tabW, XmTRAVERSE_CURRENT);
3388 freeLanguageModeRec(lm);
3389 return NULL;
3393 /* read emulated tab field */
3394 if (TextWidgetIsBlank(LMDialog.emTabW))
3396 lm->emTabDist = DEFAULT_EM_TAB_DIST;
3397 } else
3399 if (GetIntTextWarn(LMDialog.emTabW, &lm->emTabDist,
3400 "emulated tab spacing", False) != TEXT_READ_OK)
3402 freeLanguageModeRec(lm);
3403 return NULL;
3406 if (lm->emTabDist < 0 || lm->emTabDist > 100)
3408 if (!silent)
3410 DialogF(DF_WARN, LMDialog.shell, 1, "Invalid Tab Spacing",
3411 "Invalid emulated tab spacing: %d", "Dismiss",
3412 lm->emTabDist);
3413 XmProcessTraversal(LMDialog.emTabW, XmTRAVERSE_CURRENT);
3415 freeLanguageModeRec(lm);
3416 return NULL;
3420 /* read delimiters string */
3421 lm->delimiters = XmTextGetString(LMDialog.delimitW);
3422 if (*lm->delimiters == '\0') {
3423 XtFree(lm->delimiters);
3424 lm->delimiters = NULL;
3427 /* read indent style */
3428 if (XmToggleButtonGetState(LMDialog.noIndentW))
3429 lm->indentStyle = NO_AUTO_INDENT;
3430 else if (XmToggleButtonGetState(LMDialog.autoIndentW))
3431 lm->indentStyle = AUTO_INDENT;
3432 else if (XmToggleButtonGetState(LMDialog.smartIndentW))
3433 lm->indentStyle = SMART_INDENT;
3434 else
3435 lm->indentStyle = DEFAULT_INDENT;
3437 /* read wrap style */
3438 if (XmToggleButtonGetState(LMDialog.noWrapW))
3439 lm->wrapStyle = NO_WRAP;
3440 else if (XmToggleButtonGetState(LMDialog.newlineWrapW))
3441 lm->wrapStyle = NEWLINE_WRAP;
3442 else if (XmToggleButtonGetState(LMDialog.contWrapW))
3443 lm->wrapStyle = CONTINUOUS_WRAP;
3444 else
3445 lm->wrapStyle = DEFAULT_WRAP;
3447 return lm;
3451 ** Return True if the language mode dialog fields are blank (unchanged from the "New"
3452 ** language mode state).
3454 static int lmDialogEmpty(void)
3456 return TextWidgetIsBlank(LMDialog.nameW) &&
3457 TextWidgetIsBlank(LMDialog.extW) &&
3458 TextWidgetIsBlank(LMDialog.recogW) &&
3459 TextWidgetIsBlank(LMDialog.delimitW) &&
3460 TextWidgetIsBlank(LMDialog.tabW) &&
3461 TextWidgetIsBlank(LMDialog.emTabW) &&
3462 XmToggleButtonGetState(LMDialog.defaultIndentW) &&
3463 XmToggleButtonGetState(LMDialog.defaultWrapW);
3467 ** Present a dialog for changing fonts (primary, and for highlighting).
3469 void ChooseFonts(WindowInfo *window, int forWindow)
3471 #define MARGIN_SPACING 10
3472 #define BTN_TEXT_OFFSET 3
3473 Widget form, primaryLbl, primaryBtn, italicLbl, italicBtn;
3474 Widget boldLbl, boldBtn, boldItalicLbl, boldItalicBtn;
3475 Widget primaryFrame, primaryForm, highlightFrame, highlightForm;
3476 Widget okBtn, applyBtn, dismissBtn;
3477 fontDialog *fd;
3478 XmString s1;
3479 int ac;
3480 Arg args[20];
3482 /* if the dialog is already displayed, just pop it to the top and return */
3483 if (window->fontDialog != NULL) {
3484 RaiseShellWindow(((fontDialog *)window->fontDialog)->shell);
3485 return;
3488 /* Create a structure for keeping track of dialog state */
3489 fd = (fontDialog *)XtMalloc(sizeof(fontDialog));
3490 fd->window = window;
3491 fd->forWindow = forWindow;
3492 window->fontDialog = (void*)fd;
3494 /* Create a form widget in a dialog shell */
3495 ac = 0;
3496 XtSetArg(args[ac], XmNautoUnmanage, False); ac++;
3497 XtSetArg(args[ac], XmNresizePolicy, XmRESIZE_NONE); ac++;
3498 form = CreateFormDialog(window->shell, "choose Fonts", args, ac);
3499 XtVaSetValues(form, XmNshadowThickness, 0, NULL);
3500 fd->shell = XtParent(form);
3501 XtVaSetValues(fd->shell, XmNtitle, "Text Fonts", NULL);
3502 AddMotifCloseCallback(XtParent(form), fontDismissCB, fd);
3503 XtAddCallback(form, XmNdestroyCallback, fontDestroyCB, fd);
3505 primaryFrame = XtVaCreateManagedWidget("primaryFrame", xmFrameWidgetClass,
3506 form, XmNmarginHeight, 3,
3507 XmNtopAttachment, XmATTACH_POSITION,
3508 XmNtopPosition, 2,
3509 XmNleftAttachment, XmATTACH_POSITION,
3510 XmNleftPosition, 1,
3511 XmNrightAttachment, XmATTACH_POSITION,
3512 XmNrightPosition, 99, NULL);
3513 primaryForm = XtVaCreateManagedWidget("primaryForm", xmFormWidgetClass,
3514 primaryFrame, NULL);
3515 primaryLbl = XtVaCreateManagedWidget("primaryFont", xmLabelGadgetClass,
3516 primaryFrame,
3517 XmNlabelString, s1=XmStringCreateSimple("Primary Font"),
3518 XmNmnemonic, 'P',
3519 XmNchildType, XmFRAME_TITLE_CHILD,
3520 XmNchildHorizontalAlignment, XmALIGNMENT_CENTER, NULL);
3521 XmStringFree(s1);
3523 primaryBtn = XtVaCreateManagedWidget("primaryBtn",
3524 xmPushButtonWidgetClass, primaryForm,
3525 XmNlabelString, s1=XmStringCreateSimple("Browse..."),
3526 XmNmnemonic, 'r',
3527 XmNtopAttachment, XmATTACH_POSITION,
3528 XmNtopPosition, 2,
3529 XmNtopOffset, BTN_TEXT_OFFSET,
3530 XmNleftAttachment, XmATTACH_POSITION,
3531 XmNleftPosition, 1, NULL);
3532 XmStringFree(s1);
3533 XtAddCallback(primaryBtn, XmNactivateCallback, primaryBrowseCB, fd);
3535 fd->primaryW = XtVaCreateManagedWidget("primary", xmTextWidgetClass,
3536 primaryForm,
3537 XmNcolumns, 70,
3538 XmNmaxLength, MAX_FONT_LEN,
3539 XmNleftAttachment, XmATTACH_WIDGET,
3540 XmNleftWidget, primaryBtn,
3541 XmNtopAttachment, XmATTACH_POSITION,
3542 XmNtopPosition, 2,
3543 XmNrightAttachment, XmATTACH_POSITION,
3544 XmNrightPosition, 99, NULL);
3545 RemapDeleteKey(fd->primaryW);
3546 XtAddCallback(fd->primaryW, XmNvalueChangedCallback,
3547 primaryModifiedCB, fd);
3548 XtVaSetValues(primaryLbl, XmNuserData, fd->primaryW, NULL);
3550 highlightFrame = XtVaCreateManagedWidget("highlightFrame",
3551 xmFrameWidgetClass, form,
3552 XmNmarginHeight, 3,
3553 XmNnavigationType, XmTAB_GROUP,
3554 XmNtopAttachment, XmATTACH_WIDGET,
3555 XmNtopWidget, primaryFrame,
3556 XmNtopOffset, 20,
3557 XmNleftAttachment, XmATTACH_POSITION,
3558 XmNleftPosition, 1,
3559 XmNrightAttachment, XmATTACH_POSITION,
3560 XmNrightPosition, 99, NULL);
3561 highlightForm = XtVaCreateManagedWidget("highlightForm", xmFormWidgetClass,
3562 highlightFrame, NULL);
3563 XtVaCreateManagedWidget("highlightFonts", xmLabelGadgetClass,
3564 highlightFrame,
3565 XmNlabelString,
3566 s1=XmStringCreateSimple("Fonts for Syntax Highlighting"),
3567 XmNchildType, XmFRAME_TITLE_CHILD,
3568 XmNchildHorizontalAlignment, XmALIGNMENT_CENTER, NULL);
3569 XmStringFree(s1);
3571 fd->fillW = XtVaCreateManagedWidget("fillBtn",
3572 xmPushButtonWidgetClass, highlightForm,
3573 XmNlabelString,
3574 s1=XmStringCreateSimple("Fill Highlight Fonts from Primary"),
3575 XmNmnemonic, 'F',
3576 XmNtopAttachment, XmATTACH_POSITION,
3577 XmNtopPosition, 2,
3578 XmNtopOffset, BTN_TEXT_OFFSET,
3579 XmNleftAttachment, XmATTACH_POSITION,
3580 XmNleftPosition, 1, NULL);
3581 XmStringFree(s1);
3582 XtAddCallback(fd->fillW, XmNactivateCallback, fillFromPrimaryCB, fd);
3584 italicLbl = XtVaCreateManagedWidget("italicLbl", xmLabelGadgetClass,
3585 highlightForm,
3586 XmNlabelString, s1=XmStringCreateSimple("Italic Font"),
3587 XmNmnemonic, 'I',
3588 XmNalignment, XmALIGNMENT_BEGINNING,
3589 XmNtopAttachment, XmATTACH_WIDGET,
3590 XmNtopWidget, fd->fillW,
3591 XmNtopOffset, MARGIN_SPACING,
3592 XmNleftAttachment, XmATTACH_POSITION,
3593 XmNleftPosition, 1, NULL);
3594 XmStringFree(s1);
3596 fd->italicErrW = XtVaCreateManagedWidget("italicErrLbl",
3597 xmLabelGadgetClass, highlightForm,
3598 XmNlabelString, s1=XmStringCreateSimple(
3599 "(vvv spacing is inconsistent with primary font vvv)"),
3600 XmNalignment, XmALIGNMENT_END,
3601 XmNtopAttachment, XmATTACH_WIDGET,
3602 XmNtopWidget, fd->fillW,
3603 XmNtopOffset, MARGIN_SPACING,
3604 XmNleftAttachment, XmATTACH_WIDGET,
3605 XmNleftWidget, italicLbl,
3606 XmNrightAttachment, XmATTACH_POSITION,
3607 XmNrightPosition, 99, NULL);
3608 XmStringFree(s1);
3610 italicBtn = XtVaCreateManagedWidget("italicBtn",
3611 xmPushButtonWidgetClass, highlightForm,
3612 XmNlabelString, s1=XmStringCreateSimple("Browse..."),
3613 XmNmnemonic, 'o',
3614 XmNtopAttachment, XmATTACH_WIDGET,
3615 XmNtopWidget, italicLbl,
3616 XmNtopOffset, BTN_TEXT_OFFSET,
3617 XmNleftAttachment, XmATTACH_POSITION,
3618 XmNleftPosition, 1, NULL);
3619 XmStringFree(s1);
3620 XtAddCallback(italicBtn, XmNactivateCallback, italicBrowseCB, fd);
3622 fd->italicW = XtVaCreateManagedWidget("italic", xmTextWidgetClass,
3623 highlightForm,
3624 XmNmaxLength, MAX_FONT_LEN,
3625 XmNleftAttachment, XmATTACH_WIDGET,
3626 XmNleftWidget, italicBtn,
3627 XmNtopAttachment, XmATTACH_WIDGET,
3628 XmNtopWidget, italicLbl,
3629 XmNrightAttachment, XmATTACH_POSITION,
3630 XmNrightPosition, 99, NULL);
3631 RemapDeleteKey(fd->italicW);
3632 XtAddCallback(fd->italicW, XmNvalueChangedCallback,
3633 italicModifiedCB, fd);
3634 XtVaSetValues(italicLbl, XmNuserData, fd->italicW, NULL);
3636 boldLbl = XtVaCreateManagedWidget("boldLbl", xmLabelGadgetClass,
3637 highlightForm,
3638 XmNlabelString, s1=XmStringCreateSimple("Bold Font"),
3639 XmNmnemonic, 'B',
3640 XmNalignment, XmALIGNMENT_BEGINNING,
3641 XmNtopAttachment, XmATTACH_WIDGET,
3642 XmNtopWidget, italicBtn,
3643 XmNtopOffset, MARGIN_SPACING,
3644 XmNleftAttachment, XmATTACH_POSITION,
3645 XmNleftPosition, 1, NULL);
3646 XmStringFree(s1);
3648 fd->boldErrW = XtVaCreateManagedWidget("boldErrLbl",
3649 xmLabelGadgetClass, highlightForm,
3650 XmNlabelString, s1=XmStringCreateSimple(""),
3651 XmNalignment, XmALIGNMENT_END,
3652 XmNtopAttachment, XmATTACH_WIDGET,
3653 XmNtopWidget, italicBtn,
3654 XmNtopOffset, MARGIN_SPACING,
3655 XmNleftAttachment, XmATTACH_WIDGET,
3656 XmNleftWidget, boldLbl,
3657 XmNrightAttachment, XmATTACH_POSITION,
3658 XmNrightPosition, 99, NULL);
3659 XmStringFree(s1);
3661 boldBtn = XtVaCreateManagedWidget("boldBtn",
3662 xmPushButtonWidgetClass, highlightForm,
3663 XmNlabelString, s1=XmStringCreateSimple("Browse..."),
3664 XmNmnemonic, 'w',
3665 XmNtopAttachment, XmATTACH_WIDGET,
3666 XmNtopWidget, boldLbl,
3667 XmNtopOffset, BTN_TEXT_OFFSET,
3668 XmNleftAttachment, XmATTACH_POSITION,
3669 XmNleftPosition, 1, NULL);
3670 XmStringFree(s1);
3671 XtAddCallback(boldBtn, XmNactivateCallback, boldBrowseCB, fd);
3673 fd->boldW = XtVaCreateManagedWidget("bold", xmTextWidgetClass,
3674 highlightForm,
3675 XmNmaxLength, MAX_FONT_LEN,
3676 XmNleftAttachment, XmATTACH_WIDGET,
3677 XmNleftWidget, boldBtn,
3678 XmNtopAttachment, XmATTACH_WIDGET,
3679 XmNtopWidget, boldLbl,
3680 XmNrightAttachment, XmATTACH_POSITION,
3681 XmNrightPosition, 99, NULL);
3682 RemapDeleteKey(fd->boldW);
3683 XtAddCallback(fd->boldW, XmNvalueChangedCallback,
3684 boldModifiedCB, fd);
3685 XtVaSetValues(boldLbl, XmNuserData, fd->boldW, NULL);
3687 boldItalicLbl = XtVaCreateManagedWidget("boldItalicLbl", xmLabelGadgetClass,
3688 highlightForm,
3689 XmNlabelString, s1=XmStringCreateSimple("Bold Italic Font"),
3690 XmNmnemonic, 'l',
3691 XmNalignment, XmALIGNMENT_BEGINNING,
3692 XmNtopAttachment, XmATTACH_WIDGET,
3693 XmNtopWidget, boldBtn,
3694 XmNtopOffset, MARGIN_SPACING,
3695 XmNleftAttachment, XmATTACH_POSITION,
3696 XmNleftPosition, 1, NULL);
3697 XmStringFree(s1);
3699 fd->boldItalicErrW = XtVaCreateManagedWidget("boldItalicErrLbl",
3700 xmLabelGadgetClass, highlightForm,
3701 XmNlabelString, s1=XmStringCreateSimple(""),
3702 XmNalignment, XmALIGNMENT_END,
3703 XmNtopAttachment, XmATTACH_WIDGET,
3704 XmNtopWidget, boldBtn,
3705 XmNtopOffset, MARGIN_SPACING,
3706 XmNleftAttachment, XmATTACH_WIDGET,
3707 XmNleftWidget, boldItalicLbl,
3708 XmNrightAttachment, XmATTACH_POSITION,
3709 XmNrightPosition, 99, NULL);
3710 XmStringFree(s1);
3712 boldItalicBtn = XtVaCreateManagedWidget("boldItalicBtn",
3713 xmPushButtonWidgetClass, highlightForm,
3714 XmNlabelString, s1=XmStringCreateSimple("Browse..."),
3715 XmNmnemonic, 's',
3716 XmNtopAttachment, XmATTACH_WIDGET,
3717 XmNtopWidget, boldItalicLbl,
3718 XmNtopOffset, BTN_TEXT_OFFSET,
3719 XmNleftAttachment, XmATTACH_POSITION,
3720 XmNleftPosition, 1, NULL);
3721 XmStringFree(s1);
3722 XtAddCallback(boldItalicBtn, XmNactivateCallback, boldItalicBrowseCB, fd);
3724 fd->boldItalicW = XtVaCreateManagedWidget("boldItalic",
3725 xmTextWidgetClass, highlightForm,
3726 XmNmaxLength, MAX_FONT_LEN,
3727 XmNleftAttachment, XmATTACH_WIDGET,
3728 XmNleftWidget, boldItalicBtn,
3729 XmNtopAttachment, XmATTACH_WIDGET,
3730 XmNtopWidget, boldItalicLbl,
3731 XmNrightAttachment, XmATTACH_POSITION,
3732 XmNrightPosition, 99, NULL);
3733 RemapDeleteKey(fd->boldItalicW);
3734 XtAddCallback(fd->boldItalicW, XmNvalueChangedCallback,
3735 boldItalicModifiedCB, fd);
3736 XtVaSetValues(boldItalicLbl, XmNuserData, fd->boldItalicW, NULL);
3738 okBtn = XtVaCreateManagedWidget("ok", xmPushButtonWidgetClass, form,
3739 XmNlabelString, s1=XmStringCreateSimple("OK"),
3740 XmNtopAttachment, XmATTACH_WIDGET,
3741 XmNtopWidget, highlightFrame,
3742 XmNtopOffset, MARGIN_SPACING,
3743 XmNleftAttachment, XmATTACH_POSITION,
3744 XmNleftPosition, forWindow ? 13 : 26,
3745 XmNrightAttachment, XmATTACH_POSITION,
3746 XmNrightPosition, forWindow ? 27 : 40, NULL);
3747 XtAddCallback(okBtn, XmNactivateCallback, fontOkCB, fd);
3748 XmStringFree(s1);
3750 if (forWindow) {
3751 applyBtn = XtVaCreateManagedWidget("apply",xmPushButtonWidgetClass,form,
3752 XmNlabelString, s1=XmStringCreateSimple("Apply"),
3753 XmNmnemonic, 'A',
3754 XmNtopAttachment, XmATTACH_WIDGET,
3755 XmNtopWidget, highlightFrame,
3756 XmNtopOffset, MARGIN_SPACING,
3757 XmNleftAttachment, XmATTACH_POSITION,
3758 XmNleftPosition, 43,
3759 XmNrightAttachment, XmATTACH_POSITION,
3760 XmNrightPosition, 57, NULL);
3761 XtAddCallback(applyBtn, XmNactivateCallback, fontApplyCB, fd);
3762 XmStringFree(s1);
3765 dismissBtn = XtVaCreateManagedWidget("dismiss",xmPushButtonWidgetClass,form,
3766 XmNlabelString, s1=XmStringCreateSimple("Dismiss"),
3767 XmNtopAttachment, XmATTACH_WIDGET,
3768 XmNtopWidget, highlightFrame,
3769 XmNtopOffset, MARGIN_SPACING,
3770 XmNleftAttachment, XmATTACH_POSITION,
3771 XmNleftPosition, forWindow ? 73 : 59,
3772 XmNrightAttachment, XmATTACH_POSITION,
3773 XmNrightPosition, forWindow ? 87 : 73, NULL);
3774 XtAddCallback(dismissBtn, XmNactivateCallback, fontDismissCB, fd);
3775 XmStringFree(s1);
3777 /* Set initial default button */
3778 XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
3779 XtVaSetValues(form, XmNcancelButton, dismissBtn, NULL);
3781 /* Set initial values */
3782 if (forWindow) {
3783 XmTextSetString(fd->primaryW, window->fontName);
3784 XmTextSetString(fd->boldW, window->boldFontName);
3785 XmTextSetString(fd->italicW, window->italicFontName);
3786 XmTextSetString(fd->boldItalicW, window->boldItalicFontName);
3787 } else {
3788 XmTextSetString(fd->primaryW, GetPrefFontName());
3789 XmTextSetString(fd->boldW, GetPrefBoldFontName());
3790 XmTextSetString(fd->italicW, GetPrefItalicFontName());
3791 XmTextSetString(fd->boldItalicW, GetPrefBoldItalicFontName());
3794 /* Handle mnemonic selection of buttons and focus to dialog */
3795 AddDialogMnemonicHandler(form, FALSE);
3797 /* put up dialog */
3798 ManageDialogCenteredOnPointer(form);
3801 static void fillFromPrimaryCB(Widget w, XtPointer clientData,
3802 XtPointer callData)
3804 fontDialog *fd = (fontDialog *)clientData;
3805 char *primaryName, *errMsg;
3806 char modifiedFontName[MAX_FONT_LEN];
3807 char *searchString = "(-[^-]*-[^-]*)-([^-]*)-([^-]*)-(.*)";
3808 char *italicReplaceString = "\\1-\\2-o-\\4";
3809 char *boldReplaceString = "\\1-bold-\\3-\\4";
3810 char *boldItalicReplaceString = "\\1-bold-o-\\4";
3811 regexp *compiledRE;
3813 /* Match the primary font agains RE pattern for font names. If it
3814 doesn't match, we can't generate highlight font names, so return */
3815 compiledRE = CompileRE(searchString, &errMsg, REDFLT_STANDARD);
3816 primaryName = XmTextGetString(fd->primaryW);
3817 if (!ExecRE(compiledRE, NULL, primaryName, NULL, False, '\0', '\0', NULL, NULL)) {
3818 XBell(XtDisplay(fd->shell), 0);
3819 free(compiledRE);
3820 XtFree(primaryName);
3821 return;
3824 /* Make up names for new fonts based on RE replace patterns */
3825 SubstituteRE(compiledRE, italicReplaceString, modifiedFontName,
3826 MAX_FONT_LEN);
3827 XmTextSetString(fd->italicW, modifiedFontName);
3828 SubstituteRE(compiledRE, boldReplaceString, modifiedFontName,
3829 MAX_FONT_LEN);
3830 XmTextSetString(fd->boldW, modifiedFontName);
3831 SubstituteRE(compiledRE, boldItalicReplaceString, modifiedFontName,
3832 MAX_FONT_LEN);
3833 XmTextSetString(fd->boldItalicW, modifiedFontName);
3834 XtFree(primaryName);
3835 free(compiledRE);
3838 static void primaryModifiedCB(Widget w, XtPointer clientData,
3839 XtPointer callData)
3841 fontDialog *fd = (fontDialog *)clientData;
3843 showFontStatus(fd, fd->italicW, fd->italicErrW);
3844 showFontStatus(fd, fd->boldW, fd->boldErrW);
3845 showFontStatus(fd, fd->boldItalicW, fd->boldItalicErrW);
3847 static void italicModifiedCB(Widget w, XtPointer clientData, XtPointer callData)
3849 fontDialog *fd = (fontDialog *)clientData;
3851 showFontStatus(fd, fd->italicW, fd->italicErrW);
3853 static void boldModifiedCB(Widget w, XtPointer clientData, XtPointer callData)
3855 fontDialog *fd = (fontDialog *)clientData;
3857 showFontStatus(fd, fd->boldW, fd->boldErrW);
3859 static void boldItalicModifiedCB(Widget w, XtPointer clientData,
3860 XtPointer callData)
3862 fontDialog *fd = (fontDialog *)clientData;
3864 showFontStatus(fd, fd->boldItalicW, fd->boldItalicErrW);
3867 static void primaryBrowseCB(Widget w, XtPointer clientData, XtPointer callData)
3869 fontDialog *fd = (fontDialog *)clientData;
3871 browseFont(fd->shell, fd->primaryW, fd);
3873 static void italicBrowseCB(Widget w, XtPointer clientData, XtPointer callData)
3875 fontDialog *fd = (fontDialog *)clientData;
3877 browseFont(fd->shell, fd->italicW, fd);
3879 static void boldBrowseCB(Widget w, XtPointer clientData, XtPointer callData)
3881 fontDialog *fd = (fontDialog *)clientData;
3883 browseFont(fd->shell, fd->boldW, fd);
3885 static void boldItalicBrowseCB(Widget w, XtPointer clientData,
3886 XtPointer callData)
3888 fontDialog *fd = (fontDialog *)clientData;
3890 browseFont(fd->shell, fd->boldItalicW, fd);
3893 static void fontDestroyCB(Widget w, XtPointer clientData, XtPointer callData)
3895 fontDialog *fd = (fontDialog *)clientData;
3897 fd->window->fontDialog = NULL;
3898 XtFree((char *)fd);
3901 static void fontOkCB(Widget w, XtPointer clientData, XtPointer callData)
3903 fontDialog *fd = (fontDialog *)clientData;
3905 updateFonts(fd);
3907 /* pop down and destroy the dialog */
3908 XtDestroyWidget(fd->shell);
3911 static void fontApplyCB(Widget w, XtPointer clientData, XtPointer callData)
3913 fontDialog *fd = (fontDialog *)clientData;
3915 updateFonts(fd);
3918 static void fontDismissCB(Widget w, XtPointer clientData, XtPointer callData)
3920 fontDialog *fd = (fontDialog *)clientData;
3922 /* pop down and destroy the dialog */
3923 XtDestroyWidget(fd->shell);
3927 ** Check over a font name in a text field to make sure it agrees with the
3928 ** primary font in height and spacing.
3930 static int checkFontStatus(fontDialog *fd, Widget fontTextFieldW)
3932 char *primaryName, *testName;
3933 XFontStruct *primaryFont, *testFont;
3934 Display *display = XtDisplay(fontTextFieldW);
3935 int primaryWidth, primaryHeight, testWidth, testHeight;
3937 /* Get width and height of the font to check. Note the test for empty
3938 name: X11R6 clients freak out X11R5 servers if they ask them to load
3939 an empty font name, and kill the whole application! */
3940 testName = XmTextGetString(fontTextFieldW);
3941 if (testName[0] == '\0') {
3942 XtFree(testName);
3943 return BAD_FONT;
3945 testFont = XLoadQueryFont(display, testName);
3946 if (testFont == NULL) {
3947 XtFree(testName);
3948 return BAD_FONT;
3950 XtFree(testName);
3951 testWidth = testFont->min_bounds.width;
3952 testHeight = testFont->ascent + testFont->descent;
3953 XFreeFont(display, testFont);
3955 /* Get width and height of the primary font */
3956 primaryName = XmTextGetString(fd->primaryW);
3957 if (primaryName[0] == '\0') {
3958 XtFree(primaryName);
3959 return BAD_FONT;
3961 primaryFont = XLoadQueryFont(display, primaryName);
3962 if (primaryFont == NULL) {
3963 XtFree(primaryName);
3964 return BAD_PRIMARY;
3966 XtFree(primaryName);
3967 primaryWidth = primaryFont->min_bounds.width;
3968 primaryHeight = primaryFont->ascent + primaryFont->descent;
3969 XFreeFont(display, primaryFont);
3971 /* Compare font information */
3972 if (testWidth != primaryWidth)
3973 return BAD_SPACING;
3974 if (testHeight != primaryHeight)
3975 return BAD_SIZE;
3976 return GOOD_FONT;
3980 ** Update the error label for a font text field to reflect its validity and degree
3981 ** of agreement with the currently selected primary font
3983 static int showFontStatus(fontDialog *fd, Widget fontTextFieldW,
3984 Widget errorLabelW)
3986 int status;
3987 XmString s;
3988 char *msg;
3990 status = checkFontStatus(fd, fontTextFieldW);
3991 if (status == BAD_PRIMARY)
3992 msg = "(font below may not match primary font)";
3993 else if (status == BAD_FONT)
3994 msg = "(xxx font below is invalid xxx)";
3995 else if (status == BAD_SIZE)
3996 msg = "(height of font below does not match primary)";
3997 else if (status == BAD_SPACING)
3998 msg = "(spacing of font below does not match primary)";
3999 else
4000 msg = "";
4002 XtVaSetValues(errorLabelW, XmNlabelString, s=XmStringCreateSimple(msg),
4003 NULL);
4004 XmStringFree(s);
4005 return status;
4009 ** Put up a font selector panel to set the font name in the text widget "fontTextW"
4011 static void browseFont(Widget parent, Widget fontTextW, fontDialog *fd)
4013 char *origFontName, *newFontName;
4014 Pixel fgPixel, bgPixel;
4015 int dummy;
4017 origFontName = XmTextGetString(fontTextW);
4019 /* Get the values from the defaults */
4020 fgPixel = AllocColor(parent, GetPrefColorName(TEXT_FG_COLOR),
4021 &dummy, &dummy, &dummy);
4022 bgPixel = AllocColor(parent, GetPrefColorName(TEXT_BG_COLOR),
4023 &dummy, &dummy, &dummy);
4025 newFontName = FontSel(parent, PREF_FIXED, origFontName, fgPixel, bgPixel);
4026 XtFree(origFontName);
4027 if (newFontName == NULL)
4028 return;
4029 XmTextSetString(fontTextW, newFontName);
4030 XtFree(newFontName);
4034 ** Accept the changes in the dialog and set the fonts regardless of errors
4036 static void updateFonts(fontDialog *fd)
4038 char *fontName, *italicName, *boldName, *boldItalicName;
4040 fontName = XmTextGetString(fd->primaryW);
4041 italicName = XmTextGetString(fd->italicW);
4042 boldName = XmTextGetString(fd->boldW);
4043 boldItalicName = XmTextGetString(fd->boldItalicW);
4045 if (fd->forWindow) {
4046 char *params[4];
4047 params[0] = fontName;
4048 params[1] = italicName;
4049 params[2] = boldName;
4050 params[3] = boldItalicName;
4051 XtCallActionProc(fd->window->textArea, "set_fonts", NULL, params, 4);
4053 SetFonts(fd->window, fontName, italicName, boldName, boldItalicName);
4056 else {
4057 SetPrefFont(fontName);
4058 SetPrefItalicFont(italicName);
4059 SetPrefBoldFont(boldName);
4060 SetPrefBoldItalicFont(boldItalicName);
4062 XtFree(fontName);
4063 XtFree(italicName);
4064 XtFree(boldName);
4065 XtFree(boldItalicName);
4069 ** Change the language mode to the one indexed by "mode", reseting word
4070 ** delimiters, syntax highlighting and other mode specific parameters
4072 static void reapplyLanguageMode(WindowInfo *window, int mode, int forceDefaults)
4074 char *delimiters;
4075 int i, wrapMode, indentStyle, tabDist, emTabDist, highlight, oldEmTabDist;
4076 int wrapModeIsDef, tabDistIsDef, emTabDistIsDef, indentStyleIsDef;
4077 int highlightIsDef, haveHighlightPatterns, haveSmartIndentMacros;
4078 int oldMode = window->languageMode;
4079 WindowInfo *wi;
4081 /* If the mode is the same, and changes aren't being forced (as might
4082 happen with Save As...), don't mess with already correct settings */
4083 if (window->languageMode == mode && !forceDefaults)
4084 return;
4086 /* Change the mode name stored in the window */
4087 window->languageMode = mode;
4089 /* Unload oldMode's default calltips file if there are no more windows
4090 in that mode and the mode has a default file */
4091 if (oldMode != PLAIN_LANGUAGE_MODE && LanguageModes[oldMode]->defTipsFile) {
4092 for (wi = WindowList; wi; wi = wi->next)
4093 if (wi->languageMode == oldMode) break;
4094 if (!wi) DeleteTagsFile( LanguageModes[oldMode]->defTipsFile, TIP );
4097 /* Make sure we didn't accidentally delete a default calltips file that
4098 also belongs another language mode (also load the tips file for the
4099 new lang. mode) */
4100 for (wi = WindowList; wi; wi = wi->next) {
4101 i = wi->languageMode;
4102 if (i != PLAIN_LANGUAGE_MODE && LanguageModes[i]->defTipsFile)
4103 if (AddTagsFile( LanguageModes[i]->defTipsFile, TIP ) == FALSE)
4104 fprintf( stderr, "Error loading default calltips file:\n"
4105 " \"%s\"\n", LanguageModes[i]->defTipsFile );
4108 /* Set delimiters for all text widgets */
4109 if (mode == PLAIN_LANGUAGE_MODE || LanguageModes[mode]->delimiters == NULL)
4110 delimiters = GetPrefDelimiters();
4111 else
4112 delimiters = LanguageModes[mode]->delimiters;
4113 XtVaSetValues(window->textArea, textNwordDelimiters, delimiters, NULL);
4114 for (i=0; i<window->nPanes; i++)
4115 XtVaSetValues(window->textPanes[i], textNautoIndent, delimiters, NULL);
4117 /* Decide on desired values for language-specific parameters. If a
4118 parameter was set to its default value, set it to the new default,
4119 otherwise, leave it alone */
4120 wrapModeIsDef = window->wrapMode == GetPrefWrap(oldMode);
4121 tabDistIsDef = BufGetTabDistance(window->buffer) == GetPrefTabDist(oldMode);
4122 XtVaGetValues(window->textArea, textNemulateTabs, &oldEmTabDist, NULL);
4123 emTabDistIsDef = oldEmTabDist == GetPrefEmTabDist(oldMode);
4124 indentStyleIsDef = window->indentStyle == GetPrefAutoIndent(oldMode) ||
4125 (GetPrefAutoIndent(oldMode) == SMART_INDENT &&
4126 window->indentStyle == AUTO_INDENT &&
4127 !SmartIndentMacrosAvailable(LanguageModeName(oldMode)));
4128 highlightIsDef = window->highlightSyntax == GetPrefHighlightSyntax()
4129 || (GetPrefHighlightSyntax() &&
4130 FindPatternSet(LanguageModeName(oldMode)) == NULL);
4131 wrapMode = wrapModeIsDef || forceDefaults ?
4132 GetPrefWrap(mode) : window->wrapMode;
4133 tabDist = tabDistIsDef || forceDefaults ?
4134 GetPrefTabDist(mode) : BufGetTabDistance(window->buffer);
4135 emTabDist = emTabDistIsDef || forceDefaults ?
4136 GetPrefEmTabDist(mode) : oldEmTabDist;
4137 indentStyle = indentStyleIsDef || forceDefaults ?
4138 GetPrefAutoIndent(mode) : window->indentStyle;
4139 highlight = highlightIsDef || forceDefaults ?
4140 GetPrefHighlightSyntax() : window->highlightSyntax;
4142 /* Dim/undim smart-indent and highlighting menu items depending on
4143 whether patterns/macros are available */
4144 haveHighlightPatterns = FindPatternSet(LanguageModeName(mode)) != NULL;
4145 haveSmartIndentMacros = SmartIndentMacrosAvailable(LanguageModeName(mode));
4146 XtSetSensitive(window->highlightItem, haveHighlightPatterns);
4147 XtSetSensitive(window->smartIndentItem, haveSmartIndentMacros);
4149 /* Turn off requested options which are not available */
4150 highlight = haveHighlightPatterns && highlight;
4151 if (indentStyle == SMART_INDENT && !haveSmartIndentMacros)
4152 indentStyle = AUTO_INDENT;
4154 /* Change highlighting */
4155 window->highlightSyntax = highlight;
4156 XmToggleButtonSetState(window->highlightItem, highlight, False);
4157 StopHighlighting(window);
4158 if (highlight)
4159 StartHighlighting(window, False);
4161 /* Force a change of smart indent macros (SetAutoIndent will re-start) */
4162 if (window->indentStyle == SMART_INDENT) {
4163 EndSmartIndent(window);
4164 window->indentStyle = AUTO_INDENT;
4167 /* set requested wrap, indent, and tabs */
4168 SetAutoWrap(window, wrapMode);
4169 SetAutoIndent(window, indentStyle);
4170 SetTabDist(window, tabDist);
4171 SetEmTabDist(window, emTabDist);
4173 /* Add/remove language specific menu items */
4174 #ifndef VMS
4175 UpdateShellMenu(window);
4176 #endif
4177 UpdateMacroMenu(window);
4178 UpdateBGMenu(window);
4182 ** Find and return the name of the appropriate languange mode for
4183 ** the file in "window". Returns a pointer to a string, which will
4184 ** remain valid until a change is made to the language modes list.
4186 static int matchLanguageMode(WindowInfo *window)
4188 char *ext, *first200;
4189 int i, j, fileNameLen, extLen, beginPos, endPos, start;
4190 const char *versionExtendedPath;
4192 /*... look for an explicit mode statement first */
4194 /* Do a regular expression search on for recognition pattern */
4195 first200 = BufGetRange(window->buffer, 0, 200);
4196 for (i=0; i<NLanguageModes; i++) {
4197 if (LanguageModes[i]->recognitionExpr != NULL) {
4198 if (SearchString(first200, LanguageModes[i]->recognitionExpr,
4199 SEARCH_FORWARD, SEARCH_REGEX, False, 0, &beginPos,
4200 &endPos, NULL, NULL, NULL))
4202 XtFree(first200);
4203 return i;
4207 XtFree(first200);
4209 /* Look at file extension ("@@/" starts a ClearCase version extended path,
4210 which gets appended after the file extension, and therefore must be
4211 stripped off to recognize the extension to make ClearCase users happy) */
4212 fileNameLen = strlen(window->filename);
4213 #ifdef VMS
4214 if (strchr(window->filename, ';') != NULL)
4215 fileNameLen = strchr(window->filename, ';') - window->filename;
4216 #else
4217 if ((versionExtendedPath = GetClearCaseVersionExtendedPath(window->filename)) != NULL)
4218 fileNameLen = versionExtendedPath - window->filename;
4219 #endif
4220 for (i=0; i<NLanguageModes; i++) {
4221 for (j=0; j<LanguageModes[i]->nExtensions; j++) {
4222 ext = LanguageModes[i]->extensions[j];
4223 extLen = strlen(ext);
4224 start = fileNameLen - extLen;
4225 #if defined(__VMS) && (__VMS_VER >= 70200000)
4226 /* VMS v7.2 has case-preserving filenames */
4227 if (start >= 0 && !strncasecmp(&window->filename[start], ext, extLen))
4228 return i;
4229 #else
4230 if (start >= 0 && !strncmp(&window->filename[start], ext, extLen))
4231 return i;
4232 #endif
4236 /* no appropriate mode was found */
4237 return PLAIN_LANGUAGE_MODE;
4240 static int loadLanguageModesString(char *inString, int fileVer)
4242 char *errMsg, *styleName, *inPtr = inString;
4243 languageModeRec *lm;
4244 int i;
4246 for (;;) {
4248 /* skip over blank space */
4249 inPtr += strspn(inPtr, " \t\n");
4251 /* Allocate a language mode structure to return, set unread fields to
4252 empty so everything can be freed on errors by freeLanguageModeRec */
4253 lm = (languageModeRec *)XtMalloc(sizeof(languageModeRec));
4254 lm->nExtensions = 0;
4255 lm->recognitionExpr = NULL;
4256 lm->defTipsFile = NULL;
4257 lm->delimiters = NULL;
4259 /* read language mode name */
4260 lm->name = ReadSymbolicField(&inPtr);
4261 if (lm->name == NULL) {
4262 XtFree((char *)lm);
4263 return modeError(NULL,inString,inPtr,"language mode name required");
4265 if (!SkipDelimiter(&inPtr, &errMsg))
4266 return modeError(lm, inString, inPtr, errMsg);
4268 /* read list of extensions */
4269 lm->extensions = readExtensionList(&inPtr,
4270 &lm->nExtensions);
4271 if (!SkipDelimiter(&inPtr, &errMsg))
4272 return modeError(lm, inString, inPtr, errMsg);
4274 /* read the recognition regular expression */
4275 if (*inPtr == '\n' || *inPtr == '\0' || *inPtr == ':')
4276 lm->recognitionExpr = NULL;
4277 else if (!ReadQuotedString(&inPtr, &errMsg, &lm->recognitionExpr))
4278 return modeError(lm, inString,inPtr, errMsg);
4279 if (!SkipDelimiter(&inPtr, &errMsg))
4280 return modeError(lm, inString, inPtr, errMsg);
4282 /* read the indent style */
4283 styleName = ReadSymbolicField(&inPtr);
4284 if (styleName == NULL)
4285 lm->indentStyle = DEFAULT_INDENT;
4286 else {
4287 for (i=0; i<N_INDENT_STYLES; i++) {
4288 if (!strcmp(styleName, AutoIndentTypes[i])) {
4289 lm->indentStyle = i;
4290 break;
4293 XtFree(styleName);
4294 if (i == N_INDENT_STYLES)
4295 return modeError(lm,inString,inPtr,"unrecognized indent style");
4297 if (!SkipDelimiter(&inPtr, &errMsg))
4298 return modeError(lm, inString, inPtr, errMsg);
4300 /* read the wrap style */
4301 styleName = ReadSymbolicField(&inPtr);
4302 if (styleName == NULL)
4303 lm->wrapStyle = DEFAULT_WRAP;
4304 else {
4305 for (i=0; i<N_WRAP_STYLES; i++) {
4306 if (!strcmp(styleName, AutoWrapTypes[i])) {
4307 lm->wrapStyle = i;
4308 break;
4311 XtFree(styleName);
4312 if (i == N_WRAP_STYLES)
4313 return modeError(lm, inString, inPtr,"unrecognized wrap style");
4315 if (!SkipDelimiter(&inPtr, &errMsg))
4316 return modeError(lm, inString, inPtr, errMsg);
4318 /* read the tab distance */
4319 if (*inPtr == '\n' || *inPtr == '\0' || *inPtr == ':')
4320 lm->tabDist = DEFAULT_TAB_DIST;
4321 else if (!ReadNumericField(&inPtr, &lm->tabDist))
4322 return modeError(lm, inString, inPtr, "bad tab spacing");
4323 if (!SkipDelimiter(&inPtr, &errMsg))
4324 return modeError(lm, inString, inPtr, errMsg);
4326 /* read emulated tab distance */
4327 if (*inPtr == '\n' || *inPtr == '\0' || *inPtr == ':')
4328 lm->emTabDist = DEFAULT_EM_TAB_DIST;
4329 else if (!ReadNumericField(&inPtr, &lm->emTabDist))
4330 return modeError(lm, inString, inPtr, "bad emulated tab spacing");
4331 if (!SkipDelimiter(&inPtr, &errMsg))
4332 return modeError(lm, inString, inPtr, errMsg);
4334 /* read the delimiters string */
4335 if (*inPtr == '\n' || *inPtr == '\0' || *inPtr == ':')
4336 lm->delimiters = NULL;
4337 else if (!ReadQuotedString(&inPtr, &errMsg, &lm->delimiters))
4338 return modeError(lm, inString, inPtr, errMsg);
4340 /* After 5.3 all language modes need a default tips file field */
4341 if (!SkipDelimiter(&inPtr, &errMsg))
4342 if (fileVer > 5003)
4343 return modeError(lm, inString, inPtr, errMsg);
4345 /* read the default tips file */
4346 if (*inPtr == '\n' || *inPtr == '\0')
4347 lm->defTipsFile = NULL;
4348 else if (!ReadQuotedString(&inPtr, &errMsg, &lm->defTipsFile))
4349 return modeError(lm, inString, inPtr, errMsg);
4351 /* pattern set was read correctly, add/replace it in the list */
4352 for (i=0; i<NLanguageModes; i++) {
4353 if (!strcmp(LanguageModes[i]->name, lm->name)) {
4354 freeLanguageModeRec(LanguageModes[i]);
4355 LanguageModes[i] = lm;
4356 break;
4359 if (i == NLanguageModes) {
4360 LanguageModes[NLanguageModes++] = lm;
4361 if (NLanguageModes > MAX_LANGUAGE_MODES)
4362 return modeError(NULL, inString, inPtr,
4363 "maximum allowable number of language modes exceeded");
4366 /* if the string ends here, we're done */
4367 inPtr += strspn(inPtr, " \t\n");
4368 if (*inPtr == '\0')
4369 return True;
4370 } /* End for(;;) */
4373 static char *writeLanguageModesString(void)
4375 int i;
4376 char *outStr, *escapedStr, *str, numBuf[25];
4377 textBuffer *outBuf;
4379 outBuf = BufCreate();
4380 for (i=0; i<NLanguageModes; i++) {
4381 BufInsert(outBuf, outBuf->length, "\t");
4382 BufInsert(outBuf, outBuf->length, LanguageModes[i]->name);
4383 BufInsert(outBuf, outBuf->length, ":");
4384 BufInsert(outBuf, outBuf->length, str = createExtString(
4385 LanguageModes[i]->extensions, LanguageModes[i]->nExtensions));
4386 XtFree(str);
4387 BufInsert(outBuf, outBuf->length, ":");
4388 if (LanguageModes[i]->recognitionExpr != NULL) {
4389 BufInsert(outBuf, outBuf->length,
4390 str=MakeQuotedString(LanguageModes[i]->recognitionExpr));
4391 XtFree(str);
4393 BufInsert(outBuf, outBuf->length, ":");
4394 if (LanguageModes[i]->indentStyle != DEFAULT_INDENT)
4395 BufInsert(outBuf, outBuf->length,
4396 AutoIndentTypes[LanguageModes[i]->indentStyle]);
4397 BufInsert(outBuf, outBuf->length, ":");
4398 if (LanguageModes[i]->wrapStyle != DEFAULT_WRAP)
4399 BufInsert(outBuf, outBuf->length,
4400 AutoWrapTypes[LanguageModes[i]->wrapStyle]);
4401 BufInsert(outBuf, outBuf->length, ":");
4402 if (LanguageModes[i]->tabDist != DEFAULT_TAB_DIST) {
4403 sprintf(numBuf, "%d", LanguageModes[i]->tabDist);
4404 BufInsert(outBuf, outBuf->length, numBuf);
4406 BufInsert(outBuf, outBuf->length, ":");
4407 if (LanguageModes[i]->emTabDist != DEFAULT_EM_TAB_DIST) {
4408 sprintf(numBuf, "%d", LanguageModes[i]->emTabDist);
4409 BufInsert(outBuf, outBuf->length, numBuf);
4411 BufInsert(outBuf, outBuf->length, ":");
4412 if (LanguageModes[i]->delimiters != NULL) {
4413 BufInsert(outBuf, outBuf->length,
4414 str=MakeQuotedString(LanguageModes[i]->delimiters));
4415 XtFree(str);
4417 BufInsert(outBuf, outBuf->length, ":");
4418 if (LanguageModes[i]->defTipsFile != NULL) {
4419 BufInsert(outBuf, outBuf->length,
4420 str=MakeQuotedString(LanguageModes[i]->defTipsFile));
4421 XtFree(str);
4424 BufInsert(outBuf, outBuf->length, "\n");
4427 /* Get the output, and lop off the trailing newline */
4428 outStr = BufGetRange(outBuf, 0, outBuf->length - 1);
4429 BufFree(outBuf);
4430 escapedStr = EscapeSensitiveChars(outStr);
4431 XtFree(outStr);
4432 return escapedStr;
4435 static char *createExtString(char **extensions, int nExtensions)
4437 int e, length = 1;
4438 char *outStr, *outPtr;
4440 for (e=0; e<nExtensions; e++)
4441 length += strlen(extensions[e]) + 1;
4442 outStr = outPtr = XtMalloc(length);
4443 for (e=0; e<nExtensions; e++) {
4444 strcpy(outPtr, extensions[e]);
4445 outPtr += strlen(extensions[e]);
4446 *outPtr++ = ' ';
4448 if (nExtensions == 0)
4449 *outPtr = '\0';
4450 else
4451 *(outPtr-1) = '\0';
4452 return outStr;
4455 static char **readExtensionList(char **inPtr, int *nExtensions)
4457 char *extensionList[MAX_FILE_EXTENSIONS];
4458 char **retList, *strStart;
4459 int i, len;
4461 /* skip over blank space */
4462 *inPtr += strspn(*inPtr, " \t");
4464 for (i=0; i<MAX_FILE_EXTENSIONS && **inPtr!=':' && **inPtr!='\0'; i++) {
4465 *inPtr += strspn(*inPtr, " \t");
4466 strStart = *inPtr;
4467 while (**inPtr!=' ' && **inPtr!='\t' && **inPtr!=':' && **inPtr!='\0')
4468 (*inPtr)++;
4469 len = *inPtr - strStart;
4470 extensionList[i] = XtMalloc(len + 1);
4471 strncpy(extensionList[i], strStart, len);
4472 extensionList[i][len] = '\0';
4474 *nExtensions = i;
4475 if (i == 0)
4476 return NULL;
4477 retList = (char **)XtMalloc(sizeof(char *) * i);
4478 memcpy(retList, extensionList, sizeof(char *) * i);
4479 return retList;
4482 int ReadNumericField(char **inPtr, int *value)
4484 int charsRead;
4486 /* skip over blank space */
4487 *inPtr += strspn(*inPtr, " \t");
4489 if (sscanf(*inPtr, "%d%n", value, &charsRead) != 1)
4490 return False;
4491 *inPtr += charsRead;
4492 return True;
4496 ** Parse a symbolic field, skipping initial and trailing whitespace,
4497 ** stops on first invalid character or end of string. Valid characters
4498 ** are letters, numbers, _, -, +, $, #, and internal whitespace. Internal
4499 ** whitespace is compressed to single space characters.
4501 char *ReadSymbolicField(char **inPtr)
4503 char *outStr, *outPtr, *strStart, *strPtr;
4504 int len;
4506 /* skip over initial blank space */
4507 *inPtr += strspn(*inPtr, " \t");
4509 /* Find the first invalid character or end of string to know how
4510 much memory to allocate for the returned string */
4511 strStart = *inPtr;
4512 while (isalnum((unsigned char)**inPtr) || **inPtr=='_' || **inPtr=='-' ||
4513 **inPtr=='+' || **inPtr=='$' || **inPtr=='#' || **inPtr==' ' ||
4514 **inPtr=='\t')
4515 (*inPtr)++;
4516 len = *inPtr - strStart;
4517 if (len == 0)
4518 return NULL;
4519 outStr = outPtr = XtMalloc(len + 1);
4521 /* Copy the string, compressing internal whitespace to a single space */
4522 strPtr = strStart;
4523 while (strPtr - strStart < len) {
4524 if (*strPtr == ' ' || *strPtr == '\t') {
4525 strPtr += strspn(strPtr, " \t");
4526 *outPtr++ = ' ';
4527 } else
4528 *outPtr++ = *strPtr++;
4531 /* If there's space on the end, take it back off */
4532 if (outPtr > outStr && *(outPtr-1) == ' ')
4533 outPtr--;
4534 if (outPtr == outStr) {
4535 XtFree(outStr);
4536 return NULL;
4538 *outPtr = '\0';
4539 return outStr;
4543 ** parse an individual quoted string. Anything between
4544 ** double quotes is acceptable, quote characters can be escaped by "".
4545 ** Returns allocated string "string" containing
4546 ** argument minus quotes. If not successful, returns False with
4547 ** (statically allocated) message in "errMsg".
4549 int ReadQuotedString(char **inPtr, char **errMsg, char **string)
4551 char *outPtr, *c;
4553 /* skip over blank space */
4554 *inPtr += strspn(*inPtr, " \t");
4556 /* look for initial quote */
4557 if (**inPtr != '\"') {
4558 *errMsg = "expecting quoted string";
4559 return False;
4561 (*inPtr)++;
4563 /* calculate max length and allocate returned string */
4564 for (c= *inPtr; ; c++) {
4565 if (*c == '\0') {
4566 *errMsg = "string not terminated";
4567 return False;
4568 } else if (*c == '\"') {
4569 if (*(c+1) == '\"')
4570 c++;
4571 else
4572 break;
4576 /* copy string up to end quote, transforming escaped quotes into quotes */
4577 *string = XtMalloc(c - *inPtr + 1);
4578 outPtr = *string;
4579 while (True) {
4580 if (**inPtr == '\"') {
4581 if (*(*inPtr+1) == '\"')
4582 (*inPtr)++;
4583 else
4584 break;
4586 *outPtr++ = *(*inPtr)++;
4588 *outPtr = '\0';
4590 /* skip end quote */
4591 (*inPtr)++;
4592 return True;
4596 ** Replace characters which the X resource file reader considers control
4597 ** characters, such that a string will read back as it appears in "string".
4598 ** (So far, newline characters are replaced with with \n\<newline> and
4599 ** backslashes with \\. This has not been tested exhaustively, and
4600 ** probably should be. It would certainly be more asthetic if other
4601 ** control characters were replaced as well).
4603 ** Returns an allocated string which must be freed by the caller with XtFree.
4605 char *EscapeSensitiveChars(const char *string)
4607 const char *c;
4608 char *outStr, *outPtr;
4609 int length = 0;
4611 /* calculate length and allocate returned string */
4612 for (c=string; *c!='\0'; c++) {
4613 if (*c == '\\')
4614 length++;
4615 else if (*c == '\n')
4616 length += 3;
4617 length++;
4619 outStr = XtMalloc(length + 1);
4620 outPtr = outStr;
4622 /* add backslashes */
4623 for (c=string; *c!='\0'; c++) {
4624 if (*c == '\\')
4625 *outPtr++ = '\\';
4626 else if (*c == '\n') {
4627 *outPtr++ = '\\';
4628 *outPtr++ = 'n';
4629 *outPtr++ = '\\';
4631 *outPtr++ = *c;
4633 *outPtr = '\0';
4634 return outStr;
4638 ** Adds double quotes around a string and escape existing double quote
4639 ** characters with two double quotes. Enables the string to be read back
4640 ** by ReadQuotedString.
4642 char *MakeQuotedString(const char *string)
4644 const char *c;
4645 char *outStr, *outPtr;
4646 int length = 0;
4648 /* calculate length and allocate returned string */
4649 for (c=string; *c!='\0'; c++) {
4650 if (*c == '\"')
4651 length++;
4652 length++;
4654 outStr = XtMalloc(length + 3);
4655 outPtr = outStr;
4657 /* add starting quote */
4658 *outPtr++ = '\"';
4660 /* copy string, escaping quotes with "" */
4661 for (c=string; *c!='\0'; c++) {
4662 if (*c == '\"')
4663 *outPtr++ = '\"';
4664 *outPtr++ = *c;
4667 /* add ending quote */
4668 *outPtr++ = '\"';
4670 /* terminate string and return */
4671 *outPtr = '\0';
4672 return outStr;
4676 ** Read a dialog text field containing a symbolic name (language mode names,
4677 ** style names, highlight pattern names, colors, and fonts), clean the
4678 ** entered text of leading and trailing whitespace, compress all
4679 ** internal whitespace to one space character, and check it over for
4680 ** colons, which interfere with the preferences file reader/writer syntax.
4681 ** Returns NULL on error, and puts up a dialog if silent is False. Returns
4682 ** an empty string if the text field is blank.
4684 char *ReadSymbolicFieldTextWidget(Widget textW, const char *fieldName, int silent)
4686 char *string, *stringPtr, *parsedString;
4688 /* read from the text widget */
4689 string = stringPtr = XmTextGetString(textW);
4691 /* parse it with the same routine used to read symbolic fields from
4692 files. If the string is not read entirely, there are invalid
4693 characters, so warn the user if not in silent mode. */
4694 parsedString = ReadSymbolicField(&stringPtr);
4695 if (*stringPtr != '\0')
4697 if (!silent)
4699 *(stringPtr + 1) = '\0';
4700 DialogF(DF_WARN, textW, 1, "Invalid Character",
4701 "Invalid character \"%s\" in %s", "Dismiss", stringPtr,
4702 fieldName);
4703 XmProcessTraversal(textW, XmTRAVERSE_CURRENT);
4705 XtFree(string);
4706 if (parsedString != NULL)
4707 XtFree(parsedString);
4708 return NULL;
4710 XtFree(string);
4711 if (parsedString == NULL) {
4712 parsedString = XtMalloc(1);
4713 *parsedString = '\0';
4715 return parsedString;
4719 ** Create a pulldown menu pane with the names of the current language modes.
4720 ** XmNuserData for each item contains the language mode name.
4722 Widget CreateLanguageModeMenu(Widget parent, XtCallbackProc cbProc, void *cbArg)
4724 Widget menu, btn;
4725 int i;
4726 XmString s1;
4728 menu = CreatePulldownMenu(parent, "languageModes", NULL, 0);
4729 for (i=0; i<NLanguageModes; i++) {
4730 btn = XtVaCreateManagedWidget("languageMode", xmPushButtonGadgetClass,
4731 menu,
4732 XmNlabelString, s1=XmStringCreateSimple(LanguageModes[i]->name),
4733 XmNmarginHeight, 0,
4734 XmNuserData, (void *)LanguageModes[i]->name, NULL);
4735 XmStringFree(s1);
4736 XtAddCallback(btn, XmNactivateCallback, cbProc, cbArg);
4738 return menu;
4742 ** Set the language mode menu in option menu "optMenu" to
4743 ** show a particular language mode
4745 void SetLangModeMenu(Widget optMenu, const char *modeName)
4747 int i;
4748 Cardinal nItems;
4749 WidgetList items;
4750 Widget pulldown, selectedItem;
4751 char *itemName;
4753 XtVaGetValues(optMenu, XmNsubMenuId, &pulldown, NULL);
4754 XtVaGetValues(pulldown, XmNchildren, &items, XmNnumChildren, &nItems, NULL);
4755 if (nItems == 0)
4756 return;
4757 selectedItem = items[0];
4758 for (i=0; i<(int)nItems; i++) {
4759 XtVaGetValues(items[i], XmNuserData, &itemName, NULL);
4760 if (!strcmp(itemName, modeName)) {
4761 selectedItem = items[i];
4762 break;
4765 XtVaSetValues(optMenu, XmNmenuHistory, selectedItem,NULL);
4769 ** Create a submenu for chosing language mode for the current window.
4771 Widget CreateLanguageModeSubMenu(WindowInfo *window, Widget parent, char *name,
4772 char *label, char mnemonic)
4774 XmString s1=XmStringCreateSimple(label);
4776 window->langModeCascade = XtVaCreateManagedWidget(name,
4777 xmCascadeButtonGadgetClass, parent, XmNlabelString,
4778 s1, XmNmnemonic, mnemonic,
4779 XmNsubMenuId, NULL, NULL);
4780 XmStringFree(s1);
4781 updateLanguageModeSubmenu(window);
4782 return window->langModeCascade;
4786 ** Re-build the language mode sub-menu using the current data stored
4787 ** in the master list: LanguageModes.
4789 static void updateLanguageModeSubmenu(WindowInfo *window)
4791 int i;
4792 XmString s1;
4793 Widget menu, btn;
4794 Arg args[1] = {{XmNradioBehavior, (XtArgVal)True}};
4796 /* Destroy and re-create the menu pane */
4797 XtVaGetValues(window->langModeCascade, XmNsubMenuId, &menu, NULL);
4798 if (menu != NULL)
4799 XtDestroyWidget(menu);
4800 menu = CreatePulldownMenu(XtParent(window->langModeCascade),
4801 "languageModes", args, 1);
4802 btn = XtVaCreateManagedWidget("languageMode",
4803 xmToggleButtonGadgetClass, menu,
4804 XmNlabelString, s1=XmStringCreateSimple("Plain"),
4805 XmNuserData, (void *)PLAIN_LANGUAGE_MODE,
4806 XmNset, window->languageMode==PLAIN_LANGUAGE_MODE, NULL);
4807 XmStringFree(s1);
4808 XtAddCallback(btn, XmNvalueChangedCallback, setLangModeCB, window);
4809 for (i=0; i<NLanguageModes; i++) {
4810 btn = XtVaCreateManagedWidget("languageMode",
4811 xmToggleButtonGadgetClass, menu,
4812 XmNlabelString, s1=XmStringCreateSimple(LanguageModes[i]->name),
4813 XmNmarginHeight, 0,
4814 XmNuserData, (void *)i,
4815 XmNset, window->languageMode==i, NULL);
4816 XmStringFree(s1);
4817 XtAddCallback(btn, XmNvalueChangedCallback, setLangModeCB, window);
4819 XtVaSetValues(window->langModeCascade, XmNsubMenuId, menu, NULL);
4822 static void setLangModeCB(Widget w, XtPointer clientData, XtPointer callData)
4824 WindowInfo *window = (WindowInfo *)clientData;
4825 char *params[1];
4826 void *mode;
4828 if (!XmToggleButtonGetState(w))
4829 return;
4831 /* get name of language mode stored in userData field of menu item */
4832 XtVaGetValues(w, XmNuserData, &mode, NULL);
4834 /* If the mode didn't change, do nothing */
4835 if (window->languageMode == (int)mode)
4836 return;
4838 /* redo syntax highlighting word delimiters, etc. */
4840 reapplyLanguageMode(window, (int)mode, False);
4842 params[0] = (((int)mode) == PLAIN_LANGUAGE_MODE) ? "" : LanguageModes[(int)mode]->name;
4843 XtCallActionProc(window->textArea, "set_language_mode", NULL, params, 1);
4847 ** Skip a delimiter and it's surrounding whitespace
4849 int SkipDelimiter(char **inPtr, char **errMsg)
4851 *inPtr += strspn(*inPtr, " \t");
4852 if (**inPtr != ':') {
4853 *errMsg = "syntax error";
4854 return False;
4856 (*inPtr)++;
4857 *inPtr += strspn(*inPtr, " \t");
4858 return True;
4862 ** Skip an optional separator and its surrounding whitespace
4863 ** return true if delimiter found
4865 int SkipOptSeparator(char separator, char **inPtr, char **errMsg)
4867 *inPtr += strspn(*inPtr, " \t");
4868 if (**inPtr != separator) {
4869 return False;
4871 (*inPtr)++;
4872 *inPtr += strspn(*inPtr, " \t");
4873 return True;
4877 ** Short-hand error processing for language mode parsing errors, frees
4878 ** lm (if non-null), prints a formatted message explaining where the
4879 ** error is, and returns False;
4881 static int modeError(languageModeRec *lm, const char *stringStart,
4882 const char *stoppedAt, const char *message)
4884 if (lm != NULL)
4885 freeLanguageModeRec(lm);
4886 return ParseError(NULL, stringStart, stoppedAt,
4887 "language mode specification", message);
4891 ** Report parsing errors in resource strings or macros, formatted nicely so
4892 ** the user can tell where things became botched. Errors can be sent either
4893 ** to stderr, or displayed in a dialog. For stderr, pass toDialog as NULL.
4894 ** For a dialog, pass the dialog parent in toDialog.
4896 int ParseError(Widget toDialog, const char *stringStart, const char *stoppedAt,
4897 const char *errorIn, const char *message)
4899 int len, nNonWhite = 0;
4900 const char *c;
4901 char *errorLine;
4903 for (c=stoppedAt; c>=stringStart; c--) {
4904 if (c == stringStart)
4905 break;
4906 else if (*c == '\n' && nNonWhite >= 5)
4907 break;
4908 else if (*c != ' ' && *c != '\t')
4909 nNonWhite++;
4911 len = stoppedAt - c + (*stoppedAt == '\0' ? 0 : 1);
4912 errorLine = XtMalloc(len+4);
4913 strncpy(errorLine, c, len);
4914 errorLine[len++] = '<';
4915 errorLine[len++] = '=';
4916 errorLine[len++] = '=';
4917 errorLine[len] = '\0';
4918 if (toDialog == NULL)
4920 fprintf(stderr, "NEdit: %s in %s:\n%s\n", message, errorIn, errorLine);
4921 } else
4923 DialogF(DF_WARN, toDialog, 1, "Parse Error", "%s in %s:\n%s", "Dismiss",
4924 message, errorIn, errorLine);
4926 XtFree(errorLine);
4927 return False;
4931 ** Compare two strings which may be NULL
4933 int AllocatedStringsDiffer(const char *s1, const char *s2)
4935 if (s1 == NULL && s2 == NULL)
4936 return False;
4937 if (s1 == NULL || s2 == NULL)
4938 return True;
4939 return strcmp(s1, s2);
4942 static void updatePatternsTo5dot1(void)
4944 const char *htmlDefaultExpr = "^[ \t]*HTML[ \t]*:[ \t]*Default[ \t]*$";
4945 const char *vhdlAnchorExpr = "^[ \t]*VHDL:";
4947 /* Add new patterns if there aren't already existing patterns with
4948 the same name. If possible, insert before VHDL in language mode
4949 list. If not, just add to end */
4950 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*PostScript:"))
4951 spliceString(&TempStringPrefs.highlight, "PostScript:Default",
4952 vhdlAnchorExpr);
4953 if (!regexFind(TempStringPrefs.language, "^[ \t]*PostScript:"))
4954 spliceString(&TempStringPrefs.language,
4955 "PostScript:.ps .PS .eps .EPS .epsf .epsi::::::",
4956 vhdlAnchorExpr);
4957 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*Lex:"))
4958 spliceString(&TempStringPrefs.highlight, "Lex:Default",
4959 vhdlAnchorExpr);
4960 if (!regexFind(TempStringPrefs.language, "^[ \t]*Lex:"))
4961 spliceString(&TempStringPrefs.language, "Lex:.lex::::::",
4962 vhdlAnchorExpr);
4963 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*SQL:"))
4964 spliceString(&TempStringPrefs.highlight, "SQL:Default",
4965 vhdlAnchorExpr);
4966 if (!regexFind(TempStringPrefs.language, "^[ \t]*SQL:"))
4967 spliceString(&TempStringPrefs.language, "SQL:.sql::::::",
4968 vhdlAnchorExpr);
4969 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*Matlab:"))
4970 spliceString(&TempStringPrefs.highlight, "Matlab:Default",
4971 vhdlAnchorExpr);
4972 if (!regexFind(TempStringPrefs.language, "^[ \t]*Matlab:"))
4973 spliceString(&TempStringPrefs.language, "Matlab:..m .oct .sci::::::",
4974 vhdlAnchorExpr);
4975 if (!regexFind(TempStringPrefs.smartIndent, "^[ \t]*Matlab:"))
4976 spliceString(&TempStringPrefs.smartIndent, "Matlab:Default", NULL);
4977 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Label:"))
4978 spliceString(&TempStringPrefs.styles, "Label:red:Italic",
4979 "^[ \t]*Flag:");
4980 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Storage Type1:"))
4981 spliceString(&TempStringPrefs.styles, "Storage Type1:saddle brown:Bold",
4982 "^[ \t]*String:");
4984 /* Replace html pattern with sgml html pattern, as long as there
4985 isn't an existing html pattern which will be overwritten */
4986 if (regexFind(TempStringPrefs.highlight, htmlDefaultExpr)) {
4987 regexReplace(&TempStringPrefs.highlight, htmlDefaultExpr,
4988 "SGML HTML:Default");
4989 if (!regexReplace(&TempStringPrefs.language, "^[ \t]*HTML:.*$",
4990 "SGML HTML:.sgml .sgm .html .htm:\"\\<(?ihtml)\\>\":::::\n")) {
4991 spliceString(&TempStringPrefs.language,
4992 "SGML HTML:.sgml .sgm .html .htm:\"\\<(?ihtml)\\>\":::::\n",
4993 vhdlAnchorExpr);
4998 static void updatePatternsTo5dot2(void)
5000 #ifdef VMS
5001 const char *cppLm5dot1 =
5002 "^[ \t]*C\\+\\+:\\.CC \\.HH \\.I::::::\"\\.,/\\\\`'!\\|@#%\\^&\\*\\(\\)-=\\+\\{\\}\\[\\]\"\":;\\<\\>\\?~\"";
5003 const char *perlLm5dot1 =
5004 "^[ \t]*Perl:\\.PL \\.PM \\.P5:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\.\\*perl\":::::";
5005 const char *psLm5dot1 =
5006 "^[ \t]*PostScript:\\.ps \\.PS \\.eps \\.EPS \\.epsf \\.epsi:\"\\^%!\":::::\"/%\\(\\)\\{\\}\\[\\]\\<\\>\"";
5007 const char *tclLm5dot1 = "^[ \t]*Tcl:\\.TCL::::::";
5009 const char *cppLm5dot2 =
5010 "C++:.CC .HH .C .H .I .CXX .HXX .CPP::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\"";
5011 const char *perlLm5dot2 =
5012 "Perl:.PL .PM .P5:\"^[ \\t]*#[ \\t]*!.*perl\":Auto:None:::\".,/\\\\`'!$@#%^&*()-=+{}[]\"\":;<>?~|\"";
5013 const char *psLm5dot2 =
5014 "PostScript:.ps .PS .eps .EPS .epsf .epsi:\"^%!\":::::\"/%(){}[]<>\"";
5015 const char *tclLm5dot2 =
5016 "Tcl:.TCL::Smart:None:::";
5017 #else
5018 const char *cppLm5dot1 =
5019 "^[ \t]*C\\+\\+:\\.cc \\.hh \\.C \\.H \\.i \\.cxx \\.hxx::::::\"\\.,/\\\\`'!\\|@#%\\^&\\*\\(\\)-=\\+\\{\\}\\[\\]\"\":;\\<\\>\\?~\"";
5020 const char *perlLm5dot1 =
5021 "^[ \t]*Perl:\\.pl \\.pm \\.p5:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\.\\*perl\":::::";
5022 const char *psLm5dot1 =
5023 "^[ \t]*PostScript:\\.ps \\.PS \\.eps \\.EPS \\.epsf \\.epsi:\"\\^%!\":::::\"/%\\(\\)\\{\\}\\[\\]\\<\\>\"";
5024 const char *shLm5dot1 =
5025 "^[ \t]*Sh Ksh Bash:\\.sh \\.bash \\.ksh \\.profile:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\[ \\\\t\\]\\*/bin/\\(sh\\|ksh\\|bash\\)\":::::";
5026 const char *tclLm5dot1 = "^[ \t]*Tcl:\\.tcl::::::";
5028 const char *cppLm5dot2 =
5029 "C++:.cc .hh .C .H .i .cxx .hxx .cpp::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\"";
5030 const char *perlLm5dot2 =
5031 "Perl:.pl .pm .p5 .PL:\"^[ \\t]*#[ \\t]*!.*perl\":Auto:None:::\".,/\\\\`'!$@#%^&*()-=+{}[]\"\":;<>?~|\"";
5032 const char *psLm5dot2 =
5033 "PostScript:.ps .eps .epsf .epsi:\"^%!\":::::\"/%(){}[]<>\"";
5034 const char *shLm5dot2 =
5035 "Sh Ksh Bash:.sh .bash .ksh .profile .bashrc .bash_logout .bash_login .bash_profile:\"^[ \\t]*#[ \\t]*![ \\t]*/.*bin/(sh|ksh|bash)\":::::";
5036 const char *tclLm5dot2 =
5037 "Tcl:.tcl .tk .itcl .itk::Smart:None:::";
5038 #endif /* VMS */
5040 const char *cssLm5dot2 =
5041 "CSS:css::Auto:None:::\".,/\\`'!|@#%^&*()=+{}[]\"\":;<>?~\"";
5042 const char *reLm5dot2 =
5043 "Regex:.reg .regex:\"\\(\\?[:#=!iInN].+\\)\":None:Continuous:::";
5044 const char *xmlLm5dot2 =
5045 "XML:.xml .xsl .dtd:\"\\<(?i\\?xml|!doctype)\"::None:::\"<>/=\"\"'()+*?|\"";
5047 const char *cssHl5dot2 = "CSS:Default";
5048 const char *reHl5dot2 = "Regex:Default";
5049 const char *xmlHl5dot2 = "XML:Default";
5051 const char *ptrStyle = "Pointer:#660000:Bold";
5052 const char *reStyle = "Regex:#009944:Bold";
5053 const char *wrnStyle = "Warning:brown2:Italic";
5055 /* First upgrade modified language modes, only if the user hasn't
5056 altered the default 5.1 definitions. */
5057 if (regexFind(TempStringPrefs.language, cppLm5dot1))
5058 regexReplace(&TempStringPrefs.language, cppLm5dot1, cppLm5dot2);
5059 if (regexFind(TempStringPrefs.language, perlLm5dot1))
5060 regexReplace(&TempStringPrefs.language, perlLm5dot1, perlLm5dot2);
5061 if (regexFind(TempStringPrefs.language, psLm5dot1))
5062 regexReplace(&TempStringPrefs.language, psLm5dot1, psLm5dot2);
5063 #ifndef VMS
5064 if (regexFind(TempStringPrefs.language, shLm5dot1))
5065 regexReplace(&TempStringPrefs.language, shLm5dot1, shLm5dot2);
5066 #endif
5067 if (regexFind(TempStringPrefs.language, tclLm5dot1))
5068 regexReplace(&TempStringPrefs.language, tclLm5dot1, tclLm5dot2);
5070 /* Then append the new modes (trying to keep them in alphabetical order
5071 makes no sense, since 5.1 didn't use alphabetical order). */
5072 if (!regexFind(TempStringPrefs.language, "^[ \t]*CSS:"))
5073 spliceString(&TempStringPrefs.language, cssLm5dot2, NULL);
5074 if (!regexFind(TempStringPrefs.language, "^[ \t]*Regex:"))
5075 spliceString(&TempStringPrefs.language, reLm5dot2, NULL);
5076 if (!regexFind(TempStringPrefs.language, "^[ \t]*XML:"))
5077 spliceString(&TempStringPrefs.language, xmlLm5dot2, NULL);
5079 /* Enable default highlighting patterns for these modes, unless already
5080 present */
5081 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*CSS:"))
5082 spliceString(&TempStringPrefs.highlight, cssHl5dot2, NULL);
5083 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*Regex:"))
5084 spliceString(&TempStringPrefs.highlight, reHl5dot2, NULL);
5085 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*XML:"))
5086 spliceString(&TempStringPrefs.highlight, xmlHl5dot2, NULL);
5088 /* Finally, append the new highlight styles */
5090 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Warning:"))
5091 spliceString(&TempStringPrefs.styles, wrnStyle, NULL);
5092 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Regex:"))
5093 spliceString(&TempStringPrefs.styles, reStyle, "^[ \t]*Warning:");
5094 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Pointer:"))
5095 spliceString(&TempStringPrefs.styles, ptrStyle, "^[ \t]*Regex:");
5098 static void updatePatternsTo5dot3(void)
5100 /* This is a bogus function on non-VMS */
5101 #ifdef VMS
5102 const char *psLm5dot2 =
5103 "^[ \t]*PostScript:\\.ps \\.PS \\.eps \\.EPS \\.epsf \\.epsi:\"\\^%!\":::::\"/%\\(\\)\\{\\}\\[\\]\\<\\>\"";
5105 const char *psLm5dot3 =
5106 "PostScript:.ps .PS .eps .EPS .epsf .EPSF .epsi .EPSI:\"^%!\":::::\"/%(){}[]<>\"";
5108 /* Upgrade modified language modes, only if the user hasn't
5109 altered the default 5.2 definitions. */
5110 if (regexFind(TempStringPrefs.language, psLm5dot2))
5111 regexReplace(&TempStringPrefs.language, psLm5dot2, psLm5dot3);
5112 #endif
5115 static void updatePatternsTo5dot4(void)
5117 #ifdef VMS
5118 const char *pyLm5dot3 =
5119 "Python:\\.PY:\"\\^#!\\.\\*python\":Auto:None::::?\n";
5120 const char *xrLm5dot3 =
5121 "X Resources:\\.XRESOURCES \\.XDEFAULTS \\.NEDIT:\"\\^\\[!#\\]\\.\\*\\(\\[Aa\\]pp\\|\\[Xx\\]\\)\\.\\*\\[Dd\\]efaults\"::::::?\n";
5123 const char *pyLm5dot4 =
5124 "Python:.PY:\"^#!.*python\":Auto:None:::\"!\"\"#$%&'()*+,-./:;<=>?@[\\\\]^`{|}~\":\n";
5125 const char *xrLm5dot4 =
5126 "X Resources:.XRESOURCES .XDEFAULTS .NEDIT NEDIT.RC:\"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults\"::::::\n";
5127 #else
5128 const char *pyLm5dot3 =
5129 "Python:\\.py:\"\\^#!\\.\\*python\":Auto:None::::?\n";
5130 const char *xrLm5dot3 =
5131 "X Resources:\\.Xresources \\.Xdefaults \\.nedit:\"\\^\\[!#\\]\\.\\*\\(\\[Aa\\]pp\\|\\[Xx\\]\\)\\.\\*\\[Dd\\]efaults\"::::::?\n";
5133 const char *pyLm5dot4 =
5134 "Python:.py:\"^#!.*python\":Auto:None:::\"!\"\"#$%&'()*+,-./:;<=>?@[\\\\]^`{|}~\":\n";
5135 const char *xrLm5dot4 =
5136 "X Resources:.Xresources .Xdefaults .nedit nedit.rc:\"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults\"::::::\n";
5137 #endif
5139 /* Upgrade modified language modes, only if the user hasn't
5140 altered the default 5.3 definitions. */
5141 if (regexFind(TempStringPrefs.language, pyLm5dot3))
5142 regexReplace(&TempStringPrefs.language, pyLm5dot3, pyLm5dot4);
5143 if (regexFind(TempStringPrefs.language, xrLm5dot3))
5144 regexReplace(&TempStringPrefs.language, xrLm5dot3, xrLm5dot4);
5148 * We migrate a color from the X resources to the prefs if:
5149 * 1. The prefs entry is equal to the default entry
5150 * 2. The X resource is not equal to the default entry
5152 static void migrateColor(XrmDatabase prefDB, XrmDatabase appDB,
5153 char *class, char *name, int color_index, char *default_val)
5155 char *type, *valueString;
5156 XrmValue rsrcValue;
5158 /* If this color has been customized in the color dialog then use
5159 that value */
5160 if ( strcmp(default_val, PrefData.colorNames[color_index]) )
5161 return;
5163 /* Retrieve the value of the resource from the DB */
5164 if (XrmGetResource(prefDB, name, class, &type, &rsrcValue)) {
5165 if (strcmp(type, XmRString)) {
5166 fprintf(stderr,"Internal Error: Unexpected resource type, %s\n",
5167 type);
5168 return;
5170 valueString = rsrcValue.addr;
5171 } else if (XrmGetResource(appDB, name, class, &type, &rsrcValue)) {
5172 if (strcmp(type, XmRString)) {
5173 fprintf(stderr,"Internal Error: Unexpected resource type, %s\n",
5174 type);
5175 return;
5177 valueString = rsrcValue.addr;
5178 } else
5179 /* No resources set */
5180 return;
5182 /* An X resource is set. If it's non-default, update the prefs. */
5183 if ( strcmp(valueString, default_val) ) {
5184 strncpy(PrefData.colorNames[color_index], valueString,
5185 MAX_COLOR_LEN);
5190 * In 5.4 we moved color preferences from X resources to a color dialog,
5191 * meaning they're in the normal prefs system. Users who have customized
5192 * their colors with X resources would probably prefer not to have to redo
5193 * the customization in the dialog, so we migrate them to the prefs for them.
5195 static void migrateColorResources(XrmDatabase prefDB, XrmDatabase appDB)
5197 migrateColor(prefDB, appDB, APP_CLASS ".Text.Foreground",
5198 APP_NAME ".text.foreground", TEXT_FG_COLOR,
5199 NEDIT_DEFAULT_FG);
5200 migrateColor(prefDB, appDB, APP_CLASS ".Text.Background",
5201 APP_NAME ".text.background", TEXT_BG_COLOR,
5202 NEDIT_DEFAULT_TEXT_BG);
5203 migrateColor(prefDB, appDB, APP_CLASS ".Text.SelectForeground",
5204 APP_NAME ".text.selectForeground", SELECT_FG_COLOR,
5205 NEDIT_DEFAULT_SEL_FG);
5206 migrateColor(prefDB, appDB, APP_CLASS ".Text.SelectBackground",
5207 APP_NAME ".text.selectBackground", SELECT_BG_COLOR,
5208 NEDIT_DEFAULT_SEL_BG);
5209 migrateColor(prefDB, appDB, APP_CLASS ".Text.HighlightForeground",
5210 APP_NAME ".text.highlightForeground", HILITE_FG_COLOR,
5211 NEDIT_DEFAULT_HI_FG);
5212 migrateColor(prefDB, appDB, APP_CLASS ".Text.HighlightBackground",
5213 APP_NAME ".text.highlightBackground", HILITE_BG_COLOR,
5214 NEDIT_DEFAULT_HI_BG);
5215 migrateColor(prefDB, appDB, APP_CLASS ".Text.LineNumForeground",
5216 APP_NAME ".text.lineNumForeground", LINENO_FG_COLOR,
5217 NEDIT_DEFAULT_LINENO_FG);
5218 migrateColor(prefDB, appDB, APP_CLASS ".Text.CursorForeground",
5219 APP_NAME ".text.cursorForeground", CURSOR_FG_COLOR,
5220 NEDIT_DEFAULT_CURSOR_FG);
5224 ** Inserts a string into intoString, reallocating it with XtMalloc. If
5225 ** regular expression atExpr is found, inserts the string before atExpr
5226 ** followed by a newline. If atExpr is not found, inserts insertString
5227 ** at the end, PRECEDED by a newline.
5229 static void spliceString(char **intoString, const char *insertString, const char *atExpr)
5231 int beginPos, endPos;
5232 int intoLen = strlen(*intoString);
5233 int insertLen = strlen(insertString);
5234 char *newString = XtMalloc(intoLen + insertLen + 2);
5236 if (atExpr != NULL && SearchString(*intoString, atExpr,
5237 SEARCH_FORWARD, SEARCH_REGEX, False, 0, &beginPos, &endPos,
5238 NULL, NULL, NULL)) {
5239 strncpy(newString, *intoString, beginPos);
5240 strncpy(&newString[beginPos], insertString, insertLen);
5241 newString[beginPos+insertLen] = '\n';
5242 strncpy(&newString[beginPos+insertLen+1],
5243 &((*intoString)[beginPos]), intoLen - beginPos);
5244 } else {
5245 strncpy(newString, *intoString, intoLen);
5246 newString[intoLen] = '\n';
5247 strncpy(&newString[intoLen+1], insertString, insertLen);
5249 newString[intoLen + insertLen + 1] = '\0';
5250 XtFree(*intoString);
5251 *intoString = newString;
5255 ** Simplified regular expression search routine which just returns true
5256 ** or false depending on whether inString matches expr
5258 static int regexFind(const char *inString, const char *expr)
5260 int beginPos, endPos;
5261 return SearchString(inString, expr, SEARCH_FORWARD, SEARCH_REGEX, False,
5262 0, &beginPos, &endPos, NULL, NULL, NULL);
5266 ** Simplified regular expression replacement routine which replaces the
5267 ** first occurence of expr in inString with replaceWith, reallocating
5268 ** inString with XtMalloc. If expr is not found, does nothing and
5269 ** returns false.
5271 static int regexReplace(char **inString, const char *expr, const char *replaceWith)
5273 int beginPos, endPos, newLen;
5274 char *newString;
5275 int replaceLen = strlen(replaceWith);
5276 int inLen = strlen(*inString);
5278 if (!SearchString(*inString, expr, SEARCH_FORWARD, SEARCH_REGEX, False,
5279 0, &beginPos, &endPos, NULL, NULL, NULL))
5280 return FALSE;
5281 newLen = inLen + replaceLen - (endPos-beginPos);
5282 newString = XtMalloc(newLen + 1);
5283 strncpy(newString, *inString, beginPos);
5284 strncpy(&newString[beginPos], replaceWith, replaceLen);
5285 strncpy(&newString[beginPos+replaceLen],
5286 &((*inString)[endPos]), inLen - endPos);
5287 newString[newLen] = '\0';
5288 XtFree(*inString);
5289 *inString = newString;
5290 return TRUE;
5294 #ifndef VMS
5296 ** Replace all '#' characters in shell commands by '##' to keep commands
5297 ** containing those working. '#' is a line number placeholder in 5.3 and
5298 ** had no special meaning before.
5300 static void updateShellCmdsTo5dot3(void)
5302 char *cOld, *cNew, *pCol, *pNL;
5303 int nHash, isCmd;
5304 char *newString;
5306 if(!TempStringPrefs.shellCmds)
5307 return;
5309 /* Count number of '#'. If there are '#' characters in the non-command
5310 ** part of the definition we count too much and later allocate too much
5311 ** memory for the new string, but this doesn't hurt.
5313 for(cOld=TempStringPrefs.shellCmds, nHash=0; *cOld; cOld++)
5314 if(*cOld == '#')
5315 nHash++;
5317 /* No '#' -> no conversion necessary. */
5318 if(!nHash)
5319 return;
5321 newString=XtMalloc(strlen(TempStringPrefs.shellCmds) + 1 + nHash);
5323 cOld = TempStringPrefs.shellCmds;
5324 cNew = newString;
5325 isCmd = 0;
5326 pCol = NULL;
5327 pNL = NULL;
5329 /* Copy all characters from TempStringPrefs.shellCmds into newString
5330 ** and duplicate '#' in command parts. A simple check for really beeing
5331 ** inside a command part (starting with '\n', between the the two last
5332 ** '\n' a colon ':' must have been found) is preformed.
5334 while(*cOld) {
5335 /* actually every 2nd line is a command. We additionally
5336 ** check if there is a colon ':' in the previous line.
5338 if(*cOld=='\n') {
5339 if((pCol > pNL) && !isCmd)
5340 isCmd=1;
5341 else
5342 isCmd=0;
5343 pNL=cOld;
5346 if(!isCmd && *cOld ==':')
5347 pCol = cOld;
5349 /* Duplicate hashes if we're in a command part */
5350 if(isCmd && *cOld=='#')
5351 *cNew++ = '#';
5353 /* Copy every character */
5354 *cNew++ = *cOld++;
5358 /* Terminate new preferences string */
5359 *cNew = 0;
5361 /* free the old memory */
5362 XtFree(TempStringPrefs.shellCmds);
5364 /* exchange the string */
5365 TempStringPrefs.shellCmds = newString;
5369 #else
5371 static void updateShellCmdsTo5dot3(void) {
5372 /* No shell commands in VMS ! */
5373 return;
5376 #endif
5378 #ifdef SGI_CUSTOM
5380 ** Present the user a dialog for specifying whether or not a short
5381 ** menu mode preference should be applied toward the default setting.
5382 ** Return False (function value) if operation was canceled, return True
5383 ** in setDefault if requested to reset the default value.
5385 static int shortPrefToDefault(Widget parent, const char *settingName, int *setDefault)
5387 char msg[100] = "";
5389 if (!GetPrefShortMenus()) {
5390 *setDefault = False;
5391 return True;
5394 sprintf(msg, "%s\nSave as default for future windows as well?", settingName);
5395 switch (DialogF (DF_QUES, parent, 3, "Save Default", msg, "Yes", "No",
5396 "Cancel"))
5398 case 1: /* yes */
5399 *setDefault = True;
5400 return True;
5401 case 2: /* no */
5402 *setDefault = False;
5403 return True;
5404 case 3: /* cancel */
5405 return False;
5407 return False; /* not reached */
5409 #endif
5411 /* Unload the default calltips file for this window unless somebody else
5412 is using it */
5413 void UnloadLanguageModeTipsFile(WindowInfo *window) {
5414 int mode;
5415 WindowInfo *wi;
5417 mode = window->languageMode;
5418 if (mode != PLAIN_LANGUAGE_MODE && LanguageModes[mode]->defTipsFile) {
5419 for (wi = WindowList; wi; wi = wi->next)
5420 if (wi->languageMode == mode && wi != window)
5421 break;
5422 if (!wi) /* If we got to end of WindowList... */
5423 DeleteTagsFile( LanguageModes[mode]->defTipsFile, TIP );
5426 /* Make sure we didn't accidentally delete a default calltips file that
5427 also belongs to another language mode */
5428 for (wi = WindowList; wi; wi = wi->next) {
5429 if (wi == window)
5430 continue;
5431 mode = wi->languageMode;
5432 if (mode != PLAIN_LANGUAGE_MODE && LanguageModes[mode]->defTipsFile)
5433 if (AddTagsFile( LanguageModes[mode]->defTipsFile, TIP ) == FALSE)
5434 fprintf( stderr, "Error loading default calltips file:\n"
5435 " \"%s\"\n", LanguageModes[mode]->defTipsFile );
5439 /******************************************************************************
5440 * The Color selection dialog
5441 ******************************************************************************/
5444 There are 8 colors: And 8 indices:
5445 textFg TEXT_FG_COLOR
5446 textBg TEXT_BG_COLOR
5447 selectFg SELECT_FG_COLOR
5448 selectBg SELECT_BG_COLOR
5449 hiliteFg HILITE_FG_COLOR
5450 hiliteBg HILITE_BG_COLOR
5451 lineNoFg LINENO_FG_COLOR
5452 cursorFg CURSOR_FG_COLOR
5455 #define MARGIN_SPACING 10
5458 * Callbacks for field modifications
5460 static void textFgModifiedCB(Widget w, XtPointer clientData,
5461 XtPointer callData)
5463 colorDialog *cd = (colorDialog *)clientData;
5464 showColorStatus(cd, cd->textFgW, cd->textFgErrW);
5467 static void textBgModifiedCB(Widget w, XtPointer clientData,
5468 XtPointer callData)
5470 colorDialog *cd = (colorDialog *)clientData;
5471 showColorStatus(cd, cd->textBgW, cd->textBgErrW);
5474 static void selectFgModifiedCB(Widget w, XtPointer clientData,
5475 XtPointer callData)
5477 colorDialog *cd = (colorDialog *)clientData;
5478 showColorStatus(cd, cd->selectFgW, cd->selectFgErrW);
5481 static void selectBgModifiedCB(Widget w, XtPointer clientData,
5482 XtPointer callData)
5484 colorDialog *cd = (colorDialog *)clientData;
5485 showColorStatus(cd, cd->selectBgW, cd->selectBgErrW);
5488 static void hiliteFgModifiedCB(Widget w, XtPointer clientData,
5489 XtPointer callData)
5491 colorDialog *cd = (colorDialog *)clientData;
5492 showColorStatus(cd, cd->hiliteFgW, cd->hiliteFgErrW);
5495 static void hiliteBgModifiedCB(Widget w, XtPointer clientData,
5496 XtPointer callData)
5498 colorDialog *cd = (colorDialog *)clientData;
5499 showColorStatus(cd, cd->hiliteBgW, cd->hiliteBgErrW);
5502 static void lineNoFgModifiedCB(Widget w, XtPointer clientData,
5503 XtPointer callData)
5505 colorDialog *cd = (colorDialog *)clientData;
5506 showColorStatus(cd, cd->lineNoFgW, cd->lineNoFgErrW);
5509 static void cursorFgModifiedCB(Widget w, XtPointer clientData,
5510 XtPointer callData)
5512 colorDialog *cd = (colorDialog *)clientData;
5513 showColorStatus(cd, cd->cursorFgW, cd->cursorFgErrW);
5518 * Helper functions for validating colors
5520 static int verifyAllColors(colorDialog *cd) {
5521 /* Maybe just check for empty strings in error widgets instead? */
5522 return (checkColorStatus(cd, cd->textFgW) &&
5523 checkColorStatus(cd, cd->textBgW) &&
5524 checkColorStatus(cd, cd->selectFgW) &&
5525 checkColorStatus(cd, cd->selectBgW) &&
5526 checkColorStatus(cd, cd->hiliteFgW) &&
5527 checkColorStatus(cd, cd->hiliteBgW) &&
5528 checkColorStatus(cd, cd->lineNoFgW) &&
5529 checkColorStatus(cd, cd->cursorFgW) );
5532 /* Returns True if the color is valid, False if it's not */
5533 static Boolean checkColorStatus(colorDialog *cd, Widget colorFieldW)
5535 Colormap cMap;
5536 XColor colorDef;
5537 Status status;
5538 Display *display = XtDisplay(cd->shell);
5539 char *text = XmTextGetString(colorFieldW);
5540 XtVaGetValues(cd->shell, XtNcolormap, &cMap, NULL);
5541 status = XParseColor(display, cMap, text, &colorDef);
5542 XtFree(text);
5543 return (status != 0);
5546 /* Show or hide errorLabelW depending on whether or not colorFieldW
5547 contains a valid color name. */
5548 static void showColorStatus(colorDialog *cd, Widget colorFieldW,
5549 Widget errorLabelW)
5551 /* Should set the OK/Apply button sensitivity here, instead
5552 of leaving is sensitive and then complaining if an error. */
5553 XtSetMappedWhenManaged( errorLabelW, !checkColorStatus(cd, colorFieldW) );
5556 /* Update the colors in the window or in the preferences */
5557 static void updateColors(colorDialog *cd)
5559 WindowInfo *window;
5561 char *textFg = XmTextGetString(cd->textFgW),
5562 *textBg = XmTextGetString(cd->textBgW),
5563 *selectFg = XmTextGetString(cd->selectFgW),
5564 *selectBg = XmTextGetString(cd->selectBgW),
5565 *hiliteFg = XmTextGetString(cd->hiliteFgW),
5566 *hiliteBg = XmTextGetString(cd->hiliteBgW),
5567 *lineNoFg = XmTextGetString(cd->lineNoFgW),
5568 *cursorFg = XmTextGetString(cd->cursorFgW);
5570 for (window = WindowList; window != NULL; window = window->next)
5572 SetColors(window, textFg, textBg, selectFg, selectBg, hiliteFg,
5573 hiliteBg, lineNoFg, cursorFg);
5576 SetPrefColorName(TEXT_FG_COLOR , textFg );
5577 SetPrefColorName(TEXT_BG_COLOR , textBg );
5578 SetPrefColorName(SELECT_FG_COLOR, selectFg);
5579 SetPrefColorName(SELECT_BG_COLOR, selectBg);
5580 SetPrefColorName(HILITE_FG_COLOR, hiliteFg);
5581 SetPrefColorName(HILITE_BG_COLOR, hiliteBg);
5582 SetPrefColorName(LINENO_FG_COLOR, lineNoFg);
5583 SetPrefColorName(CURSOR_FG_COLOR, cursorFg);
5585 XtFree(textFg);
5586 XtFree(textBg);
5587 XtFree(selectFg);
5588 XtFree(selectBg);
5589 XtFree(hiliteFg);
5590 XtFree(hiliteBg);
5591 XtFree(lineNoFg);
5592 XtFree(cursorFg);
5597 * Dialog button callbacks
5600 static void colorDestroyCB(Widget w, XtPointer clientData, XtPointer callData)
5602 colorDialog *cd = (colorDialog *)clientData;
5604 cd->window->colorDialog = NULL;
5605 XtFree((char *)cd);
5608 static void colorOkCB(Widget w, XtPointer clientData, XtPointer callData)
5610 colorDialog *cd = (colorDialog *)clientData;
5612 if(!verifyAllColors(cd))
5614 DialogF(DF_ERR, w, 1, "Invalid Colors",
5615 "All colors must be valid to proceed.", "Dismiss");
5616 return;
5618 updateColors(cd);
5620 /* pop down and destroy the dialog */
5621 XtDestroyWidget(cd->shell);
5624 static void colorApplyCB(Widget w, XtPointer clientData, XtPointer callData)
5626 colorDialog *cd = (colorDialog *)clientData;
5628 if(!verifyAllColors(cd))
5630 DialogF(DF_ERR, w, 1, "Invalid Colors",
5631 "All colors must be valid to be applied.", "Dismiss");
5632 return;
5634 updateColors(cd);
5637 static void colorDismissCB(Widget w, XtPointer clientData, XtPointer callData)
5639 colorDialog *cd = (colorDialog *)clientData;
5641 /* pop down and destroy the dialog */
5642 XtDestroyWidget(cd->shell);
5646 /* Add a label, error label, and text entry label with a validation
5647 callback */
5648 static Widget addColorGroup( Widget parent, const char *name, char mnemonic,
5649 char *label, Widget *fieldW, Widget *errW, Widget topWidget,
5650 int leftPos, int rightPos, XtCallbackProc modCallback,
5651 colorDialog *cd )
5653 Widget lblW;
5654 char *longerName;
5655 XmString s1;
5656 int nameLen = strlen(name);
5658 /* The label widget */
5659 longerName = XtMalloc(nameLen+7);
5660 strcpy(longerName, name);
5661 strcat(longerName, "Lbl");
5662 lblW = XtVaCreateManagedWidget(longerName,
5663 xmLabelGadgetClass, parent,
5664 XmNlabelString, s1=XmStringCreateSimple( label ),
5665 XmNmnemonic, mnemonic,
5666 XmNtopAttachment, XmATTACH_WIDGET,
5667 XmNtopWidget, topWidget,
5668 XmNtopOffset, MARGIN_SPACING,
5669 XmNleftAttachment, XmATTACH_POSITION,
5670 XmNleftPosition, leftPos, NULL);
5671 XmStringFree(s1);
5673 /* The error label widget */
5674 strcpy(&(longerName[nameLen]), "ErrLbl");
5675 *errW = XtVaCreateManagedWidget(longerName,
5676 xmLabelWidgetClass, parent,
5677 XmNlabelString, s1=XmStringCreateSimple("(Invalid!)"),
5678 XmNalignment, XmALIGNMENT_END,
5679 XmNtopAttachment, XmATTACH_WIDGET,
5680 XmNtopWidget, topWidget,
5681 XmNtopOffset, MARGIN_SPACING,
5682 XmNleftAttachment, XmATTACH_WIDGET,
5683 XmNleftWidget, lblW,
5684 XmNrightAttachment, XmATTACH_POSITION,
5685 XmNrightPosition, rightPos, NULL);
5686 XmStringFree(s1);
5688 /* The text field entry widget */
5689 *fieldW = XtVaCreateManagedWidget(name, xmTextWidgetClass,
5690 parent,
5691 XmNcolumns, MAX_COLOR_LEN-1,
5692 XmNmaxLength, MAX_COLOR_LEN-1,
5693 XmNleftAttachment, XmATTACH_POSITION,
5694 XmNleftPosition, leftPos,
5695 XmNrightAttachment, XmATTACH_POSITION,
5696 XmNrightPosition, rightPos,
5697 XmNtopAttachment, XmATTACH_WIDGET,
5698 XmNtopWidget, lblW, NULL);
5699 RemapDeleteKey(*fieldW);
5700 XtAddCallback(*fieldW, XmNvalueChangedCallback,
5701 modCallback, cd);
5702 XtVaSetValues(lblW, XmNuserData, *fieldW, NULL);
5704 XtFree(longerName);
5705 return *fieldW;
5710 * Code for the dialog itself
5712 void ChooseColors(WindowInfo *window, int forWindow)
5714 Widget form, tmpW, topW, infoLbl;
5715 Widget okBtn, applyBtn, dismissBtn, fillBtn;
5716 colorDialog *cd;
5717 XmString s1;
5718 int ac;
5719 Arg args[20];
5721 /* if the dialog is already displayed, just pop it to the top and return */
5722 if (window->colorDialog != NULL) {
5723 RaiseShellWindow(((colorDialog *)window->colorDialog)->shell);
5724 return;
5727 /* Create a structure for keeping track of dialog state */
5728 cd = XtNew(colorDialog);
5729 window->colorDialog = (void*)cd;
5731 /* Create a form widget in a dialog shell */
5732 ac = 0;
5733 XtSetArg(args[ac], XmNautoUnmanage, False); ac++;
5734 XtSetArg(args[ac], XmNresizePolicy, XmRESIZE_NONE); ac++;
5735 form = CreateFormDialog(window->shell, "choose colors", args, ac);
5736 XtVaSetValues(form, XmNshadowThickness, 0, NULL);
5737 cd->shell = XtParent(form);
5738 cd->window = window;
5739 XtVaSetValues(cd->shell, XmNtitle, "Colors", NULL);
5740 AddMotifCloseCallback(XtParent(form), colorDismissCB, cd);
5741 XtAddCallback(form, XmNdestroyCallback, colorDestroyCB, cd);
5743 /* Information label */
5744 infoLbl = XtVaCreateManagedWidget("infoLbl",
5745 xmLabelGadgetClass, form,
5746 XmNtopAttachment, XmATTACH_POSITION,
5747 XmNtopPosition, 2,
5748 XmNleftAttachment, XmATTACH_POSITION,
5749 XmNleftPosition, 1,
5750 XmNrightAttachment, XmATTACH_POSITION,
5751 XmNrightPosition, 99,
5752 XmNalignment, XmALIGNMENT_CENTER,
5753 XmNlabelString, s1 = XmStringCreateLtoR(
5754 "Colors can be entered as names (e.g. red, blue) or "
5755 "as RGB triples\nin the format #RRGGBB, where each digit "
5756 "is in the range 0-f.", XmFONTLIST_DEFAULT_TAG),
5757 NULL);
5758 XmStringFree(s1);
5760 topW = infoLbl;
5762 /* The left column (foregrounds) of color entry groups */
5763 tmpW = addColorGroup( form, "textFg", 'P', "Plain Text Foreground",
5764 &(cd->textFgW), &(cd->textFgErrW), topW, 1, 49,
5765 textFgModifiedCB, cd );
5766 tmpW = addColorGroup( form, "selectFg", 'S', "Selection Foreground",
5767 &(cd->selectFgW), &(cd->selectFgErrW), tmpW, 1, 49,
5768 selectFgModifiedCB, cd );
5769 tmpW = addColorGroup( form, "hiliteFg", 'M', "Matching (..) Foreground",
5770 &(cd->hiliteFgW), &(cd->hiliteFgErrW), tmpW, 1, 49,
5771 hiliteFgModifiedCB, cd );
5772 tmpW = addColorGroup( form, "lineNoFg", 'L', "Line Numbers",
5773 &(cd->lineNoFgW), &(cd->lineNoFgErrW), tmpW, 1, 49,
5774 lineNoFgModifiedCB, cd );
5776 /* The right column (backgrounds) */
5777 tmpW = addColorGroup( form, "textBg", 'T', "Text Area Background",
5778 &(cd->textBgW), &(cd->textBgErrW), topW, 51, 99,
5779 textBgModifiedCB, cd );
5780 tmpW = addColorGroup( form, "selectBg", 'B', "Selection Background",
5781 &(cd->selectBgW), &(cd->selectBgErrW), tmpW, 51, 99,
5782 selectBgModifiedCB, cd );
5783 tmpW = addColorGroup( form, "hiliteBg", 'h', "Matching (..) Background",
5784 &(cd->hiliteBgW), &(cd->hiliteBgErrW), tmpW, 51, 99,
5785 hiliteBgModifiedCB, cd );
5786 tmpW = addColorGroup( form, "cursorFg", 'C', "Cursor Color",
5787 &(cd->cursorFgW), &(cd->cursorFgErrW), tmpW, 51, 99,
5788 cursorFgModifiedCB, cd );
5790 tmpW = XtVaCreateManagedWidget("infoLbl",
5791 xmLabelGadgetClass, form,
5792 XmNtopAttachment, XmATTACH_WIDGET,
5793 XmNtopWidget, tmpW,
5794 XmNtopOffset, MARGIN_SPACING,
5795 XmNleftAttachment, XmATTACH_POSITION,
5796 XmNleftPosition, 1,
5797 XmNrightAttachment, XmATTACH_POSITION,
5798 XmNrightPosition, 99,
5799 XmNalignment, XmALIGNMENT_CENTER,
5800 XmNlabelString, s1 = XmStringCreateLtoR(
5801 "NOTE: Foreground colors only apply when syntax highlighting "
5802 "is DISABLED.\n", XmFONTLIST_DEFAULT_TAG),
5803 NULL);
5804 XmStringFree(s1);
5806 /* The OK, Apply, and Cancel buttons */
5807 okBtn = XtVaCreateManagedWidget("ok", xmPushButtonWidgetClass, form,
5808 XmNlabelString, s1=XmStringCreateSimple("OK"),
5809 XmNtopAttachment, XmATTACH_WIDGET,
5810 XmNtopWidget, tmpW,
5811 /* XmNtopOffset, MARGIN_SPACING, */
5812 XmNleftAttachment, XmATTACH_POSITION,
5813 XmNleftPosition, 10,
5814 XmNrightAttachment, XmATTACH_POSITION,
5815 XmNrightPosition, 30,
5816 XmNbottomAttachment, XmATTACH_POSITION,
5817 XmNbottomPosition, 99, NULL);
5818 XtAddCallback(okBtn, XmNactivateCallback, colorOkCB, cd);
5819 XmStringFree(s1);
5821 applyBtn = XtVaCreateManagedWidget(
5822 "apply", xmPushButtonWidgetClass, form,
5823 XmNlabelString, s1=XmStringCreateSimple("Apply"),
5824 XmNtopAttachment, XmATTACH_WIDGET,
5825 XmNtopWidget, tmpW,
5826 /* XmNtopOffset, MARGIN_SPACING, */
5827 XmNmnemonic, 'A',
5828 XmNleftAttachment, XmATTACH_POSITION,
5829 XmNleftPosition, 40,
5830 XmNrightAttachment, XmATTACH_POSITION,
5831 XmNrightPosition, 60,
5832 XmNbottomAttachment, XmATTACH_POSITION,
5833 XmNbottomPosition, 99, NULL);
5834 XtAddCallback(applyBtn, XmNactivateCallback, colorApplyCB, cd);
5835 XmStringFree(s1);
5837 dismissBtn = XtVaCreateManagedWidget(
5838 "dismiss", xmPushButtonWidgetClass, form,
5839 XmNlabelString, s1=XmStringCreateSimple("Dismiss"),
5840 XmNtopAttachment, XmATTACH_WIDGET,
5841 XmNtopWidget, tmpW,
5842 /* XmNtopOffset, MARGIN_SPACING, */
5843 XmNleftAttachment, XmATTACH_POSITION,
5844 XmNleftPosition, 70,
5845 XmNrightAttachment, XmATTACH_POSITION,
5846 XmNrightPosition, 90,
5847 XmNbottomAttachment, XmATTACH_POSITION,
5848 XmNbottomPosition, 99, NULL);
5849 XtAddCallback(dismissBtn, XmNactivateCallback, colorDismissCB, cd);
5850 XmStringFree(s1);
5852 /* Set initial default button */
5853 XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
5854 XtVaSetValues(form, XmNcancelButton, dismissBtn, NULL);
5856 /* Set initial values */
5857 XmTextSetString(cd->textFgW, GetPrefColorName(TEXT_FG_COLOR ));
5858 XmTextSetString(cd->textBgW, GetPrefColorName(TEXT_BG_COLOR ));
5859 XmTextSetString(cd->selectFgW, GetPrefColorName(SELECT_FG_COLOR));
5860 XmTextSetString(cd->selectBgW, GetPrefColorName(SELECT_BG_COLOR));
5861 XmTextSetString(cd->hiliteFgW, GetPrefColorName(HILITE_FG_COLOR));
5862 XmTextSetString(cd->hiliteBgW, GetPrefColorName(HILITE_BG_COLOR));
5863 XmTextSetString(cd->lineNoFgW, GetPrefColorName(LINENO_FG_COLOR));
5864 XmTextSetString(cd->cursorFgW, GetPrefColorName(CURSOR_FG_COLOR));
5866 /* Handle mnemonic selection of buttons and focus to dialog */
5867 AddDialogMnemonicHandler(form, FALSE);
5869 /* put up dialog */
5870 ManageDialogCenteredOnPointer(form);