Force a terminating \n on macro file load time
[nedit.git] / source / preferences.c
blob5b1cd67afcdc1ccb3d8323b78569a291a4c1f426
1 static const char CVSID[] = "$Id: preferences.c,v 1.159 2008/08/20 14:57:35 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: ");
1523 fprintf(stderr, filename);
1524 fprintf(stderr, "\n");
1528 void SetPrefOpenInTab(int state)
1530 WindowInfo *w = WindowList;
1531 setIntPref(&PrefData.openInTab, state);
1532 for(; w != NULL; w = w->next)
1533 UpdateNewOppositeMenu(w, state);
1536 int GetPrefOpenInTab(void)
1538 return PrefData.openInTab;
1541 void SetPrefWrap(int state)
1543 setIntPref(&PrefData.wrapStyle, state);
1546 int GetPrefWrap(int langMode)
1548 if (langMode == PLAIN_LANGUAGE_MODE ||
1549 LanguageModes[langMode]->wrapStyle == DEFAULT_WRAP)
1550 return PrefData.wrapStyle;
1551 return LanguageModes[langMode]->wrapStyle;
1554 void SetPrefWrapMargin(int margin)
1556 setIntPref(&PrefData.wrapMargin, margin);
1559 int GetPrefWrapMargin(void)
1561 return PrefData.wrapMargin;
1564 void SetPrefSearch(int searchType)
1566 setIntPref(&PrefData.searchMethod, searchType);
1569 int GetPrefSearch(void)
1571 return PrefData.searchMethod;
1574 #ifdef REPLACE_SCOPE
1575 void SetPrefReplaceDefScope(int scope)
1577 setIntPref(&PrefData.replaceDefScope, scope);
1580 int GetPrefReplaceDefScope(void)
1582 return PrefData.replaceDefScope;
1584 #endif
1586 void SetPrefAutoIndent(int state)
1588 setIntPref(&PrefData.autoIndent, state);
1591 int GetPrefAutoIndent(int langMode)
1593 if (langMode == PLAIN_LANGUAGE_MODE ||
1594 LanguageModes[langMode]->indentStyle == DEFAULT_INDENT)
1595 return PrefData.autoIndent;
1596 return LanguageModes[langMode]->indentStyle;
1599 void SetPrefAutoSave(int state)
1601 setIntPref(&PrefData.autoSave, state);
1604 int GetPrefAutoSave(void)
1606 return PrefData.autoSave;
1609 void SetPrefSaveOldVersion(int state)
1611 setIntPref(&PrefData.saveOldVersion, state);
1614 int GetPrefSaveOldVersion(void)
1616 return PrefData.saveOldVersion;
1619 void SetPrefSearchDlogs(int state)
1621 setIntPref(&PrefData.searchDlogs, state);
1624 int GetPrefSearchDlogs(void)
1626 return PrefData.searchDlogs;
1629 void SetPrefBeepOnSearchWrap(int state)
1631 setIntPref(&PrefData.searchWrapBeep, state);
1634 int GetPrefBeepOnSearchWrap(void)
1636 return PrefData.searchWrapBeep;
1639 void SetPrefKeepSearchDlogs(int state)
1641 setIntPref(&PrefData.keepSearchDlogs, state);
1644 int GetPrefKeepSearchDlogs(void)
1646 return PrefData.keepSearchDlogs;
1649 void SetPrefSearchWraps(int state)
1651 setIntPref(&PrefData.searchWraps, state);
1654 int GetPrefStickyCaseSenseBtn(void)
1656 return PrefData.stickyCaseSenseBtn;
1659 int GetPrefSearchWraps(void)
1661 return PrefData.searchWraps;
1664 void SetPrefStatsLine(int state)
1666 setIntPref(&PrefData.statsLine, state);
1669 int GetPrefStatsLine(void)
1671 return PrefData.statsLine;
1674 void SetPrefISearchLine(int state)
1676 setIntPref(&PrefData.iSearchLine, state);
1679 int GetPrefISearchLine(void)
1681 return PrefData.iSearchLine;
1684 void SetPrefSortTabs(int state)
1686 setIntPref(&PrefData.sortTabs, state);
1689 int GetPrefSortTabs(void)
1691 return PrefData.sortTabs;
1694 void SetPrefTabBar(int state)
1696 setIntPref(&PrefData.tabBar, state);
1699 int GetPrefTabBar(void)
1701 return PrefData.tabBar;
1704 void SetPrefTabBarHideOne(int state)
1706 setIntPref(&PrefData.tabBarHideOne, state);
1709 int GetPrefTabBarHideOne(void)
1711 return PrefData.tabBarHideOne;
1714 void SetPrefGlobalTabNavigate(int state)
1716 setIntPref(&PrefData.globalTabNavigate, state);
1719 int GetPrefGlobalTabNavigate(void)
1721 return PrefData.globalTabNavigate;
1724 void SetPrefToolTips(int state)
1726 setIntPref(&PrefData.toolTips, state);
1729 int GetPrefToolTips(void)
1731 return PrefData.toolTips;
1734 void SetPrefLineNums(int state)
1736 setIntPref(&PrefData.lineNums, state);
1739 int GetPrefLineNums(void)
1741 return PrefData.lineNums;
1744 void SetPrefShowPathInWindowsMenu(int state)
1746 setIntPref(&PrefData.pathInWindowsMenu, state);
1749 int GetPrefShowPathInWindowsMenu(void)
1751 return PrefData.pathInWindowsMenu;
1754 void SetPrefWarnFileMods(int state)
1756 setIntPref(&PrefData.warnFileMods, state);
1759 int GetPrefWarnFileMods(void)
1761 return PrefData.warnFileMods;
1764 void SetPrefWarnRealFileMods(int state)
1766 setIntPref(&PrefData.warnRealFileMods, state);
1769 int GetPrefWarnRealFileMods(void)
1771 return PrefData.warnRealFileMods;
1774 void SetPrefWarnExit(int state)
1776 setIntPref(&PrefData.warnExit, state);
1779 int GetPrefWarnExit(void)
1781 return PrefData.warnExit;
1784 void SetPrefv(int state)
1786 setIntPref(&PrefData.findReplaceUsesSelection, state);
1789 int GetPrefFindReplaceUsesSelection(void)
1791 return PrefData.findReplaceUsesSelection;
1794 int GetPrefMapDelete(void)
1796 return PrefData.mapDelete;
1799 int GetPrefStdOpenDialog(void)
1801 return PrefData.stdOpenDialog;
1804 void SetPrefRows(int nRows)
1806 setIntPref(&PrefData.textRows, nRows);
1809 int GetPrefRows(void)
1811 return PrefData.textRows;
1814 void SetPrefCols(int nCols)
1816 setIntPref(&PrefData.textCols, nCols);
1819 int GetPrefCols(void)
1821 return PrefData.textCols;
1824 void SetPrefTabDist(int tabDist)
1826 setIntPref(&PrefData.tabDist, tabDist);
1829 int GetPrefTabDist(int langMode)
1831 int tabDist;
1832 if (langMode == PLAIN_LANGUAGE_MODE ||
1833 LanguageModes[langMode]->tabDist == DEFAULT_TAB_DIST) {
1834 tabDist = PrefData.tabDist;
1835 } else {
1836 tabDist = LanguageModes[langMode]->tabDist;
1838 /* Make sure that the tab distance is in range (garbage may have
1839 been entered via the command line or the X resources, causing
1840 errors later on, like division by zero). */
1841 if (tabDist <= 0) return 1;
1842 if (tabDist > MAX_EXP_CHAR_LEN) return MAX_EXP_CHAR_LEN;
1843 return tabDist;
1846 void SetPrefEmTabDist(int tabDist)
1848 setIntPref(&PrefData.emTabDist, tabDist);
1851 int GetPrefEmTabDist(int langMode)
1853 if (langMode == PLAIN_LANGUAGE_MODE ||
1854 LanguageModes[langMode]->emTabDist == DEFAULT_EM_TAB_DIST)
1855 return PrefData.emTabDist;
1856 return LanguageModes[langMode]->emTabDist;
1859 void SetPrefInsertTabs(int state)
1861 setIntPref(&PrefData.insertTabs, state);
1864 int GetPrefInsertTabs(void)
1866 return PrefData.insertTabs;
1869 void SetPrefShowMatching(int state)
1871 setIntPref(&PrefData.showMatchingStyle, state);
1874 int GetPrefShowMatching(void)
1877 * For backwards compatibility with pre-5.2 versions, the boolean
1878 * False/True matching behavior is converted to NO_FLASH/FLASH_DELIMIT.
1880 if (PrefData.showMatchingStyle >= N_SHOW_MATCHING_STYLES)
1881 PrefData.showMatchingStyle -= N_SHOW_MATCHING_STYLES;
1882 return PrefData.showMatchingStyle;
1885 void SetPrefMatchSyntaxBased(int state)
1887 setIntPref(&PrefData.matchSyntaxBased, state);
1890 int GetPrefMatchSyntaxBased(void)
1892 return PrefData.matchSyntaxBased;
1895 void SetPrefHighlightSyntax(Boolean state)
1897 setIntPref(&PrefData.highlightSyntax, state);
1900 Boolean GetPrefHighlightSyntax(void)
1902 return PrefData.highlightSyntax;
1905 void SetPrefBacklightChars(int state)
1907 setIntPref(&PrefData.backlightChars, state);
1910 int GetPrefBacklightChars(void)
1912 return PrefData.backlightChars;
1915 void SetPrefBacklightCharTypes(char *types)
1917 setStringAllocPref(&PrefData.backlightCharTypes, types);
1920 char *GetPrefBacklightCharTypes(void)
1922 return PrefData.backlightCharTypes;
1925 void SetPrefRepositionDialogs(int state)
1927 setIntPref(&PrefData.repositionDialogs, state);
1930 int GetPrefRepositionDialogs(void)
1932 return PrefData.repositionDialogs;
1935 void SetPrefAutoScroll(int state)
1937 WindowInfo *w = WindowList;
1938 int margin = state ? PrefData.autoScrollVPadding : 0;
1940 setIntPref(&PrefData.autoScroll, state);
1941 for(w = WindowList; w != NULL; w = w->next)
1942 SetAutoScroll(w, margin);
1945 int GetPrefAutoScroll(void)
1947 return PrefData.autoScroll;
1950 int GetVerticalAutoScroll(void)
1952 return PrefData.autoScroll ? PrefData.autoScrollVPadding : 0;
1955 void SetPrefAppendLF(int state)
1957 setIntPref(&PrefData.appendLF, state);
1960 int GetPrefAppendLF(void)
1962 return PrefData.appendLF;
1965 void SetPrefSortOpenPrevMenu(int state)
1967 setIntPref(&PrefData.sortOpenPrevMenu, state);
1970 int GetPrefSortOpenPrevMenu(void)
1972 return PrefData.sortOpenPrevMenu;
1975 char *GetPrefTagFile(void)
1977 return PrefData.tagFile;
1980 void SetPrefSmartTags(int state)
1982 setIntPref(&PrefData.smartTags, state);
1985 int GetPrefSmartTags(void)
1987 return PrefData.smartTags;
1990 int GetPrefAlwaysCheckRelTagsSpecs(void)
1992 return PrefData.alwaysCheckRelativeTagsSpecs;
1995 char *GetPrefDelimiters(void)
1997 return PrefData.delimiters;
2000 char *GetPrefColorName(int index)
2002 return PrefData.colorNames[index];
2005 void SetPrefColorName(int index, const char *name)
2007 setStringPref(PrefData.colorNames[index], name);
2011 ** Set the font preferences using the font name (the fontList is generated
2012 ** in this call). Note that this leaks memory and server resources each
2013 ** time the default font is re-set. See note on SetFontByName in window.c
2014 ** for more information.
2016 void SetPrefFont(char *fontName)
2018 XFontStruct *font;
2020 setStringPref(PrefData.fontString, fontName);
2021 font = XLoadQueryFont(TheDisplay, fontName);
2022 PrefData.fontList = font==NULL ? NULL :
2023 XmFontListCreate(font, XmSTRING_DEFAULT_CHARSET);
2026 void SetPrefBoldFont(char *fontName)
2028 setStringPref(PrefData.boldFontString, fontName);
2029 PrefData.boldFontStruct = XLoadQueryFont(TheDisplay, fontName);
2032 void SetPrefItalicFont(char *fontName)
2034 setStringPref(PrefData.italicFontString, fontName);
2035 PrefData.italicFontStruct = XLoadQueryFont(TheDisplay, fontName);
2037 void SetPrefBoldItalicFont(char *fontName)
2039 setStringPref(PrefData.boldItalicFontString, fontName);
2040 PrefData.boldItalicFontStruct = XLoadQueryFont(TheDisplay, fontName);
2043 char *GetPrefFontName(void)
2045 return PrefData.fontString;
2048 char *GetPrefBoldFontName(void)
2050 return PrefData.boldFontString;
2053 char *GetPrefItalicFontName(void)
2055 return PrefData.italicFontString;
2058 char *GetPrefBoldItalicFontName(void)
2060 return PrefData.boldItalicFontString;
2063 XmFontList GetPrefFontList(void)
2065 return PrefData.fontList;
2068 XFontStruct *GetPrefBoldFont(void)
2070 return PrefData.boldFontStruct;
2073 XFontStruct *GetPrefItalicFont(void)
2075 return PrefData.italicFontStruct;
2078 XFontStruct *GetPrefBoldItalicFont(void)
2080 return PrefData.boldItalicFontStruct;
2083 char *GetPrefHelpFontName(int index)
2085 return PrefData.helpFontNames[index];
2088 char *GetPrefHelpLinkColor(void)
2090 return PrefData.helpLinkColor;
2093 char *GetPrefTooltipBgColor(void)
2095 return PrefData.tooltipBgColor;
2098 void SetPrefShell(const char *shell)
2100 setStringPref(PrefData.shell, shell);
2103 const char* GetPrefShell(void)
2105 return PrefData.shell;
2108 char *GetPrefGeometry(void)
2110 return PrefData.geometry;
2113 char *GetPrefServerName(void)
2115 return PrefData.serverName;
2118 char *GetPrefBGMenuBtn(void)
2120 return PrefData.bgMenuBtn;
2123 int GetPrefMaxPrevOpenFiles(void)
2125 return PrefData.maxPrevOpenFiles;
2128 int GetPrefTypingHidesPointer(void)
2130 return(PrefData.typingHidesPointer);
2133 #ifdef SGI_CUSTOM
2134 void SetPrefShortMenus(int state)
2136 setIntPref(&PrefData.shortMenus, state);
2139 int GetPrefShortMenus(void)
2141 return PrefData.shortMenus;
2143 #endif
2145 void SetPrefTitleFormat(const char* format)
2147 const WindowInfo* window;
2149 setStringPref(PrefData.titleFormat, format);
2151 /* update all windows */
2152 for (window=WindowList; window!=NULL; window=window->next) {
2153 UpdateWindowTitle(window);
2156 const char* GetPrefTitleFormat(void)
2158 return PrefData.titleFormat;
2161 Boolean GetPrefUndoModifiesSelection(void)
2163 return (Boolean)PrefData.undoModifiesSelection;
2166 Boolean GetPrefFocusOnRaise(void)
2168 return (Boolean)PrefData.focusOnRaise;
2171 Boolean GetPrefForceOSConversion(void)
2173 return (Boolean) PrefData.forceOSConversion;
2176 Boolean GetPrefHonorSymlinks(void)
2178 return PrefData.honorSymlinks;
2181 int GetPrefOverrideVirtKeyBindings(void)
2183 return PrefData.virtKeyOverride;
2186 int GetPrefTruncSubstitution(void)
2188 return PrefData.truncSubstitution;
2192 ** If preferences don't get saved, ask the user on exit whether to save
2194 void MarkPrefsChanged(void)
2196 PrefsHaveChanged = True;
2200 ** Check if preferences have changed, and if so, ask the user if he wants
2201 ** to re-save. Returns False if user requests cancelation of Exit (or whatever
2202 ** operation triggered this call to be made).
2204 int CheckPrefsChangesSaved(Widget dialogParent)
2206 int resp;
2208 if (!PrefsHaveChanged)
2209 return True;
2211 resp = DialogF(DF_WARN, dialogParent, 3, "Default Preferences",
2212 ImportedFile == NULL ?
2213 "Default Preferences have changed.\n"
2214 "Save changes to NEdit preference file?" :
2215 "Default Preferences have changed. SAVING \n"
2216 "CHANGES WILL INCORPORATE ADDITIONAL\nSETTINGS FROM FILE: %s",
2217 "Save", "Don't Save", "Cancel", ImportedFile);
2218 if (resp == 2)
2219 return True;
2220 if (resp == 3)
2221 return False;
2223 SaveNEditPrefs(dialogParent, True);
2224 return True;
2228 ** set *prefDataField to newValue, but first check if they're different
2229 ** and update PrefsHaveChanged if a preference setting has now changed.
2231 static void setIntPref(int *prefDataField, int newValue)
2233 if (newValue != *prefDataField)
2234 PrefsHaveChanged = True;
2235 *prefDataField = newValue;
2238 static void setStringPref(char *prefDataField, const char *newValue)
2240 if (strcmp(prefDataField, newValue))
2241 PrefsHaveChanged = True;
2242 strcpy(prefDataField, newValue);
2245 static void setStringAllocPref(char **pprefDataField, char *newValue)
2247 char *p_newField;
2249 /* treat empty strings as nulls */
2250 if (newValue && *newValue == '\0')
2251 newValue = NULL;
2252 if (*pprefDataField && **pprefDataField == '\0')
2253 *pprefDataField = NULL; /* assume statically alloc'ed "" */
2255 /* check changes */
2256 if (!*pprefDataField && !newValue)
2257 return;
2258 else if (!*pprefDataField && newValue)
2259 PrefsHaveChanged = True;
2260 else if (*pprefDataField && !newValue)
2261 PrefsHaveChanged = True;
2262 else if (strcmp(*pprefDataField, newValue))
2263 PrefsHaveChanged = True;
2265 /* get rid of old preference */
2266 XtFree(*pprefDataField);
2268 /* store new preference */
2269 if (newValue) {
2270 p_newField = XtMalloc(strlen(newValue) + 1);
2271 strcpy(p_newField, newValue);
2273 *pprefDataField = newValue;
2277 ** Set the language mode for the window, update the menu and trigger language
2278 ** mode specific actions (turn on/off highlighting). If forceNewDefaults is
2279 ** true, re-establish default settings for language-specific preferences
2280 ** regardless of whether they were previously set by the user.
2282 void SetLanguageMode(WindowInfo *window, int mode, int forceNewDefaults)
2284 Widget menu;
2285 WidgetList items;
2286 int n;
2287 Cardinal nItems;
2288 void *userData;
2290 /* Do mode-specific actions */
2291 reapplyLanguageMode(window, mode, forceNewDefaults);
2293 /* Select the correct language mode in the sub-menu */
2294 if (IsTopDocument(window)) {
2295 XtVaGetValues(window->langModeCascade, XmNsubMenuId, &menu, NULL);
2296 XtVaGetValues(menu, XmNchildren, &items, XmNnumChildren, &nItems, NULL);
2297 for (n=0; n<(int)nItems; n++) {
2298 XtVaGetValues(items[n], XmNuserData, &userData, NULL);
2299 XmToggleButtonSetState(items[n], (int)userData == mode, False);
2305 ** Lookup a language mode by name, returning the index of the language
2306 ** mode or PLAIN_LANGUAGE_MODE if the name is not found
2308 int FindLanguageMode(const char *languageName)
2310 int i;
2312 /* Compare each language mode to the one we were presented */
2313 for (i=0; i<NLanguageModes; i++)
2314 if (!strcmp(languageName, LanguageModes[i]->name))
2315 return i;
2317 return PLAIN_LANGUAGE_MODE;
2322 ** Apply language mode matching criteria and set window->languageMode to
2323 ** the appropriate mode for the current file, trigger language mode
2324 ** specific actions (turn on/off highlighting), and update the language
2325 ** mode menu item. If forceNewDefaults is true, re-establish default
2326 ** settings for language-specific preferences regardless of whether
2327 ** they were previously set by the user.
2329 void DetermineLanguageMode(WindowInfo *window, int forceNewDefaults)
2331 SetLanguageMode(window, matchLanguageMode(window), forceNewDefaults);
2335 ** Return the name of the current language mode set in "window", or NULL
2336 ** if the current mode is "Plain".
2338 char *LanguageModeName(int mode)
2340 if (mode == PLAIN_LANGUAGE_MODE)
2341 return NULL;
2342 else
2343 return LanguageModes[mode]->name;
2347 ** Get the set of word delimiters for the language mode set in the current
2348 ** window. Returns NULL when no language mode is set (it would be easy to
2349 ** return the default delimiter set when the current language mode is "Plain",
2350 ** or the mode doesn't have its own delimiters, but this is usually used
2351 ** to supply delimiters for RE searching, and ExecRE can skip compiling a
2352 ** delimiter table when delimiters is NULL).
2354 char *GetWindowDelimiters(const WindowInfo *window)
2356 if (window->languageMode == PLAIN_LANGUAGE_MODE)
2357 return NULL;
2358 else
2359 return LanguageModes[window->languageMode]->delimiters;
2363 ** Put up a dialog for selecting a custom initial window size
2365 void RowColumnPrefDialog(Widget parent)
2367 Widget form, selBox, topLabel;
2368 Arg selBoxArgs[2];
2369 XmString s1;
2371 XtSetArg(selBoxArgs[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
2372 XtSetArg(selBoxArgs[1], XmNautoUnmanage, False);
2373 selBox = CreatePromptDialog(parent, "customSize", selBoxArgs, 2);
2374 XtAddCallback(selBox, XmNokCallback, (XtCallbackProc)sizeOKCB, NULL);
2375 XtAddCallback(selBox, XmNcancelCallback, (XtCallbackProc)sizeCancelCB,NULL);
2376 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_TEXT));
2377 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_SELECTION_LABEL));
2378 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_HELP_BUTTON));
2379 XtVaSetValues(XtParent(selBox), XmNtitle, "Initial Window Size", NULL);
2381 form = XtVaCreateManagedWidget("form", xmFormWidgetClass, selBox, NULL);
2383 topLabel = XtVaCreateManagedWidget("topLabel", xmLabelGadgetClass, form,
2384 XmNlabelString, s1=MKSTRING(
2385 "Enter desired size in rows\nand columns of characters:"), NULL);
2386 XmStringFree(s1);
2388 RowText = XtVaCreateManagedWidget("rows", xmTextWidgetClass, form,
2389 XmNcolumns, 3,
2390 XmNtopAttachment, XmATTACH_WIDGET,
2391 XmNleftAttachment, XmATTACH_POSITION,
2392 XmNrightAttachment, XmATTACH_POSITION,
2393 XmNtopWidget, topLabel,
2394 XmNleftPosition, 5,
2395 XmNrightPosition, 45, NULL);
2396 RemapDeleteKey(RowText);
2398 XtVaCreateManagedWidget("xLabel", xmLabelGadgetClass, form,
2399 XmNlabelString, s1=MKSTRING("x"),
2400 XmNtopAttachment, XmATTACH_WIDGET,
2401 XmNleftAttachment, XmATTACH_POSITION,
2402 XmNrightAttachment, XmATTACH_POSITION,
2403 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2404 XmNtopWidget, topLabel,
2405 XmNbottomWidget, RowText,
2406 XmNleftPosition, 45,
2407 XmNrightPosition, 55, NULL);
2408 XmStringFree(s1);
2410 ColText = XtVaCreateManagedWidget("cols", xmTextWidgetClass, form,
2411 XmNcolumns, 3,
2412 XmNtopAttachment, XmATTACH_WIDGET,
2413 XmNleftAttachment, XmATTACH_POSITION,
2414 XmNrightAttachment, XmATTACH_POSITION,
2415 XmNtopWidget, topLabel,
2416 XmNleftPosition, 55,
2417 XmNrightPosition, 95, NULL);
2418 RemapDeleteKey(ColText);
2420 /* put up dialog and wait for user to press ok or cancel */
2421 DoneWithSizeDialog = False;
2422 ManageDialogCenteredOnPointer(selBox);
2423 while (!DoneWithSizeDialog)
2425 XEvent event;
2426 XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
2427 ServerDispatchEvent(&event);
2430 XtDestroyWidget(selBox);
2433 static void sizeOKCB(Widget w, XtPointer clientData, XtPointer callData)
2435 int rowValue, colValue, stat;
2437 /* get the values that the user entered and make sure they're ok */
2438 stat = GetIntTextWarn(RowText, &rowValue, "number of rows", True);
2439 if (stat != TEXT_READ_OK)
2440 return;
2441 stat = GetIntTextWarn(ColText, &colValue, "number of columns", True);
2442 if (stat != TEXT_READ_OK)
2443 return;
2445 /* set the corresponding preferences and dismiss the dialog */
2446 SetPrefRows(rowValue);
2447 SetPrefCols(colValue);
2448 DoneWithSizeDialog = True;
2451 static void sizeCancelCB(Widget w, XtPointer clientData, XtPointer callData)
2453 DoneWithSizeDialog = True;
2457 ** Present the user a dialog for setting tab related preferences, either as
2458 ** defaults, or for a specific window (pass "forWindow" as NULL to set default
2459 ** preference, or a window to set preferences for the specific window.
2461 void TabsPrefDialog(Widget parent, WindowInfo *forWindow)
2463 Widget form, selBox;
2464 Arg selBoxArgs[2];
2465 XmString s1;
2466 int emulate, emTabDist, useTabs, tabDist;
2468 XtSetArg(selBoxArgs[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
2469 XtSetArg(selBoxArgs[1], XmNautoUnmanage, False);
2470 selBox = CreatePromptDialog(parent, "customSize", selBoxArgs, 2);
2471 XtAddCallback(selBox, XmNokCallback, (XtCallbackProc)tabsOKCB, NULL);
2472 XtAddCallback(selBox, XmNcancelCallback, (XtCallbackProc)tabsCancelCB,NULL);
2473 XtAddCallback(selBox, XmNhelpCallback, (XtCallbackProc)tabsHelpCB,NULL);
2474 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_TEXT));
2475 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_SELECTION_LABEL));
2476 XtVaSetValues(XtParent(selBox), XmNtitle, "Tabs", NULL);
2478 form = XtVaCreateManagedWidget("form", xmFormWidgetClass, selBox, NULL);
2480 TabDistText = XtVaCreateManagedWidget("tabDistText", xmTextWidgetClass,
2481 form, XmNcolumns, 7,
2482 XmNtopAttachment, XmATTACH_FORM,
2483 XmNrightAttachment, XmATTACH_FORM, NULL);
2484 RemapDeleteKey(TabDistText);
2485 XtVaCreateManagedWidget("tabDistLabel", xmLabelGadgetClass, form,
2486 XmNlabelString, s1=XmStringCreateSimple(
2487 "Tab spacing (for hardware tab characters)"),
2488 XmNmnemonic, 'T',
2489 XmNuserData, TabDistText,
2490 XmNtopAttachment, XmATTACH_FORM,
2491 XmNleftAttachment, XmATTACH_FORM,
2492 XmNrightAttachment, XmATTACH_WIDGET,
2493 XmNrightWidget, TabDistText,
2494 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2495 XmNbottomWidget, TabDistText, NULL);
2496 XmStringFree(s1);
2498 EmTabText = XtVaCreateManagedWidget("emTabText", xmTextWidgetClass, form,
2499 XmNcolumns, 7,
2500 XmNtopAttachment, XmATTACH_WIDGET,
2501 XmNtopWidget, TabDistText,
2502 XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET,
2503 XmNrightWidget, TabDistText, NULL);
2504 RemapDeleteKey(EmTabText);
2505 EmTabLabel = XtVaCreateManagedWidget("emTabLabel", xmLabelGadgetClass, form,
2506 XmNlabelString, s1=XmStringCreateSimple("Emulated tab spacing"),
2507 XmNmnemonic, 's',
2508 XmNuserData, EmTabText,
2509 XmNtopAttachment, XmATTACH_WIDGET,
2510 XmNtopWidget, TabDistText,
2511 XmNrightAttachment, XmATTACH_WIDGET,
2512 XmNrightWidget, EmTabText,
2513 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2514 XmNbottomWidget, EmTabText, NULL);
2515 XmStringFree(s1);
2516 EmTabToggle = XtVaCreateManagedWidget("emTabToggle",
2517 xmToggleButtonWidgetClass, form, XmNlabelString,
2518 s1=XmStringCreateSimple("Emulate tabs"),
2519 XmNmnemonic, 'E',
2520 XmNtopAttachment, XmATTACH_WIDGET,
2521 XmNtopWidget, TabDistText,
2522 XmNleftAttachment, XmATTACH_FORM,
2523 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2524 XmNbottomWidget, EmTabText, NULL);
2525 XmStringFree(s1);
2526 XtAddCallback(EmTabToggle, XmNvalueChangedCallback, emTabsCB, NULL);
2527 UseTabsToggle = XtVaCreateManagedWidget("useTabsToggle",
2528 xmToggleButtonWidgetClass, form,
2529 XmNlabelString, s1=XmStringCreateSimple(
2530 "Use tab characters in padding and emulated tabs"),
2531 XmNmnemonic, 'U',
2532 XmNtopAttachment, XmATTACH_WIDGET,
2533 XmNtopWidget, EmTabText,
2534 XmNtopOffset, 5,
2535 XmNleftAttachment, XmATTACH_FORM, NULL);
2536 XmStringFree(s1);
2538 /* Set default values */
2539 if (forWindow == NULL) {
2540 emTabDist = GetPrefEmTabDist(PLAIN_LANGUAGE_MODE);
2541 useTabs = GetPrefInsertTabs();
2542 tabDist = GetPrefTabDist(PLAIN_LANGUAGE_MODE);
2543 } else {
2544 XtVaGetValues(forWindow->textArea, textNemulateTabs, &emTabDist, NULL);
2545 useTabs = forWindow->buffer->useTabs;
2546 tabDist = BufGetTabDistance(forWindow->buffer);
2548 emulate = emTabDist != 0;
2549 SetIntText(TabDistText, tabDist);
2550 XmToggleButtonSetState(EmTabToggle, emulate, True);
2551 if (emulate)
2552 SetIntText(EmTabText, emTabDist);
2553 XmToggleButtonSetState(UseTabsToggle, useTabs, False);
2554 XtSetSensitive(EmTabText, emulate);
2555 XtSetSensitive(EmTabLabel, emulate);
2557 /* Handle mnemonic selection of buttons and focus to dialog */
2558 AddDialogMnemonicHandler(form, FALSE);
2560 /* Set the widget to get focus */
2561 #if XmVersion >= 1002
2562 XtVaSetValues(form, XmNinitialFocus, TabDistText, NULL);
2563 #endif
2565 /* put up dialog and wait for user to press ok or cancel */
2566 TabsDialogForWindow = forWindow;
2567 DoneWithTabsDialog = False;
2568 ManageDialogCenteredOnPointer(selBox);
2569 while (!DoneWithTabsDialog)
2571 XEvent event;
2572 XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
2573 ServerDispatchEvent(&event);
2576 XtDestroyWidget(selBox);
2579 static void tabsOKCB(Widget w, XtPointer clientData, XtPointer callData)
2581 int emulate, useTabs, stat, tabDist, emTabDist;
2582 WindowInfo *window = TabsDialogForWindow;
2584 /* get the values that the user entered and make sure they're ok */
2585 emulate = XmToggleButtonGetState(EmTabToggle);
2586 useTabs = XmToggleButtonGetState(UseTabsToggle);
2587 stat = GetIntTextWarn(TabDistText, &tabDist, "tab spacing", True);
2588 if (stat != TEXT_READ_OK)
2589 return;
2591 if (tabDist <= 0 || tabDist > MAX_EXP_CHAR_LEN)
2593 DialogF(DF_WARN, TabDistText, 1, "Tab Spacing",
2594 "Tab spacing out of range", "OK");
2595 return;
2598 if (emulate) {
2599 stat = GetIntTextWarn(EmTabText, &emTabDist, "emulated tab spacing",True);
2600 if (stat != TEXT_READ_OK)
2601 return;
2603 if (emTabDist <= 0 || tabDist >= 1000)
2605 DialogF(DF_WARN, EmTabText, 1, "Tab Spacing",
2606 "Emulated tab spacing out of range", "OK");
2607 return;
2609 } else
2610 emTabDist = 0;
2612 #ifdef SGI_CUSTOM
2613 /* Ask the user about saving as a default preference */
2614 if (TabsDialogForWindow != NULL) {
2615 int setDefault;
2616 if (!shortPrefToDefault(window->shell, "Tab Settings", &setDefault)) {
2617 DoneWithTabsDialog = True;
2618 return;
2620 if (setDefault) {
2621 SetPrefTabDist(tabDist);
2622 SetPrefEmTabDist(emTabDist);
2623 SetPrefInsertTabs(useTabs);
2624 SaveNEditPrefs(window->shell, GetPrefShortMenus());
2627 #endif
2629 /* Set the value in either the requested window or default preferences */
2630 if (TabsDialogForWindow == NULL) {
2631 SetPrefTabDist(tabDist);
2632 SetPrefEmTabDist(emTabDist);
2633 SetPrefInsertTabs(useTabs);
2634 } else {
2635 char *params[1];
2636 char numStr[25];
2638 params[0] = numStr;
2639 sprintf(numStr, "%d", tabDist);
2640 XtCallActionProc(window->textArea, "set_tab_dist", NULL, params, 1);
2641 params[0] = numStr;
2642 sprintf(numStr, "%d", emTabDist);
2643 XtCallActionProc(window->textArea, "set_em_tab_dist", NULL, params, 1);
2644 params[0] = numStr;
2645 sprintf(numStr, "%d", useTabs);
2646 XtCallActionProc(window->textArea, "set_use_tabs", NULL, params, 1);
2648 setTabDist(window, tabDist);
2649 setEmTabDist(window, emTabDist);
2650 window->buffer->useTabs = useTabs;
2653 DoneWithTabsDialog = True;
2656 static void tabsCancelCB(Widget w, XtPointer clientData, XtPointer callData)
2658 DoneWithTabsDialog = True;
2661 static void tabsHelpCB(Widget w, XtPointer clientData, XtPointer callData)
2663 Help(HELP_TABS_DIALOG);
2666 static void emTabsCB(Widget w, XtPointer clientData, XtPointer callData)
2668 int state = XmToggleButtonGetState(w);
2670 XtSetSensitive(EmTabLabel, state);
2671 XtSetSensitive(EmTabText, state);
2675 ** Present the user a dialog for setting wrap margin.
2677 void WrapMarginDialog(Widget parent, WindowInfo *forWindow)
2679 Widget form, selBox;
2680 Arg selBoxArgs[2];
2681 XmString s1;
2682 int margin;
2684 XtSetArg(selBoxArgs[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
2685 XtSetArg(selBoxArgs[1], XmNautoUnmanage, False);
2686 selBox = CreatePromptDialog(parent, "wrapMargin", selBoxArgs, 2);
2687 XtAddCallback(selBox, XmNokCallback, (XtCallbackProc)wrapOKCB, NULL);
2688 XtAddCallback(selBox, XmNcancelCallback, (XtCallbackProc)wrapCancelCB,NULL);
2689 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_TEXT));
2690 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_SELECTION_LABEL));
2691 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_HELP_BUTTON));
2692 XtVaSetValues(XtParent(selBox), XmNtitle, "Wrap Margin", NULL);
2694 form = XtVaCreateManagedWidget("form", xmFormWidgetClass, selBox, NULL);
2696 WrapWindowToggle = XtVaCreateManagedWidget("wrapWindowToggle",
2697 xmToggleButtonWidgetClass, form, XmNlabelString,
2698 s1=XmStringCreateSimple("Wrap and Fill at width of window"),
2699 XmNmnemonic, 'W',
2700 XmNtopAttachment, XmATTACH_FORM,
2701 XmNleftAttachment, XmATTACH_FORM, NULL);
2702 XmStringFree(s1);
2703 XtAddCallback(WrapWindowToggle, XmNvalueChangedCallback, wrapWindowCB,NULL);
2704 WrapText = XtVaCreateManagedWidget("wrapText", xmTextWidgetClass, form,
2705 XmNcolumns, 5,
2706 XmNtopAttachment, XmATTACH_WIDGET,
2707 XmNtopWidget, WrapWindowToggle,
2708 XmNrightAttachment, XmATTACH_FORM, NULL);
2709 RemapDeleteKey(WrapText);
2710 WrapTextLabel = XtVaCreateManagedWidget("wrapMarginLabel",
2711 xmLabelGadgetClass, form,
2712 XmNlabelString, s1=XmStringCreateSimple(
2713 "Margin for Wrap and Fill"),
2714 XmNmnemonic, 'M',
2715 XmNuserData, WrapText,
2716 XmNtopAttachment, XmATTACH_WIDGET,
2717 XmNtopWidget, WrapWindowToggle,
2718 XmNleftAttachment, XmATTACH_FORM,
2719 XmNrightAttachment, XmATTACH_WIDGET,
2720 XmNrightWidget, WrapText,
2721 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2722 XmNbottomWidget, WrapText, NULL);
2723 XmStringFree(s1);
2725 /* Set default value */
2726 if (forWindow == NULL)
2727 margin = GetPrefWrapMargin();
2728 else
2729 XtVaGetValues(forWindow->textArea, textNwrapMargin, &margin, NULL);
2730 XmToggleButtonSetState(WrapWindowToggle, margin==0, True);
2731 if (margin != 0)
2732 SetIntText(WrapText, margin);
2733 XtSetSensitive(WrapText, margin!=0);
2734 XtSetSensitive(WrapTextLabel, margin!=0);
2736 /* Handle mnemonic selection of buttons and focus to dialog */
2737 AddDialogMnemonicHandler(form, FALSE);
2739 /* put up dialog and wait for user to press ok or cancel */
2740 WrapDialogForWindow = forWindow;
2741 DoneWithWrapDialog = False;
2742 ManageDialogCenteredOnPointer(selBox);
2743 while (!DoneWithWrapDialog)
2745 XEvent event;
2746 XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
2747 ServerDispatchEvent(&event);
2750 XtDestroyWidget(selBox);
2753 static void wrapOKCB(Widget w, XtPointer clientData, XtPointer callData)
2755 int wrapAtWindow, margin, stat;
2756 WindowInfo *window = WrapDialogForWindow;
2758 /* get the values that the user entered and make sure they're ok */
2759 wrapAtWindow = XmToggleButtonGetState(WrapWindowToggle);
2760 if (wrapAtWindow)
2761 margin = 0;
2762 else {
2763 stat = GetIntTextWarn(WrapText, &margin, "wrap Margin", True);
2764 if (stat != TEXT_READ_OK)
2765 return;
2767 if (margin <= 0 || margin >= 1000)
2769 DialogF(DF_WARN, WrapText, 1, "Wrap Margin",
2770 "Wrap margin out of range", "OK");
2771 return;
2776 #ifdef SGI_CUSTOM
2777 /* Ask the user about saving as a default preference */
2778 if (WrapDialogForWindow != NULL) {
2779 int setDefault;
2780 if (!shortPrefToDefault(window->shell, "Wrap Margin Settings",
2781 &setDefault)) {
2782 DoneWithWrapDialog = True;
2783 return;
2785 if (setDefault) {
2786 SetPrefWrapMargin(margin);
2787 SaveNEditPrefs(window->shell, GetPrefShortMenus());
2790 #endif
2792 /* Set the value in either the requested window or default preferences */
2793 if (WrapDialogForWindow == NULL)
2794 SetPrefWrapMargin(margin);
2795 else {
2796 char *params[1];
2797 char marginStr[25];
2798 sprintf(marginStr, "%d", margin);
2799 params[0] = marginStr;
2800 XtCallActionProc(window->textArea, "set_wrap_margin", NULL, params, 1);
2802 DoneWithWrapDialog = True;
2805 static void wrapCancelCB(Widget w, XtPointer clientData, XtPointer callData)
2807 DoneWithWrapDialog = True;
2810 static void wrapWindowCB(Widget w, XtPointer clientData, XtPointer callData)
2812 int wrapAtWindow = XmToggleButtonGetState(w);
2814 XtSetSensitive(WrapTextLabel, !wrapAtWindow);
2815 XtSetSensitive(WrapText, !wrapAtWindow);
2819 ** Create and show a dialog for selecting the shell
2821 void SelectShellDialog(Widget parent, WindowInfo* forWindow)
2823 Widget shellSelDialog;
2824 Arg shellSelDialogArgs[2];
2825 XmString label;
2827 /* Set up the dialog. */
2828 XtSetArg(shellSelDialogArgs[0],
2829 XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
2830 XtSetArg(shellSelDialogArgs[1], XmNautoUnmanage, False);
2831 shellSelDialog = CreatePromptDialog(parent, "shellSelDialog",
2832 shellSelDialogArgs, 2);
2834 /* Fix dialog to our liking. */
2835 XtVaSetValues(XtParent(shellSelDialog), XmNtitle, "Command Shell", NULL);
2836 XtAddCallback(shellSelDialog, XmNokCallback, (XtCallbackProc) shellSelOKCB,
2837 shellSelDialog);
2838 XtAddCallback(shellSelDialog, XmNcancelCallback,
2839 (XtCallbackProc) shellSelCancelCB, NULL);
2840 XtUnmanageChild(XmSelectionBoxGetChild(shellSelDialog, XmDIALOG_HELP_BUTTON));
2841 label = XmStringCreateLocalized("Enter shell path:");
2842 XtVaSetValues(shellSelDialog, XmNselectionLabelString, label, NULL);
2843 XmStringFree(label);
2845 /* Set dialog's text to the current setting. */
2846 XmTextSetString(XmSelectionBoxGetChild(shellSelDialog, XmDIALOG_TEXT),
2847 (char*) GetPrefShell());
2849 DoneWithShellSelDialog = False;
2851 /* Show dialog and wait until the user made her choice. */
2852 ManageDialogCenteredOnPointer(shellSelDialog);
2853 while (!DoneWithShellSelDialog) {
2854 XEvent event;
2855 XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
2856 ServerDispatchEvent(&event);
2859 XtDestroyWidget(shellSelDialog);
2862 static void shellSelOKCB(Widget widget, XtPointer clientData,
2863 XtPointer callData)
2865 Widget shellSelDialog = (Widget) clientData;
2866 String shellName = XtMalloc(MAXPATHLEN);
2867 struct stat attribute;
2868 unsigned dlgResult;
2870 /* Leave with a warning if the dialog is not up. */
2871 if (!XtIsRealized(shellSelDialog)) {
2872 fprintf(stderr, "nedit: Callback shellSelOKCB() illegally called.\n");
2873 return;
2876 /* Get the string that the user entered and make sure it's ok. */
2877 shellName = XmTextGetString(XmSelectionBoxGetChild(shellSelDialog,
2878 XmDIALOG_TEXT));
2880 if (-1 == stat(shellName, &attribute)) {
2881 dlgResult = DialogF(DF_WARN, shellSelDialog, 2, "Command Shell",
2882 "The selected shell is not available.\nDo you want to use it anyway?",
2883 "OK", "Cancel");
2884 if (1 != dlgResult) {
2885 return;
2889 SetPrefShell(shellName);
2890 XtFree(shellName);
2892 DoneWithShellSelDialog = True;
2895 static void shellSelCancelCB(Widget widgget, XtPointer clientData,
2896 XtPointer callData)
2898 DoneWithShellSelDialog = True;
2902 ** Present a dialog for editing language mode information
2904 void EditLanguageModes(void)
2906 #define LIST_RIGHT 40
2907 #define LEFT_MARGIN_POS 1
2908 #define RIGHT_MARGIN_POS 99
2909 #define H_MARGIN 5
2910 Widget form, nameLbl, topLbl, extLbl, recogLbl, delimitLbl, defTipsLbl;
2911 Widget okBtn, applyBtn, closeBtn;
2912 Widget overrideFrame, overrideForm, delimitForm;
2913 Widget tabForm, tabLbl, indentBox, wrapBox;
2914 XmString s1;
2915 int i, ac;
2916 Arg args[20];
2918 /* if the dialog is already displayed, just pop it to the top and return */
2919 if (LMDialog.shell != NULL) {
2920 RaiseDialogWindow(LMDialog.shell);
2921 return;
2924 LMDialog.languageModeList = (languageModeRec **)XtMalloc(
2925 sizeof(languageModeRec *) * MAX_LANGUAGE_MODES);
2926 for (i=0; i<NLanguageModes; i++)
2927 LMDialog.languageModeList[i] = copyLanguageModeRec(LanguageModes[i]);
2928 LMDialog.nLanguageModes = NLanguageModes;
2930 /* Create a form widget in an application shell */
2931 ac = 0;
2932 XtSetArg(args[ac], XmNdeleteResponse, XmDO_NOTHING); ac++;
2933 XtSetArg(args[ac], XmNiconName, "NEdit Language Modes"); ac++;
2934 XtSetArg(args[ac], XmNtitle, "Language Modes"); ac++;
2935 LMDialog.shell = CreateWidget(TheAppShell, "langModes",
2936 topLevelShellWidgetClass, args, ac);
2937 AddSmallIcon(LMDialog.shell);
2938 form = XtVaCreateManagedWidget("editLanguageModes", xmFormWidgetClass,
2939 LMDialog.shell, XmNautoUnmanage, False,
2940 XmNresizePolicy, XmRESIZE_NONE, NULL);
2941 XtAddCallback(form, XmNdestroyCallback, lmDestroyCB, NULL);
2942 AddMotifCloseCallback(LMDialog.shell, lmCloseCB, NULL);
2944 topLbl = XtVaCreateManagedWidget("topLabel", xmLabelGadgetClass, form,
2945 XmNlabelString, s1=MKSTRING(
2946 "To modify the properties of an existing language mode, select the name from\n\
2947 the list on the left. To add a new language, select \"New\" from the list."),
2948 XmNmnemonic, 'N',
2949 XmNtopAttachment, XmATTACH_POSITION,
2950 XmNtopPosition, 2,
2951 XmNleftAttachment, XmATTACH_POSITION,
2952 XmNleftPosition, LEFT_MARGIN_POS,
2953 XmNrightAttachment, XmATTACH_POSITION,
2954 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
2955 XmStringFree(s1);
2957 nameLbl = XtVaCreateManagedWidget("nameLbl", xmLabelGadgetClass, form,
2958 XmNlabelString, s1=XmStringCreateSimple("Name"),
2959 XmNmnemonic, 'm',
2960 XmNalignment, XmALIGNMENT_BEGINNING,
2961 XmNleftAttachment, XmATTACH_POSITION,
2962 XmNleftPosition, LIST_RIGHT,
2963 XmNtopAttachment, XmATTACH_WIDGET,
2964 XmNtopOffset, H_MARGIN,
2965 XmNtopWidget, topLbl, NULL);
2966 XmStringFree(s1);
2968 LMDialog.nameW = XtVaCreateManagedWidget("name", xmTextWidgetClass, form,
2969 XmNcolumns, 15,
2970 XmNleftAttachment, XmATTACH_POSITION,
2971 XmNleftPosition, LIST_RIGHT,
2972 XmNtopAttachment, XmATTACH_WIDGET,
2973 XmNtopWidget, nameLbl,
2974 XmNrightAttachment, XmATTACH_POSITION,
2975 XmNrightPosition, (RIGHT_MARGIN_POS + LIST_RIGHT)/2, NULL);
2976 RemapDeleteKey(LMDialog.nameW);
2977 XtVaSetValues(nameLbl, XmNuserData, LMDialog.nameW, NULL);
2979 extLbl = XtVaCreateManagedWidget("extLbl", xmLabelGadgetClass, form,
2980 XmNlabelString,
2981 s1=XmStringCreateSimple("File extensions (separate w/ space)"),
2982 XmNmnemonic, 'F',
2983 XmNalignment, XmALIGNMENT_BEGINNING,
2984 XmNleftAttachment, XmATTACH_POSITION,
2985 XmNleftPosition, LIST_RIGHT,
2986 XmNtopAttachment, XmATTACH_WIDGET,
2987 XmNtopOffset, H_MARGIN,
2988 XmNtopWidget, LMDialog.nameW, NULL);
2989 XmStringFree(s1);
2991 LMDialog.extW = XtVaCreateManagedWidget("ext", xmTextWidgetClass, form,
2992 XmNleftAttachment, XmATTACH_POSITION,
2993 XmNleftPosition, LIST_RIGHT,
2994 XmNtopAttachment, XmATTACH_WIDGET,
2995 XmNtopWidget, extLbl,
2996 XmNrightAttachment, XmATTACH_POSITION,
2997 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
2998 RemapDeleteKey(LMDialog.extW);
2999 XtVaSetValues(extLbl, XmNuserData, LMDialog.extW, NULL);
3001 recogLbl = XtVaCreateManagedWidget("recogLbl", xmLabelGadgetClass, form,
3002 XmNlabelString, s1=MKSTRING(
3003 "Recognition regular expression (applied to first 200\n\
3004 characters of file to determine type from content)"),
3005 XmNalignment, XmALIGNMENT_BEGINNING,
3006 XmNmnemonic, 'R',
3007 XmNleftAttachment, XmATTACH_POSITION,
3008 XmNleftPosition, LIST_RIGHT,
3009 XmNtopAttachment, XmATTACH_WIDGET,
3010 XmNtopOffset, H_MARGIN,
3011 XmNtopWidget, LMDialog.extW, NULL);
3012 XmStringFree(s1);
3014 LMDialog.recogW = XtVaCreateManagedWidget("recog", xmTextWidgetClass, form,
3015 XmNleftAttachment, XmATTACH_POSITION,
3016 XmNleftPosition, LIST_RIGHT,
3017 XmNtopAttachment, XmATTACH_WIDGET,
3018 XmNtopWidget, recogLbl,
3019 XmNrightAttachment, XmATTACH_POSITION,
3020 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
3021 RemapDeleteKey(LMDialog.recogW);
3022 XtVaSetValues(recogLbl, XmNuserData, LMDialog.recogW, NULL);
3024 defTipsLbl = XtVaCreateManagedWidget("defTipsLbl", xmLabelGadgetClass, form,
3025 XmNlabelString, s1=MKSTRING(
3026 "Default calltips file(s) (separate w/colons)"),
3027 XmNalignment, XmALIGNMENT_BEGINNING,
3028 XmNmnemonic, 'c',
3029 XmNleftAttachment, XmATTACH_POSITION,
3030 XmNleftPosition, LIST_RIGHT,
3031 XmNtopAttachment, XmATTACH_WIDGET,
3032 XmNtopOffset, H_MARGIN,
3033 XmNtopWidget, LMDialog.recogW, NULL);
3034 XmStringFree(s1);
3036 LMDialog.defTipsW = XtVaCreateManagedWidget("defTips", xmTextWidgetClass,
3037 form,
3038 XmNleftAttachment, XmATTACH_POSITION,
3039 XmNleftPosition, LIST_RIGHT,
3040 XmNtopAttachment, XmATTACH_WIDGET,
3041 XmNtopWidget, defTipsLbl,
3042 XmNrightAttachment, XmATTACH_POSITION,
3043 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
3044 RemapDeleteKey(LMDialog.defTipsW);
3045 XtVaSetValues(defTipsLbl, XmNuserData, LMDialog.defTipsW, NULL);
3047 okBtn = XtVaCreateManagedWidget("ok", xmPushButtonWidgetClass, form,
3048 XmNlabelString, s1=XmStringCreateSimple("OK"),
3049 XmNmarginWidth, BUTTON_WIDTH_MARGIN,
3050 XmNleftAttachment, XmATTACH_POSITION,
3051 XmNleftPosition, 10,
3052 XmNrightAttachment, XmATTACH_POSITION,
3053 XmNrightPosition, 30,
3054 XmNbottomAttachment, XmATTACH_POSITION,
3055 XmNbottomPosition, 99, NULL);
3056 XtAddCallback(okBtn, XmNactivateCallback, lmOkCB, NULL);
3057 XmStringFree(s1);
3059 applyBtn = XtVaCreateManagedWidget("apply", xmPushButtonWidgetClass, form,
3060 XmNlabelString, s1=XmStringCreateSimple("Apply"),
3061 XmNmnemonic, 'A',
3062 XmNleftAttachment, XmATTACH_POSITION,
3063 XmNleftPosition, 40,
3064 XmNrightAttachment, XmATTACH_POSITION,
3065 XmNrightPosition, 60,
3066 XmNbottomAttachment, XmATTACH_POSITION,
3067 XmNbottomPosition, 99, NULL);
3068 XtAddCallback(applyBtn, XmNactivateCallback, lmApplyCB, NULL);
3069 XmStringFree(s1);
3071 closeBtn = XtVaCreateManagedWidget("close",xmPushButtonWidgetClass,form,
3072 XmNlabelString, s1=XmStringCreateSimple("Close"),
3073 XmNleftAttachment, XmATTACH_POSITION,
3074 XmNleftPosition, 70,
3075 XmNrightAttachment, XmATTACH_POSITION,
3076 XmNrightPosition, 90,
3077 XmNbottomAttachment, XmATTACH_POSITION,
3078 XmNbottomPosition, 99, NULL);
3079 XtAddCallback(closeBtn, XmNactivateCallback, lmCloseCB, NULL);
3080 XmStringFree(s1);
3082 overrideFrame = XtVaCreateManagedWidget("overrideFrame",
3083 xmFrameWidgetClass, form,
3084 XmNleftAttachment, XmATTACH_POSITION,
3085 XmNleftPosition, LEFT_MARGIN_POS,
3086 XmNrightAttachment, XmATTACH_POSITION,
3087 XmNrightPosition, RIGHT_MARGIN_POS,
3088 XmNbottomAttachment, XmATTACH_WIDGET,
3089 XmNbottomWidget, closeBtn,
3090 XmNbottomOffset, H_MARGIN, NULL);
3091 overrideForm = XtVaCreateManagedWidget("overrideForm", xmFormWidgetClass,
3092 overrideFrame, NULL);
3093 XtVaCreateManagedWidget("overrideLbl", xmLabelGadgetClass, overrideFrame,
3094 XmNlabelString, s1=XmStringCreateSimple("Override Defaults"),
3095 XmNchildType, XmFRAME_TITLE_CHILD,
3096 XmNchildHorizontalAlignment, XmALIGNMENT_CENTER, NULL);
3097 XmStringFree(s1);
3099 delimitForm = XtVaCreateManagedWidget("delimitForm", xmFormWidgetClass,
3100 overrideForm,
3101 XmNleftAttachment, XmATTACH_POSITION,
3102 XmNleftPosition, LEFT_MARGIN_POS,
3103 XmNtopAttachment, XmATTACH_FORM,
3104 XmNtopOffset, H_MARGIN,
3105 XmNrightAttachment, XmATTACH_POSITION,
3106 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
3107 delimitLbl = XtVaCreateManagedWidget("delimitLbl", xmLabelGadgetClass,
3108 delimitForm,
3109 XmNlabelString, s1=XmStringCreateSimple("Word delimiters"),
3110 XmNmnemonic, 'W',
3111 XmNleftAttachment, XmATTACH_FORM,
3112 XmNtopAttachment, XmATTACH_FORM,
3113 XmNbottomAttachment, XmATTACH_FORM, NULL);
3114 XmStringFree(s1);
3115 LMDialog.delimitW = XtVaCreateManagedWidget("delimit", xmTextWidgetClass,
3116 delimitForm,
3117 XmNtopAttachment, XmATTACH_FORM,
3118 XmNleftAttachment, XmATTACH_WIDGET,
3119 XmNleftWidget, delimitLbl,
3120 XmNrightAttachment, XmATTACH_FORM,
3121 XmNbottomAttachment, XmATTACH_FORM, NULL);
3122 RemapDeleteKey(LMDialog.delimitW);
3123 XtVaSetValues(delimitLbl, XmNuserData, LMDialog.delimitW, NULL);
3125 tabForm = XtVaCreateManagedWidget("tabForm", xmFormWidgetClass,
3126 overrideForm,
3127 XmNleftAttachment, XmATTACH_POSITION,
3128 XmNleftPosition, LEFT_MARGIN_POS,
3129 XmNtopAttachment, XmATTACH_WIDGET,
3130 XmNtopWidget, delimitForm,
3131 XmNtopOffset, H_MARGIN,
3132 XmNrightAttachment, XmATTACH_POSITION,
3133 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
3134 tabLbl = XtVaCreateManagedWidget("tabLbl", xmLabelGadgetClass, tabForm,
3135 XmNlabelString, s1=XmStringCreateSimple(
3136 "Alternative hardware tab spacing"),
3137 XmNmnemonic, 't',
3138 XmNleftAttachment, XmATTACH_FORM,
3139 XmNtopAttachment, XmATTACH_FORM,
3140 XmNbottomAttachment, XmATTACH_FORM, NULL);
3141 XmStringFree(s1);
3142 LMDialog.tabW = XtVaCreateManagedWidget("delimit", xmTextWidgetClass,
3143 tabForm,
3144 XmNcolumns, 3,
3145 XmNtopAttachment, XmATTACH_FORM,
3146 XmNleftAttachment, XmATTACH_WIDGET,
3147 XmNleftWidget, tabLbl,
3148 XmNbottomAttachment, XmATTACH_FORM, NULL);
3149 RemapDeleteKey(LMDialog.tabW);
3150 XtVaSetValues(tabLbl, XmNuserData, LMDialog.tabW, NULL);
3151 LMDialog.emTabW = XtVaCreateManagedWidget("delimit", xmTextWidgetClass,
3152 tabForm,
3153 XmNcolumns, 3,
3154 XmNtopAttachment, XmATTACH_FORM,
3155 XmNrightAttachment, XmATTACH_FORM,
3156 XmNbottomAttachment, XmATTACH_FORM, NULL);
3157 RemapDeleteKey(LMDialog.emTabW);
3158 XtVaCreateManagedWidget("emTabLbl", xmLabelGadgetClass, tabForm,
3159 XmNlabelString,
3160 s1=XmStringCreateSimple("Alternative emulated tab spacing"),
3161 XmNalignment, XmALIGNMENT_END,
3162 XmNmnemonic, 'e',
3163 XmNuserData, LMDialog.emTabW,
3164 XmNleftAttachment, XmATTACH_WIDGET,
3165 XmNleftWidget, LMDialog.tabW,
3166 XmNrightAttachment, XmATTACH_WIDGET,
3167 XmNrightWidget, LMDialog.emTabW,
3168 XmNtopAttachment, XmATTACH_FORM,
3169 XmNbottomAttachment, XmATTACH_FORM, NULL);
3170 XmStringFree(s1);
3172 indentBox = XtVaCreateManagedWidget("indentBox", xmRowColumnWidgetClass,
3173 overrideForm,
3174 XmNorientation, XmHORIZONTAL,
3175 XmNpacking, XmPACK_TIGHT,
3176 XmNradioBehavior, True,
3177 XmNleftAttachment, XmATTACH_POSITION,
3178 XmNleftPosition, LEFT_MARGIN_POS,
3179 XmNtopAttachment, XmATTACH_WIDGET,
3180 XmNtopWidget, tabForm,
3181 XmNtopOffset, H_MARGIN, NULL);
3182 LMDialog.defaultIndentW = XtVaCreateManagedWidget("defaultIndent",
3183 xmToggleButtonWidgetClass, indentBox,
3184 XmNset, True,
3185 XmNmarginHeight, 0,
3186 XmNlabelString, s1=XmStringCreateSimple("Default indent style"),
3187 XmNmnemonic, 'D', NULL);
3188 XmStringFree(s1);
3189 LMDialog.noIndentW = XtVaCreateManagedWidget("noIndent",
3190 xmToggleButtonWidgetClass, indentBox,
3191 XmNmarginHeight, 0,
3192 XmNlabelString, s1=XmStringCreateSimple("No automatic indent"),
3193 XmNmnemonic, 'N', NULL);
3194 XmStringFree(s1);
3195 LMDialog.autoIndentW = XtVaCreateManagedWidget("autoIndent",
3196 xmToggleButtonWidgetClass, indentBox,
3197 XmNmarginHeight, 0,
3198 XmNlabelString, s1=XmStringCreateSimple("Auto-indent"),
3199 XmNmnemonic, 'A', NULL);
3200 XmStringFree(s1);
3201 LMDialog.smartIndentW = XtVaCreateManagedWidget("smartIndent",
3202 xmToggleButtonWidgetClass, indentBox,
3203 XmNmarginHeight, 0,
3204 XmNlabelString, s1=XmStringCreateSimple("Smart-indent"),
3205 XmNmnemonic, 'S', NULL);
3206 XmStringFree(s1);
3208 wrapBox = XtVaCreateManagedWidget("wrapBox", xmRowColumnWidgetClass,
3209 overrideForm,
3210 XmNorientation, XmHORIZONTAL,
3211 XmNpacking, XmPACK_TIGHT,
3212 XmNradioBehavior, True,
3213 XmNleftAttachment, XmATTACH_POSITION,
3214 XmNleftPosition, LEFT_MARGIN_POS,
3215 XmNtopAttachment, XmATTACH_WIDGET,
3216 XmNtopWidget, indentBox,
3217 XmNtopOffset, H_MARGIN,
3218 XmNbottomAttachment, XmATTACH_FORM,
3219 XmNbottomOffset, H_MARGIN, NULL);
3220 LMDialog.defaultWrapW = XtVaCreateManagedWidget("defaultWrap",
3221 xmToggleButtonWidgetClass, wrapBox,
3222 XmNset, True,
3223 XmNmarginHeight, 0,
3224 XmNlabelString, s1=XmStringCreateSimple("Default wrap style"),
3225 XmNmnemonic, 'D', NULL);
3226 XmStringFree(s1);
3227 LMDialog.noWrapW = XtVaCreateManagedWidget("noWrap",
3228 xmToggleButtonWidgetClass, wrapBox,
3229 XmNmarginHeight, 0,
3230 XmNlabelString, s1=XmStringCreateSimple("No wrapping"),
3231 XmNmnemonic, 'N', NULL);
3232 XmStringFree(s1);
3233 LMDialog.newlineWrapW = XtVaCreateManagedWidget("newlineWrap",
3234 xmToggleButtonWidgetClass, wrapBox,
3235 XmNmarginHeight, 0,
3236 XmNlabelString, s1=XmStringCreateSimple("Auto newline wrap"),
3237 XmNmnemonic, 'A', NULL);
3238 XmStringFree(s1);
3239 LMDialog.contWrapW = XtVaCreateManagedWidget("contWrap",
3240 xmToggleButtonWidgetClass, wrapBox,
3241 XmNmarginHeight, 0,
3242 XmNlabelString, s1=XmStringCreateSimple("Continuous wrap"),
3243 XmNmnemonic, 'C', NULL);
3244 XmStringFree(s1);
3246 XtVaCreateManagedWidget("stretchForm", xmFormWidgetClass, form,
3247 XmNtopAttachment, XmATTACH_WIDGET,
3248 XmNtopWidget, LMDialog.defTipsW,
3249 XmNleftAttachment, XmATTACH_POSITION,
3250 XmNleftPosition, LIST_RIGHT,
3251 XmNrightAttachment, XmATTACH_POSITION,
3252 XmNrightPosition, RIGHT_MARGIN_POS,
3253 XmNbottomAttachment, XmATTACH_WIDGET,
3254 XmNbottomWidget, overrideFrame,
3255 XmNbottomOffset, H_MARGIN*2, NULL);
3257 ac = 0;
3258 XtSetArg(args[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
3259 XtSetArg(args[ac], XmNtopOffset, H_MARGIN); ac++;
3260 XtSetArg(args[ac], XmNtopWidget, topLbl); ac++;
3261 XtSetArg(args[ac], XmNleftAttachment, XmATTACH_POSITION); ac++;
3262 XtSetArg(args[ac], XmNleftPosition, LEFT_MARGIN_POS); ac++;
3263 XtSetArg(args[ac], XmNrightAttachment, XmATTACH_POSITION); ac++;
3264 XtSetArg(args[ac], XmNrightPosition, LIST_RIGHT-1); ac++;
3265 XtSetArg(args[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
3266 XtSetArg(args[ac], XmNbottomWidget, overrideFrame); ac++;
3267 XtSetArg(args[ac], XmNbottomOffset, H_MARGIN*2); ac++;
3268 LMDialog.managedListW = CreateManagedList(form, "list", args, ac,
3269 (void **)LMDialog.languageModeList, &LMDialog.nLanguageModes,
3270 MAX_LANGUAGE_MODES, 15, lmGetDisplayedCB, NULL, lmSetDisplayedCB,
3271 NULL, lmFreeItemCB);
3272 AddDeleteConfirmCB(LMDialog.managedListW, lmDeleteConfirmCB, NULL);
3273 XtVaSetValues(topLbl, XmNuserData, LMDialog.managedListW, NULL);
3275 /* Set initial default button */
3276 XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
3277 XtVaSetValues(form, XmNcancelButton, closeBtn, NULL);
3279 /* Handle mnemonic selection of buttons and focus to dialog */
3280 AddDialogMnemonicHandler(form, FALSE);
3282 /* Realize all of the widgets in the new dialog */
3283 RealizeWithoutForcingPosition(LMDialog.shell);
3286 static void lmDestroyCB(Widget w, XtPointer clientData, XtPointer callData)
3288 int i;
3290 for (i=0; i<LMDialog.nLanguageModes; i++)
3291 freeLanguageModeRec(LMDialog.languageModeList[i]);
3292 XtFree((char *)LMDialog.languageModeList);
3295 static void lmOkCB(Widget w, XtPointer clientData, XtPointer callData)
3297 if (!updateLMList())
3298 return;
3300 /* pop down and destroy the dialog */
3301 XtDestroyWidget(LMDialog.shell);
3302 LMDialog.shell = NULL;
3305 static void lmApplyCB(Widget w, XtPointer clientData, XtPointer callData)
3307 updateLMList();
3310 static void lmCloseCB(Widget w, XtPointer clientData, XtPointer callData)
3312 /* pop down and destroy the dialog */
3313 XtDestroyWidget(LMDialog.shell);
3314 LMDialog.shell = NULL;
3317 static int lmDeleteConfirmCB(int itemIndex, void *cbArg)
3319 int i;
3321 /* Allow duplicate names to be deleted regardless of dependencies */
3322 for (i=0; i<LMDialog.nLanguageModes; i++)
3323 if (i != itemIndex && !strcmp(LMDialog.languageModeList[i]->name,
3324 LMDialog.languageModeList[itemIndex]->name))
3325 return True;
3327 /* don't allow deletion if data will be lost */
3328 if (LMHasHighlightPatterns(LMDialog.languageModeList[itemIndex]->name))
3330 DialogF(DF_WARN, LMDialog.shell, 1, "Patterns exist",
3331 "This language mode has syntax highlighting\n"
3332 "patterns defined. Please delete the patterns\n"
3333 "first, in Preferences -> Default Settings ->\n"
3334 "Syntax Highlighting, before proceeding here.", "OK");
3335 return False;
3338 /* don't allow deletion if data will be lost */
3339 if (LMHasSmartIndentMacros(LMDialog.languageModeList[itemIndex]->name))
3341 DialogF(DF_WARN, LMDialog.shell, 1, "Smart Indent Macros exist",
3342 "This language mode has smart indent macros\n"
3343 "defined. Please delete the macros first,\n"
3344 "in Preferences -> Default Settings ->\n"
3345 "Auto Indent -> Program Smart Indent,\n"
3346 "before proceeding here.", "OK");
3347 return False;
3350 return True;
3354 ** Apply the changes that the user has made in the language modes dialog to the
3355 ** stored language mode information for this NEdit session (the data array
3356 ** LanguageModes)
3358 static int updateLMList(void)
3360 WindowInfo *window;
3361 int oldLanguageMode;
3362 char *oldModeName, *newDelimiters;
3363 int i, j;
3365 /* Get the current contents of the dialog fields */
3366 if (!UpdateManagedList(LMDialog.managedListW, True))
3367 return False;
3369 /* Fix up language mode indices in all open windows (which may change
3370 if the currently selected mode is deleted or has changed position),
3371 and update word delimiters */
3372 for (window=WindowList; window!=NULL; window=window->next) {
3373 if (window->languageMode != PLAIN_LANGUAGE_MODE) {
3374 oldLanguageMode = window->languageMode;
3375 oldModeName = LanguageModes[window->languageMode]->name;
3376 window->languageMode = PLAIN_LANGUAGE_MODE;
3377 for (i=0; i<LMDialog.nLanguageModes; i++) {
3378 if (!strcmp(oldModeName, LMDialog.languageModeList[i]->name)) {
3379 newDelimiters = LMDialog.languageModeList[i]->delimiters;
3380 if (newDelimiters == NULL)
3381 newDelimiters = GetPrefDelimiters();
3382 XtVaSetValues(window->textArea, textNwordDelimiters,
3383 newDelimiters, NULL);
3384 for (j=0; j<window->nPanes; j++)
3385 XtVaSetValues(window->textPanes[j],
3386 textNwordDelimiters, newDelimiters, NULL);
3387 /* don't forget to adapt the LM stored within the user menu cache */
3388 if (window->userMenuCache->umcLanguageMode == oldLanguageMode)
3389 window->userMenuCache->umcLanguageMode = i;
3390 if (window->userBGMenuCache.ubmcLanguageMode == oldLanguageMode)
3391 window->userBGMenuCache.ubmcLanguageMode = i;
3392 /* update the language mode of this window (document) */
3393 window->languageMode = i;
3394 break;
3400 /* If there were any name changes, re-name dependent highlight patterns
3401 and smart-indent macros and fix up the weird rename-format names */
3402 for (i=0; i<LMDialog.nLanguageModes; i++) {
3403 if (strchr(LMDialog.languageModeList[i]->name, ':') != NULL) {
3404 char *newName = strrchr(LMDialog.languageModeList[i]->name, ':')+1;
3405 *strchr(LMDialog.languageModeList[i]->name, ':') = '\0';
3406 RenameHighlightPattern(LMDialog.languageModeList[i]->name, newName);
3407 RenameSmartIndentMacros(LMDialog.languageModeList[i]->name, newName);
3408 memmove(LMDialog.languageModeList[i]->name, newName,
3409 strlen(newName) + 1);
3410 ChangeManagedListData(LMDialog.managedListW);
3414 /* Replace the old language mode list with the new one from the dialog */
3415 for (i=0; i<NLanguageModes; i++)
3416 freeLanguageModeRec(LanguageModes[i]);
3417 for (i=0; i<LMDialog.nLanguageModes; i++)
3418 LanguageModes[i] = copyLanguageModeRec(LMDialog.languageModeList[i]);
3419 NLanguageModes = LMDialog.nLanguageModes;
3421 /* Update user menu info to update language mode dependencies of
3422 user menu items */
3423 UpdateUserMenuInfo();
3425 /* Update the menus in the window menu bars and load any needed
3426 calltips files */
3427 for (window=WindowList; window!=NULL; window=window->next) {
3428 updateLanguageModeSubmenu(window);
3429 if (window->languageMode != PLAIN_LANGUAGE_MODE &&
3430 LanguageModes[window->languageMode]->defTipsFile != NULL)
3431 AddTagsFile(LanguageModes[window->languageMode]->defTipsFile, TIP);
3432 /* cache user menus: Rebuild all user menus of this window */
3433 RebuildAllMenus(window);
3436 /* If a syntax highlighting dialog is up, update its menu */
3437 UpdateLanguageModeMenu();
3438 /* The same for the smart indent macro dialog */
3439 UpdateLangModeMenuSmartIndent();
3440 /* Note that preferences have been changed */
3441 MarkPrefsChanged();
3443 return True;
3446 static void *lmGetDisplayedCB(void *oldItem, int explicitRequest, int *abort,
3447 void *cbArg)
3449 languageModeRec *lm, *oldLM = (languageModeRec *)oldItem;
3450 char *tempName;
3451 int i, nCopies, oldLen;
3453 /* If the dialog is currently displaying the "new" entry and the
3454 fields are empty, that's just fine */
3455 if (oldItem == NULL && lmDialogEmpty())
3456 return NULL;
3458 /* Read the data the user has entered in the dialog fields */
3459 lm = readLMDialogFields(True);
3461 /* If there was a name change of a non-duplicate language mode, modify the
3462 name to the weird format of: ":old name:new name". This signals that a
3463 name change is necessary in lm dependent data such as highlight
3464 patterns. Duplicate language modes may be re-named at will, since no
3465 data will be lost due to the name change. */
3466 if (lm != NULL && oldLM != NULL && strcmp(oldLM->name, lm->name)) {
3467 nCopies = 0;
3468 for (i=0; i<LMDialog.nLanguageModes; i++)
3469 if (!strcmp(oldLM->name, LMDialog.languageModeList[i]->name))
3470 nCopies++;
3471 if (nCopies <= 1) {
3472 oldLen = strchr(oldLM->name, ':') == NULL ? strlen(oldLM->name) :
3473 strchr(oldLM->name, ':') - oldLM->name;
3474 tempName = XtMalloc(oldLen + strlen(lm->name) + 2);
3475 strncpy(tempName, oldLM->name, oldLen);
3476 sprintf(&tempName[oldLen], ":%s", lm->name);
3477 XtFree(lm->name);
3478 lm->name = tempName;
3482 /* If there are no problems reading the data, just return it */
3483 if (lm != NULL)
3484 return (void *)lm;
3486 /* If there are problems, and the user didn't ask for the fields to be
3487 read, give more warning */
3488 if (!explicitRequest)
3490 if (DialogF(DF_WARN, LMDialog.shell, 2, "Discard Language Mode",
3491 "Discard incomplete entry\nfor current language mode?", "Keep",
3492 "Discard") == 2)
3494 return oldItem == NULL
3495 ? NULL
3496 : (void *)copyLanguageModeRec((languageModeRec *)oldItem);
3500 /* Do readLMDialogFields again without "silent" mode to display warning */
3501 lm = readLMDialogFields(False);
3502 *abort = True;
3503 return NULL;
3506 static void lmSetDisplayedCB(void *item, void *cbArg)
3508 languageModeRec *lm = (languageModeRec *)item;
3509 char *extStr;
3511 if (item == NULL) {
3512 XmTextSetString(LMDialog.nameW, "");
3513 XmTextSetString(LMDialog.extW, "");
3514 XmTextSetString(LMDialog.recogW, "");
3515 XmTextSetString(LMDialog.defTipsW, "");
3516 XmTextSetString(LMDialog.delimitW, "");
3517 XmTextSetString(LMDialog.tabW, "");
3518 XmTextSetString(LMDialog.emTabW, "");
3519 RadioButtonChangeState(LMDialog.defaultIndentW, True, True);
3520 RadioButtonChangeState(LMDialog.defaultWrapW, True, True);
3521 } else {
3522 XmTextSetString(LMDialog.nameW, strchr(lm->name, ':') == NULL ?
3523 lm->name : strchr(lm->name, ':')+1);
3524 extStr = createExtString(lm->extensions, lm->nExtensions);
3525 XmTextSetString(LMDialog.extW, extStr);
3526 XtFree(extStr);
3527 XmTextSetString(LMDialog.recogW, lm->recognitionExpr);
3528 XmTextSetString(LMDialog.defTipsW, lm->defTipsFile);
3529 XmTextSetString(LMDialog.delimitW, lm->delimiters);
3530 if (lm->tabDist == DEFAULT_TAB_DIST)
3531 XmTextSetString(LMDialog.tabW, "");
3532 else
3533 SetIntText(LMDialog.tabW, lm->tabDist);
3534 if (lm->emTabDist == DEFAULT_EM_TAB_DIST)
3535 XmTextSetString(LMDialog.emTabW, "");
3536 else
3537 SetIntText(LMDialog.emTabW, lm->emTabDist);
3538 RadioButtonChangeState(LMDialog.defaultIndentW,
3539 lm->indentStyle == DEFAULT_INDENT, False);
3540 RadioButtonChangeState(LMDialog.noIndentW,
3541 lm->indentStyle == NO_AUTO_INDENT, False);
3542 RadioButtonChangeState(LMDialog.autoIndentW,
3543 lm->indentStyle == AUTO_INDENT, False);
3544 RadioButtonChangeState(LMDialog.smartIndentW,
3545 lm->indentStyle == SMART_INDENT, False);
3546 RadioButtonChangeState(LMDialog.defaultWrapW,
3547 lm->wrapStyle == DEFAULT_WRAP, False);
3548 RadioButtonChangeState(LMDialog.noWrapW,
3549 lm->wrapStyle == NO_WRAP, False);
3550 RadioButtonChangeState(LMDialog.newlineWrapW,
3551 lm->wrapStyle == NEWLINE_WRAP, False);
3552 RadioButtonChangeState(LMDialog.contWrapW,
3553 lm->wrapStyle == CONTINUOUS_WRAP, False);
3557 static void lmFreeItemCB(void *item)
3559 freeLanguageModeRec((languageModeRec *)item);
3562 static void freeLanguageModeRec(languageModeRec *lm)
3564 int i;
3566 XtFree(lm->name);
3567 XtFree(lm->recognitionExpr);
3568 XtFree(lm->defTipsFile);
3569 XtFree(lm->delimiters);
3570 for (i=0; i<lm->nExtensions; i++)
3571 XtFree(lm->extensions[i]);
3572 XtFree((char*) lm->extensions);
3573 XtFree((char *)lm);
3577 ** Copy a languageModeRec data structure and all of the allocated data it contains
3579 static languageModeRec *copyLanguageModeRec(languageModeRec *lm)
3581 languageModeRec *newLM;
3582 int i;
3584 newLM = (languageModeRec *)XtMalloc(sizeof(languageModeRec));
3585 newLM->name = XtMalloc(strlen(lm->name)+1);
3586 strcpy(newLM->name, lm->name);
3587 newLM->nExtensions = lm->nExtensions;
3588 newLM->extensions = (char **)XtMalloc(sizeof(char *) * lm->nExtensions);
3589 for (i=0; i<lm->nExtensions; i++) {
3590 newLM->extensions[i] = XtMalloc(strlen(lm->extensions[i]) + 1);
3591 strcpy(newLM->extensions[i], lm->extensions[i]);
3593 if (lm->recognitionExpr == NULL)
3594 newLM->recognitionExpr = NULL;
3595 else {
3596 newLM->recognitionExpr = XtMalloc(strlen(lm->recognitionExpr)+1);
3597 strcpy(newLM->recognitionExpr, lm->recognitionExpr);
3599 if (lm->defTipsFile == NULL)
3600 newLM->defTipsFile = NULL;
3601 else {
3602 newLM->defTipsFile = XtMalloc(strlen(lm->defTipsFile)+1);
3603 strcpy(newLM->defTipsFile, lm->defTipsFile);
3605 if (lm->delimiters == NULL)
3606 newLM->delimiters = NULL;
3607 else {
3608 newLM->delimiters = XtMalloc(strlen(lm->delimiters)+1);
3609 strcpy(newLM->delimiters, lm->delimiters);
3611 newLM->wrapStyle = lm->wrapStyle;
3612 newLM->indentStyle = lm->indentStyle;
3613 newLM->tabDist = lm->tabDist;
3614 newLM->emTabDist = lm->emTabDist;
3615 return newLM;
3619 ** Read the fields in the language modes dialog and create a languageModeRec data
3620 ** structure reflecting the current state of the selected language mode in the dialog.
3621 ** If any of the information is incorrect or missing, display a warning dialog and
3622 ** return NULL. Passing "silent" as True, suppresses the warning dialogs.
3624 static languageModeRec *readLMDialogFields(int silent)
3626 languageModeRec *lm;
3627 regexp *compiledRE;
3628 char *compileMsg, *extStr, *extPtr;
3630 /* Allocate a language mode structure to return, set unread fields to
3631 empty so everything can be freed on errors by freeLanguageModeRec */
3632 lm = (languageModeRec *)XtMalloc(sizeof(languageModeRec));
3633 lm->nExtensions = 0;
3634 lm->recognitionExpr = NULL;
3635 lm->defTipsFile = NULL;
3636 lm->delimiters = NULL;
3638 /* read the name field */
3639 lm->name = ReadSymbolicFieldTextWidget(LMDialog.nameW,
3640 "language mode name", silent);
3641 if (lm->name == NULL) {
3642 XtFree((char *)lm);
3643 return NULL;
3646 if (*lm->name == '\0')
3648 if (!silent)
3650 DialogF(DF_WARN, LMDialog.shell, 1, "Language Mode Name",
3651 "Please specify a name\nfor the language mode", "OK");
3652 XmProcessTraversal(LMDialog.nameW, XmTRAVERSE_CURRENT);
3654 freeLanguageModeRec(lm);
3655 return NULL;
3658 /* read the extension list field */
3659 extStr = extPtr = XmTextGetString(LMDialog.extW);
3660 lm->extensions = readExtensionList(&extPtr, &lm->nExtensions);
3661 XtFree(extStr);
3663 /* read recognition expression */
3664 lm->recognitionExpr = XmTextGetString(LMDialog.recogW);
3665 if (*lm->recognitionExpr == '\0') {
3666 XtFree(lm->recognitionExpr);
3667 lm->recognitionExpr = NULL;
3668 } else
3670 compiledRE = CompileRE(lm->recognitionExpr, &compileMsg, REDFLT_STANDARD);
3672 if (compiledRE == NULL)
3674 if (!silent)
3676 DialogF(DF_WARN, LMDialog.shell, 1, "Regex",
3677 "Recognition expression:\n%s", "OK", compileMsg);
3678 XmProcessTraversal(LMDialog.recogW, XmTRAVERSE_CURRENT);
3680 XtFree((char *)compiledRE);
3681 freeLanguageModeRec(lm);
3682 return NULL;
3685 XtFree((char *)compiledRE);
3688 /* Read the default calltips file for the language mode */
3689 lm->defTipsFile = XmTextGetString(LMDialog.defTipsW);
3690 if (*lm->defTipsFile == '\0') {
3691 /* Empty string */
3692 XtFree(lm->defTipsFile);
3693 lm->defTipsFile = NULL;
3694 } else {
3695 /* Ensure that AddTagsFile will work */
3696 if (AddTagsFile(lm->defTipsFile, TIP) == FALSE) {
3697 if (!silent)
3699 DialogF(DF_WARN, LMDialog.shell, 1, "Error reading Calltips",
3700 "Can't read default calltips file(s):\n \"%s\"\n",
3701 "OK", lm->defTipsFile);
3702 XmProcessTraversal(LMDialog.recogW, XmTRAVERSE_CURRENT);
3704 freeLanguageModeRec(lm);
3705 return NULL;
3706 } else
3707 if (DeleteTagsFile(lm->defTipsFile, TIP, False) == FALSE)
3708 fprintf(stderr, "nedit: Internal error: Trouble deleting "
3709 "calltips file(s):\n \"%s\"\n", lm->defTipsFile);
3712 /* read tab spacing field */
3713 if (TextWidgetIsBlank(LMDialog.tabW))
3714 lm->tabDist = DEFAULT_TAB_DIST;
3715 else {
3716 if (GetIntTextWarn(LMDialog.tabW, &lm->tabDist, "tab spacing", False)
3717 != TEXT_READ_OK) {
3718 freeLanguageModeRec(lm);
3719 return NULL;
3722 if (lm->tabDist <= 0 || lm->tabDist > 100)
3724 if (!silent)
3726 DialogF(DF_WARN, LMDialog.shell, 1, "Invalid Tab Spacing",
3727 "Invalid tab spacing: %d", "OK", lm->tabDist);
3728 XmProcessTraversal(LMDialog.tabW, XmTRAVERSE_CURRENT);
3730 freeLanguageModeRec(lm);
3731 return NULL;
3735 /* read emulated tab field */
3736 if (TextWidgetIsBlank(LMDialog.emTabW))
3738 lm->emTabDist = DEFAULT_EM_TAB_DIST;
3739 } else
3741 if (GetIntTextWarn(LMDialog.emTabW, &lm->emTabDist,
3742 "emulated tab spacing", False) != TEXT_READ_OK)
3744 freeLanguageModeRec(lm);
3745 return NULL;
3748 if (lm->emTabDist < 0 || lm->emTabDist > 100)
3750 if (!silent)
3752 DialogF(DF_WARN, LMDialog.shell, 1, "Invalid Tab Spacing",
3753 "Invalid emulated tab spacing: %d", "OK",
3754 lm->emTabDist);
3755 XmProcessTraversal(LMDialog.emTabW, XmTRAVERSE_CURRENT);
3757 freeLanguageModeRec(lm);
3758 return NULL;
3762 /* read delimiters string */
3763 lm->delimiters = XmTextGetString(LMDialog.delimitW);
3764 if (*lm->delimiters == '\0') {
3765 XtFree(lm->delimiters);
3766 lm->delimiters = NULL;
3769 /* read indent style */
3770 if (XmToggleButtonGetState(LMDialog.noIndentW))
3771 lm->indentStyle = NO_AUTO_INDENT;
3772 else if (XmToggleButtonGetState(LMDialog.autoIndentW))
3773 lm->indentStyle = AUTO_INDENT;
3774 else if (XmToggleButtonGetState(LMDialog.smartIndentW))
3775 lm->indentStyle = SMART_INDENT;
3776 else
3777 lm->indentStyle = DEFAULT_INDENT;
3779 /* read wrap style */
3780 if (XmToggleButtonGetState(LMDialog.noWrapW))
3781 lm->wrapStyle = NO_WRAP;
3782 else if (XmToggleButtonGetState(LMDialog.newlineWrapW))
3783 lm->wrapStyle = NEWLINE_WRAP;
3784 else if (XmToggleButtonGetState(LMDialog.contWrapW))
3785 lm->wrapStyle = CONTINUOUS_WRAP;
3786 else
3787 lm->wrapStyle = DEFAULT_WRAP;
3789 return lm;
3793 ** Return True if the language mode dialog fields are blank (unchanged from the "New"
3794 ** language mode state).
3796 static int lmDialogEmpty(void)
3798 return TextWidgetIsBlank(LMDialog.nameW) &&
3799 TextWidgetIsBlank(LMDialog.extW) &&
3800 TextWidgetIsBlank(LMDialog.recogW) &&
3801 TextWidgetIsBlank(LMDialog.delimitW) &&
3802 TextWidgetIsBlank(LMDialog.tabW) &&
3803 TextWidgetIsBlank(LMDialog.emTabW) &&
3804 XmToggleButtonGetState(LMDialog.defaultIndentW) &&
3805 XmToggleButtonGetState(LMDialog.defaultWrapW);
3809 ** Present a dialog for changing fonts (primary, and for highlighting).
3811 void ChooseFonts(WindowInfo *window, int forWindow)
3813 #define MARGIN_SPACING 10
3814 #define BTN_TEXT_OFFSET 3
3815 Widget form, primaryLbl, primaryBtn, italicLbl, italicBtn;
3816 Widget boldLbl, boldBtn, boldItalicLbl, boldItalicBtn;
3817 Widget primaryFrame, primaryForm, highlightFrame, highlightForm;
3818 Widget okBtn, applyBtn, cancelBtn;
3819 fontDialog *fd;
3820 XmString s1;
3821 int ac;
3822 Arg args[20];
3824 /* if the dialog is already displayed, just pop it to the top and return */
3825 if (window->fontDialog != NULL) {
3826 RaiseDialogWindow(((fontDialog *)window->fontDialog)->shell);
3827 return;
3830 /* Create a structure for keeping track of dialog state */
3831 fd = (fontDialog *)XtMalloc(sizeof(fontDialog));
3832 fd->window = window;
3833 fd->forWindow = forWindow;
3834 window->fontDialog = (void*)fd;
3836 /* Create a form widget in a dialog shell */
3837 ac = 0;
3838 XtSetArg(args[ac], XmNautoUnmanage, False); ac++;
3839 XtSetArg(args[ac], XmNresizePolicy, XmRESIZE_NONE); ac++;
3840 form = CreateFormDialog(window->shell, "choose Fonts", args, ac);
3841 XtVaSetValues(form, XmNshadowThickness, 0, NULL);
3842 fd->shell = XtParent(form);
3843 XtVaSetValues(fd->shell, XmNtitle, "Text Fonts", NULL);
3844 AddMotifCloseCallback(XtParent(form), fontCancelCB, fd);
3845 XtAddCallback(form, XmNdestroyCallback, fontDestroyCB, fd);
3847 primaryFrame = XtVaCreateManagedWidget("primaryFrame", xmFrameWidgetClass,
3848 form, XmNmarginHeight, 3,
3849 XmNtopAttachment, XmATTACH_POSITION,
3850 XmNtopPosition, 2,
3851 XmNleftAttachment, XmATTACH_POSITION,
3852 XmNleftPosition, 1,
3853 XmNrightAttachment, XmATTACH_POSITION,
3854 XmNrightPosition, 99, NULL);
3855 primaryForm = XtVaCreateManagedWidget("primaryForm", xmFormWidgetClass,
3856 primaryFrame, NULL);
3857 primaryLbl = XtVaCreateManagedWidget("primaryFont", xmLabelGadgetClass,
3858 primaryFrame,
3859 XmNlabelString, s1=XmStringCreateSimple("Primary Font"),
3860 XmNmnemonic, 'P',
3861 XmNchildType, XmFRAME_TITLE_CHILD,
3862 XmNchildHorizontalAlignment, XmALIGNMENT_CENTER, NULL);
3863 XmStringFree(s1);
3865 primaryBtn = XtVaCreateManagedWidget("primaryBtn",
3866 xmPushButtonWidgetClass, primaryForm,
3867 XmNlabelString, s1=XmStringCreateSimple("Browse..."),
3868 XmNmnemonic, 'r',
3869 XmNtopAttachment, XmATTACH_POSITION,
3870 XmNtopPosition, 2,
3871 XmNtopOffset, BTN_TEXT_OFFSET,
3872 XmNleftAttachment, XmATTACH_POSITION,
3873 XmNleftPosition, 1, NULL);
3874 XmStringFree(s1);
3875 XtAddCallback(primaryBtn, XmNactivateCallback, primaryBrowseCB, fd);
3877 fd->primaryW = XtVaCreateManagedWidget("primary", xmTextWidgetClass,
3878 primaryForm,
3879 XmNcolumns, 70,
3880 XmNmaxLength, MAX_FONT_LEN,
3881 XmNleftAttachment, XmATTACH_WIDGET,
3882 XmNleftWidget, primaryBtn,
3883 XmNtopAttachment, XmATTACH_POSITION,
3884 XmNtopPosition, 2,
3885 XmNrightAttachment, XmATTACH_POSITION,
3886 XmNrightPosition, 99, NULL);
3887 RemapDeleteKey(fd->primaryW);
3888 XtAddCallback(fd->primaryW, XmNvalueChangedCallback,
3889 primaryModifiedCB, fd);
3890 XtVaSetValues(primaryLbl, XmNuserData, fd->primaryW, NULL);
3892 highlightFrame = XtVaCreateManagedWidget("highlightFrame",
3893 xmFrameWidgetClass, form,
3894 XmNmarginHeight, 3,
3895 XmNnavigationType, XmTAB_GROUP,
3896 XmNtopAttachment, XmATTACH_WIDGET,
3897 XmNtopWidget, primaryFrame,
3898 XmNtopOffset, 20,
3899 XmNleftAttachment, XmATTACH_POSITION,
3900 XmNleftPosition, 1,
3901 XmNrightAttachment, XmATTACH_POSITION,
3902 XmNrightPosition, 99, NULL);
3903 highlightForm = XtVaCreateManagedWidget("highlightForm", xmFormWidgetClass,
3904 highlightFrame, NULL);
3905 XtVaCreateManagedWidget("highlightFonts", xmLabelGadgetClass,
3906 highlightFrame,
3907 XmNlabelString,
3908 s1=XmStringCreateSimple("Fonts for Syntax Highlighting"),
3909 XmNchildType, XmFRAME_TITLE_CHILD,
3910 XmNchildHorizontalAlignment, XmALIGNMENT_CENTER, NULL);
3911 XmStringFree(s1);
3913 fd->fillW = XtVaCreateManagedWidget("fillBtn",
3914 xmPushButtonWidgetClass, highlightForm,
3915 XmNlabelString,
3916 s1=XmStringCreateSimple("Fill Highlight Fonts from Primary"),
3917 XmNmnemonic, 'F',
3918 XmNtopAttachment, XmATTACH_POSITION,
3919 XmNtopPosition, 2,
3920 XmNtopOffset, BTN_TEXT_OFFSET,
3921 XmNleftAttachment, XmATTACH_POSITION,
3922 XmNleftPosition, 1, NULL);
3923 XmStringFree(s1);
3924 XtAddCallback(fd->fillW, XmNactivateCallback, fillFromPrimaryCB, fd);
3926 italicLbl = XtVaCreateManagedWidget("italicLbl", xmLabelGadgetClass,
3927 highlightForm,
3928 XmNlabelString, s1=XmStringCreateSimple("Italic Font"),
3929 XmNmnemonic, 'I',
3930 XmNalignment, XmALIGNMENT_BEGINNING,
3931 XmNtopAttachment, XmATTACH_WIDGET,
3932 XmNtopWidget, fd->fillW,
3933 XmNtopOffset, MARGIN_SPACING,
3934 XmNleftAttachment, XmATTACH_POSITION,
3935 XmNleftPosition, 1, NULL);
3936 XmStringFree(s1);
3938 fd->italicErrW = XtVaCreateManagedWidget("italicErrLbl",
3939 xmLabelGadgetClass, highlightForm,
3940 XmNlabelString, s1=XmStringCreateSimple(
3941 "(vvv spacing is inconsistent with primary font vvv)"),
3942 XmNalignment, XmALIGNMENT_END,
3943 XmNtopAttachment, XmATTACH_WIDGET,
3944 XmNtopWidget, fd->fillW,
3945 XmNtopOffset, MARGIN_SPACING,
3946 XmNleftAttachment, XmATTACH_WIDGET,
3947 XmNleftWidget, italicLbl,
3948 XmNrightAttachment, XmATTACH_POSITION,
3949 XmNrightPosition, 99, NULL);
3950 XmStringFree(s1);
3952 italicBtn = XtVaCreateManagedWidget("italicBtn",
3953 xmPushButtonWidgetClass, highlightForm,
3954 XmNlabelString, s1=XmStringCreateSimple("Browse..."),
3955 XmNmnemonic, 'o',
3956 XmNtopAttachment, XmATTACH_WIDGET,
3957 XmNtopWidget, italicLbl,
3958 XmNtopOffset, BTN_TEXT_OFFSET,
3959 XmNleftAttachment, XmATTACH_POSITION,
3960 XmNleftPosition, 1, NULL);
3961 XmStringFree(s1);
3962 XtAddCallback(italicBtn, XmNactivateCallback, italicBrowseCB, fd);
3964 fd->italicW = XtVaCreateManagedWidget("italic", xmTextWidgetClass,
3965 highlightForm,
3966 XmNmaxLength, MAX_FONT_LEN,
3967 XmNleftAttachment, XmATTACH_WIDGET,
3968 XmNleftWidget, italicBtn,
3969 XmNtopAttachment, XmATTACH_WIDGET,
3970 XmNtopWidget, italicLbl,
3971 XmNrightAttachment, XmATTACH_POSITION,
3972 XmNrightPosition, 99, NULL);
3973 RemapDeleteKey(fd->italicW);
3974 XtAddCallback(fd->italicW, XmNvalueChangedCallback,
3975 italicModifiedCB, fd);
3976 XtVaSetValues(italicLbl, XmNuserData, fd->italicW, NULL);
3978 boldLbl = XtVaCreateManagedWidget("boldLbl", xmLabelGadgetClass,
3979 highlightForm,
3980 XmNlabelString, s1=XmStringCreateSimple("Bold Font"),
3981 XmNmnemonic, 'B',
3982 XmNalignment, XmALIGNMENT_BEGINNING,
3983 XmNtopAttachment, XmATTACH_WIDGET,
3984 XmNtopWidget, italicBtn,
3985 XmNtopOffset, MARGIN_SPACING,
3986 XmNleftAttachment, XmATTACH_POSITION,
3987 XmNleftPosition, 1, NULL);
3988 XmStringFree(s1);
3990 fd->boldErrW = XtVaCreateManagedWidget("boldErrLbl",
3991 xmLabelGadgetClass, highlightForm,
3992 XmNlabelString, s1=XmStringCreateSimple(""),
3993 XmNalignment, XmALIGNMENT_END,
3994 XmNtopAttachment, XmATTACH_WIDGET,
3995 XmNtopWidget, italicBtn,
3996 XmNtopOffset, MARGIN_SPACING,
3997 XmNleftAttachment, XmATTACH_WIDGET,
3998 XmNleftWidget, boldLbl,
3999 XmNrightAttachment, XmATTACH_POSITION,
4000 XmNrightPosition, 99, NULL);
4001 XmStringFree(s1);
4003 boldBtn = XtVaCreateManagedWidget("boldBtn",
4004 xmPushButtonWidgetClass, highlightForm,
4005 XmNlabelString, s1=XmStringCreateSimple("Browse..."),
4006 XmNmnemonic, 'w',
4007 XmNtopAttachment, XmATTACH_WIDGET,
4008 XmNtopWidget, boldLbl,
4009 XmNtopOffset, BTN_TEXT_OFFSET,
4010 XmNleftAttachment, XmATTACH_POSITION,
4011 XmNleftPosition, 1, NULL);
4012 XmStringFree(s1);
4013 XtAddCallback(boldBtn, XmNactivateCallback, boldBrowseCB, fd);
4015 fd->boldW = XtVaCreateManagedWidget("bold", xmTextWidgetClass,
4016 highlightForm,
4017 XmNmaxLength, MAX_FONT_LEN,
4018 XmNleftAttachment, XmATTACH_WIDGET,
4019 XmNleftWidget, boldBtn,
4020 XmNtopAttachment, XmATTACH_WIDGET,
4021 XmNtopWidget, boldLbl,
4022 XmNrightAttachment, XmATTACH_POSITION,
4023 XmNrightPosition, 99, NULL);
4024 RemapDeleteKey(fd->boldW);
4025 XtAddCallback(fd->boldW, XmNvalueChangedCallback,
4026 boldModifiedCB, fd);
4027 XtVaSetValues(boldLbl, XmNuserData, fd->boldW, NULL);
4029 boldItalicLbl = XtVaCreateManagedWidget("boldItalicLbl", xmLabelGadgetClass,
4030 highlightForm,
4031 XmNlabelString, s1=XmStringCreateSimple("Bold Italic Font"),
4032 XmNmnemonic, 'l',
4033 XmNalignment, XmALIGNMENT_BEGINNING,
4034 XmNtopAttachment, XmATTACH_WIDGET,
4035 XmNtopWidget, boldBtn,
4036 XmNtopOffset, MARGIN_SPACING,
4037 XmNleftAttachment, XmATTACH_POSITION,
4038 XmNleftPosition, 1, NULL);
4039 XmStringFree(s1);
4041 fd->boldItalicErrW = XtVaCreateManagedWidget("boldItalicErrLbl",
4042 xmLabelGadgetClass, highlightForm,
4043 XmNlabelString, s1=XmStringCreateSimple(""),
4044 XmNalignment, XmALIGNMENT_END,
4045 XmNtopAttachment, XmATTACH_WIDGET,
4046 XmNtopWidget, boldBtn,
4047 XmNtopOffset, MARGIN_SPACING,
4048 XmNleftAttachment, XmATTACH_WIDGET,
4049 XmNleftWidget, boldItalicLbl,
4050 XmNrightAttachment, XmATTACH_POSITION,
4051 XmNrightPosition, 99, NULL);
4052 XmStringFree(s1);
4054 boldItalicBtn = XtVaCreateManagedWidget("boldItalicBtn",
4055 xmPushButtonWidgetClass, highlightForm,
4056 XmNlabelString, s1=XmStringCreateSimple("Browse..."),
4057 XmNmnemonic, 's',
4058 XmNtopAttachment, XmATTACH_WIDGET,
4059 XmNtopWidget, boldItalicLbl,
4060 XmNtopOffset, BTN_TEXT_OFFSET,
4061 XmNleftAttachment, XmATTACH_POSITION,
4062 XmNleftPosition, 1, NULL);
4063 XmStringFree(s1);
4064 XtAddCallback(boldItalicBtn, XmNactivateCallback, boldItalicBrowseCB, fd);
4066 fd->boldItalicW = XtVaCreateManagedWidget("boldItalic",
4067 xmTextWidgetClass, highlightForm,
4068 XmNmaxLength, MAX_FONT_LEN,
4069 XmNleftAttachment, XmATTACH_WIDGET,
4070 XmNleftWidget, boldItalicBtn,
4071 XmNtopAttachment, XmATTACH_WIDGET,
4072 XmNtopWidget, boldItalicLbl,
4073 XmNrightAttachment, XmATTACH_POSITION,
4074 XmNrightPosition, 99, NULL);
4075 RemapDeleteKey(fd->boldItalicW);
4076 XtAddCallback(fd->boldItalicW, XmNvalueChangedCallback,
4077 boldItalicModifiedCB, fd);
4078 XtVaSetValues(boldItalicLbl, XmNuserData, fd->boldItalicW, NULL);
4080 okBtn = XtVaCreateManagedWidget("ok", xmPushButtonWidgetClass, form,
4081 XmNlabelString, s1=XmStringCreateSimple("OK"),
4082 XmNmarginWidth, BUTTON_WIDTH_MARGIN,
4083 XmNtopAttachment, XmATTACH_WIDGET,
4084 XmNtopWidget, highlightFrame,
4085 XmNtopOffset, MARGIN_SPACING,
4086 XmNleftAttachment, XmATTACH_POSITION,
4087 XmNleftPosition, forWindow ? 13 : 26,
4088 XmNrightAttachment, XmATTACH_POSITION,
4089 XmNrightPosition, forWindow ? 27 : 40, NULL);
4090 XtAddCallback(okBtn, XmNactivateCallback, fontOkCB, fd);
4091 XmStringFree(s1);
4093 if (forWindow) {
4094 applyBtn = XtVaCreateManagedWidget("apply",xmPushButtonWidgetClass,form,
4095 XmNlabelString, s1=XmStringCreateSimple("Apply"),
4096 XmNmnemonic, 'A',
4097 XmNtopAttachment, XmATTACH_WIDGET,
4098 XmNtopWidget, highlightFrame,
4099 XmNtopOffset, MARGIN_SPACING,
4100 XmNleftAttachment, XmATTACH_POSITION,
4101 XmNleftPosition, 43,
4102 XmNrightAttachment, XmATTACH_POSITION,
4103 XmNrightPosition, 57, NULL);
4104 XtAddCallback(applyBtn, XmNactivateCallback, fontApplyCB, fd);
4105 XmStringFree(s1);
4108 cancelBtn = XtVaCreateManagedWidget("cancel",
4109 xmPushButtonWidgetClass, form,
4110 XmNlabelString,
4111 s1 = XmStringCreateSimple(forWindow ? "Close" : "Cancel"),
4112 XmNtopAttachment, XmATTACH_WIDGET,
4113 XmNtopWidget, highlightFrame,
4114 XmNtopOffset, MARGIN_SPACING,
4115 XmNleftAttachment, XmATTACH_POSITION,
4116 XmNleftPosition, forWindow ? 73 : 59,
4117 XmNrightAttachment, XmATTACH_POSITION,
4118 XmNrightPosition, forWindow ? 87 : 73,
4119 NULL);
4120 XtAddCallback(cancelBtn, XmNactivateCallback, fontCancelCB, fd);
4121 XmStringFree(s1);
4123 /* Set initial default button */
4124 XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
4125 XtVaSetValues(form, XmNcancelButton, cancelBtn, NULL);
4127 /* Set initial values */
4128 if (forWindow) {
4129 XmTextSetString(fd->primaryW, window->fontName);
4130 XmTextSetString(fd->boldW, window->boldFontName);
4131 XmTextSetString(fd->italicW, window->italicFontName);
4132 XmTextSetString(fd->boldItalicW, window->boldItalicFontName);
4133 } else {
4134 XmTextSetString(fd->primaryW, GetPrefFontName());
4135 XmTextSetString(fd->boldW, GetPrefBoldFontName());
4136 XmTextSetString(fd->italicW, GetPrefItalicFontName());
4137 XmTextSetString(fd->boldItalicW, GetPrefBoldItalicFontName());
4140 /* Handle mnemonic selection of buttons and focus to dialog */
4141 AddDialogMnemonicHandler(form, FALSE);
4143 /* put up dialog */
4144 ManageDialogCenteredOnPointer(form);
4147 static void fillFromPrimaryCB(Widget w, XtPointer clientData,
4148 XtPointer callData)
4150 fontDialog *fd = (fontDialog *)clientData;
4151 char *primaryName, *errMsg;
4152 char modifiedFontName[MAX_FONT_LEN];
4153 char *searchString = "(-[^-]*-[^-]*)-([^-]*)-([^-]*)-(.*)";
4154 char *italicReplaceString = "\\1-\\2-o-\\4";
4155 char *boldReplaceString = "\\1-bold-\\3-\\4";
4156 char *boldItalicReplaceString = "\\1-bold-o-\\4";
4157 regexp *compiledRE;
4159 /* Match the primary font agains RE pattern for font names. If it
4160 doesn't match, we can't generate highlight font names, so return */
4161 compiledRE = CompileRE(searchString, &errMsg, REDFLT_STANDARD);
4162 primaryName = XmTextGetString(fd->primaryW);
4163 if (!ExecRE(compiledRE, primaryName, NULL, False, '\0', '\0', NULL, NULL, NULL)) {
4164 XBell(XtDisplay(fd->shell), 0);
4165 free(compiledRE);
4166 XtFree(primaryName);
4167 return;
4170 /* Make up names for new fonts based on RE replace patterns */
4171 SubstituteRE(compiledRE, italicReplaceString, modifiedFontName,
4172 MAX_FONT_LEN);
4173 XmTextSetString(fd->italicW, modifiedFontName);
4174 SubstituteRE(compiledRE, boldReplaceString, modifiedFontName,
4175 MAX_FONT_LEN);
4176 XmTextSetString(fd->boldW, modifiedFontName);
4177 SubstituteRE(compiledRE, boldItalicReplaceString, modifiedFontName,
4178 MAX_FONT_LEN);
4179 XmTextSetString(fd->boldItalicW, modifiedFontName);
4180 XtFree(primaryName);
4181 free(compiledRE);
4184 static void primaryModifiedCB(Widget w, XtPointer clientData,
4185 XtPointer callData)
4187 fontDialog *fd = (fontDialog *)clientData;
4189 showFontStatus(fd, fd->italicW, fd->italicErrW);
4190 showFontStatus(fd, fd->boldW, fd->boldErrW);
4191 showFontStatus(fd, fd->boldItalicW, fd->boldItalicErrW);
4193 static void italicModifiedCB(Widget w, XtPointer clientData, XtPointer callData)
4195 fontDialog *fd = (fontDialog *)clientData;
4197 showFontStatus(fd, fd->italicW, fd->italicErrW);
4199 static void boldModifiedCB(Widget w, XtPointer clientData, XtPointer callData)
4201 fontDialog *fd = (fontDialog *)clientData;
4203 showFontStatus(fd, fd->boldW, fd->boldErrW);
4205 static void boldItalicModifiedCB(Widget w, XtPointer clientData,
4206 XtPointer callData)
4208 fontDialog *fd = (fontDialog *)clientData;
4210 showFontStatus(fd, fd->boldItalicW, fd->boldItalicErrW);
4213 static void primaryBrowseCB(Widget w, XtPointer clientData, XtPointer callData)
4215 fontDialog *fd = (fontDialog *)clientData;
4217 browseFont(fd->shell, fd->primaryW);
4219 static void italicBrowseCB(Widget w, XtPointer clientData, XtPointer callData)
4221 fontDialog *fd = (fontDialog *)clientData;
4223 browseFont(fd->shell, fd->italicW);
4225 static void boldBrowseCB(Widget w, XtPointer clientData, XtPointer callData)
4227 fontDialog *fd = (fontDialog *)clientData;
4229 browseFont(fd->shell, fd->boldW);
4231 static void boldItalicBrowseCB(Widget w, XtPointer clientData,
4232 XtPointer callData)
4234 fontDialog *fd = (fontDialog *)clientData;
4236 browseFont(fd->shell, fd->boldItalicW);
4239 static void fontDestroyCB(Widget w, XtPointer clientData, XtPointer callData)
4241 fontDialog *fd = (fontDialog *)clientData;
4243 fd->window->fontDialog = NULL;
4244 XtFree((char *)fd);
4247 static void fontOkCB(Widget w, XtPointer clientData, XtPointer callData)
4249 fontDialog *fd = (fontDialog *)clientData;
4251 updateFonts(fd);
4253 /* pop down and destroy the dialog */
4254 XtDestroyWidget(fd->shell);
4257 static void fontApplyCB(Widget w, XtPointer clientData, XtPointer callData)
4259 fontDialog *fd = (fontDialog *)clientData;
4261 updateFonts(fd);
4264 static void fontCancelCB(Widget w, XtPointer clientData, XtPointer callData)
4266 fontDialog *fd = (fontDialog *)clientData;
4268 /* pop down and destroy the dialog */
4269 XtDestroyWidget(fd->shell);
4273 ** Check over a font name in a text field to make sure it agrees with the
4274 ** primary font in height and spacing.
4276 static int checkFontStatus(fontDialog *fd, Widget fontTextFieldW)
4278 char *primaryName, *testName;
4279 XFontStruct *primaryFont, *testFont;
4280 Display *display = XtDisplay(fontTextFieldW);
4281 int primaryWidth, primaryHeight, testWidth, testHeight;
4283 /* Get width and height of the font to check. Note the test for empty
4284 name: X11R6 clients freak out X11R5 servers if they ask them to load
4285 an empty font name, and kill the whole application! */
4286 testName = XmTextGetString(fontTextFieldW);
4287 if (testName[0] == '\0') {
4288 XtFree(testName);
4289 return BAD_FONT;
4291 testFont = XLoadQueryFont(display, testName);
4292 if (testFont == NULL) {
4293 XtFree(testName);
4294 return BAD_FONT;
4296 XtFree(testName);
4297 testWidth = testFont->min_bounds.width;
4298 testHeight = testFont->ascent + testFont->descent;
4299 XFreeFont(display, testFont);
4301 /* Get width and height of the primary font */
4302 primaryName = XmTextGetString(fd->primaryW);
4303 if (primaryName[0] == '\0') {
4304 XtFree(primaryName);
4305 return BAD_FONT;
4307 primaryFont = XLoadQueryFont(display, primaryName);
4308 if (primaryFont == NULL) {
4309 XtFree(primaryName);
4310 return BAD_PRIMARY;
4312 XtFree(primaryName);
4313 primaryWidth = primaryFont->min_bounds.width;
4314 primaryHeight = primaryFont->ascent + primaryFont->descent;
4315 XFreeFont(display, primaryFont);
4317 /* Compare font information */
4318 if (testWidth != primaryWidth)
4319 return BAD_SPACING;
4320 if (testHeight != primaryHeight)
4321 return BAD_SIZE;
4322 return GOOD_FONT;
4326 ** Update the error label for a font text field to reflect its validity and degree
4327 ** of agreement with the currently selected primary font
4329 static int showFontStatus(fontDialog *fd, Widget fontTextFieldW,
4330 Widget errorLabelW)
4332 int status;
4333 XmString s;
4334 char *msg;
4336 status = checkFontStatus(fd, fontTextFieldW);
4337 if (status == BAD_PRIMARY)
4338 msg = "(font below may not match primary font)";
4339 else if (status == BAD_FONT)
4340 msg = "(xxx font below is invalid xxx)";
4341 else if (status == BAD_SIZE)
4342 msg = "(height of font below does not match primary)";
4343 else if (status == BAD_SPACING)
4344 msg = "(spacing of font below does not match primary)";
4345 else
4346 msg = "";
4348 XtVaSetValues(errorLabelW, XmNlabelString, s=XmStringCreateSimple(msg),
4349 NULL);
4350 XmStringFree(s);
4351 return status;
4355 ** Put up a font selector panel to set the font name in the text widget "fontTextW"
4357 static void browseFont(Widget parent, Widget fontTextW)
4359 char *origFontName, *newFontName;
4360 Pixel fgPixel, bgPixel;
4361 int dummy;
4363 origFontName = XmTextGetString(fontTextW);
4365 /* Get the values from the defaults */
4366 fgPixel = AllocColor(parent, GetPrefColorName(TEXT_FG_COLOR),
4367 &dummy, &dummy, &dummy);
4368 bgPixel = AllocColor(parent, GetPrefColorName(TEXT_BG_COLOR),
4369 &dummy, &dummy, &dummy);
4371 newFontName = FontSel(parent, PREF_FIXED, origFontName, fgPixel, bgPixel);
4372 XtFree(origFontName);
4373 if (newFontName == NULL)
4374 return;
4375 XmTextSetString(fontTextW, newFontName);
4376 XtFree(newFontName);
4380 ** Accept the changes in the dialog and set the fonts regardless of errors
4382 static void updateFonts(fontDialog *fd)
4384 char *fontName, *italicName, *boldName, *boldItalicName;
4386 fontName = XmTextGetString(fd->primaryW);
4387 italicName = XmTextGetString(fd->italicW);
4388 boldName = XmTextGetString(fd->boldW);
4389 boldItalicName = XmTextGetString(fd->boldItalicW);
4391 if (fd->forWindow) {
4392 char *params[4];
4393 params[0] = fontName;
4394 params[1] = italicName;
4395 params[2] = boldName;
4396 params[3] = boldItalicName;
4397 XtCallActionProc(fd->window->textArea, "set_fonts", NULL, params, 4);
4399 SetFonts(fd->window, fontName, italicName, boldName, boldItalicName);
4402 else {
4403 SetPrefFont(fontName);
4404 SetPrefItalicFont(italicName);
4405 SetPrefBoldFont(boldName);
4406 SetPrefBoldItalicFont(boldItalicName);
4408 XtFree(fontName);
4409 XtFree(italicName);
4410 XtFree(boldName);
4411 XtFree(boldItalicName);
4415 ** Change the language mode to the one indexed by "mode", reseting word
4416 ** delimiters, syntax highlighting and other mode specific parameters
4418 static void reapplyLanguageMode(WindowInfo *window, int mode, int forceDefaults)
4420 char *delimiters;
4421 int i, wrapMode, indentStyle, tabDist, emTabDist, highlight, oldEmTabDist;
4422 int wrapModeIsDef, tabDistIsDef, emTabDistIsDef, indentStyleIsDef;
4423 int highlightIsDef, haveHighlightPatterns, haveSmartIndentMacros;
4424 int oldMode = window->languageMode;
4426 /* If the mode is the same, and changes aren't being forced (as might
4427 happen with Save As...), don't mess with already correct settings */
4428 if (window->languageMode == mode && !forceDefaults)
4429 return;
4431 /* Change the mode name stored in the window */
4432 window->languageMode = mode;
4434 /* Decref oldMode's default calltips file if needed */
4435 if (oldMode != PLAIN_LANGUAGE_MODE && LanguageModes[oldMode]->defTipsFile) {
4436 DeleteTagsFile( LanguageModes[oldMode]->defTipsFile, TIP, False );
4439 /* Set delimiters for all text widgets */
4440 if (mode == PLAIN_LANGUAGE_MODE || LanguageModes[mode]->delimiters == NULL)
4441 delimiters = GetPrefDelimiters();
4442 else
4443 delimiters = LanguageModes[mode]->delimiters;
4444 XtVaSetValues(window->textArea, textNwordDelimiters, delimiters, NULL);
4445 for (i=0; i<window->nPanes; i++)
4446 XtVaSetValues(window->textPanes[i], textNautoIndent, delimiters, NULL);
4448 /* Decide on desired values for language-specific parameters. If a
4449 parameter was set to its default value, set it to the new default,
4450 otherwise, leave it alone */
4451 wrapModeIsDef = window->wrapMode == GetPrefWrap(oldMode);
4452 tabDistIsDef = BufGetTabDistance(window->buffer) == GetPrefTabDist(oldMode);
4453 XtVaGetValues(window->textArea, textNemulateTabs, &oldEmTabDist, NULL);
4454 emTabDistIsDef = oldEmTabDist == GetPrefEmTabDist(oldMode);
4455 indentStyleIsDef = window->indentStyle == GetPrefAutoIndent(oldMode) ||
4456 (GetPrefAutoIndent(oldMode) == SMART_INDENT &&
4457 window->indentStyle == AUTO_INDENT &&
4458 !SmartIndentMacrosAvailable(LanguageModeName(oldMode)));
4459 highlightIsDef = window->highlightSyntax == GetPrefHighlightSyntax()
4460 || (GetPrefHighlightSyntax() &&
4461 FindPatternSet(LanguageModeName(oldMode)) == NULL);
4462 wrapMode = wrapModeIsDef || forceDefaults ?
4463 GetPrefWrap(mode) : window->wrapMode;
4464 tabDist = tabDistIsDef || forceDefaults ?
4465 GetPrefTabDist(mode) : BufGetTabDistance(window->buffer);
4466 emTabDist = emTabDistIsDef || forceDefaults ?
4467 GetPrefEmTabDist(mode) : oldEmTabDist;
4468 indentStyle = indentStyleIsDef || forceDefaults ?
4469 GetPrefAutoIndent(mode) : window->indentStyle;
4470 highlight = highlightIsDef || forceDefaults ?
4471 GetPrefHighlightSyntax() : window->highlightSyntax;
4473 /* Dim/undim smart-indent and highlighting menu items depending on
4474 whether patterns/macros are available */
4475 haveHighlightPatterns = FindPatternSet(LanguageModeName(mode)) != NULL;
4476 haveSmartIndentMacros = SmartIndentMacrosAvailable(LanguageModeName(mode));
4477 if (IsTopDocument(window)) {
4478 XtSetSensitive(window->highlightItem, haveHighlightPatterns);
4479 XtSetSensitive(window->smartIndentItem, haveSmartIndentMacros);
4482 /* Turn off requested options which are not available */
4483 highlight = haveHighlightPatterns && highlight;
4484 if (indentStyle == SMART_INDENT && !haveSmartIndentMacros)
4485 indentStyle = AUTO_INDENT;
4487 /* Change highlighting */
4488 window->highlightSyntax = highlight;
4489 SetToggleButtonState(window, window->highlightItem, highlight, False);
4490 StopHighlighting(window);
4492 /* we defer highlighting to RaiseDocument() if doc is hidden */
4493 if (IsTopDocument(window) && highlight)
4494 StartHighlighting(window, False);
4496 /* Force a change of smart indent macros (SetAutoIndent will re-start) */
4497 if (window->indentStyle == SMART_INDENT) {
4498 EndSmartIndent(window);
4499 window->indentStyle = AUTO_INDENT;
4502 /* set requested wrap, indent, and tabs */
4503 SetAutoWrap(window, wrapMode);
4504 SetAutoIndent(window, indentStyle);
4505 SetTabDist(window, tabDist);
4506 SetEmTabDist(window, emTabDist);
4508 /* Load calltips files for new mode */
4509 if (mode != PLAIN_LANGUAGE_MODE && LanguageModes[mode]->defTipsFile) {
4510 AddTagsFile( LanguageModes[mode]->defTipsFile, TIP );
4513 /* Add/remove language specific menu items */
4514 UpdateUserMenus(window);
4518 ** Find and return the name of the appropriate languange mode for
4519 ** the file in "window". Returns a pointer to a string, which will
4520 ** remain valid until a change is made to the language modes list.
4522 static int matchLanguageMode(WindowInfo *window)
4524 char *ext, *first200;
4525 int i, j, fileNameLen, extLen, beginPos, endPos, start;
4526 const char *versionExtendedPath;
4528 /*... look for an explicit mode statement first */
4530 /* Do a regular expression search on for recognition pattern */
4531 first200 = BufGetRange(window->buffer, 0, 200);
4532 for (i=0; i<NLanguageModes; i++) {
4533 if (LanguageModes[i]->recognitionExpr != NULL) {
4534 if (SearchString(first200, LanguageModes[i]->recognitionExpr,
4535 SEARCH_FORWARD, SEARCH_REGEX, False, 0, &beginPos,
4536 &endPos, NULL, NULL, NULL))
4538 XtFree(first200);
4539 return i;
4543 XtFree(first200);
4545 /* Look at file extension ("@@/" starts a ClearCase version extended path,
4546 which gets appended after the file extension, and therefore must be
4547 stripped off to recognize the extension to make ClearCase users happy) */
4548 fileNameLen = strlen(window->filename);
4549 #ifdef VMS
4550 if (strchr(window->filename, ';') != NULL)
4551 fileNameLen = strchr(window->filename, ';') - window->filename;
4552 #else
4553 if ((versionExtendedPath = GetClearCaseVersionExtendedPath(window->filename)) != NULL)
4554 fileNameLen = versionExtendedPath - window->filename;
4555 #endif
4556 for (i=0; i<NLanguageModes; i++) {
4557 for (j=0; j<LanguageModes[i]->nExtensions; j++) {
4558 ext = LanguageModes[i]->extensions[j];
4559 extLen = strlen(ext);
4560 start = fileNameLen - extLen;
4561 #if defined(__VMS) && (__VMS_VER >= 70200000)
4562 /* VMS v7.2 has case-preserving filenames */
4563 if (start >= 0 && !strncasecmp(&window->filename[start], ext, extLen))
4564 return i;
4565 #else
4566 if (start >= 0 && !strncmp(&window->filename[start], ext, extLen))
4567 return i;
4568 #endif
4572 /* no appropriate mode was found */
4573 return PLAIN_LANGUAGE_MODE;
4576 static int loadLanguageModesString(char *inString, int fileVer)
4578 char *errMsg, *styleName, *inPtr = inString;
4579 languageModeRec *lm;
4580 int i;
4582 for (;;) {
4584 /* skip over blank space */
4585 inPtr += strspn(inPtr, " \t\n");
4587 /* Allocate a language mode structure to return, set unread fields to
4588 empty so everything can be freed on errors by freeLanguageModeRec */
4589 lm = (languageModeRec *)XtMalloc(sizeof(languageModeRec));
4590 lm->nExtensions = 0;
4591 lm->recognitionExpr = NULL;
4592 lm->defTipsFile = NULL;
4593 lm->delimiters = NULL;
4595 /* read language mode name */
4596 lm->name = ReadSymbolicField(&inPtr);
4597 if (lm->name == NULL) {
4598 XtFree((char *)lm);
4599 return modeError(NULL,inString,inPtr,"language mode name required");
4601 if (!SkipDelimiter(&inPtr, &errMsg))
4602 return modeError(lm, inString, inPtr, errMsg);
4604 /* read list of extensions */
4605 lm->extensions = readExtensionList(&inPtr,
4606 &lm->nExtensions);
4607 if (!SkipDelimiter(&inPtr, &errMsg))
4608 return modeError(lm, inString, inPtr, errMsg);
4610 /* read the recognition regular expression */
4611 if (*inPtr == '\n' || *inPtr == '\0' || *inPtr == ':')
4612 lm->recognitionExpr = NULL;
4613 else if (!ReadQuotedString(&inPtr, &errMsg, &lm->recognitionExpr))
4614 return modeError(lm, inString,inPtr, errMsg);
4615 if (!SkipDelimiter(&inPtr, &errMsg))
4616 return modeError(lm, inString, inPtr, errMsg);
4618 /* read the indent style */
4619 styleName = ReadSymbolicField(&inPtr);
4620 if (styleName == NULL)
4621 lm->indentStyle = DEFAULT_INDENT;
4622 else {
4623 for (i=0; i<N_INDENT_STYLES; i++) {
4624 if (!strcmp(styleName, AutoIndentTypes[i])) {
4625 lm->indentStyle = i;
4626 break;
4629 XtFree(styleName);
4630 if (i == N_INDENT_STYLES)
4631 return modeError(lm,inString,inPtr,"unrecognized indent style");
4633 if (!SkipDelimiter(&inPtr, &errMsg))
4634 return modeError(lm, inString, inPtr, errMsg);
4636 /* read the wrap style */
4637 styleName = ReadSymbolicField(&inPtr);
4638 if (styleName == NULL)
4639 lm->wrapStyle = DEFAULT_WRAP;
4640 else {
4641 for (i=0; i<N_WRAP_STYLES; i++) {
4642 if (!strcmp(styleName, AutoWrapTypes[i])) {
4643 lm->wrapStyle = i;
4644 break;
4647 XtFree(styleName);
4648 if (i == N_WRAP_STYLES)
4649 return modeError(lm, inString, inPtr,"unrecognized wrap style");
4651 if (!SkipDelimiter(&inPtr, &errMsg))
4652 return modeError(lm, inString, inPtr, errMsg);
4654 /* read the tab distance */
4655 if (*inPtr == '\n' || *inPtr == '\0' || *inPtr == ':')
4656 lm->tabDist = DEFAULT_TAB_DIST;
4657 else if (!ReadNumericField(&inPtr, &lm->tabDist))
4658 return modeError(lm, inString, inPtr, "bad tab spacing");
4659 if (!SkipDelimiter(&inPtr, &errMsg))
4660 return modeError(lm, inString, inPtr, errMsg);
4662 /* read emulated tab distance */
4663 if (*inPtr == '\n' || *inPtr == '\0' || *inPtr == ':')
4664 lm->emTabDist = DEFAULT_EM_TAB_DIST;
4665 else if (!ReadNumericField(&inPtr, &lm->emTabDist))
4666 return modeError(lm, inString, inPtr, "bad emulated tab spacing");
4667 if (!SkipDelimiter(&inPtr, &errMsg))
4668 return modeError(lm, inString, inPtr, errMsg);
4670 /* read the delimiters string */
4671 if (*inPtr == '\n' || *inPtr == '\0' || *inPtr == ':')
4672 lm->delimiters = NULL;
4673 else if (!ReadQuotedString(&inPtr, &errMsg, &lm->delimiters))
4674 return modeError(lm, inString, inPtr, errMsg);
4676 /* After 5.3 all language modes need a default tips file field */
4677 if (!SkipDelimiter(&inPtr, &errMsg))
4678 if (fileVer > 5003)
4679 return modeError(lm, inString, inPtr, errMsg);
4681 /* read the default tips file */
4682 if (*inPtr == '\n' || *inPtr == '\0')
4683 lm->defTipsFile = NULL;
4684 else if (!ReadQuotedString(&inPtr, &errMsg, &lm->defTipsFile))
4685 return modeError(lm, inString, inPtr, errMsg);
4687 /* pattern set was read correctly, add/replace it in the list */
4688 for (i=0; i<NLanguageModes; i++) {
4689 if (!strcmp(LanguageModes[i]->name, lm->name)) {
4690 freeLanguageModeRec(LanguageModes[i]);
4691 LanguageModes[i] = lm;
4692 break;
4695 if (i == NLanguageModes) {
4696 LanguageModes[NLanguageModes++] = lm;
4697 if (NLanguageModes > MAX_LANGUAGE_MODES)
4698 return modeError(NULL, inString, inPtr,
4699 "maximum allowable number of language modes exceeded");
4702 /* if the string ends here, we're done */
4703 inPtr += strspn(inPtr, " \t\n");
4704 if (*inPtr == '\0')
4705 return True;
4706 } /* End for(;;) */
4709 static char *writeLanguageModesString(void)
4711 int i;
4712 char *outStr, *escapedStr, *str, numBuf[25];
4713 textBuffer *outBuf;
4715 outBuf = BufCreate();
4716 for (i=0; i<NLanguageModes; i++) {
4717 BufInsert(outBuf, outBuf->length, "\t");
4718 BufInsert(outBuf, outBuf->length, LanguageModes[i]->name);
4719 BufInsert(outBuf, outBuf->length, ":");
4720 BufInsert(outBuf, outBuf->length, str = createExtString(
4721 LanguageModes[i]->extensions, LanguageModes[i]->nExtensions));
4722 XtFree(str);
4723 BufInsert(outBuf, outBuf->length, ":");
4724 if (LanguageModes[i]->recognitionExpr != NULL) {
4725 BufInsert(outBuf, outBuf->length,
4726 str=MakeQuotedString(LanguageModes[i]->recognitionExpr));
4727 XtFree(str);
4729 BufInsert(outBuf, outBuf->length, ":");
4730 if (LanguageModes[i]->indentStyle != DEFAULT_INDENT)
4731 BufInsert(outBuf, outBuf->length,
4732 AutoIndentTypes[LanguageModes[i]->indentStyle]);
4733 BufInsert(outBuf, outBuf->length, ":");
4734 if (LanguageModes[i]->wrapStyle != DEFAULT_WRAP)
4735 BufInsert(outBuf, outBuf->length,
4736 AutoWrapTypes[LanguageModes[i]->wrapStyle]);
4737 BufInsert(outBuf, outBuf->length, ":");
4738 if (LanguageModes[i]->tabDist != DEFAULT_TAB_DIST) {
4739 sprintf(numBuf, "%d", LanguageModes[i]->tabDist);
4740 BufInsert(outBuf, outBuf->length, numBuf);
4742 BufInsert(outBuf, outBuf->length, ":");
4743 if (LanguageModes[i]->emTabDist != DEFAULT_EM_TAB_DIST) {
4744 sprintf(numBuf, "%d", LanguageModes[i]->emTabDist);
4745 BufInsert(outBuf, outBuf->length, numBuf);
4747 BufInsert(outBuf, outBuf->length, ":");
4748 if (LanguageModes[i]->delimiters != NULL) {
4749 BufInsert(outBuf, outBuf->length,
4750 str=MakeQuotedString(LanguageModes[i]->delimiters));
4751 XtFree(str);
4753 BufInsert(outBuf, outBuf->length, ":");
4754 if (LanguageModes[i]->defTipsFile != NULL) {
4755 BufInsert(outBuf, outBuf->length,
4756 str=MakeQuotedString(LanguageModes[i]->defTipsFile));
4757 XtFree(str);
4760 BufInsert(outBuf, outBuf->length, "\n");
4763 /* Get the output, and lop off the trailing newline */
4764 outStr = BufGetRange(outBuf, 0, outBuf->length - 1);
4765 BufFree(outBuf);
4766 escapedStr = EscapeSensitiveChars(outStr);
4767 XtFree(outStr);
4768 return escapedStr;
4771 static char *createExtString(char **extensions, int nExtensions)
4773 int e, length = 1;
4774 char *outStr, *outPtr;
4776 for (e=0; e<nExtensions; e++)
4777 length += strlen(extensions[e]) + 1;
4778 outStr = outPtr = XtMalloc(length);
4779 for (e=0; e<nExtensions; e++) {
4780 strcpy(outPtr, extensions[e]);
4781 outPtr += strlen(extensions[e]);
4782 *outPtr++ = ' ';
4784 if (nExtensions == 0)
4785 *outPtr = '\0';
4786 else
4787 *(outPtr-1) = '\0';
4788 return outStr;
4791 static char **readExtensionList(char **inPtr, int *nExtensions)
4793 char *extensionList[MAX_FILE_EXTENSIONS];
4794 char **retList, *strStart;
4795 int i, len;
4797 /* skip over blank space */
4798 *inPtr += strspn(*inPtr, " \t");
4800 for (i=0; i<MAX_FILE_EXTENSIONS && **inPtr!=':' && **inPtr!='\0'; i++) {
4801 *inPtr += strspn(*inPtr, " \t");
4802 strStart = *inPtr;
4803 while (**inPtr!=' ' && **inPtr!='\t' && **inPtr!=':' && **inPtr!='\0')
4804 (*inPtr)++;
4805 len = *inPtr - strStart;
4806 extensionList[i] = XtMalloc(len + 1);
4807 strncpy(extensionList[i], strStart, len);
4808 extensionList[i][len] = '\0';
4810 *nExtensions = i;
4811 if (i == 0)
4812 return NULL;
4813 retList = (char **)XtMalloc(sizeof(char *) * i);
4814 memcpy(retList, extensionList, sizeof(char *) * i);
4815 return retList;
4818 int ReadNumericField(char **inPtr, int *value)
4820 int charsRead;
4822 /* skip over blank space */
4823 *inPtr += strspn(*inPtr, " \t");
4825 if (sscanf(*inPtr, "%d%n", value, &charsRead) != 1)
4826 return False;
4827 *inPtr += charsRead;
4828 return True;
4832 ** Parse a symbolic field, skipping initial and trailing whitespace,
4833 ** stops on first invalid character or end of string. Valid characters
4834 ** are letters, numbers, _, -, +, $, #, and internal whitespace. Internal
4835 ** whitespace is compressed to single space characters.
4837 char *ReadSymbolicField(char **inPtr)
4839 char *outStr, *outPtr, *strStart, *strPtr;
4840 int len;
4842 /* skip over initial blank space */
4843 *inPtr += strspn(*inPtr, " \t");
4845 /* Find the first invalid character or end of string to know how
4846 much memory to allocate for the returned string */
4847 strStart = *inPtr;
4848 while (isalnum((unsigned char)**inPtr) || **inPtr=='_' || **inPtr=='-' ||
4849 **inPtr=='+' || **inPtr=='$' || **inPtr=='#' || **inPtr==' ' ||
4850 **inPtr=='\t')
4851 (*inPtr)++;
4852 len = *inPtr - strStart;
4853 if (len == 0)
4854 return NULL;
4855 outStr = outPtr = XtMalloc(len + 1);
4857 /* Copy the string, compressing internal whitespace to a single space */
4858 strPtr = strStart;
4859 while (strPtr - strStart < len) {
4860 if (*strPtr == ' ' || *strPtr == '\t') {
4861 strPtr += strspn(strPtr, " \t");
4862 *outPtr++ = ' ';
4863 } else
4864 *outPtr++ = *strPtr++;
4867 /* If there's space on the end, take it back off */
4868 if (outPtr > outStr && *(outPtr-1) == ' ')
4869 outPtr--;
4870 if (outPtr == outStr) {
4871 XtFree(outStr);
4872 return NULL;
4874 *outPtr = '\0';
4875 return outStr;
4879 ** parse an individual quoted string. Anything between
4880 ** double quotes is acceptable, quote characters can be escaped by "".
4881 ** Returns allocated string "string" containing
4882 ** argument minus quotes. If not successful, returns False with
4883 ** (statically allocated) message in "errMsg".
4885 int ReadQuotedString(char **inPtr, char **errMsg, char **string)
4887 char *outPtr, *c;
4889 /* skip over blank space */
4890 *inPtr += strspn(*inPtr, " \t");
4892 /* look for initial quote */
4893 if (**inPtr != '\"') {
4894 *errMsg = "expecting quoted string";
4895 return False;
4897 (*inPtr)++;
4899 /* calculate max length and allocate returned string */
4900 for (c= *inPtr; ; c++) {
4901 if (*c == '\0') {
4902 *errMsg = "string not terminated";
4903 return False;
4904 } else if (*c == '\"') {
4905 if (*(c+1) == '\"')
4906 c++;
4907 else
4908 break;
4912 /* copy string up to end quote, transforming escaped quotes into quotes */
4913 *string = XtMalloc(c - *inPtr + 1);
4914 outPtr = *string;
4915 while (True) {
4916 if (**inPtr == '\"') {
4917 if (*(*inPtr+1) == '\"')
4918 (*inPtr)++;
4919 else
4920 break;
4922 *outPtr++ = *(*inPtr)++;
4924 *outPtr = '\0';
4926 /* skip end quote */
4927 (*inPtr)++;
4928 return True;
4932 ** Replace characters which the X resource file reader considers control
4933 ** characters, such that a string will read back as it appears in "string".
4934 ** (So far, newline characters are replaced with with \n\<newline> and
4935 ** backslashes with \\. This has not been tested exhaustively, and
4936 ** probably should be. It would certainly be more asthetic if other
4937 ** control characters were replaced as well).
4939 ** Returns an allocated string which must be freed by the caller with XtFree.
4941 char *EscapeSensitiveChars(const char *string)
4943 const char *c;
4944 char *outStr, *outPtr;
4945 int length = 0;
4947 /* calculate length and allocate returned string */
4948 for (c=string; *c!='\0'; c++) {
4949 if (*c == '\\')
4950 length++;
4951 else if (*c == '\n')
4952 length += 3;
4953 length++;
4955 outStr = XtMalloc(length + 1);
4956 outPtr = outStr;
4958 /* add backslashes */
4959 for (c=string; *c!='\0'; c++) {
4960 if (*c == '\\')
4961 *outPtr++ = '\\';
4962 else if (*c == '\n') {
4963 *outPtr++ = '\\';
4964 *outPtr++ = 'n';
4965 *outPtr++ = '\\';
4967 *outPtr++ = *c;
4969 *outPtr = '\0';
4970 return outStr;
4974 ** Adds double quotes around a string and escape existing double quote
4975 ** characters with two double quotes. Enables the string to be read back
4976 ** by ReadQuotedString.
4978 char *MakeQuotedString(const char *string)
4980 const char *c;
4981 char *outStr, *outPtr;
4982 int length = 0;
4984 /* calculate length and allocate returned string */
4985 for (c=string; *c!='\0'; c++) {
4986 if (*c == '\"')
4987 length++;
4988 length++;
4990 outStr = XtMalloc(length + 3);
4991 outPtr = outStr;
4993 /* add starting quote */
4994 *outPtr++ = '\"';
4996 /* copy string, escaping quotes with "" */
4997 for (c=string; *c!='\0'; c++) {
4998 if (*c == '\"')
4999 *outPtr++ = '\"';
5000 *outPtr++ = *c;
5003 /* add ending quote */
5004 *outPtr++ = '\"';
5006 /* terminate string and return */
5007 *outPtr = '\0';
5008 return outStr;
5012 ** Read a dialog text field containing a symbolic name (language mode names,
5013 ** style names, highlight pattern names, colors, and fonts), clean the
5014 ** entered text of leading and trailing whitespace, compress all
5015 ** internal whitespace to one space character, and check it over for
5016 ** colons, which interfere with the preferences file reader/writer syntax.
5017 ** Returns NULL on error, and puts up a dialog if silent is False. Returns
5018 ** an empty string if the text field is blank.
5020 char *ReadSymbolicFieldTextWidget(Widget textW, const char *fieldName, int silent)
5022 char *string, *stringPtr, *parsedString;
5024 /* read from the text widget */
5025 string = stringPtr = XmTextGetString(textW);
5027 /* parse it with the same routine used to read symbolic fields from
5028 files. If the string is not read entirely, there are invalid
5029 characters, so warn the user if not in silent mode. */
5030 parsedString = ReadSymbolicField(&stringPtr);
5031 if (*stringPtr != '\0')
5033 if (!silent)
5035 *(stringPtr + 1) = '\0';
5036 DialogF(DF_WARN, textW, 1, "Invalid Character",
5037 "Invalid character \"%s\" in %s", "OK", stringPtr,
5038 fieldName);
5039 XmProcessTraversal(textW, XmTRAVERSE_CURRENT);
5041 XtFree(string);
5042 XtFree(parsedString);
5043 return NULL;
5045 XtFree(string);
5046 if (parsedString == NULL) {
5047 parsedString = XtMalloc(1);
5048 *parsedString = '\0';
5050 return parsedString;
5054 ** Create a pulldown menu pane with the names of the current language modes.
5055 ** XmNuserData for each item contains the language mode name.
5057 Widget CreateLanguageModeMenu(Widget parent, XtCallbackProc cbProc, void *cbArg)
5059 Widget menu, btn;
5060 int i;
5061 XmString s1;
5063 menu = CreatePulldownMenu(parent, "languageModes", NULL, 0);
5064 for (i=0; i<NLanguageModes; i++) {
5065 btn = XtVaCreateManagedWidget("languageMode", xmPushButtonGadgetClass,
5066 menu,
5067 XmNlabelString, s1=XmStringCreateSimple(LanguageModes[i]->name),
5068 XmNmarginHeight, 0,
5069 XmNuserData, (void *)LanguageModes[i]->name, NULL);
5070 XmStringFree(s1);
5071 XtAddCallback(btn, XmNactivateCallback, cbProc, cbArg);
5073 return menu;
5077 ** Set the language mode menu in option menu "optMenu" to
5078 ** show a particular language mode
5080 void SetLangModeMenu(Widget optMenu, const char *modeName)
5082 int i;
5083 Cardinal nItems;
5084 WidgetList items;
5085 Widget pulldown, selectedItem;
5086 char *itemName;
5088 XtVaGetValues(optMenu, XmNsubMenuId, &pulldown, NULL);
5089 XtVaGetValues(pulldown, XmNchildren, &items, XmNnumChildren, &nItems, NULL);
5090 if (nItems == 0)
5091 return;
5092 selectedItem = items[0];
5093 for (i=0; i<(int)nItems; i++) {
5094 XtVaGetValues(items[i], XmNuserData, &itemName, NULL);
5095 if (!strcmp(itemName, modeName)) {
5096 selectedItem = items[i];
5097 break;
5100 XtVaSetValues(optMenu, XmNmenuHistory, selectedItem,NULL);
5104 ** Create a submenu for chosing language mode for the current window.
5106 void CreateLanguageModeSubMenu(WindowInfo* window, const Widget parent,
5107 const char* name, const char* label, const char mnemonic)
5109 XmString string = XmStringCreateSimple((char*) label);
5111 window->langModeCascade = XtVaCreateManagedWidget(name,
5112 xmCascadeButtonGadgetClass, parent,
5113 XmNlabelString, string,
5114 XmNmnemonic, mnemonic,
5115 XmNsubMenuId, NULL,
5116 NULL);
5117 XmStringFree(string);
5119 updateLanguageModeSubmenu(window);
5123 ** Re-build the language mode sub-menu using the current data stored
5124 ** in the master list: LanguageModes.
5126 static void updateLanguageModeSubmenu(WindowInfo *window)
5128 int i;
5129 XmString s1;
5130 Widget menu, btn;
5131 Arg args[1] = {{XmNradioBehavior, (XtArgVal)True}};
5133 /* Destroy and re-create the menu pane */
5134 XtVaGetValues(window->langModeCascade, XmNsubMenuId, &menu, NULL);
5135 if (menu != NULL)
5136 XtDestroyWidget(menu);
5137 menu = CreatePulldownMenu(XtParent(window->langModeCascade),
5138 "languageModes", args, 1);
5139 btn = XtVaCreateManagedWidget("languageMode",
5140 xmToggleButtonGadgetClass, menu,
5141 XmNlabelString, s1=XmStringCreateSimple("Plain"),
5142 XmNuserData, (void *)PLAIN_LANGUAGE_MODE,
5143 XmNset, window->languageMode==PLAIN_LANGUAGE_MODE, NULL);
5144 XmStringFree(s1);
5145 XtAddCallback(btn, XmNvalueChangedCallback, setLangModeCB, window);
5146 for (i=0; i<NLanguageModes; i++) {
5147 btn = XtVaCreateManagedWidget("languageMode",
5148 xmToggleButtonGadgetClass, menu,
5149 XmNlabelString, s1=XmStringCreateSimple(LanguageModes[i]->name),
5150 XmNmarginHeight, 0,
5151 XmNuserData, (void *)i,
5152 XmNset, window->languageMode==i, NULL);
5153 XmStringFree(s1);
5154 XtAddCallback(btn, XmNvalueChangedCallback, setLangModeCB, window);
5156 XtVaSetValues(window->langModeCascade, XmNsubMenuId, menu, NULL);
5159 static void setLangModeCB(Widget w, XtPointer clientData, XtPointer callData)
5161 WindowInfo *window = WidgetToWindow(MENU_WIDGET(w));
5162 char *params[1];
5163 void *mode;
5165 if (!XmToggleButtonGetState(w))
5166 return;
5168 /* get name of language mode stored in userData field of menu item */
5169 XtVaGetValues(w, XmNuserData, &mode, NULL);
5171 /* If the mode didn't change, do nothing */
5172 if (window->languageMode == (int)mode)
5173 return;
5175 /* redo syntax highlighting word delimiters, etc. */
5177 reapplyLanguageMode(window, (int)mode, False);
5179 params[0] = (((int)mode) == PLAIN_LANGUAGE_MODE) ? "" : LanguageModes[(int)mode]->name;
5180 XtCallActionProc(window->textArea, "set_language_mode", NULL, params, 1);
5184 ** Skip a delimiter and it's surrounding whitespace
5186 int SkipDelimiter(char **inPtr, char **errMsg)
5188 *inPtr += strspn(*inPtr, " \t");
5189 if (**inPtr != ':') {
5190 *errMsg = "syntax error";
5191 return False;
5193 (*inPtr)++;
5194 *inPtr += strspn(*inPtr, " \t");
5195 return True;
5199 ** Skip an optional separator and its surrounding whitespace
5200 ** return true if delimiter found
5202 int SkipOptSeparator(char separator, char **inPtr)
5204 *inPtr += strspn(*inPtr, " \t");
5205 if (**inPtr != separator) {
5206 return False;
5208 (*inPtr)++;
5209 *inPtr += strspn(*inPtr, " \t");
5210 return True;
5214 ** Short-hand error processing for language mode parsing errors, frees
5215 ** lm (if non-null), prints a formatted message explaining where the
5216 ** error is, and returns False;
5218 static int modeError(languageModeRec *lm, const char *stringStart,
5219 const char *stoppedAt, const char *message)
5221 if (lm != NULL)
5222 freeLanguageModeRec(lm);
5223 return ParseError(NULL, stringStart, stoppedAt,
5224 "language mode specification", message);
5228 ** Report parsing errors in resource strings or macros, formatted nicely so
5229 ** the user can tell where things became botched. Errors can be sent either
5230 ** to stderr, or displayed in a dialog. For stderr, pass toDialog as NULL.
5231 ** For a dialog, pass the dialog parent in toDialog.
5233 int ParseError(Widget toDialog, const char *stringStart, const char *stoppedAt,
5234 const char *errorIn, const char *message)
5236 int len, nNonWhite = 0;
5237 const char *c;
5238 char *errorLine;
5240 for (c=stoppedAt; c>=stringStart; c--) {
5241 if (c == stringStart)
5242 break;
5243 else if (*c == '\n' && nNonWhite >= 5)
5244 break;
5245 else if (*c != ' ' && *c != '\t')
5246 nNonWhite++;
5248 len = stoppedAt - c + (*stoppedAt == '\0' ? 0 : 1);
5249 errorLine = XtMalloc(len+4);
5250 strncpy(errorLine, c, len);
5251 errorLine[len++] = '<';
5252 errorLine[len++] = '=';
5253 errorLine[len++] = '=';
5254 errorLine[len] = '\0';
5255 if (toDialog == NULL)
5257 fprintf(stderr, "NEdit: %s in %s:\n%s\n", message, errorIn, errorLine);
5258 } else
5260 DialogF(DF_WARN, toDialog, 1, "Parse Error", "%s in %s:\n%s", "OK",
5261 message, errorIn, errorLine);
5263 XtFree(errorLine);
5264 return False;
5268 ** Compare two strings which may be NULL
5270 int AllocatedStringsDiffer(const char *s1, const char *s2)
5272 if (s1 == NULL && s2 == NULL)
5273 return False;
5274 if (s1 == NULL || s2 == NULL)
5275 return True;
5276 return strcmp(s1, s2);
5279 static void updatePatternsTo5dot1(void)
5281 const char *htmlDefaultExpr = "^[ \t]*HTML[ \t]*:[ \t]*Default[ \t]*$";
5282 const char *vhdlAnchorExpr = "^[ \t]*VHDL:";
5284 /* Add new patterns if there aren't already existing patterns with
5285 the same name. If possible, insert before VHDL in language mode
5286 list. If not, just add to end */
5287 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*PostScript:"))
5288 spliceString(&TempStringPrefs.highlight, "PostScript:Default",
5289 vhdlAnchorExpr);
5290 if (!regexFind(TempStringPrefs.language, "^[ \t]*PostScript:"))
5291 spliceString(&TempStringPrefs.language,
5292 "PostScript:.ps .PS .eps .EPS .epsf .epsi::::::",
5293 vhdlAnchorExpr);
5294 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*Lex:"))
5295 spliceString(&TempStringPrefs.highlight, "Lex:Default",
5296 vhdlAnchorExpr);
5297 if (!regexFind(TempStringPrefs.language, "^[ \t]*Lex:"))
5298 spliceString(&TempStringPrefs.language, "Lex:.lex::::::",
5299 vhdlAnchorExpr);
5300 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*SQL:"))
5301 spliceString(&TempStringPrefs.highlight, "SQL:Default",
5302 vhdlAnchorExpr);
5303 if (!regexFind(TempStringPrefs.language, "^[ \t]*SQL:"))
5304 spliceString(&TempStringPrefs.language, "SQL:.sql::::::",
5305 vhdlAnchorExpr);
5306 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*Matlab:"))
5307 spliceString(&TempStringPrefs.highlight, "Matlab:Default",
5308 vhdlAnchorExpr);
5309 if (!regexFind(TempStringPrefs.language, "^[ \t]*Matlab:"))
5310 spliceString(&TempStringPrefs.language, "Matlab:..m .oct .sci::::::",
5311 vhdlAnchorExpr);
5312 if (!regexFind(TempStringPrefs.smartIndent, "^[ \t]*Matlab:"))
5313 spliceString(&TempStringPrefs.smartIndent, "Matlab:Default", NULL);
5314 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Label:"))
5315 spliceString(&TempStringPrefs.styles, "Label:red:Italic",
5316 "^[ \t]*Flag:");
5317 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Storage Type1:"))
5318 spliceString(&TempStringPrefs.styles, "Storage Type1:saddle brown:Bold",
5319 "^[ \t]*String:");
5321 /* Replace html pattern with sgml html pattern, as long as there
5322 isn't an existing html pattern which will be overwritten */
5323 if (regexFind(TempStringPrefs.highlight, htmlDefaultExpr)) {
5324 regexReplace(&TempStringPrefs.highlight, htmlDefaultExpr,
5325 "SGML HTML:Default");
5326 if (!regexReplace(&TempStringPrefs.language, "^[ \t]*HTML:.*$",
5327 "SGML HTML:.sgml .sgm .html .htm:\"\\<(?ihtml)\\>\":::::\n")) {
5328 spliceString(&TempStringPrefs.language,
5329 "SGML HTML:.sgml .sgm .html .htm:\"\\<(?ihtml)\\>\":::::\n",
5330 vhdlAnchorExpr);
5335 static void updatePatternsTo5dot2(void)
5337 #ifdef VMS
5338 const char *cppLm5dot1 =
5339 "^[ \t]*C\\+\\+:\\.CC \\.HH \\.I::::::\"\\.,/\\\\`'!\\|@#%\\^&\\*\\(\\)-=\\+\\{\\}\\[\\]\"\":;\\<\\>\\?~\"";
5340 const char *perlLm5dot1 =
5341 "^[ \t]*Perl:\\.PL \\.PM \\.P5:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\.\\*perl\":::::";
5342 const char *psLm5dot1 =
5343 "^[ \t]*PostScript:\\.ps \\.PS \\.eps \\.EPS \\.epsf \\.epsi:\"\\^%!\":::::\"/%\\(\\)\\{\\}\\[\\]\\<\\>\"";
5344 const char *tclLm5dot1 = "^[ \t]*Tcl:\\.TCL::::::";
5346 const char *cppLm5dot2 =
5347 "C++:.CC .HH .C .H .I .CXX .HXX .CPP::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\"";
5348 const char *perlLm5dot2 =
5349 "Perl:.PL .PM .P5:\"^[ \\t]*#[ \\t]*!.*perl\":Auto:None:::\".,/\\\\`'!$@#%^&*()-=+{}[]\"\":;<>?~|\"";
5350 const char *psLm5dot2 =
5351 "PostScript:.ps .PS .eps .EPS .epsf .epsi:\"^%!\":::::\"/%(){}[]<>\"";
5352 const char *tclLm5dot2 =
5353 "Tcl:.TCL::Smart:None:::";
5354 #else
5355 const char *cppLm5dot1 =
5356 "^[ \t]*C\\+\\+:\\.cc \\.hh \\.C \\.H \\.i \\.cxx \\.hxx::::::\"\\.,/\\\\`'!\\|@#%\\^&\\*\\(\\)-=\\+\\{\\}\\[\\]\"\":;\\<\\>\\?~\"";
5357 const char *perlLm5dot1 =
5358 "^[ \t]*Perl:\\.pl \\.pm \\.p5:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\.\\*perl\":::::";
5359 const char *psLm5dot1 =
5360 "^[ \t]*PostScript:\\.ps \\.PS \\.eps \\.EPS \\.epsf \\.epsi:\"\\^%!\":::::\"/%\\(\\)\\{\\}\\[\\]\\<\\>\"";
5361 const char *shLm5dot1 =
5362 "^[ \t]*Sh Ksh Bash:\\.sh \\.bash \\.ksh \\.profile:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\[ \\\\t\\]\\*/bin/\\(sh\\|ksh\\|bash\\)\":::::";
5363 const char *tclLm5dot1 = "^[ \t]*Tcl:\\.tcl::::::";
5365 const char *cppLm5dot2 =
5366 "C++:.cc .hh .C .H .i .cxx .hxx .cpp::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\"";
5367 const char *perlLm5dot2 =
5368 "Perl:.pl .pm .p5 .PL:\"^[ \\t]*#[ \\t]*!.*perl\":Auto:None:::\".,/\\\\`'!$@#%^&*()-=+{}[]\"\":;<>?~|\"";
5369 const char *psLm5dot2 =
5370 "PostScript:.ps .eps .epsf .epsi:\"^%!\":::::\"/%(){}[]<>\"";
5371 const char *shLm5dot2 =
5372 "Sh Ksh Bash:.sh .bash .ksh .profile .bashrc .bash_logout .bash_login .bash_profile:\"^[ \\t]*#[ \\t]*![ \\t]*/.*bin/(sh|ksh|bash)\":::::";
5373 const char *tclLm5dot2 =
5374 "Tcl:.tcl .tk .itcl .itk::Smart:None:::";
5375 #endif /* VMS */
5377 const char *cssLm5dot2 =
5378 "CSS:css::Auto:None:::\".,/\\`'!|@#%^&*()=+{}[]\"\":;<>?~\"";
5379 const char *reLm5dot2 =
5380 "Regex:.reg .regex:\"\\(\\?[:#=!iInN].+\\)\":None:Continuous:::";
5381 const char *xmlLm5dot2 =
5382 "XML:.xml .xsl .dtd:\"\\<(?i\\?xml|!doctype)\"::None:::\"<>/=\"\"'()+*?|\"";
5384 const char *cssHl5dot2 = "CSS:Default";
5385 const char *reHl5dot2 = "Regex:Default";
5386 const char *xmlHl5dot2 = "XML:Default";
5388 const char *ptrStyle = "Pointer:#660000:Bold";
5389 const char *reStyle = "Regex:#009944:Bold";
5390 const char *wrnStyle = "Warning:brown2:Italic";
5392 /* First upgrade modified language modes, only if the user hasn't
5393 altered the default 5.1 definitions. */
5394 if (regexFind(TempStringPrefs.language, cppLm5dot1))
5395 regexReplace(&TempStringPrefs.language, cppLm5dot1, cppLm5dot2);
5396 if (regexFind(TempStringPrefs.language, perlLm5dot1))
5397 regexReplace(&TempStringPrefs.language, perlLm5dot1, perlLm5dot2);
5398 if (regexFind(TempStringPrefs.language, psLm5dot1))
5399 regexReplace(&TempStringPrefs.language, psLm5dot1, psLm5dot2);
5400 #ifndef VMS
5401 if (regexFind(TempStringPrefs.language, shLm5dot1))
5402 regexReplace(&TempStringPrefs.language, shLm5dot1, shLm5dot2);
5403 #endif
5404 if (regexFind(TempStringPrefs.language, tclLm5dot1))
5405 regexReplace(&TempStringPrefs.language, tclLm5dot1, tclLm5dot2);
5407 /* Then append the new modes (trying to keep them in alphabetical order
5408 makes no sense, since 5.1 didn't use alphabetical order). */
5409 if (!regexFind(TempStringPrefs.language, "^[ \t]*CSS:"))
5410 spliceString(&TempStringPrefs.language, cssLm5dot2, NULL);
5411 if (!regexFind(TempStringPrefs.language, "^[ \t]*Regex:"))
5412 spliceString(&TempStringPrefs.language, reLm5dot2, NULL);
5413 if (!regexFind(TempStringPrefs.language, "^[ \t]*XML:"))
5414 spliceString(&TempStringPrefs.language, xmlLm5dot2, NULL);
5416 /* Enable default highlighting patterns for these modes, unless already
5417 present */
5418 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*CSS:"))
5419 spliceString(&TempStringPrefs.highlight, cssHl5dot2, NULL);
5420 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*Regex:"))
5421 spliceString(&TempStringPrefs.highlight, reHl5dot2, NULL);
5422 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*XML:"))
5423 spliceString(&TempStringPrefs.highlight, xmlHl5dot2, NULL);
5425 /* Finally, append the new highlight styles */
5427 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Warning:"))
5428 spliceString(&TempStringPrefs.styles, wrnStyle, NULL);
5429 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Regex:"))
5430 spliceString(&TempStringPrefs.styles, reStyle, "^[ \t]*Warning:");
5431 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Pointer:"))
5432 spliceString(&TempStringPrefs.styles, ptrStyle, "^[ \t]*Regex:");
5435 static void updatePatternsTo5dot3(void)
5437 /* This is a bogus function on non-VMS */
5438 #ifdef VMS
5439 const char *psLm5dot2 =
5440 "^[ \t]*PostScript:\\.ps \\.PS \\.eps \\.EPS \\.epsf \\.epsi:\"\\^%!\":::::\"/%\\(\\)\\{\\}\\[\\]\\<\\>\"";
5442 const char *psLm5dot3 =
5443 "PostScript:.ps .PS .eps .EPS .epsf .EPSF .epsi .EPSI:\"^%!\":::::\"/%(){}[]<>\"";
5445 /* Upgrade modified language modes, only if the user hasn't
5446 altered the default 5.2 definitions. */
5447 if (regexFind(TempStringPrefs.language, psLm5dot2))
5448 regexReplace(&TempStringPrefs.language, psLm5dot2, psLm5dot3);
5449 #endif
5452 static void updatePatternsTo5dot4(void)
5454 #ifdef VMS
5455 const char *pyLm5dot3 =
5456 "Python:\\.PY:\"\\^#!\\.\\*python\":Auto:None::::?\n";
5457 const char *xrLm5dot3 =
5458 "X Resources:\\.XRESOURCES \\.XDEFAULTS \\.NEDIT:\"\\^\\[!#\\]\\.\\*\\(\\[Aa\\]pp\\|\\[Xx\\]\\)\\.\\*\\[Dd\\]efaults\"::::::?\n";
5460 const char *pyLm5dot4 =
5461 "Python:.PY:\"^#!.*python\":Auto:None:::\"!\"\"#$%&'()*+,-./:;<=>?@[\\\\]^`{|}~\":\n";
5462 const char *xrLm5dot4 =
5463 "X Resources:.XRESOURCES .XDEFAULTS .NEDIT NEDIT.RC:\"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults\"::::::\n";
5464 #else
5465 const char *pyLm5dot3 =
5466 "Python:\\.py:\"\\^#!\\.\\*python\":Auto:None::::?\n";
5467 const char *xrLm5dot3 =
5468 "X Resources:\\.Xresources \\.Xdefaults \\.nedit:\"\\^\\[!#\\]\\.\\*\\(\\[Aa\\]pp\\|\\[Xx\\]\\)\\.\\*\\[Dd\\]efaults\"::::::?\n";
5470 const char *pyLm5dot4 =
5471 "Python:.py:\"^#!.*python\":Auto:None:::\"!\"\"#$%&'()*+,-./:;<=>?@[\\\\]^`{|}~\":\n";
5472 const char *xrLm5dot4 =
5473 "X Resources:.Xresources .Xdefaults .nedit nedit.rc:\"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults\"::::::\n";
5474 #endif
5476 /* Upgrade modified language modes, only if the user hasn't
5477 altered the default 5.3 definitions. */
5478 if (regexFind(TempStringPrefs.language, pyLm5dot3))
5479 regexReplace(&TempStringPrefs.language, pyLm5dot3, pyLm5dot4);
5480 if (regexFind(TempStringPrefs.language, xrLm5dot3))
5481 regexReplace(&TempStringPrefs.language, xrLm5dot3, xrLm5dot4);
5483 /* Add new styles */
5484 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Identifier2:"))
5485 spliceString(&TempStringPrefs.styles, "Identifier2:SteelBlue:Plain",
5486 "^[ \t]*Subroutine:");
5489 static void updatePatternsTo5dot6(void)
5491 const char *pats[] = {
5492 #ifndef VMS
5493 "Csh:\\.csh \\.cshrc \\.login \\.logout:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\[ \\\\t\\]\\*/bin/csh\"::::::\\n",
5494 "Csh:.csh .cshrc .tcshrc .login .logout:\"^[ \\t]*#[ \\t]*![ \\t]*/bin/t?csh\"::::::\n",
5495 "LaTeX:\\.tex \\.sty \\.cls \\.ltx \\.ins:::::::\\n",
5496 "LaTeX:.tex .sty .cls .ltx .ins .clo .fd:::::::\n",
5497 "X Resources:\\.Xresources \\.Xdefaults \\.nedit:\"\\^\\[!#\\]\\.\\*\\(\\[Aa\\]pp\\|\\[Xx\\]\\)\\.\\*\\[Dd\\]efaults\"::::::\\n",
5498 "X Resources:.Xresources .Xdefaults .nedit .pats nedit.rc:\"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults\"::::::\n",
5499 #else
5500 "Csh:\\.csh \\.cshrc \\.login \\.logout:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\[ \\\\t\\]\\*/bin/csh\"::::::\\n",
5501 "Csh:.CSH .CSHRC .TCSHRC .LOGIN .LOGOUT:\"^[ \\t]*#[ \\t]*![ \\t]*/bin/t?csh\"::::::\n",
5502 "LaTeX:\\.TEX \\.STY \\.CLS \\.LTX \\.INS:::::::\\n",
5503 "LaTeX:.TEX .STY .CLS .LTX .INS .CLO .FD:::::::\n",
5504 "Lex:\\.lex:::::::\\n",
5505 "Lex:.LEX:::::::\n",
5506 "Matlab:\\.m \\.oct \\.sci:::::::\\n",
5507 "Matlab:.M .OCT .SCI:::::::\n",
5508 "Regex:\\.reg \\.regex:\"\\\\\\(\\\\\\?\\[:#=!iInN\\]\\.\\+\\\\\\\)\":None:Continuous::::\\n",
5509 "Regex:.REG .REGEX:\"\\(\\?[:#=!iInN].+\\)\":None:Continuous::::\n",
5510 "SGML HTML:\\.sgml \\.sgm \\.html \\.htm:\"\\\\\\<\\[Hh\\]\\[Tt\\]\\[Mm\\]\\[Ll\\]\\\\\\>\"::::::\\n",
5511 "SGML HTML:.SGML .SGM .HTML .HTM:\"\\<[Hh][Tt][Mm][Ll]\\>\"::::::\n",
5512 "SQL:\\.sql:::::::\\n",
5513 "SQL:.SQL:::::::\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 "Sh Ksh Bash:.SH .BASH .KSH .PROFILE .BASHRC .BASH_LOGOUT .BASH_LOGIN .BASH_PROFILE:\"^[ \\t]*#[ \\t]*![ \\t]*/.*bin/(bash|ksh|sh|zsh)\"::::::\n",
5516 "XML:\\.xml \\.xsl \\.dtd:\"\\\\\\<\\(\\?i\\\\\\?xml\\|!doctype\\)\"::None:::\"\\<\\>/=\"\"'\\(\\)\\+\\*\\?\\|\":\\n",
5517 "XML:.XML .XSL .DTD:\"\\<(?i\\?xml|!doctype)\"::None:::\"<>/=\"\"'()+*?|\":\n",
5518 "X Resources:\\.XRESOURCES \\.XDEFAULTS \\.NEDIT:\"\\^\\[!#\\]\\.\\*\\(\\[Aa\\]pp\\|\\[Xx\\]\\)\\.\\*\\[Dd\\]efaults\"::::::\\n",
5519 "X Resources:.XRESOURCES .XDEFAULTS .NEDIT .PATS NEDIT.RC:\"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults\"::::::\n",
5520 #endif
5521 NULL };
5523 /* Upgrade modified language modes, only if the user hasn't
5524 altered the default 5.5 definitions. */
5525 int i;
5526 for (i = 0; pats[i]; i+=2) {
5527 if (regexFind(TempStringPrefs.language, pats[i]))
5528 regexReplace(&TempStringPrefs.language, pats[i], pats[i+1]);
5531 /* Add new styles */
5532 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Bracket:"))
5533 spliceString(&TempStringPrefs.styles, "Bracket:dark blue:Bold",
5534 "^[ \t]*Storage Type:");
5535 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Operator:"))
5536 spliceString(&TempStringPrefs.styles, "Operator:dark blue:Bold",
5537 "^[ \t]*Bracket:");
5542 * We migrate a color from the X resources to the prefs if:
5543 * 1. The prefs entry is equal to the default entry
5544 * 2. The X resource is not equal to the default entry
5546 static void migrateColor(XrmDatabase prefDB, XrmDatabase appDB,
5547 char *class, char *name, int color_index, char *default_val)
5549 char *type, *valueString;
5550 XrmValue rsrcValue;
5552 /* If this color has been customized in the color dialog then use
5553 that value */
5554 if ( strcmp(default_val, PrefData.colorNames[color_index]) )
5555 return;
5557 /* Retrieve the value of the resource from the DB */
5558 if (XrmGetResource(prefDB, name, class, &type, &rsrcValue)) {
5559 if (strcmp(type, XmRString)) {
5560 fprintf(stderr,"Internal Error: Unexpected resource type, %s\n",
5561 type);
5562 return;
5564 valueString = rsrcValue.addr;
5565 } else if (XrmGetResource(appDB, name, class, &type, &rsrcValue)) {
5566 if (strcmp(type, XmRString)) {
5567 fprintf(stderr,"Internal Error: Unexpected resource type, %s\n",
5568 type);
5569 return;
5571 valueString = rsrcValue.addr;
5572 } else
5573 /* No resources set */
5574 return;
5576 /* An X resource is set. If it's non-default, update the prefs. */
5577 if ( strcmp(valueString, default_val) ) {
5578 strncpy(PrefData.colorNames[color_index], valueString,
5579 MAX_COLOR_LEN);
5584 * In 5.4 we moved color preferences from X resources to a color dialog,
5585 * meaning they're in the normal prefs system. Users who have customized
5586 * their colors with X resources would probably prefer not to have to redo
5587 * the customization in the dialog, so we migrate them to the prefs for them.
5589 static void migrateColorResources(XrmDatabase prefDB, XrmDatabase appDB)
5591 migrateColor(prefDB, appDB, APP_CLASS ".Text.Foreground",
5592 APP_NAME ".text.foreground", TEXT_FG_COLOR,
5593 NEDIT_DEFAULT_FG);
5594 migrateColor(prefDB, appDB, APP_CLASS ".Text.Background",
5595 APP_NAME ".text.background", TEXT_BG_COLOR,
5596 NEDIT_DEFAULT_TEXT_BG);
5597 migrateColor(prefDB, appDB, APP_CLASS ".Text.SelectForeground",
5598 APP_NAME ".text.selectForeground", SELECT_FG_COLOR,
5599 NEDIT_DEFAULT_SEL_FG);
5600 migrateColor(prefDB, appDB, APP_CLASS ".Text.SelectBackground",
5601 APP_NAME ".text.selectBackground", SELECT_BG_COLOR,
5602 NEDIT_DEFAULT_SEL_BG);
5603 migrateColor(prefDB, appDB, APP_CLASS ".Text.HighlightForeground",
5604 APP_NAME ".text.highlightForeground", HILITE_FG_COLOR,
5605 NEDIT_DEFAULT_HI_FG);
5606 migrateColor(prefDB, appDB, APP_CLASS ".Text.HighlightBackground",
5607 APP_NAME ".text.highlightBackground", HILITE_BG_COLOR,
5608 NEDIT_DEFAULT_HI_BG);
5609 migrateColor(prefDB, appDB, APP_CLASS ".Text.LineNumForeground",
5610 APP_NAME ".text.lineNumForeground", LINENO_FG_COLOR,
5611 NEDIT_DEFAULT_LINENO_FG);
5612 migrateColor(prefDB, appDB, APP_CLASS ".Text.CursorForeground",
5613 APP_NAME ".text.cursorForeground", CURSOR_FG_COLOR,
5614 NEDIT_DEFAULT_CURSOR_FG);
5618 ** Inserts a string into intoString, reallocating it with XtMalloc. If
5619 ** regular expression atExpr is found, inserts the string before atExpr
5620 ** followed by a newline. If atExpr is not found, inserts insertString
5621 ** at the end, PRECEDED by a newline.
5623 static void spliceString(char **intoString, const char *insertString, const char *atExpr)
5625 int beginPos, endPos;
5626 int intoLen = strlen(*intoString);
5627 int insertLen = strlen(insertString);
5628 char *newString = XtMalloc(intoLen + insertLen + 2);
5630 if (atExpr != NULL && SearchString(*intoString, atExpr,
5631 SEARCH_FORWARD, SEARCH_REGEX, False, 0, &beginPos, &endPos,
5632 NULL, NULL, NULL)) {
5633 strncpy(newString, *intoString, beginPos);
5634 strncpy(&newString[beginPos], insertString, insertLen);
5635 newString[beginPos+insertLen] = '\n';
5636 strncpy(&newString[beginPos+insertLen+1],
5637 &((*intoString)[beginPos]), intoLen - beginPos);
5638 } else {
5639 strncpy(newString, *intoString, intoLen);
5640 newString[intoLen] = '\n';
5641 strncpy(&newString[intoLen+1], insertString, insertLen);
5643 newString[intoLen + insertLen + 1] = '\0';
5644 XtFree(*intoString);
5645 *intoString = newString;
5649 ** Simplified regular expression search routine which just returns true
5650 ** or false depending on whether inString matches expr
5652 static int regexFind(const char *inString, const char *expr)
5654 int beginPos, endPos;
5655 return SearchString(inString, expr, SEARCH_FORWARD, SEARCH_REGEX, False,
5656 0, &beginPos, &endPos, NULL, NULL, NULL);
5660 ** Simplified case-sensisitive string search routine which just
5661 ** returns true or false depending on whether inString matches expr
5663 static int caseFind(const char *inString, const char *expr)
5665 int beginPos, endPos;
5666 return SearchString(inString, expr, SEARCH_FORWARD, SEARCH_CASE_SENSE,
5667 False, 0, &beginPos, &endPos, NULL, NULL, NULL);
5671 ** Common implementation for simplified string replacement routines.
5673 static int stringReplace(char **inString, const char *expr,
5674 const char *replaceWith, int searchType,
5675 int replaceLen)
5677 int beginPos, endPos, newLen;
5678 char *newString;
5679 int inLen = strlen(*inString);
5680 if (0 >= replaceLen) replaceLen = strlen(replaceWith);
5681 if (!SearchString(*inString, expr, SEARCH_FORWARD, searchType, False,
5682 0, &beginPos, &endPos, NULL, NULL, NULL))
5683 return FALSE;
5684 newLen = inLen + replaceLen - (endPos-beginPos);
5685 newString = XtMalloc(newLen + 1);
5686 strncpy(newString, *inString, beginPos);
5687 strncpy(&newString[beginPos], replaceWith, replaceLen);
5688 strncpy(&newString[beginPos+replaceLen],
5689 &((*inString)[endPos]), inLen - endPos);
5690 newString[newLen] = '\0';
5691 XtFree(*inString);
5692 *inString = newString;
5693 return TRUE;
5697 ** Simplified regular expression replacement routine which replaces the
5698 ** first occurence of expr in inString with replaceWith, reallocating
5699 ** inString with XtMalloc. If expr is not found, does nothing and
5700 ** returns false.
5702 static int regexReplace(char **inString, const char *expr,
5703 const char *replaceWith)
5705 return stringReplace(inString, expr, replaceWith, SEARCH_REGEX, -1);
5709 ** Simplified case-sensisitive string replacement routine which
5710 ** replaces the first occurence of expr in inString with replaceWith,
5711 ** reallocating inString with XtMalloc. If expr is not found, does nothing
5712 ** and returns false.
5714 static int caseReplace(char **inString, const char *expr,
5715 const char *replaceWith, int replaceLen)
5717 return stringReplace(inString, expr, replaceWith, SEARCH_CASE_SENSE,
5718 replaceLen);
5722 ** Looks for a (case-sensitive literal) match of an old macro text in a
5723 ** temporary macro commands buffer. If the text is found, it is replaced by
5724 ** a substring of the default macros, bounded by a given start and end pattern
5725 ** (inclusive). Returns the length of the replacement.
5727 static int replaceMacroIfUnchanged(const char* oldText, const char* newStart,
5728 const char* newEnd)
5730 if (caseFind(TempStringPrefs.macroCmds, oldText)) {
5731 #ifdef VMS
5732 const char *start = strstr(PrefDescrip[1].defaultString, newStart);
5733 #else
5734 const char *start = strstr(PrefDescrip[2].defaultString, newStart);
5735 #endif
5736 if (start) {
5737 const char *end = strstr(start, newEnd);
5738 if (end) {
5739 int length = (int)(end-start) + strlen(newEnd);
5740 caseReplace(&TempStringPrefs.macroCmds, oldText, start, length);
5741 return length;
5745 return 0;
5748 #ifndef VMS
5750 ** Replace all '#' characters in shell commands by '##' to keep commands
5751 ** containing those working. '#' is a line number placeholder in 5.3 and
5752 ** had no special meaning before.
5754 static void updateShellCmdsTo5dot3(void)
5756 char *cOld, *cNew, *pCol, *pNL;
5757 int nHash, isCmd;
5758 char *newString;
5760 if(!TempStringPrefs.shellCmds)
5761 return;
5763 /* Count number of '#'. If there are '#' characters in the non-command
5764 ** part of the definition we count too much and later allocate too much
5765 ** memory for the new string, but this doesn't hurt.
5767 for(cOld=TempStringPrefs.shellCmds, nHash=0; *cOld; cOld++)
5768 if(*cOld == '#')
5769 nHash++;
5771 /* No '#' -> no conversion necessary. */
5772 if(!nHash)
5773 return;
5775 newString=XtMalloc(strlen(TempStringPrefs.shellCmds) + 1 + nHash);
5777 cOld = TempStringPrefs.shellCmds;
5778 cNew = newString;
5779 isCmd = 0;
5780 pCol = NULL;
5781 pNL = NULL;
5783 /* Copy all characters from TempStringPrefs.shellCmds into newString
5784 ** and duplicate '#' in command parts. A simple check for really beeing
5785 ** inside a command part (starting with '\n', between the the two last
5786 ** '\n' a colon ':' must have been found) is preformed.
5788 while(*cOld) {
5789 /* actually every 2nd line is a command. We additionally
5790 ** check if there is a colon ':' in the previous line.
5792 if(*cOld=='\n') {
5793 if((pCol > pNL) && !isCmd)
5794 isCmd=1;
5795 else
5796 isCmd=0;
5797 pNL=cOld;
5800 if(!isCmd && *cOld ==':')
5801 pCol = cOld;
5803 /* Duplicate hashes if we're in a command part */
5804 if(isCmd && *cOld=='#')
5805 *cNew++ = '#';
5807 /* Copy every character */
5808 *cNew++ = *cOld++;
5812 /* Terminate new preferences string */
5813 *cNew = 0;
5815 /* free the old memory */
5816 XtFree(TempStringPrefs.shellCmds);
5818 /* exchange the string */
5819 TempStringPrefs.shellCmds = newString;
5823 #else
5825 static void updateShellCmdsTo5dot3(void) {
5826 /* No shell commands in VMS ! */
5827 return;
5830 #endif
5832 static void updateShellCmdsTo5dot4(void)
5834 #ifndef VMS /* No shell commands on VMS */
5836 #ifdef __FreeBSD__
5837 const char* wc5dot3 =
5838 "^(\\s*)set wc=`wc`; echo \\$wc\\[1\\] \"words,\" \\$wc\\[2\\] \"lines,\" \\$wc\\[3\\] \"characters\"\\n";
5839 const char* wc5dot4 =
5840 "wc | awk '{print $2 \" lines, \" $1 \" words, \" $3 \" characters\"}'\n";
5841 #else
5842 const char* wc5dot3 =
5843 "^(\\s*)set wc=`wc`; echo \\$wc\\[1\\] \"lines,\" \\$wc\\[2\\] \"words,\" \\$wc\\[3\\] \"characters\"\\n";
5844 const char* wc5dot4 =
5845 "wc | awk '{print $1 \" lines, \" $2 \" words, \" $3 \" characters\"}'\n";
5846 #endif /* __FreeBSD__ */
5848 if (regexFind(TempStringPrefs.shellCmds, wc5dot3))
5849 regexReplace(&TempStringPrefs.shellCmds, wc5dot3, wc5dot4);
5851 #endif /* VMS */
5853 return;
5856 static void updateMacroCmdsTo5dot5(void)
5858 const char* uc5dot4 =
5859 "^(\\s*)if \\(substring\\(sel, keepEnd - 1, keepEnd == \" \"\\)\\)\\n";
5860 const char* uc5dot5 =
5861 " if (substring(sel, keepEnd - 1, keepEnd) == \" \")\n";
5862 if (regexFind(TempStringPrefs.macroCmds, uc5dot4))
5863 regexReplace(&TempStringPrefs.macroCmds, uc5dot4, uc5dot5);
5865 return;
5868 static void updateMacroCmdsTo5dot6(void)
5871 This is ridiculous. Macros don't belong in the default preferences
5872 string.
5873 This code is also likely to break when the macro commands are upgraded
5874 again in a next release, because it looks for patterns in the default
5875 macro string (which may change).
5876 Using a "Default" mechanism, like we do for highlighting patterns
5877 would simplify upgrading A LOT in the future, but changing the way
5878 default macros are stored, is a lot of work too, unfortunately.
5880 const char *pats[] = {
5881 "Complete Word:Alt+D::: {\n\
5882 # Tuning parameters\n\
5883 ScanDistance = 200\n\
5885 # Search back to a word boundary to find the word to complete\n\
5886 startScan = max(0, $cursor - ScanDistance)\n\
5887 endScan = min($text_length, $cursor + ScanDistance)\n\
5888 scanString = get_range(startScan, endScan)\n\
5889 keyEnd = $cursor-startScan\n\
5890 keyStart = search_string(scanString, \"<\", keyEnd, \"backward\", \"regex\")\n\
5891 if (keyStart == -1)\n\
5892 return\n\
5893 keyString = \"<\" substring(scanString, keyStart, keyEnd)\n\
5895 # search both forward and backward from the cursor position. Note that\n\
5896 # using a regex search can lead to incorrect results if any of the special\n\
5897 # regex characters is encountered, which is not considered a delimiter\n\
5898 backwardSearchResult = search_string(scanString, keyString, keyStart-1, \\\n\
5899 \"backward\", \"regex\")\n\
5900 forwardSearchResult = search_string(scanString, keyString, keyEnd, \"regex\")\n\
5901 if (backwardSearchResult == -1 && forwardSearchResult == -1) {\n\
5902 beep()\n\
5903 return\n\
5904 }\n\
5906 # if only one direction matched, use that, otherwise use the nearest\n\
5907 if (backwardSearchResult == -1)\n\
5908 matchStart = forwardSearchResult\n\
5909 else if (forwardSearchResult == -1)\n\
5910 matchStart = backwardSearchResult\n\
5911 else {\n\
5912 if (keyStart - backwardSearchResult <= forwardSearchResult - keyEnd)\n\
5913 matchStart = backwardSearchResult\n\
5914 else\n\
5915 matchStart = forwardSearchResult\n\
5916 }\n\
5918 # find the complete word\n\
5919 matchEnd = search_string(scanString, \">\", matchStart, \"regex\")\n\
5920 completedWord = substring(scanString, matchStart, matchEnd)\n\
5922 # replace it in the window\n\
5923 replace_range(startScan + keyStart, $cursor, completedWord)\n\
5924 }", "Complete Word:", "\n\t}",
5925 "Fill Sel. w/Char:::R: {\n\
5926 if ($selection_start == -1) {\n\
5927 beep()\n\
5928 return\n\
5929 }\n\
5931 # Ask the user what character to fill with\n\
5932 fillChar = string_dialog(\"Fill selection with what character?\", \"OK\", \"Cancel\")\n\
5933 if ($string_dialog_button == 2 || $string_dialog_button == 0)\n\
5934 return\n\
5936 # Count the number of lines in the selection\n\
5937 nLines = 0\n\
5938 for (i=$selection_start; i<$selection_end; i++)\n\
5939 if (get_character(i) == \"\\n\")\n\
5940 nLines++\n\
5942 # Create the fill text\n\
5943 rectangular = $selection_left != -1\n\
5944 line = \"\"\n\
5945 fillText = \"\"\n\
5946 if (rectangular) {\n\
5947 for (i=0; i<$selection_right-$selection_left; i++)\n\
5948 line = line fillChar\n\
5949 for (i=0; i<nLines; i++)\n\
5950 fillText = fillText line \"\\n\"\n\
5951 fillText = fillText line\n\
5952 } else {\n\
5953 if (nLines == 0) {\n\
5954 for (i=$selection_start; i<$selection_end; i++)\n\
5955 fillText = fillText fillChar\n\
5956 } else {\n\
5957 startIndent = 0\n\
5958 for (i=$selection_start-1; i>=0 && get_character(i)!=\"\\n\"; i--)\n\
5959 startIndent++\n\
5960 for (i=0; i<$wrap_margin-startIndent; i++)\n\
5961 fillText = fillText fillChar\n\
5962 fillText = fillText \"\\n\"\n\
5963 for (i=0; i<$wrap_margin; i++)\n\
5964 line = line fillChar\n\
5965 for (i=0; i<nLines-1; i++)\n\
5966 fillText = fillText line \"\\n\"\n\
5967 for (i=$selection_end-1; i>=$selection_start && get_character(i)!=\"\\n\"; \\\n\
5968 i--)\n\
5969 fillText = fillText fillChar\n\
5970 }\n\
5971 }\n\
5973 # Replace the selection with the fill text\n\
5974 replace_selection(fillText)\n\
5975 }", "Fill Sel. w/Char:", "\n\t}",
5976 "Comments>/* Uncomment */@C@C++@Java@CSS@JavaScript@Lex:::R: {\n\
5977 sel = get_selection()\n\
5978 selStart = $selection_start\n\
5979 selEnd = $selection_end\n\
5980 commentStart = search_string(sel, \"/*\", 0)\n\
5981 if (substring(sel, commentStart + 2, commentStart + 3) == \" \")\n\
5982 keepStart = commentStart + 3\n\
5983 else\n\
5984 keepStart = commentStart + 2\n\
5985 keepEnd = search_string(sel, \"*/\", length(sel), \"backward\")\n\
5986 commentEnd = keepEnd + 2\n\
5987 if (substring(sel, keepEnd - 1, keepEnd) == \" \")\n\
5988 keepEnd = keepEnd - 1\n\
5989 replace_range(selStart + commentStart, selStart + commentEnd, \\\n\
5990 substring(sel, keepStart, keepEnd))\n\
5991 select(selStart, selEnd - (keepStart-commentStart) - \\\n\
5992 (commentEnd - keepEnd))\n\
5993 }", "Comments>/* Uncomment */", "\n\t}",
5994 "Comments>Bar Uncomment@C:::R: {\n\
5995 selStart = $selection_start\n\
5996 selEnd = $selection_end\n\
5997 newText = get_range(selStart+3, selEnd-4)\n\
5998 newText = replace_in_string(newText, \"^ \\\\* \", \"\", \"regex\")\n\
5999 replace_range(selStart, selEnd, newText)\n\
6000 select(selStart, selStart + length(newText))\n\
6001 }","Comments>Bar Uncomment@C:", "\n\t}",
6002 "Make C Prototypes@C@C++:::: {\n\
6003 if ($selection_start == -1) {\n\
6004 start = 0\n\
6005 end = $text_length\n\
6006 } else {\n\
6007 start = $selection_start\n\
6008 end = $selection_end\n\
6009 }\n\
6010 string = get_range(start, end)\n\
6011 nDefs = 0", "Make C Prototypes@C@C++:", "\t\tnDefs = 0",
6012 NULL };
6013 int i;
6014 for (i = 0; pats[i]; i+=3)
6015 replaceMacroIfUnchanged(pats[i], pats[i+1], pats[i+2]);
6016 return;
6019 #ifdef SGI_CUSTOM
6021 ** Present the user a dialog for specifying whether or not a short
6022 ** menu mode preference should be applied toward the default setting.
6023 ** Return False (function value) if operation was canceled, return True
6024 ** in setDefault if requested to reset the default value.
6026 static int shortPrefToDefault(Widget parent, const char *settingName, int *setDefault)
6028 char msg[100] = "";
6030 if (!GetPrefShortMenus()) {
6031 *setDefault = False;
6032 return True;
6035 sprintf(msg, "%s\nSave as default for future windows as well?", settingName);
6036 switch (DialogF (DF_QUES, parent, 3, "Save Default", msg, "Yes", "No",
6037 "Cancel"))
6039 case 1: /* yes */
6040 *setDefault = True;
6041 return True;
6042 case 2: /* no */
6043 *setDefault = False;
6044 return True;
6045 case 3: /* cancel */
6046 return False;
6048 return False; /* not reached */
6050 #endif
6052 /* Decref the default calltips file(s) for this window */
6053 void UnloadLanguageModeTipsFile(WindowInfo *window)
6055 int mode;
6057 mode = window->languageMode;
6058 if (mode != PLAIN_LANGUAGE_MODE && LanguageModes[mode]->defTipsFile) {
6059 DeleteTagsFile( LanguageModes[mode]->defTipsFile, TIP, False );
6063 /******************************************************************************
6064 * The Color selection dialog
6065 ******************************************************************************/
6068 There are 8 colors: And 8 indices:
6069 textFg TEXT_FG_COLOR
6070 textBg TEXT_BG_COLOR
6071 selectFg SELECT_FG_COLOR
6072 selectBg SELECT_BG_COLOR
6073 hiliteFg HILITE_FG_COLOR
6074 hiliteBg HILITE_BG_COLOR
6075 lineNoFg LINENO_FG_COLOR
6076 cursorFg CURSOR_FG_COLOR
6079 #define MARGIN_SPACING 10
6082 * Callbacks for field modifications
6084 static void textFgModifiedCB(Widget w, XtPointer clientData,
6085 XtPointer callData)
6087 colorDialog *cd = (colorDialog *)clientData;
6088 showColorStatus(cd, cd->textFgW, cd->textFgErrW);
6091 static void textBgModifiedCB(Widget w, XtPointer clientData,
6092 XtPointer callData)
6094 colorDialog *cd = (colorDialog *)clientData;
6095 showColorStatus(cd, cd->textBgW, cd->textBgErrW);
6098 static void selectFgModifiedCB(Widget w, XtPointer clientData,
6099 XtPointer callData)
6101 colorDialog *cd = (colorDialog *)clientData;
6102 showColorStatus(cd, cd->selectFgW, cd->selectFgErrW);
6105 static void selectBgModifiedCB(Widget w, XtPointer clientData,
6106 XtPointer callData)
6108 colorDialog *cd = (colorDialog *)clientData;
6109 showColorStatus(cd, cd->selectBgW, cd->selectBgErrW);
6112 static void hiliteFgModifiedCB(Widget w, XtPointer clientData,
6113 XtPointer callData)
6115 colorDialog *cd = (colorDialog *)clientData;
6116 showColorStatus(cd, cd->hiliteFgW, cd->hiliteFgErrW);
6119 static void hiliteBgModifiedCB(Widget w, XtPointer clientData,
6120 XtPointer callData)
6122 colorDialog *cd = (colorDialog *)clientData;
6123 showColorStatus(cd, cd->hiliteBgW, cd->hiliteBgErrW);
6126 static void lineNoFgModifiedCB(Widget w, XtPointer clientData,
6127 XtPointer callData)
6129 colorDialog *cd = (colorDialog *)clientData;
6130 showColorStatus(cd, cd->lineNoFgW, cd->lineNoFgErrW);
6133 static void cursorFgModifiedCB(Widget w, XtPointer clientData,
6134 XtPointer callData)
6136 colorDialog *cd = (colorDialog *)clientData;
6137 showColorStatus(cd, cd->cursorFgW, cd->cursorFgErrW);
6142 * Helper functions for validating colors
6144 static int verifyAllColors(colorDialog *cd)
6146 /* Maybe just check for empty strings in error widgets instead? */
6147 return (checkColorStatus(cd, cd->textFgW) &&
6148 checkColorStatus(cd, cd->textBgW) &&
6149 checkColorStatus(cd, cd->selectFgW) &&
6150 checkColorStatus(cd, cd->selectBgW) &&
6151 checkColorStatus(cd, cd->hiliteFgW) &&
6152 checkColorStatus(cd, cd->hiliteBgW) &&
6153 checkColorStatus(cd, cd->lineNoFgW) &&
6154 checkColorStatus(cd, cd->cursorFgW) );
6157 /* Returns True if the color is valid, False if it's not */
6158 static Boolean checkColorStatus(colorDialog *cd, Widget colorFieldW)
6160 Colormap cMap;
6161 XColor colorDef;
6162 Status status;
6163 Display *display = XtDisplay(cd->shell);
6164 char *text = XmTextGetString(colorFieldW);
6165 XtVaGetValues(cd->shell, XtNcolormap, &cMap, NULL);
6166 status = XParseColor(display, cMap, text, &colorDef);
6167 XtFree(text);
6168 return (status != 0);
6171 /* Show or hide errorLabelW depending on whether or not colorFieldW
6172 contains a valid color name. */
6173 static void showColorStatus(colorDialog *cd, Widget colorFieldW,
6174 Widget errorLabelW)
6176 /* Should set the OK/Apply button sensitivity here, instead
6177 of leaving is sensitive and then complaining if an error. */
6178 XtSetMappedWhenManaged( errorLabelW, !checkColorStatus(cd, colorFieldW) );
6181 /* Update the colors in the window or in the preferences */
6182 static void updateColors(colorDialog *cd)
6184 WindowInfo *window;
6186 char *textFg = XmTextGetString(cd->textFgW),
6187 *textBg = XmTextGetString(cd->textBgW),
6188 *selectFg = XmTextGetString(cd->selectFgW),
6189 *selectBg = XmTextGetString(cd->selectBgW),
6190 *hiliteFg = XmTextGetString(cd->hiliteFgW),
6191 *hiliteBg = XmTextGetString(cd->hiliteBgW),
6192 *lineNoFg = XmTextGetString(cd->lineNoFgW),
6193 *cursorFg = XmTextGetString(cd->cursorFgW);
6195 for (window = WindowList; window != NULL; window = window->next)
6197 SetColors(window, textFg, textBg, selectFg, selectBg, hiliteFg,
6198 hiliteBg, lineNoFg, cursorFg);
6201 SetPrefColorName(TEXT_FG_COLOR , textFg );
6202 SetPrefColorName(TEXT_BG_COLOR , textBg );
6203 SetPrefColorName(SELECT_FG_COLOR, selectFg);
6204 SetPrefColorName(SELECT_BG_COLOR, selectBg);
6205 SetPrefColorName(HILITE_FG_COLOR, hiliteFg);
6206 SetPrefColorName(HILITE_BG_COLOR, hiliteBg);
6207 SetPrefColorName(LINENO_FG_COLOR, lineNoFg);
6208 SetPrefColorName(CURSOR_FG_COLOR, cursorFg);
6210 XtFree(textFg);
6211 XtFree(textBg);
6212 XtFree(selectFg);
6213 XtFree(selectBg);
6214 XtFree(hiliteFg);
6215 XtFree(hiliteBg);
6216 XtFree(lineNoFg);
6217 XtFree(cursorFg);
6222 * Dialog button callbacks
6225 static void colorDestroyCB(Widget w, XtPointer clientData, XtPointer callData)
6227 colorDialog *cd = (colorDialog *)clientData;
6229 cd->window->colorDialog = NULL;
6230 XtFree((char *)cd);
6233 static void colorOkCB(Widget w, XtPointer clientData, XtPointer callData)
6235 colorDialog *cd = (colorDialog *)clientData;
6237 if(!verifyAllColors(cd))
6239 DialogF(DF_ERR, w, 1, "Invalid Colors",
6240 "All colors must be valid to proceed.", "OK");
6241 return;
6243 updateColors(cd);
6245 /* pop down and destroy the dialog */
6246 XtDestroyWidget(cd->shell);
6249 static void colorApplyCB(Widget w, XtPointer clientData, XtPointer callData)
6251 colorDialog *cd = (colorDialog *)clientData;
6253 if(!verifyAllColors(cd))
6255 DialogF(DF_ERR, w, 1, "Invalid Colors",
6256 "All colors must be valid to be applied.", "OK");
6257 return;
6259 updateColors(cd);
6262 static void colorCloseCB(Widget w, XtPointer clientData, XtPointer callData)
6264 colorDialog *cd = (colorDialog *)clientData;
6266 /* pop down and destroy the dialog */
6267 XtDestroyWidget(cd->shell);
6271 /* Add a label, error label, and text entry label with a validation
6272 callback */
6273 static Widget addColorGroup( Widget parent, const char *name, char mnemonic,
6274 char *label, Widget *fieldW, Widget *errW, Widget topWidget,
6275 int leftPos, int rightPos, XtCallbackProc modCallback,
6276 colorDialog *cd )
6278 Widget lblW;
6279 char *longerName;
6280 XmString s1;
6281 int nameLen = strlen(name);
6283 /* The label widget */
6284 longerName = XtMalloc(nameLen+7);
6285 strcpy(longerName, name);
6286 strcat(longerName, "Lbl");
6287 lblW = XtVaCreateManagedWidget(longerName,
6288 xmLabelGadgetClass, parent,
6289 XmNlabelString, s1=XmStringCreateSimple( label ),
6290 XmNmnemonic, mnemonic,
6291 XmNtopAttachment, XmATTACH_WIDGET,
6292 XmNtopWidget, topWidget,
6293 XmNtopOffset, MARGIN_SPACING,
6294 XmNleftAttachment, XmATTACH_POSITION,
6295 XmNleftPosition, leftPos, NULL);
6296 XmStringFree(s1);
6298 /* The error label widget */
6299 strcpy(&(longerName[nameLen]), "ErrLbl");
6300 *errW = XtVaCreateManagedWidget(longerName,
6301 xmLabelWidgetClass, parent,
6302 XmNlabelString, s1=XmStringCreateSimple("(Invalid!)"),
6303 XmNalignment, XmALIGNMENT_END,
6304 XmNtopAttachment, XmATTACH_WIDGET,
6305 XmNtopWidget, topWidget,
6306 XmNtopOffset, MARGIN_SPACING,
6307 XmNleftAttachment, XmATTACH_WIDGET,
6308 XmNleftWidget, lblW,
6309 XmNrightAttachment, XmATTACH_POSITION,
6310 XmNrightPosition, rightPos, NULL);
6311 XmStringFree(s1);
6313 /* The text field entry widget */
6314 *fieldW = XtVaCreateManagedWidget(name, xmTextWidgetClass,
6315 parent,
6316 XmNcolumns, MAX_COLOR_LEN-1,
6317 XmNmaxLength, MAX_COLOR_LEN-1,
6318 XmNleftAttachment, XmATTACH_POSITION,
6319 XmNleftPosition, leftPos,
6320 XmNrightAttachment, XmATTACH_POSITION,
6321 XmNrightPosition, rightPos,
6322 XmNtopAttachment, XmATTACH_WIDGET,
6323 XmNtopWidget, lblW, NULL);
6324 RemapDeleteKey(*fieldW);
6325 XtAddCallback(*fieldW, XmNvalueChangedCallback,
6326 modCallback, cd);
6327 XtVaSetValues(lblW, XmNuserData, *fieldW, NULL);
6329 XtFree(longerName);
6330 return *fieldW;
6335 * Code for the dialog itself
6337 void ChooseColors(WindowInfo *window)
6339 Widget form, tmpW, topW, infoLbl;
6340 Widget okBtn, applyBtn, closeBtn;
6341 colorDialog *cd;
6342 XmString s1;
6343 int ac;
6344 Arg args[20];
6346 /* if the dialog is already displayed, just pop it to the top and return */
6347 if (window->colorDialog != NULL) {
6348 RaiseDialogWindow(((colorDialog *)window->colorDialog)->shell);
6349 return;
6352 /* Create a structure for keeping track of dialog state */
6353 cd = XtNew(colorDialog);
6354 window->colorDialog = (void*)cd;
6356 /* Create a form widget in a dialog shell */
6357 ac = 0;
6358 XtSetArg(args[ac], XmNautoUnmanage, False); ac++;
6359 XtSetArg(args[ac], XmNresizePolicy, XmRESIZE_NONE); ac++;
6360 form = CreateFormDialog(window->shell, "choose colors", args, ac);
6361 XtVaSetValues(form, XmNshadowThickness, 0, NULL);
6362 cd->shell = XtParent(form);
6363 cd->window = window;
6364 XtVaSetValues(cd->shell, XmNtitle, "Colors", NULL);
6365 AddMotifCloseCallback(XtParent(form), colorCloseCB, cd);
6366 XtAddCallback(form, XmNdestroyCallback, colorDestroyCB, cd);
6368 /* Information label */
6369 infoLbl = XtVaCreateManagedWidget("infoLbl",
6370 xmLabelGadgetClass, form,
6371 XmNtopAttachment, XmATTACH_POSITION,
6372 XmNtopPosition, 2,
6373 XmNleftAttachment, XmATTACH_POSITION,
6374 XmNleftPosition, 1,
6375 XmNrightAttachment, XmATTACH_POSITION,
6376 XmNrightPosition, 99,
6377 XmNalignment, XmALIGNMENT_CENTER,
6378 XmNlabelString, s1 = XmStringCreateLtoR(
6379 "Colors can be entered as names (e.g. red, blue) or "
6380 "as RGB triples\nin the format #RRGGBB, where each digit "
6381 "is in the range 0-f.", XmFONTLIST_DEFAULT_TAG),
6382 NULL);
6383 XmStringFree(s1);
6385 topW = infoLbl;
6387 /* The left column (foregrounds) of color entry groups */
6388 tmpW = addColorGroup( form, "textFg", 'P', "Plain Text Foreground",
6389 &(cd->textFgW), &(cd->textFgErrW), topW, 1, 49,
6390 textFgModifiedCB, cd );
6391 tmpW = addColorGroup( form, "selectFg", 'S', "Selection Foreground",
6392 &(cd->selectFgW), &(cd->selectFgErrW), tmpW, 1, 49,
6393 selectFgModifiedCB, cd );
6394 tmpW = addColorGroup( form, "hiliteFg", 'M', "Matching (..) Foreground",
6395 &(cd->hiliteFgW), &(cd->hiliteFgErrW), tmpW, 1, 49,
6396 hiliteFgModifiedCB, cd );
6397 tmpW = addColorGroup( form, "lineNoFg", 'L', "Line Numbers",
6398 &(cd->lineNoFgW), &(cd->lineNoFgErrW), tmpW, 1, 49,
6399 lineNoFgModifiedCB, cd );
6401 /* The right column (backgrounds) */
6402 tmpW = addColorGroup( form, "textBg", 'T', "Text Area Background",
6403 &(cd->textBgW), &(cd->textBgErrW), topW, 51, 99,
6404 textBgModifiedCB, cd );
6405 tmpW = addColorGroup( form, "selectBg", 'B', "Selection Background",
6406 &(cd->selectBgW), &(cd->selectBgErrW), tmpW, 51, 99,
6407 selectBgModifiedCB, cd );
6408 tmpW = addColorGroup( form, "hiliteBg", 'h', "Matching (..) Background",
6409 &(cd->hiliteBgW), &(cd->hiliteBgErrW), tmpW, 51, 99,
6410 hiliteBgModifiedCB, cd );
6411 tmpW = addColorGroup( form, "cursorFg", 'C', "Cursor Color",
6412 &(cd->cursorFgW), &(cd->cursorFgErrW), tmpW, 51, 99,
6413 cursorFgModifiedCB, cd );
6415 tmpW = XtVaCreateManagedWidget("infoLbl",
6416 xmLabelGadgetClass, form,
6417 XmNtopAttachment, XmATTACH_WIDGET,
6418 XmNtopWidget, tmpW,
6419 XmNtopOffset, MARGIN_SPACING,
6420 XmNleftAttachment, XmATTACH_POSITION,
6421 XmNleftPosition, 1,
6422 XmNrightAttachment, XmATTACH_POSITION,
6423 XmNrightPosition, 99,
6424 XmNalignment, XmALIGNMENT_CENTER,
6425 XmNlabelString, s1 = XmStringCreateLtoR(
6426 "NOTE: Foreground colors only apply when syntax highlighting "
6427 "is DISABLED.\n", XmFONTLIST_DEFAULT_TAG),
6428 NULL);
6429 XmStringFree(s1);
6431 tmpW = XtVaCreateManagedWidget("sep",
6432 xmSeparatorGadgetClass, form,
6433 XmNtopAttachment, XmATTACH_WIDGET,
6434 XmNtopWidget, tmpW,
6435 XmNleftAttachment, XmATTACH_FORM,
6436 XmNrightAttachment, XmATTACH_FORM, NULL);
6438 /* The OK, Apply, and Cancel buttons */
6439 okBtn = XtVaCreateManagedWidget("ok",
6440 xmPushButtonWidgetClass, form,
6441 XmNlabelString, s1=XmStringCreateSimple("OK"),
6442 XmNmarginWidth, BUTTON_WIDTH_MARGIN,
6443 XmNtopAttachment, XmATTACH_WIDGET,
6444 XmNtopWidget, tmpW,
6445 XmNtopOffset, MARGIN_SPACING,
6446 XmNleftAttachment, XmATTACH_POSITION,
6447 XmNleftPosition, 10,
6448 XmNrightAttachment, XmATTACH_POSITION,
6449 XmNrightPosition, 30,
6450 NULL);
6451 XtAddCallback(okBtn, XmNactivateCallback, colorOkCB, cd);
6452 XmStringFree(s1);
6454 applyBtn = XtVaCreateManagedWidget(
6455 "apply", xmPushButtonWidgetClass, form,
6456 XmNlabelString, s1=XmStringCreateSimple("Apply"),
6457 XmNtopAttachment, XmATTACH_WIDGET,
6458 XmNtopWidget, tmpW,
6459 XmNtopOffset, MARGIN_SPACING,
6460 XmNmnemonic, 'A',
6461 XmNleftAttachment, XmATTACH_POSITION,
6462 XmNleftPosition, 40,
6463 XmNrightAttachment, XmATTACH_POSITION,
6464 XmNrightPosition, 60, NULL);
6465 XtAddCallback(applyBtn, XmNactivateCallback, colorApplyCB, cd);
6466 XmStringFree(s1);
6468 closeBtn = XtVaCreateManagedWidget("close",
6469 xmPushButtonWidgetClass, form,
6470 XmNlabelString, s1=XmStringCreateSimple("Close"),
6471 XmNtopAttachment, XmATTACH_WIDGET,
6472 XmNtopWidget, tmpW,
6473 XmNtopOffset, MARGIN_SPACING,
6474 XmNleftAttachment, XmATTACH_POSITION,
6475 XmNleftPosition, 70,
6476 XmNrightAttachment, XmATTACH_POSITION,
6477 XmNrightPosition, 90,
6478 NULL);
6479 XtAddCallback(closeBtn, XmNactivateCallback, colorCloseCB, cd);
6480 XmStringFree(s1);
6482 /* Set initial default button */
6483 XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
6484 XtVaSetValues(form, XmNcancelButton, closeBtn, NULL);
6486 /* Set initial values */
6487 XmTextSetString(cd->textFgW, GetPrefColorName(TEXT_FG_COLOR ));
6488 XmTextSetString(cd->textBgW, GetPrefColorName(TEXT_BG_COLOR ));
6489 XmTextSetString(cd->selectFgW, GetPrefColorName(SELECT_FG_COLOR));
6490 XmTextSetString(cd->selectBgW, GetPrefColorName(SELECT_BG_COLOR));
6491 XmTextSetString(cd->hiliteFgW, GetPrefColorName(HILITE_FG_COLOR));
6492 XmTextSetString(cd->hiliteBgW, GetPrefColorName(HILITE_BG_COLOR));
6493 XmTextSetString(cd->lineNoFgW, GetPrefColorName(LINENO_FG_COLOR));
6494 XmTextSetString(cd->cursorFgW, GetPrefColorName(CURSOR_FG_COLOR));
6496 /* Handle mnemonic selection of buttons and focus to dialog */
6497 AddDialogMnemonicHandler(form, FALSE);
6499 /* put up dialog */
6500 ManageDialogCenteredOnPointer(form);
6504 ** This function passes up a pointer to the static name of the default
6505 ** shell, currently defined as the user's login shell.
6506 ** In case of errors, the fallback of "sh" will be returned.
6508 static const char* getDefaultShell(void)
6510 struct passwd* passwdEntry = NULL;
6511 static char shellBuffer[MAXPATHLEN + 1] = "sh";
6513 passwdEntry = getpwuid(getuid()); /* getuid() never fails. */
6515 if (NULL == passwdEntry)
6517 /* Something bad happened! Do something, quick! */
6518 perror("nedit: Failed to get passwd entry (falling back to 'sh')");
6519 return "sh";
6522 /* *passwdEntry may be overwritten */
6523 /* TODO: To make this and other function calling getpwuid() more robust,
6524 passwdEntry should be kept in a central position (Core->sysinfo?).
6525 That way, local code would always get a current copy of passwdEntry,
6526 but could still be kept lean. The obvious alternative of a central
6527 facility within NEdit to access passwdEntry would increase coupling
6528 and would have to cover a lot of assumptions. */
6529 strncpy(shellBuffer, passwdEntry->pw_shell, MAXPATHLEN);
6530 shellBuffer[MAXPATHLEN] = '\0';
6532 return shellBuffer;