Don't use -import argument as fprintf format
[nedit.git] / source / preferences.c
blob74592d64a7a320b508c977ba1026954cf276f7e6
1 static const char CVSID[] = "$Id: preferences.c,v 1.160 2008/10/22 09:00:48 lebert 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. In addition, you may distribute version of this program linked to *
12 * Motif or Open Motif. See README for details. *
13 * *
14 * This software is distributed in the hope that it will be useful, but WITHOUT *
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
17 * for more details. *
18 * *
19 * You should have received a copy of the GNU General Public License along with *
20 * software; if not, write to the Free Software Foundation, Inc., 59 Temple *
21 * Place, Suite 330, Boston, MA 02111-1307 USA *
22 * *
23 * Nirvana Text Editor *
24 * April 20, 1993 *
25 * *
26 * Written by Mark Edel *
27 * *
28 *******************************************************************************/
30 #ifdef HAVE_CONFIG_H
31 #include "../config.h"
32 #endif
34 #include "preferences.h"
35 #include "textBuf.h"
36 #include "nedit.h"
37 #include "menu.h"
38 #include "text.h"
39 #include "search.h"
40 #include "window.h"
41 #include "userCmds.h"
42 #include "highlight.h"
43 #include "highlightData.h"
44 #include "help.h"
45 #include "regularExp.h"
46 #include "smartIndent.h"
47 #include "windowTitle.h"
48 #include "server.h"
49 #include "tags.h"
50 #include "../util/prefFile.h"
51 #include "../util/misc.h"
52 #include "../util/DialogF.h"
53 #include "../util/managedList.h"
54 #include "../util/fontsel.h"
55 #include "../util/fileUtils.h"
56 #include "../util/utils.h"
58 #include <ctype.h>
59 #include <pwd.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #include <stdio.h>
63 #include <unistd.h>
64 #include <sys/stat.h>
65 #ifdef VMS
66 #include "../util/VMSparam.h"
67 #else
68 #ifndef __MVS__
69 #include <sys/param.h>
70 #endif
71 #include "../util/clearcase.h"
72 #endif /*VMS*/
74 #include <Xm/Xm.h>
75 #include <Xm/SelectioB.h>
76 #include <Xm/Form.h>
77 #include <Xm/List.h>
78 #include <Xm/SeparatoG.h>
79 #include <Xm/LabelG.h>
80 #include <Xm/Label.h>
81 #include <Xm/PushBG.h>
82 #include <Xm/PushB.h>
83 #include <Xm/ToggleBG.h>
84 #include <Xm/ToggleB.h>
85 #include <Xm/RowColumn.h>
86 #include <Xm/CascadeBG.h>
87 #include <Xm/Frame.h>
88 #include <Xm/Text.h>
90 #ifdef HAVE_DEBUG_H
91 #include "../debug.h"
92 #endif
94 #if XmVersion >= 1002
95 #define MENU_WIDGET(w) (XmGetPostedFromWidget(XtParent(w)))
96 #else
97 #define MENU_WIDGET(w) (w)
98 #endif
100 #define PREF_FILE_VERSION "5.6"
102 /* New styles added in 5.2 for auto-upgrade */
103 #define ADD_5_2_STYLES " Pointer:#660000:Bold\nRegex:#009944:Bold\nWarning:brown2:Italic"
105 /* maximum number of word delimiters allowed (256 allows whole character set) */
106 #define MAX_WORD_DELIMITERS 256
108 /* maximum number of file extensions allowed in a language mode */
109 #define MAX_FILE_EXTENSIONS 20
111 /* Return values for checkFontStatus */
112 enum fontStatus {GOOD_FONT, BAD_PRIMARY, BAD_FONT, BAD_SIZE, BAD_SPACING};
114 /* enumerated type preference strings
115 ** The order of the elements in this array must be exactly the same
116 ** as the order of the corresponding integers of the enum SearchType
117 ** defined in search.h (!!)
119 static char *SearchMethodStrings[] = {
120 "Literal", "CaseSense", "RegExp",
121 "LiteralWord", "CaseSenseWord", "RegExpNoCase",
122 NULL
125 #ifdef REPLACE_SCOPE
126 /* enumerated default scope for replace dialog if a selection exists when
127 ** the dialog is popped up.
129 static char *ReplaceDefScopeStrings[] = {
130 "Window", "Selection", "Smart", NULL
132 #endif
134 #define N_WRAP_STYLES 3
135 static char *AutoWrapTypes[N_WRAP_STYLES+3] = {"None", "Newline", "Continuous",
136 "True", "False", NULL};
137 #define N_INDENT_STYLES 3
138 static char *AutoIndentTypes[N_INDENT_STYLES+3] = {"None", "Auto",
139 "Smart", "True", "False", NULL};
140 #define N_VIRTKEY_OVERRIDE_MODES 3
141 static char *VirtKeyOverrideModes[N_VIRTKEY_OVERRIDE_MODES+1] = { "Never",
142 "Auto", "Always", NULL};
144 #define N_SHOW_MATCHING_STYLES 3
145 /* For backward compatibility, "False" and "True" are still accepted.
146 They are internally converted to "Off" and "Delimiter" respectively.
147 NOTE: N_SHOW_MATCHING_STYLES must correspond to the number of
148 _real_ matching styles, not counting False & True.
149 False and True should also be the last ones in the list. */
150 static char *ShowMatchingTypes[] = {"Off", "Delimiter", "Range",
151 "False", "True", NULL};
153 /* This array must be kept in parallel to the enum truncSubstitution
154 in nedit.h */
155 static char* TruncSubstitutionModes[] = {"Silent", "Fail", "Warn", "Ignore", NULL};
157 /* suplement wrap and indent styles w/ a value meaning "use default" for
158 the override fields in the language modes dialog */
159 #define DEFAULT_WRAP -1
160 #define DEFAULT_INDENT -1
161 #define DEFAULT_TAB_DIST -1
162 #define DEFAULT_EM_TAB_DIST -1
164 /* list of available language modes and language specific preferences */
165 static int NLanguageModes = 0;
166 typedef struct {
167 char *name;
168 int nExtensions;
169 char **extensions;
170 char *recognitionExpr;
171 char *defTipsFile;
172 char *delimiters;
173 int wrapStyle;
174 int indentStyle;
175 int tabDist;
176 int emTabDist;
177 } languageModeRec;
178 static languageModeRec *LanguageModes[MAX_LANGUAGE_MODES];
180 /* Language mode dialog information */
181 static struct {
182 Widget shell;
183 Widget nameW;
184 Widget extW;
185 Widget recogW;
186 Widget defTipsW;
187 Widget delimitW;
188 Widget managedListW;
189 Widget tabW;
190 Widget emTabW;
191 Widget defaultIndentW;
192 Widget noIndentW;
193 Widget autoIndentW;
194 Widget smartIndentW;
195 Widget defaultWrapW;
196 Widget noWrapW;
197 Widget newlineWrapW;
198 Widget contWrapW;
199 languageModeRec **languageModeList;
200 int nLanguageModes;
201 } LMDialog = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
202 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0};
204 /* Font dialog information */
205 typedef struct {
206 Widget shell;
207 Widget primaryW;
208 Widget fillW;
209 Widget italicW;
210 Widget italicErrW;
211 Widget boldW;
212 Widget boldErrW;
213 Widget boldItalicW;
214 Widget boldItalicErrW;
215 WindowInfo *window;
216 int forWindow;
217 } fontDialog;
219 /* Color dialog information */
220 typedef struct {
221 Widget shell;
222 Widget textFgW;
223 Widget textFgErrW;
224 Widget textBgW;
225 Widget textBgErrW;
226 Widget selectFgW;
227 Widget selectFgErrW;
228 Widget selectBgW;
229 Widget selectBgErrW;
230 Widget hiliteFgW;
231 Widget hiliteFgErrW;
232 Widget hiliteBgW;
233 Widget hiliteBgErrW;
234 Widget lineNoFgW;
235 Widget lineNoFgErrW;
236 Widget cursorFgW;
237 Widget cursorFgErrW;
238 WindowInfo *window;
239 } colorDialog;
241 /* Repository for simple preferences settings */
242 static struct prefData {
243 int openInTab; /* open files in new tabs */
244 int wrapStyle; /* what kind of wrapping to do */
245 int wrapMargin; /* 0=wrap at window width, other=wrap margin */
246 int autoIndent; /* style for auto-indent */
247 int autoSave; /* whether automatic backup feature is on */
248 int saveOldVersion; /* whether to preserve a copy of last version */
249 int searchDlogs; /* whether to show explanatory search dialogs */
250 int searchWrapBeep; /* 1=beep when search restarts at begin/end */
251 int keepSearchDlogs; /* whether to retain find and replace dialogs */
252 int searchWraps; /* whether to attempt search again if reach bof or eof */
253 int statsLine; /* whether to show the statistics line */
254 int iSearchLine; /* whether to show the incremental search line*/
255 int tabBar; /* whether to show the tab bar */
256 int tabBarHideOne; /* hide tab bar if only one document in window */
257 int globalTabNavigate; /* prev/next document across windows */
258 int toolTips; /* whether to show the tooltips */
259 int lineNums; /* whether to show line numbers */
260 int pathInWindowsMenu; /* whether to show path in windows menu */
261 int warnFileMods; /* warn user if files externally modified */
262 int warnRealFileMods; /* only warn if file contents modified */
263 int warnExit; /* whether to warn on exit */
264 int searchMethod; /* initial search method as a text string */
265 #ifdef REPLACE_SCOPE
266 int replaceDefScope; /* default replace scope if selection exists */
267 #endif
268 int textRows; /* initial window height in characters */
269 int textCols; /* initial window width in characters */
270 int tabDist; /* number of characters between tab stops */
271 int emTabDist; /* non-zero tab dist. if emulated tabs are on */
272 int insertTabs; /* whether to use tabs for padding */
273 int showMatchingStyle; /* how to flash matching parenthesis */
274 int matchSyntaxBased; /* use syntax info to match parenthesis */
275 int highlightSyntax; /* whether to highlight syntax by default */
276 int smartTags; /* look for tag in current window first */
277 int alwaysCheckRelativeTagsSpecs; /* for every new opened file of session */
278 int stickyCaseSenseBtn; /* whether Case Word Btn is sticky to Regex Btn */
279 int prefFileRead; /* detects whether a .nedit existed */
280 int backlightChars; /* whether to apply character "backlighting" */
281 char *backlightCharTypes; /* the backlighting color definitions */
282 #ifdef SGI_CUSTOM
283 int shortMenus; /* short menu mode */
284 #endif
285 char fontString[MAX_FONT_LEN]; /* names of fonts for text widget */
286 char boldFontString[MAX_FONT_LEN];
287 char italicFontString[MAX_FONT_LEN];
288 char boldItalicFontString[MAX_FONT_LEN];
289 XmFontList fontList; /* XmFontLists corresp. to above named fonts */
290 XFontStruct *boldFontStruct;
291 XFontStruct *italicFontStruct;
292 XFontStruct *boldItalicFontStruct;
293 int sortTabs; /* sort tabs alphabetically */
294 int repositionDialogs; /* w. to reposition dialogs under the pointer */
295 int autoScroll; /* w. to autoscroll near top/bottom of screen */
296 int autoScrollVPadding; /* how close to get before autoscrolling */
297 int sortOpenPrevMenu; /* whether to sort the "Open Previous" menu */
298 int appendLF; /* Whether to append LF at the end of each file */
299 int mapDelete; /* whether to map delete to backspace */
300 int stdOpenDialog; /* w. to retain redundant text field in Open */
301 char tagFile[MAXPATHLEN]; /* name of tags file to look for at startup */
302 int maxPrevOpenFiles; /* limit to size of Open Previous menu */
303 int typingHidesPointer; /* hide mouse pointer when typing */
304 char delimiters[MAX_WORD_DELIMITERS]; /* punctuation characters */
305 char shell[MAXPATHLEN + 1]; /* shell to use for executing commands */
306 char geometry[MAX_GEOM_STRING_LEN]; /* per-application geometry string,
307 only for the clueless */
308 char serverName[MAXPATHLEN];/* server name for multiple servers per disp. */
309 char bgMenuBtn[MAX_ACCEL_LEN]; /* X event description for triggering
310 posting of background menu */
311 char fileVersion[6]; /* Version of nedit which wrote the .nedit
312 file we're reading */
313 int findReplaceUsesSelection; /* whether the find replace dialog is automatically
314 loaded with the primary selection */
315 int virtKeyOverride; /* Override Motif default virtual key bindings
316 never, if invalid, or always */
317 char titleFormat[MAX_TITLE_FORMAT_LEN];
318 char helpFontNames[NUM_HELP_FONTS][MAX_FONT_LEN];/* fonts for help system */
319 char helpLinkColor[MAX_COLOR_LEN]; /* Color for hyperlinks in the help system */
320 char colorNames[NUM_COLORS][MAX_COLOR_LEN];
321 char tooltipBgColor[MAX_COLOR_LEN];
322 int undoModifiesSelection;
323 int focusOnRaise;
324 Boolean honorSymlinks;
325 int truncSubstitution;
326 Boolean forceOSConversion;
327 } PrefData;
329 /* Temporary storage for preferences strings which are discarded after being
330 read */
331 static struct {
332 char *shellCmds;
333 char *macroCmds;
334 char *bgMenuCmds;
335 char *highlight;
336 char *language;
337 char *styles;
338 char *smartIndent;
339 char *smartIndentCommon;
340 char *shell;
341 } TempStringPrefs;
343 /* preference descriptions for SavePreferences and RestorePreferences. */
344 static PrefDescripRec PrefDescrip[] = {
345 {"fileVersion", "FileVersion" , PREF_STRING, "", PrefData.fileVersion,
346 (void *)sizeof(PrefData.fileVersion), True},
347 #ifndef VMS
348 #ifdef linux
349 {"shellCommands", "ShellCommands", PREF_ALLOC_STRING, "spell:Alt+B:s:EX:\n\
350 cat>spellTmp; xterm -e ispell -x spellTmp; cat spellTmp; rm spellTmp\n\
351 wc::w:ED:\nwc | awk '{print $1 \" lines, \" $2 \" words, \" $3 \" characters\"}'\n\
352 sort::o:EX:\nsort\nnumber lines::n:AW:\nnl -ba\nmake:Alt+Z:m:W:\nmake\n\
353 expand::p:EX:\nexpand\nunexpand::u:EX:\nunexpand\n",
354 &TempStringPrefs.shellCmds, NULL, True},
355 #elif __FreeBSD__
356 {"shellCommands", "ShellCommands", PREF_ALLOC_STRING, "spell:Alt+B:s:EX:\n\
357 cat>spellTmp; xterm -e ispell -x spellTmp; cat spellTmp; rm spellTmp\n\
358 wc::w:ED:\nwc | awk '{print $2 \" lines, \" $1 \" words, \" $3 \" characters\"}'\n\
359 sort::o:EX:\nsort\nnumber lines::n:AW:\npr -tn\nmake:Alt+Z:m:W:\nmake\n\
360 expand::p:EX:\nexpand\nunexpand::u:EX:\nunexpand\n",
361 &TempStringPrefs.shellCmds, NULL, True},
362 #else
363 {"shellCommands", "ShellCommands", PREF_ALLOC_STRING, "spell:Alt+B:s:ED:\n\
364 (cat;echo \"\") | spell\nwc::w:ED:\nwc | awk '{print $1 \" lines, \" $2 \" words, \" $3 \" characters\"}'\n\
365 \nsort::o:EX:\nsort\nnumber lines::n:AW:\nnl -ba\nmake:Alt+Z:m:W:\nmake\n\
366 expand::p:EX:\nexpand\nunexpand::u:EX:\nunexpand\n",
367 &TempStringPrefs.shellCmds, NULL, True},
368 #endif /* linux, __FreeBSD__ */
369 #endif /* VMS */
370 {"macroCommands", "MacroCommands", PREF_ALLOC_STRING,
371 "Complete Word:Alt+D::: {\n\
372 # This macro attempts to complete the current word by\n\
373 # finding another word in the same document that has\n\
374 # the same prefix; repeated invocations of the macro\n\
375 # (by repeated typing of its accelerator, say) cycles\n\
376 # through the alternatives found.\n\
377 # \n\
378 # Make sure $compWord contains something (a dummy index)\n\
379 $compWord[\"\"] = \"\"\n\
381 # Test whether the rest of $compWord has been initialized:\n\
382 # this avoids having to initialize the global variable\n\
383 # $compWord in an external macro file\n\
384 if (!(\"wordEnd\" in $compWord)) {\n\
385 # we need to initialize it\n\
386 $compWord[\"wordEnd\"] = 0\n\
387 $compWord[\"repeat\"] = 0\n\
388 $compWord[\"init\"] = 0\n\
389 $compWord[\"wordStart\"] = 0\n\
390 }\n\
392 if ($compWord[\"wordEnd\"] == $cursor) {\n\
393 $compWord[\"repeat\"] += 1\n\
394 }\n\
395 else {\n\
396 $compWord[\"repeat\"] = 1\n\
397 $compWord[\"init\"] = $cursor\n\
399 # search back to a word boundary to find the word to complete\n\
400 # (we use \\w here to allow for programming \"words\" that can include\n\
401 # digits and underscores; use \\l for letters only)\n\
402 $compWord[\"wordStart\"] = search(\"<\\\\w+\", $cursor, \"backward\", \"regex\", \"wrap\")\n\
404 if ($compWord[\"wordStart\"] == -1)\n\
405 return\n\
407 if ($search_end == $cursor)\n\
408 $compWord[\"word\"] = get_range($compWord[\"wordStart\"], $cursor)\n\
409 else\n\
410 return\n\
411 }\n\
412 s = $cursor\n\
413 for (i=0; i <= $compWord[\"repeat\"]; i++)\n\
414 s = search($compWord[\"word\"], s - 1, \"backward\", \"regex\", \"wrap\")\n\
416 if (s == $compWord[\"wordStart\"]) {\n\
417 beep()\n\
418 $compWord[\"repeat\"] = 0\n\
419 s = $compWord[\"wordStart\"]\n\
420 se = $compWord[\"init\"]\n\
421 }\n\
422 else\n\
423 se = search(\">\", s, \"regex\")\n\
425 replace_range($compWord[\"wordStart\"], $cursor, get_range(s, se))\n\
427 $compWord[\"wordEnd\"] = $cursor\n\
428 }\n\
429 Fill Sel. w/Char:::R: {\n\
430 # This macro replaces each character position in\n\
431 # the selection with the string typed into the dialog\n\
432 # it displays.\n\
433 if ($selection_start == -1) {\n\
434 beep()\n\
435 return\n\
436 }\n\
438 # Ask the user what character to fill with\n\
439 fillChar = string_dialog(\"Fill selection with what character?\", \\\n\
440 \"OK\", \"Cancel\")\n\
441 if ($string_dialog_button == 2 || $string_dialog_button == 0)\n\
442 return\n\
444 # Count the number of lines (NL characters) in the selection\n\
445 # (by removing all non-NLs in selection and counting the remainder)\n\
446 nLines = length(replace_in_string(get_selection(), \\\n\
447 \"^.*$\", \"\", \"regex\"))\n\
449 rectangular = $selection_left != -1\n\
451 # work out the pieces of required of the replacement text\n\
452 # this will be top mid bot where top is empty or ends in NL,\n\
453 # mid is 0 or more lines of repeats ending with NL, and\n\
454 # bot is 0 or more repeats of the fillChar\n\
456 toplen = -1 # top piece by default empty (no NL)\n\
457 midlen = 0\n\
458 botlen = 0\n\
460 if (rectangular) {\n\
461 # just fill the rectangle: mid\\n \\ nLines\n\
462 # mid\\n /\n\
463 # bot - last line with no nl\n\
464 midlen = $selection_right - $selection_left\n\
465 botlen = $selection_right - $selection_left\n\
466 } else {\n\
467 # |col[0]\n\
468 # .........toptoptop\\n |col[0]\n\
469 # either midmidmidmidmidmid\\n \\ nLines - 1 or ...botbot...\n\
470 # midmidmidmidmidmid\\n / |col[1]\n\
471 # botbot... |\n\
472 # |col[1] |wrap margin\n\
473 # we need column positions col[0], col[1] of selection start and\n\
474 # end (use a loop and arrays to do the two positions)\n\
475 sel[0] = $selection_start\n\
476 sel[1] = $selection_end\n\
478 # col[0] = pos_to_column($selection_start)\n\
479 # col[1] = pos_to_column($selection_end)\n\
481 for (i = 0; i < 2; ++i) {\n\
482 end = sel[i]\n\
483 pos = search(\"^\", end, \"regex\", \"backward\")\n\
484 thisCol = 0\n\
485 while (pos < end) {\n\
486 nexttab = search(\"\\t\", pos)\n\
487 if (nexttab < 0 || nexttab >= end) {\n\
488 thisCol += end - pos # count remaining non-tabs\n\
489 nexttab = end\n\
490 } else {\n\
491 thisCol += nexttab - pos + $tab_dist\n\
492 thisCol -= (thisCol % $tab_dist)\n\
493 }\n\
494 pos = nexttab + 1 # skip past the tab or end\n\
495 }\n\
496 col[i] = thisCol\n\
497 }\n\
498 toplen = max($wrap_margin - col[0], 0)\n\
499 botlen = min(col[1], $wrap_margin)\n\
501 if (nLines == 0) {\n\
502 toplen = -1\n\
503 botlen = max(botlen - col[0], 0)\n\
504 } else {\n\
505 midlen = $wrap_margin\n\
506 if (toplen < 0)\n\
507 toplen = 0\n\
508 nLines-- # top piece will end in a NL\n\
509 }\n\
510 }\n\
512 # Create the fill text\n\
513 # which is the longest piece? make a line of that length\n\
514 # (use string doubling - this allows the piece to be\n\
515 # appended to double in size at each iteration)\n\
517 len = max(toplen, midlen, botlen)\n\
518 charlen = length(fillChar) # maybe more than one char given!\n\
520 line = \"\"\n\
521 while (len > 0) {\n\
522 if (len % 2)\n\
523 line = line fillChar\n\
524 len /= 2\n\
525 if (len > 0)\n\
526 fillChar = fillChar fillChar\n\
527 }\n\
528 # assemble our pieces\n\
529 toppiece = \"\"\n\
530 midpiece = \"\"\n\
531 botpiece = \"\"\n\
532 if (toplen >= 0)\n\
533 toppiece = substring(line, 0, toplen * charlen) \"\\n\"\n\
534 if (botlen > 0)\n\
535 botpiece = substring(line, 0, botlen * charlen)\n\
537 # assemble midpiece (use doubling again)\n\
538 line = substring(line, 0, midlen * charlen) \"\\n\"\n\
539 while (nLines > 0) {\n\
540 if (nLines % 2)\n\
541 midpiece = midpiece line\n\
542 nLines /= 2\n\
543 if (nLines > 0)\n\
544 line = line line\n\
545 }\n\
546 # Replace the selection with the complete fill text\n\
547 replace_selection(toppiece midpiece botpiece)\n\
548 }\n\
549 Quote Mail Reply:::: {\n\
550 if ($selection_start == -1)\n\
551 replace_all(\"^.*$\", \"\\\\> &\", \"regex\")\n\
552 else\n\
553 replace_in_selection(\"^.*$\", \"\\\\> &\", \"regex\")\n\
554 }\n\
555 Unquote Mail Reply:::: {\n\
556 if ($selection_start == -1)\n\
557 replace_all(\"(^\\\\> )(.*)$\", \"\\\\2\", \"regex\")\n\
558 else\n\
559 replace_in_selection(\"(^\\\\> )(.*)$\", \"\\\\2\", \"regex\")\n\
560 }\n\
561 Comments>/* Comment */@C@C++@Java@CSS@JavaScript@Lex:::R: {\n\
562 selStart = $selection_start\n\
563 selEnd = $selection_end\n\
564 replace_range(selStart, selEnd, \"/* \" get_selection() \" */\")\n\
565 select(selStart, selEnd + 6)\n\
566 }\n\
567 Comments>/* Uncomment */@C@C++@Java@CSS@JavaScript@Lex:::R: {\n\
568 pos = search(\"(?n\\\\s*/\\\\*\\\\s*)\", $selection_start, \"regex\")\n\
569 start = $search_end\n\
570 end = search(\"(?n\\\\*/\\\\s*)\", $selection_end, \"regex\", \"backward\")\n\
571 if (pos != $selection_start || end == -1 )\n\
572 return\n\
573 replace_selection(get_range(start, end))\n\
574 select(pos, $cursor)\n\
575 }\n\
576 Comments>// Comment@C@C++@Java@JavaScript:::R: {\n\
577 replace_in_selection(\"^.*$\", \"// &\", \"regex\")\n\
578 }\n\
579 Comments>// Uncomment@C@C++@Java@JavaScript:::R: {\n\
580 replace_in_selection(\"(^[ \\\\t]*// ?)(.*)$\", \"\\\\2\", \"regex\")\n\
581 }\n\
582 Comments># Comment@Perl@Sh Ksh Bash@NEdit Macro@Makefile@Awk@Csh@Python@Tcl:::R: {\n\
583 replace_in_selection(\"^.*$\", \"#&\", \"regex\")\n\
584 }\n\
585 Comments># Uncomment@Perl@Sh Ksh Bash@NEdit Macro@Makefile@Awk@Csh@Python@Tcl:::R: {\n\
586 replace_in_selection(\"(^[ \\\\t]*#)(.*)$\", \"\\\\2\", \"regex\")\n\
587 }\n\
588 Comments>-- Comment@SQL:::R: {\n\
589 replace_in_selection(\"^.*$\", \"--&\", \"regex\")\n\
590 }\n\
591 Comments>-- Uncomment@SQL:::R: {\n\
592 replace_in_selection(\"(^[ \\\\t]*--)(.*)$\", \"\\\\2\", \"regex\")\n\
593 }\n\
594 Comments>! Comment@X Resources:::R: {\n\
595 replace_in_selection(\"^.*$\", \"!&\", \"regex\")\n\
596 }\n\
597 Comments>! Uncomment@X Resources:::R: {\n\
598 replace_in_selection(\"(^[ \\\\t]*!)(.*)$\", \"\\\\2\", \"regex\")\n\
599 }\n\
600 Comments>% Comment@LaTeX:::R: {\n\
601 replace_in_selection(\"^.*$\", \"%&\", \"regex\")\n\
602 }\n\
603 Comments>% Uncomment@LaTeX:::R: {\n\
604 replace_in_selection(\"(^[ \\\\t]*%)(.*)$\", \"\\\\2\", \"regex\")\n\
605 }\n\
606 Comments>Bar Comment@C:::R: {\n\
607 if ($selection_left != -1) {\n\
608 dialog(\"Selection must not be rectangular\")\n\
609 return\n\
610 }\n\
611 start = $selection_start\n\
612 end = $selection_end-1\n\
613 origText = get_range($selection_start, $selection_end-1)\n\
614 newText = \"/*\\n\" replace_in_string(get_range(start, end), \\\n\
615 \"^\", \" * \", \"regex\") \"\\n */\\n\"\n\
616 replace_selection(newText)\n\
617 select(start, start + length(newText))\n\
618 }\n\
619 Comments>Bar Uncomment@C:::R: {\n\
620 selStart = $selection_start\n\
621 selEnd = $selection_end\n\
622 pos = search(\"/\\\\*\\\\s*\\\\n\", selStart, \"regex\")\n\
623 if (pos != selStart) return\n\
624 start = $search_end\n\
625 end = search(\"\\\\n\\\\s*\\\\*/\\\\s*\\\\n?\", selEnd, \"regex\", \"backward\")\n\
626 if (end == -1 || $search_end < selEnd) return\n\
627 newText = get_range(start, end)\n\
628 newText = replace_in_string(newText,\"^ *\\\\* ?\", \"\", \"regex\", \"copy\")\n\
629 if (get_range(selEnd, selEnd - 1) == \"\\n\") selEnd -= 1\n\
630 replace_range(selStart, selEnd, newText)\n\
631 select(selStart, selStart + length(newText))\n\
632 }\n\
633 Make C Prototypes@C@C++:::: {\n\
634 # simplistic extraction of C function prototypes, usually good enough\n\
635 if ($selection_start == -1) {\n\
636 start = 0\n\
637 end = $text_length\n\
638 } else {\n\
639 start = $selection_start\n\
640 end = $selection_end\n\
641 }\n\
642 string = get_range(start, end)\n\
643 # remove all C++ and C comments, then all blank lines in the extracted range\n\
644 string = replace_in_string(string, \"//.*$\", \"\", \"regex\", \"copy\")\n\
645 string = replace_in_string(string, \"(?n/\\\\*.*?\\\\*/)\", \"\", \"regex\", \"copy\")\n\
646 string = replace_in_string(string, \"^\\\\s*\\n\", \"\", \"regex\", \"copy\")\n\
647 nDefs = 0\n\
648 searchPos = 0\n\
649 prototypes = \"\"\n\
650 staticPrototypes = \"\"\n\
651 for (;;) {\n\
652 headerStart = search_string(string, \\\n\
653 \"^[a-zA-Z]([^;#\\\"'{}=><!/]|\\n)*\\\\)[ \\t]*\\n?[ \\t]*\\\\{\", \\\n\
654 searchPos, \"regex\")\n\
655 if (headerStart == -1)\n\
656 break\n\
657 headerEnd = search_string(string, \")\", $search_end,\"backward\") + 1\n\
658 prototype = substring(string, headerStart, headerEnd) \";\\n\"\n\
659 if (substring(string, headerStart, headerStart+6) == \"static\")\n\
660 staticPrototypes = staticPrototypes prototype\n\
661 else\n\
662 prototypes = prototypes prototype\n\
663 searchPos = headerEnd\n\
664 nDefs++\n\
665 }\n\
666 if (nDefs == 0) {\n\
667 dialog(\"No function declarations found\")\n\
668 return\n\
669 }\n\
670 new()\n\
671 focus_window(\"last\")\n\
672 replace_range(0, 0, prototypes staticPrototypes)\n\
673 }", &TempStringPrefs.macroCmds, NULL, True},
674 {"bgMenuCommands", "BGMenuCommands", PREF_ALLOC_STRING,
675 "Undo:::: {\nundo()\n}\n\
676 Redo:::: {\nredo()\n}\n\
677 Cut:::R: {\ncut_clipboard()\n}\n\
678 Copy:::R: {\ncopy_clipboard()\n}\n\
679 Paste:::: {\npaste_clipboard()\n}", &TempStringPrefs.bgMenuCmds,
680 NULL, True},
681 #ifdef VMS
682 /* The VAX compiler can't compile Java-Script's definition in highlightData.c */
683 {"highlightPatterns", "HighlightPatterns", PREF_ALLOC_STRING,
684 "Ada:Default\n\
685 Awk:Default\n\
686 C++:Default\n\
687 C:Default\n\
688 CSS:Default\n\
689 Csh:Default\n\
690 Fortran:Default\n\
691 Java:Default\n\
692 LaTeX:Default\n\
693 Lex:Default\n\
694 Makefile:Default\n\
695 Matlab:Default\n\
696 NEdit Macro:Default\n\
697 Pascal:Default\n\
698 Perl:Default\n\
699 PostScript:Default\n\
700 Python:Default\n\
701 Regex:Default\n\
702 SGML HTML:Default\n\
703 SQL:Default\n\
704 Sh Ksh Bash:Default\n\
705 Tcl:Default\n\
706 VHDL:Default\n\
707 Verilog:Default\n\
708 XML:Default\n\
709 X Resources:Default\n\
710 Yacc:Default",
711 &TempStringPrefs.highlight, NULL, True},
712 {"languageModes", "LanguageModes", PREF_ALLOC_STRING,
713 #else
714 {"highlightPatterns", "HighlightPatterns", PREF_ALLOC_STRING,
715 "Ada:Default\n\
716 Awk:Default\n\
717 C++:Default\n\
718 C:Default\n\
719 CSS:Default\n\
720 Csh:Default\n\
721 Fortran:Default\n\
722 Java:Default\n\
723 JavaScript:Default\n\
724 LaTeX:Default\n\
725 Lex:Default\n\
726 Makefile:Default\n\
727 Matlab:Default\n\
728 NEdit Macro:Default\n\
729 Pascal:Default\n\
730 Perl:Default\n\
731 PostScript:Default\n\
732 Python:Default\n\
733 Regex:Default\n\
734 SGML HTML:Default\n\
735 SQL:Default\n\
736 Sh Ksh Bash:Default\n\
737 Tcl:Default\n\
738 VHDL:Default\n\
739 Verilog:Default\n\
740 XML:Default\n\
741 X Resources:Default\n\
742 Yacc:Default",
743 &TempStringPrefs.highlight, NULL, True},
744 {"languageModes", "LanguageModes", PREF_ALLOC_STRING,
745 #endif /*VMS*/
746 #ifdef VMS
747 /* TODO: Some tests indicate that these have to be upper case, but what about
748 the PostScript pattern then? How does VMS handle caseness anyway? */
749 "Ada:.ADA .AD .ADS .ADB .A:::::::\n\
750 Awk:.AWK:::::::\n\
751 C++:.CC .HH .C .H .I .CXX .HXX .CPP::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\":\n\
752 C:.C .H::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\":\n\
753 CSS:CSS::Auto:None:::\".,/\\`'!|@#%^&*()=+{}[]\"\":;<>?~\":\n\
754 Csh:.CSH .CSHRC .TCSHRC .LOGIN .LOGOUT:\"^[ \\t]*#[ \\t]*![ \\t]*/bin/t?csh\"::::::\n\
755 Fortran:.F .F77 .FOR:::::::\n\
756 Java:.JAVA:::::::\n\
757 LaTeX:.TEX .STY .CLS .LTX .INS .CLO .FD:::::::\n\
758 Lex:.LEX:::::::\n\
759 Makefile:MAKEFILE:::None:8:8::\n\
760 Matlab:.M .OCT .SCI:::::::\n\
761 NEdit Macro:.NM .NEDITMACRO:::::::\n\
762 Pascal:.PAS .P .INT:::::::\n\
763 Perl:.PL .PM .P5:\"^[ \\t]*#[ \\t]*!.*perl\":Auto:None:::\".,/\\\\`'!$@#%^&*()-=+{}[]\"\":;<>?~|\":\n\
764 PostScript:.ps .PS .eps .EPS .epsf .epsi:\"^%!\":::::\"/%(){}[]<>\":\n\
765 Python:.PY:\"^#!.*python\":Auto:None:::\"!\"\"#$%&'()*+,-./:;<=>?@[\\\\]^`{|}~\":\n\
766 Regex:.REG .REGEX:\"\\(\\?[:#=!iInN].+\\)\":None:Continuous::::\n\
767 SGML HTML:.SGML .SGM .HTML .HTM:\"\\<[Hh][Tt][Mm][Ll]\\>\"::::::\n\
768 SQL:.SQL:::::::\n\
769 Sh Ksh Bash:.SH .BASH .KSH .PROFILE .BASHRC .BASH_LOGOUT .BASH_LOGIN .BASH_PROFILE:\"^[ \\t]*#[ \\t]*![ \\t]*/.*bin/(bash|ksh|sh|zsh)\"::::::\n\
770 Tcl:.TCL::Smart:None::::\n\
771 VHDL:.VHD .VHDL .VDL:::::::\n\
772 Verilog:.V:::::::\n\
773 XML:.XML .XSL .DTD:\"\\<(?i\\?xml|!doctype)\"::None:::\"<>/=\"\"'()+*?|\":\n\
774 X Resources:.XRESOURCES .XDEFAULTS .NEDIT .PATS NEDIT.RC:\"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults\"::::::\n\
775 Yacc:.Y::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\":",
776 #else
777 "Ada:.ada .ad .ads .adb .a:::::::\n\
778 Awk:.awk:::::::\n\
779 C++:.cc .hh .C .H .i .cxx .hxx .cpp .c++::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\":\n\
780 C:.c .h::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\":\n\
781 CSS:css::Auto:None:::\".,/\\`'!|@#%^&*()=+{}[]\"\":;<>?~\":\n\
782 Csh:.csh .cshrc .tcshrc .login .logout:\"^[ \\t]*#[ \\t]*![ \\t]*/bin/t?csh\"::::::\n\
783 Fortran:.f .f77 .for:::::::\n\
784 Java:.java:::::::\n\
785 JavaScript:.js:::::::\n\
786 LaTeX:.tex .sty .cls .ltx .ins .clo .fd:::::::\n\
787 Lex:.lex:::::::\n\
788 Makefile:Makefile makefile .gmk:::None:8:8::\n\
789 Matlab:.m .oct .sci:::::::\n\
790 NEdit Macro:.nm .neditmacro:::::::\n\
791 Pascal:.pas .p .int:::::::\n\
792 Perl:.pl .pm .p5 .PL:\"^[ \\t]*#[ \\t]*!.*perl\":Auto:None:::\".,/\\\\`'!$@#%^&*()-=+{}[]\"\":;<>?~|\":\n\
793 PostScript:.ps .eps .epsf .epsi:\"^%!\":::::\"/%(){}[]<>\":\n\
794 Python:.py:\"^#!.*python\":Auto:None:::\"!\"\"#$%&'()*+,-./:;<=>?@[\\\\]^`{|}~\":\n\
795 Regex:.reg .regex:\"\\(\\?[:#=!iInN].+\\)\":None:Continuous::::\n\
796 SGML HTML:.sgml .sgm .html .htm:\"\\<[Hh][Tt][Mm][Ll]\\>\"::::::\n\
797 SQL:.sql:::::::\n\
798 Sh Ksh Bash:.sh .bash .ksh .profile .bashrc .bash_logout .bash_login .bash_profile:\"^[ \\t]*#[ \\t]*![ \\t]*/.*bin/(bash|ksh|sh|zsh)\"::::::\n\
799 Tcl:.tcl .tk .itcl .itk::Smart:None::::\n\
800 VHDL:.vhd .vhdl .vdl:::::::\n\
801 Verilog:.v:::::::\n\
802 XML:.xml .xsl .dtd:\"\\<(?i\\?xml|!doctype)\"::None:::\"<>/=\"\"'()+*?|\":\n\
803 X Resources:.Xresources .Xdefaults .nedit .pats nedit.rc:\"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults\"::::::\n\
804 Yacc:.y::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\":",
805 #endif
806 &TempStringPrefs.language, NULL, True},
807 {"styles", "Styles", PREF_ALLOC_STRING, "Plain:black:Plain\n\
808 Comment:gray20:Italic\n\
809 Keyword:black:Bold\n\
810 Operator:dark blue:Bold\n\
811 Bracket:dark blue:Bold\n\
812 Storage Type:brown:Bold\n\
813 Storage Type1:saddle brown:Bold\n\
814 String:darkGreen:Plain\n\
815 String1:SeaGreen:Plain\n\
816 String2:darkGreen:Bold\n\
817 Preprocessor:RoyalBlue4:Plain\n\
818 Preprocessor1:blue:Plain\n\
819 Character Const:darkGreen:Plain\n\
820 Numeric Const:darkGreen:Plain\n\
821 Identifier:brown:Plain\n\
822 Identifier1:RoyalBlue4:Plain\n\
823 Identifier2:SteelBlue:Plain\n\
824 Subroutine:brown:Plain\n\
825 Subroutine1:chocolate:Plain\n\
826 Ada Attributes:plum:Bold\n\
827 Label:red:Italic\n\
828 Flag:red:Bold\n\
829 Text Comment:SteelBlue4:Italic\n\
830 Text Key:VioletRed4:Bold\n\
831 Text Key1:VioletRed4:Plain\n\
832 Text Arg:RoyalBlue4:Bold\n\
833 Text Arg1:SteelBlue4:Bold\n\
834 Text Arg2:RoyalBlue4:Plain\n\
835 Text Escape:gray30:Bold\n\
836 LaTeX Math:darkGreen:Plain\n"
837 ADD_5_2_STYLES,
838 &TempStringPrefs.styles, NULL, True},
839 {"smartIndentInit", "SmartIndentInit", PREF_ALLOC_STRING,
840 "C:Default\n\
841 C++:Default\n\
842 Python:Default\n\
843 Matlab:Default", &TempStringPrefs.smartIndent, NULL, True},
844 {"smartIndentInitCommon", "SmartIndentInitCommon", PREF_ALLOC_STRING,
845 "Default", &TempStringPrefs.smartIndentCommon, NULL, True},
846 {"autoWrap", "AutoWrap", PREF_ENUM, "Continuous",
847 &PrefData.wrapStyle, AutoWrapTypes, True},
848 {"wrapMargin", "WrapMargin", PREF_INT, "0",
849 &PrefData.wrapMargin, NULL, True},
850 {"autoIndent", "AutoIndent", PREF_ENUM, "Auto",
851 &PrefData.autoIndent, AutoIndentTypes, True},
852 {"autoSave", "AutoSave", PREF_BOOLEAN, "True",
853 &PrefData.autoSave, NULL, True},
854 {"openInTab", "OpenInTab", PREF_BOOLEAN, "True",
855 &PrefData.openInTab, NULL, True},
856 {"saveOldVersion", "SaveOldVersion", PREF_BOOLEAN, "False",
857 &PrefData.saveOldVersion, NULL, True},
858 {"showMatching", "ShowMatching", PREF_ENUM, "Delimiter",
859 &PrefData.showMatchingStyle, ShowMatchingTypes, True},
860 {"matchSyntaxBased", "MatchSyntaxBased", PREF_BOOLEAN, "True",
861 &PrefData.matchSyntaxBased, NULL, True},
862 {"highlightSyntax", "HighlightSyntax", PREF_BOOLEAN, "True",
863 &PrefData.highlightSyntax, NULL, True},
864 {"backlightChars", "BacklightChars", PREF_BOOLEAN, "False",
865 &PrefData.backlightChars, NULL, True},
866 {"backlightCharTypes", "BacklightCharTypes", PREF_ALLOC_STRING,
867 "0-8,10-31,127:red;9:#dedede;32,160-255:#f0f0f0;128-159:orange",
868 /* gray87 gray94 */
869 &PrefData.backlightCharTypes, NULL, False},
870 {"searchDialogs", "SearchDialogs", PREF_BOOLEAN, "False",
871 &PrefData.searchDlogs, NULL, True},
872 {"beepOnSearchWrap", "BeepOnSearchWrap", PREF_BOOLEAN, "False",
873 &PrefData.searchWrapBeep, NULL, True},
874 {"retainSearchDialogs", "RetainSearchDialogs", PREF_BOOLEAN, "False",
875 &PrefData.keepSearchDlogs, NULL, True},
876 {"searchWraps", "SearchWraps", PREF_BOOLEAN, "True",
877 &PrefData.searchWraps, NULL, True},
878 {"stickyCaseSenseButton", "StickyCaseSenseButton", PREF_BOOLEAN, "True",
879 &PrefData.stickyCaseSenseBtn, NULL, True},
880 #if XmVersion < 1002 /* Flashing is annoying in 1.1 versions */
881 {"repositionDialogs", "RepositionDialogs", PREF_BOOLEAN, "False",
882 &PrefData.repositionDialogs, NULL, True},
883 #else
884 {"repositionDialogs", "RepositionDialogs", PREF_BOOLEAN, "True",
885 &PrefData.repositionDialogs, NULL, True},
886 #endif
887 {"autoScroll", "AutoScroll", PREF_BOOLEAN, "False",
888 &PrefData.autoScroll, NULL, True},
889 {"autoScrollVPadding", "AutoScrollVPadding", PREF_INT, "4",
890 &PrefData.autoScrollVPadding, NULL, False},
891 {"appendLF", "AppendLF", PREF_BOOLEAN, "True",
892 &PrefData.appendLF, NULL, True},
893 {"sortOpenPrevMenu", "SortOpenPrevMenu", PREF_BOOLEAN, "True",
894 &PrefData.sortOpenPrevMenu, NULL, True},
895 {"statisticsLine", "StatisticsLine", PREF_BOOLEAN, "False",
896 &PrefData.statsLine, NULL, True},
897 {"iSearchLine", "ISearchLine", PREF_BOOLEAN, "False",
898 &PrefData.iSearchLine, NULL, True},
899 {"sortTabs", "SortTabs", PREF_BOOLEAN, "False",
900 &PrefData.sortTabs, NULL, True},
901 {"tabBar", "TabBar", PREF_BOOLEAN, "True",
902 &PrefData.tabBar, NULL, True},
903 {"tabBarHideOne", "TabBarHideOne", PREF_BOOLEAN, "True",
904 &PrefData.tabBarHideOne, NULL, True},
905 {"toolTips", "ToolTips", PREF_BOOLEAN, "True",
906 &PrefData.toolTips, NULL, True},
907 {"globalTabNavigate", "GlobalTabNavigate", PREF_BOOLEAN, "False",
908 &PrefData.globalTabNavigate, NULL, True},
909 {"lineNumbers", "LineNumbers", PREF_BOOLEAN, "False",
910 &PrefData.lineNums, NULL, True},
911 {"pathInWindowsMenu", "PathInWindowsMenu", PREF_BOOLEAN, "True",
912 &PrefData.pathInWindowsMenu, NULL, True},
913 {"warnFileMods", "WarnFileMods", PREF_BOOLEAN, "True",
914 &PrefData.warnFileMods, NULL, True},
915 {"warnRealFileMods", "WarnRealFileMods", PREF_BOOLEAN, "True",
916 &PrefData.warnRealFileMods, NULL, True},
917 {"warnExit", "WarnExit", PREF_BOOLEAN, "True",
918 &PrefData.warnExit, NULL, True},
919 {"searchMethod", "SearchMethod", PREF_ENUM, "Literal",
920 &PrefData.searchMethod, SearchMethodStrings, True},
921 #ifdef REPLACE_SCOPE
922 {"replaceDefaultScope", "ReplaceDefaultScope", PREF_ENUM, "Smart",
923 &PrefData.replaceDefScope, ReplaceDefScopeStrings, True},
924 #endif
925 {"textRows", "TextRows", PREF_INT, "24",
926 &PrefData.textRows, NULL, True},
927 {"textCols", "TextCols", PREF_INT, "80",
928 &PrefData.textCols, NULL, True},
929 {"tabDistance", "TabDistance", PREF_INT, "8",
930 &PrefData.tabDist, NULL, True},
931 {"emulateTabs", "EmulateTabs", PREF_INT, "0",
932 &PrefData.emTabDist, NULL, True},
933 {"insertTabs", "InsertTabs", PREF_BOOLEAN, "True",
934 &PrefData.insertTabs, NULL, True},
935 {"textFont", "TextFont", PREF_STRING,
936 "-*-courier-medium-r-normal--*-120-*-*-*-iso8859-1",
937 PrefData.fontString, (void *)sizeof(PrefData.fontString), True},
938 {"boldHighlightFont", "BoldHighlightFont", PREF_STRING,
939 "-*-courier-bold-r-normal--*-120-*-*-*-iso8859-1",
940 PrefData.boldFontString, (void *)sizeof(PrefData.boldFontString), True},
941 {"italicHighlightFont", "ItalicHighlightFont", PREF_STRING,
942 "-*-courier-medium-o-normal--*-120-*-*-*-iso8859-1",
943 PrefData.italicFontString,
944 (void *)sizeof(PrefData.italicFontString), True},
945 {"boldItalicHighlightFont", "BoldItalicHighlightFont", PREF_STRING,
946 "-*-courier-bold-o-normal--*-120-*-*-*-iso8859-1",
947 PrefData.boldItalicFontString,
948 (void *)sizeof(PrefData.boldItalicFontString), True},
949 {"helpFont", "HelpFont", PREF_STRING,
950 "-*-helvetica-medium-r-normal--*-120-*-*-*-iso8859-1",
951 PrefData.helpFontNames[HELP_FONT],
952 (void *)sizeof(PrefData.helpFontNames[HELP_FONT]), False},
953 {"boldHelpFont", "BoldHelpFont", PREF_STRING,
954 "-*-helvetica-bold-r-normal--*-120-*-*-*-iso8859-1",
955 PrefData.helpFontNames[BOLD_HELP_FONT],
956 (void *)sizeof(PrefData.helpFontNames[BOLD_HELP_FONT]), False},
957 {"italicHelpFont", "ItalicHelpFont", PREF_STRING,
958 "-*-helvetica-medium-o-normal--*-120-*-*-*-iso8859-1",
959 PrefData.helpFontNames[ITALIC_HELP_FONT],
960 (void *)sizeof(PrefData.helpFontNames[ITALIC_HELP_FONT]), False},
961 {"boldItalicHelpFont", "BoldItalicHelpFont", PREF_STRING,
962 "-*-helvetica-bold-o-normal--*-120-*-*-*-iso8859-1",
963 PrefData.helpFontNames[BOLD_ITALIC_HELP_FONT],
964 (void *)sizeof(PrefData.helpFontNames[BOLD_ITALIC_HELP_FONT]), False},
965 {"fixedHelpFont", "FixedHelpFont", PREF_STRING,
966 "-*-courier-medium-r-normal--*-120-*-*-*-iso8859-1",
967 PrefData.helpFontNames[FIXED_HELP_FONT],
968 (void *)sizeof(PrefData.helpFontNames[FIXED_HELP_FONT]), False},
969 {"boldFixedHelpFont", "BoldFixedHelpFont", PREF_STRING,
970 "-*-courier-bold-r-normal--*-120-*-*-*-iso8859-1",
971 PrefData.helpFontNames[BOLD_FIXED_HELP_FONT],
972 (void *)sizeof(PrefData.helpFontNames[BOLD_FIXED_HELP_FONT]), False},
973 {"italicFixedHelpFont", "ItalicFixedHelpFont", PREF_STRING,
974 "-*-courier-medium-o-normal--*-120-*-*-*-iso8859-1",
975 PrefData.helpFontNames[ITALIC_FIXED_HELP_FONT],
976 (void *)sizeof(PrefData.helpFontNames[ITALIC_FIXED_HELP_FONT]), False},
977 {"boldItalicFixedHelpFont", "BoldItalicFixedHelpFont", PREF_STRING,
978 "-*-courier-bold-o-normal--*-120-*-*-*-iso8859-1",
979 PrefData.helpFontNames[BOLD_ITALIC_FIXED_HELP_FONT],
980 (void *)sizeof(PrefData.helpFontNames[BOLD_ITALIC_FIXED_HELP_FONT]), False},
981 {"helpLinkFont", "HelpLinkFont", PREF_STRING,
982 "-*-helvetica-medium-r-normal--*-120-*-*-*-iso8859-1",
983 PrefData.helpFontNames[HELP_LINK_FONT],
984 (void *)sizeof(PrefData.helpFontNames[HELP_LINK_FONT]), False},
985 {"h1HelpFont", "H1HelpFont", PREF_STRING,
986 "-*-helvetica-bold-r-normal--*-140-*-*-*-iso8859-1",
987 PrefData.helpFontNames[H1_HELP_FONT],
988 (void *)sizeof(PrefData.helpFontNames[H1_HELP_FONT]), False},
989 {"h2HelpFont", "H2HelpFont", PREF_STRING,
990 "-*-helvetica-bold-o-normal--*-120-*-*-*-iso8859-1",
991 PrefData.helpFontNames[H2_HELP_FONT],
992 (void *)sizeof(PrefData.helpFontNames[H2_HELP_FONT]), False},
993 {"h3HelpFont", "H3HelpFont", PREF_STRING,
994 "-*-courier-bold-r-normal--*-120-*-*-*-iso8859-1",
995 PrefData.helpFontNames[H3_HELP_FONT],
996 (void *)sizeof(PrefData.helpFontNames[H3_HELP_FONT]), False},
997 {"helpLinkColor", "HelpLinkColor", PREF_STRING, "#009900",
998 PrefData.helpLinkColor,
999 (void *)sizeof(PrefData.helpLinkColor), False},
1001 {"textFgColor", "TextFgColor", PREF_STRING, NEDIT_DEFAULT_FG,
1002 PrefData.colorNames[TEXT_FG_COLOR],
1003 (void *)sizeof(PrefData.colorNames[TEXT_FG_COLOR]), True},
1004 {"textBgColor", "TextBgColor", PREF_STRING, NEDIT_DEFAULT_TEXT_BG,
1005 PrefData.colorNames[TEXT_BG_COLOR],
1006 (void *)sizeof(PrefData.colorNames[TEXT_BG_COLOR]), True},
1007 {"selectFgColor", "SelectFgColor", PREF_STRING, NEDIT_DEFAULT_SEL_FG,
1008 PrefData.colorNames[SELECT_FG_COLOR],
1009 (void *)sizeof(PrefData.colorNames[SELECT_FG_COLOR]), True},
1010 {"selectBgColor", "SelectBgColor", PREF_STRING, NEDIT_DEFAULT_SEL_BG,
1011 PrefData.colorNames[SELECT_BG_COLOR],
1012 (void *)sizeof(PrefData.colorNames[SELECT_BG_COLOR]), True},
1013 {"hiliteFgColor", "HiliteFgColor", PREF_STRING, NEDIT_DEFAULT_HI_FG,
1014 PrefData.colorNames[HILITE_FG_COLOR],
1015 (void *)sizeof(PrefData.colorNames[HILITE_FG_COLOR]), True},
1016 {"hiliteBgColor", "HiliteBgColor", PREF_STRING, NEDIT_DEFAULT_HI_BG,
1017 PrefData.colorNames[HILITE_BG_COLOR],
1018 (void *)sizeof(PrefData.colorNames[HILITE_BG_COLOR]), True},
1019 {"lineNoFgColor", "LineNoFgColor", PREF_STRING, NEDIT_DEFAULT_LINENO_FG,
1020 PrefData.colorNames[LINENO_FG_COLOR],
1021 (void *)sizeof(PrefData.colorNames[LINENO_FG_COLOR]), True},
1022 {"cursorFgColor", "CursorFgColor", PREF_STRING, NEDIT_DEFAULT_CURSOR_FG,
1023 PrefData.colorNames[CURSOR_FG_COLOR],
1024 (void *)sizeof(PrefData.colorNames[CURSOR_FG_COLOR]), True},
1025 {"tooltipBgColor", "TooltipBgColor", PREF_STRING, "LemonChiffon1",
1026 PrefData.tooltipBgColor,
1027 (void *)sizeof(PrefData.tooltipBgColor), False},
1028 {"shell", "Shell", PREF_STRING, "DEFAULT", PrefData.shell,
1029 (void*) sizeof(PrefData.shell), True},
1030 {"geometry", "Geometry", PREF_STRING, "",
1031 PrefData.geometry, (void *)sizeof(PrefData.geometry), False},
1032 {"remapDeleteKey", "RemapDeleteKey", PREF_BOOLEAN, "False",
1033 &PrefData.mapDelete, NULL, False},
1034 {"stdOpenDialog", "StdOpenDialog", PREF_BOOLEAN, "False",
1035 &PrefData.stdOpenDialog, NULL, False},
1036 {"tagFile", "TagFile", PREF_STRING,
1037 "", PrefData.tagFile, (void *)sizeof(PrefData.tagFile), False},
1038 {"wordDelimiters", "WordDelimiters", PREF_STRING,
1039 ".,/\\`'!|@#%^&*()-=+{}[]\":;<>?",
1040 PrefData.delimiters, (void *)sizeof(PrefData.delimiters), False},
1041 {"serverName", "ServerName", PREF_STRING, "", PrefData.serverName,
1042 (void *)sizeof(PrefData.serverName), False},
1043 {"maxPrevOpenFiles", "MaxPrevOpenFiles", PREF_INT, "30",
1044 &PrefData.maxPrevOpenFiles, NULL, False},
1045 {"bgMenuButton", "BGMenuButton" , PREF_STRING,
1046 "~Shift~Ctrl~Meta~Alt<Btn3Down>", PrefData.bgMenuBtn,
1047 (void *)sizeof(PrefData.bgMenuBtn), False},
1048 {"smartTags", "SmartTags", PREF_BOOLEAN, "True",
1049 &PrefData.smartTags, NULL, True},
1050 {"typingHidesPointer", "TypingHidesPointer", PREF_BOOLEAN, "False",
1051 &PrefData.typingHidesPointer, NULL, False},
1052 {"alwaysCheckRelativeTagsSpecs", "AlwaysCheckRelativeTagsSpecs",
1053 PREF_BOOLEAN, "True", &PrefData.alwaysCheckRelativeTagsSpecs, NULL, False},
1054 {"prefFileRead", "PrefFileRead", PREF_BOOLEAN, "False",
1055 &PrefData.prefFileRead, NULL, True},
1056 #ifdef SGI_CUSTOM
1057 {"shortMenus", "ShortMenus", PREF_BOOLEAN, "False", &PrefData.shortMenus,
1058 NULL, True},
1059 #endif
1060 {"findReplaceUsesSelection", "FindReplaceUsesSelection", PREF_BOOLEAN, "False",
1061 &PrefData.findReplaceUsesSelection, NULL, False},
1062 {"overrideDefaultVirtualKeyBindings", "OverrideDefaultVirtualKeyBindings",
1063 PREF_ENUM, "Auto", &PrefData.virtKeyOverride, VirtKeyOverrideModes, False},
1064 {"titleFormat", "TitleFormat", PREF_STRING, "{%c} [%s] %f (%S) - %d",
1065 PrefData.titleFormat, (void *)sizeof(PrefData.titleFormat), True},
1066 {"undoModifiesSelection", "UndoModifiesSelection", PREF_BOOLEAN,
1067 "True", &PrefData.undoModifiesSelection, NULL, False},
1068 {"focusOnRaise", "FocusOnRaise", PREF_BOOLEAN,
1069 "False", &PrefData.focusOnRaise, NULL, False},
1070 {"forceOSConversion", "ForceOSConversion", PREF_BOOLEAN, "True",
1071 &PrefData.forceOSConversion, NULL, False},
1072 {"truncSubstitution", "TruncSubstitution", PREF_ENUM, "Fail",
1073 &PrefData.truncSubstitution, TruncSubstitutionModes, False},
1074 {"honorSymlinks", "HonorSymlinks", PREF_BOOLEAN, "True",
1075 &PrefData.honorSymlinks, NULL, False}
1078 static XrmOptionDescRec OpTable[] = {
1079 {"-wrap", ".autoWrap", XrmoptionNoArg, (caddr_t)"Continuous"},
1080 {"-nowrap", ".autoWrap", XrmoptionNoArg, (caddr_t)"None"},
1081 {"-autowrap", ".autoWrap", XrmoptionNoArg, (caddr_t)"Newline"},
1082 {"-noautowrap", ".autoWrap", XrmoptionNoArg, (caddr_t)"None"},
1083 {"-autoindent", ".autoIndent", XrmoptionNoArg, (caddr_t)"Auto"},
1084 {"-noautoindent", ".autoIndent", XrmoptionNoArg, (caddr_t)"False"},
1085 {"-autosave", ".autoSave", XrmoptionNoArg, (caddr_t)"True"},
1086 {"-noautosave", ".autoSave", XrmoptionNoArg, (caddr_t)"False"},
1087 {"-rows", ".textRows", XrmoptionSepArg, (caddr_t)NULL},
1088 {"-columns", ".textCols", XrmoptionSepArg, (caddr_t)NULL},
1089 {"-tabs", ".tabDistance", XrmoptionSepArg, (caddr_t)NULL},
1090 {"-font", ".textFont", XrmoptionSepArg, (caddr_t)NULL},
1091 {"-fn", ".textFont", XrmoptionSepArg, (caddr_t)NULL},
1092 {"-svrname", ".serverName", XrmoptionSepArg, (caddr_t)NULL},
1095 static const char HeaderText[] = "\
1096 ! Preferences file for NEdit\n\
1097 ! (User settings in X \"application defaults\" format)\n\
1098 !\n\
1099 ! This file is overwritten by the \"Save Defaults...\" command in NEdit\n\
1100 ! and serves only the interactively settable options presented in the NEdit\n\
1101 ! \"Preferences\" menu. To modify other options, such as key bindings, use\n\
1102 ! the .Xdefaults file in your home directory (or the X resource\n\
1103 ! specification method appropriate to your system). The contents of this\n\
1104 ! file can be moved into an X resource file, but since resources in this file\n\
1105 ! override their corresponding X resources, either this file should be \n\
1106 ! deleted or individual resource lines in the file should be deleted for the\n\
1107 ! moved lines to take effect.\n";
1109 /* Module-global variable set when any preference changes (for asking the
1110 user about re-saving on exit) */
1111 static int PrefsHaveChanged = False;
1113 /* Module-global variable set when user uses -import to load additional
1114 preferences on top of the defaults. Contains name of file loaded */
1115 static char *ImportedFile = NULL;
1117 /* Module-global variables to support Initial Window Size... dialog */
1118 static int DoneWithSizeDialog;
1119 static Widget RowText, ColText;
1121 /* Module-global variables for Tabs dialog */
1122 static int DoneWithTabsDialog;
1123 static WindowInfo *TabsDialogForWindow;
1124 static Widget TabDistText, EmTabText, EmTabToggle, UseTabsToggle, EmTabLabel;
1126 /* Module-global variables for Wrap Margin dialog */
1127 static int DoneWithWrapDialog;
1128 static WindowInfo *WrapDialogForWindow;
1129 static Widget WrapText, WrapTextLabel, WrapWindowToggle;
1131 /* Module-global variables for shell selection dialog */
1132 static int DoneWithShellSelDialog = False;
1134 static void translatePrefFormats(int convertOld, int fileVer);
1135 static void setIntPref(int *prefDataField, int newValue);
1136 static void setStringPref(char *prefDataField, const char *newValue);
1137 static void sizeOKCB(Widget w, XtPointer clientData, XtPointer callData);
1138 static void setStringAllocPref(char **pprefDataField, char *newValue);
1139 static void sizeCancelCB(Widget w, XtPointer clientData, XtPointer callData);
1140 static void tabsOKCB(Widget w, XtPointer clientData, XtPointer callData);
1141 static void tabsCancelCB(Widget w, XtPointer clientData, XtPointer callData);
1142 static void tabsHelpCB(Widget w, XtPointer clientData, XtPointer callData);
1143 static void emTabsCB(Widget w, XtPointer clientData, XtPointer callData);
1144 static void wrapOKCB(Widget w, XtPointer clientData, XtPointer callData);
1145 static void wrapCancelCB(Widget w, XtPointer clientData, XtPointer callData);
1146 static void wrapWindowCB(Widget w, XtPointer clientData, XtPointer callData);
1147 static void shellSelOKCB(Widget widget, XtPointer clientData,
1148 XtPointer callData);
1149 static void shellSelCancelCB(Widget widgget, XtPointer clientData,
1150 XtPointer callData);
1151 static void reapplyLanguageMode(WindowInfo *window, int mode,int forceDefaults);
1153 static void fillFromPrimaryCB(Widget w, XtPointer clientData,
1154 XtPointer callData);
1155 static int checkFontStatus(fontDialog *fd, Widget fontTextFieldW);
1156 static int showFontStatus(fontDialog *fd, Widget fontTextFieldW,
1157 Widget errorLabelW);
1158 static void primaryModifiedCB(Widget w, XtPointer clientData,
1159 XtPointer callData);
1160 static void italicModifiedCB(Widget w, XtPointer clientData,
1161 XtPointer callData);
1162 static void boldModifiedCB(Widget w, XtPointer clientData, XtPointer callData);
1163 static void boldItalicModifiedCB(Widget w, XtPointer clientData,
1164 XtPointer callData);
1165 static void primaryBrowseCB(Widget w, XtPointer clientData, XtPointer callData);
1166 static void italicBrowseCB(Widget w, XtPointer clientData, XtPointer callData);
1167 static void boldBrowseCB(Widget w, XtPointer clientData, XtPointer callData);
1168 static void boldItalicBrowseCB(Widget w, XtPointer clientData,
1169 XtPointer callData);
1170 static void browseFont(Widget parent, Widget fontTextW);
1171 static void fontDestroyCB(Widget w, XtPointer clientData, XtPointer callData);
1172 static void fontOkCB(Widget w, XtPointer clientData, XtPointer callData);
1173 static void fontApplyCB(Widget w, XtPointer clientData, XtPointer callData);
1174 static void fontCancelCB(Widget w, XtPointer clientData, XtPointer callData);
1175 static void updateFonts(fontDialog *fd);
1177 static Boolean checkColorStatus(colorDialog *cd, Widget colorFieldW);
1178 static int verifyAllColors (colorDialog *cd);
1179 static void showColorStatus (colorDialog *cd, Widget colorFieldW,
1180 Widget errorLabelW);
1181 static void updateColors(colorDialog *cd);
1182 static void colorDestroyCB(Widget w, XtPointer clientData, XtPointer callData);
1183 static void colorOkCB (Widget w, XtPointer clientData, XtPointer callData);
1184 static void colorApplyCB (Widget w, XtPointer clientData, XtPointer callData);
1185 static void colorCloseCB(Widget w, XtPointer clientData, XtPointer callData);
1186 static void textFgModifiedCB (Widget w, XtPointer clientData,
1187 XtPointer callData);
1188 static void textBgModifiedCB (Widget w, XtPointer clientData,
1189 XtPointer callData);
1190 static void selectFgModifiedCB(Widget w, XtPointer clientData,
1191 XtPointer callData);
1192 static void selectBgModifiedCB(Widget w, XtPointer clientData,
1193 XtPointer callData);
1194 static void hiliteFgModifiedCB(Widget w, XtPointer clientData,
1195 XtPointer callData);
1196 static void hiliteBgModifiedCB(Widget w, XtPointer clientData,
1197 XtPointer callData);
1198 static void lineNoFgModifiedCB(Widget w, XtPointer clientData,
1199 XtPointer callData);
1200 static void cursorFgModifiedCB(Widget w, XtPointer clientData,
1201 XtPointer callData);
1203 static int matchLanguageMode(WindowInfo *window);
1204 static int loadLanguageModesString(char *inString, int fileVer);
1205 static char *writeLanguageModesString(void);
1206 static char *createExtString(char **extensions, int nExtensions);
1207 static char **readExtensionList(char **inPtr, int *nExtensions);
1208 static void updateLanguageModeSubmenu(WindowInfo *window);
1209 static void setLangModeCB(Widget w, XtPointer clientData, XtPointer callData);
1210 static int modeError(languageModeRec *lm, const char *stringStart,
1211 const char *stoppedAt, const char *message);
1212 static void lmDestroyCB(Widget w, XtPointer clientData, XtPointer callData);
1213 static void lmOkCB(Widget w, XtPointer clientData, XtPointer callData);
1214 static void lmApplyCB(Widget w, XtPointer clientData, XtPointer callData);
1215 static void lmCloseCB(Widget w, XtPointer clientData, XtPointer callData);
1216 static int lmDeleteConfirmCB(int itemIndex, void *cbArg);
1217 static int updateLMList(void);
1218 static languageModeRec *copyLanguageModeRec(languageModeRec *lm);
1219 static void *lmGetDisplayedCB(void *oldItem, int explicitRequest, int *abort,
1220 void *cbArg);
1221 static void lmSetDisplayedCB(void *item, void *cbArg);
1222 static languageModeRec *readLMDialogFields(int silent);
1223 static void lmFreeItemCB(void *item);
1224 static void freeLanguageModeRec(languageModeRec *lm);
1225 static int lmDialogEmpty(void);
1226 static void updatePatternsTo5dot1(void);
1227 static void updatePatternsTo5dot2(void);
1228 static void updatePatternsTo5dot3(void);
1229 static void updatePatternsTo5dot4(void);
1230 static void updateShellCmdsTo5dot3(void);
1231 static void updateShellCmdsTo5dot4(void);
1232 static void updateMacroCmdsTo5dot5(void);
1233 static void updatePatternsTo5dot6(void);
1234 static void updateMacroCmdsTo5dot6(void);
1235 static void migrateColorResources(XrmDatabase prefDB, XrmDatabase appDB);
1236 static void spliceString(char **intoString, const char *insertString, const char *atExpr);
1237 static int regexFind(const char *inString, const char *expr);
1238 static int regexReplace(char **inString, const char *expr,
1239 const char *replaceWith);
1240 static int caseFind(const char *inString, const char *expr);
1241 static int caseReplace(char **inString, const char *expr,
1242 const char *replaceWith, int replaceLen);
1243 static int stringReplace(char **inString, const char *expr,
1244 const char *replaceWith, int searchType,
1245 int replaceLen);
1246 static int replaceMacroIfUnchanged(const char* oldText, const char* newStart,
1247 const char* newEnd);
1248 static const char* getDefaultShell(void);
1251 #ifdef SGI_CUSTOM
1252 static int shortPrefToDefault(Widget parent, const char *settingName, int *setDefault);
1253 #endif
1255 XrmDatabase CreateNEditPrefDB(int *argcInOut, char **argvInOut)
1257 return CreatePreferencesDatabase(GetRCFileName(NEDIT_RC), APP_NAME,
1258 OpTable, XtNumber(OpTable), (unsigned int *)argcInOut, argvInOut);
1261 void RestoreNEditPrefs(XrmDatabase prefDB, XrmDatabase appDB)
1263 int requiresConversion;
1264 int major; /* The integral part of version number */
1265 int minor; /* fractional part of version number */
1266 int fileVer = 0; /* Both combined into an integer */
1267 int nparsed;
1269 /* Load preferences */
1270 RestorePreferences(prefDB, appDB, APP_NAME,
1271 APP_CLASS, PrefDescrip, XtNumber(PrefDescrip));
1273 /* If the preferences file was written by an older version of NEdit,
1274 warn the user that it will be converted. */
1275 requiresConversion = PrefData.prefFileRead &&
1276 PrefData.fileVersion[0] == '\0';
1277 if (requiresConversion) {
1278 updatePatternsTo5dot1();
1281 if (PrefData.prefFileRead) {
1282 if (PrefData.fileVersion[0] == '\0') {
1283 fileVer = 0; /* Pre-5.1 */
1285 else {
1286 /* Note: do not change the format of this. Older executables
1287 need to read this field for forward compatability. */
1288 nparsed = sscanf(PrefData.fileVersion, "%d.%d", &major, &minor);
1289 if (nparsed >= 2) {
1290 /* Use OSF-style numbering scheme */
1291 fileVer = major * 1000 + minor;
1296 if (PrefData.prefFileRead && fileVer < 5002) {
1297 updatePatternsTo5dot2();
1300 if (PrefData.prefFileRead && fileVer < 5003) {
1301 updateShellCmdsTo5dot3();
1302 updatePatternsTo5dot3();
1305 /* Note that we don't care about unreleased file versions. Anyone
1306 who is running a CVS or alpha version of NEdit is resposnbile
1307 for managing the preferences file themselves. Otherwise, it
1308 gets impossible to track the number of "in-between" file formats.
1309 We only do auto-upgrading for a real release. */
1311 if (PrefData.prefFileRead && (fileVer < 5004)) {
1312 migrateColorResources(prefDB, appDB);
1313 updateShellCmdsTo5dot4();
1314 updatePatternsTo5dot4();
1316 if (PrefData.prefFileRead && (fileVer < 5005)) {
1317 updateMacroCmdsTo5dot5();
1319 if (PrefData.prefFileRead && (fileVer < 5006)) {
1320 fprintf(stderr, "NEdit: Converting .nedit file to 5.6 version.\n"
1321 " To keep, use Preferences -> Save Defaults\n");
1322 updateMacroCmdsTo5dot6();
1323 updatePatternsTo5dot6();
1325 /* Migrate colors if there's no config file yet */
1326 if (!PrefData.prefFileRead) {
1327 migrateColorResources(prefDB, appDB);
1330 /* Do further parsing on resource types which RestorePreferences does
1331 not understand and reads as strings, to put them in the final form
1332 in which nedit stores and uses. If the preferences file was
1333 written by an older version of NEdit, update regular expressions in
1334 highlight patterns to quote braces and use & instead of \0 */
1335 translatePrefFormats(requiresConversion, fileVer);
1339 ** Many of of NEdit's preferences are much more complicated than just simple
1340 ** integers or strings. These are read as strings, but must be parsed and
1341 ** translated into something meaningful. This routine does the translation,
1342 ** and, in most cases, frees the original string, which is no longer useful.
1344 ** In addition this function covers settings that, while simple, require
1345 ** additional steps before they can be published.
1347 ** The argument convertOld attempts a conversion from pre 5.1 format .nedit
1348 ** files (which means patterns and macros may contain regular expressions
1349 ** which are of the older syntax where braces were not quoted, and \0 was a
1350 ** legal substitution character). Macros, so far can not be automatically
1351 ** converted, unfortunately.
1353 static void translatePrefFormats(int convertOld, int fileVer)
1355 XFontStruct *font;
1357 /* Parse the strings which represent types which are not decoded by
1358 the standard resource manager routines */
1359 #ifndef VMS
1360 if (TempStringPrefs.shellCmds != NULL) {
1361 LoadShellCmdsString(TempStringPrefs.shellCmds);
1362 XtFree(TempStringPrefs.shellCmds);
1363 TempStringPrefs.shellCmds = NULL;
1365 #endif /* VMS */
1366 if (TempStringPrefs.macroCmds != NULL) {
1367 LoadMacroCmdsString(TempStringPrefs.macroCmds);
1368 XtFree(TempStringPrefs.macroCmds);
1369 TempStringPrefs.macroCmds = NULL;
1371 if (TempStringPrefs.bgMenuCmds != NULL) {
1372 LoadBGMenuCmdsString(TempStringPrefs.bgMenuCmds);
1373 XtFree(TempStringPrefs.bgMenuCmds);
1374 TempStringPrefs.bgMenuCmds = NULL;
1376 if (TempStringPrefs.highlight != NULL) {
1377 LoadHighlightString(TempStringPrefs.highlight, convertOld);
1378 XtFree(TempStringPrefs.highlight);
1379 TempStringPrefs.highlight = NULL;
1381 if (TempStringPrefs.styles != NULL) {
1382 LoadStylesString(TempStringPrefs.styles);
1383 XtFree(TempStringPrefs.styles);
1384 TempStringPrefs.styles = NULL;
1386 if (TempStringPrefs.language != NULL) {
1387 loadLanguageModesString(TempStringPrefs.language, fileVer);
1388 XtFree(TempStringPrefs.language);
1389 TempStringPrefs.language = NULL;
1391 if (TempStringPrefs.smartIndent != NULL) {
1392 LoadSmartIndentString(TempStringPrefs.smartIndent);
1393 XtFree(TempStringPrefs.smartIndent);
1394 TempStringPrefs.smartIndent = NULL;
1396 if (TempStringPrefs.smartIndentCommon != NULL) {
1397 LoadSmartIndentCommonString(TempStringPrefs.smartIndentCommon);
1398 XtFree(TempStringPrefs.smartIndentCommon);
1399 TempStringPrefs.smartIndentCommon = NULL;
1402 /* translate the font names into fontLists suitable for the text widget */
1403 font = XLoadQueryFont(TheDisplay, PrefData.fontString);
1404 PrefData.fontList = font==NULL ? NULL :
1405 XmFontListCreate(font, XmSTRING_DEFAULT_CHARSET);
1406 PrefData.boldFontStruct = XLoadQueryFont(TheDisplay,
1407 PrefData.boldFontString);
1408 PrefData.italicFontStruct = XLoadQueryFont(TheDisplay,
1409 PrefData.italicFontString);
1410 PrefData.boldItalicFontStruct = XLoadQueryFont(TheDisplay,
1411 PrefData.boldItalicFontString);
1414 ** The default set for the comand shell in PrefDescrip ("DEFAULT") is
1415 ** only a place-holder, the actual default is the user's login shell
1416 ** (or whatever is implemented in getDefaultShell()). We put the login
1417 ** shell's name in PrefData here.
1419 if (0 == strcmp(PrefData.shell, "DEFAULT")) {
1420 strncpy(PrefData.shell, getDefaultShell(), MAXPATHLEN);
1421 PrefData.shell[MAXPATHLEN] = '\0';
1424 /* For compatability with older (4.0.3 and before) versions, the autoWrap
1425 and autoIndent resources can accept values of True and False. Translate
1426 them into acceptable wrap and indent styles */
1427 if (PrefData.wrapStyle == 3) PrefData.wrapStyle = CONTINUOUS_WRAP;
1428 if (PrefData.wrapStyle == 4) PrefData.wrapStyle = NO_WRAP;
1429 if (PrefData.autoIndent == 3) PrefData.autoIndent = AUTO_INDENT;
1430 if (PrefData.autoIndent == 4) PrefData.autoIndent = NO_AUTO_INDENT;
1432 /* setup language mode dependent info of user menus (to increase
1433 performance when switching between documents of different
1434 language modes) */
1435 SetupUserMenuInfo();
1438 void SaveNEditPrefs(Widget parent, int quietly)
1440 const char* prefFileName = GetRCFileName(NEDIT_RC);
1441 if (prefFileName == NULL)
1443 /* GetRCFileName() might return NULL if an error occurs during
1444 creation of the preference file directory. */
1445 DialogF(DF_WARN, parent, 1, "Error saving Preferences",
1446 "Unable to save preferences: Cannot determine filename.",
1447 "OK");
1448 return;
1451 if (!quietly) {
1452 if (DialogF(DF_INF, parent, 2, "Save Preferences",
1453 ImportedFile == NULL ?
1454 "Default preferences will be saved in the file:\n"
1455 "%s\n"
1456 "NEdit automatically loads this file\n"
1457 "each time it is started." :
1458 "Default preferences will be saved in the file:\n"
1459 "%s\n"
1460 "SAVING WILL INCORPORATE SETTINGS\n"
1461 "FROM FILE: %s", "OK", "Cancel",
1462 prefFileName, ImportedFile) == 2) {
1463 return;
1467 /* Write the more dynamic settings into TempStringPrefs.
1468 These locations are set in PrefDescrip, so this is where
1469 SavePreferences() will look for them. */
1470 #ifndef VMS
1471 TempStringPrefs.shellCmds = WriteShellCmdsString();
1472 #endif /* VMS */
1473 TempStringPrefs.macroCmds = WriteMacroCmdsString();
1474 TempStringPrefs.bgMenuCmds = WriteBGMenuCmdsString();
1475 TempStringPrefs.highlight = WriteHighlightString();
1476 TempStringPrefs.language = writeLanguageModesString();
1477 TempStringPrefs.styles = WriteStylesString();
1478 TempStringPrefs.smartIndent = WriteSmartIndentString();
1479 TempStringPrefs.smartIndentCommon = WriteSmartIndentCommonString();
1480 strcpy(PrefData.fileVersion, PREF_FILE_VERSION);
1482 if (!SavePreferences(XtDisplay(parent), prefFileName, HeaderText,
1483 PrefDescrip, XtNumber(PrefDescrip)))
1485 DialogF(DF_WARN, parent, 1, "Save Preferences",
1486 "Unable to save preferences in %s", "OK", prefFileName);
1489 #ifndef VMS
1490 XtFree(TempStringPrefs.shellCmds);
1491 #endif /* VMS */
1492 XtFree(TempStringPrefs.macroCmds);
1493 XtFree(TempStringPrefs.bgMenuCmds);
1494 XtFree(TempStringPrefs.highlight);
1495 XtFree(TempStringPrefs.language);
1496 XtFree(TempStringPrefs.styles);
1497 XtFree(TempStringPrefs.smartIndent);
1498 XtFree(TempStringPrefs.smartIndentCommon);
1500 PrefsHaveChanged = False;
1504 ** Load an additional preferences file on top of the existing preferences
1505 ** derived from defaults, the .nedit file, and X resources.
1507 void ImportPrefFile(const char *filename, int convertOld)
1509 XrmDatabase db;
1510 char *fileString;
1512 fileString = ReadAnyTextFile(filename, False);
1513 if (fileString != NULL){
1514 db = XrmGetStringDatabase(fileString);
1515 XtFree(fileString);
1516 OverlayPreferences(db, APP_NAME, APP_CLASS, PrefDescrip,
1517 XtNumber(PrefDescrip));
1518 translatePrefFormats(convertOld, -1);
1519 ImportedFile = XtNewString(filename);
1520 } else
1522 fprintf(stderr, "Could not read additional preferences file: %s\n",
1523 filename);
1527 void SetPrefOpenInTab(int state)
1529 WindowInfo *w = WindowList;
1530 setIntPref(&PrefData.openInTab, state);
1531 for(; w != NULL; w = w->next)
1532 UpdateNewOppositeMenu(w, state);
1535 int GetPrefOpenInTab(void)
1537 return PrefData.openInTab;
1540 void SetPrefWrap(int state)
1542 setIntPref(&PrefData.wrapStyle, state);
1545 int GetPrefWrap(int langMode)
1547 if (langMode == PLAIN_LANGUAGE_MODE ||
1548 LanguageModes[langMode]->wrapStyle == DEFAULT_WRAP)
1549 return PrefData.wrapStyle;
1550 return LanguageModes[langMode]->wrapStyle;
1553 void SetPrefWrapMargin(int margin)
1555 setIntPref(&PrefData.wrapMargin, margin);
1558 int GetPrefWrapMargin(void)
1560 return PrefData.wrapMargin;
1563 void SetPrefSearch(int searchType)
1565 setIntPref(&PrefData.searchMethod, searchType);
1568 int GetPrefSearch(void)
1570 return PrefData.searchMethod;
1573 #ifdef REPLACE_SCOPE
1574 void SetPrefReplaceDefScope(int scope)
1576 setIntPref(&PrefData.replaceDefScope, scope);
1579 int GetPrefReplaceDefScope(void)
1581 return PrefData.replaceDefScope;
1583 #endif
1585 void SetPrefAutoIndent(int state)
1587 setIntPref(&PrefData.autoIndent, state);
1590 int GetPrefAutoIndent(int langMode)
1592 if (langMode == PLAIN_LANGUAGE_MODE ||
1593 LanguageModes[langMode]->indentStyle == DEFAULT_INDENT)
1594 return PrefData.autoIndent;
1595 return LanguageModes[langMode]->indentStyle;
1598 void SetPrefAutoSave(int state)
1600 setIntPref(&PrefData.autoSave, state);
1603 int GetPrefAutoSave(void)
1605 return PrefData.autoSave;
1608 void SetPrefSaveOldVersion(int state)
1610 setIntPref(&PrefData.saveOldVersion, state);
1613 int GetPrefSaveOldVersion(void)
1615 return PrefData.saveOldVersion;
1618 void SetPrefSearchDlogs(int state)
1620 setIntPref(&PrefData.searchDlogs, state);
1623 int GetPrefSearchDlogs(void)
1625 return PrefData.searchDlogs;
1628 void SetPrefBeepOnSearchWrap(int state)
1630 setIntPref(&PrefData.searchWrapBeep, state);
1633 int GetPrefBeepOnSearchWrap(void)
1635 return PrefData.searchWrapBeep;
1638 void SetPrefKeepSearchDlogs(int state)
1640 setIntPref(&PrefData.keepSearchDlogs, state);
1643 int GetPrefKeepSearchDlogs(void)
1645 return PrefData.keepSearchDlogs;
1648 void SetPrefSearchWraps(int state)
1650 setIntPref(&PrefData.searchWraps, state);
1653 int GetPrefStickyCaseSenseBtn(void)
1655 return PrefData.stickyCaseSenseBtn;
1658 int GetPrefSearchWraps(void)
1660 return PrefData.searchWraps;
1663 void SetPrefStatsLine(int state)
1665 setIntPref(&PrefData.statsLine, state);
1668 int GetPrefStatsLine(void)
1670 return PrefData.statsLine;
1673 void SetPrefISearchLine(int state)
1675 setIntPref(&PrefData.iSearchLine, state);
1678 int GetPrefISearchLine(void)
1680 return PrefData.iSearchLine;
1683 void SetPrefSortTabs(int state)
1685 setIntPref(&PrefData.sortTabs, state);
1688 int GetPrefSortTabs(void)
1690 return PrefData.sortTabs;
1693 void SetPrefTabBar(int state)
1695 setIntPref(&PrefData.tabBar, state);
1698 int GetPrefTabBar(void)
1700 return PrefData.tabBar;
1703 void SetPrefTabBarHideOne(int state)
1705 setIntPref(&PrefData.tabBarHideOne, state);
1708 int GetPrefTabBarHideOne(void)
1710 return PrefData.tabBarHideOne;
1713 void SetPrefGlobalTabNavigate(int state)
1715 setIntPref(&PrefData.globalTabNavigate, state);
1718 int GetPrefGlobalTabNavigate(void)
1720 return PrefData.globalTabNavigate;
1723 void SetPrefToolTips(int state)
1725 setIntPref(&PrefData.toolTips, state);
1728 int GetPrefToolTips(void)
1730 return PrefData.toolTips;
1733 void SetPrefLineNums(int state)
1735 setIntPref(&PrefData.lineNums, state);
1738 int GetPrefLineNums(void)
1740 return PrefData.lineNums;
1743 void SetPrefShowPathInWindowsMenu(int state)
1745 setIntPref(&PrefData.pathInWindowsMenu, state);
1748 int GetPrefShowPathInWindowsMenu(void)
1750 return PrefData.pathInWindowsMenu;
1753 void SetPrefWarnFileMods(int state)
1755 setIntPref(&PrefData.warnFileMods, state);
1758 int GetPrefWarnFileMods(void)
1760 return PrefData.warnFileMods;
1763 void SetPrefWarnRealFileMods(int state)
1765 setIntPref(&PrefData.warnRealFileMods, state);
1768 int GetPrefWarnRealFileMods(void)
1770 return PrefData.warnRealFileMods;
1773 void SetPrefWarnExit(int state)
1775 setIntPref(&PrefData.warnExit, state);
1778 int GetPrefWarnExit(void)
1780 return PrefData.warnExit;
1783 void SetPrefv(int state)
1785 setIntPref(&PrefData.findReplaceUsesSelection, state);
1788 int GetPrefFindReplaceUsesSelection(void)
1790 return PrefData.findReplaceUsesSelection;
1793 int GetPrefMapDelete(void)
1795 return PrefData.mapDelete;
1798 int GetPrefStdOpenDialog(void)
1800 return PrefData.stdOpenDialog;
1803 void SetPrefRows(int nRows)
1805 setIntPref(&PrefData.textRows, nRows);
1808 int GetPrefRows(void)
1810 return PrefData.textRows;
1813 void SetPrefCols(int nCols)
1815 setIntPref(&PrefData.textCols, nCols);
1818 int GetPrefCols(void)
1820 return PrefData.textCols;
1823 void SetPrefTabDist(int tabDist)
1825 setIntPref(&PrefData.tabDist, tabDist);
1828 int GetPrefTabDist(int langMode)
1830 int tabDist;
1831 if (langMode == PLAIN_LANGUAGE_MODE ||
1832 LanguageModes[langMode]->tabDist == DEFAULT_TAB_DIST) {
1833 tabDist = PrefData.tabDist;
1834 } else {
1835 tabDist = LanguageModes[langMode]->tabDist;
1837 /* Make sure that the tab distance is in range (garbage may have
1838 been entered via the command line or the X resources, causing
1839 errors later on, like division by zero). */
1840 if (tabDist <= 0) return 1;
1841 if (tabDist > MAX_EXP_CHAR_LEN) return MAX_EXP_CHAR_LEN;
1842 return tabDist;
1845 void SetPrefEmTabDist(int tabDist)
1847 setIntPref(&PrefData.emTabDist, tabDist);
1850 int GetPrefEmTabDist(int langMode)
1852 if (langMode == PLAIN_LANGUAGE_MODE ||
1853 LanguageModes[langMode]->emTabDist == DEFAULT_EM_TAB_DIST)
1854 return PrefData.emTabDist;
1855 return LanguageModes[langMode]->emTabDist;
1858 void SetPrefInsertTabs(int state)
1860 setIntPref(&PrefData.insertTabs, state);
1863 int GetPrefInsertTabs(void)
1865 return PrefData.insertTabs;
1868 void SetPrefShowMatching(int state)
1870 setIntPref(&PrefData.showMatchingStyle, state);
1873 int GetPrefShowMatching(void)
1876 * For backwards compatibility with pre-5.2 versions, the boolean
1877 * False/True matching behavior is converted to NO_FLASH/FLASH_DELIMIT.
1879 if (PrefData.showMatchingStyle >= N_SHOW_MATCHING_STYLES)
1880 PrefData.showMatchingStyle -= N_SHOW_MATCHING_STYLES;
1881 return PrefData.showMatchingStyle;
1884 void SetPrefMatchSyntaxBased(int state)
1886 setIntPref(&PrefData.matchSyntaxBased, state);
1889 int GetPrefMatchSyntaxBased(void)
1891 return PrefData.matchSyntaxBased;
1894 void SetPrefHighlightSyntax(Boolean state)
1896 setIntPref(&PrefData.highlightSyntax, state);
1899 Boolean GetPrefHighlightSyntax(void)
1901 return PrefData.highlightSyntax;
1904 void SetPrefBacklightChars(int state)
1906 setIntPref(&PrefData.backlightChars, state);
1909 int GetPrefBacklightChars(void)
1911 return PrefData.backlightChars;
1914 void SetPrefBacklightCharTypes(char *types)
1916 setStringAllocPref(&PrefData.backlightCharTypes, types);
1919 char *GetPrefBacklightCharTypes(void)
1921 return PrefData.backlightCharTypes;
1924 void SetPrefRepositionDialogs(int state)
1926 setIntPref(&PrefData.repositionDialogs, state);
1929 int GetPrefRepositionDialogs(void)
1931 return PrefData.repositionDialogs;
1934 void SetPrefAutoScroll(int state)
1936 WindowInfo *w = WindowList;
1937 int margin = state ? PrefData.autoScrollVPadding : 0;
1939 setIntPref(&PrefData.autoScroll, state);
1940 for(w = WindowList; w != NULL; w = w->next)
1941 SetAutoScroll(w, margin);
1944 int GetPrefAutoScroll(void)
1946 return PrefData.autoScroll;
1949 int GetVerticalAutoScroll(void)
1951 return PrefData.autoScroll ? PrefData.autoScrollVPadding : 0;
1954 void SetPrefAppendLF(int state)
1956 setIntPref(&PrefData.appendLF, state);
1959 int GetPrefAppendLF(void)
1961 return PrefData.appendLF;
1964 void SetPrefSortOpenPrevMenu(int state)
1966 setIntPref(&PrefData.sortOpenPrevMenu, state);
1969 int GetPrefSortOpenPrevMenu(void)
1971 return PrefData.sortOpenPrevMenu;
1974 char *GetPrefTagFile(void)
1976 return PrefData.tagFile;
1979 void SetPrefSmartTags(int state)
1981 setIntPref(&PrefData.smartTags, state);
1984 int GetPrefSmartTags(void)
1986 return PrefData.smartTags;
1989 int GetPrefAlwaysCheckRelTagsSpecs(void)
1991 return PrefData.alwaysCheckRelativeTagsSpecs;
1994 char *GetPrefDelimiters(void)
1996 return PrefData.delimiters;
1999 char *GetPrefColorName(int index)
2001 return PrefData.colorNames[index];
2004 void SetPrefColorName(int index, const char *name)
2006 setStringPref(PrefData.colorNames[index], name);
2010 ** Set the font preferences using the font name (the fontList is generated
2011 ** in this call). Note that this leaks memory and server resources each
2012 ** time the default font is re-set. See note on SetFontByName in window.c
2013 ** for more information.
2015 void SetPrefFont(char *fontName)
2017 XFontStruct *font;
2019 setStringPref(PrefData.fontString, fontName);
2020 font = XLoadQueryFont(TheDisplay, fontName);
2021 PrefData.fontList = font==NULL ? NULL :
2022 XmFontListCreate(font, XmSTRING_DEFAULT_CHARSET);
2025 void SetPrefBoldFont(char *fontName)
2027 setStringPref(PrefData.boldFontString, fontName);
2028 PrefData.boldFontStruct = XLoadQueryFont(TheDisplay, fontName);
2031 void SetPrefItalicFont(char *fontName)
2033 setStringPref(PrefData.italicFontString, fontName);
2034 PrefData.italicFontStruct = XLoadQueryFont(TheDisplay, fontName);
2036 void SetPrefBoldItalicFont(char *fontName)
2038 setStringPref(PrefData.boldItalicFontString, fontName);
2039 PrefData.boldItalicFontStruct = XLoadQueryFont(TheDisplay, fontName);
2042 char *GetPrefFontName(void)
2044 return PrefData.fontString;
2047 char *GetPrefBoldFontName(void)
2049 return PrefData.boldFontString;
2052 char *GetPrefItalicFontName(void)
2054 return PrefData.italicFontString;
2057 char *GetPrefBoldItalicFontName(void)
2059 return PrefData.boldItalicFontString;
2062 XmFontList GetPrefFontList(void)
2064 return PrefData.fontList;
2067 XFontStruct *GetPrefBoldFont(void)
2069 return PrefData.boldFontStruct;
2072 XFontStruct *GetPrefItalicFont(void)
2074 return PrefData.italicFontStruct;
2077 XFontStruct *GetPrefBoldItalicFont(void)
2079 return PrefData.boldItalicFontStruct;
2082 char *GetPrefHelpFontName(int index)
2084 return PrefData.helpFontNames[index];
2087 char *GetPrefHelpLinkColor(void)
2089 return PrefData.helpLinkColor;
2092 char *GetPrefTooltipBgColor(void)
2094 return PrefData.tooltipBgColor;
2097 void SetPrefShell(const char *shell)
2099 setStringPref(PrefData.shell, shell);
2102 const char* GetPrefShell(void)
2104 return PrefData.shell;
2107 char *GetPrefGeometry(void)
2109 return PrefData.geometry;
2112 char *GetPrefServerName(void)
2114 return PrefData.serverName;
2117 char *GetPrefBGMenuBtn(void)
2119 return PrefData.bgMenuBtn;
2122 int GetPrefMaxPrevOpenFiles(void)
2124 return PrefData.maxPrevOpenFiles;
2127 int GetPrefTypingHidesPointer(void)
2129 return(PrefData.typingHidesPointer);
2132 #ifdef SGI_CUSTOM
2133 void SetPrefShortMenus(int state)
2135 setIntPref(&PrefData.shortMenus, state);
2138 int GetPrefShortMenus(void)
2140 return PrefData.shortMenus;
2142 #endif
2144 void SetPrefTitleFormat(const char* format)
2146 const WindowInfo* window;
2148 setStringPref(PrefData.titleFormat, format);
2150 /* update all windows */
2151 for (window=WindowList; window!=NULL; window=window->next) {
2152 UpdateWindowTitle(window);
2155 const char* GetPrefTitleFormat(void)
2157 return PrefData.titleFormat;
2160 Boolean GetPrefUndoModifiesSelection(void)
2162 return (Boolean)PrefData.undoModifiesSelection;
2165 Boolean GetPrefFocusOnRaise(void)
2167 return (Boolean)PrefData.focusOnRaise;
2170 Boolean GetPrefForceOSConversion(void)
2172 return (Boolean) PrefData.forceOSConversion;
2175 Boolean GetPrefHonorSymlinks(void)
2177 return PrefData.honorSymlinks;
2180 int GetPrefOverrideVirtKeyBindings(void)
2182 return PrefData.virtKeyOverride;
2185 int GetPrefTruncSubstitution(void)
2187 return PrefData.truncSubstitution;
2191 ** If preferences don't get saved, ask the user on exit whether to save
2193 void MarkPrefsChanged(void)
2195 PrefsHaveChanged = True;
2199 ** Check if preferences have changed, and if so, ask the user if he wants
2200 ** to re-save. Returns False if user requests cancelation of Exit (or whatever
2201 ** operation triggered this call to be made).
2203 int CheckPrefsChangesSaved(Widget dialogParent)
2205 int resp;
2207 if (!PrefsHaveChanged)
2208 return True;
2210 resp = DialogF(DF_WARN, dialogParent, 3, "Default Preferences",
2211 ImportedFile == NULL ?
2212 "Default Preferences have changed.\n"
2213 "Save changes to NEdit preference file?" :
2214 "Default Preferences have changed. SAVING \n"
2215 "CHANGES WILL INCORPORATE ADDITIONAL\nSETTINGS FROM FILE: %s",
2216 "Save", "Don't Save", "Cancel", ImportedFile);
2217 if (resp == 2)
2218 return True;
2219 if (resp == 3)
2220 return False;
2222 SaveNEditPrefs(dialogParent, True);
2223 return True;
2227 ** set *prefDataField to newValue, but first check if they're different
2228 ** and update PrefsHaveChanged if a preference setting has now changed.
2230 static void setIntPref(int *prefDataField, int newValue)
2232 if (newValue != *prefDataField)
2233 PrefsHaveChanged = True;
2234 *prefDataField = newValue;
2237 static void setStringPref(char *prefDataField, const char *newValue)
2239 if (strcmp(prefDataField, newValue))
2240 PrefsHaveChanged = True;
2241 strcpy(prefDataField, newValue);
2244 static void setStringAllocPref(char **pprefDataField, char *newValue)
2246 char *p_newField;
2248 /* treat empty strings as nulls */
2249 if (newValue && *newValue == '\0')
2250 newValue = NULL;
2251 if (*pprefDataField && **pprefDataField == '\0')
2252 *pprefDataField = NULL; /* assume statically alloc'ed "" */
2254 /* check changes */
2255 if (!*pprefDataField && !newValue)
2256 return;
2257 else if (!*pprefDataField && newValue)
2258 PrefsHaveChanged = True;
2259 else if (*pprefDataField && !newValue)
2260 PrefsHaveChanged = True;
2261 else if (strcmp(*pprefDataField, newValue))
2262 PrefsHaveChanged = True;
2264 /* get rid of old preference */
2265 XtFree(*pprefDataField);
2267 /* store new preference */
2268 if (newValue) {
2269 p_newField = XtMalloc(strlen(newValue) + 1);
2270 strcpy(p_newField, newValue);
2272 *pprefDataField = newValue;
2276 ** Set the language mode for the window, update the menu and trigger language
2277 ** mode specific actions (turn on/off highlighting). If forceNewDefaults is
2278 ** true, re-establish default settings for language-specific preferences
2279 ** regardless of whether they were previously set by the user.
2281 void SetLanguageMode(WindowInfo *window, int mode, int forceNewDefaults)
2283 Widget menu;
2284 WidgetList items;
2285 int n;
2286 Cardinal nItems;
2287 void *userData;
2289 /* Do mode-specific actions */
2290 reapplyLanguageMode(window, mode, forceNewDefaults);
2292 /* Select the correct language mode in the sub-menu */
2293 if (IsTopDocument(window)) {
2294 XtVaGetValues(window->langModeCascade, XmNsubMenuId, &menu, NULL);
2295 XtVaGetValues(menu, XmNchildren, &items, XmNnumChildren, &nItems, NULL);
2296 for (n=0; n<(int)nItems; n++) {
2297 XtVaGetValues(items[n], XmNuserData, &userData, NULL);
2298 XmToggleButtonSetState(items[n], (int)userData == mode, False);
2304 ** Lookup a language mode by name, returning the index of the language
2305 ** mode or PLAIN_LANGUAGE_MODE if the name is not found
2307 int FindLanguageMode(const char *languageName)
2309 int i;
2311 /* Compare each language mode to the one we were presented */
2312 for (i=0; i<NLanguageModes; i++)
2313 if (!strcmp(languageName, LanguageModes[i]->name))
2314 return i;
2316 return PLAIN_LANGUAGE_MODE;
2321 ** Apply language mode matching criteria and set window->languageMode to
2322 ** the appropriate mode for the current file, trigger language mode
2323 ** specific actions (turn on/off highlighting), and update the language
2324 ** mode menu item. If forceNewDefaults is true, re-establish default
2325 ** settings for language-specific preferences regardless of whether
2326 ** they were previously set by the user.
2328 void DetermineLanguageMode(WindowInfo *window, int forceNewDefaults)
2330 SetLanguageMode(window, matchLanguageMode(window), forceNewDefaults);
2334 ** Return the name of the current language mode set in "window", or NULL
2335 ** if the current mode is "Plain".
2337 char *LanguageModeName(int mode)
2339 if (mode == PLAIN_LANGUAGE_MODE)
2340 return NULL;
2341 else
2342 return LanguageModes[mode]->name;
2346 ** Get the set of word delimiters for the language mode set in the current
2347 ** window. Returns NULL when no language mode is set (it would be easy to
2348 ** return the default delimiter set when the current language mode is "Plain",
2349 ** or the mode doesn't have its own delimiters, but this is usually used
2350 ** to supply delimiters for RE searching, and ExecRE can skip compiling a
2351 ** delimiter table when delimiters is NULL).
2353 char *GetWindowDelimiters(const WindowInfo *window)
2355 if (window->languageMode == PLAIN_LANGUAGE_MODE)
2356 return NULL;
2357 else
2358 return LanguageModes[window->languageMode]->delimiters;
2362 ** Put up a dialog for selecting a custom initial window size
2364 void RowColumnPrefDialog(Widget parent)
2366 Widget form, selBox, topLabel;
2367 Arg selBoxArgs[2];
2368 XmString s1;
2370 XtSetArg(selBoxArgs[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
2371 XtSetArg(selBoxArgs[1], XmNautoUnmanage, False);
2372 selBox = CreatePromptDialog(parent, "customSize", selBoxArgs, 2);
2373 XtAddCallback(selBox, XmNokCallback, (XtCallbackProc)sizeOKCB, NULL);
2374 XtAddCallback(selBox, XmNcancelCallback, (XtCallbackProc)sizeCancelCB,NULL);
2375 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_TEXT));
2376 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_SELECTION_LABEL));
2377 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_HELP_BUTTON));
2378 XtVaSetValues(XtParent(selBox), XmNtitle, "Initial Window Size", NULL);
2380 form = XtVaCreateManagedWidget("form", xmFormWidgetClass, selBox, NULL);
2382 topLabel = XtVaCreateManagedWidget("topLabel", xmLabelGadgetClass, form,
2383 XmNlabelString, s1=MKSTRING(
2384 "Enter desired size in rows\nand columns of characters:"), NULL);
2385 XmStringFree(s1);
2387 RowText = XtVaCreateManagedWidget("rows", xmTextWidgetClass, form,
2388 XmNcolumns, 3,
2389 XmNtopAttachment, XmATTACH_WIDGET,
2390 XmNleftAttachment, XmATTACH_POSITION,
2391 XmNrightAttachment, XmATTACH_POSITION,
2392 XmNtopWidget, topLabel,
2393 XmNleftPosition, 5,
2394 XmNrightPosition, 45, NULL);
2395 RemapDeleteKey(RowText);
2397 XtVaCreateManagedWidget("xLabel", xmLabelGadgetClass, form,
2398 XmNlabelString, s1=MKSTRING("x"),
2399 XmNtopAttachment, XmATTACH_WIDGET,
2400 XmNleftAttachment, XmATTACH_POSITION,
2401 XmNrightAttachment, XmATTACH_POSITION,
2402 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2403 XmNtopWidget, topLabel,
2404 XmNbottomWidget, RowText,
2405 XmNleftPosition, 45,
2406 XmNrightPosition, 55, NULL);
2407 XmStringFree(s1);
2409 ColText = XtVaCreateManagedWidget("cols", xmTextWidgetClass, form,
2410 XmNcolumns, 3,
2411 XmNtopAttachment, XmATTACH_WIDGET,
2412 XmNleftAttachment, XmATTACH_POSITION,
2413 XmNrightAttachment, XmATTACH_POSITION,
2414 XmNtopWidget, topLabel,
2415 XmNleftPosition, 55,
2416 XmNrightPosition, 95, NULL);
2417 RemapDeleteKey(ColText);
2419 /* put up dialog and wait for user to press ok or cancel */
2420 DoneWithSizeDialog = False;
2421 ManageDialogCenteredOnPointer(selBox);
2422 while (!DoneWithSizeDialog)
2424 XEvent event;
2425 XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
2426 ServerDispatchEvent(&event);
2429 XtDestroyWidget(selBox);
2432 static void sizeOKCB(Widget w, XtPointer clientData, XtPointer callData)
2434 int rowValue, colValue, stat;
2436 /* get the values that the user entered and make sure they're ok */
2437 stat = GetIntTextWarn(RowText, &rowValue, "number of rows", True);
2438 if (stat != TEXT_READ_OK)
2439 return;
2440 stat = GetIntTextWarn(ColText, &colValue, "number of columns", True);
2441 if (stat != TEXT_READ_OK)
2442 return;
2444 /* set the corresponding preferences and dismiss the dialog */
2445 SetPrefRows(rowValue);
2446 SetPrefCols(colValue);
2447 DoneWithSizeDialog = True;
2450 static void sizeCancelCB(Widget w, XtPointer clientData, XtPointer callData)
2452 DoneWithSizeDialog = True;
2456 ** Present the user a dialog for setting tab related preferences, either as
2457 ** defaults, or for a specific window (pass "forWindow" as NULL to set default
2458 ** preference, or a window to set preferences for the specific window.
2460 void TabsPrefDialog(Widget parent, WindowInfo *forWindow)
2462 Widget form, selBox;
2463 Arg selBoxArgs[2];
2464 XmString s1;
2465 int emulate, emTabDist, useTabs, tabDist;
2467 XtSetArg(selBoxArgs[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
2468 XtSetArg(selBoxArgs[1], XmNautoUnmanage, False);
2469 selBox = CreatePromptDialog(parent, "customSize", selBoxArgs, 2);
2470 XtAddCallback(selBox, XmNokCallback, (XtCallbackProc)tabsOKCB, NULL);
2471 XtAddCallback(selBox, XmNcancelCallback, (XtCallbackProc)tabsCancelCB,NULL);
2472 XtAddCallback(selBox, XmNhelpCallback, (XtCallbackProc)tabsHelpCB,NULL);
2473 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_TEXT));
2474 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_SELECTION_LABEL));
2475 XtVaSetValues(XtParent(selBox), XmNtitle, "Tabs", NULL);
2477 form = XtVaCreateManagedWidget("form", xmFormWidgetClass, selBox, NULL);
2479 TabDistText = XtVaCreateManagedWidget("tabDistText", xmTextWidgetClass,
2480 form, XmNcolumns, 7,
2481 XmNtopAttachment, XmATTACH_FORM,
2482 XmNrightAttachment, XmATTACH_FORM, NULL);
2483 RemapDeleteKey(TabDistText);
2484 XtVaCreateManagedWidget("tabDistLabel", xmLabelGadgetClass, form,
2485 XmNlabelString, s1=XmStringCreateSimple(
2486 "Tab spacing (for hardware tab characters)"),
2487 XmNmnemonic, 'T',
2488 XmNuserData, TabDistText,
2489 XmNtopAttachment, XmATTACH_FORM,
2490 XmNleftAttachment, XmATTACH_FORM,
2491 XmNrightAttachment, XmATTACH_WIDGET,
2492 XmNrightWidget, TabDistText,
2493 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2494 XmNbottomWidget, TabDistText, NULL);
2495 XmStringFree(s1);
2497 EmTabText = XtVaCreateManagedWidget("emTabText", xmTextWidgetClass, form,
2498 XmNcolumns, 7,
2499 XmNtopAttachment, XmATTACH_WIDGET,
2500 XmNtopWidget, TabDistText,
2501 XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET,
2502 XmNrightWidget, TabDistText, NULL);
2503 RemapDeleteKey(EmTabText);
2504 EmTabLabel = XtVaCreateManagedWidget("emTabLabel", xmLabelGadgetClass, form,
2505 XmNlabelString, s1=XmStringCreateSimple("Emulated tab spacing"),
2506 XmNmnemonic, 's',
2507 XmNuserData, EmTabText,
2508 XmNtopAttachment, XmATTACH_WIDGET,
2509 XmNtopWidget, TabDistText,
2510 XmNrightAttachment, XmATTACH_WIDGET,
2511 XmNrightWidget, EmTabText,
2512 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2513 XmNbottomWidget, EmTabText, NULL);
2514 XmStringFree(s1);
2515 EmTabToggle = XtVaCreateManagedWidget("emTabToggle",
2516 xmToggleButtonWidgetClass, form, XmNlabelString,
2517 s1=XmStringCreateSimple("Emulate tabs"),
2518 XmNmnemonic, 'E',
2519 XmNtopAttachment, XmATTACH_WIDGET,
2520 XmNtopWidget, TabDistText,
2521 XmNleftAttachment, XmATTACH_FORM,
2522 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2523 XmNbottomWidget, EmTabText, NULL);
2524 XmStringFree(s1);
2525 XtAddCallback(EmTabToggle, XmNvalueChangedCallback, emTabsCB, NULL);
2526 UseTabsToggle = XtVaCreateManagedWidget("useTabsToggle",
2527 xmToggleButtonWidgetClass, form,
2528 XmNlabelString, s1=XmStringCreateSimple(
2529 "Use tab characters in padding and emulated tabs"),
2530 XmNmnemonic, 'U',
2531 XmNtopAttachment, XmATTACH_WIDGET,
2532 XmNtopWidget, EmTabText,
2533 XmNtopOffset, 5,
2534 XmNleftAttachment, XmATTACH_FORM, NULL);
2535 XmStringFree(s1);
2537 /* Set default values */
2538 if (forWindow == NULL) {
2539 emTabDist = GetPrefEmTabDist(PLAIN_LANGUAGE_MODE);
2540 useTabs = GetPrefInsertTabs();
2541 tabDist = GetPrefTabDist(PLAIN_LANGUAGE_MODE);
2542 } else {
2543 XtVaGetValues(forWindow->textArea, textNemulateTabs, &emTabDist, NULL);
2544 useTabs = forWindow->buffer->useTabs;
2545 tabDist = BufGetTabDistance(forWindow->buffer);
2547 emulate = emTabDist != 0;
2548 SetIntText(TabDistText, tabDist);
2549 XmToggleButtonSetState(EmTabToggle, emulate, True);
2550 if (emulate)
2551 SetIntText(EmTabText, emTabDist);
2552 XmToggleButtonSetState(UseTabsToggle, useTabs, False);
2553 XtSetSensitive(EmTabText, emulate);
2554 XtSetSensitive(EmTabLabel, emulate);
2556 /* Handle mnemonic selection of buttons and focus to dialog */
2557 AddDialogMnemonicHandler(form, FALSE);
2559 /* Set the widget to get focus */
2560 #if XmVersion >= 1002
2561 XtVaSetValues(form, XmNinitialFocus, TabDistText, NULL);
2562 #endif
2564 /* put up dialog and wait for user to press ok or cancel */
2565 TabsDialogForWindow = forWindow;
2566 DoneWithTabsDialog = False;
2567 ManageDialogCenteredOnPointer(selBox);
2568 while (!DoneWithTabsDialog)
2570 XEvent event;
2571 XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
2572 ServerDispatchEvent(&event);
2575 XtDestroyWidget(selBox);
2578 static void tabsOKCB(Widget w, XtPointer clientData, XtPointer callData)
2580 int emulate, useTabs, stat, tabDist, emTabDist;
2581 WindowInfo *window = TabsDialogForWindow;
2583 /* get the values that the user entered and make sure they're ok */
2584 emulate = XmToggleButtonGetState(EmTabToggle);
2585 useTabs = XmToggleButtonGetState(UseTabsToggle);
2586 stat = GetIntTextWarn(TabDistText, &tabDist, "tab spacing", True);
2587 if (stat != TEXT_READ_OK)
2588 return;
2590 if (tabDist <= 0 || tabDist > MAX_EXP_CHAR_LEN)
2592 DialogF(DF_WARN, TabDistText, 1, "Tab Spacing",
2593 "Tab spacing out of range", "OK");
2594 return;
2597 if (emulate) {
2598 stat = GetIntTextWarn(EmTabText, &emTabDist, "emulated tab spacing",True);
2599 if (stat != TEXT_READ_OK)
2600 return;
2602 if (emTabDist <= 0 || tabDist >= 1000)
2604 DialogF(DF_WARN, EmTabText, 1, "Tab Spacing",
2605 "Emulated tab spacing out of range", "OK");
2606 return;
2608 } else
2609 emTabDist = 0;
2611 #ifdef SGI_CUSTOM
2612 /* Ask the user about saving as a default preference */
2613 if (TabsDialogForWindow != NULL) {
2614 int setDefault;
2615 if (!shortPrefToDefault(window->shell, "Tab Settings", &setDefault)) {
2616 DoneWithTabsDialog = True;
2617 return;
2619 if (setDefault) {
2620 SetPrefTabDist(tabDist);
2621 SetPrefEmTabDist(emTabDist);
2622 SetPrefInsertTabs(useTabs);
2623 SaveNEditPrefs(window->shell, GetPrefShortMenus());
2626 #endif
2628 /* Set the value in either the requested window or default preferences */
2629 if (TabsDialogForWindow == NULL) {
2630 SetPrefTabDist(tabDist);
2631 SetPrefEmTabDist(emTabDist);
2632 SetPrefInsertTabs(useTabs);
2633 } else {
2634 char *params[1];
2635 char numStr[25];
2637 params[0] = numStr;
2638 sprintf(numStr, "%d", tabDist);
2639 XtCallActionProc(window->textArea, "set_tab_dist", NULL, params, 1);
2640 params[0] = numStr;
2641 sprintf(numStr, "%d", emTabDist);
2642 XtCallActionProc(window->textArea, "set_em_tab_dist", NULL, params, 1);
2643 params[0] = numStr;
2644 sprintf(numStr, "%d", useTabs);
2645 XtCallActionProc(window->textArea, "set_use_tabs", NULL, params, 1);
2647 setTabDist(window, tabDist);
2648 setEmTabDist(window, emTabDist);
2649 window->buffer->useTabs = useTabs;
2652 DoneWithTabsDialog = True;
2655 static void tabsCancelCB(Widget w, XtPointer clientData, XtPointer callData)
2657 DoneWithTabsDialog = True;
2660 static void tabsHelpCB(Widget w, XtPointer clientData, XtPointer callData)
2662 Help(HELP_TABS_DIALOG);
2665 static void emTabsCB(Widget w, XtPointer clientData, XtPointer callData)
2667 int state = XmToggleButtonGetState(w);
2669 XtSetSensitive(EmTabLabel, state);
2670 XtSetSensitive(EmTabText, state);
2674 ** Present the user a dialog for setting wrap margin.
2676 void WrapMarginDialog(Widget parent, WindowInfo *forWindow)
2678 Widget form, selBox;
2679 Arg selBoxArgs[2];
2680 XmString s1;
2681 int margin;
2683 XtSetArg(selBoxArgs[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
2684 XtSetArg(selBoxArgs[1], XmNautoUnmanage, False);
2685 selBox = CreatePromptDialog(parent, "wrapMargin", selBoxArgs, 2);
2686 XtAddCallback(selBox, XmNokCallback, (XtCallbackProc)wrapOKCB, NULL);
2687 XtAddCallback(selBox, XmNcancelCallback, (XtCallbackProc)wrapCancelCB,NULL);
2688 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_TEXT));
2689 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_SELECTION_LABEL));
2690 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_HELP_BUTTON));
2691 XtVaSetValues(XtParent(selBox), XmNtitle, "Wrap Margin", NULL);
2693 form = XtVaCreateManagedWidget("form", xmFormWidgetClass, selBox, NULL);
2695 WrapWindowToggle = XtVaCreateManagedWidget("wrapWindowToggle",
2696 xmToggleButtonWidgetClass, form, XmNlabelString,
2697 s1=XmStringCreateSimple("Wrap and Fill at width of window"),
2698 XmNmnemonic, 'W',
2699 XmNtopAttachment, XmATTACH_FORM,
2700 XmNleftAttachment, XmATTACH_FORM, NULL);
2701 XmStringFree(s1);
2702 XtAddCallback(WrapWindowToggle, XmNvalueChangedCallback, wrapWindowCB,NULL);
2703 WrapText = XtVaCreateManagedWidget("wrapText", xmTextWidgetClass, form,
2704 XmNcolumns, 5,
2705 XmNtopAttachment, XmATTACH_WIDGET,
2706 XmNtopWidget, WrapWindowToggle,
2707 XmNrightAttachment, XmATTACH_FORM, NULL);
2708 RemapDeleteKey(WrapText);
2709 WrapTextLabel = XtVaCreateManagedWidget("wrapMarginLabel",
2710 xmLabelGadgetClass, form,
2711 XmNlabelString, s1=XmStringCreateSimple(
2712 "Margin for Wrap and Fill"),
2713 XmNmnemonic, 'M',
2714 XmNuserData, WrapText,
2715 XmNtopAttachment, XmATTACH_WIDGET,
2716 XmNtopWidget, WrapWindowToggle,
2717 XmNleftAttachment, XmATTACH_FORM,
2718 XmNrightAttachment, XmATTACH_WIDGET,
2719 XmNrightWidget, WrapText,
2720 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2721 XmNbottomWidget, WrapText, NULL);
2722 XmStringFree(s1);
2724 /* Set default value */
2725 if (forWindow == NULL)
2726 margin = GetPrefWrapMargin();
2727 else
2728 XtVaGetValues(forWindow->textArea, textNwrapMargin, &margin, NULL);
2729 XmToggleButtonSetState(WrapWindowToggle, margin==0, True);
2730 if (margin != 0)
2731 SetIntText(WrapText, margin);
2732 XtSetSensitive(WrapText, margin!=0);
2733 XtSetSensitive(WrapTextLabel, margin!=0);
2735 /* Handle mnemonic selection of buttons and focus to dialog */
2736 AddDialogMnemonicHandler(form, FALSE);
2738 /* put up dialog and wait for user to press ok or cancel */
2739 WrapDialogForWindow = forWindow;
2740 DoneWithWrapDialog = False;
2741 ManageDialogCenteredOnPointer(selBox);
2742 while (!DoneWithWrapDialog)
2744 XEvent event;
2745 XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
2746 ServerDispatchEvent(&event);
2749 XtDestroyWidget(selBox);
2752 static void wrapOKCB(Widget w, XtPointer clientData, XtPointer callData)
2754 int wrapAtWindow, margin, stat;
2755 WindowInfo *window = WrapDialogForWindow;
2757 /* get the values that the user entered and make sure they're ok */
2758 wrapAtWindow = XmToggleButtonGetState(WrapWindowToggle);
2759 if (wrapAtWindow)
2760 margin = 0;
2761 else {
2762 stat = GetIntTextWarn(WrapText, &margin, "wrap Margin", True);
2763 if (stat != TEXT_READ_OK)
2764 return;
2766 if (margin <= 0 || margin >= 1000)
2768 DialogF(DF_WARN, WrapText, 1, "Wrap Margin",
2769 "Wrap margin out of range", "OK");
2770 return;
2775 #ifdef SGI_CUSTOM
2776 /* Ask the user about saving as a default preference */
2777 if (WrapDialogForWindow != NULL) {
2778 int setDefault;
2779 if (!shortPrefToDefault(window->shell, "Wrap Margin Settings",
2780 &setDefault)) {
2781 DoneWithWrapDialog = True;
2782 return;
2784 if (setDefault) {
2785 SetPrefWrapMargin(margin);
2786 SaveNEditPrefs(window->shell, GetPrefShortMenus());
2789 #endif
2791 /* Set the value in either the requested window or default preferences */
2792 if (WrapDialogForWindow == NULL)
2793 SetPrefWrapMargin(margin);
2794 else {
2795 char *params[1];
2796 char marginStr[25];
2797 sprintf(marginStr, "%d", margin);
2798 params[0] = marginStr;
2799 XtCallActionProc(window->textArea, "set_wrap_margin", NULL, params, 1);
2801 DoneWithWrapDialog = True;
2804 static void wrapCancelCB(Widget w, XtPointer clientData, XtPointer callData)
2806 DoneWithWrapDialog = True;
2809 static void wrapWindowCB(Widget w, XtPointer clientData, XtPointer callData)
2811 int wrapAtWindow = XmToggleButtonGetState(w);
2813 XtSetSensitive(WrapTextLabel, !wrapAtWindow);
2814 XtSetSensitive(WrapText, !wrapAtWindow);
2818 ** Create and show a dialog for selecting the shell
2820 void SelectShellDialog(Widget parent, WindowInfo* forWindow)
2822 Widget shellSelDialog;
2823 Arg shellSelDialogArgs[2];
2824 XmString label;
2826 /* Set up the dialog. */
2827 XtSetArg(shellSelDialogArgs[0],
2828 XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
2829 XtSetArg(shellSelDialogArgs[1], XmNautoUnmanage, False);
2830 shellSelDialog = CreatePromptDialog(parent, "shellSelDialog",
2831 shellSelDialogArgs, 2);
2833 /* Fix dialog to our liking. */
2834 XtVaSetValues(XtParent(shellSelDialog), XmNtitle, "Command Shell", NULL);
2835 XtAddCallback(shellSelDialog, XmNokCallback, (XtCallbackProc) shellSelOKCB,
2836 shellSelDialog);
2837 XtAddCallback(shellSelDialog, XmNcancelCallback,
2838 (XtCallbackProc) shellSelCancelCB, NULL);
2839 XtUnmanageChild(XmSelectionBoxGetChild(shellSelDialog, XmDIALOG_HELP_BUTTON));
2840 label = XmStringCreateLocalized("Enter shell path:");
2841 XtVaSetValues(shellSelDialog, XmNselectionLabelString, label, NULL);
2842 XmStringFree(label);
2844 /* Set dialog's text to the current setting. */
2845 XmTextSetString(XmSelectionBoxGetChild(shellSelDialog, XmDIALOG_TEXT),
2846 (char*) GetPrefShell());
2848 DoneWithShellSelDialog = False;
2850 /* Show dialog and wait until the user made her choice. */
2851 ManageDialogCenteredOnPointer(shellSelDialog);
2852 while (!DoneWithShellSelDialog) {
2853 XEvent event;
2854 XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
2855 ServerDispatchEvent(&event);
2858 XtDestroyWidget(shellSelDialog);
2861 static void shellSelOKCB(Widget widget, XtPointer clientData,
2862 XtPointer callData)
2864 Widget shellSelDialog = (Widget) clientData;
2865 String shellName = XtMalloc(MAXPATHLEN);
2866 struct stat attribute;
2867 unsigned dlgResult;
2869 /* Leave with a warning if the dialog is not up. */
2870 if (!XtIsRealized(shellSelDialog)) {
2871 fprintf(stderr, "nedit: Callback shellSelOKCB() illegally called.\n");
2872 return;
2875 /* Get the string that the user entered and make sure it's ok. */
2876 shellName = XmTextGetString(XmSelectionBoxGetChild(shellSelDialog,
2877 XmDIALOG_TEXT));
2879 if (-1 == stat(shellName, &attribute)) {
2880 dlgResult = DialogF(DF_WARN, shellSelDialog, 2, "Command Shell",
2881 "The selected shell is not available.\nDo you want to use it anyway?",
2882 "OK", "Cancel");
2883 if (1 != dlgResult) {
2884 return;
2888 SetPrefShell(shellName);
2889 XtFree(shellName);
2891 DoneWithShellSelDialog = True;
2894 static void shellSelCancelCB(Widget widgget, XtPointer clientData,
2895 XtPointer callData)
2897 DoneWithShellSelDialog = True;
2901 ** Present a dialog for editing language mode information
2903 void EditLanguageModes(void)
2905 #define LIST_RIGHT 40
2906 #define LEFT_MARGIN_POS 1
2907 #define RIGHT_MARGIN_POS 99
2908 #define H_MARGIN 5
2909 Widget form, nameLbl, topLbl, extLbl, recogLbl, delimitLbl, defTipsLbl;
2910 Widget okBtn, applyBtn, closeBtn;
2911 Widget overrideFrame, overrideForm, delimitForm;
2912 Widget tabForm, tabLbl, indentBox, wrapBox;
2913 XmString s1;
2914 int i, ac;
2915 Arg args[20];
2917 /* if the dialog is already displayed, just pop it to the top and return */
2918 if (LMDialog.shell != NULL) {
2919 RaiseDialogWindow(LMDialog.shell);
2920 return;
2923 LMDialog.languageModeList = (languageModeRec **)XtMalloc(
2924 sizeof(languageModeRec *) * MAX_LANGUAGE_MODES);
2925 for (i=0; i<NLanguageModes; i++)
2926 LMDialog.languageModeList[i] = copyLanguageModeRec(LanguageModes[i]);
2927 LMDialog.nLanguageModes = NLanguageModes;
2929 /* Create a form widget in an application shell */
2930 ac = 0;
2931 XtSetArg(args[ac], XmNdeleteResponse, XmDO_NOTHING); ac++;
2932 XtSetArg(args[ac], XmNiconName, "NEdit Language Modes"); ac++;
2933 XtSetArg(args[ac], XmNtitle, "Language Modes"); ac++;
2934 LMDialog.shell = CreateWidget(TheAppShell, "langModes",
2935 topLevelShellWidgetClass, args, ac);
2936 AddSmallIcon(LMDialog.shell);
2937 form = XtVaCreateManagedWidget("editLanguageModes", xmFormWidgetClass,
2938 LMDialog.shell, XmNautoUnmanage, False,
2939 XmNresizePolicy, XmRESIZE_NONE, NULL);
2940 XtAddCallback(form, XmNdestroyCallback, lmDestroyCB, NULL);
2941 AddMotifCloseCallback(LMDialog.shell, lmCloseCB, NULL);
2943 topLbl = XtVaCreateManagedWidget("topLabel", xmLabelGadgetClass, form,
2944 XmNlabelString, s1=MKSTRING(
2945 "To modify the properties of an existing language mode, select the name from\n\
2946 the list on the left. To add a new language, select \"New\" from the list."),
2947 XmNmnemonic, 'N',
2948 XmNtopAttachment, XmATTACH_POSITION,
2949 XmNtopPosition, 2,
2950 XmNleftAttachment, XmATTACH_POSITION,
2951 XmNleftPosition, LEFT_MARGIN_POS,
2952 XmNrightAttachment, XmATTACH_POSITION,
2953 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
2954 XmStringFree(s1);
2956 nameLbl = XtVaCreateManagedWidget("nameLbl", xmLabelGadgetClass, form,
2957 XmNlabelString, s1=XmStringCreateSimple("Name"),
2958 XmNmnemonic, 'm',
2959 XmNalignment, XmALIGNMENT_BEGINNING,
2960 XmNleftAttachment, XmATTACH_POSITION,
2961 XmNleftPosition, LIST_RIGHT,
2962 XmNtopAttachment, XmATTACH_WIDGET,
2963 XmNtopOffset, H_MARGIN,
2964 XmNtopWidget, topLbl, NULL);
2965 XmStringFree(s1);
2967 LMDialog.nameW = XtVaCreateManagedWidget("name", xmTextWidgetClass, form,
2968 XmNcolumns, 15,
2969 XmNleftAttachment, XmATTACH_POSITION,
2970 XmNleftPosition, LIST_RIGHT,
2971 XmNtopAttachment, XmATTACH_WIDGET,
2972 XmNtopWidget, nameLbl,
2973 XmNrightAttachment, XmATTACH_POSITION,
2974 XmNrightPosition, (RIGHT_MARGIN_POS + LIST_RIGHT)/2, NULL);
2975 RemapDeleteKey(LMDialog.nameW);
2976 XtVaSetValues(nameLbl, XmNuserData, LMDialog.nameW, NULL);
2978 extLbl = XtVaCreateManagedWidget("extLbl", xmLabelGadgetClass, form,
2979 XmNlabelString,
2980 s1=XmStringCreateSimple("File extensions (separate w/ space)"),
2981 XmNmnemonic, 'F',
2982 XmNalignment, XmALIGNMENT_BEGINNING,
2983 XmNleftAttachment, XmATTACH_POSITION,
2984 XmNleftPosition, LIST_RIGHT,
2985 XmNtopAttachment, XmATTACH_WIDGET,
2986 XmNtopOffset, H_MARGIN,
2987 XmNtopWidget, LMDialog.nameW, NULL);
2988 XmStringFree(s1);
2990 LMDialog.extW = XtVaCreateManagedWidget("ext", xmTextWidgetClass, form,
2991 XmNleftAttachment, XmATTACH_POSITION,
2992 XmNleftPosition, LIST_RIGHT,
2993 XmNtopAttachment, XmATTACH_WIDGET,
2994 XmNtopWidget, extLbl,
2995 XmNrightAttachment, XmATTACH_POSITION,
2996 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
2997 RemapDeleteKey(LMDialog.extW);
2998 XtVaSetValues(extLbl, XmNuserData, LMDialog.extW, NULL);
3000 recogLbl = XtVaCreateManagedWidget("recogLbl", xmLabelGadgetClass, form,
3001 XmNlabelString, s1=MKSTRING(
3002 "Recognition regular expression (applied to first 200\n\
3003 characters of file to determine type from content)"),
3004 XmNalignment, XmALIGNMENT_BEGINNING,
3005 XmNmnemonic, 'R',
3006 XmNleftAttachment, XmATTACH_POSITION,
3007 XmNleftPosition, LIST_RIGHT,
3008 XmNtopAttachment, XmATTACH_WIDGET,
3009 XmNtopOffset, H_MARGIN,
3010 XmNtopWidget, LMDialog.extW, NULL);
3011 XmStringFree(s1);
3013 LMDialog.recogW = XtVaCreateManagedWidget("recog", xmTextWidgetClass, form,
3014 XmNleftAttachment, XmATTACH_POSITION,
3015 XmNleftPosition, LIST_RIGHT,
3016 XmNtopAttachment, XmATTACH_WIDGET,
3017 XmNtopWidget, recogLbl,
3018 XmNrightAttachment, XmATTACH_POSITION,
3019 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
3020 RemapDeleteKey(LMDialog.recogW);
3021 XtVaSetValues(recogLbl, XmNuserData, LMDialog.recogW, NULL);
3023 defTipsLbl = XtVaCreateManagedWidget("defTipsLbl", xmLabelGadgetClass, form,
3024 XmNlabelString, s1=MKSTRING(
3025 "Default calltips file(s) (separate w/colons)"),
3026 XmNalignment, XmALIGNMENT_BEGINNING,
3027 XmNmnemonic, 'c',
3028 XmNleftAttachment, XmATTACH_POSITION,
3029 XmNleftPosition, LIST_RIGHT,
3030 XmNtopAttachment, XmATTACH_WIDGET,
3031 XmNtopOffset, H_MARGIN,
3032 XmNtopWidget, LMDialog.recogW, NULL);
3033 XmStringFree(s1);
3035 LMDialog.defTipsW = XtVaCreateManagedWidget("defTips", xmTextWidgetClass,
3036 form,
3037 XmNleftAttachment, XmATTACH_POSITION,
3038 XmNleftPosition, LIST_RIGHT,
3039 XmNtopAttachment, XmATTACH_WIDGET,
3040 XmNtopWidget, defTipsLbl,
3041 XmNrightAttachment, XmATTACH_POSITION,
3042 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
3043 RemapDeleteKey(LMDialog.defTipsW);
3044 XtVaSetValues(defTipsLbl, XmNuserData, LMDialog.defTipsW, NULL);
3046 okBtn = XtVaCreateManagedWidget("ok", xmPushButtonWidgetClass, form,
3047 XmNlabelString, s1=XmStringCreateSimple("OK"),
3048 XmNmarginWidth, BUTTON_WIDTH_MARGIN,
3049 XmNleftAttachment, XmATTACH_POSITION,
3050 XmNleftPosition, 10,
3051 XmNrightAttachment, XmATTACH_POSITION,
3052 XmNrightPosition, 30,
3053 XmNbottomAttachment, XmATTACH_POSITION,
3054 XmNbottomPosition, 99, NULL);
3055 XtAddCallback(okBtn, XmNactivateCallback, lmOkCB, NULL);
3056 XmStringFree(s1);
3058 applyBtn = XtVaCreateManagedWidget("apply", xmPushButtonWidgetClass, form,
3059 XmNlabelString, s1=XmStringCreateSimple("Apply"),
3060 XmNmnemonic, 'A',
3061 XmNleftAttachment, XmATTACH_POSITION,
3062 XmNleftPosition, 40,
3063 XmNrightAttachment, XmATTACH_POSITION,
3064 XmNrightPosition, 60,
3065 XmNbottomAttachment, XmATTACH_POSITION,
3066 XmNbottomPosition, 99, NULL);
3067 XtAddCallback(applyBtn, XmNactivateCallback, lmApplyCB, NULL);
3068 XmStringFree(s1);
3070 closeBtn = XtVaCreateManagedWidget("close",xmPushButtonWidgetClass,form,
3071 XmNlabelString, s1=XmStringCreateSimple("Close"),
3072 XmNleftAttachment, XmATTACH_POSITION,
3073 XmNleftPosition, 70,
3074 XmNrightAttachment, XmATTACH_POSITION,
3075 XmNrightPosition, 90,
3076 XmNbottomAttachment, XmATTACH_POSITION,
3077 XmNbottomPosition, 99, NULL);
3078 XtAddCallback(closeBtn, XmNactivateCallback, lmCloseCB, NULL);
3079 XmStringFree(s1);
3081 overrideFrame = XtVaCreateManagedWidget("overrideFrame",
3082 xmFrameWidgetClass, form,
3083 XmNleftAttachment, XmATTACH_POSITION,
3084 XmNleftPosition, LEFT_MARGIN_POS,
3085 XmNrightAttachment, XmATTACH_POSITION,
3086 XmNrightPosition, RIGHT_MARGIN_POS,
3087 XmNbottomAttachment, XmATTACH_WIDGET,
3088 XmNbottomWidget, closeBtn,
3089 XmNbottomOffset, H_MARGIN, NULL);
3090 overrideForm = XtVaCreateManagedWidget("overrideForm", xmFormWidgetClass,
3091 overrideFrame, NULL);
3092 XtVaCreateManagedWidget("overrideLbl", xmLabelGadgetClass, overrideFrame,
3093 XmNlabelString, s1=XmStringCreateSimple("Override Defaults"),
3094 XmNchildType, XmFRAME_TITLE_CHILD,
3095 XmNchildHorizontalAlignment, XmALIGNMENT_CENTER, NULL);
3096 XmStringFree(s1);
3098 delimitForm = XtVaCreateManagedWidget("delimitForm", xmFormWidgetClass,
3099 overrideForm,
3100 XmNleftAttachment, XmATTACH_POSITION,
3101 XmNleftPosition, LEFT_MARGIN_POS,
3102 XmNtopAttachment, XmATTACH_FORM,
3103 XmNtopOffset, H_MARGIN,
3104 XmNrightAttachment, XmATTACH_POSITION,
3105 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
3106 delimitLbl = XtVaCreateManagedWidget("delimitLbl", xmLabelGadgetClass,
3107 delimitForm,
3108 XmNlabelString, s1=XmStringCreateSimple("Word delimiters"),
3109 XmNmnemonic, 'W',
3110 XmNleftAttachment, XmATTACH_FORM,
3111 XmNtopAttachment, XmATTACH_FORM,
3112 XmNbottomAttachment, XmATTACH_FORM, NULL);
3113 XmStringFree(s1);
3114 LMDialog.delimitW = XtVaCreateManagedWidget("delimit", xmTextWidgetClass,
3115 delimitForm,
3116 XmNtopAttachment, XmATTACH_FORM,
3117 XmNleftAttachment, XmATTACH_WIDGET,
3118 XmNleftWidget, delimitLbl,
3119 XmNrightAttachment, XmATTACH_FORM,
3120 XmNbottomAttachment, XmATTACH_FORM, NULL);
3121 RemapDeleteKey(LMDialog.delimitW);
3122 XtVaSetValues(delimitLbl, XmNuserData, LMDialog.delimitW, NULL);
3124 tabForm = XtVaCreateManagedWidget("tabForm", xmFormWidgetClass,
3125 overrideForm,
3126 XmNleftAttachment, XmATTACH_POSITION,
3127 XmNleftPosition, LEFT_MARGIN_POS,
3128 XmNtopAttachment, XmATTACH_WIDGET,
3129 XmNtopWidget, delimitForm,
3130 XmNtopOffset, H_MARGIN,
3131 XmNrightAttachment, XmATTACH_POSITION,
3132 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
3133 tabLbl = XtVaCreateManagedWidget("tabLbl", xmLabelGadgetClass, tabForm,
3134 XmNlabelString, s1=XmStringCreateSimple(
3135 "Alternative hardware tab spacing"),
3136 XmNmnemonic, 't',
3137 XmNleftAttachment, XmATTACH_FORM,
3138 XmNtopAttachment, XmATTACH_FORM,
3139 XmNbottomAttachment, XmATTACH_FORM, NULL);
3140 XmStringFree(s1);
3141 LMDialog.tabW = XtVaCreateManagedWidget("delimit", xmTextWidgetClass,
3142 tabForm,
3143 XmNcolumns, 3,
3144 XmNtopAttachment, XmATTACH_FORM,
3145 XmNleftAttachment, XmATTACH_WIDGET,
3146 XmNleftWidget, tabLbl,
3147 XmNbottomAttachment, XmATTACH_FORM, NULL);
3148 RemapDeleteKey(LMDialog.tabW);
3149 XtVaSetValues(tabLbl, XmNuserData, LMDialog.tabW, NULL);
3150 LMDialog.emTabW = XtVaCreateManagedWidget("delimit", xmTextWidgetClass,
3151 tabForm,
3152 XmNcolumns, 3,
3153 XmNtopAttachment, XmATTACH_FORM,
3154 XmNrightAttachment, XmATTACH_FORM,
3155 XmNbottomAttachment, XmATTACH_FORM, NULL);
3156 RemapDeleteKey(LMDialog.emTabW);
3157 XtVaCreateManagedWidget("emTabLbl", xmLabelGadgetClass, tabForm,
3158 XmNlabelString,
3159 s1=XmStringCreateSimple("Alternative emulated tab spacing"),
3160 XmNalignment, XmALIGNMENT_END,
3161 XmNmnemonic, 'e',
3162 XmNuserData, LMDialog.emTabW,
3163 XmNleftAttachment, XmATTACH_WIDGET,
3164 XmNleftWidget, LMDialog.tabW,
3165 XmNrightAttachment, XmATTACH_WIDGET,
3166 XmNrightWidget, LMDialog.emTabW,
3167 XmNtopAttachment, XmATTACH_FORM,
3168 XmNbottomAttachment, XmATTACH_FORM, NULL);
3169 XmStringFree(s1);
3171 indentBox = XtVaCreateManagedWidget("indentBox", xmRowColumnWidgetClass,
3172 overrideForm,
3173 XmNorientation, XmHORIZONTAL,
3174 XmNpacking, XmPACK_TIGHT,
3175 XmNradioBehavior, True,
3176 XmNleftAttachment, XmATTACH_POSITION,
3177 XmNleftPosition, LEFT_MARGIN_POS,
3178 XmNtopAttachment, XmATTACH_WIDGET,
3179 XmNtopWidget, tabForm,
3180 XmNtopOffset, H_MARGIN, NULL);
3181 LMDialog.defaultIndentW = XtVaCreateManagedWidget("defaultIndent",
3182 xmToggleButtonWidgetClass, indentBox,
3183 XmNset, True,
3184 XmNmarginHeight, 0,
3185 XmNlabelString, s1=XmStringCreateSimple("Default indent style"),
3186 XmNmnemonic, 'D', NULL);
3187 XmStringFree(s1);
3188 LMDialog.noIndentW = XtVaCreateManagedWidget("noIndent",
3189 xmToggleButtonWidgetClass, indentBox,
3190 XmNmarginHeight, 0,
3191 XmNlabelString, s1=XmStringCreateSimple("No automatic indent"),
3192 XmNmnemonic, 'N', NULL);
3193 XmStringFree(s1);
3194 LMDialog.autoIndentW = XtVaCreateManagedWidget("autoIndent",
3195 xmToggleButtonWidgetClass, indentBox,
3196 XmNmarginHeight, 0,
3197 XmNlabelString, s1=XmStringCreateSimple("Auto-indent"),
3198 XmNmnemonic, 'A', NULL);
3199 XmStringFree(s1);
3200 LMDialog.smartIndentW = XtVaCreateManagedWidget("smartIndent",
3201 xmToggleButtonWidgetClass, indentBox,
3202 XmNmarginHeight, 0,
3203 XmNlabelString, s1=XmStringCreateSimple("Smart-indent"),
3204 XmNmnemonic, 'S', NULL);
3205 XmStringFree(s1);
3207 wrapBox = XtVaCreateManagedWidget("wrapBox", xmRowColumnWidgetClass,
3208 overrideForm,
3209 XmNorientation, XmHORIZONTAL,
3210 XmNpacking, XmPACK_TIGHT,
3211 XmNradioBehavior, True,
3212 XmNleftAttachment, XmATTACH_POSITION,
3213 XmNleftPosition, LEFT_MARGIN_POS,
3214 XmNtopAttachment, XmATTACH_WIDGET,
3215 XmNtopWidget, indentBox,
3216 XmNtopOffset, H_MARGIN,
3217 XmNbottomAttachment, XmATTACH_FORM,
3218 XmNbottomOffset, H_MARGIN, NULL);
3219 LMDialog.defaultWrapW = XtVaCreateManagedWidget("defaultWrap",
3220 xmToggleButtonWidgetClass, wrapBox,
3221 XmNset, True,
3222 XmNmarginHeight, 0,
3223 XmNlabelString, s1=XmStringCreateSimple("Default wrap style"),
3224 XmNmnemonic, 'D', NULL);
3225 XmStringFree(s1);
3226 LMDialog.noWrapW = XtVaCreateManagedWidget("noWrap",
3227 xmToggleButtonWidgetClass, wrapBox,
3228 XmNmarginHeight, 0,
3229 XmNlabelString, s1=XmStringCreateSimple("No wrapping"),
3230 XmNmnemonic, 'N', NULL);
3231 XmStringFree(s1);
3232 LMDialog.newlineWrapW = XtVaCreateManagedWidget("newlineWrap",
3233 xmToggleButtonWidgetClass, wrapBox,
3234 XmNmarginHeight, 0,
3235 XmNlabelString, s1=XmStringCreateSimple("Auto newline wrap"),
3236 XmNmnemonic, 'A', NULL);
3237 XmStringFree(s1);
3238 LMDialog.contWrapW = XtVaCreateManagedWidget("contWrap",
3239 xmToggleButtonWidgetClass, wrapBox,
3240 XmNmarginHeight, 0,
3241 XmNlabelString, s1=XmStringCreateSimple("Continuous wrap"),
3242 XmNmnemonic, 'C', NULL);
3243 XmStringFree(s1);
3245 XtVaCreateManagedWidget("stretchForm", xmFormWidgetClass, form,
3246 XmNtopAttachment, XmATTACH_WIDGET,
3247 XmNtopWidget, LMDialog.defTipsW,
3248 XmNleftAttachment, XmATTACH_POSITION,
3249 XmNleftPosition, LIST_RIGHT,
3250 XmNrightAttachment, XmATTACH_POSITION,
3251 XmNrightPosition, RIGHT_MARGIN_POS,
3252 XmNbottomAttachment, XmATTACH_WIDGET,
3253 XmNbottomWidget, overrideFrame,
3254 XmNbottomOffset, H_MARGIN*2, NULL);
3256 ac = 0;
3257 XtSetArg(args[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
3258 XtSetArg(args[ac], XmNtopOffset, H_MARGIN); ac++;
3259 XtSetArg(args[ac], XmNtopWidget, topLbl); ac++;
3260 XtSetArg(args[ac], XmNleftAttachment, XmATTACH_POSITION); ac++;
3261 XtSetArg(args[ac], XmNleftPosition, LEFT_MARGIN_POS); ac++;
3262 XtSetArg(args[ac], XmNrightAttachment, XmATTACH_POSITION); ac++;
3263 XtSetArg(args[ac], XmNrightPosition, LIST_RIGHT-1); ac++;
3264 XtSetArg(args[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
3265 XtSetArg(args[ac], XmNbottomWidget, overrideFrame); ac++;
3266 XtSetArg(args[ac], XmNbottomOffset, H_MARGIN*2); ac++;
3267 LMDialog.managedListW = CreateManagedList(form, "list", args, ac,
3268 (void **)LMDialog.languageModeList, &LMDialog.nLanguageModes,
3269 MAX_LANGUAGE_MODES, 15, lmGetDisplayedCB, NULL, lmSetDisplayedCB,
3270 NULL, lmFreeItemCB);
3271 AddDeleteConfirmCB(LMDialog.managedListW, lmDeleteConfirmCB, NULL);
3272 XtVaSetValues(topLbl, XmNuserData, LMDialog.managedListW, NULL);
3274 /* Set initial default button */
3275 XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
3276 XtVaSetValues(form, XmNcancelButton, closeBtn, NULL);
3278 /* Handle mnemonic selection of buttons and focus to dialog */
3279 AddDialogMnemonicHandler(form, FALSE);
3281 /* Realize all of the widgets in the new dialog */
3282 RealizeWithoutForcingPosition(LMDialog.shell);
3285 static void lmDestroyCB(Widget w, XtPointer clientData, XtPointer callData)
3287 int i;
3289 for (i=0; i<LMDialog.nLanguageModes; i++)
3290 freeLanguageModeRec(LMDialog.languageModeList[i]);
3291 XtFree((char *)LMDialog.languageModeList);
3294 static void lmOkCB(Widget w, XtPointer clientData, XtPointer callData)
3296 if (!updateLMList())
3297 return;
3299 /* pop down and destroy the dialog */
3300 XtDestroyWidget(LMDialog.shell);
3301 LMDialog.shell = NULL;
3304 static void lmApplyCB(Widget w, XtPointer clientData, XtPointer callData)
3306 updateLMList();
3309 static void lmCloseCB(Widget w, XtPointer clientData, XtPointer callData)
3311 /* pop down and destroy the dialog */
3312 XtDestroyWidget(LMDialog.shell);
3313 LMDialog.shell = NULL;
3316 static int lmDeleteConfirmCB(int itemIndex, void *cbArg)
3318 int i;
3320 /* Allow duplicate names to be deleted regardless of dependencies */
3321 for (i=0; i<LMDialog.nLanguageModes; i++)
3322 if (i != itemIndex && !strcmp(LMDialog.languageModeList[i]->name,
3323 LMDialog.languageModeList[itemIndex]->name))
3324 return True;
3326 /* don't allow deletion if data will be lost */
3327 if (LMHasHighlightPatterns(LMDialog.languageModeList[itemIndex]->name))
3329 DialogF(DF_WARN, LMDialog.shell, 1, "Patterns exist",
3330 "This language mode has syntax highlighting\n"
3331 "patterns defined. Please delete the patterns\n"
3332 "first, in Preferences -> Default Settings ->\n"
3333 "Syntax Highlighting, before proceeding here.", "OK");
3334 return False;
3337 /* don't allow deletion if data will be lost */
3338 if (LMHasSmartIndentMacros(LMDialog.languageModeList[itemIndex]->name))
3340 DialogF(DF_WARN, LMDialog.shell, 1, "Smart Indent Macros exist",
3341 "This language mode has smart indent macros\n"
3342 "defined. Please delete the macros first,\n"
3343 "in Preferences -> Default Settings ->\n"
3344 "Auto Indent -> Program Smart Indent,\n"
3345 "before proceeding here.", "OK");
3346 return False;
3349 return True;
3353 ** Apply the changes that the user has made in the language modes dialog to the
3354 ** stored language mode information for this NEdit session (the data array
3355 ** LanguageModes)
3357 static int updateLMList(void)
3359 WindowInfo *window;
3360 int oldLanguageMode;
3361 char *oldModeName, *newDelimiters;
3362 int i, j;
3364 /* Get the current contents of the dialog fields */
3365 if (!UpdateManagedList(LMDialog.managedListW, True))
3366 return False;
3368 /* Fix up language mode indices in all open windows (which may change
3369 if the currently selected mode is deleted or has changed position),
3370 and update word delimiters */
3371 for (window=WindowList; window!=NULL; window=window->next) {
3372 if (window->languageMode != PLAIN_LANGUAGE_MODE) {
3373 oldLanguageMode = window->languageMode;
3374 oldModeName = LanguageModes[window->languageMode]->name;
3375 window->languageMode = PLAIN_LANGUAGE_MODE;
3376 for (i=0; i<LMDialog.nLanguageModes; i++) {
3377 if (!strcmp(oldModeName, LMDialog.languageModeList[i]->name)) {
3378 newDelimiters = LMDialog.languageModeList[i]->delimiters;
3379 if (newDelimiters == NULL)
3380 newDelimiters = GetPrefDelimiters();
3381 XtVaSetValues(window->textArea, textNwordDelimiters,
3382 newDelimiters, NULL);
3383 for (j=0; j<window->nPanes; j++)
3384 XtVaSetValues(window->textPanes[j],
3385 textNwordDelimiters, newDelimiters, NULL);
3386 /* don't forget to adapt the LM stored within the user menu cache */
3387 if (window->userMenuCache->umcLanguageMode == oldLanguageMode)
3388 window->userMenuCache->umcLanguageMode = i;
3389 if (window->userBGMenuCache.ubmcLanguageMode == oldLanguageMode)
3390 window->userBGMenuCache.ubmcLanguageMode = i;
3391 /* update the language mode of this window (document) */
3392 window->languageMode = i;
3393 break;
3399 /* If there were any name changes, re-name dependent highlight patterns
3400 and smart-indent macros and fix up the weird rename-format names */
3401 for (i=0; i<LMDialog.nLanguageModes; i++) {
3402 if (strchr(LMDialog.languageModeList[i]->name, ':') != NULL) {
3403 char *newName = strrchr(LMDialog.languageModeList[i]->name, ':')+1;
3404 *strchr(LMDialog.languageModeList[i]->name, ':') = '\0';
3405 RenameHighlightPattern(LMDialog.languageModeList[i]->name, newName);
3406 RenameSmartIndentMacros(LMDialog.languageModeList[i]->name, newName);
3407 memmove(LMDialog.languageModeList[i]->name, newName,
3408 strlen(newName) + 1);
3409 ChangeManagedListData(LMDialog.managedListW);
3413 /* Replace the old language mode list with the new one from the dialog */
3414 for (i=0; i<NLanguageModes; i++)
3415 freeLanguageModeRec(LanguageModes[i]);
3416 for (i=0; i<LMDialog.nLanguageModes; i++)
3417 LanguageModes[i] = copyLanguageModeRec(LMDialog.languageModeList[i]);
3418 NLanguageModes = LMDialog.nLanguageModes;
3420 /* Update user menu info to update language mode dependencies of
3421 user menu items */
3422 UpdateUserMenuInfo();
3424 /* Update the menus in the window menu bars and load any needed
3425 calltips files */
3426 for (window=WindowList; window!=NULL; window=window->next) {
3427 updateLanguageModeSubmenu(window);
3428 if (window->languageMode != PLAIN_LANGUAGE_MODE &&
3429 LanguageModes[window->languageMode]->defTipsFile != NULL)
3430 AddTagsFile(LanguageModes[window->languageMode]->defTipsFile, TIP);
3431 /* cache user menus: Rebuild all user menus of this window */
3432 RebuildAllMenus(window);
3435 /* If a syntax highlighting dialog is up, update its menu */
3436 UpdateLanguageModeMenu();
3437 /* The same for the smart indent macro dialog */
3438 UpdateLangModeMenuSmartIndent();
3439 /* Note that preferences have been changed */
3440 MarkPrefsChanged();
3442 return True;
3445 static void *lmGetDisplayedCB(void *oldItem, int explicitRequest, int *abort,
3446 void *cbArg)
3448 languageModeRec *lm, *oldLM = (languageModeRec *)oldItem;
3449 char *tempName;
3450 int i, nCopies, oldLen;
3452 /* If the dialog is currently displaying the "new" entry and the
3453 fields are empty, that's just fine */
3454 if (oldItem == NULL && lmDialogEmpty())
3455 return NULL;
3457 /* Read the data the user has entered in the dialog fields */
3458 lm = readLMDialogFields(True);
3460 /* If there was a name change of a non-duplicate language mode, modify the
3461 name to the weird format of: ":old name:new name". This signals that a
3462 name change is necessary in lm dependent data such as highlight
3463 patterns. Duplicate language modes may be re-named at will, since no
3464 data will be lost due to the name change. */
3465 if (lm != NULL && oldLM != NULL && strcmp(oldLM->name, lm->name)) {
3466 nCopies = 0;
3467 for (i=0; i<LMDialog.nLanguageModes; i++)
3468 if (!strcmp(oldLM->name, LMDialog.languageModeList[i]->name))
3469 nCopies++;
3470 if (nCopies <= 1) {
3471 oldLen = strchr(oldLM->name, ':') == NULL ? strlen(oldLM->name) :
3472 strchr(oldLM->name, ':') - oldLM->name;
3473 tempName = XtMalloc(oldLen + strlen(lm->name) + 2);
3474 strncpy(tempName, oldLM->name, oldLen);
3475 sprintf(&tempName[oldLen], ":%s", lm->name);
3476 XtFree(lm->name);
3477 lm->name = tempName;
3481 /* If there are no problems reading the data, just return it */
3482 if (lm != NULL)
3483 return (void *)lm;
3485 /* If there are problems, and the user didn't ask for the fields to be
3486 read, give more warning */
3487 if (!explicitRequest)
3489 if (DialogF(DF_WARN, LMDialog.shell, 2, "Discard Language Mode",
3490 "Discard incomplete entry\nfor current language mode?", "Keep",
3491 "Discard") == 2)
3493 return oldItem == NULL
3494 ? NULL
3495 : (void *)copyLanguageModeRec((languageModeRec *)oldItem);
3499 /* Do readLMDialogFields again without "silent" mode to display warning */
3500 lm = readLMDialogFields(False);
3501 *abort = True;
3502 return NULL;
3505 static void lmSetDisplayedCB(void *item, void *cbArg)
3507 languageModeRec *lm = (languageModeRec *)item;
3508 char *extStr;
3510 if (item == NULL) {
3511 XmTextSetString(LMDialog.nameW, "");
3512 XmTextSetString(LMDialog.extW, "");
3513 XmTextSetString(LMDialog.recogW, "");
3514 XmTextSetString(LMDialog.defTipsW, "");
3515 XmTextSetString(LMDialog.delimitW, "");
3516 XmTextSetString(LMDialog.tabW, "");
3517 XmTextSetString(LMDialog.emTabW, "");
3518 RadioButtonChangeState(LMDialog.defaultIndentW, True, True);
3519 RadioButtonChangeState(LMDialog.defaultWrapW, True, True);
3520 } else {
3521 XmTextSetString(LMDialog.nameW, strchr(lm->name, ':') == NULL ?
3522 lm->name : strchr(lm->name, ':')+1);
3523 extStr = createExtString(lm->extensions, lm->nExtensions);
3524 XmTextSetString(LMDialog.extW, extStr);
3525 XtFree(extStr);
3526 XmTextSetString(LMDialog.recogW, lm->recognitionExpr);
3527 XmTextSetString(LMDialog.defTipsW, lm->defTipsFile);
3528 XmTextSetString(LMDialog.delimitW, lm->delimiters);
3529 if (lm->tabDist == DEFAULT_TAB_DIST)
3530 XmTextSetString(LMDialog.tabW, "");
3531 else
3532 SetIntText(LMDialog.tabW, lm->tabDist);
3533 if (lm->emTabDist == DEFAULT_EM_TAB_DIST)
3534 XmTextSetString(LMDialog.emTabW, "");
3535 else
3536 SetIntText(LMDialog.emTabW, lm->emTabDist);
3537 RadioButtonChangeState(LMDialog.defaultIndentW,
3538 lm->indentStyle == DEFAULT_INDENT, False);
3539 RadioButtonChangeState(LMDialog.noIndentW,
3540 lm->indentStyle == NO_AUTO_INDENT, False);
3541 RadioButtonChangeState(LMDialog.autoIndentW,
3542 lm->indentStyle == AUTO_INDENT, False);
3543 RadioButtonChangeState(LMDialog.smartIndentW,
3544 lm->indentStyle == SMART_INDENT, False);
3545 RadioButtonChangeState(LMDialog.defaultWrapW,
3546 lm->wrapStyle == DEFAULT_WRAP, False);
3547 RadioButtonChangeState(LMDialog.noWrapW,
3548 lm->wrapStyle == NO_WRAP, False);
3549 RadioButtonChangeState(LMDialog.newlineWrapW,
3550 lm->wrapStyle == NEWLINE_WRAP, False);
3551 RadioButtonChangeState(LMDialog.contWrapW,
3552 lm->wrapStyle == CONTINUOUS_WRAP, False);
3556 static void lmFreeItemCB(void *item)
3558 freeLanguageModeRec((languageModeRec *)item);
3561 static void freeLanguageModeRec(languageModeRec *lm)
3563 int i;
3565 XtFree(lm->name);
3566 XtFree(lm->recognitionExpr);
3567 XtFree(lm->defTipsFile);
3568 XtFree(lm->delimiters);
3569 for (i=0; i<lm->nExtensions; i++)
3570 XtFree(lm->extensions[i]);
3571 XtFree((char*) lm->extensions);
3572 XtFree((char *)lm);
3576 ** Copy a languageModeRec data structure and all of the allocated data it contains
3578 static languageModeRec *copyLanguageModeRec(languageModeRec *lm)
3580 languageModeRec *newLM;
3581 int i;
3583 newLM = (languageModeRec *)XtMalloc(sizeof(languageModeRec));
3584 newLM->name = XtMalloc(strlen(lm->name)+1);
3585 strcpy(newLM->name, lm->name);
3586 newLM->nExtensions = lm->nExtensions;
3587 newLM->extensions = (char **)XtMalloc(sizeof(char *) * lm->nExtensions);
3588 for (i=0; i<lm->nExtensions; i++) {
3589 newLM->extensions[i] = XtMalloc(strlen(lm->extensions[i]) + 1);
3590 strcpy(newLM->extensions[i], lm->extensions[i]);
3592 if (lm->recognitionExpr == NULL)
3593 newLM->recognitionExpr = NULL;
3594 else {
3595 newLM->recognitionExpr = XtMalloc(strlen(lm->recognitionExpr)+1);
3596 strcpy(newLM->recognitionExpr, lm->recognitionExpr);
3598 if (lm->defTipsFile == NULL)
3599 newLM->defTipsFile = NULL;
3600 else {
3601 newLM->defTipsFile = XtMalloc(strlen(lm->defTipsFile)+1);
3602 strcpy(newLM->defTipsFile, lm->defTipsFile);
3604 if (lm->delimiters == NULL)
3605 newLM->delimiters = NULL;
3606 else {
3607 newLM->delimiters = XtMalloc(strlen(lm->delimiters)+1);
3608 strcpy(newLM->delimiters, lm->delimiters);
3610 newLM->wrapStyle = lm->wrapStyle;
3611 newLM->indentStyle = lm->indentStyle;
3612 newLM->tabDist = lm->tabDist;
3613 newLM->emTabDist = lm->emTabDist;
3614 return newLM;
3618 ** Read the fields in the language modes dialog and create a languageModeRec data
3619 ** structure reflecting the current state of the selected language mode in the dialog.
3620 ** If any of the information is incorrect or missing, display a warning dialog and
3621 ** return NULL. Passing "silent" as True, suppresses the warning dialogs.
3623 static languageModeRec *readLMDialogFields(int silent)
3625 languageModeRec *lm;
3626 regexp *compiledRE;
3627 char *compileMsg, *extStr, *extPtr;
3629 /* Allocate a language mode structure to return, set unread fields to
3630 empty so everything can be freed on errors by freeLanguageModeRec */
3631 lm = (languageModeRec *)XtMalloc(sizeof(languageModeRec));
3632 lm->nExtensions = 0;
3633 lm->recognitionExpr = NULL;
3634 lm->defTipsFile = NULL;
3635 lm->delimiters = NULL;
3637 /* read the name field */
3638 lm->name = ReadSymbolicFieldTextWidget(LMDialog.nameW,
3639 "language mode name", silent);
3640 if (lm->name == NULL) {
3641 XtFree((char *)lm);
3642 return NULL;
3645 if (*lm->name == '\0')
3647 if (!silent)
3649 DialogF(DF_WARN, LMDialog.shell, 1, "Language Mode Name",
3650 "Please specify a name\nfor the language mode", "OK");
3651 XmProcessTraversal(LMDialog.nameW, XmTRAVERSE_CURRENT);
3653 freeLanguageModeRec(lm);
3654 return NULL;
3657 /* read the extension list field */
3658 extStr = extPtr = XmTextGetString(LMDialog.extW);
3659 lm->extensions = readExtensionList(&extPtr, &lm->nExtensions);
3660 XtFree(extStr);
3662 /* read recognition expression */
3663 lm->recognitionExpr = XmTextGetString(LMDialog.recogW);
3664 if (*lm->recognitionExpr == '\0') {
3665 XtFree(lm->recognitionExpr);
3666 lm->recognitionExpr = NULL;
3667 } else
3669 compiledRE = CompileRE(lm->recognitionExpr, &compileMsg, REDFLT_STANDARD);
3671 if (compiledRE == NULL)
3673 if (!silent)
3675 DialogF(DF_WARN, LMDialog.shell, 1, "Regex",
3676 "Recognition expression:\n%s", "OK", compileMsg);
3677 XmProcessTraversal(LMDialog.recogW, XmTRAVERSE_CURRENT);
3679 XtFree((char *)compiledRE);
3680 freeLanguageModeRec(lm);
3681 return NULL;
3684 XtFree((char *)compiledRE);
3687 /* Read the default calltips file for the language mode */
3688 lm->defTipsFile = XmTextGetString(LMDialog.defTipsW);
3689 if (*lm->defTipsFile == '\0') {
3690 /* Empty string */
3691 XtFree(lm->defTipsFile);
3692 lm->defTipsFile = NULL;
3693 } else {
3694 /* Ensure that AddTagsFile will work */
3695 if (AddTagsFile(lm->defTipsFile, TIP) == FALSE) {
3696 if (!silent)
3698 DialogF(DF_WARN, LMDialog.shell, 1, "Error reading Calltips",
3699 "Can't read default calltips file(s):\n \"%s\"\n",
3700 "OK", lm->defTipsFile);
3701 XmProcessTraversal(LMDialog.recogW, XmTRAVERSE_CURRENT);
3703 freeLanguageModeRec(lm);
3704 return NULL;
3705 } else
3706 if (DeleteTagsFile(lm->defTipsFile, TIP, False) == FALSE)
3707 fprintf(stderr, "nedit: Internal error: Trouble deleting "
3708 "calltips file(s):\n \"%s\"\n", lm->defTipsFile);
3711 /* read tab spacing field */
3712 if (TextWidgetIsBlank(LMDialog.tabW))
3713 lm->tabDist = DEFAULT_TAB_DIST;
3714 else {
3715 if (GetIntTextWarn(LMDialog.tabW, &lm->tabDist, "tab spacing", False)
3716 != TEXT_READ_OK) {
3717 freeLanguageModeRec(lm);
3718 return NULL;
3721 if (lm->tabDist <= 0 || lm->tabDist > 100)
3723 if (!silent)
3725 DialogF(DF_WARN, LMDialog.shell, 1, "Invalid Tab Spacing",
3726 "Invalid tab spacing: %d", "OK", lm->tabDist);
3727 XmProcessTraversal(LMDialog.tabW, XmTRAVERSE_CURRENT);
3729 freeLanguageModeRec(lm);
3730 return NULL;
3734 /* read emulated tab field */
3735 if (TextWidgetIsBlank(LMDialog.emTabW))
3737 lm->emTabDist = DEFAULT_EM_TAB_DIST;
3738 } else
3740 if (GetIntTextWarn(LMDialog.emTabW, &lm->emTabDist,
3741 "emulated tab spacing", False) != TEXT_READ_OK)
3743 freeLanguageModeRec(lm);
3744 return NULL;
3747 if (lm->emTabDist < 0 || lm->emTabDist > 100)
3749 if (!silent)
3751 DialogF(DF_WARN, LMDialog.shell, 1, "Invalid Tab Spacing",
3752 "Invalid emulated tab spacing: %d", "OK",
3753 lm->emTabDist);
3754 XmProcessTraversal(LMDialog.emTabW, XmTRAVERSE_CURRENT);
3756 freeLanguageModeRec(lm);
3757 return NULL;
3761 /* read delimiters string */
3762 lm->delimiters = XmTextGetString(LMDialog.delimitW);
3763 if (*lm->delimiters == '\0') {
3764 XtFree(lm->delimiters);
3765 lm->delimiters = NULL;
3768 /* read indent style */
3769 if (XmToggleButtonGetState(LMDialog.noIndentW))
3770 lm->indentStyle = NO_AUTO_INDENT;
3771 else if (XmToggleButtonGetState(LMDialog.autoIndentW))
3772 lm->indentStyle = AUTO_INDENT;
3773 else if (XmToggleButtonGetState(LMDialog.smartIndentW))
3774 lm->indentStyle = SMART_INDENT;
3775 else
3776 lm->indentStyle = DEFAULT_INDENT;
3778 /* read wrap style */
3779 if (XmToggleButtonGetState(LMDialog.noWrapW))
3780 lm->wrapStyle = NO_WRAP;
3781 else if (XmToggleButtonGetState(LMDialog.newlineWrapW))
3782 lm->wrapStyle = NEWLINE_WRAP;
3783 else if (XmToggleButtonGetState(LMDialog.contWrapW))
3784 lm->wrapStyle = CONTINUOUS_WRAP;
3785 else
3786 lm->wrapStyle = DEFAULT_WRAP;
3788 return lm;
3792 ** Return True if the language mode dialog fields are blank (unchanged from the "New"
3793 ** language mode state).
3795 static int lmDialogEmpty(void)
3797 return TextWidgetIsBlank(LMDialog.nameW) &&
3798 TextWidgetIsBlank(LMDialog.extW) &&
3799 TextWidgetIsBlank(LMDialog.recogW) &&
3800 TextWidgetIsBlank(LMDialog.delimitW) &&
3801 TextWidgetIsBlank(LMDialog.tabW) &&
3802 TextWidgetIsBlank(LMDialog.emTabW) &&
3803 XmToggleButtonGetState(LMDialog.defaultIndentW) &&
3804 XmToggleButtonGetState(LMDialog.defaultWrapW);
3808 ** Present a dialog for changing fonts (primary, and for highlighting).
3810 void ChooseFonts(WindowInfo *window, int forWindow)
3812 #define MARGIN_SPACING 10
3813 #define BTN_TEXT_OFFSET 3
3814 Widget form, primaryLbl, primaryBtn, italicLbl, italicBtn;
3815 Widget boldLbl, boldBtn, boldItalicLbl, boldItalicBtn;
3816 Widget primaryFrame, primaryForm, highlightFrame, highlightForm;
3817 Widget okBtn, applyBtn, cancelBtn;
3818 fontDialog *fd;
3819 XmString s1;
3820 int ac;
3821 Arg args[20];
3823 /* if the dialog is already displayed, just pop it to the top and return */
3824 if (window->fontDialog != NULL) {
3825 RaiseDialogWindow(((fontDialog *)window->fontDialog)->shell);
3826 return;
3829 /* Create a structure for keeping track of dialog state */
3830 fd = (fontDialog *)XtMalloc(sizeof(fontDialog));
3831 fd->window = window;
3832 fd->forWindow = forWindow;
3833 window->fontDialog = (void*)fd;
3835 /* Create a form widget in a dialog shell */
3836 ac = 0;
3837 XtSetArg(args[ac], XmNautoUnmanage, False); ac++;
3838 XtSetArg(args[ac], XmNresizePolicy, XmRESIZE_NONE); ac++;
3839 form = CreateFormDialog(window->shell, "choose Fonts", args, ac);
3840 XtVaSetValues(form, XmNshadowThickness, 0, NULL);
3841 fd->shell = XtParent(form);
3842 XtVaSetValues(fd->shell, XmNtitle, "Text Fonts", NULL);
3843 AddMotifCloseCallback(XtParent(form), fontCancelCB, fd);
3844 XtAddCallback(form, XmNdestroyCallback, fontDestroyCB, fd);
3846 primaryFrame = XtVaCreateManagedWidget("primaryFrame", xmFrameWidgetClass,
3847 form, XmNmarginHeight, 3,
3848 XmNtopAttachment, XmATTACH_POSITION,
3849 XmNtopPosition, 2,
3850 XmNleftAttachment, XmATTACH_POSITION,
3851 XmNleftPosition, 1,
3852 XmNrightAttachment, XmATTACH_POSITION,
3853 XmNrightPosition, 99, NULL);
3854 primaryForm = XtVaCreateManagedWidget("primaryForm", xmFormWidgetClass,
3855 primaryFrame, NULL);
3856 primaryLbl = XtVaCreateManagedWidget("primaryFont", xmLabelGadgetClass,
3857 primaryFrame,
3858 XmNlabelString, s1=XmStringCreateSimple("Primary Font"),
3859 XmNmnemonic, 'P',
3860 XmNchildType, XmFRAME_TITLE_CHILD,
3861 XmNchildHorizontalAlignment, XmALIGNMENT_CENTER, NULL);
3862 XmStringFree(s1);
3864 primaryBtn = XtVaCreateManagedWidget("primaryBtn",
3865 xmPushButtonWidgetClass, primaryForm,
3866 XmNlabelString, s1=XmStringCreateSimple("Browse..."),
3867 XmNmnemonic, 'r',
3868 XmNtopAttachment, XmATTACH_POSITION,
3869 XmNtopPosition, 2,
3870 XmNtopOffset, BTN_TEXT_OFFSET,
3871 XmNleftAttachment, XmATTACH_POSITION,
3872 XmNleftPosition, 1, NULL);
3873 XmStringFree(s1);
3874 XtAddCallback(primaryBtn, XmNactivateCallback, primaryBrowseCB, fd);
3876 fd->primaryW = XtVaCreateManagedWidget("primary", xmTextWidgetClass,
3877 primaryForm,
3878 XmNcolumns, 70,
3879 XmNmaxLength, MAX_FONT_LEN,
3880 XmNleftAttachment, XmATTACH_WIDGET,
3881 XmNleftWidget, primaryBtn,
3882 XmNtopAttachment, XmATTACH_POSITION,
3883 XmNtopPosition, 2,
3884 XmNrightAttachment, XmATTACH_POSITION,
3885 XmNrightPosition, 99, NULL);
3886 RemapDeleteKey(fd->primaryW);
3887 XtAddCallback(fd->primaryW, XmNvalueChangedCallback,
3888 primaryModifiedCB, fd);
3889 XtVaSetValues(primaryLbl, XmNuserData, fd->primaryW, NULL);
3891 highlightFrame = XtVaCreateManagedWidget("highlightFrame",
3892 xmFrameWidgetClass, form,
3893 XmNmarginHeight, 3,
3894 XmNnavigationType, XmTAB_GROUP,
3895 XmNtopAttachment, XmATTACH_WIDGET,
3896 XmNtopWidget, primaryFrame,
3897 XmNtopOffset, 20,
3898 XmNleftAttachment, XmATTACH_POSITION,
3899 XmNleftPosition, 1,
3900 XmNrightAttachment, XmATTACH_POSITION,
3901 XmNrightPosition, 99, NULL);
3902 highlightForm = XtVaCreateManagedWidget("highlightForm", xmFormWidgetClass,
3903 highlightFrame, NULL);
3904 XtVaCreateManagedWidget("highlightFonts", xmLabelGadgetClass,
3905 highlightFrame,
3906 XmNlabelString,
3907 s1=XmStringCreateSimple("Fonts for Syntax Highlighting"),
3908 XmNchildType, XmFRAME_TITLE_CHILD,
3909 XmNchildHorizontalAlignment, XmALIGNMENT_CENTER, NULL);
3910 XmStringFree(s1);
3912 fd->fillW = XtVaCreateManagedWidget("fillBtn",
3913 xmPushButtonWidgetClass, highlightForm,
3914 XmNlabelString,
3915 s1=XmStringCreateSimple("Fill Highlight Fonts from Primary"),
3916 XmNmnemonic, 'F',
3917 XmNtopAttachment, XmATTACH_POSITION,
3918 XmNtopPosition, 2,
3919 XmNtopOffset, BTN_TEXT_OFFSET,
3920 XmNleftAttachment, XmATTACH_POSITION,
3921 XmNleftPosition, 1, NULL);
3922 XmStringFree(s1);
3923 XtAddCallback(fd->fillW, XmNactivateCallback, fillFromPrimaryCB, fd);
3925 italicLbl = XtVaCreateManagedWidget("italicLbl", xmLabelGadgetClass,
3926 highlightForm,
3927 XmNlabelString, s1=XmStringCreateSimple("Italic Font"),
3928 XmNmnemonic, 'I',
3929 XmNalignment, XmALIGNMENT_BEGINNING,
3930 XmNtopAttachment, XmATTACH_WIDGET,
3931 XmNtopWidget, fd->fillW,
3932 XmNtopOffset, MARGIN_SPACING,
3933 XmNleftAttachment, XmATTACH_POSITION,
3934 XmNleftPosition, 1, NULL);
3935 XmStringFree(s1);
3937 fd->italicErrW = XtVaCreateManagedWidget("italicErrLbl",
3938 xmLabelGadgetClass, highlightForm,
3939 XmNlabelString, s1=XmStringCreateSimple(
3940 "(vvv spacing is inconsistent with primary font vvv)"),
3941 XmNalignment, XmALIGNMENT_END,
3942 XmNtopAttachment, XmATTACH_WIDGET,
3943 XmNtopWidget, fd->fillW,
3944 XmNtopOffset, MARGIN_SPACING,
3945 XmNleftAttachment, XmATTACH_WIDGET,
3946 XmNleftWidget, italicLbl,
3947 XmNrightAttachment, XmATTACH_POSITION,
3948 XmNrightPosition, 99, NULL);
3949 XmStringFree(s1);
3951 italicBtn = XtVaCreateManagedWidget("italicBtn",
3952 xmPushButtonWidgetClass, highlightForm,
3953 XmNlabelString, s1=XmStringCreateSimple("Browse..."),
3954 XmNmnemonic, 'o',
3955 XmNtopAttachment, XmATTACH_WIDGET,
3956 XmNtopWidget, italicLbl,
3957 XmNtopOffset, BTN_TEXT_OFFSET,
3958 XmNleftAttachment, XmATTACH_POSITION,
3959 XmNleftPosition, 1, NULL);
3960 XmStringFree(s1);
3961 XtAddCallback(italicBtn, XmNactivateCallback, italicBrowseCB, fd);
3963 fd->italicW = XtVaCreateManagedWidget("italic", xmTextWidgetClass,
3964 highlightForm,
3965 XmNmaxLength, MAX_FONT_LEN,
3966 XmNleftAttachment, XmATTACH_WIDGET,
3967 XmNleftWidget, italicBtn,
3968 XmNtopAttachment, XmATTACH_WIDGET,
3969 XmNtopWidget, italicLbl,
3970 XmNrightAttachment, XmATTACH_POSITION,
3971 XmNrightPosition, 99, NULL);
3972 RemapDeleteKey(fd->italicW);
3973 XtAddCallback(fd->italicW, XmNvalueChangedCallback,
3974 italicModifiedCB, fd);
3975 XtVaSetValues(italicLbl, XmNuserData, fd->italicW, NULL);
3977 boldLbl = XtVaCreateManagedWidget("boldLbl", xmLabelGadgetClass,
3978 highlightForm,
3979 XmNlabelString, s1=XmStringCreateSimple("Bold Font"),
3980 XmNmnemonic, 'B',
3981 XmNalignment, XmALIGNMENT_BEGINNING,
3982 XmNtopAttachment, XmATTACH_WIDGET,
3983 XmNtopWidget, italicBtn,
3984 XmNtopOffset, MARGIN_SPACING,
3985 XmNleftAttachment, XmATTACH_POSITION,
3986 XmNleftPosition, 1, NULL);
3987 XmStringFree(s1);
3989 fd->boldErrW = XtVaCreateManagedWidget("boldErrLbl",
3990 xmLabelGadgetClass, highlightForm,
3991 XmNlabelString, s1=XmStringCreateSimple(""),
3992 XmNalignment, XmALIGNMENT_END,
3993 XmNtopAttachment, XmATTACH_WIDGET,
3994 XmNtopWidget, italicBtn,
3995 XmNtopOffset, MARGIN_SPACING,
3996 XmNleftAttachment, XmATTACH_WIDGET,
3997 XmNleftWidget, boldLbl,
3998 XmNrightAttachment, XmATTACH_POSITION,
3999 XmNrightPosition, 99, NULL);
4000 XmStringFree(s1);
4002 boldBtn = XtVaCreateManagedWidget("boldBtn",
4003 xmPushButtonWidgetClass, highlightForm,
4004 XmNlabelString, s1=XmStringCreateSimple("Browse..."),
4005 XmNmnemonic, 'w',
4006 XmNtopAttachment, XmATTACH_WIDGET,
4007 XmNtopWidget, boldLbl,
4008 XmNtopOffset, BTN_TEXT_OFFSET,
4009 XmNleftAttachment, XmATTACH_POSITION,
4010 XmNleftPosition, 1, NULL);
4011 XmStringFree(s1);
4012 XtAddCallback(boldBtn, XmNactivateCallback, boldBrowseCB, fd);
4014 fd->boldW = XtVaCreateManagedWidget("bold", xmTextWidgetClass,
4015 highlightForm,
4016 XmNmaxLength, MAX_FONT_LEN,
4017 XmNleftAttachment, XmATTACH_WIDGET,
4018 XmNleftWidget, boldBtn,
4019 XmNtopAttachment, XmATTACH_WIDGET,
4020 XmNtopWidget, boldLbl,
4021 XmNrightAttachment, XmATTACH_POSITION,
4022 XmNrightPosition, 99, NULL);
4023 RemapDeleteKey(fd->boldW);
4024 XtAddCallback(fd->boldW, XmNvalueChangedCallback,
4025 boldModifiedCB, fd);
4026 XtVaSetValues(boldLbl, XmNuserData, fd->boldW, NULL);
4028 boldItalicLbl = XtVaCreateManagedWidget("boldItalicLbl", xmLabelGadgetClass,
4029 highlightForm,
4030 XmNlabelString, s1=XmStringCreateSimple("Bold Italic Font"),
4031 XmNmnemonic, 'l',
4032 XmNalignment, XmALIGNMENT_BEGINNING,
4033 XmNtopAttachment, XmATTACH_WIDGET,
4034 XmNtopWidget, boldBtn,
4035 XmNtopOffset, MARGIN_SPACING,
4036 XmNleftAttachment, XmATTACH_POSITION,
4037 XmNleftPosition, 1, NULL);
4038 XmStringFree(s1);
4040 fd->boldItalicErrW = XtVaCreateManagedWidget("boldItalicErrLbl",
4041 xmLabelGadgetClass, highlightForm,
4042 XmNlabelString, s1=XmStringCreateSimple(""),
4043 XmNalignment, XmALIGNMENT_END,
4044 XmNtopAttachment, XmATTACH_WIDGET,
4045 XmNtopWidget, boldBtn,
4046 XmNtopOffset, MARGIN_SPACING,
4047 XmNleftAttachment, XmATTACH_WIDGET,
4048 XmNleftWidget, boldItalicLbl,
4049 XmNrightAttachment, XmATTACH_POSITION,
4050 XmNrightPosition, 99, NULL);
4051 XmStringFree(s1);
4053 boldItalicBtn = XtVaCreateManagedWidget("boldItalicBtn",
4054 xmPushButtonWidgetClass, highlightForm,
4055 XmNlabelString, s1=XmStringCreateSimple("Browse..."),
4056 XmNmnemonic, 's',
4057 XmNtopAttachment, XmATTACH_WIDGET,
4058 XmNtopWidget, boldItalicLbl,
4059 XmNtopOffset, BTN_TEXT_OFFSET,
4060 XmNleftAttachment, XmATTACH_POSITION,
4061 XmNleftPosition, 1, NULL);
4062 XmStringFree(s1);
4063 XtAddCallback(boldItalicBtn, XmNactivateCallback, boldItalicBrowseCB, fd);
4065 fd->boldItalicW = XtVaCreateManagedWidget("boldItalic",
4066 xmTextWidgetClass, highlightForm,
4067 XmNmaxLength, MAX_FONT_LEN,
4068 XmNleftAttachment, XmATTACH_WIDGET,
4069 XmNleftWidget, boldItalicBtn,
4070 XmNtopAttachment, XmATTACH_WIDGET,
4071 XmNtopWidget, boldItalicLbl,
4072 XmNrightAttachment, XmATTACH_POSITION,
4073 XmNrightPosition, 99, NULL);
4074 RemapDeleteKey(fd->boldItalicW);
4075 XtAddCallback(fd->boldItalicW, XmNvalueChangedCallback,
4076 boldItalicModifiedCB, fd);
4077 XtVaSetValues(boldItalicLbl, XmNuserData, fd->boldItalicW, NULL);
4079 okBtn = XtVaCreateManagedWidget("ok", xmPushButtonWidgetClass, form,
4080 XmNlabelString, s1=XmStringCreateSimple("OK"),
4081 XmNmarginWidth, BUTTON_WIDTH_MARGIN,
4082 XmNtopAttachment, XmATTACH_WIDGET,
4083 XmNtopWidget, highlightFrame,
4084 XmNtopOffset, MARGIN_SPACING,
4085 XmNleftAttachment, XmATTACH_POSITION,
4086 XmNleftPosition, forWindow ? 13 : 26,
4087 XmNrightAttachment, XmATTACH_POSITION,
4088 XmNrightPosition, forWindow ? 27 : 40, NULL);
4089 XtAddCallback(okBtn, XmNactivateCallback, fontOkCB, fd);
4090 XmStringFree(s1);
4092 if (forWindow) {
4093 applyBtn = XtVaCreateManagedWidget("apply",xmPushButtonWidgetClass,form,
4094 XmNlabelString, s1=XmStringCreateSimple("Apply"),
4095 XmNmnemonic, 'A',
4096 XmNtopAttachment, XmATTACH_WIDGET,
4097 XmNtopWidget, highlightFrame,
4098 XmNtopOffset, MARGIN_SPACING,
4099 XmNleftAttachment, XmATTACH_POSITION,
4100 XmNleftPosition, 43,
4101 XmNrightAttachment, XmATTACH_POSITION,
4102 XmNrightPosition, 57, NULL);
4103 XtAddCallback(applyBtn, XmNactivateCallback, fontApplyCB, fd);
4104 XmStringFree(s1);
4107 cancelBtn = XtVaCreateManagedWidget("cancel",
4108 xmPushButtonWidgetClass, form,
4109 XmNlabelString,
4110 s1 = XmStringCreateSimple(forWindow ? "Close" : "Cancel"),
4111 XmNtopAttachment, XmATTACH_WIDGET,
4112 XmNtopWidget, highlightFrame,
4113 XmNtopOffset, MARGIN_SPACING,
4114 XmNleftAttachment, XmATTACH_POSITION,
4115 XmNleftPosition, forWindow ? 73 : 59,
4116 XmNrightAttachment, XmATTACH_POSITION,
4117 XmNrightPosition, forWindow ? 87 : 73,
4118 NULL);
4119 XtAddCallback(cancelBtn, XmNactivateCallback, fontCancelCB, fd);
4120 XmStringFree(s1);
4122 /* Set initial default button */
4123 XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
4124 XtVaSetValues(form, XmNcancelButton, cancelBtn, NULL);
4126 /* Set initial values */
4127 if (forWindow) {
4128 XmTextSetString(fd->primaryW, window->fontName);
4129 XmTextSetString(fd->boldW, window->boldFontName);
4130 XmTextSetString(fd->italicW, window->italicFontName);
4131 XmTextSetString(fd->boldItalicW, window->boldItalicFontName);
4132 } else {
4133 XmTextSetString(fd->primaryW, GetPrefFontName());
4134 XmTextSetString(fd->boldW, GetPrefBoldFontName());
4135 XmTextSetString(fd->italicW, GetPrefItalicFontName());
4136 XmTextSetString(fd->boldItalicW, GetPrefBoldItalicFontName());
4139 /* Handle mnemonic selection of buttons and focus to dialog */
4140 AddDialogMnemonicHandler(form, FALSE);
4142 /* put up dialog */
4143 ManageDialogCenteredOnPointer(form);
4146 static void fillFromPrimaryCB(Widget w, XtPointer clientData,
4147 XtPointer callData)
4149 fontDialog *fd = (fontDialog *)clientData;
4150 char *primaryName, *errMsg;
4151 char modifiedFontName[MAX_FONT_LEN];
4152 char *searchString = "(-[^-]*-[^-]*)-([^-]*)-([^-]*)-(.*)";
4153 char *italicReplaceString = "\\1-\\2-o-\\4";
4154 char *boldReplaceString = "\\1-bold-\\3-\\4";
4155 char *boldItalicReplaceString = "\\1-bold-o-\\4";
4156 regexp *compiledRE;
4158 /* Match the primary font agains RE pattern for font names. If it
4159 doesn't match, we can't generate highlight font names, so return */
4160 compiledRE = CompileRE(searchString, &errMsg, REDFLT_STANDARD);
4161 primaryName = XmTextGetString(fd->primaryW);
4162 if (!ExecRE(compiledRE, primaryName, NULL, False, '\0', '\0', NULL, NULL, NULL)) {
4163 XBell(XtDisplay(fd->shell), 0);
4164 free(compiledRE);
4165 XtFree(primaryName);
4166 return;
4169 /* Make up names for new fonts based on RE replace patterns */
4170 SubstituteRE(compiledRE, italicReplaceString, modifiedFontName,
4171 MAX_FONT_LEN);
4172 XmTextSetString(fd->italicW, modifiedFontName);
4173 SubstituteRE(compiledRE, boldReplaceString, modifiedFontName,
4174 MAX_FONT_LEN);
4175 XmTextSetString(fd->boldW, modifiedFontName);
4176 SubstituteRE(compiledRE, boldItalicReplaceString, modifiedFontName,
4177 MAX_FONT_LEN);
4178 XmTextSetString(fd->boldItalicW, modifiedFontName);
4179 XtFree(primaryName);
4180 free(compiledRE);
4183 static void primaryModifiedCB(Widget w, XtPointer clientData,
4184 XtPointer callData)
4186 fontDialog *fd = (fontDialog *)clientData;
4188 showFontStatus(fd, fd->italicW, fd->italicErrW);
4189 showFontStatus(fd, fd->boldW, fd->boldErrW);
4190 showFontStatus(fd, fd->boldItalicW, fd->boldItalicErrW);
4192 static void italicModifiedCB(Widget w, XtPointer clientData, XtPointer callData)
4194 fontDialog *fd = (fontDialog *)clientData;
4196 showFontStatus(fd, fd->italicW, fd->italicErrW);
4198 static void boldModifiedCB(Widget w, XtPointer clientData, XtPointer callData)
4200 fontDialog *fd = (fontDialog *)clientData;
4202 showFontStatus(fd, fd->boldW, fd->boldErrW);
4204 static void boldItalicModifiedCB(Widget w, XtPointer clientData,
4205 XtPointer callData)
4207 fontDialog *fd = (fontDialog *)clientData;
4209 showFontStatus(fd, fd->boldItalicW, fd->boldItalicErrW);
4212 static void primaryBrowseCB(Widget w, XtPointer clientData, XtPointer callData)
4214 fontDialog *fd = (fontDialog *)clientData;
4216 browseFont(fd->shell, fd->primaryW);
4218 static void italicBrowseCB(Widget w, XtPointer clientData, XtPointer callData)
4220 fontDialog *fd = (fontDialog *)clientData;
4222 browseFont(fd->shell, fd->italicW);
4224 static void boldBrowseCB(Widget w, XtPointer clientData, XtPointer callData)
4226 fontDialog *fd = (fontDialog *)clientData;
4228 browseFont(fd->shell, fd->boldW);
4230 static void boldItalicBrowseCB(Widget w, XtPointer clientData,
4231 XtPointer callData)
4233 fontDialog *fd = (fontDialog *)clientData;
4235 browseFont(fd->shell, fd->boldItalicW);
4238 static void fontDestroyCB(Widget w, XtPointer clientData, XtPointer callData)
4240 fontDialog *fd = (fontDialog *)clientData;
4242 fd->window->fontDialog = NULL;
4243 XtFree((char *)fd);
4246 static void fontOkCB(Widget w, XtPointer clientData, XtPointer callData)
4248 fontDialog *fd = (fontDialog *)clientData;
4250 updateFonts(fd);
4252 /* pop down and destroy the dialog */
4253 XtDestroyWidget(fd->shell);
4256 static void fontApplyCB(Widget w, XtPointer clientData, XtPointer callData)
4258 fontDialog *fd = (fontDialog *)clientData;
4260 updateFonts(fd);
4263 static void fontCancelCB(Widget w, XtPointer clientData, XtPointer callData)
4265 fontDialog *fd = (fontDialog *)clientData;
4267 /* pop down and destroy the dialog */
4268 XtDestroyWidget(fd->shell);
4272 ** Check over a font name in a text field to make sure it agrees with the
4273 ** primary font in height and spacing.
4275 static int checkFontStatus(fontDialog *fd, Widget fontTextFieldW)
4277 char *primaryName, *testName;
4278 XFontStruct *primaryFont, *testFont;
4279 Display *display = XtDisplay(fontTextFieldW);
4280 int primaryWidth, primaryHeight, testWidth, testHeight;
4282 /* Get width and height of the font to check. Note the test for empty
4283 name: X11R6 clients freak out X11R5 servers if they ask them to load
4284 an empty font name, and kill the whole application! */
4285 testName = XmTextGetString(fontTextFieldW);
4286 if (testName[0] == '\0') {
4287 XtFree(testName);
4288 return BAD_FONT;
4290 testFont = XLoadQueryFont(display, testName);
4291 if (testFont == NULL) {
4292 XtFree(testName);
4293 return BAD_FONT;
4295 XtFree(testName);
4296 testWidth = testFont->min_bounds.width;
4297 testHeight = testFont->ascent + testFont->descent;
4298 XFreeFont(display, testFont);
4300 /* Get width and height of the primary font */
4301 primaryName = XmTextGetString(fd->primaryW);
4302 if (primaryName[0] == '\0') {
4303 XtFree(primaryName);
4304 return BAD_FONT;
4306 primaryFont = XLoadQueryFont(display, primaryName);
4307 if (primaryFont == NULL) {
4308 XtFree(primaryName);
4309 return BAD_PRIMARY;
4311 XtFree(primaryName);
4312 primaryWidth = primaryFont->min_bounds.width;
4313 primaryHeight = primaryFont->ascent + primaryFont->descent;
4314 XFreeFont(display, primaryFont);
4316 /* Compare font information */
4317 if (testWidth != primaryWidth)
4318 return BAD_SPACING;
4319 if (testHeight != primaryHeight)
4320 return BAD_SIZE;
4321 return GOOD_FONT;
4325 ** Update the error label for a font text field to reflect its validity and degree
4326 ** of agreement with the currently selected primary font
4328 static int showFontStatus(fontDialog *fd, Widget fontTextFieldW,
4329 Widget errorLabelW)
4331 int status;
4332 XmString s;
4333 char *msg;
4335 status = checkFontStatus(fd, fontTextFieldW);
4336 if (status == BAD_PRIMARY)
4337 msg = "(font below may not match primary font)";
4338 else if (status == BAD_FONT)
4339 msg = "(xxx font below is invalid xxx)";
4340 else if (status == BAD_SIZE)
4341 msg = "(height of font below does not match primary)";
4342 else if (status == BAD_SPACING)
4343 msg = "(spacing of font below does not match primary)";
4344 else
4345 msg = "";
4347 XtVaSetValues(errorLabelW, XmNlabelString, s=XmStringCreateSimple(msg),
4348 NULL);
4349 XmStringFree(s);
4350 return status;
4354 ** Put up a font selector panel to set the font name in the text widget "fontTextW"
4356 static void browseFont(Widget parent, Widget fontTextW)
4358 char *origFontName, *newFontName;
4359 Pixel fgPixel, bgPixel;
4360 int dummy;
4362 origFontName = XmTextGetString(fontTextW);
4364 /* Get the values from the defaults */
4365 fgPixel = AllocColor(parent, GetPrefColorName(TEXT_FG_COLOR),
4366 &dummy, &dummy, &dummy);
4367 bgPixel = AllocColor(parent, GetPrefColorName(TEXT_BG_COLOR),
4368 &dummy, &dummy, &dummy);
4370 newFontName = FontSel(parent, PREF_FIXED, origFontName, fgPixel, bgPixel);
4371 XtFree(origFontName);
4372 if (newFontName == NULL)
4373 return;
4374 XmTextSetString(fontTextW, newFontName);
4375 XtFree(newFontName);
4379 ** Accept the changes in the dialog and set the fonts regardless of errors
4381 static void updateFonts(fontDialog *fd)
4383 char *fontName, *italicName, *boldName, *boldItalicName;
4385 fontName = XmTextGetString(fd->primaryW);
4386 italicName = XmTextGetString(fd->italicW);
4387 boldName = XmTextGetString(fd->boldW);
4388 boldItalicName = XmTextGetString(fd->boldItalicW);
4390 if (fd->forWindow) {
4391 char *params[4];
4392 params[0] = fontName;
4393 params[1] = italicName;
4394 params[2] = boldName;
4395 params[3] = boldItalicName;
4396 XtCallActionProc(fd->window->textArea, "set_fonts", NULL, params, 4);
4398 SetFonts(fd->window, fontName, italicName, boldName, boldItalicName);
4401 else {
4402 SetPrefFont(fontName);
4403 SetPrefItalicFont(italicName);
4404 SetPrefBoldFont(boldName);
4405 SetPrefBoldItalicFont(boldItalicName);
4407 XtFree(fontName);
4408 XtFree(italicName);
4409 XtFree(boldName);
4410 XtFree(boldItalicName);
4414 ** Change the language mode to the one indexed by "mode", reseting word
4415 ** delimiters, syntax highlighting and other mode specific parameters
4417 static void reapplyLanguageMode(WindowInfo *window, int mode, int forceDefaults)
4419 char *delimiters;
4420 int i, wrapMode, indentStyle, tabDist, emTabDist, highlight, oldEmTabDist;
4421 int wrapModeIsDef, tabDistIsDef, emTabDistIsDef, indentStyleIsDef;
4422 int highlightIsDef, haveHighlightPatterns, haveSmartIndentMacros;
4423 int oldMode = window->languageMode;
4425 /* If the mode is the same, and changes aren't being forced (as might
4426 happen with Save As...), don't mess with already correct settings */
4427 if (window->languageMode == mode && !forceDefaults)
4428 return;
4430 /* Change the mode name stored in the window */
4431 window->languageMode = mode;
4433 /* Decref oldMode's default calltips file if needed */
4434 if (oldMode != PLAIN_LANGUAGE_MODE && LanguageModes[oldMode]->defTipsFile) {
4435 DeleteTagsFile( LanguageModes[oldMode]->defTipsFile, TIP, False );
4438 /* Set delimiters for all text widgets */
4439 if (mode == PLAIN_LANGUAGE_MODE || LanguageModes[mode]->delimiters == NULL)
4440 delimiters = GetPrefDelimiters();
4441 else
4442 delimiters = LanguageModes[mode]->delimiters;
4443 XtVaSetValues(window->textArea, textNwordDelimiters, delimiters, NULL);
4444 for (i=0; i<window->nPanes; i++)
4445 XtVaSetValues(window->textPanes[i], textNautoIndent, delimiters, NULL);
4447 /* Decide on desired values for language-specific parameters. If a
4448 parameter was set to its default value, set it to the new default,
4449 otherwise, leave it alone */
4450 wrapModeIsDef = window->wrapMode == GetPrefWrap(oldMode);
4451 tabDistIsDef = BufGetTabDistance(window->buffer) == GetPrefTabDist(oldMode);
4452 XtVaGetValues(window->textArea, textNemulateTabs, &oldEmTabDist, NULL);
4453 emTabDistIsDef = oldEmTabDist == GetPrefEmTabDist(oldMode);
4454 indentStyleIsDef = window->indentStyle == GetPrefAutoIndent(oldMode) ||
4455 (GetPrefAutoIndent(oldMode) == SMART_INDENT &&
4456 window->indentStyle == AUTO_INDENT &&
4457 !SmartIndentMacrosAvailable(LanguageModeName(oldMode)));
4458 highlightIsDef = window->highlightSyntax == GetPrefHighlightSyntax()
4459 || (GetPrefHighlightSyntax() &&
4460 FindPatternSet(LanguageModeName(oldMode)) == NULL);
4461 wrapMode = wrapModeIsDef || forceDefaults ?
4462 GetPrefWrap(mode) : window->wrapMode;
4463 tabDist = tabDistIsDef || forceDefaults ?
4464 GetPrefTabDist(mode) : BufGetTabDistance(window->buffer);
4465 emTabDist = emTabDistIsDef || forceDefaults ?
4466 GetPrefEmTabDist(mode) : oldEmTabDist;
4467 indentStyle = indentStyleIsDef || forceDefaults ?
4468 GetPrefAutoIndent(mode) : window->indentStyle;
4469 highlight = highlightIsDef || forceDefaults ?
4470 GetPrefHighlightSyntax() : window->highlightSyntax;
4472 /* Dim/undim smart-indent and highlighting menu items depending on
4473 whether patterns/macros are available */
4474 haveHighlightPatterns = FindPatternSet(LanguageModeName(mode)) != NULL;
4475 haveSmartIndentMacros = SmartIndentMacrosAvailable(LanguageModeName(mode));
4476 if (IsTopDocument(window)) {
4477 XtSetSensitive(window->highlightItem, haveHighlightPatterns);
4478 XtSetSensitive(window->smartIndentItem, haveSmartIndentMacros);
4481 /* Turn off requested options which are not available */
4482 highlight = haveHighlightPatterns && highlight;
4483 if (indentStyle == SMART_INDENT && !haveSmartIndentMacros)
4484 indentStyle = AUTO_INDENT;
4486 /* Change highlighting */
4487 window->highlightSyntax = highlight;
4488 SetToggleButtonState(window, window->highlightItem, highlight, False);
4489 StopHighlighting(window);
4491 /* we defer highlighting to RaiseDocument() if doc is hidden */
4492 if (IsTopDocument(window) && highlight)
4493 StartHighlighting(window, False);
4495 /* Force a change of smart indent macros (SetAutoIndent will re-start) */
4496 if (window->indentStyle == SMART_INDENT) {
4497 EndSmartIndent(window);
4498 window->indentStyle = AUTO_INDENT;
4501 /* set requested wrap, indent, and tabs */
4502 SetAutoWrap(window, wrapMode);
4503 SetAutoIndent(window, indentStyle);
4504 SetTabDist(window, tabDist);
4505 SetEmTabDist(window, emTabDist);
4507 /* Load calltips files for new mode */
4508 if (mode != PLAIN_LANGUAGE_MODE && LanguageModes[mode]->defTipsFile) {
4509 AddTagsFile( LanguageModes[mode]->defTipsFile, TIP );
4512 /* Add/remove language specific menu items */
4513 UpdateUserMenus(window);
4517 ** Find and return the name of the appropriate languange mode for
4518 ** the file in "window". Returns a pointer to a string, which will
4519 ** remain valid until a change is made to the language modes list.
4521 static int matchLanguageMode(WindowInfo *window)
4523 char *ext, *first200;
4524 int i, j, fileNameLen, extLen, beginPos, endPos, start;
4525 const char *versionExtendedPath;
4527 /*... look for an explicit mode statement first */
4529 /* Do a regular expression search on for recognition pattern */
4530 first200 = BufGetRange(window->buffer, 0, 200);
4531 for (i=0; i<NLanguageModes; i++) {
4532 if (LanguageModes[i]->recognitionExpr != NULL) {
4533 if (SearchString(first200, LanguageModes[i]->recognitionExpr,
4534 SEARCH_FORWARD, SEARCH_REGEX, False, 0, &beginPos,
4535 &endPos, NULL, NULL, NULL))
4537 XtFree(first200);
4538 return i;
4542 XtFree(first200);
4544 /* Look at file extension ("@@/" starts a ClearCase version extended path,
4545 which gets appended after the file extension, and therefore must be
4546 stripped off to recognize the extension to make ClearCase users happy) */
4547 fileNameLen = strlen(window->filename);
4548 #ifdef VMS
4549 if (strchr(window->filename, ';') != NULL)
4550 fileNameLen = strchr(window->filename, ';') - window->filename;
4551 #else
4552 if ((versionExtendedPath = GetClearCaseVersionExtendedPath(window->filename)) != NULL)
4553 fileNameLen = versionExtendedPath - window->filename;
4554 #endif
4555 for (i=0; i<NLanguageModes; i++) {
4556 for (j=0; j<LanguageModes[i]->nExtensions; j++) {
4557 ext = LanguageModes[i]->extensions[j];
4558 extLen = strlen(ext);
4559 start = fileNameLen - extLen;
4560 #if defined(__VMS) && (__VMS_VER >= 70200000)
4561 /* VMS v7.2 has case-preserving filenames */
4562 if (start >= 0 && !strncasecmp(&window->filename[start], ext, extLen))
4563 return i;
4564 #else
4565 if (start >= 0 && !strncmp(&window->filename[start], ext, extLen))
4566 return i;
4567 #endif
4571 /* no appropriate mode was found */
4572 return PLAIN_LANGUAGE_MODE;
4575 static int loadLanguageModesString(char *inString, int fileVer)
4577 char *errMsg, *styleName, *inPtr = inString;
4578 languageModeRec *lm;
4579 int i;
4581 for (;;) {
4583 /* skip over blank space */
4584 inPtr += strspn(inPtr, " \t\n");
4586 /* Allocate a language mode structure to return, set unread fields to
4587 empty so everything can be freed on errors by freeLanguageModeRec */
4588 lm = (languageModeRec *)XtMalloc(sizeof(languageModeRec));
4589 lm->nExtensions = 0;
4590 lm->recognitionExpr = NULL;
4591 lm->defTipsFile = NULL;
4592 lm->delimiters = NULL;
4594 /* read language mode name */
4595 lm->name = ReadSymbolicField(&inPtr);
4596 if (lm->name == NULL) {
4597 XtFree((char *)lm);
4598 return modeError(NULL,inString,inPtr,"language mode name required");
4600 if (!SkipDelimiter(&inPtr, &errMsg))
4601 return modeError(lm, inString, inPtr, errMsg);
4603 /* read list of extensions */
4604 lm->extensions = readExtensionList(&inPtr,
4605 &lm->nExtensions);
4606 if (!SkipDelimiter(&inPtr, &errMsg))
4607 return modeError(lm, inString, inPtr, errMsg);
4609 /* read the recognition regular expression */
4610 if (*inPtr == '\n' || *inPtr == '\0' || *inPtr == ':')
4611 lm->recognitionExpr = NULL;
4612 else if (!ReadQuotedString(&inPtr, &errMsg, &lm->recognitionExpr))
4613 return modeError(lm, inString,inPtr, errMsg);
4614 if (!SkipDelimiter(&inPtr, &errMsg))
4615 return modeError(lm, inString, inPtr, errMsg);
4617 /* read the indent style */
4618 styleName = ReadSymbolicField(&inPtr);
4619 if (styleName == NULL)
4620 lm->indentStyle = DEFAULT_INDENT;
4621 else {
4622 for (i=0; i<N_INDENT_STYLES; i++) {
4623 if (!strcmp(styleName, AutoIndentTypes[i])) {
4624 lm->indentStyle = i;
4625 break;
4628 XtFree(styleName);
4629 if (i == N_INDENT_STYLES)
4630 return modeError(lm,inString,inPtr,"unrecognized indent style");
4632 if (!SkipDelimiter(&inPtr, &errMsg))
4633 return modeError(lm, inString, inPtr, errMsg);
4635 /* read the wrap style */
4636 styleName = ReadSymbolicField(&inPtr);
4637 if (styleName == NULL)
4638 lm->wrapStyle = DEFAULT_WRAP;
4639 else {
4640 for (i=0; i<N_WRAP_STYLES; i++) {
4641 if (!strcmp(styleName, AutoWrapTypes[i])) {
4642 lm->wrapStyle = i;
4643 break;
4646 XtFree(styleName);
4647 if (i == N_WRAP_STYLES)
4648 return modeError(lm, inString, inPtr,"unrecognized wrap style");
4650 if (!SkipDelimiter(&inPtr, &errMsg))
4651 return modeError(lm, inString, inPtr, errMsg);
4653 /* read the tab distance */
4654 if (*inPtr == '\n' || *inPtr == '\0' || *inPtr == ':')
4655 lm->tabDist = DEFAULT_TAB_DIST;
4656 else if (!ReadNumericField(&inPtr, &lm->tabDist))
4657 return modeError(lm, inString, inPtr, "bad tab spacing");
4658 if (!SkipDelimiter(&inPtr, &errMsg))
4659 return modeError(lm, inString, inPtr, errMsg);
4661 /* read emulated tab distance */
4662 if (*inPtr == '\n' || *inPtr == '\0' || *inPtr == ':')
4663 lm->emTabDist = DEFAULT_EM_TAB_DIST;
4664 else if (!ReadNumericField(&inPtr, &lm->emTabDist))
4665 return modeError(lm, inString, inPtr, "bad emulated tab spacing");
4666 if (!SkipDelimiter(&inPtr, &errMsg))
4667 return modeError(lm, inString, inPtr, errMsg);
4669 /* read the delimiters string */
4670 if (*inPtr == '\n' || *inPtr == '\0' || *inPtr == ':')
4671 lm->delimiters = NULL;
4672 else if (!ReadQuotedString(&inPtr, &errMsg, &lm->delimiters))
4673 return modeError(lm, inString, inPtr, errMsg);
4675 /* After 5.3 all language modes need a default tips file field */
4676 if (!SkipDelimiter(&inPtr, &errMsg))
4677 if (fileVer > 5003)
4678 return modeError(lm, inString, inPtr, errMsg);
4680 /* read the default tips file */
4681 if (*inPtr == '\n' || *inPtr == '\0')
4682 lm->defTipsFile = NULL;
4683 else if (!ReadQuotedString(&inPtr, &errMsg, &lm->defTipsFile))
4684 return modeError(lm, inString, inPtr, errMsg);
4686 /* pattern set was read correctly, add/replace it in the list */
4687 for (i=0; i<NLanguageModes; i++) {
4688 if (!strcmp(LanguageModes[i]->name, lm->name)) {
4689 freeLanguageModeRec(LanguageModes[i]);
4690 LanguageModes[i] = lm;
4691 break;
4694 if (i == NLanguageModes) {
4695 LanguageModes[NLanguageModes++] = lm;
4696 if (NLanguageModes > MAX_LANGUAGE_MODES)
4697 return modeError(NULL, inString, inPtr,
4698 "maximum allowable number of language modes exceeded");
4701 /* if the string ends here, we're done */
4702 inPtr += strspn(inPtr, " \t\n");
4703 if (*inPtr == '\0')
4704 return True;
4705 } /* End for(;;) */
4708 static char *writeLanguageModesString(void)
4710 int i;
4711 char *outStr, *escapedStr, *str, numBuf[25];
4712 textBuffer *outBuf;
4714 outBuf = BufCreate();
4715 for (i=0; i<NLanguageModes; i++) {
4716 BufInsert(outBuf, outBuf->length, "\t");
4717 BufInsert(outBuf, outBuf->length, LanguageModes[i]->name);
4718 BufInsert(outBuf, outBuf->length, ":");
4719 BufInsert(outBuf, outBuf->length, str = createExtString(
4720 LanguageModes[i]->extensions, LanguageModes[i]->nExtensions));
4721 XtFree(str);
4722 BufInsert(outBuf, outBuf->length, ":");
4723 if (LanguageModes[i]->recognitionExpr != NULL) {
4724 BufInsert(outBuf, outBuf->length,
4725 str=MakeQuotedString(LanguageModes[i]->recognitionExpr));
4726 XtFree(str);
4728 BufInsert(outBuf, outBuf->length, ":");
4729 if (LanguageModes[i]->indentStyle != DEFAULT_INDENT)
4730 BufInsert(outBuf, outBuf->length,
4731 AutoIndentTypes[LanguageModes[i]->indentStyle]);
4732 BufInsert(outBuf, outBuf->length, ":");
4733 if (LanguageModes[i]->wrapStyle != DEFAULT_WRAP)
4734 BufInsert(outBuf, outBuf->length,
4735 AutoWrapTypes[LanguageModes[i]->wrapStyle]);
4736 BufInsert(outBuf, outBuf->length, ":");
4737 if (LanguageModes[i]->tabDist != DEFAULT_TAB_DIST) {
4738 sprintf(numBuf, "%d", LanguageModes[i]->tabDist);
4739 BufInsert(outBuf, outBuf->length, numBuf);
4741 BufInsert(outBuf, outBuf->length, ":");
4742 if (LanguageModes[i]->emTabDist != DEFAULT_EM_TAB_DIST) {
4743 sprintf(numBuf, "%d", LanguageModes[i]->emTabDist);
4744 BufInsert(outBuf, outBuf->length, numBuf);
4746 BufInsert(outBuf, outBuf->length, ":");
4747 if (LanguageModes[i]->delimiters != NULL) {
4748 BufInsert(outBuf, outBuf->length,
4749 str=MakeQuotedString(LanguageModes[i]->delimiters));
4750 XtFree(str);
4752 BufInsert(outBuf, outBuf->length, ":");
4753 if (LanguageModes[i]->defTipsFile != NULL) {
4754 BufInsert(outBuf, outBuf->length,
4755 str=MakeQuotedString(LanguageModes[i]->defTipsFile));
4756 XtFree(str);
4759 BufInsert(outBuf, outBuf->length, "\n");
4762 /* Get the output, and lop off the trailing newline */
4763 outStr = BufGetRange(outBuf, 0, outBuf->length - 1);
4764 BufFree(outBuf);
4765 escapedStr = EscapeSensitiveChars(outStr);
4766 XtFree(outStr);
4767 return escapedStr;
4770 static char *createExtString(char **extensions, int nExtensions)
4772 int e, length = 1;
4773 char *outStr, *outPtr;
4775 for (e=0; e<nExtensions; e++)
4776 length += strlen(extensions[e]) + 1;
4777 outStr = outPtr = XtMalloc(length);
4778 for (e=0; e<nExtensions; e++) {
4779 strcpy(outPtr, extensions[e]);
4780 outPtr += strlen(extensions[e]);
4781 *outPtr++ = ' ';
4783 if (nExtensions == 0)
4784 *outPtr = '\0';
4785 else
4786 *(outPtr-1) = '\0';
4787 return outStr;
4790 static char **readExtensionList(char **inPtr, int *nExtensions)
4792 char *extensionList[MAX_FILE_EXTENSIONS];
4793 char **retList, *strStart;
4794 int i, len;
4796 /* skip over blank space */
4797 *inPtr += strspn(*inPtr, " \t");
4799 for (i=0; i<MAX_FILE_EXTENSIONS && **inPtr!=':' && **inPtr!='\0'; i++) {
4800 *inPtr += strspn(*inPtr, " \t");
4801 strStart = *inPtr;
4802 while (**inPtr!=' ' && **inPtr!='\t' && **inPtr!=':' && **inPtr!='\0')
4803 (*inPtr)++;
4804 len = *inPtr - strStart;
4805 extensionList[i] = XtMalloc(len + 1);
4806 strncpy(extensionList[i], strStart, len);
4807 extensionList[i][len] = '\0';
4809 *nExtensions = i;
4810 if (i == 0)
4811 return NULL;
4812 retList = (char **)XtMalloc(sizeof(char *) * i);
4813 memcpy(retList, extensionList, sizeof(char *) * i);
4814 return retList;
4817 int ReadNumericField(char **inPtr, int *value)
4819 int charsRead;
4821 /* skip over blank space */
4822 *inPtr += strspn(*inPtr, " \t");
4824 if (sscanf(*inPtr, "%d%n", value, &charsRead) != 1)
4825 return False;
4826 *inPtr += charsRead;
4827 return True;
4831 ** Parse a symbolic field, skipping initial and trailing whitespace,
4832 ** stops on first invalid character or end of string. Valid characters
4833 ** are letters, numbers, _, -, +, $, #, and internal whitespace. Internal
4834 ** whitespace is compressed to single space characters.
4836 char *ReadSymbolicField(char **inPtr)
4838 char *outStr, *outPtr, *strStart, *strPtr;
4839 int len;
4841 /* skip over initial blank space */
4842 *inPtr += strspn(*inPtr, " \t");
4844 /* Find the first invalid character or end of string to know how
4845 much memory to allocate for the returned string */
4846 strStart = *inPtr;
4847 while (isalnum((unsigned char)**inPtr) || **inPtr=='_' || **inPtr=='-' ||
4848 **inPtr=='+' || **inPtr=='$' || **inPtr=='#' || **inPtr==' ' ||
4849 **inPtr=='\t')
4850 (*inPtr)++;
4851 len = *inPtr - strStart;
4852 if (len == 0)
4853 return NULL;
4854 outStr = outPtr = XtMalloc(len + 1);
4856 /* Copy the string, compressing internal whitespace to a single space */
4857 strPtr = strStart;
4858 while (strPtr - strStart < len) {
4859 if (*strPtr == ' ' || *strPtr == '\t') {
4860 strPtr += strspn(strPtr, " \t");
4861 *outPtr++ = ' ';
4862 } else
4863 *outPtr++ = *strPtr++;
4866 /* If there's space on the end, take it back off */
4867 if (outPtr > outStr && *(outPtr-1) == ' ')
4868 outPtr--;
4869 if (outPtr == outStr) {
4870 XtFree(outStr);
4871 return NULL;
4873 *outPtr = '\0';
4874 return outStr;
4878 ** parse an individual quoted string. Anything between
4879 ** double quotes is acceptable, quote characters can be escaped by "".
4880 ** Returns allocated string "string" containing
4881 ** argument minus quotes. If not successful, returns False with
4882 ** (statically allocated) message in "errMsg".
4884 int ReadQuotedString(char **inPtr, char **errMsg, char **string)
4886 char *outPtr, *c;
4888 /* skip over blank space */
4889 *inPtr += strspn(*inPtr, " \t");
4891 /* look for initial quote */
4892 if (**inPtr != '\"') {
4893 *errMsg = "expecting quoted string";
4894 return False;
4896 (*inPtr)++;
4898 /* calculate max length and allocate returned string */
4899 for (c= *inPtr; ; c++) {
4900 if (*c == '\0') {
4901 *errMsg = "string not terminated";
4902 return False;
4903 } else if (*c == '\"') {
4904 if (*(c+1) == '\"')
4905 c++;
4906 else
4907 break;
4911 /* copy string up to end quote, transforming escaped quotes into quotes */
4912 *string = XtMalloc(c - *inPtr + 1);
4913 outPtr = *string;
4914 while (True) {
4915 if (**inPtr == '\"') {
4916 if (*(*inPtr+1) == '\"')
4917 (*inPtr)++;
4918 else
4919 break;
4921 *outPtr++ = *(*inPtr)++;
4923 *outPtr = '\0';
4925 /* skip end quote */
4926 (*inPtr)++;
4927 return True;
4931 ** Replace characters which the X resource file reader considers control
4932 ** characters, such that a string will read back as it appears in "string".
4933 ** (So far, newline characters are replaced with with \n\<newline> and
4934 ** backslashes with \\. This has not been tested exhaustively, and
4935 ** probably should be. It would certainly be more asthetic if other
4936 ** control characters were replaced as well).
4938 ** Returns an allocated string which must be freed by the caller with XtFree.
4940 char *EscapeSensitiveChars(const char *string)
4942 const char *c;
4943 char *outStr, *outPtr;
4944 int length = 0;
4946 /* calculate length and allocate returned string */
4947 for (c=string; *c!='\0'; c++) {
4948 if (*c == '\\')
4949 length++;
4950 else if (*c == '\n')
4951 length += 3;
4952 length++;
4954 outStr = XtMalloc(length + 1);
4955 outPtr = outStr;
4957 /* add backslashes */
4958 for (c=string; *c!='\0'; c++) {
4959 if (*c == '\\')
4960 *outPtr++ = '\\';
4961 else if (*c == '\n') {
4962 *outPtr++ = '\\';
4963 *outPtr++ = 'n';
4964 *outPtr++ = '\\';
4966 *outPtr++ = *c;
4968 *outPtr = '\0';
4969 return outStr;
4973 ** Adds double quotes around a string and escape existing double quote
4974 ** characters with two double quotes. Enables the string to be read back
4975 ** by ReadQuotedString.
4977 char *MakeQuotedString(const char *string)
4979 const char *c;
4980 char *outStr, *outPtr;
4981 int length = 0;
4983 /* calculate length and allocate returned string */
4984 for (c=string; *c!='\0'; c++) {
4985 if (*c == '\"')
4986 length++;
4987 length++;
4989 outStr = XtMalloc(length + 3);
4990 outPtr = outStr;
4992 /* add starting quote */
4993 *outPtr++ = '\"';
4995 /* copy string, escaping quotes with "" */
4996 for (c=string; *c!='\0'; c++) {
4997 if (*c == '\"')
4998 *outPtr++ = '\"';
4999 *outPtr++ = *c;
5002 /* add ending quote */
5003 *outPtr++ = '\"';
5005 /* terminate string and return */
5006 *outPtr = '\0';
5007 return outStr;
5011 ** Read a dialog text field containing a symbolic name (language mode names,
5012 ** style names, highlight pattern names, colors, and fonts), clean the
5013 ** entered text of leading and trailing whitespace, compress all
5014 ** internal whitespace to one space character, and check it over for
5015 ** colons, which interfere with the preferences file reader/writer syntax.
5016 ** Returns NULL on error, and puts up a dialog if silent is False. Returns
5017 ** an empty string if the text field is blank.
5019 char *ReadSymbolicFieldTextWidget(Widget textW, const char *fieldName, int silent)
5021 char *string, *stringPtr, *parsedString;
5023 /* read from the text widget */
5024 string = stringPtr = XmTextGetString(textW);
5026 /* parse it with the same routine used to read symbolic fields from
5027 files. If the string is not read entirely, there are invalid
5028 characters, so warn the user if not in silent mode. */
5029 parsedString = ReadSymbolicField(&stringPtr);
5030 if (*stringPtr != '\0')
5032 if (!silent)
5034 *(stringPtr + 1) = '\0';
5035 DialogF(DF_WARN, textW, 1, "Invalid Character",
5036 "Invalid character \"%s\" in %s", "OK", stringPtr,
5037 fieldName);
5038 XmProcessTraversal(textW, XmTRAVERSE_CURRENT);
5040 XtFree(string);
5041 XtFree(parsedString);
5042 return NULL;
5044 XtFree(string);
5045 if (parsedString == NULL) {
5046 parsedString = XtMalloc(1);
5047 *parsedString = '\0';
5049 return parsedString;
5053 ** Create a pulldown menu pane with the names of the current language modes.
5054 ** XmNuserData for each item contains the language mode name.
5056 Widget CreateLanguageModeMenu(Widget parent, XtCallbackProc cbProc, void *cbArg)
5058 Widget menu, btn;
5059 int i;
5060 XmString s1;
5062 menu = CreatePulldownMenu(parent, "languageModes", NULL, 0);
5063 for (i=0; i<NLanguageModes; i++) {
5064 btn = XtVaCreateManagedWidget("languageMode", xmPushButtonGadgetClass,
5065 menu,
5066 XmNlabelString, s1=XmStringCreateSimple(LanguageModes[i]->name),
5067 XmNmarginHeight, 0,
5068 XmNuserData, (void *)LanguageModes[i]->name, NULL);
5069 XmStringFree(s1);
5070 XtAddCallback(btn, XmNactivateCallback, cbProc, cbArg);
5072 return menu;
5076 ** Set the language mode menu in option menu "optMenu" to
5077 ** show a particular language mode
5079 void SetLangModeMenu(Widget optMenu, const char *modeName)
5081 int i;
5082 Cardinal nItems;
5083 WidgetList items;
5084 Widget pulldown, selectedItem;
5085 char *itemName;
5087 XtVaGetValues(optMenu, XmNsubMenuId, &pulldown, NULL);
5088 XtVaGetValues(pulldown, XmNchildren, &items, XmNnumChildren, &nItems, NULL);
5089 if (nItems == 0)
5090 return;
5091 selectedItem = items[0];
5092 for (i=0; i<(int)nItems; i++) {
5093 XtVaGetValues(items[i], XmNuserData, &itemName, NULL);
5094 if (!strcmp(itemName, modeName)) {
5095 selectedItem = items[i];
5096 break;
5099 XtVaSetValues(optMenu, XmNmenuHistory, selectedItem,NULL);
5103 ** Create a submenu for chosing language mode for the current window.
5105 void CreateLanguageModeSubMenu(WindowInfo* window, const Widget parent,
5106 const char* name, const char* label, const char mnemonic)
5108 XmString string = XmStringCreateSimple((char*) label);
5110 window->langModeCascade = XtVaCreateManagedWidget(name,
5111 xmCascadeButtonGadgetClass, parent,
5112 XmNlabelString, string,
5113 XmNmnemonic, mnemonic,
5114 XmNsubMenuId, NULL,
5115 NULL);
5116 XmStringFree(string);
5118 updateLanguageModeSubmenu(window);
5122 ** Re-build the language mode sub-menu using the current data stored
5123 ** in the master list: LanguageModes.
5125 static void updateLanguageModeSubmenu(WindowInfo *window)
5127 int i;
5128 XmString s1;
5129 Widget menu, btn;
5130 Arg args[1] = {{XmNradioBehavior, (XtArgVal)True}};
5132 /* Destroy and re-create the menu pane */
5133 XtVaGetValues(window->langModeCascade, XmNsubMenuId, &menu, NULL);
5134 if (menu != NULL)
5135 XtDestroyWidget(menu);
5136 menu = CreatePulldownMenu(XtParent(window->langModeCascade),
5137 "languageModes", args, 1);
5138 btn = XtVaCreateManagedWidget("languageMode",
5139 xmToggleButtonGadgetClass, menu,
5140 XmNlabelString, s1=XmStringCreateSimple("Plain"),
5141 XmNuserData, (void *)PLAIN_LANGUAGE_MODE,
5142 XmNset, window->languageMode==PLAIN_LANGUAGE_MODE, NULL);
5143 XmStringFree(s1);
5144 XtAddCallback(btn, XmNvalueChangedCallback, setLangModeCB, window);
5145 for (i=0; i<NLanguageModes; i++) {
5146 btn = XtVaCreateManagedWidget("languageMode",
5147 xmToggleButtonGadgetClass, menu,
5148 XmNlabelString, s1=XmStringCreateSimple(LanguageModes[i]->name),
5149 XmNmarginHeight, 0,
5150 XmNuserData, (void *)i,
5151 XmNset, window->languageMode==i, NULL);
5152 XmStringFree(s1);
5153 XtAddCallback(btn, XmNvalueChangedCallback, setLangModeCB, window);
5155 XtVaSetValues(window->langModeCascade, XmNsubMenuId, menu, NULL);
5158 static void setLangModeCB(Widget w, XtPointer clientData, XtPointer callData)
5160 WindowInfo *window = WidgetToWindow(MENU_WIDGET(w));
5161 char *params[1];
5162 void *mode;
5164 if (!XmToggleButtonGetState(w))
5165 return;
5167 /* get name of language mode stored in userData field of menu item */
5168 XtVaGetValues(w, XmNuserData, &mode, NULL);
5170 /* If the mode didn't change, do nothing */
5171 if (window->languageMode == (int)mode)
5172 return;
5174 /* redo syntax highlighting word delimiters, etc. */
5176 reapplyLanguageMode(window, (int)mode, False);
5178 params[0] = (((int)mode) == PLAIN_LANGUAGE_MODE) ? "" : LanguageModes[(int)mode]->name;
5179 XtCallActionProc(window->textArea, "set_language_mode", NULL, params, 1);
5183 ** Skip a delimiter and it's surrounding whitespace
5185 int SkipDelimiter(char **inPtr, char **errMsg)
5187 *inPtr += strspn(*inPtr, " \t");
5188 if (**inPtr != ':') {
5189 *errMsg = "syntax error";
5190 return False;
5192 (*inPtr)++;
5193 *inPtr += strspn(*inPtr, " \t");
5194 return True;
5198 ** Skip an optional separator and its surrounding whitespace
5199 ** return true if delimiter found
5201 int SkipOptSeparator(char separator, char **inPtr)
5203 *inPtr += strspn(*inPtr, " \t");
5204 if (**inPtr != separator) {
5205 return False;
5207 (*inPtr)++;
5208 *inPtr += strspn(*inPtr, " \t");
5209 return True;
5213 ** Short-hand error processing for language mode parsing errors, frees
5214 ** lm (if non-null), prints a formatted message explaining where the
5215 ** error is, and returns False;
5217 static int modeError(languageModeRec *lm, const char *stringStart,
5218 const char *stoppedAt, const char *message)
5220 if (lm != NULL)
5221 freeLanguageModeRec(lm);
5222 return ParseError(NULL, stringStart, stoppedAt,
5223 "language mode specification", message);
5227 ** Report parsing errors in resource strings or macros, formatted nicely so
5228 ** the user can tell where things became botched. Errors can be sent either
5229 ** to stderr, or displayed in a dialog. For stderr, pass toDialog as NULL.
5230 ** For a dialog, pass the dialog parent in toDialog.
5232 int ParseError(Widget toDialog, const char *stringStart, const char *stoppedAt,
5233 const char *errorIn, const char *message)
5235 int len, nNonWhite = 0;
5236 const char *c;
5237 char *errorLine;
5239 for (c=stoppedAt; c>=stringStart; c--) {
5240 if (c == stringStart)
5241 break;
5242 else if (*c == '\n' && nNonWhite >= 5)
5243 break;
5244 else if (*c != ' ' && *c != '\t')
5245 nNonWhite++;
5247 len = stoppedAt - c + (*stoppedAt == '\0' ? 0 : 1);
5248 errorLine = XtMalloc(len+4);
5249 strncpy(errorLine, c, len);
5250 errorLine[len++] = '<';
5251 errorLine[len++] = '=';
5252 errorLine[len++] = '=';
5253 errorLine[len] = '\0';
5254 if (toDialog == NULL)
5256 fprintf(stderr, "NEdit: %s in %s:\n%s\n", message, errorIn, errorLine);
5257 } else
5259 DialogF(DF_WARN, toDialog, 1, "Parse Error", "%s in %s:\n%s", "OK",
5260 message, errorIn, errorLine);
5262 XtFree(errorLine);
5263 return False;
5267 ** Compare two strings which may be NULL
5269 int AllocatedStringsDiffer(const char *s1, const char *s2)
5271 if (s1 == NULL && s2 == NULL)
5272 return False;
5273 if (s1 == NULL || s2 == NULL)
5274 return True;
5275 return strcmp(s1, s2);
5278 static void updatePatternsTo5dot1(void)
5280 const char *htmlDefaultExpr = "^[ \t]*HTML[ \t]*:[ \t]*Default[ \t]*$";
5281 const char *vhdlAnchorExpr = "^[ \t]*VHDL:";
5283 /* Add new patterns if there aren't already existing patterns with
5284 the same name. If possible, insert before VHDL in language mode
5285 list. If not, just add to end */
5286 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*PostScript:"))
5287 spliceString(&TempStringPrefs.highlight, "PostScript:Default",
5288 vhdlAnchorExpr);
5289 if (!regexFind(TempStringPrefs.language, "^[ \t]*PostScript:"))
5290 spliceString(&TempStringPrefs.language,
5291 "PostScript:.ps .PS .eps .EPS .epsf .epsi::::::",
5292 vhdlAnchorExpr);
5293 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*Lex:"))
5294 spliceString(&TempStringPrefs.highlight, "Lex:Default",
5295 vhdlAnchorExpr);
5296 if (!regexFind(TempStringPrefs.language, "^[ \t]*Lex:"))
5297 spliceString(&TempStringPrefs.language, "Lex:.lex::::::",
5298 vhdlAnchorExpr);
5299 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*SQL:"))
5300 spliceString(&TempStringPrefs.highlight, "SQL:Default",
5301 vhdlAnchorExpr);
5302 if (!regexFind(TempStringPrefs.language, "^[ \t]*SQL:"))
5303 spliceString(&TempStringPrefs.language, "SQL:.sql::::::",
5304 vhdlAnchorExpr);
5305 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*Matlab:"))
5306 spliceString(&TempStringPrefs.highlight, "Matlab:Default",
5307 vhdlAnchorExpr);
5308 if (!regexFind(TempStringPrefs.language, "^[ \t]*Matlab:"))
5309 spliceString(&TempStringPrefs.language, "Matlab:..m .oct .sci::::::",
5310 vhdlAnchorExpr);
5311 if (!regexFind(TempStringPrefs.smartIndent, "^[ \t]*Matlab:"))
5312 spliceString(&TempStringPrefs.smartIndent, "Matlab:Default", NULL);
5313 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Label:"))
5314 spliceString(&TempStringPrefs.styles, "Label:red:Italic",
5315 "^[ \t]*Flag:");
5316 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Storage Type1:"))
5317 spliceString(&TempStringPrefs.styles, "Storage Type1:saddle brown:Bold",
5318 "^[ \t]*String:");
5320 /* Replace html pattern with sgml html pattern, as long as there
5321 isn't an existing html pattern which will be overwritten */
5322 if (regexFind(TempStringPrefs.highlight, htmlDefaultExpr)) {
5323 regexReplace(&TempStringPrefs.highlight, htmlDefaultExpr,
5324 "SGML HTML:Default");
5325 if (!regexReplace(&TempStringPrefs.language, "^[ \t]*HTML:.*$",
5326 "SGML HTML:.sgml .sgm .html .htm:\"\\<(?ihtml)\\>\":::::\n")) {
5327 spliceString(&TempStringPrefs.language,
5328 "SGML HTML:.sgml .sgm .html .htm:\"\\<(?ihtml)\\>\":::::\n",
5329 vhdlAnchorExpr);
5334 static void updatePatternsTo5dot2(void)
5336 #ifdef VMS
5337 const char *cppLm5dot1 =
5338 "^[ \t]*C\\+\\+:\\.CC \\.HH \\.I::::::\"\\.,/\\\\`'!\\|@#%\\^&\\*\\(\\)-=\\+\\{\\}\\[\\]\"\":;\\<\\>\\?~\"";
5339 const char *perlLm5dot1 =
5340 "^[ \t]*Perl:\\.PL \\.PM \\.P5:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\.\\*perl\":::::";
5341 const char *psLm5dot1 =
5342 "^[ \t]*PostScript:\\.ps \\.PS \\.eps \\.EPS \\.epsf \\.epsi:\"\\^%!\":::::\"/%\\(\\)\\{\\}\\[\\]\\<\\>\"";
5343 const char *tclLm5dot1 = "^[ \t]*Tcl:\\.TCL::::::";
5345 const char *cppLm5dot2 =
5346 "C++:.CC .HH .C .H .I .CXX .HXX .CPP::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\"";
5347 const char *perlLm5dot2 =
5348 "Perl:.PL .PM .P5:\"^[ \\t]*#[ \\t]*!.*perl\":Auto:None:::\".,/\\\\`'!$@#%^&*()-=+{}[]\"\":;<>?~|\"";
5349 const char *psLm5dot2 =
5350 "PostScript:.ps .PS .eps .EPS .epsf .epsi:\"^%!\":::::\"/%(){}[]<>\"";
5351 const char *tclLm5dot2 =
5352 "Tcl:.TCL::Smart:None:::";
5353 #else
5354 const char *cppLm5dot1 =
5355 "^[ \t]*C\\+\\+:\\.cc \\.hh \\.C \\.H \\.i \\.cxx \\.hxx::::::\"\\.,/\\\\`'!\\|@#%\\^&\\*\\(\\)-=\\+\\{\\}\\[\\]\"\":;\\<\\>\\?~\"";
5356 const char *perlLm5dot1 =
5357 "^[ \t]*Perl:\\.pl \\.pm \\.p5:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\.\\*perl\":::::";
5358 const char *psLm5dot1 =
5359 "^[ \t]*PostScript:\\.ps \\.PS \\.eps \\.EPS \\.epsf \\.epsi:\"\\^%!\":::::\"/%\\(\\)\\{\\}\\[\\]\\<\\>\"";
5360 const char *shLm5dot1 =
5361 "^[ \t]*Sh Ksh Bash:\\.sh \\.bash \\.ksh \\.profile:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\[ \\\\t\\]\\*/bin/\\(sh\\|ksh\\|bash\\)\":::::";
5362 const char *tclLm5dot1 = "^[ \t]*Tcl:\\.tcl::::::";
5364 const char *cppLm5dot2 =
5365 "C++:.cc .hh .C .H .i .cxx .hxx .cpp::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\"";
5366 const char *perlLm5dot2 =
5367 "Perl:.pl .pm .p5 .PL:\"^[ \\t]*#[ \\t]*!.*perl\":Auto:None:::\".,/\\\\`'!$@#%^&*()-=+{}[]\"\":;<>?~|\"";
5368 const char *psLm5dot2 =
5369 "PostScript:.ps .eps .epsf .epsi:\"^%!\":::::\"/%(){}[]<>\"";
5370 const char *shLm5dot2 =
5371 "Sh Ksh Bash:.sh .bash .ksh .profile .bashrc .bash_logout .bash_login .bash_profile:\"^[ \\t]*#[ \\t]*![ \\t]*/.*bin/(sh|ksh|bash)\":::::";
5372 const char *tclLm5dot2 =
5373 "Tcl:.tcl .tk .itcl .itk::Smart:None:::";
5374 #endif /* VMS */
5376 const char *cssLm5dot2 =
5377 "CSS:css::Auto:None:::\".,/\\`'!|@#%^&*()=+{}[]\"\":;<>?~\"";
5378 const char *reLm5dot2 =
5379 "Regex:.reg .regex:\"\\(\\?[:#=!iInN].+\\)\":None:Continuous:::";
5380 const char *xmlLm5dot2 =
5381 "XML:.xml .xsl .dtd:\"\\<(?i\\?xml|!doctype)\"::None:::\"<>/=\"\"'()+*?|\"";
5383 const char *cssHl5dot2 = "CSS:Default";
5384 const char *reHl5dot2 = "Regex:Default";
5385 const char *xmlHl5dot2 = "XML:Default";
5387 const char *ptrStyle = "Pointer:#660000:Bold";
5388 const char *reStyle = "Regex:#009944:Bold";
5389 const char *wrnStyle = "Warning:brown2:Italic";
5391 /* First upgrade modified language modes, only if the user hasn't
5392 altered the default 5.1 definitions. */
5393 if (regexFind(TempStringPrefs.language, cppLm5dot1))
5394 regexReplace(&TempStringPrefs.language, cppLm5dot1, cppLm5dot2);
5395 if (regexFind(TempStringPrefs.language, perlLm5dot1))
5396 regexReplace(&TempStringPrefs.language, perlLm5dot1, perlLm5dot2);
5397 if (regexFind(TempStringPrefs.language, psLm5dot1))
5398 regexReplace(&TempStringPrefs.language, psLm5dot1, psLm5dot2);
5399 #ifndef VMS
5400 if (regexFind(TempStringPrefs.language, shLm5dot1))
5401 regexReplace(&TempStringPrefs.language, shLm5dot1, shLm5dot2);
5402 #endif
5403 if (regexFind(TempStringPrefs.language, tclLm5dot1))
5404 regexReplace(&TempStringPrefs.language, tclLm5dot1, tclLm5dot2);
5406 /* Then append the new modes (trying to keep them in alphabetical order
5407 makes no sense, since 5.1 didn't use alphabetical order). */
5408 if (!regexFind(TempStringPrefs.language, "^[ \t]*CSS:"))
5409 spliceString(&TempStringPrefs.language, cssLm5dot2, NULL);
5410 if (!regexFind(TempStringPrefs.language, "^[ \t]*Regex:"))
5411 spliceString(&TempStringPrefs.language, reLm5dot2, NULL);
5412 if (!regexFind(TempStringPrefs.language, "^[ \t]*XML:"))
5413 spliceString(&TempStringPrefs.language, xmlLm5dot2, NULL);
5415 /* Enable default highlighting patterns for these modes, unless already
5416 present */
5417 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*CSS:"))
5418 spliceString(&TempStringPrefs.highlight, cssHl5dot2, NULL);
5419 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*Regex:"))
5420 spliceString(&TempStringPrefs.highlight, reHl5dot2, NULL);
5421 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*XML:"))
5422 spliceString(&TempStringPrefs.highlight, xmlHl5dot2, NULL);
5424 /* Finally, append the new highlight styles */
5426 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Warning:"))
5427 spliceString(&TempStringPrefs.styles, wrnStyle, NULL);
5428 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Regex:"))
5429 spliceString(&TempStringPrefs.styles, reStyle, "^[ \t]*Warning:");
5430 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Pointer:"))
5431 spliceString(&TempStringPrefs.styles, ptrStyle, "^[ \t]*Regex:");
5434 static void updatePatternsTo5dot3(void)
5436 /* This is a bogus function on non-VMS */
5437 #ifdef VMS
5438 const char *psLm5dot2 =
5439 "^[ \t]*PostScript:\\.ps \\.PS \\.eps \\.EPS \\.epsf \\.epsi:\"\\^%!\":::::\"/%\\(\\)\\{\\}\\[\\]\\<\\>\"";
5441 const char *psLm5dot3 =
5442 "PostScript:.ps .PS .eps .EPS .epsf .EPSF .epsi .EPSI:\"^%!\":::::\"/%(){}[]<>\"";
5444 /* Upgrade modified language modes, only if the user hasn't
5445 altered the default 5.2 definitions. */
5446 if (regexFind(TempStringPrefs.language, psLm5dot2))
5447 regexReplace(&TempStringPrefs.language, psLm5dot2, psLm5dot3);
5448 #endif
5451 static void updatePatternsTo5dot4(void)
5453 #ifdef VMS
5454 const char *pyLm5dot3 =
5455 "Python:\\.PY:\"\\^#!\\.\\*python\":Auto:None::::?\n";
5456 const char *xrLm5dot3 =
5457 "X Resources:\\.XRESOURCES \\.XDEFAULTS \\.NEDIT:\"\\^\\[!#\\]\\.\\*\\(\\[Aa\\]pp\\|\\[Xx\\]\\)\\.\\*\\[Dd\\]efaults\"::::::?\n";
5459 const char *pyLm5dot4 =
5460 "Python:.PY:\"^#!.*python\":Auto:None:::\"!\"\"#$%&'()*+,-./:;<=>?@[\\\\]^`{|}~\":\n";
5461 const char *xrLm5dot4 =
5462 "X Resources:.XRESOURCES .XDEFAULTS .NEDIT NEDIT.RC:\"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults\"::::::\n";
5463 #else
5464 const char *pyLm5dot3 =
5465 "Python:\\.py:\"\\^#!\\.\\*python\":Auto:None::::?\n";
5466 const char *xrLm5dot3 =
5467 "X Resources:\\.Xresources \\.Xdefaults \\.nedit:\"\\^\\[!#\\]\\.\\*\\(\\[Aa\\]pp\\|\\[Xx\\]\\)\\.\\*\\[Dd\\]efaults\"::::::?\n";
5469 const char *pyLm5dot4 =
5470 "Python:.py:\"^#!.*python\":Auto:None:::\"!\"\"#$%&'()*+,-./:;<=>?@[\\\\]^`{|}~\":\n";
5471 const char *xrLm5dot4 =
5472 "X Resources:.Xresources .Xdefaults .nedit nedit.rc:\"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults\"::::::\n";
5473 #endif
5475 /* Upgrade modified language modes, only if the user hasn't
5476 altered the default 5.3 definitions. */
5477 if (regexFind(TempStringPrefs.language, pyLm5dot3))
5478 regexReplace(&TempStringPrefs.language, pyLm5dot3, pyLm5dot4);
5479 if (regexFind(TempStringPrefs.language, xrLm5dot3))
5480 regexReplace(&TempStringPrefs.language, xrLm5dot3, xrLm5dot4);
5482 /* Add new styles */
5483 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Identifier2:"))
5484 spliceString(&TempStringPrefs.styles, "Identifier2:SteelBlue:Plain",
5485 "^[ \t]*Subroutine:");
5488 static void updatePatternsTo5dot6(void)
5490 const char *pats[] = {
5491 #ifndef VMS
5492 "Csh:\\.csh \\.cshrc \\.login \\.logout:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\[ \\\\t\\]\\*/bin/csh\"::::::\\n",
5493 "Csh:.csh .cshrc .tcshrc .login .logout:\"^[ \\t]*#[ \\t]*![ \\t]*/bin/t?csh\"::::::\n",
5494 "LaTeX:\\.tex \\.sty \\.cls \\.ltx \\.ins:::::::\\n",
5495 "LaTeX:.tex .sty .cls .ltx .ins .clo .fd:::::::\n",
5496 "X Resources:\\.Xresources \\.Xdefaults \\.nedit:\"\\^\\[!#\\]\\.\\*\\(\\[Aa\\]pp\\|\\[Xx\\]\\)\\.\\*\\[Dd\\]efaults\"::::::\\n",
5497 "X Resources:.Xresources .Xdefaults .nedit .pats nedit.rc:\"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults\"::::::\n",
5498 #else
5499 "Csh:\\.csh \\.cshrc \\.login \\.logout:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\[ \\\\t\\]\\*/bin/csh\"::::::\\n",
5500 "Csh:.CSH .CSHRC .TCSHRC .LOGIN .LOGOUT:\"^[ \\t]*#[ \\t]*![ \\t]*/bin/t?csh\"::::::\n",
5501 "LaTeX:\\.TEX \\.STY \\.CLS \\.LTX \\.INS:::::::\\n",
5502 "LaTeX:.TEX .STY .CLS .LTX .INS .CLO .FD:::::::\n",
5503 "Lex:\\.lex:::::::\\n",
5504 "Lex:.LEX:::::::\n",
5505 "Matlab:\\.m \\.oct \\.sci:::::::\\n",
5506 "Matlab:.M .OCT .SCI:::::::\n",
5507 "Regex:\\.reg \\.regex:\"\\\\\\(\\\\\\?\\[:#=!iInN\\]\\.\\+\\\\\\\)\":None:Continuous::::\\n",
5508 "Regex:.REG .REGEX:\"\\(\\?[:#=!iInN].+\\)\":None:Continuous::::\n",
5509 "SGML HTML:\\.sgml \\.sgm \\.html \\.htm:\"\\\\\\<\\[Hh\\]\\[Tt\\]\\[Mm\\]\\[Ll\\]\\\\\\>\"::::::\\n",
5510 "SGML HTML:.SGML .SGM .HTML .HTM:\"\\<[Hh][Tt][Mm][Ll]\\>\"::::::\n",
5511 "SQL:\\.sql:::::::\\n",
5512 "SQL:.SQL:::::::\n",
5513 "Sh Ksh Bash:\\.sh \\.bash \\.ksh \\.profile \\.bashrc \\.bash_logout \\.bash_login \\.bash_profile:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\[ \\\\t\\]\\*/\\.\\*bin/\\(bash\\|ksh\\|sh\\|zsh\\)\"::::::\\n",
5514 "Sh Ksh Bash:.SH .BASH .KSH .PROFILE .BASHRC .BASH_LOGOUT .BASH_LOGIN .BASH_PROFILE:\"^[ \\t]*#[ \\t]*![ \\t]*/.*bin/(bash|ksh|sh|zsh)\"::::::\n",
5515 "XML:\\.xml \\.xsl \\.dtd:\"\\\\\\<\\(\\?i\\\\\\?xml\\|!doctype\\)\"::None:::\"\\<\\>/=\"\"'\\(\\)\\+\\*\\?\\|\":\\n",
5516 "XML:.XML .XSL .DTD:\"\\<(?i\\?xml|!doctype)\"::None:::\"<>/=\"\"'()+*?|\":\n",
5517 "X Resources:\\.XRESOURCES \\.XDEFAULTS \\.NEDIT:\"\\^\\[!#\\]\\.\\*\\(\\[Aa\\]pp\\|\\[Xx\\]\\)\\.\\*\\[Dd\\]efaults\"::::::\\n",
5518 "X Resources:.XRESOURCES .XDEFAULTS .NEDIT .PATS NEDIT.RC:\"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults\"::::::\n",
5519 #endif
5520 NULL };
5522 /* Upgrade modified language modes, only if the user hasn't
5523 altered the default 5.5 definitions. */
5524 int i;
5525 for (i = 0; pats[i]; i+=2) {
5526 if (regexFind(TempStringPrefs.language, pats[i]))
5527 regexReplace(&TempStringPrefs.language, pats[i], pats[i+1]);
5530 /* Add new styles */
5531 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Bracket:"))
5532 spliceString(&TempStringPrefs.styles, "Bracket:dark blue:Bold",
5533 "^[ \t]*Storage Type:");
5534 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Operator:"))
5535 spliceString(&TempStringPrefs.styles, "Operator:dark blue:Bold",
5536 "^[ \t]*Bracket:");
5541 * We migrate a color from the X resources to the prefs if:
5542 * 1. The prefs entry is equal to the default entry
5543 * 2. The X resource is not equal to the default entry
5545 static void migrateColor(XrmDatabase prefDB, XrmDatabase appDB,
5546 char *class, char *name, int color_index, char *default_val)
5548 char *type, *valueString;
5549 XrmValue rsrcValue;
5551 /* If this color has been customized in the color dialog then use
5552 that value */
5553 if ( strcmp(default_val, PrefData.colorNames[color_index]) )
5554 return;
5556 /* Retrieve the value of the resource from the DB */
5557 if (XrmGetResource(prefDB, name, class, &type, &rsrcValue)) {
5558 if (strcmp(type, XmRString)) {
5559 fprintf(stderr,"Internal Error: Unexpected resource type, %s\n",
5560 type);
5561 return;
5563 valueString = rsrcValue.addr;
5564 } else if (XrmGetResource(appDB, name, class, &type, &rsrcValue)) {
5565 if (strcmp(type, XmRString)) {
5566 fprintf(stderr,"Internal Error: Unexpected resource type, %s\n",
5567 type);
5568 return;
5570 valueString = rsrcValue.addr;
5571 } else
5572 /* No resources set */
5573 return;
5575 /* An X resource is set. If it's non-default, update the prefs. */
5576 if ( strcmp(valueString, default_val) ) {
5577 strncpy(PrefData.colorNames[color_index], valueString,
5578 MAX_COLOR_LEN);
5583 * In 5.4 we moved color preferences from X resources to a color dialog,
5584 * meaning they're in the normal prefs system. Users who have customized
5585 * their colors with X resources would probably prefer not to have to redo
5586 * the customization in the dialog, so we migrate them to the prefs for them.
5588 static void migrateColorResources(XrmDatabase prefDB, XrmDatabase appDB)
5590 migrateColor(prefDB, appDB, APP_CLASS ".Text.Foreground",
5591 APP_NAME ".text.foreground", TEXT_FG_COLOR,
5592 NEDIT_DEFAULT_FG);
5593 migrateColor(prefDB, appDB, APP_CLASS ".Text.Background",
5594 APP_NAME ".text.background", TEXT_BG_COLOR,
5595 NEDIT_DEFAULT_TEXT_BG);
5596 migrateColor(prefDB, appDB, APP_CLASS ".Text.SelectForeground",
5597 APP_NAME ".text.selectForeground", SELECT_FG_COLOR,
5598 NEDIT_DEFAULT_SEL_FG);
5599 migrateColor(prefDB, appDB, APP_CLASS ".Text.SelectBackground",
5600 APP_NAME ".text.selectBackground", SELECT_BG_COLOR,
5601 NEDIT_DEFAULT_SEL_BG);
5602 migrateColor(prefDB, appDB, APP_CLASS ".Text.HighlightForeground",
5603 APP_NAME ".text.highlightForeground", HILITE_FG_COLOR,
5604 NEDIT_DEFAULT_HI_FG);
5605 migrateColor(prefDB, appDB, APP_CLASS ".Text.HighlightBackground",
5606 APP_NAME ".text.highlightBackground", HILITE_BG_COLOR,
5607 NEDIT_DEFAULT_HI_BG);
5608 migrateColor(prefDB, appDB, APP_CLASS ".Text.LineNumForeground",
5609 APP_NAME ".text.lineNumForeground", LINENO_FG_COLOR,
5610 NEDIT_DEFAULT_LINENO_FG);
5611 migrateColor(prefDB, appDB, APP_CLASS ".Text.CursorForeground",
5612 APP_NAME ".text.cursorForeground", CURSOR_FG_COLOR,
5613 NEDIT_DEFAULT_CURSOR_FG);
5617 ** Inserts a string into intoString, reallocating it with XtMalloc. If
5618 ** regular expression atExpr is found, inserts the string before atExpr
5619 ** followed by a newline. If atExpr is not found, inserts insertString
5620 ** at the end, PRECEDED by a newline.
5622 static void spliceString(char **intoString, const char *insertString, const char *atExpr)
5624 int beginPos, endPos;
5625 int intoLen = strlen(*intoString);
5626 int insertLen = strlen(insertString);
5627 char *newString = XtMalloc(intoLen + insertLen + 2);
5629 if (atExpr != NULL && SearchString(*intoString, atExpr,
5630 SEARCH_FORWARD, SEARCH_REGEX, False, 0, &beginPos, &endPos,
5631 NULL, NULL, NULL)) {
5632 strncpy(newString, *intoString, beginPos);
5633 strncpy(&newString[beginPos], insertString, insertLen);
5634 newString[beginPos+insertLen] = '\n';
5635 strncpy(&newString[beginPos+insertLen+1],
5636 &((*intoString)[beginPos]), intoLen - beginPos);
5637 } else {
5638 strncpy(newString, *intoString, intoLen);
5639 newString[intoLen] = '\n';
5640 strncpy(&newString[intoLen+1], insertString, insertLen);
5642 newString[intoLen + insertLen + 1] = '\0';
5643 XtFree(*intoString);
5644 *intoString = newString;
5648 ** Simplified regular expression search routine which just returns true
5649 ** or false depending on whether inString matches expr
5651 static int regexFind(const char *inString, const char *expr)
5653 int beginPos, endPos;
5654 return SearchString(inString, expr, SEARCH_FORWARD, SEARCH_REGEX, False,
5655 0, &beginPos, &endPos, NULL, NULL, NULL);
5659 ** Simplified case-sensisitive string search routine which just
5660 ** returns true or false depending on whether inString matches expr
5662 static int caseFind(const char *inString, const char *expr)
5664 int beginPos, endPos;
5665 return SearchString(inString, expr, SEARCH_FORWARD, SEARCH_CASE_SENSE,
5666 False, 0, &beginPos, &endPos, NULL, NULL, NULL);
5670 ** Common implementation for simplified string replacement routines.
5672 static int stringReplace(char **inString, const char *expr,
5673 const char *replaceWith, int searchType,
5674 int replaceLen)
5676 int beginPos, endPos, newLen;
5677 char *newString;
5678 int inLen = strlen(*inString);
5679 if (0 >= replaceLen) replaceLen = strlen(replaceWith);
5680 if (!SearchString(*inString, expr, SEARCH_FORWARD, searchType, False,
5681 0, &beginPos, &endPos, NULL, NULL, NULL))
5682 return FALSE;
5683 newLen = inLen + replaceLen - (endPos-beginPos);
5684 newString = XtMalloc(newLen + 1);
5685 strncpy(newString, *inString, beginPos);
5686 strncpy(&newString[beginPos], replaceWith, replaceLen);
5687 strncpy(&newString[beginPos+replaceLen],
5688 &((*inString)[endPos]), inLen - endPos);
5689 newString[newLen] = '\0';
5690 XtFree(*inString);
5691 *inString = newString;
5692 return TRUE;
5696 ** Simplified regular expression replacement routine which replaces the
5697 ** first occurence of expr in inString with replaceWith, reallocating
5698 ** inString with XtMalloc. If expr is not found, does nothing and
5699 ** returns false.
5701 static int regexReplace(char **inString, const char *expr,
5702 const char *replaceWith)
5704 return stringReplace(inString, expr, replaceWith, SEARCH_REGEX, -1);
5708 ** Simplified case-sensisitive string replacement routine which
5709 ** replaces the first occurence of expr in inString with replaceWith,
5710 ** reallocating inString with XtMalloc. If expr is not found, does nothing
5711 ** and returns false.
5713 static int caseReplace(char **inString, const char *expr,
5714 const char *replaceWith, int replaceLen)
5716 return stringReplace(inString, expr, replaceWith, SEARCH_CASE_SENSE,
5717 replaceLen);
5721 ** Looks for a (case-sensitive literal) match of an old macro text in a
5722 ** temporary macro commands buffer. If the text is found, it is replaced by
5723 ** a substring of the default macros, bounded by a given start and end pattern
5724 ** (inclusive). Returns the length of the replacement.
5726 static int replaceMacroIfUnchanged(const char* oldText, const char* newStart,
5727 const char* newEnd)
5729 if (caseFind(TempStringPrefs.macroCmds, oldText)) {
5730 #ifdef VMS
5731 const char *start = strstr(PrefDescrip[1].defaultString, newStart);
5732 #else
5733 const char *start = strstr(PrefDescrip[2].defaultString, newStart);
5734 #endif
5735 if (start) {
5736 const char *end = strstr(start, newEnd);
5737 if (end) {
5738 int length = (int)(end-start) + strlen(newEnd);
5739 caseReplace(&TempStringPrefs.macroCmds, oldText, start, length);
5740 return length;
5744 return 0;
5747 #ifndef VMS
5749 ** Replace all '#' characters in shell commands by '##' to keep commands
5750 ** containing those working. '#' is a line number placeholder in 5.3 and
5751 ** had no special meaning before.
5753 static void updateShellCmdsTo5dot3(void)
5755 char *cOld, *cNew, *pCol, *pNL;
5756 int nHash, isCmd;
5757 char *newString;
5759 if(!TempStringPrefs.shellCmds)
5760 return;
5762 /* Count number of '#'. If there are '#' characters in the non-command
5763 ** part of the definition we count too much and later allocate too much
5764 ** memory for the new string, but this doesn't hurt.
5766 for(cOld=TempStringPrefs.shellCmds, nHash=0; *cOld; cOld++)
5767 if(*cOld == '#')
5768 nHash++;
5770 /* No '#' -> no conversion necessary. */
5771 if(!nHash)
5772 return;
5774 newString=XtMalloc(strlen(TempStringPrefs.shellCmds) + 1 + nHash);
5776 cOld = TempStringPrefs.shellCmds;
5777 cNew = newString;
5778 isCmd = 0;
5779 pCol = NULL;
5780 pNL = NULL;
5782 /* Copy all characters from TempStringPrefs.shellCmds into newString
5783 ** and duplicate '#' in command parts. A simple check for really beeing
5784 ** inside a command part (starting with '\n', between the the two last
5785 ** '\n' a colon ':' must have been found) is preformed.
5787 while(*cOld) {
5788 /* actually every 2nd line is a command. We additionally
5789 ** check if there is a colon ':' in the previous line.
5791 if(*cOld=='\n') {
5792 if((pCol > pNL) && !isCmd)
5793 isCmd=1;
5794 else
5795 isCmd=0;
5796 pNL=cOld;
5799 if(!isCmd && *cOld ==':')
5800 pCol = cOld;
5802 /* Duplicate hashes if we're in a command part */
5803 if(isCmd && *cOld=='#')
5804 *cNew++ = '#';
5806 /* Copy every character */
5807 *cNew++ = *cOld++;
5811 /* Terminate new preferences string */
5812 *cNew = 0;
5814 /* free the old memory */
5815 XtFree(TempStringPrefs.shellCmds);
5817 /* exchange the string */
5818 TempStringPrefs.shellCmds = newString;
5822 #else
5824 static void updateShellCmdsTo5dot3(void) {
5825 /* No shell commands in VMS ! */
5826 return;
5829 #endif
5831 static void updateShellCmdsTo5dot4(void)
5833 #ifndef VMS /* No shell commands on VMS */
5835 #ifdef __FreeBSD__
5836 const char* wc5dot3 =
5837 "^(\\s*)set wc=`wc`; echo \\$wc\\[1\\] \"words,\" \\$wc\\[2\\] \"lines,\" \\$wc\\[3\\] \"characters\"\\n";
5838 const char* wc5dot4 =
5839 "wc | awk '{print $2 \" lines, \" $1 \" words, \" $3 \" characters\"}'\n";
5840 #else
5841 const char* wc5dot3 =
5842 "^(\\s*)set wc=`wc`; echo \\$wc\\[1\\] \"lines,\" \\$wc\\[2\\] \"words,\" \\$wc\\[3\\] \"characters\"\\n";
5843 const char* wc5dot4 =
5844 "wc | awk '{print $1 \" lines, \" $2 \" words, \" $3 \" characters\"}'\n";
5845 #endif /* __FreeBSD__ */
5847 if (regexFind(TempStringPrefs.shellCmds, wc5dot3))
5848 regexReplace(&TempStringPrefs.shellCmds, wc5dot3, wc5dot4);
5850 #endif /* VMS */
5852 return;
5855 static void updateMacroCmdsTo5dot5(void)
5857 const char* uc5dot4 =
5858 "^(\\s*)if \\(substring\\(sel, keepEnd - 1, keepEnd == \" \"\\)\\)\\n";
5859 const char* uc5dot5 =
5860 " if (substring(sel, keepEnd - 1, keepEnd) == \" \")\n";
5861 if (regexFind(TempStringPrefs.macroCmds, uc5dot4))
5862 regexReplace(&TempStringPrefs.macroCmds, uc5dot4, uc5dot5);
5864 return;
5867 static void updateMacroCmdsTo5dot6(void)
5870 This is ridiculous. Macros don't belong in the default preferences
5871 string.
5872 This code is also likely to break when the macro commands are upgraded
5873 again in a next release, because it looks for patterns in the default
5874 macro string (which may change).
5875 Using a "Default" mechanism, like we do for highlighting patterns
5876 would simplify upgrading A LOT in the future, but changing the way
5877 default macros are stored, is a lot of work too, unfortunately.
5879 const char *pats[] = {
5880 "Complete Word:Alt+D::: {\n\
5881 # Tuning parameters\n\
5882 ScanDistance = 200\n\
5884 # Search back to a word boundary to find the word to complete\n\
5885 startScan = max(0, $cursor - ScanDistance)\n\
5886 endScan = min($text_length, $cursor + ScanDistance)\n\
5887 scanString = get_range(startScan, endScan)\n\
5888 keyEnd = $cursor-startScan\n\
5889 keyStart = search_string(scanString, \"<\", keyEnd, \"backward\", \"regex\")\n\
5890 if (keyStart == -1)\n\
5891 return\n\
5892 keyString = \"<\" substring(scanString, keyStart, keyEnd)\n\
5894 # search both forward and backward from the cursor position. Note that\n\
5895 # using a regex search can lead to incorrect results if any of the special\n\
5896 # regex characters is encountered, which is not considered a delimiter\n\
5897 backwardSearchResult = search_string(scanString, keyString, keyStart-1, \\\n\
5898 \"backward\", \"regex\")\n\
5899 forwardSearchResult = search_string(scanString, keyString, keyEnd, \"regex\")\n\
5900 if (backwardSearchResult == -1 && forwardSearchResult == -1) {\n\
5901 beep()\n\
5902 return\n\
5903 }\n\
5905 # if only one direction matched, use that, otherwise use the nearest\n\
5906 if (backwardSearchResult == -1)\n\
5907 matchStart = forwardSearchResult\n\
5908 else if (forwardSearchResult == -1)\n\
5909 matchStart = backwardSearchResult\n\
5910 else {\n\
5911 if (keyStart - backwardSearchResult <= forwardSearchResult - keyEnd)\n\
5912 matchStart = backwardSearchResult\n\
5913 else\n\
5914 matchStart = forwardSearchResult\n\
5915 }\n\
5917 # find the complete word\n\
5918 matchEnd = search_string(scanString, \">\", matchStart, \"regex\")\n\
5919 completedWord = substring(scanString, matchStart, matchEnd)\n\
5921 # replace it in the window\n\
5922 replace_range(startScan + keyStart, $cursor, completedWord)\n\
5923 }", "Complete Word:", "\n\t}",
5924 "Fill Sel. w/Char:::R: {\n\
5925 if ($selection_start == -1) {\n\
5926 beep()\n\
5927 return\n\
5928 }\n\
5930 # Ask the user what character to fill with\n\
5931 fillChar = string_dialog(\"Fill selection with what character?\", \"OK\", \"Cancel\")\n\
5932 if ($string_dialog_button == 2 || $string_dialog_button == 0)\n\
5933 return\n\
5935 # Count the number of lines in the selection\n\
5936 nLines = 0\n\
5937 for (i=$selection_start; i<$selection_end; i++)\n\
5938 if (get_character(i) == \"\\n\")\n\
5939 nLines++\n\
5941 # Create the fill text\n\
5942 rectangular = $selection_left != -1\n\
5943 line = \"\"\n\
5944 fillText = \"\"\n\
5945 if (rectangular) {\n\
5946 for (i=0; i<$selection_right-$selection_left; i++)\n\
5947 line = line fillChar\n\
5948 for (i=0; i<nLines; i++)\n\
5949 fillText = fillText line \"\\n\"\n\
5950 fillText = fillText line\n\
5951 } else {\n\
5952 if (nLines == 0) {\n\
5953 for (i=$selection_start; i<$selection_end; i++)\n\
5954 fillText = fillText fillChar\n\
5955 } else {\n\
5956 startIndent = 0\n\
5957 for (i=$selection_start-1; i>=0 && get_character(i)!=\"\\n\"; i--)\n\
5958 startIndent++\n\
5959 for (i=0; i<$wrap_margin-startIndent; i++)\n\
5960 fillText = fillText fillChar\n\
5961 fillText = fillText \"\\n\"\n\
5962 for (i=0; i<$wrap_margin; i++)\n\
5963 line = line fillChar\n\
5964 for (i=0; i<nLines-1; i++)\n\
5965 fillText = fillText line \"\\n\"\n\
5966 for (i=$selection_end-1; i>=$selection_start && get_character(i)!=\"\\n\"; \\\n\
5967 i--)\n\
5968 fillText = fillText fillChar\n\
5969 }\n\
5970 }\n\
5972 # Replace the selection with the fill text\n\
5973 replace_selection(fillText)\n\
5974 }", "Fill Sel. w/Char:", "\n\t}",
5975 "Comments>/* Uncomment */@C@C++@Java@CSS@JavaScript@Lex:::R: {\n\
5976 sel = get_selection()\n\
5977 selStart = $selection_start\n\
5978 selEnd = $selection_end\n\
5979 commentStart = search_string(sel, \"/*\", 0)\n\
5980 if (substring(sel, commentStart + 2, commentStart + 3) == \" \")\n\
5981 keepStart = commentStart + 3\n\
5982 else\n\
5983 keepStart = commentStart + 2\n\
5984 keepEnd = search_string(sel, \"*/\", length(sel), \"backward\")\n\
5985 commentEnd = keepEnd + 2\n\
5986 if (substring(sel, keepEnd - 1, keepEnd) == \" \")\n\
5987 keepEnd = keepEnd - 1\n\
5988 replace_range(selStart + commentStart, selStart + commentEnd, \\\n\
5989 substring(sel, keepStart, keepEnd))\n\
5990 select(selStart, selEnd - (keepStart-commentStart) - \\\n\
5991 (commentEnd - keepEnd))\n\
5992 }", "Comments>/* Uncomment */", "\n\t}",
5993 "Comments>Bar Uncomment@C:::R: {\n\
5994 selStart = $selection_start\n\
5995 selEnd = $selection_end\n\
5996 newText = get_range(selStart+3, selEnd-4)\n\
5997 newText = replace_in_string(newText, \"^ \\\\* \", \"\", \"regex\")\n\
5998 replace_range(selStart, selEnd, newText)\n\
5999 select(selStart, selStart + length(newText))\n\
6000 }","Comments>Bar Uncomment@C:", "\n\t}",
6001 "Make C Prototypes@C@C++:::: {\n\
6002 if ($selection_start == -1) {\n\
6003 start = 0\n\
6004 end = $text_length\n\
6005 } else {\n\
6006 start = $selection_start\n\
6007 end = $selection_end\n\
6008 }\n\
6009 string = get_range(start, end)\n\
6010 nDefs = 0", "Make C Prototypes@C@C++:", "\t\tnDefs = 0",
6011 NULL };
6012 int i;
6013 for (i = 0; pats[i]; i+=3)
6014 replaceMacroIfUnchanged(pats[i], pats[i+1], pats[i+2]);
6015 return;
6018 #ifdef SGI_CUSTOM
6020 ** Present the user a dialog for specifying whether or not a short
6021 ** menu mode preference should be applied toward the default setting.
6022 ** Return False (function value) if operation was canceled, return True
6023 ** in setDefault if requested to reset the default value.
6025 static int shortPrefToDefault(Widget parent, const char *settingName, int *setDefault)
6027 char msg[100] = "";
6029 if (!GetPrefShortMenus()) {
6030 *setDefault = False;
6031 return True;
6034 sprintf(msg, "%s\nSave as default for future windows as well?", settingName);
6035 switch (DialogF (DF_QUES, parent, 3, "Save Default", msg, "Yes", "No",
6036 "Cancel"))
6038 case 1: /* yes */
6039 *setDefault = True;
6040 return True;
6041 case 2: /* no */
6042 *setDefault = False;
6043 return True;
6044 case 3: /* cancel */
6045 return False;
6047 return False; /* not reached */
6049 #endif
6051 /* Decref the default calltips file(s) for this window */
6052 void UnloadLanguageModeTipsFile(WindowInfo *window)
6054 int mode;
6056 mode = window->languageMode;
6057 if (mode != PLAIN_LANGUAGE_MODE && LanguageModes[mode]->defTipsFile) {
6058 DeleteTagsFile( LanguageModes[mode]->defTipsFile, TIP, False );
6062 /******************************************************************************
6063 * The Color selection dialog
6064 ******************************************************************************/
6067 There are 8 colors: And 8 indices:
6068 textFg TEXT_FG_COLOR
6069 textBg TEXT_BG_COLOR
6070 selectFg SELECT_FG_COLOR
6071 selectBg SELECT_BG_COLOR
6072 hiliteFg HILITE_FG_COLOR
6073 hiliteBg HILITE_BG_COLOR
6074 lineNoFg LINENO_FG_COLOR
6075 cursorFg CURSOR_FG_COLOR
6078 #define MARGIN_SPACING 10
6081 * Callbacks for field modifications
6083 static void textFgModifiedCB(Widget w, XtPointer clientData,
6084 XtPointer callData)
6086 colorDialog *cd = (colorDialog *)clientData;
6087 showColorStatus(cd, cd->textFgW, cd->textFgErrW);
6090 static void textBgModifiedCB(Widget w, XtPointer clientData,
6091 XtPointer callData)
6093 colorDialog *cd = (colorDialog *)clientData;
6094 showColorStatus(cd, cd->textBgW, cd->textBgErrW);
6097 static void selectFgModifiedCB(Widget w, XtPointer clientData,
6098 XtPointer callData)
6100 colorDialog *cd = (colorDialog *)clientData;
6101 showColorStatus(cd, cd->selectFgW, cd->selectFgErrW);
6104 static void selectBgModifiedCB(Widget w, XtPointer clientData,
6105 XtPointer callData)
6107 colorDialog *cd = (colorDialog *)clientData;
6108 showColorStatus(cd, cd->selectBgW, cd->selectBgErrW);
6111 static void hiliteFgModifiedCB(Widget w, XtPointer clientData,
6112 XtPointer callData)
6114 colorDialog *cd = (colorDialog *)clientData;
6115 showColorStatus(cd, cd->hiliteFgW, cd->hiliteFgErrW);
6118 static void hiliteBgModifiedCB(Widget w, XtPointer clientData,
6119 XtPointer callData)
6121 colorDialog *cd = (colorDialog *)clientData;
6122 showColorStatus(cd, cd->hiliteBgW, cd->hiliteBgErrW);
6125 static void lineNoFgModifiedCB(Widget w, XtPointer clientData,
6126 XtPointer callData)
6128 colorDialog *cd = (colorDialog *)clientData;
6129 showColorStatus(cd, cd->lineNoFgW, cd->lineNoFgErrW);
6132 static void cursorFgModifiedCB(Widget w, XtPointer clientData,
6133 XtPointer callData)
6135 colorDialog *cd = (colorDialog *)clientData;
6136 showColorStatus(cd, cd->cursorFgW, cd->cursorFgErrW);
6141 * Helper functions for validating colors
6143 static int verifyAllColors(colorDialog *cd)
6145 /* Maybe just check for empty strings in error widgets instead? */
6146 return (checkColorStatus(cd, cd->textFgW) &&
6147 checkColorStatus(cd, cd->textBgW) &&
6148 checkColorStatus(cd, cd->selectFgW) &&
6149 checkColorStatus(cd, cd->selectBgW) &&
6150 checkColorStatus(cd, cd->hiliteFgW) &&
6151 checkColorStatus(cd, cd->hiliteBgW) &&
6152 checkColorStatus(cd, cd->lineNoFgW) &&
6153 checkColorStatus(cd, cd->cursorFgW) );
6156 /* Returns True if the color is valid, False if it's not */
6157 static Boolean checkColorStatus(colorDialog *cd, Widget colorFieldW)
6159 Colormap cMap;
6160 XColor colorDef;
6161 Status status;
6162 Display *display = XtDisplay(cd->shell);
6163 char *text = XmTextGetString(colorFieldW);
6164 XtVaGetValues(cd->shell, XtNcolormap, &cMap, NULL);
6165 status = XParseColor(display, cMap, text, &colorDef);
6166 XtFree(text);
6167 return (status != 0);
6170 /* Show or hide errorLabelW depending on whether or not colorFieldW
6171 contains a valid color name. */
6172 static void showColorStatus(colorDialog *cd, Widget colorFieldW,
6173 Widget errorLabelW)
6175 /* Should set the OK/Apply button sensitivity here, instead
6176 of leaving is sensitive and then complaining if an error. */
6177 XtSetMappedWhenManaged( errorLabelW, !checkColorStatus(cd, colorFieldW) );
6180 /* Update the colors in the window or in the preferences */
6181 static void updateColors(colorDialog *cd)
6183 WindowInfo *window;
6185 char *textFg = XmTextGetString(cd->textFgW),
6186 *textBg = XmTextGetString(cd->textBgW),
6187 *selectFg = XmTextGetString(cd->selectFgW),
6188 *selectBg = XmTextGetString(cd->selectBgW),
6189 *hiliteFg = XmTextGetString(cd->hiliteFgW),
6190 *hiliteBg = XmTextGetString(cd->hiliteBgW),
6191 *lineNoFg = XmTextGetString(cd->lineNoFgW),
6192 *cursorFg = XmTextGetString(cd->cursorFgW);
6194 for (window = WindowList; window != NULL; window = window->next)
6196 SetColors(window, textFg, textBg, selectFg, selectBg, hiliteFg,
6197 hiliteBg, lineNoFg, cursorFg);
6200 SetPrefColorName(TEXT_FG_COLOR , textFg );
6201 SetPrefColorName(TEXT_BG_COLOR , textBg );
6202 SetPrefColorName(SELECT_FG_COLOR, selectFg);
6203 SetPrefColorName(SELECT_BG_COLOR, selectBg);
6204 SetPrefColorName(HILITE_FG_COLOR, hiliteFg);
6205 SetPrefColorName(HILITE_BG_COLOR, hiliteBg);
6206 SetPrefColorName(LINENO_FG_COLOR, lineNoFg);
6207 SetPrefColorName(CURSOR_FG_COLOR, cursorFg);
6209 XtFree(textFg);
6210 XtFree(textBg);
6211 XtFree(selectFg);
6212 XtFree(selectBg);
6213 XtFree(hiliteFg);
6214 XtFree(hiliteBg);
6215 XtFree(lineNoFg);
6216 XtFree(cursorFg);
6221 * Dialog button callbacks
6224 static void colorDestroyCB(Widget w, XtPointer clientData, XtPointer callData)
6226 colorDialog *cd = (colorDialog *)clientData;
6228 cd->window->colorDialog = NULL;
6229 XtFree((char *)cd);
6232 static void colorOkCB(Widget w, XtPointer clientData, XtPointer callData)
6234 colorDialog *cd = (colorDialog *)clientData;
6236 if(!verifyAllColors(cd))
6238 DialogF(DF_ERR, w, 1, "Invalid Colors",
6239 "All colors must be valid to proceed.", "OK");
6240 return;
6242 updateColors(cd);
6244 /* pop down and destroy the dialog */
6245 XtDestroyWidget(cd->shell);
6248 static void colorApplyCB(Widget w, XtPointer clientData, XtPointer callData)
6250 colorDialog *cd = (colorDialog *)clientData;
6252 if(!verifyAllColors(cd))
6254 DialogF(DF_ERR, w, 1, "Invalid Colors",
6255 "All colors must be valid to be applied.", "OK");
6256 return;
6258 updateColors(cd);
6261 static void colorCloseCB(Widget w, XtPointer clientData, XtPointer callData)
6263 colorDialog *cd = (colorDialog *)clientData;
6265 /* pop down and destroy the dialog */
6266 XtDestroyWidget(cd->shell);
6270 /* Add a label, error label, and text entry label with a validation
6271 callback */
6272 static Widget addColorGroup( Widget parent, const char *name, char mnemonic,
6273 char *label, Widget *fieldW, Widget *errW, Widget topWidget,
6274 int leftPos, int rightPos, XtCallbackProc modCallback,
6275 colorDialog *cd )
6277 Widget lblW;
6278 char *longerName;
6279 XmString s1;
6280 int nameLen = strlen(name);
6282 /* The label widget */
6283 longerName = XtMalloc(nameLen+7);
6284 strcpy(longerName, name);
6285 strcat(longerName, "Lbl");
6286 lblW = XtVaCreateManagedWidget(longerName,
6287 xmLabelGadgetClass, parent,
6288 XmNlabelString, s1=XmStringCreateSimple( label ),
6289 XmNmnemonic, mnemonic,
6290 XmNtopAttachment, XmATTACH_WIDGET,
6291 XmNtopWidget, topWidget,
6292 XmNtopOffset, MARGIN_SPACING,
6293 XmNleftAttachment, XmATTACH_POSITION,
6294 XmNleftPosition, leftPos, NULL);
6295 XmStringFree(s1);
6297 /* The error label widget */
6298 strcpy(&(longerName[nameLen]), "ErrLbl");
6299 *errW = XtVaCreateManagedWidget(longerName,
6300 xmLabelWidgetClass, parent,
6301 XmNlabelString, s1=XmStringCreateSimple("(Invalid!)"),
6302 XmNalignment, XmALIGNMENT_END,
6303 XmNtopAttachment, XmATTACH_WIDGET,
6304 XmNtopWidget, topWidget,
6305 XmNtopOffset, MARGIN_SPACING,
6306 XmNleftAttachment, XmATTACH_WIDGET,
6307 XmNleftWidget, lblW,
6308 XmNrightAttachment, XmATTACH_POSITION,
6309 XmNrightPosition, rightPos, NULL);
6310 XmStringFree(s1);
6312 /* The text field entry widget */
6313 *fieldW = XtVaCreateManagedWidget(name, xmTextWidgetClass,
6314 parent,
6315 XmNcolumns, MAX_COLOR_LEN-1,
6316 XmNmaxLength, MAX_COLOR_LEN-1,
6317 XmNleftAttachment, XmATTACH_POSITION,
6318 XmNleftPosition, leftPos,
6319 XmNrightAttachment, XmATTACH_POSITION,
6320 XmNrightPosition, rightPos,
6321 XmNtopAttachment, XmATTACH_WIDGET,
6322 XmNtopWidget, lblW, NULL);
6323 RemapDeleteKey(*fieldW);
6324 XtAddCallback(*fieldW, XmNvalueChangedCallback,
6325 modCallback, cd);
6326 XtVaSetValues(lblW, XmNuserData, *fieldW, NULL);
6328 XtFree(longerName);
6329 return *fieldW;
6334 * Code for the dialog itself
6336 void ChooseColors(WindowInfo *window)
6338 Widget form, tmpW, topW, infoLbl;
6339 Widget okBtn, applyBtn, closeBtn;
6340 colorDialog *cd;
6341 XmString s1;
6342 int ac;
6343 Arg args[20];
6345 /* if the dialog is already displayed, just pop it to the top and return */
6346 if (window->colorDialog != NULL) {
6347 RaiseDialogWindow(((colorDialog *)window->colorDialog)->shell);
6348 return;
6351 /* Create a structure for keeping track of dialog state */
6352 cd = XtNew(colorDialog);
6353 window->colorDialog = (void*)cd;
6355 /* Create a form widget in a dialog shell */
6356 ac = 0;
6357 XtSetArg(args[ac], XmNautoUnmanage, False); ac++;
6358 XtSetArg(args[ac], XmNresizePolicy, XmRESIZE_NONE); ac++;
6359 form = CreateFormDialog(window->shell, "choose colors", args, ac);
6360 XtVaSetValues(form, XmNshadowThickness, 0, NULL);
6361 cd->shell = XtParent(form);
6362 cd->window = window;
6363 XtVaSetValues(cd->shell, XmNtitle, "Colors", NULL);
6364 AddMotifCloseCallback(XtParent(form), colorCloseCB, cd);
6365 XtAddCallback(form, XmNdestroyCallback, colorDestroyCB, cd);
6367 /* Information label */
6368 infoLbl = XtVaCreateManagedWidget("infoLbl",
6369 xmLabelGadgetClass, form,
6370 XmNtopAttachment, XmATTACH_POSITION,
6371 XmNtopPosition, 2,
6372 XmNleftAttachment, XmATTACH_POSITION,
6373 XmNleftPosition, 1,
6374 XmNrightAttachment, XmATTACH_POSITION,
6375 XmNrightPosition, 99,
6376 XmNalignment, XmALIGNMENT_CENTER,
6377 XmNlabelString, s1 = XmStringCreateLtoR(
6378 "Colors can be entered as names (e.g. red, blue) or "
6379 "as RGB triples\nin the format #RRGGBB, where each digit "
6380 "is in the range 0-f.", XmFONTLIST_DEFAULT_TAG),
6381 NULL);
6382 XmStringFree(s1);
6384 topW = infoLbl;
6386 /* The left column (foregrounds) of color entry groups */
6387 tmpW = addColorGroup( form, "textFg", 'P', "Plain Text Foreground",
6388 &(cd->textFgW), &(cd->textFgErrW), topW, 1, 49,
6389 textFgModifiedCB, cd );
6390 tmpW = addColorGroup( form, "selectFg", 'S', "Selection Foreground",
6391 &(cd->selectFgW), &(cd->selectFgErrW), tmpW, 1, 49,
6392 selectFgModifiedCB, cd );
6393 tmpW = addColorGroup( form, "hiliteFg", 'M', "Matching (..) Foreground",
6394 &(cd->hiliteFgW), &(cd->hiliteFgErrW), tmpW, 1, 49,
6395 hiliteFgModifiedCB, cd );
6396 tmpW = addColorGroup( form, "lineNoFg", 'L', "Line Numbers",
6397 &(cd->lineNoFgW), &(cd->lineNoFgErrW), tmpW, 1, 49,
6398 lineNoFgModifiedCB, cd );
6400 /* The right column (backgrounds) */
6401 tmpW = addColorGroup( form, "textBg", 'T', "Text Area Background",
6402 &(cd->textBgW), &(cd->textBgErrW), topW, 51, 99,
6403 textBgModifiedCB, cd );
6404 tmpW = addColorGroup( form, "selectBg", 'B', "Selection Background",
6405 &(cd->selectBgW), &(cd->selectBgErrW), tmpW, 51, 99,
6406 selectBgModifiedCB, cd );
6407 tmpW = addColorGroup( form, "hiliteBg", 'h', "Matching (..) Background",
6408 &(cd->hiliteBgW), &(cd->hiliteBgErrW), tmpW, 51, 99,
6409 hiliteBgModifiedCB, cd );
6410 tmpW = addColorGroup( form, "cursorFg", 'C', "Cursor Color",
6411 &(cd->cursorFgW), &(cd->cursorFgErrW), tmpW, 51, 99,
6412 cursorFgModifiedCB, cd );
6414 tmpW = XtVaCreateManagedWidget("infoLbl",
6415 xmLabelGadgetClass, form,
6416 XmNtopAttachment, XmATTACH_WIDGET,
6417 XmNtopWidget, tmpW,
6418 XmNtopOffset, MARGIN_SPACING,
6419 XmNleftAttachment, XmATTACH_POSITION,
6420 XmNleftPosition, 1,
6421 XmNrightAttachment, XmATTACH_POSITION,
6422 XmNrightPosition, 99,
6423 XmNalignment, XmALIGNMENT_CENTER,
6424 XmNlabelString, s1 = XmStringCreateLtoR(
6425 "NOTE: Foreground colors only apply when syntax highlighting "
6426 "is DISABLED.\n", XmFONTLIST_DEFAULT_TAG),
6427 NULL);
6428 XmStringFree(s1);
6430 tmpW = XtVaCreateManagedWidget("sep",
6431 xmSeparatorGadgetClass, form,
6432 XmNtopAttachment, XmATTACH_WIDGET,
6433 XmNtopWidget, tmpW,
6434 XmNleftAttachment, XmATTACH_FORM,
6435 XmNrightAttachment, XmATTACH_FORM, NULL);
6437 /* The OK, Apply, and Cancel buttons */
6438 okBtn = XtVaCreateManagedWidget("ok",
6439 xmPushButtonWidgetClass, form,
6440 XmNlabelString, s1=XmStringCreateSimple("OK"),
6441 XmNmarginWidth, BUTTON_WIDTH_MARGIN,
6442 XmNtopAttachment, XmATTACH_WIDGET,
6443 XmNtopWidget, tmpW,
6444 XmNtopOffset, MARGIN_SPACING,
6445 XmNleftAttachment, XmATTACH_POSITION,
6446 XmNleftPosition, 10,
6447 XmNrightAttachment, XmATTACH_POSITION,
6448 XmNrightPosition, 30,
6449 NULL);
6450 XtAddCallback(okBtn, XmNactivateCallback, colorOkCB, cd);
6451 XmStringFree(s1);
6453 applyBtn = XtVaCreateManagedWidget(
6454 "apply", xmPushButtonWidgetClass, form,
6455 XmNlabelString, s1=XmStringCreateSimple("Apply"),
6456 XmNtopAttachment, XmATTACH_WIDGET,
6457 XmNtopWidget, tmpW,
6458 XmNtopOffset, MARGIN_SPACING,
6459 XmNmnemonic, 'A',
6460 XmNleftAttachment, XmATTACH_POSITION,
6461 XmNleftPosition, 40,
6462 XmNrightAttachment, XmATTACH_POSITION,
6463 XmNrightPosition, 60, NULL);
6464 XtAddCallback(applyBtn, XmNactivateCallback, colorApplyCB, cd);
6465 XmStringFree(s1);
6467 closeBtn = XtVaCreateManagedWidget("close",
6468 xmPushButtonWidgetClass, form,
6469 XmNlabelString, s1=XmStringCreateSimple("Close"),
6470 XmNtopAttachment, XmATTACH_WIDGET,
6471 XmNtopWidget, tmpW,
6472 XmNtopOffset, MARGIN_SPACING,
6473 XmNleftAttachment, XmATTACH_POSITION,
6474 XmNleftPosition, 70,
6475 XmNrightAttachment, XmATTACH_POSITION,
6476 XmNrightPosition, 90,
6477 NULL);
6478 XtAddCallback(closeBtn, XmNactivateCallback, colorCloseCB, cd);
6479 XmStringFree(s1);
6481 /* Set initial default button */
6482 XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
6483 XtVaSetValues(form, XmNcancelButton, closeBtn, NULL);
6485 /* Set initial values */
6486 XmTextSetString(cd->textFgW, GetPrefColorName(TEXT_FG_COLOR ));
6487 XmTextSetString(cd->textBgW, GetPrefColorName(TEXT_BG_COLOR ));
6488 XmTextSetString(cd->selectFgW, GetPrefColorName(SELECT_FG_COLOR));
6489 XmTextSetString(cd->selectBgW, GetPrefColorName(SELECT_BG_COLOR));
6490 XmTextSetString(cd->hiliteFgW, GetPrefColorName(HILITE_FG_COLOR));
6491 XmTextSetString(cd->hiliteBgW, GetPrefColorName(HILITE_BG_COLOR));
6492 XmTextSetString(cd->lineNoFgW, GetPrefColorName(LINENO_FG_COLOR));
6493 XmTextSetString(cd->cursorFgW, GetPrefColorName(CURSOR_FG_COLOR));
6495 /* Handle mnemonic selection of buttons and focus to dialog */
6496 AddDialogMnemonicHandler(form, FALSE);
6498 /* put up dialog */
6499 ManageDialogCenteredOnPointer(form);
6503 ** This function passes up a pointer to the static name of the default
6504 ** shell, currently defined as the user's login shell.
6505 ** In case of errors, the fallback of "sh" will be returned.
6507 static const char* getDefaultShell(void)
6509 struct passwd* passwdEntry = NULL;
6510 static char shellBuffer[MAXPATHLEN + 1] = "sh";
6512 passwdEntry = getpwuid(getuid()); /* getuid() never fails. */
6514 if (NULL == passwdEntry)
6516 /* Something bad happened! Do something, quick! */
6517 perror("nedit: Failed to get passwd entry (falling back to 'sh')");
6518 return "sh";
6521 /* *passwdEntry may be overwritten */
6522 /* TODO: To make this and other function calling getpwuid() more robust,
6523 passwdEntry should be kept in a central position (Core->sysinfo?).
6524 That way, local code would always get a current copy of passwdEntry,
6525 but could still be kept lean. The obvious alternative of a central
6526 facility within NEdit to access passwdEntry would increase coupling
6527 and would have to cover a lot of assumptions. */
6528 strncpy(shellBuffer, passwdEntry->pw_shell, MAXPATHLEN);
6529 shellBuffer[MAXPATHLEN] = '\0';
6531 return shellBuffer;