1 /*******************************************************************************
2 * *
3 * preferences.c -- Nirvana Editor preferences processing *
4 * *
5 * Copyright (C) 1999 Mark Edel *
6 * *
7 * This is free software; you can redistribute it and/or modify it under the *
8 * terms of the GNU General Public License as published by the Free Software *
9 * Foundation; either version 2 of the License, or (at your option) any later *
10 * version. In addition, you may distribute version of this program linked to *
11 * Motif or Open Motif. See README for details. *
12 * *
13 * This software is distributed in the hope that it will be useful, but WITHOUT *
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
16 * for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License along with *
19 * software; if not, write to the Free Software Foundation, Inc., 59 Temple *
20 * Place, Suite 330, Boston, MA 02111-1307 USA *
21 * *
22 * Nirvana Text Editor *
23 * April 20, 1993 *
24 * *
25 * Written by Mark Edel *
26 * *
27 *******************************************************************************/
28
29 #ifdef HAVE_CONFIG_H
30 #include "../config.h"
31 #endif
32
33 #include "preferences.h"
34 #include "textBuf.h"
35 #include "nedit.h"
36 #include "menu.h"
37 #include "text.h"
38 #include "search.h"
39 #include "window.h"
40 #include "userCmds.h"
41 #include "highlight.h"
42 #include "highlightData.h"
43 #include "help.h"
44 #include "regularExp.h"
45 #include "smartIndent.h"
46 #include "windowTitle.h"
47 #include "server.h"
48 #include "tags.h"
49 #include "../util/prefFile.h"
50 #include "../util/misc.h"
51 #include "../util/DialogF.h"
52 #include "../util/managedList.h"
53 #include "../util/fontsel.h"
54 #include "../util/fileUtils.h"
55 #include "../util/utils.h"
56 #include "../util/nedit_malloc.h"
57
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*/
73
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>
89
90 #ifdef HAVE_DEBUG_H
91 #include "../debug.h"
92 #endif
93
94 #if XmVersion >= 1002
95 #define MENU_WIDGET(w) (XmGetPostedFromWidget(XtParent(w)))
96 #else
97 #define MENU_WIDGET(w) (w)
98 #endif
99
100 #define PREF_FILE_VERSION "5.6"
101
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"
104
105 /* maximum number of word delimiters allowed (256 allows whole character set) */
106 #define MAX_WORD_DELIMITERS 256
107
108 /* maximum number of file extensions allowed in a language mode */
109 #define MAX_FILE_EXTENSIONS 20
110
111 /* Return values for checkFontStatus */
112 enum fontStatus {GOOD_FONT, BAD_PRIMARY, BAD_FONT, BAD_SIZE, BAD_SPACING};
113
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 (!!)
118 */
119 static char *SearchMethodStrings[] = {
120 "Literal", "CaseSense", "RegExp",
121 "LiteralWord", "CaseSenseWord", "RegExpNoCase",
122 NULL
123 };
124
125 #ifdef REPLACE_SCOPE
126 /* enumerated default scope for replace dialog if a selection exists when
127 ** the dialog is popped up.
128 */
129 static char *ReplaceDefScopeStrings[] = {
130 "Window", "Selection", "Smart", NULL
131 };
132 #endif
133
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};
143
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};
152
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};
156
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
163
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];
179
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};
203
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;
218
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;
240
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;
328
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;
342
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\
380 \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\
391 \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\
398 \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\
403 \n\
404 if ($compWord[\"wordStart\"] == -1)\n\
405 return\n\
406 \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\
415 \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\
424 \n\
425 replace_range($compWord[\"wordStart\"], $cursor, get_range(s, se))\n\
426 \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\
437 \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\
443 \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\
448 \n\
449 rectangular = $selection_left != -1\n\
450 \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\
455 \n\
456 toplen = -1 # top piece by default empty (no NL)\n\
457 midlen = 0\n\
458 botlen = 0\n\
459 \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\
477 \n\
478 # col[0] = pos_to_column($selection_start)\n\
479 # col[1] = pos_to_column($selection_end)\n\
480 \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\
500 \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\
511 \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\
516 \n\
517 len = max(toplen, midlen, botlen)\n\
518 charlen = length(fillChar) # maybe more than one char given!\n\
519 \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\
536 \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--14-*-*-*-*-iso8859-1",
937 PrefData.fontString, (void *)sizeof(PrefData.fontString), True},
938 {"boldHighlightFont", "BoldHighlightFont", PREF_STRING,
939 "-*-courier-bold-r-normal--14-*-*-*-*-iso8859-1",
940 PrefData.boldFontString, (void *)sizeof(PrefData.boldFontString), True},
941 {"italicHighlightFont", "ItalicHighlightFont", PREF_STRING,
942 "-*-courier-medium-o-normal--14-*-*-*-*-iso8859-1",
943 PrefData.italicFontString,
944 (void *)sizeof(PrefData.italicFontString), True},
945 {"boldItalicHighlightFont", "BoldItalicHighlightFont", PREF_STRING,
946 "-*-courier-bold-o-normal--14-*-*-*-*-iso8859-1",
947 PrefData.boldItalicFontString,
948 (void *)sizeof(PrefData.boldItalicFontString), True},
949 {"helpFont", "HelpFont", PREF_STRING,
950 "-*-helvetica-medium-r-normal--14-*-*-*-*-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--14-*-*-*-*-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--14-*-*-*-*-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--14-*-*-*-*-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--14-*-*-*-*-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--14-*-*-*-*-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--14-*-*-*-*-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--14-*-*-*-*-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--14-*-*-*-*-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--14-*-*-*-*-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--14-*-*-*-*-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},
1000
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}
1076 };
1077
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},
1093 };
1094
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";
1108
1109 /* Module-global variable set when any preference changes (for asking the
1110 user about re-saving on exit) */
1111 static int PrefsHaveChanged = False;
1112
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;
1116
1117 /* Module-global variables to support Initial Window Size... dialog */
1118 static int DoneWithSizeDialog;
1119 static Widget RowText, ColText;
1120
1121 /* Module-global variables for Tabs dialog */
1122 static int DoneWithTabsDialog;
1123 static WindowInfo *TabsDialogForWindow;
1124 static Widget TabDistText, EmTabText, EmTabToggle, UseTabsToggle, EmTabLabel;
1125
1126 /* Module-global variables for Wrap Margin dialog */
1127 static int DoneWithWrapDialog;
1128 static WindowInfo *WrapDialogForWindow;
1129 static Widget WrapText, WrapTextLabel, WrapWindowToggle;
1130
1131 /* Module-global variables for shell selection dialog */
1132 static int DoneWithShellSelDialog = False;
1133
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);
1152
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);
1176
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);
1202
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);
1249
1250
1251 #ifdef SGI_CUSTOM
1252 static int shortPrefToDefault(Widget parent, const char *settingName, int *setDefault);
1253 #endif
1254
CreateNEditPrefDB(int * argcInOut,char ** argvInOut)1255 XrmDatabase CreateNEditPrefDB(int *argcInOut, char **argvInOut)
1256 {
1257 return CreatePreferencesDatabase(GetRCFileName(NEDIT_RC), APP_NAME,
1258 OpTable, XtNumber(OpTable), (unsigned int *)argcInOut, argvInOut);
1259 }
1260
RestoreNEditPrefs(XrmDatabase prefDB,XrmDatabase appDB)1261 void RestoreNEditPrefs(XrmDatabase prefDB, XrmDatabase appDB)
1262 {
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;
1268
1269 /* Load preferences */
1270 RestorePreferences(prefDB, appDB, APP_NAME,
1271 APP_CLASS, PrefDescrip, XtNumber(PrefDescrip));
1272
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();
1279 }
1280
1281 if (PrefData.prefFileRead) {
1282 if (PrefData.fileVersion[0] == '\0') {
1283 fileVer = 0; /* Pre-5.1 */
1284 }
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;
1292 }
1293 }
1294 }
1295
1296 if (PrefData.prefFileRead && fileVer < 5002) {
1297 updatePatternsTo5dot2();
1298 }
1299
1300 if (PrefData.prefFileRead && fileVer < 5003) {
1301 updateShellCmdsTo5dot3();
1302 updatePatternsTo5dot3();
1303 }
1304
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. */
1310
1311 if (PrefData.prefFileRead && (fileVer < 5004)) {
1312 migrateColorResources(prefDB, appDB);
1313 updateShellCmdsTo5dot4();
1314 updatePatternsTo5dot4();
1315 }
1316 if (PrefData.prefFileRead && (fileVer < 5005)) {
1317 updateMacroCmdsTo5dot5();
1318 }
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();
1324 }
1325 /* Migrate colors if there's no config file yet */
1326 if (!PrefData.prefFileRead) {
1327 migrateColorResources(prefDB, appDB);
1328 }
1329
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);
1336 }
1337
1338 /*
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.
1343 **
1344 ** In addition this function covers settings that, while simple, require
1345 ** additional steps before they can be published.
1346 **
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.
1352 */
translatePrefFormats(int convertOld,int fileVer)1353 static void translatePrefFormats(int convertOld, int fileVer)
1354 {
1355 XFontStruct *font;
1356
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 NEditFree(TempStringPrefs.shellCmds);
1363 TempStringPrefs.shellCmds = NULL;
1364 }
1365 #endif /* VMS */
1366 if (TempStringPrefs.macroCmds != NULL) {
1367 LoadMacroCmdsString(TempStringPrefs.macroCmds);
1368 NEditFree(TempStringPrefs.macroCmds);
1369 TempStringPrefs.macroCmds = NULL;
1370 }
1371 if (TempStringPrefs.bgMenuCmds != NULL) {
1372 LoadBGMenuCmdsString(TempStringPrefs.bgMenuCmds);
1373 NEditFree(TempStringPrefs.bgMenuCmds);
1374 TempStringPrefs.bgMenuCmds = NULL;
1375 }
1376 if (TempStringPrefs.highlight != NULL) {
1377 LoadHighlightString(TempStringPrefs.highlight, convertOld);
1378 NEditFree(TempStringPrefs.highlight);
1379 TempStringPrefs.highlight = NULL;
1380 }
1381 if (TempStringPrefs.styles != NULL) {
1382 LoadStylesString(TempStringPrefs.styles);
1383 NEditFree(TempStringPrefs.styles);
1384 TempStringPrefs.styles = NULL;
1385 }
1386 if (TempStringPrefs.language != NULL) {
1387 loadLanguageModesString(TempStringPrefs.language, fileVer);
1388 NEditFree(TempStringPrefs.language);
1389 TempStringPrefs.language = NULL;
1390 }
1391 if (TempStringPrefs.smartIndent != NULL) {
1392 LoadSmartIndentString(TempStringPrefs.smartIndent);
1393 NEditFree(TempStringPrefs.smartIndent);
1394 TempStringPrefs.smartIndent = NULL;
1395 }
1396 if (TempStringPrefs.smartIndentCommon != NULL) {
1397 LoadSmartIndentCommonString(TempStringPrefs.smartIndentCommon);
1398 NEditFree(TempStringPrefs.smartIndentCommon);
1399 TempStringPrefs.smartIndentCommon = NULL;
1400 }
1401
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);
1412
1413 /*
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.
1418 */
1419 if (0 == strcmp(PrefData.shell, "DEFAULT")) {
1420 strncpy(PrefData.shell, getDefaultShell(), MAXPATHLEN);
1421 PrefData.shell[MAXPATHLEN] = '\0';
1422 }
1423
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;
1431
1432 /* setup language mode dependent info of user menus (to increase
1433 performance when switching between documents of different
1434 language modes) */
1435 SetupUserMenuInfo();
1436 }
1437
SaveNEditPrefs(Widget parent,int quietly)1438 void SaveNEditPrefs(Widget parent, int quietly)
1439 {
1440 const char* prefFileName = GetRCFileName(NEDIT_RC);
1441 if (prefFileName == NULL)
1442 {
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;
1449 }
1450
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;
1464 }
1465 }
1466
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);
1481
1482 if (!SavePreferences(XtDisplay(parent), prefFileName, HeaderText,
1483 PrefDescrip, XtNumber(PrefDescrip)))
1484 {
1485 DialogF(DF_WARN, parent, 1, "Save Preferences",
1486 "Unable to save preferences in %s", "OK", prefFileName);
1487 }
1488
1489 #ifndef VMS
1490 NEditFree(TempStringPrefs.shellCmds);
1491 #endif /* VMS */
1492 NEditFree(TempStringPrefs.macroCmds);
1493 NEditFree(TempStringPrefs.bgMenuCmds);
1494 NEditFree(TempStringPrefs.highlight);
1495 NEditFree(TempStringPrefs.language);
1496 NEditFree(TempStringPrefs.styles);
1497 NEditFree(TempStringPrefs.smartIndent);
1498 NEditFree(TempStringPrefs.smartIndentCommon);
1499
1500 PrefsHaveChanged = False;
1501 }
1502
1503 /*
1504 ** Load an additional preferences file on top of the existing preferences
1505 ** derived from defaults, the .nedit file, and X resources.
1506 */
ImportPrefFile(const char * filename,int convertOld)1507 void ImportPrefFile(const char *filename, int convertOld)
1508 {
1509 XrmDatabase db;
1510 char *fileString;
1511
1512 fileString = ReadAnyTextFile(filename, False);
1513 if (fileString != NULL){
1514 db = XrmGetStringDatabase(fileString);
1515 NEditFree(fileString);
1516 OverlayPreferences(db, APP_NAME, APP_CLASS, PrefDescrip,
1517 XtNumber(PrefDescrip));
1518 translatePrefFormats(convertOld, -1);
1519 ImportedFile = NEditStrdup(filename);
1520 } else
1521 {
1522 fprintf(stderr, "Could not read additional preferences file: %s\n",
1523 filename);
1524 }
1525 }
1526
SetPrefOpenInTab(int state)1527 void SetPrefOpenInTab(int state)
1528 {
1529 WindowInfo *w = WindowList;
1530 setIntPref(&PrefData.openInTab, state);
1531 for(; w != NULL; w = w->next)
1532 UpdateNewOppositeMenu(w, state);
1533 }
1534
GetPrefOpenInTab(void)1535 int GetPrefOpenInTab(void)
1536 {
1537 return PrefData.openInTab;
1538 }
1539
SetPrefWrap(WrapStyle state)1540 void SetPrefWrap(WrapStyle state)
1541 {
1542 setIntPref(&PrefData.wrapStyle, (int)state);
1543 }
1544
GetPrefWrap(int langMode)1545 WrapStyle GetPrefWrap(int langMode)
1546 {
1547 if (langMode == PLAIN_LANGUAGE_MODE ||
1548 LanguageModes[langMode]->wrapStyle == DEFAULT_WRAP)
1549 return (WrapStyle)(PrefData.wrapStyle);
1550 return LanguageModes[langMode]->wrapStyle;
1551 }
1552
SetPrefWrapMargin(int margin)1553 void SetPrefWrapMargin(int margin)
1554 {
1555 setIntPref(&PrefData.wrapMargin, margin);
1556 }
1557
GetPrefWrapMargin(void)1558 int GetPrefWrapMargin(void)
1559 {
1560 return PrefData.wrapMargin;
1561 }
1562
SetPrefSearch(int searchType)1563 void SetPrefSearch(int searchType)
1564 {
1565 setIntPref(&PrefData.searchMethod, searchType);
1566 }
1567
GetPrefSearch(void)1568 int GetPrefSearch(void)
1569 {
1570 return PrefData.searchMethod;
1571 }
1572
1573 #ifdef REPLACE_SCOPE
SetPrefReplaceDefScope(int scope)1574 void SetPrefReplaceDefScope(int scope)
1575 {
1576 setIntPref(&PrefData.replaceDefScope, scope);
1577 }
1578
GetPrefReplaceDefScope(void)1579 int GetPrefReplaceDefScope(void)
1580 {
1581 return PrefData.replaceDefScope;
1582 }
1583 #endif
1584
SetPrefAutoIndent(IndentStyle state)1585 void SetPrefAutoIndent(IndentStyle state)
1586 {
1587 setIntPref(&PrefData.autoIndent, (int)state);
1588 }
1589
GetPrefAutoIndent(int langMode)1590 IndentStyle GetPrefAutoIndent(int langMode)
1591 {
1592 if (langMode == PLAIN_LANGUAGE_MODE ||
1593 LanguageModes[langMode]->indentStyle == DEFAULT_INDENT)
1594 return (IndentStyle)(PrefData.autoIndent);
1595 return LanguageModes[langMode]->indentStyle;
1596 }
1597
SetPrefAutoSave(int state)1598 void SetPrefAutoSave(int state)
1599 {
1600 setIntPref(&PrefData.autoSave, state);
1601 }
1602
GetPrefAutoSave(void)1603 int GetPrefAutoSave(void)
1604 {
1605 return PrefData.autoSave;
1606 }
1607
SetPrefSaveOldVersion(int state)1608 void SetPrefSaveOldVersion(int state)
1609 {
1610 setIntPref(&PrefData.saveOldVersion, state);
1611 }
1612
GetPrefSaveOldVersion(void)1613 int GetPrefSaveOldVersion(void)
1614 {
1615 return PrefData.saveOldVersion;
1616 }
1617
SetPrefSearchDlogs(int state)1618 void SetPrefSearchDlogs(int state)
1619 {
1620 setIntPref(&PrefData.searchDlogs, state);
1621 }
1622
GetPrefSearchDlogs(void)1623 int GetPrefSearchDlogs(void)
1624 {
1625 return PrefData.searchDlogs;
1626 }
1627
SetPrefBeepOnSearchWrap(int state)1628 void SetPrefBeepOnSearchWrap(int state)
1629 {
1630 setIntPref(&PrefData.searchWrapBeep, state);
1631 }
1632
GetPrefBeepOnSearchWrap(void)1633 int GetPrefBeepOnSearchWrap(void)
1634 {
1635 return PrefData.searchWrapBeep;
1636 }
1637
SetPrefKeepSearchDlogs(int state)1638 void SetPrefKeepSearchDlogs(int state)
1639 {
1640 setIntPref(&PrefData.keepSearchDlogs, state);
1641 }
1642
GetPrefKeepSearchDlogs(void)1643 int GetPrefKeepSearchDlogs(void)
1644 {
1645 return PrefData.keepSearchDlogs;
1646 }
1647
SetPrefSearchWraps(int state)1648 void SetPrefSearchWraps(int state)
1649 {
1650 setIntPref(&PrefData.searchWraps, state);
1651 }
1652
GetPrefStickyCaseSenseBtn(void)1653 int GetPrefStickyCaseSenseBtn(void)
1654 {
1655 return PrefData.stickyCaseSenseBtn;
1656 }
1657
GetPrefSearchWraps(void)1658 int GetPrefSearchWraps(void)
1659 {
1660 return PrefData.searchWraps;
1661 }
1662
SetPrefStatsLine(int state)1663 void SetPrefStatsLine(int state)
1664 {
1665 setIntPref(&PrefData.statsLine, state);
1666 }
1667
GetPrefStatsLine(void)1668 int GetPrefStatsLine(void)
1669 {
1670 return PrefData.statsLine;
1671 }
1672
SetPrefISearchLine(int state)1673 void SetPrefISearchLine(int state)
1674 {
1675 setIntPref(&PrefData.iSearchLine, state);
1676 }
1677
GetPrefISearchLine(void)1678 int GetPrefISearchLine(void)
1679 {
1680 return PrefData.iSearchLine;
1681 }
1682
SetPrefSortTabs(int state)1683 void SetPrefSortTabs(int state)
1684 {
1685 setIntPref(&PrefData.sortTabs, state);
1686 }
1687
GetPrefSortTabs(void)1688 int GetPrefSortTabs(void)
1689 {
1690 return PrefData.sortTabs;
1691 }
1692
SetPrefTabBar(int state)1693 void SetPrefTabBar(int state)
1694 {
1695 setIntPref(&PrefData.tabBar, state);
1696 }
1697
GetPrefTabBar(void)1698 int GetPrefTabBar(void)
1699 {
1700 return PrefData.tabBar;
1701 }
1702
SetPrefTabBarHideOne(int state)1703 void SetPrefTabBarHideOne(int state)
1704 {
1705 setIntPref(&PrefData.tabBarHideOne, state);
1706 }
1707
GetPrefTabBarHideOne(void)1708 int GetPrefTabBarHideOne(void)
1709 {
1710 return PrefData.tabBarHideOne;
1711 }
1712
SetPrefGlobalTabNavigate(int state)1713 void SetPrefGlobalTabNavigate(int state)
1714 {
1715 setIntPref(&PrefData.globalTabNavigate, state);
1716 }
1717
GetPrefGlobalTabNavigate(void)1718 int GetPrefGlobalTabNavigate(void)
1719 {
1720 return PrefData.globalTabNavigate;
1721 }
1722
SetPrefToolTips(int state)1723 void SetPrefToolTips(int state)
1724 {
1725 setIntPref(&PrefData.toolTips, state);
1726 }
1727
GetPrefToolTips(void)1728 int GetPrefToolTips(void)
1729 {
1730 return PrefData.toolTips;
1731 }
1732
SetPrefLineNums(int state)1733 void SetPrefLineNums(int state)
1734 {
1735 setIntPref(&PrefData.lineNums, state);
1736 }
1737
GetPrefLineNums(void)1738 int GetPrefLineNums(void)
1739 {
1740 return PrefData.lineNums;
1741 }
1742
SetPrefShowPathInWindowsMenu(int state)1743 void SetPrefShowPathInWindowsMenu(int state)
1744 {
1745 setIntPref(&PrefData.pathInWindowsMenu, state);
1746 }
1747
GetPrefShowPathInWindowsMenu(void)1748 int GetPrefShowPathInWindowsMenu(void)
1749 {
1750 return PrefData.pathInWindowsMenu;
1751 }
1752
SetPrefWarnFileMods(int state)1753 void SetPrefWarnFileMods(int state)
1754 {
1755 setIntPref(&PrefData.warnFileMods, state);
1756 }
1757
GetPrefWarnFileMods(void)1758 int GetPrefWarnFileMods(void)
1759 {
1760 return PrefData.warnFileMods;
1761 }
1762
SetPrefWarnRealFileMods(int state)1763 void SetPrefWarnRealFileMods(int state)
1764 {
1765 setIntPref(&PrefData.warnRealFileMods, state);
1766 }
1767
GetPrefWarnRealFileMods(void)1768 int GetPrefWarnRealFileMods(void)
1769 {
1770 return PrefData.warnRealFileMods;
1771 }
1772
SetPrefWarnExit(int state)1773 void SetPrefWarnExit(int state)
1774 {
1775 setIntPref(&PrefData.warnExit, state);
1776 }
1777
GetPrefWarnExit(void)1778 int GetPrefWarnExit(void)
1779 {
1780 return PrefData.warnExit;
1781 }
1782
SetPrefv(int state)1783 void SetPrefv(int state)
1784 {
1785 setIntPref(&PrefData.findReplaceUsesSelection, state);
1786 }
1787
GetPrefFindReplaceUsesSelection(void)1788 int GetPrefFindReplaceUsesSelection(void)
1789 {
1790 return PrefData.findReplaceUsesSelection;
1791 }
1792
GetPrefMapDelete(void)1793 int GetPrefMapDelete(void)
1794 {
1795 return PrefData.mapDelete;
1796 }
1797
GetPrefStdOpenDialog(void)1798 int GetPrefStdOpenDialog(void)
1799 {
1800 return PrefData.stdOpenDialog;
1801 }
1802
SetPrefRows(int nRows)1803 void SetPrefRows(int nRows)
1804 {
1805 setIntPref(&PrefData.textRows, nRows);
1806 }
1807
GetPrefRows(void)1808 int GetPrefRows(void)
1809 {
1810 return PrefData.textRows;
1811 }
1812
SetPrefCols(int nCols)1813 void SetPrefCols(int nCols)
1814 {
1815 setIntPref(&PrefData.textCols, nCols);
1816 }
1817
GetPrefCols(void)1818 int GetPrefCols(void)
1819 {
1820 return PrefData.textCols;
1821 }
1822
SetPrefTabDist(int tabDist)1823 void SetPrefTabDist(int tabDist)
1824 {
1825 setIntPref(&PrefData.tabDist, tabDist);
1826 }
1827
GetPrefTabDist(int langMode)1828 int GetPrefTabDist(int langMode)
1829 {
1830 int tabDist;
1831 if (langMode == PLAIN_LANGUAGE_MODE ||
1832 LanguageModes[langMode]->tabDist == DEFAULT_TAB_DIST) {
1833 tabDist = PrefData.tabDist;
1834 } else {
1835 tabDist = LanguageModes[langMode]->tabDist;
1836 }
1837 /* Make sure that the tab distance is in range (garbage may have
1838 been entered via the command line or the X resources, causing
1839 errors later on, like division by zero). */
1840 if (tabDist <= 0) return 1;
1841 if (tabDist > MAX_EXP_CHAR_LEN) return MAX_EXP_CHAR_LEN;
1842 return tabDist;
1843 }
1844
SetPrefEmTabDist(int tabDist)1845 void SetPrefEmTabDist(int tabDist)
1846 {
1847 setIntPref(&PrefData.emTabDist, tabDist);
1848 }
1849
GetPrefEmTabDist(int langMode)1850 int GetPrefEmTabDist(int langMode)
1851 {
1852 if (langMode == PLAIN_LANGUAGE_MODE ||
1853 LanguageModes[langMode]->emTabDist == DEFAULT_EM_TAB_DIST)
1854 return PrefData.emTabDist;
1855 return LanguageModes[langMode]->emTabDist;
1856 }
1857
SetPrefInsertTabs(int state)1858 void SetPrefInsertTabs(int state)
1859 {
1860 setIntPref(&PrefData.insertTabs, state);
1861 }
1862
GetPrefInsertTabs(void)1863 int GetPrefInsertTabs(void)
1864 {
1865 return PrefData.insertTabs;
1866 }
1867
SetPrefShowMatching(ShowMatchingStyle state)1868 void SetPrefShowMatching(ShowMatchingStyle state)
1869 {
1870 setIntPref(&PrefData.showMatchingStyle, (int)state);
1871 }
1872
GetPrefShowMatching(void)1873 ShowMatchingStyle GetPrefShowMatching(void)
1874 {
1875 /*
1876 * For backwards compatibility with pre-5.2 versions, the boolean
1877 * False/True matching behavior is converted to NO_FLASH/FLASH_DELIMIT.
1878 */
1879 if (PrefData.showMatchingStyle >= N_SHOW_MATCHING_STYLES)
1880 PrefData.showMatchingStyle -= N_SHOW_MATCHING_STYLES;
1881 return (ShowMatchingStyle)(PrefData.showMatchingStyle);
1882 }
1883
SetPrefMatchSyntaxBased(int state)1884 void SetPrefMatchSyntaxBased(int state)
1885 {
1886 setIntPref(&PrefData.matchSyntaxBased, state);
1887 }
1888
GetPrefMatchSyntaxBased(void)1889 int GetPrefMatchSyntaxBased(void)
1890 {
1891 return PrefData.matchSyntaxBased;
1892 }
1893
SetPrefHighlightSyntax(Boolean state)1894 void SetPrefHighlightSyntax(Boolean state)
1895 {
1896 setIntPref(&PrefData.highlightSyntax, state);
1897 }
1898
GetPrefHighlightSyntax(void)1899 Boolean GetPrefHighlightSyntax(void)
1900 {
1901 return PrefData.highlightSyntax;
1902 }
1903
SetPrefBacklightChars(int state)1904 void SetPrefBacklightChars(int state)
1905 {
1906 setIntPref(&PrefData.backlightChars, state);
1907 }
1908
GetPrefBacklightChars(void)1909 int GetPrefBacklightChars(void)
1910 {
1911 return PrefData.backlightChars;
1912 }
1913
SetPrefBacklightCharTypes(char * types)1914 void SetPrefBacklightCharTypes(char *types)
1915 {
1916 setStringAllocPref(&PrefData.backlightCharTypes, types);
1917 }
1918
GetPrefBacklightCharTypes(void)1919 char *GetPrefBacklightCharTypes(void)
1920 {
1921 return PrefData.backlightCharTypes;
1922 }
1923
SetPrefRepositionDialogs(int state)1924 void SetPrefRepositionDialogs(int state)
1925 {
1926 setIntPref(&PrefData.repositionDialogs, state);
1927 }
1928
GetPrefRepositionDialogs(void)1929 int GetPrefRepositionDialogs(void)
1930 {
1931 return PrefData.repositionDialogs;
1932 }
1933
SetPrefAutoScroll(int state)1934 void SetPrefAutoScroll(int state)
1935 {
1936 WindowInfo *w = WindowList;
1937 int margin = state ? PrefData.autoScrollVPadding : 0;
1938
1939 setIntPref(&PrefData.autoScroll, state);
1940 for(w = WindowList; w != NULL; w = w->next)
1941 SetAutoScroll(w, margin);
1942 }
1943
GetPrefAutoScroll(void)1944 int GetPrefAutoScroll(void)
1945 {
1946 return PrefData.autoScroll;
1947 }
1948
GetVerticalAutoScroll(void)1949 int GetVerticalAutoScroll(void)
1950 {
1951 return PrefData.autoScroll ? PrefData.autoScrollVPadding : 0;
1952 }
1953
SetPrefAppendLF(int state)1954 void SetPrefAppendLF(int state)
1955 {
1956 setIntPref(&PrefData.appendLF, state);
1957 }
1958
GetPrefAppendLF(void)1959 int GetPrefAppendLF(void)
1960 {
1961 return PrefData.appendLF;
1962 }
1963
SetPrefSortOpenPrevMenu(int state)1964 void SetPrefSortOpenPrevMenu(int state)
1965 {
1966 setIntPref(&PrefData.sortOpenPrevMenu, state);
1967 }
1968
GetPrefSortOpenPrevMenu(void)1969 int GetPrefSortOpenPrevMenu(void)
1970 {
1971 return PrefData.sortOpenPrevMenu;
1972 }
1973
GetPrefTagFile(void)1974 char *GetPrefTagFile(void)
1975 {
1976 return PrefData.tagFile;
1977 }
1978
SetPrefSmartTags(int state)1979 void SetPrefSmartTags(int state)
1980 {
1981 setIntPref(&PrefData.smartTags, state);
1982 }
1983
GetPrefSmartTags(void)1984 int GetPrefSmartTags(void)
1985 {
1986 return PrefData.smartTags;
1987 }
1988
GetPrefAlwaysCheckRelTagsSpecs(void)1989 int GetPrefAlwaysCheckRelTagsSpecs(void)
1990 {
1991 return PrefData.alwaysCheckRelativeTagsSpecs;
1992 }
1993
GetPrefDelimiters(void)1994 char *GetPrefDelimiters(void)
1995 {
1996 return PrefData.delimiters;
1997 }
1998
GetPrefColorName(int index)1999 char *GetPrefColorName(int index)
2000 {
2001 return PrefData.colorNames[index];
2002 }
2003
SetPrefColorName(int index,const char * name)2004 void SetPrefColorName(int index, const char *name)
2005 {
2006 setStringPref(PrefData.colorNames[index], name);
2007 }
2008
2009 /*
2010 ** Set the font preferences using the font name (the fontList is generated
2011 ** in this call). Note that this leaks memory and server resources each
2012 ** time the default font is re-set. See note on SetFontByName in window.c
2013 ** for more information.
2014 */
SetPrefFont(char * fontName)2015 void SetPrefFont(char *fontName)
2016 {
2017 XFontStruct *font;
2018
2019 setStringPref(PrefData.fontString, fontName);
2020 font = XLoadQueryFont(TheDisplay, fontName);
2021 PrefData.fontList = font==NULL ? NULL :
2022 XmFontListCreate(font, XmSTRING_DEFAULT_CHARSET);
2023 }
2024
SetPrefBoldFont(char * fontName)2025 void SetPrefBoldFont(char *fontName)
2026 {
2027 setStringPref(PrefData.boldFontString, fontName);
2028 PrefData.boldFontStruct = XLoadQueryFont(TheDisplay, fontName);
2029 }
2030
SetPrefItalicFont(char * fontName)2031 void SetPrefItalicFont(char *fontName)
2032 {
2033 setStringPref(PrefData.italicFontString, fontName);
2034 PrefData.italicFontStruct = XLoadQueryFont(TheDisplay, fontName);
2035 }
SetPrefBoldItalicFont(char * fontName)2036 void SetPrefBoldItalicFont(char *fontName)
2037 {
2038 setStringPref(PrefData.boldItalicFontString, fontName);
2039 PrefData.boldItalicFontStruct = XLoadQueryFont(TheDisplay, fontName);
2040 }
2041
GetPrefFontName(void)2042 char *GetPrefFontName(void)
2043 {
2044 return PrefData.fontString;
2045 }
2046
GetPrefBoldFontName(void)2047 char *GetPrefBoldFontName(void)
2048 {
2049 return PrefData.boldFontString;
2050 }
2051
GetPrefItalicFontName(void)2052 char *GetPrefItalicFontName(void)
2053 {
2054 return PrefData.italicFontString;
2055 }
2056
GetPrefBoldItalicFontName(void)2057 char *GetPrefBoldItalicFontName(void)
2058 {
2059 return PrefData.boldItalicFontString;
2060 }
2061
GetPrefFontList(void)2062 XmFontList GetPrefFontList(void)
2063 {
2064 return PrefData.fontList;
2065 }
2066
GetPrefBoldFont(void)2067 XFontStruct *GetPrefBoldFont(void)
2068 {
2069 return PrefData.boldFontStruct;
2070 }
2071
GetPrefItalicFont(void)2072 XFontStruct *GetPrefItalicFont(void)
2073 {
2074 return PrefData.italicFontStruct;
2075 }
2076
GetPrefBoldItalicFont(void)2077 XFontStruct *GetPrefBoldItalicFont(void)
2078 {
2079 return PrefData.boldItalicFontStruct;
2080 }
2081
GetPrefHelpFontName(int index)2082 char *GetPrefHelpFontName(int index)
2083 {
2084 return PrefData.helpFontNames[index];
2085 }
2086
GetPrefHelpLinkColor(void)2087 char *GetPrefHelpLinkColor(void)
2088 {
2089 return PrefData.helpLinkColor;
2090 }
2091
GetPrefTooltipBgColor(void)2092 char *GetPrefTooltipBgColor(void)
2093 {
2094 return PrefData.tooltipBgColor;
2095 }
2096
SetPrefShell(const char * shell)2097 void SetPrefShell(const char *shell)
2098 {
2099 setStringPref(PrefData.shell, shell);
2100 }
2101
GetPrefShell(void)2102 const char* GetPrefShell(void)
2103 {
2104 return PrefData.shell;
2105 }
2106
GetPrefGeometry(void)2107 char *GetPrefGeometry(void)
2108 {
2109 return PrefData.geometry;
2110 }
2111
GetPrefServerName(void)2112 char *GetPrefServerName(void)
2113 {
2114 return PrefData.serverName;
2115 }
2116
GetPrefBGMenuBtn(void)2117 char *GetPrefBGMenuBtn(void)
2118 {
2119 return PrefData.bgMenuBtn;
2120 }
2121
GetPrefMaxPrevOpenFiles(void)2122 int GetPrefMaxPrevOpenFiles(void)
2123 {
2124 return PrefData.maxPrevOpenFiles;
2125 }
2126
GetPrefTypingHidesPointer(void)2127 int GetPrefTypingHidesPointer(void)
2128 {
2129 return(PrefData.typingHidesPointer);
2130 }
2131
2132 #ifdef SGI_CUSTOM
SetPrefShortMenus(int state)2133 void SetPrefShortMenus(int state)
2134 {
2135 setIntPref(&PrefData.shortMenus, state);
2136 }
2137
GetPrefShortMenus(void)2138 int GetPrefShortMenus(void)
2139 {
2140 return PrefData.shortMenus;
2141 }
2142 #endif
2143
SetPrefTitleFormat(const char * format)2144 void SetPrefTitleFormat(const char* format)
2145 {
2146 const WindowInfo* window;
2147
2148 setStringPref(PrefData.titleFormat, format);
2149
2150 /* update all windows */
2151 for (window=WindowList; window!=NULL; window=window->next) {
2152 UpdateWindowTitle(window);
2153 }
2154 }
GetPrefTitleFormat(void)2155 const char* GetPrefTitleFormat(void)
2156 {
2157 return PrefData.titleFormat;
2158 }
2159
GetPrefUndoModifiesSelection(void)2160 Boolean GetPrefUndoModifiesSelection(void)
2161 {
2162 return (Boolean)PrefData.undoModifiesSelection;
2163 }
2164
GetPrefFocusOnRaise(void)2165 Boolean GetPrefFocusOnRaise(void)
2166 {
2167 return (Boolean)PrefData.focusOnRaise;
2168 }
2169
GetPrefForceOSConversion(void)2170 Boolean GetPrefForceOSConversion(void)
2171 {
2172 return (Boolean) PrefData.forceOSConversion;
2173 }
2174
GetPrefHonorSymlinks(void)2175 Boolean GetPrefHonorSymlinks(void)
2176 {
2177 return PrefData.honorSymlinks;
2178 }
2179
GetPrefOverrideVirtKeyBindings(void)2180 int GetPrefOverrideVirtKeyBindings(void)
2181 {
2182 return PrefData.virtKeyOverride;
2183 }
2184
GetPrefTruncSubstitution(void)2185 int GetPrefTruncSubstitution(void)
2186 {
2187 return PrefData.truncSubstitution;
2188 }
2189
2190 /*
2191 ** If preferences don't get saved, ask the user on exit whether to save
2192 */
MarkPrefsChanged(void)2193 void MarkPrefsChanged(void)
2194 {
2195 PrefsHaveChanged = True;
2196 }
2197
2198 /*
2199 ** Check if preferences have changed, and if so, ask the user if he wants
2200 ** to re-save. Returns False if user requests cancelation of Exit (or whatever
2201 ** operation triggered this call to be made).
2202 */
CheckPrefsChangesSaved(Widget dialogParent)2203 int CheckPrefsChangesSaved(Widget dialogParent)
2204 {
2205 int resp;
2206
2207 if (!PrefsHaveChanged)
2208 return True;
2209
2210 resp = DialogF(DF_WARN, dialogParent, 3, "Default Preferences",
2211 ImportedFile == NULL ?
2212 "Default Preferences have changed.\n"
2213 "Save changes to NEdit preference file?" :
2214 "Default Preferences have changed. SAVING \n"
2215 "CHANGES WILL INCORPORATE ADDITIONAL\nSETTINGS FROM FILE: %s",
2216 "Save", "Don't Save", "Cancel", ImportedFile);
2217 if (resp == 2)
2218 return True;
2219 if (resp == 3)
2220 return False;
2221
2222 SaveNEditPrefs(dialogParent, True);
2223 return True;
2224 }
2225
2226 /*
2227 ** set *prefDataField to newValue, but first check if they're different
2228 ** and update PrefsHaveChanged if a preference setting has now changed.
2229 */
setIntPref(int * prefDataField,int newValue)2230 static void setIntPref(int *prefDataField, int newValue)
2231 {
2232 if (newValue != *prefDataField)
2233 PrefsHaveChanged = True;
2234 *prefDataField = newValue;
2235 }
2236
setStringPref(char * prefDataField,const char * newValue)2237 static void setStringPref(char *prefDataField, const char *newValue)
2238 {
2239 if (strcmp(prefDataField, newValue))
2240 PrefsHaveChanged = True;
2241 strcpy(prefDataField, newValue);
2242 }
2243
setStringAllocPref(char ** pprefDataField,char * newValue)2244 static void setStringAllocPref(char **pprefDataField, char *newValue)
2245 {
2246 char *p_newField;
2247
2248 /* treat empty strings as nulls */
2249 if (newValue && *newValue == '\0')
2250 newValue = NULL;
2251 if (*pprefDataField && **pprefDataField == '\0')
2252 *pprefDataField = NULL; /* assume statically alloc'ed "" */
2253
2254 /* check changes */
2255 if (!*pprefDataField && !newValue)
2256 return;
2257 else if (!*pprefDataField && newValue)
2258 PrefsHaveChanged = True;
2259 else if (*pprefDataField && !newValue)
2260 PrefsHaveChanged = True;
2261 else if (strcmp(*pprefDataField, newValue))
2262 PrefsHaveChanged = True;
2263
2264 /* get rid of old preference */
2265 NEditFree(*pprefDataField);
2266
2267 /* store new preference */
2268 if (newValue) {
2269 p_newField = NEditStrdup(newValue);
2270 }
2271 *pprefDataField = newValue;
2272 }
2273
2274 /*
2275 ** Set the language mode for the window, update the menu and trigger language
2276 ** mode specific actions (turn on/off highlighting). If forceNewDefaults is
2277 ** true, re-establish default settings for language-specific preferences
2278 ** regardless of whether they were previously set by the user.
2279 */
SetLanguageMode(WindowInfo * window,int mode,int forceNewDefaults)2280 void SetLanguageMode(WindowInfo *window, int mode, int forceNewDefaults)
2281 {
2282 Widget menu;
2283 WidgetList items;
2284 int n;
2285 Cardinal nItems;
2286 void *userData;
2287
2288 /* Do mode-specific actions */
2289 reapplyLanguageMode(window, mode, forceNewDefaults);
2290
2291 /* Select the correct language mode in the sub-menu */
2292 if (IsTopDocument(window)) {
2293 XtVaGetValues(window->langModeCascade, XmNsubMenuId, &menu, NULL);
2294 XtVaGetValues(menu, XmNchildren, &items, XmNnumChildren, &nItems, NULL);
2295 for (n=0; n<(int)nItems; n++) {
2296 XtVaGetValues(items[n], XmNuserData, &userData, NULL);
2297 XmToggleButtonSetState(items[n], (int)(intptr_t)userData == mode, False);
2298 }
2299 }
2300 }
2301
2302 /*
2303 ** Lookup a language mode by name, returning the index of the language
2304 ** mode or PLAIN_LANGUAGE_MODE if the name is not found
2305 */
FindLanguageMode(const char * languageName)2306 int FindLanguageMode(const char *languageName)
2307 {
2308 int i;
2309
2310 /* Compare each language mode to the one we were presented */
2311 for (i=0; i<NLanguageModes; i++)
2312 if (!strcmp(languageName, LanguageModes[i]->name))
2313 return i;
2314
2315 return PLAIN_LANGUAGE_MODE;
2316 }
2317
2318
2319 /*
2320 ** Apply language mode matching criteria and set window->languageMode to
2321 ** the appropriate mode for the current file, trigger language mode
2322 ** specific actions (turn on/off highlighting), and update the language
2323 ** mode menu item. If forceNewDefaults is true, re-establish default
2324 ** settings for language-specific preferences regardless of whether
2325 ** they were previously set by the user.
2326 */
DetermineLanguageMode(WindowInfo * window,int forceNewDefaults)2327 void DetermineLanguageMode(WindowInfo *window, int forceNewDefaults)
2328 {
2329 SetLanguageMode(window, matchLanguageMode(window), forceNewDefaults);
2330 }
2331
2332 /*
2333 ** Return the name of the current language mode set in "window", or NULL
2334 ** if the current mode is "Plain".
2335 */
LanguageModeName(int mode)2336 char *LanguageModeName(int mode)
2337 {
2338 if (mode == PLAIN_LANGUAGE_MODE)
2339 return NULL;
2340 else
2341 return LanguageModes[mode]->name;
2342 }
2343
2344 /*
2345 ** Get the set of word delimiters for the language mode set in the current
2346 ** window. Returns NULL when no language mode is set (it would be easy to
2347 ** return the default delimiter set when the current language mode is "Plain",
2348 ** or the mode doesn't have its own delimiters, but this is usually used
2349 ** to supply delimiters for RE searching, and ExecRE can skip compiling a
2350 ** delimiter table when delimiters is NULL).
2351 */
GetWindowDelimiters(const WindowInfo * window)2352 char *GetWindowDelimiters(const WindowInfo *window)
2353 {
2354 if (window->languageMode == PLAIN_LANGUAGE_MODE)
2355 return NULL;
2356 else
2357 return LanguageModes[window->languageMode]->delimiters;
2358 }
2359
2360 /*
2361 ** Put up a dialog for selecting a custom initial window size
2362 */
RowColumnPrefDialog(Widget parent)2363 void RowColumnPrefDialog(Widget parent)
2364 {
2365 Widget form, selBox, topLabel;
2366 Arg selBoxArgs[2];
2367 XmString s1;
2368
2369 XtSetArg(selBoxArgs[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
2370 XtSetArg(selBoxArgs[1], XmNautoUnmanage, False);
2371 selBox = CreatePromptDialog(parent, "customSize", selBoxArgs, 2);
2372 XtAddCallback(selBox, XmNokCallback, (XtCallbackProc)sizeOKCB, NULL);
2373 XtAddCallback(selBox, XmNcancelCallback, (XtCallbackProc)sizeCancelCB,NULL);
2374 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_TEXT));
2375 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_SELECTION_LABEL));
2376 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_HELP_BUTTON));
2377 XtVaSetValues(XtParent(selBox), XmNtitle, "Initial Window Size", NULL);
2378
2379 form = XtVaCreateManagedWidget("form", xmFormWidgetClass, selBox, NULL);
2380
2381 topLabel = XtVaCreateManagedWidget("topLabel", xmLabelGadgetClass, form,
2382 XmNlabelString, s1=MKSTRING(
2383 "Enter desired size in rows\nand columns of characters:"), NULL);
2384 XmStringFree(s1);
2385
2386 RowText = XtVaCreateManagedWidget("rows", xmTextWidgetClass, form,
2387 XmNcolumns, 3,
2388 XmNtopAttachment, XmATTACH_WIDGET,
2389 XmNleftAttachment, XmATTACH_POSITION,
2390 XmNrightAttachment, XmATTACH_POSITION,
2391 XmNtopWidget, topLabel,
2392 XmNleftPosition, 5,
2393 XmNrightPosition, 45, NULL);
2394 RemapDeleteKey(RowText);
2395
2396 XtVaCreateManagedWidget("xLabel", xmLabelGadgetClass, form,
2397 XmNlabelString, s1=MKSTRING("x"),
2398 XmNtopAttachment, XmATTACH_WIDGET,
2399 XmNleftAttachment, XmATTACH_POSITION,
2400 XmNrightAttachment, XmATTACH_POSITION,
2401 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2402 XmNtopWidget, topLabel,
2403 XmNbottomWidget, RowText,
2404 XmNleftPosition, 45,
2405 XmNrightPosition, 55, NULL);
2406 XmStringFree(s1);
2407
2408 ColText = XtVaCreateManagedWidget("cols", xmTextWidgetClass, form,
2409 XmNcolumns, 3,
2410 XmNtopAttachment, XmATTACH_WIDGET,
2411 XmNleftAttachment, XmATTACH_POSITION,
2412 XmNrightAttachment, XmATTACH_POSITION,
2413 XmNtopWidget, topLabel,
2414 XmNleftPosition, 55,
2415 XmNrightPosition, 95, NULL);
2416 RemapDeleteKey(ColText);
2417
2418 /* put up dialog and wait for user to press ok or cancel */
2419 DoneWithSizeDialog = False;
2420 ManageDialogCenteredOnPointer(selBox);
2421 while (!DoneWithSizeDialog)
2422 {
2423 XEvent event;
2424 XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
2425 ServerDispatchEvent(&event);
2426 }
2427
2428 XtDestroyWidget(selBox);
2429 }
2430
sizeOKCB(Widget w,XtPointer clientData,XtPointer callData)2431 static void sizeOKCB(Widget w, XtPointer clientData, XtPointer callData)
2432 {
2433 int rowValue, colValue, stat;
2434
2435 /* get the values that the user entered and make sure they're ok */
2436 stat = GetIntTextWarn(RowText, &rowValue, "number of rows", True);
2437 if (stat != TEXT_READ_OK)
2438 return;
2439 stat = GetIntTextWarn(ColText, &colValue, "number of columns", True);
2440 if (stat != TEXT_READ_OK)
2441 return;
2442
2443 /* set the corresponding preferences and dismiss the dialog */
2444 SetPrefRows(rowValue);
2445 SetPrefCols(colValue);
2446 DoneWithSizeDialog = True;
2447 }
2448
sizeCancelCB(Widget w,XtPointer clientData,XtPointer callData)2449 static void sizeCancelCB(Widget w, XtPointer clientData, XtPointer callData)
2450 {
2451 DoneWithSizeDialog = True;
2452 }
2453
2454 /*
2455 ** Present the user a dialog for setting tab related preferences, either as
2456 ** defaults, or for a specific window (pass "forWindow" as NULL to set default
2457 ** preference, or a window to set preferences for the specific window.
2458 */
TabsPrefDialog(Widget parent,WindowInfo * forWindow)2459 void TabsPrefDialog(Widget parent, WindowInfo *forWindow)
2460 {
2461 Widget form, selBox;
2462 Arg selBoxArgs[2];
2463 XmString s1;
2464 int emulate, emTabDist, useTabs, tabDist;
2465
2466 XtSetArg(selBoxArgs[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
2467 XtSetArg(selBoxArgs[1], XmNautoUnmanage, False);
2468 selBox = CreatePromptDialog(parent, "customSize", selBoxArgs, 2);
2469 XtAddCallback(selBox, XmNokCallback, (XtCallbackProc)tabsOKCB, NULL);
2470 XtAddCallback(selBox, XmNcancelCallback, (XtCallbackProc)tabsCancelCB,NULL);
2471 XtAddCallback(selBox, XmNhelpCallback, (XtCallbackProc)tabsHelpCB,NULL);
2472 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_TEXT));
2473 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_SELECTION_LABEL));
2474 XtVaSetValues(XtParent(selBox), XmNtitle, "Tabs", NULL);
2475
2476 form = XtVaCreateManagedWidget("form", xmFormWidgetClass, selBox, NULL);
2477
2478 TabDistText = XtVaCreateManagedWidget("tabDistText", xmTextWidgetClass,
2479 form, XmNcolumns, 7,
2480 XmNtopAttachment, XmATTACH_FORM,
2481 XmNrightAttachment, XmATTACH_FORM, NULL);
2482 RemapDeleteKey(TabDistText);
2483 XtVaCreateManagedWidget("tabDistLabel", xmLabelGadgetClass, form,
2484 XmNlabelString, s1=XmStringCreateSimple(
2485 "Tab spacing (for hardware tab characters)"),
2486 XmNmnemonic, 'T',
2487 XmNuserData, TabDistText,
2488 XmNtopAttachment, XmATTACH_FORM,
2489 XmNleftAttachment, XmATTACH_FORM,
2490 XmNrightAttachment, XmATTACH_WIDGET,
2491 XmNrightWidget, TabDistText,
2492 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2493 XmNbottomWidget, TabDistText, NULL);
2494 XmStringFree(s1);
2495
2496 EmTabText = XtVaCreateManagedWidget("emTabText", xmTextWidgetClass, form,
2497 XmNcolumns, 7,
2498 XmNtopAttachment, XmATTACH_WIDGET,
2499 XmNtopWidget, TabDistText,
2500 XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET,
2501 XmNrightWidget, TabDistText, NULL);
2502 RemapDeleteKey(EmTabText);
2503 EmTabLabel = XtVaCreateManagedWidget("emTabLabel", xmLabelGadgetClass, form,
2504 XmNlabelString, s1=XmStringCreateSimple("Emulated tab spacing"),
2505 XmNmnemonic, 's',
2506 XmNuserData, EmTabText,
2507 XmNtopAttachment, XmATTACH_WIDGET,
2508 XmNtopWidget, TabDistText,
2509 XmNrightAttachment, XmATTACH_WIDGET,
2510 XmNrightWidget, EmTabText,
2511 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2512 XmNbottomWidget, EmTabText, NULL);
2513 XmStringFree(s1);
2514 EmTabToggle = XtVaCreateManagedWidget("emTabToggle",
2515 xmToggleButtonWidgetClass, form, XmNlabelString,
2516 s1=XmStringCreateSimple("Emulate tabs"),
2517 XmNmnemonic, 'E',
2518 XmNtopAttachment, XmATTACH_WIDGET,
2519 XmNtopWidget, TabDistText,
2520 XmNleftAttachment, XmATTACH_FORM,
2521 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2522 XmNbottomWidget, EmTabText, NULL);
2523 XmStringFree(s1);
2524 XtAddCallback(EmTabToggle, XmNvalueChangedCallback, emTabsCB, NULL);
2525 UseTabsToggle = XtVaCreateManagedWidget("useTabsToggle",
2526 xmToggleButtonWidgetClass, form,
2527 XmNlabelString, s1=XmStringCreateSimple(
2528 "Use tab characters in padding and emulated tabs"),
2529 XmNmnemonic, 'U',
2530 XmNtopAttachment, XmATTACH_WIDGET,
2531 XmNtopWidget, EmTabText,
2532 XmNtopOffset, 5,
2533 XmNleftAttachment, XmATTACH_FORM, NULL);
2534 XmStringFree(s1);
2535
2536 /* Set default values */
2537 if (forWindow == NULL) {
2538 emTabDist = GetPrefEmTabDist(PLAIN_LANGUAGE_MODE);
2539 useTabs = GetPrefInsertTabs();
2540 tabDist = GetPrefTabDist(PLAIN_LANGUAGE_MODE);
2541 } else {
2542 XtVaGetValues(forWindow->textArea, textNemulateTabs, &emTabDist, NULL);
2543 useTabs = forWindow->buffer->useTabs;
2544 tabDist = BufGetTabDistance(forWindow->buffer);
2545 }
2546 emulate = emTabDist != 0;
2547 SetIntText(TabDistText, tabDist);
2548 XmToggleButtonSetState(EmTabToggle, emulate, True);
2549 if (emulate)
2550 SetIntText(EmTabText, emTabDist);
2551 XmToggleButtonSetState(UseTabsToggle, useTabs, False);
2552 XtSetSensitive(EmTabText, emulate);
2553 XtSetSensitive(EmTabLabel, emulate);
2554
2555 /* Handle mnemonic selection of buttons and focus to dialog */
2556 AddDialogMnemonicHandler(form, FALSE);
2557
2558 /* Set the widget to get focus */
2559 #if XmVersion >= 1002
2560 XtVaSetValues(form, XmNinitialFocus, TabDistText, NULL);
2561 #endif
2562
2563 /* put up dialog and wait for user to press ok or cancel */
2564 TabsDialogForWindow = forWindow;
2565 DoneWithTabsDialog = False;
2566 ManageDialogCenteredOnPointer(selBox);
2567 while (!DoneWithTabsDialog)
2568 {
2569 XEvent event;
2570 XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
2571 ServerDispatchEvent(&event);
2572 }
2573
2574 XtDestroyWidget(selBox);
2575 }
2576
tabsOKCB(Widget w,XtPointer clientData,XtPointer callData)2577 static void tabsOKCB(Widget w, XtPointer clientData, XtPointer callData)
2578 {
2579 int emulate, useTabs, stat, tabDist, emTabDist;
2580 WindowInfo *window = TabsDialogForWindow;
2581
2582 /* get the values that the user entered and make sure they're ok */
2583 emulate = XmToggleButtonGetState(EmTabToggle);
2584 useTabs = XmToggleButtonGetState(UseTabsToggle);
2585 stat = GetIntTextWarn(TabDistText, &tabDist, "tab spacing", True);
2586 if (stat != TEXT_READ_OK)
2587 return;
2588
2589 if (tabDist <= 0 || tabDist > MAX_EXP_CHAR_LEN)
2590 {
2591 DialogF(DF_WARN, TabDistText, 1, "Tab Spacing",
2592 "Tab spacing out of range", "OK");
2593 return;
2594 }
2595
2596 if (emulate) {
2597 stat = GetIntTextWarn(EmTabText, &emTabDist, "emulated tab spacing",True);
2598 if (stat != TEXT_READ_OK)
2599 return;
2600
2601 if (emTabDist <= 0 || tabDist >= 1000)
2602 {
2603 DialogF(DF_WARN, EmTabText, 1, "Tab Spacing",
2604 "Emulated tab spacing out of range", "OK");
2605 return;
2606 }
2607 } else
2608 emTabDist = 0;
2609
2610 #ifdef SGI_CUSTOM
2611 /* Ask the user about saving as a default preference */
2612 if (TabsDialogForWindow != NULL) {
2613 int setDefault;
2614 if (!shortPrefToDefault(window->shell, "Tab Settings", &setDefault)) {
2615 DoneWithTabsDialog = True;
2616 return;
2617 }
2618 if (setDefault) {
2619 SetPrefTabDist(tabDist);
2620 SetPrefEmTabDist(emTabDist);
2621 SetPrefInsertTabs(useTabs);
2622 SaveNEditPrefs(window->shell, GetPrefShortMenus());
2623 }
2624 }
2625 #endif
2626
2627 /* Set the value in either the requested window or default preferences */
2628 if (TabsDialogForWindow == NULL) {
2629 SetPrefTabDist(tabDist);
2630 SetPrefEmTabDist(emTabDist);
2631 SetPrefInsertTabs(useTabs);
2632 } else {
2633 char *params[1];
2634 char numStr[25];
2635
2636 params[0] = numStr;
2637 sprintf(numStr, "%d", tabDist);
2638 XtCallActionProc(window->textArea, "set_tab_dist", NULL, params, 1);
2639 params[0] = numStr;
2640 sprintf(numStr, "%d", emTabDist);
2641 XtCallActionProc(window->textArea, "set_em_tab_dist", NULL, params, 1);
2642 params[0] = numStr;
2643 sprintf(numStr, "%d", useTabs);
2644 XtCallActionProc(window->textArea, "set_use_tabs", NULL, params, 1);
2645 /*
2646 setTabDist(window, tabDist);
2647 setEmTabDist(window, emTabDist);
2648 window->buffer->useTabs = useTabs;
2649 */
2650 }
2651 DoneWithTabsDialog = True;
2652 }
2653
tabsCancelCB(Widget w,XtPointer clientData,XtPointer callData)2654 static void tabsCancelCB(Widget w, XtPointer clientData, XtPointer callData)
2655 {
2656 DoneWithTabsDialog = True;
2657 }
2658
tabsHelpCB(Widget w,XtPointer clientData,XtPointer callData)2659 static void tabsHelpCB(Widget w, XtPointer clientData, XtPointer callData)
2660 {
2661 Help(HELP_TABS_DIALOG);
2662 }
2663
emTabsCB(Widget w,XtPointer clientData,XtPointer callData)2664 static void emTabsCB(Widget w, XtPointer clientData, XtPointer callData)
2665 {
2666 int state = XmToggleButtonGetState(w);
2667
2668 XtSetSensitive(EmTabLabel, state);
2669 XtSetSensitive(EmTabText, state);
2670 }
2671
2672 /*
2673 ** Present the user a dialog for setting wrap margin.
2674 */
WrapMarginDialog(Widget parent,WindowInfo * forWindow)2675 void WrapMarginDialog(Widget parent, WindowInfo *forWindow)
2676 {
2677 Widget form, selBox;
2678 Arg selBoxArgs[2];
2679 XmString s1;
2680 int margin;
2681
2682 XtSetArg(selBoxArgs[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
2683 XtSetArg(selBoxArgs[1], XmNautoUnmanage, False);
2684 selBox = CreatePromptDialog(parent, "wrapMargin", selBoxArgs, 2);
2685 XtAddCallback(selBox, XmNokCallback, (XtCallbackProc)wrapOKCB, NULL);
2686 XtAddCallback(selBox, XmNcancelCallback, (XtCallbackProc)wrapCancelCB,NULL);
2687 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_TEXT));
2688 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_SELECTION_LABEL));
2689 XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_HELP_BUTTON));
2690 XtVaSetValues(XtParent(selBox), XmNtitle, "Wrap Margin", NULL);
2691
2692 form = XtVaCreateManagedWidget("form", xmFormWidgetClass, selBox, NULL);
2693
2694 WrapWindowToggle = XtVaCreateManagedWidget("wrapWindowToggle",
2695 xmToggleButtonWidgetClass, form, XmNlabelString,
2696 s1=XmStringCreateSimple("Wrap and Fill at width of window"),
2697 XmNmnemonic, 'W',
2698 XmNtopAttachment, XmATTACH_FORM,
2699 XmNleftAttachment, XmATTACH_FORM, NULL);
2700 XmStringFree(s1);
2701 XtAddCallback(WrapWindowToggle, XmNvalueChangedCallback, wrapWindowCB,NULL);
2702 WrapText = XtVaCreateManagedWidget("wrapText", xmTextWidgetClass, form,
2703 XmNcolumns, 5,
2704 XmNtopAttachment, XmATTACH_WIDGET,
2705 XmNtopWidget, WrapWindowToggle,
2706 XmNrightAttachment, XmATTACH_FORM, NULL);
2707 RemapDeleteKey(WrapText);
2708 WrapTextLabel = XtVaCreateManagedWidget("wrapMarginLabel",
2709 xmLabelGadgetClass, form,
2710 XmNlabelString, s1=XmStringCreateSimple(
2711 "Margin for Wrap and Fill"),
2712 XmNmnemonic, 'M',
2713 XmNuserData, WrapText,
2714 XmNtopAttachment, XmATTACH_WIDGET,
2715 XmNtopWidget, WrapWindowToggle,
2716 XmNleftAttachment, XmATTACH_FORM,
2717 XmNrightAttachment, XmATTACH_WIDGET,
2718 XmNrightWidget, WrapText,
2719 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
2720 XmNbottomWidget, WrapText, NULL);
2721 XmStringFree(s1);
2722
2723 /* Set default value */
2724 if (forWindow == NULL)
2725 margin = GetPrefWrapMargin();
2726 else
2727 XtVaGetValues(forWindow->textArea, textNwrapMargin, &margin, NULL);
2728 XmToggleButtonSetState(WrapWindowToggle, margin==0, True);
2729 if (margin != 0)
2730 SetIntText(WrapText, margin);
2731 XtSetSensitive(WrapText, margin!=0);
2732 XtSetSensitive(WrapTextLabel, margin!=0);
2733
2734 /* Handle mnemonic selection of buttons and focus to dialog */
2735 AddDialogMnemonicHandler(form, FALSE);
2736
2737 /* put up dialog and wait for user to press ok or cancel */
2738 WrapDialogForWindow = forWindow;
2739 DoneWithWrapDialog = False;
2740 ManageDialogCenteredOnPointer(selBox);
2741 while (!DoneWithWrapDialog)
2742 {
2743 XEvent event;
2744 XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
2745 ServerDispatchEvent(&event);
2746 }
2747
2748 XtDestroyWidget(selBox);
2749 }
2750
wrapOKCB(Widget w,XtPointer clientData,XtPointer callData)2751 static void wrapOKCB(Widget w, XtPointer clientData, XtPointer callData)
2752 {
2753 int wrapAtWindow, margin, stat;
2754 WindowInfo *window = WrapDialogForWindow;
2755
2756 /* get the values that the user entered and make sure they're ok */
2757 wrapAtWindow = XmToggleButtonGetState(WrapWindowToggle);
2758 if (wrapAtWindow)
2759 margin = 0;
2760 else {
2761 stat = GetIntTextWarn(WrapText, &margin, "wrap Margin", True);
2762 if (stat != TEXT_READ_OK)
2763 return;
2764
2765 if (margin <= 0 || margin >= 1000)
2766 {
2767 DialogF(DF_WARN, WrapText, 1, "Wrap Margin",
2768 "Wrap margin out of range", "OK");
2769 return;
2770 }
2771
2772 }
2773
2774 #ifdef SGI_CUSTOM
2775 /* Ask the user about saving as a default preference */
2776 if (WrapDialogForWindow != NULL) {
2777 int setDefault;
2778 if (!shortPrefToDefault(window->shell, "Wrap Margin Settings",
2779 &setDefault)) {
2780 DoneWithWrapDialog = True;
2781 return;
2782 }
2783 if (setDefault) {
2784 SetPrefWrapMargin(margin);
2785 SaveNEditPrefs(window->shell, GetPrefShortMenus());
2786 }
2787 }
2788 #endif
2789
2790 /* Set the value in either the requested window or default preferences */
2791 if (WrapDialogForWindow == NULL)
2792 SetPrefWrapMargin(margin);
2793 else {
2794 char *params[1];
2795 char marginStr[25];
2796 sprintf(marginStr, "%d", margin);
2797 params[0] = marginStr;
2798 XtCallActionProc(window->textArea, "set_wrap_margin", NULL, params, 1);
2799 }
2800 DoneWithWrapDialog = True;
2801 }
2802
wrapCancelCB(Widget w,XtPointer clientData,XtPointer callData)2803 static void wrapCancelCB(Widget w, XtPointer clientData, XtPointer callData)
2804 {
2805 DoneWithWrapDialog = True;
2806 }
2807
wrapWindowCB(Widget w,XtPointer clientData,XtPointer callData)2808 static void wrapWindowCB(Widget w, XtPointer clientData, XtPointer callData)
2809 {
2810 int wrapAtWindow = XmToggleButtonGetState(w);
2811
2812 XtSetSensitive(WrapTextLabel, !wrapAtWindow);
2813 XtSetSensitive(WrapText, !wrapAtWindow);
2814 }
2815
2816 /*
2817 ** Create and show a dialog for selecting the shell
2818 */
SelectShellDialog(Widget parent,WindowInfo * forWindow)2819 void SelectShellDialog(Widget parent, WindowInfo* forWindow)
2820 {
2821 Widget shellSelDialog;
2822 Arg shellSelDialogArgs[2];
2823 XmString label;
2824
2825 /* Set up the dialog. */
2826 XtSetArg(shellSelDialogArgs[0],
2827 XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
2828 XtSetArg(shellSelDialogArgs[1], XmNautoUnmanage, False);
2829 shellSelDialog = CreatePromptDialog(parent, "shellSelDialog",
2830 shellSelDialogArgs, 2);
2831
2832 /* Fix dialog to our liking. */
2833 XtVaSetValues(XtParent(shellSelDialog), XmNtitle, "Command Shell", NULL);
2834 XtAddCallback(shellSelDialog, XmNokCallback, (XtCallbackProc) shellSelOKCB,
2835 shellSelDialog);
2836 XtAddCallback(shellSelDialog, XmNcancelCallback,
2837 (XtCallbackProc) shellSelCancelCB, NULL);
2838 XtUnmanageChild(XmSelectionBoxGetChild(shellSelDialog, XmDIALOG_HELP_BUTTON));
2839 label = XmStringCreateLocalized("Enter shell path:");
2840 XtVaSetValues(shellSelDialog, XmNselectionLabelString, label, NULL);
2841 XmStringFree(label);
2842
2843 /* Set dialog's text to the current setting. */
2844 XmTextSetString(XmSelectionBoxGetChild(shellSelDialog, XmDIALOG_TEXT),
2845 (char*) GetPrefShell());
2846
2847 DoneWithShellSelDialog = False;
2848
2849 /* Show dialog and wait until the user made her choice. */
2850 ManageDialogCenteredOnPointer(shellSelDialog);
2851 while (!DoneWithShellSelDialog) {
2852 XEvent event;
2853 XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
2854 ServerDispatchEvent(&event);
2855 }
2856
2857 XtDestroyWidget(shellSelDialog);
2858 }
2859
shellSelOKCB(Widget widget,XtPointer clientData,XtPointer callData)2860 static void shellSelOKCB(Widget widget, XtPointer clientData,
2861 XtPointer callData)
2862 {
2863 Widget shellSelDialog = (Widget) clientData;
2864 String shellName = (char*)NEditMalloc(MAXPATHLEN);
2865 struct stat attribute;
2866 unsigned dlgResult;
2867
2868 /* Leave with a warning if the dialog is not up. */
2869 if (!XtIsRealized(shellSelDialog)) {
2870 fprintf(stderr, "nedit: Callback shellSelOKCB() illegally called.\n");
2871 return;
2872 }
2873
2874 /* Get the string that the user entered and make sure it's ok. */
2875 shellName = XmTextGetString(XmSelectionBoxGetChild(shellSelDialog,
2876 XmDIALOG_TEXT));
2877
2878 if (-1 == stat(shellName, &attribute)) {
2879 dlgResult = DialogF(DF_WARN, shellSelDialog, 2, "Command Shell",
2880 "The selected shell is not available.\nDo you want to use it anyway?",
2881 "OK", "Cancel");
2882 if (1 != dlgResult) {
2883 return;
2884 }
2885 }
2886
2887 SetPrefShell(shellName);
2888 NEditFree(shellName);
2889
2890 DoneWithShellSelDialog = True;
2891 }
2892
shellSelCancelCB(Widget widgget,XtPointer clientData,XtPointer callData)2893 static void shellSelCancelCB(Widget widgget, XtPointer clientData,
2894 XtPointer callData)
2895 {
2896 DoneWithShellSelDialog = True;
2897 }
2898
2899 /*
2900 ** Present a dialog for editing language mode information
2901 */
EditLanguageModes(void)2902 void EditLanguageModes(void)
2903 {
2904 #define LIST_RIGHT 40
2905 #define LEFT_MARGIN_POS 1
2906 #define RIGHT_MARGIN_POS 99
2907 #define H_MARGIN 5
2908 Widget form, nameLbl, topLbl, extLbl, recogLbl, delimitLbl, defTipsLbl;
2909 Widget okBtn, applyBtn, closeBtn;
2910 Widget overrideFrame, overrideForm, delimitForm;
2911 Widget tabForm, tabLbl, indentBox, wrapBox;
2912 XmString s1;
2913 int i, ac;
2914 Arg args[20];
2915
2916 /* if the dialog is already displayed, just pop it to the top and return */
2917 if (LMDialog.shell != NULL) {
2918 RaiseDialogWindow(LMDialog.shell);
2919 return;
2920 }
2921
2922 LMDialog.languageModeList = (languageModeRec **)NEditMalloc(
2923 sizeof(languageModeRec *) * MAX_LANGUAGE_MODES);
2924 for (i=0; i<NLanguageModes; i++)
2925 LMDialog.languageModeList[i] = copyLanguageModeRec(LanguageModes[i]);
2926 LMDialog.nLanguageModes = NLanguageModes;
2927
2928 /* Create a form widget in an application shell */
2929 ac = 0;
2930 XtSetArg(args[ac], XmNdeleteResponse, XmDO_NOTHING); ac++;
2931 XtSetArg(args[ac], XmNiconName, "NEdit Language Modes"); ac++;
2932 XtSetArg(args[ac], XmNtitle, "Language Modes"); ac++;
2933 LMDialog.shell = CreateWidget(TheAppShell, "langModes",
2934 topLevelShellWidgetClass, args, ac);
2935 AddSmallIcon(LMDialog.shell);
2936 form = XtVaCreateManagedWidget("editLanguageModes", xmFormWidgetClass,
2937 LMDialog.shell, XmNautoUnmanage, False,
2938 XmNresizePolicy, XmRESIZE_NONE, NULL);
2939 XtAddCallback(form, XmNdestroyCallback, lmDestroyCB, NULL);
2940 AddMotifCloseCallback(LMDialog.shell, lmCloseCB, NULL);
2941
2942 topLbl = XtVaCreateManagedWidget("topLabel", xmLabelGadgetClass, form,
2943 XmNlabelString, s1=MKSTRING(
2944 "To modify the properties of an existing language mode, select the name from\n\
2945 the list on the left. To add a new language, select \"New\" from the list."),
2946 XmNmnemonic, 'N',
2947 XmNtopAttachment, XmATTACH_POSITION,
2948 XmNtopPosition, 2,
2949 XmNleftAttachment, XmATTACH_POSITION,
2950 XmNleftPosition, LEFT_MARGIN_POS,
2951 XmNrightAttachment, XmATTACH_POSITION,
2952 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
2953 XmStringFree(s1);
2954
2955 nameLbl = XtVaCreateManagedWidget("nameLbl", xmLabelGadgetClass, form,
2956 XmNlabelString, s1=XmStringCreateSimple("Name"),
2957 XmNmnemonic, 'm',
2958 XmNalignment, XmALIGNMENT_BEGINNING,
2959 XmNleftAttachment, XmATTACH_POSITION,
2960 XmNleftPosition, LIST_RIGHT,
2961 XmNtopAttachment, XmATTACH_WIDGET,
2962 XmNtopOffset, H_MARGIN,
2963 XmNtopWidget, topLbl, NULL);
2964 XmStringFree(s1);
2965
2966 LMDialog.nameW = XtVaCreateManagedWidget("name", xmTextWidgetClass, form,
2967 XmNcolumns, 15,
2968 XmNleftAttachment, XmATTACH_POSITION,
2969 XmNleftPosition, LIST_RIGHT,
2970 XmNtopAttachment, XmATTACH_WIDGET,
2971 XmNtopWidget, nameLbl,
2972 XmNrightAttachment, XmATTACH_POSITION,
2973 XmNrightPosition, (RIGHT_MARGIN_POS + LIST_RIGHT)/2, NULL);
2974 RemapDeleteKey(LMDialog.nameW);
2975 XtVaSetValues(nameLbl, XmNuserData, LMDialog.nameW, NULL);
2976
2977 extLbl = XtVaCreateManagedWidget("extLbl", xmLabelGadgetClass, form,
2978 XmNlabelString,
2979 s1=XmStringCreateSimple("File extensions (separate w/ space)"),
2980 XmNmnemonic, 'F',
2981 XmNalignment, XmALIGNMENT_BEGINNING,
2982 XmNleftAttachment, XmATTACH_POSITION,
2983 XmNleftPosition, LIST_RIGHT,
2984 XmNtopAttachment, XmATTACH_WIDGET,
2985 XmNtopOffset, H_MARGIN,
2986 XmNtopWidget, LMDialog.nameW, NULL);
2987 XmStringFree(s1);
2988
2989 LMDialog.extW = XtVaCreateManagedWidget("ext", xmTextWidgetClass, form,
2990 XmNleftAttachment, XmATTACH_POSITION,
2991 XmNleftPosition, LIST_RIGHT,
2992 XmNtopAttachment, XmATTACH_WIDGET,
2993 XmNtopWidget, extLbl,
2994 XmNrightAttachment, XmATTACH_POSITION,
2995 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
2996 RemapDeleteKey(LMDialog.extW);
2997 XtVaSetValues(extLbl, XmNuserData, LMDialog.extW, NULL);
2998
2999 recogLbl = XtVaCreateManagedWidget("recogLbl", xmLabelGadgetClass, form,
3000 XmNlabelString, s1=MKSTRING(
3001 "Recognition regular expression (applied to first 200\n\
3002 characters of file to determine type from content)"),
3003 XmNalignment, XmALIGNMENT_BEGINNING,
3004 XmNmnemonic, 'R',
3005 XmNleftAttachment, XmATTACH_POSITION,
3006 XmNleftPosition, LIST_RIGHT,
3007 XmNtopAttachment, XmATTACH_WIDGET,
3008 XmNtopOffset, H_MARGIN,
3009 XmNtopWidget, LMDialog.extW, NULL);
3010 XmStringFree(s1);
3011
3012 LMDialog.recogW = XtVaCreateManagedWidget("recog", xmTextWidgetClass, form,
3013 XmNleftAttachment, XmATTACH_POSITION,
3014 XmNleftPosition, LIST_RIGHT,
3015 XmNtopAttachment, XmATTACH_WIDGET,
3016 XmNtopWidget, recogLbl,
3017 XmNrightAttachment, XmATTACH_POSITION,
3018 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
3019 RemapDeleteKey(LMDialog.recogW);
3020 XtVaSetValues(recogLbl, XmNuserData, LMDialog.recogW, NULL);
3021
3022 defTipsLbl = XtVaCreateManagedWidget("defTipsLbl", xmLabelGadgetClass, form,
3023 XmNlabelString, s1=MKSTRING(
3024 "Default calltips file(s) (separate w/colons)"),
3025 XmNalignment, XmALIGNMENT_BEGINNING,
3026 XmNmnemonic, 'c',
3027 XmNleftAttachment, XmATTACH_POSITION,
3028 XmNleftPosition, LIST_RIGHT,
3029 XmNtopAttachment, XmATTACH_WIDGET,
3030 XmNtopOffset, H_MARGIN,
3031 XmNtopWidget, LMDialog.recogW, NULL);
3032 XmStringFree(s1);
3033
3034 LMDialog.defTipsW = XtVaCreateManagedWidget("defTips", xmTextWidgetClass,
3035 form,
3036 XmNleftAttachment, XmATTACH_POSITION,
3037 XmNleftPosition, LIST_RIGHT,
3038 XmNtopAttachment, XmATTACH_WIDGET,
3039 XmNtopWidget, defTipsLbl,
3040 XmNrightAttachment, XmATTACH_POSITION,
3041 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
3042 RemapDeleteKey(LMDialog.defTipsW);
3043 XtVaSetValues(defTipsLbl, XmNuserData, LMDialog.defTipsW, NULL);
3044
3045 okBtn = XtVaCreateManagedWidget("ok", xmPushButtonWidgetClass, form,
3046 XmNlabelString, s1=XmStringCreateSimple("OK"),
3047 XmNmarginWidth, BUTTON_WIDTH_MARGIN,
3048 XmNleftAttachment, XmATTACH_POSITION,
3049 XmNleftPosition, 10,
3050 XmNrightAttachment, XmATTACH_POSITION,
3051 XmNrightPosition, 30,
3052 XmNbottomAttachment, XmATTACH_POSITION,
3053 XmNbottomPosition, 99, NULL);
3054 XtAddCallback(okBtn, XmNactivateCallback, lmOkCB, NULL);
3055 XmStringFree(s1);
3056
3057 applyBtn = XtVaCreateManagedWidget("apply", xmPushButtonWidgetClass, form,
3058 XmNlabelString, s1=XmStringCreateSimple("Apply"),
3059 XmNmnemonic, 'A',
3060 XmNleftAttachment, XmATTACH_POSITION,
3061 XmNleftPosition, 40,
3062 XmNrightAttachment, XmATTACH_POSITION,
3063 XmNrightPosition, 60,
3064 XmNbottomAttachment, XmATTACH_POSITION,
3065 XmNbottomPosition, 99, NULL);
3066 XtAddCallback(applyBtn, XmNactivateCallback, lmApplyCB, NULL);
3067 XmStringFree(s1);
3068
3069 closeBtn = XtVaCreateManagedWidget("close",xmPushButtonWidgetClass,form,
3070 XmNlabelString, s1=XmStringCreateSimple("Close"),
3071 XmNleftAttachment, XmATTACH_POSITION,
3072 XmNleftPosition, 70,
3073 XmNrightAttachment, XmATTACH_POSITION,
3074 XmNrightPosition, 90,
3075 XmNbottomAttachment, XmATTACH_POSITION,
3076 XmNbottomPosition, 99, NULL);
3077 XtAddCallback(closeBtn, XmNactivateCallback, lmCloseCB, NULL);
3078 XmStringFree(s1);
3079
3080 overrideFrame = XtVaCreateManagedWidget("overrideFrame",
3081 xmFrameWidgetClass, form,
3082 XmNleftAttachment, XmATTACH_POSITION,
3083 XmNleftPosition, LEFT_MARGIN_POS,
3084 XmNrightAttachment, XmATTACH_POSITION,
3085 XmNrightPosition, RIGHT_MARGIN_POS,
3086 XmNbottomAttachment, XmATTACH_WIDGET,
3087 XmNbottomWidget, closeBtn,
3088 XmNbottomOffset, H_MARGIN, NULL);
3089 overrideForm = XtVaCreateManagedWidget("overrideForm", xmFormWidgetClass,
3090 overrideFrame, NULL);
3091 XtVaCreateManagedWidget("overrideLbl", xmLabelGadgetClass, overrideFrame,
3092 XmNlabelString, s1=XmStringCreateSimple("Override Defaults"),
3093 XmNchildType, XmFRAME_TITLE_CHILD,
3094 XmNchildHorizontalAlignment, XmALIGNMENT_CENTER, NULL);
3095 XmStringFree(s1);
3096
3097 delimitForm = XtVaCreateManagedWidget("delimitForm", xmFormWidgetClass,
3098 overrideForm,
3099 XmNleftAttachment, XmATTACH_POSITION,
3100 XmNleftPosition, LEFT_MARGIN_POS,
3101 XmNtopAttachment, XmATTACH_FORM,
3102 XmNtopOffset, H_MARGIN,
3103 XmNrightAttachment, XmATTACH_POSITION,
3104 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
3105 delimitLbl = XtVaCreateManagedWidget("delimitLbl", xmLabelGadgetClass,
3106 delimitForm,
3107 XmNlabelString, s1=XmStringCreateSimple("Word delimiters"),
3108 XmNmnemonic, 'W',
3109 XmNleftAttachment, XmATTACH_FORM,
3110 XmNtopAttachment, XmATTACH_FORM,
3111 XmNbottomAttachment, XmATTACH_FORM, NULL);
3112 XmStringFree(s1);
3113 LMDialog.delimitW = XtVaCreateManagedWidget("delimit", xmTextWidgetClass,
3114 delimitForm,
3115 XmNtopAttachment, XmATTACH_FORM,
3116 XmNleftAttachment, XmATTACH_WIDGET,
3117 XmNleftWidget, delimitLbl,
3118 XmNrightAttachment, XmATTACH_FORM,
3119 XmNbottomAttachment, XmATTACH_FORM, NULL);
3120 RemapDeleteKey(LMDialog.delimitW);
3121 XtVaSetValues(delimitLbl, XmNuserData, LMDialog.delimitW, NULL);
3122
3123 tabForm = XtVaCreateManagedWidget("tabForm", xmFormWidgetClass,
3124 overrideForm,
3125 XmNleftAttachment, XmATTACH_POSITION,
3126 XmNleftPosition, LEFT_MARGIN_POS,
3127 XmNtopAttachment, XmATTACH_WIDGET,
3128 XmNtopWidget, delimitForm,
3129 XmNtopOffset, H_MARGIN,
3130 XmNrightAttachment, XmATTACH_POSITION,
3131 XmNrightPosition, RIGHT_MARGIN_POS, NULL);
3132 tabLbl = XtVaCreateManagedWidget("tabLbl", xmLabelGadgetClass, tabForm,
3133 XmNlabelString, s1=XmStringCreateSimple(
3134 "Alternative hardware tab spacing"),
3135 XmNmnemonic, 't',
3136 XmNleftAttachment, XmATTACH_FORM,
3137 XmNtopAttachment, XmATTACH_FORM,
3138 XmNbottomAttachment, XmATTACH_FORM, NULL);
3139 XmStringFree(s1);
3140 LMDialog.tabW = XtVaCreateManagedWidget("delimit", xmTextWidgetClass,
3141 tabForm,
3142 XmNcolumns, 3,
3143 XmNtopAttachment, XmATTACH_FORM,
3144 XmNleftAttachment, XmATTACH_WIDGET,
3145 XmNleftWidget, tabLbl,
3146 XmNbottomAttachment, XmATTACH_FORM, NULL);
3147 RemapDeleteKey(LMDialog.tabW);
3148 XtVaSetValues(tabLbl, XmNuserData, LMDialog.tabW, NULL);
3149 LMDialog.emTabW = XtVaCreateManagedWidget("delimit", xmTextWidgetClass,
3150 tabForm,
3151 XmNcolumns, 3,
3152 XmNtopAttachment, XmATTACH_FORM,
3153 XmNrightAttachment, XmATTACH_FORM,
3154 XmNbottomAttachment, XmATTACH_FORM, NULL);
3155 RemapDeleteKey(LMDialog.emTabW);
3156 XtVaCreateManagedWidget("emTabLbl", xmLabelGadgetClass, tabForm,
3157 XmNlabelString,
3158 s1=XmStringCreateSimple("Alternative emulated tab spacing"),
3159 XmNalignment, XmALIGNMENT_END,
3160 XmNmnemonic, 'e',
3161 XmNuserData, LMDialog.emTabW,
3162 XmNleftAttachment, XmATTACH_WIDGET,
3163 XmNleftWidget, LMDialog.tabW,
3164 XmNrightAttachment, XmATTACH_WIDGET,
3165 XmNrightWidget, LMDialog.emTabW,
3166 XmNtopAttachment, XmATTACH_FORM,
3167 XmNbottomAttachment, XmATTACH_FORM, NULL);
3168 XmStringFree(s1);
3169
3170 indentBox = XtVaCreateManagedWidget("indentBox", xmRowColumnWidgetClass,
3171 overrideForm,
3172 XmNorientation, XmHORIZONTAL,
3173 XmNpacking, XmPACK_TIGHT,
3174 XmNradioBehavior, True,
3175 XmNleftAttachment, XmATTACH_POSITION,
3176 XmNleftPosition, LEFT_MARGIN_POS,
3177 XmNtopAttachment, XmATTACH_WIDGET,
3178 XmNtopWidget, tabForm,
3179 XmNtopOffset, H_MARGIN, NULL);
3180 LMDialog.defaultIndentW = XtVaCreateManagedWidget("defaultIndent",
3181 xmToggleButtonWidgetClass, indentBox,
3182 XmNset, True,
3183 XmNmarginHeight, 0,
3184 XmNlabelString, s1=XmStringCreateSimple("Default indent style"),
3185 XmNmnemonic, 'D', NULL);
3186 XmStringFree(s1);
3187 LMDialog.noIndentW = XtVaCreateManagedWidget("noIndent",
3188 xmToggleButtonWidgetClass, indentBox,
3189 XmNmarginHeight, 0,
3190 XmNlabelString, s1=XmStringCreateSimple("No automatic indent"),
3191 XmNmnemonic, 'N', NULL);
3192 XmStringFree(s1);
3193 LMDialog.autoIndentW = XtVaCreateManagedWidget("autoIndent",
3194 xmToggleButtonWidgetClass, indentBox,
3195 XmNmarginHeight, 0,
3196 XmNlabelString, s1=XmStringCreateSimple("Auto-indent"),
3197 XmNmnemonic, 'A', NULL);
3198 XmStringFree(s1);
3199 LMDialog.smartIndentW = XtVaCreateManagedWidget("smartIndent",
3200 xmToggleButtonWidgetClass, indentBox,
3201 XmNmarginHeight, 0,
3202 XmNlabelString, s1=XmStringCreateSimple("Smart-indent"),
3203 XmNmnemonic, 'S', NULL);
3204 XmStringFree(s1);
3205
3206 wrapBox = XtVaCreateManagedWidget("wrapBox", xmRowColumnWidgetClass,
3207 overrideForm,
3208 XmNorientation, XmHORIZONTAL,
3209 XmNpacking, XmPACK_TIGHT,
3210 XmNradioBehavior, True,
3211 XmNleftAttachment, XmATTACH_POSITION,
3212 XmNleftPosition, LEFT_MARGIN_POS,
3213 XmNtopAttachment, XmATTACH_WIDGET,
3214 XmNtopWidget, indentBox,
3215 XmNtopOffset, H_MARGIN,
3216 XmNbottomAttachment, XmATTACH_FORM,
3217 XmNbottomOffset, H_MARGIN, NULL);
3218 LMDialog.defaultWrapW = XtVaCreateManagedWidget("defaultWrap",
3219 xmToggleButtonWidgetClass, wrapBox,
3220 XmNset, True,
3221 XmNmarginHeight, 0,
3222 XmNlabelString, s1=XmStringCreateSimple("Default wrap style"),
3223 XmNmnemonic, 'D', NULL);
3224 XmStringFree(s1);
3225 LMDialog.noWrapW = XtVaCreateManagedWidget("noWrap",
3226 xmToggleButtonWidgetClass, wrapBox,
3227 XmNmarginHeight, 0,
3228 XmNlabelString, s1=XmStringCreateSimple("No wrapping"),
3229 XmNmnemonic, 'N', NULL);
3230 XmStringFree(s1);
3231 LMDialog.newlineWrapW = XtVaCreateManagedWidget("newlineWrap",
3232 xmToggleButtonWidgetClass, wrapBox,
3233 XmNmarginHeight, 0,
3234 XmNlabelString, s1=XmStringCreateSimple("Auto newline wrap"),
3235 XmNmnemonic, 'A', NULL);
3236 XmStringFree(s1);
3237 LMDialog.contWrapW = XtVaCreateManagedWidget("contWrap",
3238 xmToggleButtonWidgetClass, wrapBox,
3239 XmNmarginHeight, 0,
3240 XmNlabelString, s1=XmStringCreateSimple("Continuous wrap"),
3241 XmNmnemonic, 'C', NULL);
3242 XmStringFree(s1);
3243
3244 XtVaCreateManagedWidget("stretchForm", xmFormWidgetClass, form,
3245 XmNtopAttachment, XmATTACH_WIDGET,
3246 XmNtopWidget, LMDialog.defTipsW,
3247 XmNleftAttachment, XmATTACH_POSITION,
3248 XmNleftPosition, LIST_RIGHT,
3249 XmNrightAttachment, XmATTACH_POSITION,
3250 XmNrightPosition, RIGHT_MARGIN_POS,
3251 XmNbottomAttachment, XmATTACH_WIDGET,
3252 XmNbottomWidget, overrideFrame,
3253 XmNbottomOffset, H_MARGIN*2, NULL);
3254
3255 ac = 0;
3256 XtSetArg(args[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
3257 XtSetArg(args[ac], XmNtopOffset, H_MARGIN); ac++;
3258 XtSetArg(args[ac], XmNtopWidget, topLbl); ac++;
3259 XtSetArg(args[ac], XmNleftAttachment, XmATTACH_POSITION); ac++;
3260 XtSetArg(args[ac], XmNleftPosition, LEFT_MARGIN_POS); ac++;
3261 XtSetArg(args[ac], XmNrightAttachment, XmATTACH_POSITION); ac++;
3262 XtSetArg(args[ac], XmNrightPosition, LIST_RIGHT-1); ac++;
3263 XtSetArg(args[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
3264 XtSetArg(args[ac], XmNbottomWidget, overrideFrame); ac++;
3265 XtSetArg(args[ac], XmNbottomOffset, H_MARGIN*2); ac++;
3266 LMDialog.managedListW = CreateManagedList(form, "list", args, ac,
3267 (void **)LMDialog.languageModeList, &LMDialog.nLanguageModes,
3268 MAX_LANGUAGE_MODES, 15, lmGetDisplayedCB, NULL, lmSetDisplayedCB,
3269 NULL, lmFreeItemCB);
3270 AddDeleteConfirmCB(LMDialog.managedListW, lmDeleteConfirmCB, NULL);
3271 XtVaSetValues(topLbl, XmNuserData, LMDialog.managedListW, NULL);
3272
3273 /* Set initial default button */
3274 XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
3275 XtVaSetValues(form, XmNcancelButton, closeBtn, NULL);
3276
3277 /* Handle mnemonic selection of buttons and focus to dialog */
3278 AddDialogMnemonicHandler(form, FALSE);
3279
3280 /* Realize all of the widgets in the new dialog */
3281 RealizeWithoutForcingPosition(LMDialog.shell);
3282 }
3283
lmDestroyCB(Widget w,XtPointer clientData,XtPointer callData)3284 static void lmDestroyCB(Widget w, XtPointer clientData, XtPointer callData)
3285 {
3286 int i;
3287
3288 for (i=0; i<LMDialog.nLanguageModes; i++)
3289 freeLanguageModeRec(LMDialog.languageModeList[i]);
3290 NEditFree(LMDialog.languageModeList);
3291 }
3292
lmOkCB(Widget w,XtPointer clientData,XtPointer callData)3293 static void lmOkCB(Widget w, XtPointer clientData, XtPointer callData)
3294 {
3295 if (!updateLMList())
3296 return;
3297
3298 /* pop down and destroy the dialog */
3299 XtDestroyWidget(LMDialog.shell);
3300 LMDialog.shell = NULL;
3301 }
3302
lmApplyCB(Widget w,XtPointer clientData,XtPointer callData)3303 static void lmApplyCB(Widget w, XtPointer clientData, XtPointer callData)
3304 {
3305 updateLMList();
3306 }
3307
lmCloseCB(Widget w,XtPointer clientData,XtPointer callData)3308 static void lmCloseCB(Widget w, XtPointer clientData, XtPointer callData)
3309 {
3310 /* pop down and destroy the dialog */
3311 XtDestroyWidget(LMDialog.shell);
3312 LMDialog.shell = NULL;
3313 }
3314
lmDeleteConfirmCB(int itemIndex,void * cbArg)3315 static int lmDeleteConfirmCB(int itemIndex, void *cbArg)
3316 {
3317 int i;
3318
3319 /* Allow duplicate names to be deleted regardless of dependencies */
3320 for (i=0; i<LMDialog.nLanguageModes; i++)
3321 if (i != itemIndex && !strcmp(LMDialog.languageModeList[i]->name,
3322 LMDialog.languageModeList[itemIndex]->name))
3323 return True;
3324
3325 /* don't allow deletion if data will be lost */
3326 if (LMHasHighlightPatterns(LMDialog.languageModeList[itemIndex]->name))
3327 {
3328 DialogF(DF_WARN, LMDialog.shell, 1, "Patterns exist",
3329 "This language mode has syntax highlighting\n"
3330 "patterns defined. Please delete the patterns\n"
3331 "first, in Preferences -> Default Settings ->\n"
3332 "Syntax Highlighting, before proceeding here.", "OK");
3333 return False;
3334 }
3335
3336 /* don't allow deletion if data will be lost */
3337 if (LMHasSmartIndentMacros(LMDialog.languageModeList[itemIndex]->name))
3338 {
3339 DialogF(DF_WARN, LMDialog.shell, 1, "Smart Indent Macros exist",
3340 "This language mode has smart indent macros\n"
3341 "defined. Please delete the macros first,\n"
3342 "in Preferences -> Default Settings ->\n"
3343 "Auto Indent -> Program Smart Indent,\n"
3344 "before proceeding here.", "OK");
3345 return False;
3346 }
3347
3348 return True;
3349 }
3350
3351 /*
3352 ** Apply the changes that the user has made in the language modes dialog to the
3353 ** stored language mode information for this NEdit session (the data array
3354 ** LanguageModes)
3355 */
updateLMList(void)3356 static int updateLMList(void)
3357 {
3358 WindowInfo *window;
3359 int oldLanguageMode;
3360 char *oldModeName, *newDelimiters;
3361 int i, j;
3362
3363 /* Get the current contents of the dialog fields */
3364 if (!UpdateManagedList(LMDialog.managedListW, True))
3365 return False;
3366
3367 /* Fix up language mode indices in all open windows (which may change
3368 if the currently selected mode is deleted or has changed position),
3369 and update word delimiters */
3370 for (window=WindowList; window!=NULL; window=window->next) {
3371 if (window->languageMode != PLAIN_LANGUAGE_MODE) {
3372 oldLanguageMode = window->languageMode;
3373 oldModeName = LanguageModes[window->languageMode]->name;
3374 window->languageMode = PLAIN_LANGUAGE_MODE;
3375 for (i=0; i<LMDialog.nLanguageModes; i++) {
3376 if (!strcmp(oldModeName, LMDialog.languageModeList[i]->name)) {
3377 newDelimiters = LMDialog.languageModeList[i]->delimiters;
3378 if (newDelimiters == NULL)
3379 newDelimiters = GetPrefDelimiters();
3380 XtVaSetValues(window->textArea, textNwordDelimiters,
3381 newDelimiters, NULL);
3382 for (j=0; j<window->nPanes; j++)
3383 XtVaSetValues(window->textPanes[j],
3384 textNwordDelimiters, newDelimiters, NULL);
3385 /* don't forget to adapt the LM stored within the user menu cache */
3386 if (window->userMenuCache->umcLanguageMode == oldLanguageMode)
3387 window->userMenuCache->umcLanguageMode = i;
3388 if (window->userBGMenuCache.ubmcLanguageMode == oldLanguageMode)
3389 window->userBGMenuCache.ubmcLanguageMode = i;
3390 /* update the language mode of this window (document) */
3391 window->languageMode = i;
3392 break;
3393 }
3394 }
3395 }
3396 }
3397
3398 /* If there were any name changes, re-name dependent highlight patterns
3399 and smart-indent macros and fix up the weird rename-format names */
3400 for (i=0; i<LMDialog.nLanguageModes; i++) {
3401 if (strchr(LMDialog.languageModeList[i]->name, ':') != NULL) {
3402 char *newName = strrchr(LMDialog.languageModeList[i]->name, ':')+1;
3403 *strchr(LMDialog.languageModeList[i]->name, ':') = '\0';
3404 RenameHighlightPattern(LMDialog.languageModeList[i]->name, newName);
3405 RenameSmartIndentMacros(LMDialog.languageModeList[i]->name, newName);
3406 memmove(LMDialog.languageModeList[i]->name, newName,
3407 strlen(newName) + 1);
3408 ChangeManagedListData(LMDialog.managedListW);
3409 }
3410 }
3411
3412 /* Replace the old language mode list with the new one from the dialog */
3413 for (i=0; i<NLanguageModes; i++)
3414 freeLanguageModeRec(LanguageModes[i]);
3415 for (i=0; i<LMDialog.nLanguageModes; i++)
3416 LanguageModes[i] = copyLanguageModeRec(LMDialog.languageModeList[i]);
3417 NLanguageModes = LMDialog.nLanguageModes;
3418
3419 /* Update user menu info to update language mode dependencies of
3420 user menu items */
3421 UpdateUserMenuInfo();
3422
3423 /* Update the menus in the window menu bars and load any needed
3424 calltips files */
3425 for (window=WindowList; window!=NULL; window=window->next) {
3426 updateLanguageModeSubmenu(window);
3427 if (window->languageMode != PLAIN_LANGUAGE_MODE &&
3428 LanguageModes[window->languageMode]->defTipsFile != NULL)
3429 AddTagsFile(LanguageModes[window->languageMode]->defTipsFile, TIP);
3430 /* cache user menus: Rebuild all user menus of this window */
3431 RebuildAllMenus(window);
3432 }
3433
3434 /* If a syntax highlighting dialog is up, update its menu */
3435 UpdateLanguageModeMenu();
3436 /* The same for the smart indent macro dialog */
3437 UpdateLangModeMenuSmartIndent();
3438 /* Note that preferences have been changed */
3439 MarkPrefsChanged();
3440
3441 return True;
3442 }
3443
lmGetDisplayedCB(void * oldItem,int explicitRequest,int * abort,void * cbArg)3444 static void *lmGetDisplayedCB(void *oldItem, int explicitRequest, int *abort,
3445 void *cbArg)
3446 {
3447 languageModeRec *lm, *oldLM = (languageModeRec *)oldItem;
3448 char *tempName;
3449 int i, nCopies, oldLen;
3450
3451 /* If the dialog is currently displaying the "new" entry and the
3452 fields are empty, that's just fine */
3453 if (oldItem == NULL && lmDialogEmpty())
3454 return NULL;
3455
3456 /* Read the data the user has entered in the dialog fields */
3457 lm = readLMDialogFields(True);
3458
3459 /* If there was a name change of a non-duplicate language mode, modify the
3460 name to the weird format of: ":old name:new name". This signals that a
3461 name change is necessary in lm dependent data such as highlight
3462 patterns. Duplicate language modes may be re-named at will, since no
3463 data will be lost due to the name change. */
3464 if (lm != NULL && oldLM != NULL && strcmp(oldLM->name, lm->name)) {
3465 nCopies = 0;
3466 for (i=0; i<LMDialog.nLanguageModes; i++)
3467 if (!strcmp(oldLM->name, LMDialog.languageModeList[i]->name))
3468 nCopies++;
3469 if (nCopies <= 1) {
3470 oldLen = strchr(oldLM->name, ':') == NULL ? strlen(oldLM->name) :
3471 strchr(oldLM->name, ':') - oldLM->name;
3472 tempName = (char*)NEditMalloc(oldLen + strlen(lm->name) + 2);
3473 strncpy(tempName, oldLM->name, oldLen);
3474 sprintf(&tempName[oldLen], ":%s", lm->name);
3475 NEditFree(lm->name);
3476 lm->name = tempName;
3477 }
3478 }
3479
3480 /* If there are no problems reading the data, just return it */
3481 if (lm != NULL)
3482 return (void *)lm;
3483
3484 /* If there are problems, and the user didn't ask for the fields to be
3485 read, give more warning */
3486 if (!explicitRequest)
3487 {
3488 if (DialogF(DF_WARN, LMDialog.shell, 2, "Discard Language Mode",
3489 "Discard incomplete entry\nfor current language mode?", "Keep",
3490 "Discard") == 2)
3491 {
3492 return oldItem == NULL
3493 ? NULL
3494 : (void *)copyLanguageModeRec((languageModeRec *)oldItem);
3495 }
3496 }
3497
3498 /* Do readLMDialogFields again without "silent" mode to display warning */
3499 lm = readLMDialogFields(False);
3500 *abort = True;
3501 return NULL;
3502 }
3503
lmSetDisplayedCB(void * item,void * cbArg)3504 static void lmSetDisplayedCB(void *item, void *cbArg)
3505 {
3506 languageModeRec *lm = (languageModeRec *)item;
3507 char *extStr;
3508
3509 if (item == NULL) {
3510 XmTextSetString(LMDialog.nameW, "");
3511 XmTextSetString(LMDialog.extW, "");
3512 XmTextSetString(LMDialog.recogW, "");
3513 XmTextSetString(LMDialog.defTipsW, "");
3514 XmTextSetString(LMDialog.delimitW, "");
3515 XmTextSetString(LMDialog.tabW, "");
3516 XmTextSetString(LMDialog.emTabW, "");
3517 RadioButtonChangeState(LMDialog.defaultIndentW, True, True);
3518 RadioButtonChangeState(LMDialog.defaultWrapW, True, True);
3519 } else {
3520 XmTextSetString(LMDialog.nameW, strchr(lm->name, ':') == NULL ?
3521 lm->name : strchr(lm->name, ':')+1);
3522 extStr = createExtString(lm->extensions, lm->nExtensions);
3523 XmTextSetString(LMDialog.extW, extStr);
3524 NEditFree(extStr);
3525 XmTextSetString(LMDialog.recogW, lm->recognitionExpr);
3526 XmTextSetString(LMDialog.defTipsW, lm->defTipsFile);
3527 XmTextSetString(LMDialog.delimitW, lm->delimiters);
3528 if (lm->tabDist == DEFAULT_TAB_DIST)
3529 XmTextSetString(LMDialog.tabW, "");
3530 else
3531 SetIntText(LMDialog.tabW, lm->tabDist);
3532 if (lm->emTabDist == DEFAULT_EM_TAB_DIST)
3533 XmTextSetString(LMDialog.emTabW, "");
3534 else
3535 SetIntText(LMDialog.emTabW, lm->emTabDist);
3536 RadioButtonChangeState(LMDialog.defaultIndentW,
3537 lm->indentStyle == DEFAULT_INDENT, False);
3538 RadioButtonChangeState(LMDialog.noIndentW,
3539 lm->indentStyle == NO_AUTO_INDENT, False);
3540 RadioButtonChangeState(LMDialog.autoIndentW,
3541 lm->indentStyle == AUTO_INDENT, False);
3542 RadioButtonChangeState(LMDialog.smartIndentW,
3543 lm->indentStyle == SMART_INDENT, False);
3544 RadioButtonChangeState(LMDialog.defaultWrapW,
3545 lm->wrapStyle == DEFAULT_WRAP, False);
3546 RadioButtonChangeState(LMDialog.noWrapW,
3547 lm->wrapStyle == NO_WRAP, False);
3548 RadioButtonChangeState(LMDialog.newlineWrapW,
3549 lm->wrapStyle == NEWLINE_WRAP, False);
3550 RadioButtonChangeState(LMDialog.contWrapW,
3551 lm->wrapStyle == CONTINUOUS_WRAP, False);
3552 }
3553 }
3554
lmFreeItemCB(void * item)3555 static void lmFreeItemCB(void *item)
3556 {
3557 freeLanguageModeRec((languageModeRec *)item);
3558 }
3559
freeLanguageModeRec(languageModeRec * lm)3560 static void freeLanguageModeRec(languageModeRec *lm)
3561 {
3562 int i;
3563
3564 NEditFree(lm->name);
3565 NEditFree(lm->recognitionExpr);
3566 NEditFree(lm->defTipsFile);
3567 NEditFree(lm->delimiters);
3568 for (i=0; i<lm->nExtensions; i++)
3569 NEditFree(lm->extensions[i]);
3570 NEditFree(lm->extensions);
3571 NEditFree(lm);
3572 }
3573
3574 /*
3575 ** Copy a languageModeRec data structure and all of the allocated data it contains
3576 */
copyLanguageModeRec(languageModeRec * lm)3577 static languageModeRec *copyLanguageModeRec(languageModeRec *lm)
3578 {
3579 languageModeRec *newLM;
3580 int i;
3581
3582 newLM = (languageModeRec *)NEditMalloc(sizeof(languageModeRec));
3583 newLM->name = NEditStrdup(lm->name);
3584 newLM->nExtensions = lm->nExtensions;
3585 newLM->extensions = (char **)NEditMalloc(sizeof(char *) * lm->nExtensions);
3586 for (i=0; i<lm->nExtensions; i++) {
3587 newLM->extensions[i] = NEditStrdup(lm->extensions[i]);
3588 }
3589 if (lm->recognitionExpr == NULL)
3590 newLM->recognitionExpr = NULL;
3591 else {
3592 newLM->recognitionExpr = NEditStrdup(lm->recognitionExpr);
3593 }
3594 if (lm->defTipsFile == NULL)
3595 newLM->defTipsFile = NULL;
3596 else {
3597 newLM->defTipsFile = NEditStrdup(lm->defTipsFile);
3598 }
3599 if (lm->delimiters == NULL)
3600 newLM->delimiters = NULL;
3601 else {
3602 newLM->delimiters = NEditStrdup(lm->delimiters);
3603 }
3604 newLM->wrapStyle = lm->wrapStyle;
3605 newLM->indentStyle = lm->indentStyle;
3606 newLM->tabDist = lm->tabDist;
3607 newLM->emTabDist = lm->emTabDist;
3608 return newLM;
3609 }
3610
3611 /*
3612 ** Read the fields in the language modes dialog and create a languageModeRec data
3613 ** structure reflecting the current state of the selected language mode in the dialog.
3614 ** If any of the information is incorrect or missing, display a warning dialog and
3615 ** return NULL. Passing "silent" as True, suppresses the warning dialogs.
3616 */
readLMDialogFields(int silent)3617 static languageModeRec *readLMDialogFields(int silent)
3618 {
3619 languageModeRec *lm;
3620 regexp *compiledRE;
3621 char *compileMsg, *extStr, *extPtr;
3622
3623 /* Allocate a language mode structure to return, set unread fields to
3624 empty so everything can be freed on errors by freeLanguageModeRec */
3625 lm = (languageModeRec *)NEditMalloc(sizeof(languageModeRec));
3626 lm->nExtensions = 0;
3627 lm->recognitionExpr = NULL;
3628 lm->defTipsFile = NULL;
3629 lm->delimiters = NULL;
3630
3631 /* read the name field */
3632 lm->name = ReadSymbolicFieldTextWidget(LMDialog.nameW,
3633 "language mode name", silent);
3634 if (lm->name == NULL) {
3635 NEditFree(lm);
3636 return NULL;
3637 }
3638
3639 if (*lm->name == '\0')
3640 {
3641 if (!silent)
3642 {
3643 DialogF(DF_WARN, LMDialog.shell, 1, "Language Mode Name",
3644 "Please specify a name\nfor the language mode", "OK");
3645 XmProcessTraversal(LMDialog.nameW, XmTRAVERSE_CURRENT);
3646 }
3647 freeLanguageModeRec(lm);
3648 return NULL;
3649 }
3650
3651 /* read the extension list field */
3652 extStr = extPtr = XmTextGetString(LMDialog.extW);
3653 lm->extensions = readExtensionList(&extPtr, &lm->nExtensions);
3654 NEditFree(extStr);
3655
3656 /* read recognition expression */
3657 lm->recognitionExpr = XmTextGetString(LMDialog.recogW);
3658 if (*lm->recognitionExpr == '\0') {
3659 NEditFree(lm->recognitionExpr);
3660 lm->recognitionExpr = NULL;
3661 } else
3662 {
3663 compiledRE = CompileRE(lm->recognitionExpr, &compileMsg, REDFLT_STANDARD);
3664
3665 if (compiledRE == NULL)
3666 {
3667 if (!silent)
3668 {
3669 DialogF(DF_WARN, LMDialog.shell, 1, "Regex",
3670 "Recognition expression:\n%s", "OK", compileMsg);
3671 XmProcessTraversal(LMDialog.recogW, XmTRAVERSE_CURRENT);
3672 }
3673 NEditFree(compiledRE);
3674 freeLanguageModeRec(lm);
3675 return NULL;
3676 }
3677
3678 NEditFree(compiledRE);
3679 }
3680
3681 /* Read the default calltips file for the language mode */
3682 lm->defTipsFile = XmTextGetString(LMDialog.defTipsW);
3683 if (*lm->defTipsFile == '\0') {
3684 /* Empty string */
3685 NEditFree(lm->defTipsFile);
3686 lm->defTipsFile = NULL;
3687 } else {
3688 /* Ensure that AddTagsFile will work */
3689 if (AddTagsFile(lm->defTipsFile, TIP) == FALSE) {
3690 if (!silent)
3691 {
3692 DialogF(DF_WARN, LMDialog.shell, 1, "Error reading Calltips",
3693 "Can't read default calltips file(s):\n \"%s\"\n",
3694 "OK", lm->defTipsFile);
3695 XmProcessTraversal(LMDialog.recogW, XmTRAVERSE_CURRENT);
3696 }
3697 freeLanguageModeRec(lm);
3698 return NULL;
3699 } else
3700 if (DeleteTagsFile(lm->defTipsFile, TIP, False) == FALSE)
3701 fprintf(stderr, "nedit: Internal error: Trouble deleting "
3702 "calltips file(s):\n \"%s\"\n", lm->defTipsFile);
3703 }
3704
3705 /* read tab spacing field */
3706 if (TextWidgetIsBlank(LMDialog.tabW))
3707 lm->tabDist = DEFAULT_TAB_DIST;
3708 else {
3709 if (GetIntTextWarn(LMDialog.tabW, &lm->tabDist, "tab spacing", False)
3710 != TEXT_READ_OK) {
3711 freeLanguageModeRec(lm);
3712 return NULL;
3713 }
3714
3715 if (lm->tabDist <= 0 || lm->tabDist > 100)
3716 {
3717 if (!silent)
3718 {
3719 DialogF(DF_WARN, LMDialog.shell, 1, "Invalid Tab Spacing",
3720 "Invalid tab spacing: %d", "OK", lm->tabDist);
3721 XmProcessTraversal(LMDialog.tabW, XmTRAVERSE_CURRENT);
3722 }
3723 freeLanguageModeRec(lm);
3724 return NULL;
3725 }
3726 }
3727
3728 /* read emulated tab field */
3729 if (TextWidgetIsBlank(LMDialog.emTabW))
3730 {
3731 lm->emTabDist = DEFAULT_EM_TAB_DIST;
3732 } else
3733 {
3734 if (GetIntTextWarn(LMDialog.emTabW, &lm->emTabDist,
3735 "emulated tab spacing", False) != TEXT_READ_OK)
3736 {
3737 freeLanguageModeRec(lm);
3738 return NULL;
3739 }
3740
3741 if (lm->emTabDist < 0 || lm->emTabDist > 100)
3742 {
3743 if (!silent)
3744 {
3745 DialogF(DF_WARN, LMDialog.shell, 1, "Invalid Tab Spacing",
3746 "Invalid emulated tab spacing: %d", "OK",
3747 lm->emTabDist);
3748 XmProcessTraversal(LMDialog.emTabW, XmTRAVERSE_CURRENT);
3749 }
3750 freeLanguageModeRec(lm);
3751 return NULL;
3752 }
3753 }
3754
3755 /* read delimiters string */
3756 lm->delimiters = XmTextGetString(LMDialog.delimitW);
3757 if (*lm->delimiters == '\0') {
3758 NEditFree(lm->delimiters);
3759 lm->delimiters = NULL;
3760 }
3761
3762 /* read indent style */
3763 if (XmToggleButtonGetState(LMDialog.noIndentW))
3764 lm->indentStyle = NO_AUTO_INDENT;
3765 else if (XmToggleButtonGetState(LMDialog.autoIndentW))
3766 lm->indentStyle = AUTO_INDENT;
3767 else if (XmToggleButtonGetState(LMDialog.smartIndentW))
3768 lm->indentStyle = SMART_INDENT;
3769 else
3770 lm->indentStyle = DEFAULT_INDENT;
3771
3772 /* read wrap style */
3773 if (XmToggleButtonGetState(LMDialog.noWrapW))
3774 lm->wrapStyle = NO_WRAP;
3775 else if (XmToggleButtonGetState(LMDialog.newlineWrapW))
3776 lm->wrapStyle = NEWLINE_WRAP;
3777 else if (XmToggleButtonGetState(LMDialog.contWrapW))
3778 lm->wrapStyle = CONTINUOUS_WRAP;
3779 else
3780 lm->wrapStyle = DEFAULT_WRAP;
3781
3782 return lm;
3783 }
3784
3785 /*
3786 ** Return True if the language mode dialog fields are blank (unchanged from the "New"
3787 ** language mode state).
3788 */
lmDialogEmpty(void)3789 static int lmDialogEmpty(void)
3790 {
3791 return TextWidgetIsBlank(LMDialog.nameW) &&
3792 TextWidgetIsBlank(LMDialog.extW) &&
3793 TextWidgetIsBlank(LMDialog.recogW) &&
3794 TextWidgetIsBlank(LMDialog.delimitW) &&
3795 TextWidgetIsBlank(LMDialog.tabW) &&
3796 TextWidgetIsBlank(LMDialog.emTabW) &&
3797 XmToggleButtonGetState(LMDialog.defaultIndentW) &&
3798 XmToggleButtonGetState(LMDialog.defaultWrapW);
3799 }
3800
3801 /*
3802 ** Present a dialog for changing fonts (primary, and for highlighting).
3803 */
ChooseFonts(WindowInfo * window,int forWindow)3804 void ChooseFonts(WindowInfo *window, int forWindow)
3805 {
3806 #define MARGIN_SPACING 10
3807 #define BTN_TEXT_OFFSET 3
3808 Widget form, primaryLbl, primaryBtn, italicLbl, italicBtn;
3809 Widget boldLbl, boldBtn, boldItalicLbl, boldItalicBtn;
3810 Widget primaryFrame, primaryForm, highlightFrame, highlightForm;
3811 Widget okBtn, applyBtn, cancelBtn;
3812 fontDialog *fd;
3813 XmString s1;
3814 int ac;
3815 Arg args[20];
3816
3817 /* if the dialog is already displayed, just pop it to the top and return */
3818 if (window->fontDialog != NULL) {
3819 RaiseDialogWindow(((fontDialog *)window->fontDialog)->shell);
3820 return;
3821 }
3822
3823 /* Create a structure for keeping track of dialog state */
3824 fd = (fontDialog *)NEditMalloc(sizeof(fontDialog));
3825 fd->window = window;
3826 fd->forWindow = forWindow;
3827 window->fontDialog = (void*)fd;
3828
3829 /* Create a form widget in a dialog shell */
3830 ac = 0;
3831 XtSetArg(args[ac], XmNautoUnmanage, False); ac++;
3832 XtSetArg(args[ac], XmNresizePolicy, XmRESIZE_NONE); ac++;
3833 form = CreateFormDialog(window->shell, "choose Fonts", args, ac);
3834 XtVaSetValues(form, XmNshadowThickness, 0, NULL);
3835 fd->shell = XtParent(form);
3836 XtVaSetValues(fd->shell, XmNtitle, "Text Fonts", NULL);
3837 AddMotifCloseCallback(XtParent(form), fontCancelCB, fd);
3838 XtAddCallback(form, XmNdestroyCallback, fontDestroyCB, fd);
3839
3840 primaryFrame = XtVaCreateManagedWidget("primaryFrame", xmFrameWidgetClass,
3841 form, XmNmarginHeight, 3,
3842 XmNtopAttachment, XmATTACH_POSITION,
3843 XmNtopPosition, 2,
3844 XmNleftAttachment, XmATTACH_POSITION,
3845 XmNleftPosition, 1,
3846 XmNrightAttachment, XmATTACH_POSITION,
3847 XmNrightPosition, 99, NULL);
3848 primaryForm = XtVaCreateManagedWidget("primaryForm", xmFormWidgetClass,
3849 primaryFrame, NULL);
3850 primaryLbl = XtVaCreateManagedWidget("primaryFont", xmLabelGadgetClass,
3851 primaryFrame,
3852 XmNlabelString, s1=XmStringCreateSimple("Primary Font"),
3853 XmNmnemonic, 'P',
3854 XmNchildType, XmFRAME_TITLE_CHILD,
3855 XmNchildHorizontalAlignment, XmALIGNMENT_CENTER, NULL);
3856 XmStringFree(s1);
3857
3858 primaryBtn = XtVaCreateManagedWidget("primaryBtn",
3859 xmPushButtonWidgetClass, primaryForm,
3860 XmNlabelString, s1=XmStringCreateSimple("Browse..."),
3861 XmNmnemonic, 'r',
3862 XmNtopAttachment, XmATTACH_POSITION,
3863 XmNtopPosition, 2,
3864 XmNtopOffset, BTN_TEXT_OFFSET,
3865 XmNleftAttachment, XmATTACH_POSITION,
3866 XmNleftPosition, 1, NULL);
3867 XmStringFree(s1);
3868 XtAddCallback(primaryBtn, XmNactivateCallback, primaryBrowseCB, fd);
3869
3870 fd->primaryW = XtVaCreateManagedWidget("primary", xmTextWidgetClass,
3871 primaryForm,
3872 XmNcolumns, 70,
3873 XmNmaxLength, MAX_FONT_LEN,
3874 XmNleftAttachment, XmATTACH_WIDGET,
3875 XmNleftWidget, primaryBtn,
3876 XmNtopAttachment, XmATTACH_POSITION,
3877 XmNtopPosition, 2,
3878 XmNrightAttachment, XmATTACH_POSITION,
3879 XmNrightPosition, 99, NULL);
3880 RemapDeleteKey(fd->primaryW);
3881 XtAddCallback(fd->primaryW, XmNvalueChangedCallback,
3882 primaryModifiedCB, fd);
3883 XtVaSetValues(primaryLbl, XmNuserData, fd->primaryW, NULL);
3884
3885 highlightFrame = XtVaCreateManagedWidget("highlightFrame",
3886 xmFrameWidgetClass, form,
3887 XmNmarginHeight, 3,
3888 XmNnavigationType, XmTAB_GROUP,
3889 XmNtopAttachment, XmATTACH_WIDGET,
3890 XmNtopWidget, primaryFrame,
3891 XmNtopOffset, 20,
3892 XmNleftAttachment, XmATTACH_POSITION,
3893 XmNleftPosition, 1,
3894 XmNrightAttachment, XmATTACH_POSITION,
3895 XmNrightPosition, 99, NULL);
3896 highlightForm = XtVaCreateManagedWidget("highlightForm", xmFormWidgetClass,
3897 highlightFrame, NULL);
3898 XtVaCreateManagedWidget("highlightFonts", xmLabelGadgetClass,
3899 highlightFrame,
3900 XmNlabelString,
3901 s1=XmStringCreateSimple("Fonts for Syntax Highlighting"),
3902 XmNchildType, XmFRAME_TITLE_CHILD,
3903 XmNchildHorizontalAlignment, XmALIGNMENT_CENTER, NULL);
3904 XmStringFree(s1);
3905
3906 fd->fillW = XtVaCreateManagedWidget("fillBtn",
3907 xmPushButtonWidgetClass, highlightForm,
3908 XmNlabelString,
3909 s1=XmStringCreateSimple("Fill Highlight Fonts from Primary"),
3910 XmNmnemonic, 'F',
3911 XmNtopAttachment, XmATTACH_POSITION,
3912 XmNtopPosition, 2,
3913 XmNtopOffset, BTN_TEXT_OFFSET,
3914 XmNleftAttachment, XmATTACH_POSITION,
3915 XmNleftPosition, 1, NULL);
3916 XmStringFree(s1);
3917 XtAddCallback(fd->fillW, XmNactivateCallback, fillFromPrimaryCB, fd);
3918
3919 italicLbl = XtVaCreateManagedWidget("italicLbl", xmLabelGadgetClass,
3920 highlightForm,
3921 XmNlabelString, s1=XmStringCreateSimple("Italic Font"),
3922 XmNmnemonic, 'I',
3923 XmNalignment, XmALIGNMENT_BEGINNING,
3924 XmNtopAttachment, XmATTACH_WIDGET,
3925 XmNtopWidget, fd->fillW,
3926 XmNtopOffset, MARGIN_SPACING,
3927 XmNleftAttachment, XmATTACH_POSITION,
3928 XmNleftPosition, 1, NULL);
3929 XmStringFree(s1);
3930
3931 fd->italicErrW = XtVaCreateManagedWidget("italicErrLbl",
3932 xmLabelGadgetClass, highlightForm,
3933 XmNlabelString, s1=XmStringCreateSimple(
3934 "(vvv spacing is inconsistent with primary font vvv)"),
3935 XmNalignment, XmALIGNMENT_END,
3936 XmNtopAttachment, XmATTACH_WIDGET,
3937 XmNtopWidget, fd->fillW,
3938 XmNtopOffset, MARGIN_SPACING,
3939 XmNleftAttachment, XmATTACH_WIDGET,
3940 XmNleftWidget, italicLbl,
3941 XmNrightAttachment, XmATTACH_POSITION,
3942 XmNrightPosition, 99, NULL);
3943 XmStringFree(s1);
3944
3945 italicBtn = XtVaCreateManagedWidget("italicBtn",
3946 xmPushButtonWidgetClass, highlightForm,
3947 XmNlabelString, s1=XmStringCreateSimple("Browse..."),
3948 XmNmnemonic, 'o',
3949 XmNtopAttachment, XmATTACH_WIDGET,
3950 XmNtopWidget, italicLbl,
3951 XmNtopOffset, BTN_TEXT_OFFSET,
3952 XmNleftAttachment, XmATTACH_POSITION,
3953 XmNleftPosition, 1, NULL);
3954 XmStringFree(s1);
3955 XtAddCallback(italicBtn, XmNactivateCallback, italicBrowseCB, fd);
3956
3957 fd->italicW = XtVaCreateManagedWidget("italic", xmTextWidgetClass,
3958 highlightForm,
3959 XmNmaxLength, MAX_FONT_LEN,
3960 XmNleftAttachment, XmATTACH_WIDGET,
3961 XmNleftWidget, italicBtn,
3962 XmNtopAttachment, XmATTACH_WIDGET,
3963 XmNtopWidget, italicLbl,
3964 XmNrightAttachment, XmATTACH_POSITION,
3965 XmNrightPosition, 99, NULL);
3966 RemapDeleteKey(fd->italicW);
3967 XtAddCallback(fd->italicW, XmNvalueChangedCallback,
3968 italicModifiedCB, fd);
3969 XtVaSetValues(italicLbl, XmNuserData, fd->italicW, NULL);
3970
3971 boldLbl = XtVaCreateManagedWidget("boldLbl", xmLabelGadgetClass,
3972 highlightForm,
3973 XmNlabelString, s1=XmStringCreateSimple("Bold Font"),
3974 XmNmnemonic, 'B',
3975 XmNalignment, XmALIGNMENT_BEGINNING,
3976 XmNtopAttachment, XmATTACH_WIDGET,
3977 XmNtopWidget, italicBtn,
3978 XmNtopOffset, MARGIN_SPACING,
3979 XmNleftAttachment, XmATTACH_POSITION,
3980 XmNleftPosition, 1, NULL);
3981 XmStringFree(s1);
3982
3983 fd->boldErrW = XtVaCreateManagedWidget("boldErrLbl",
3984 xmLabelGadgetClass, highlightForm,
3985 XmNlabelString, s1=XmStringCreateSimple(""),
3986 XmNalignment, XmALIGNMENT_END,
3987 XmNtopAttachment, XmATTACH_WIDGET,
3988 XmNtopWidget, italicBtn,
3989 XmNtopOffset, MARGIN_SPACING,
3990 XmNleftAttachment, XmATTACH_WIDGET,
3991 XmNleftWidget, boldLbl,
3992 XmNrightAttachment, XmATTACH_POSITION,
3993 XmNrightPosition, 99, NULL);
3994 XmStringFree(s1);
3995
3996 boldBtn = XtVaCreateManagedWidget("boldBtn",
3997 xmPushButtonWidgetClass, highlightForm,
3998 XmNlabelString, s1=XmStringCreateSimple("Browse..."),
3999 XmNmnemonic, 'w',
4000 XmNtopAttachment, XmATTACH_WIDGET,
4001 XmNtopWidget, boldLbl,
4002 XmNtopOffset, BTN_TEXT_OFFSET,
4003 XmNleftAttachment, XmATTACH_POSITION,
4004 XmNleftPosition, 1, NULL);
4005 XmStringFree(s1);
4006 XtAddCallback(boldBtn, XmNactivateCallback, boldBrowseCB, fd);
4007
4008 fd->boldW = XtVaCreateManagedWidget("bold", xmTextWidgetClass,
4009 highlightForm,
4010 XmNmaxLength, MAX_FONT_LEN,
4011 XmNleftAttachment, XmATTACH_WIDGET,
4012 XmNleftWidget, boldBtn,
4013 XmNtopAttachment, XmATTACH_WIDGET,
4014 XmNtopWidget, boldLbl,
4015 XmNrightAttachment, XmATTACH_POSITION,
4016 XmNrightPosition, 99, NULL);
4017 RemapDeleteKey(fd->boldW);
4018 XtAddCallback(fd->boldW, XmNvalueChangedCallback,
4019 boldModifiedCB, fd);
4020 XtVaSetValues(boldLbl, XmNuserData, fd->boldW, NULL);
4021
4022 boldItalicLbl = XtVaCreateManagedWidget("boldItalicLbl", xmLabelGadgetClass,
4023 highlightForm,
4024 XmNlabelString, s1=XmStringCreateSimple("Bold Italic Font"),
4025 XmNmnemonic, 'l',
4026 XmNalignment, XmALIGNMENT_BEGINNING,
4027 XmNtopAttachment, XmATTACH_WIDGET,
4028 XmNtopWidget, boldBtn,
4029 XmNtopOffset, MARGIN_SPACING,
4030 XmNleftAttachment, XmATTACH_POSITION,
4031 XmNleftPosition, 1, NULL);
4032 XmStringFree(s1);
4033
4034 fd->boldItalicErrW = XtVaCreateManagedWidget("boldItalicErrLbl",
4035 xmLabelGadgetClass, highlightForm,
4036 XmNlabelString, s1=XmStringCreateSimple(""),
4037 XmNalignment, XmALIGNMENT_END,
4038 XmNtopAttachment, XmATTACH_WIDGET,
4039 XmNtopWidget, boldBtn,
4040 XmNtopOffset, MARGIN_SPACING,
4041 XmNleftAttachment, XmATTACH_WIDGET,
4042 XmNleftWidget, boldItalicLbl,
4043 XmNrightAttachment, XmATTACH_POSITION,
4044 XmNrightPosition, 99, NULL);
4045 XmStringFree(s1);
4046
4047 boldItalicBtn = XtVaCreateManagedWidget("boldItalicBtn",
4048 xmPushButtonWidgetClass, highlightForm,
4049 XmNlabelString, s1=XmStringCreateSimple("Browse..."),
4050 XmNmnemonic, 's',
4051 XmNtopAttachment, XmATTACH_WIDGET,
4052 XmNtopWidget, boldItalicLbl,
4053 XmNtopOffset, BTN_TEXT_OFFSET,
4054 XmNleftAttachment, XmATTACH_POSITION,
4055 XmNleftPosition, 1, NULL);
4056 XmStringFree(s1);
4057 XtAddCallback(boldItalicBtn, XmNactivateCallback, boldItalicBrowseCB, fd);
4058
4059 fd->boldItalicW = XtVaCreateManagedWidget("boldItalic",
4060 xmTextWidgetClass, highlightForm,
4061 XmNmaxLength, MAX_FONT_LEN,
4062 XmNleftAttachment, XmATTACH_WIDGET,
4063 XmNleftWidget, boldItalicBtn,
4064 XmNtopAttachment, XmATTACH_WIDGET,
4065 XmNtopWidget, boldItalicLbl,
4066 XmNrightAttachment, XmATTACH_POSITION,
4067 XmNrightPosition, 99, NULL);
4068 RemapDeleteKey(fd->boldItalicW);
4069 XtAddCallback(fd->boldItalicW, XmNvalueChangedCallback,
4070 boldItalicModifiedCB, fd);
4071 XtVaSetValues(boldItalicLbl, XmNuserData, fd->boldItalicW, NULL);
4072
4073 okBtn = XtVaCreateManagedWidget("ok", xmPushButtonWidgetClass, form,
4074 XmNlabelString, s1=XmStringCreateSimple("OK"),
4075 XmNmarginWidth, BUTTON_WIDTH_MARGIN,
4076 XmNtopAttachment, XmATTACH_WIDGET,
4077 XmNtopWidget, highlightFrame,
4078 XmNtopOffset, MARGIN_SPACING,
4079 XmNleftAttachment, XmATTACH_POSITION,
4080 XmNleftPosition, forWindow ? 13 : 26,
4081 XmNrightAttachment, XmATTACH_POSITION,
4082 XmNrightPosition, forWindow ? 27 : 40, NULL);
4083 XtAddCallback(okBtn, XmNactivateCallback, fontOkCB, fd);
4084 XmStringFree(s1);
4085
4086 if (forWindow) {
4087 applyBtn = XtVaCreateManagedWidget("apply",xmPushButtonWidgetClass,form,
4088 XmNlabelString, s1=XmStringCreateSimple("Apply"),
4089 XmNmnemonic, 'A',
4090 XmNtopAttachment, XmATTACH_WIDGET,
4091 XmNtopWidget, highlightFrame,
4092 XmNtopOffset, MARGIN_SPACING,
4093 XmNleftAttachment, XmATTACH_POSITION,
4094 XmNleftPosition, 43,
4095 XmNrightAttachment, XmATTACH_POSITION,
4096 XmNrightPosition, 57, NULL);
4097 XtAddCallback(applyBtn, XmNactivateCallback, fontApplyCB, fd);
4098 XmStringFree(s1);
4099 }
4100
4101 cancelBtn = XtVaCreateManagedWidget("cancel",
4102 xmPushButtonWidgetClass, form,
4103 XmNlabelString,
4104 s1 = XmStringCreateSimple(forWindow ? "Close" : "Cancel"),
4105 XmNtopAttachment, XmATTACH_WIDGET,
4106 XmNtopWidget, highlightFrame,
4107 XmNtopOffset, MARGIN_SPACING,
4108 XmNleftAttachment, XmATTACH_POSITION,
4109 XmNleftPosition, forWindow ? 73 : 59,
4110 XmNrightAttachment, XmATTACH_POSITION,
4111 XmNrightPosition, forWindow ? 87 : 73,
4112 NULL);
4113 XtAddCallback(cancelBtn, XmNactivateCallback, fontCancelCB, fd);
4114 XmStringFree(s1);
4115
4116 /* Set initial default button */
4117 XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
4118 XtVaSetValues(form, XmNcancelButton, cancelBtn, NULL);
4119
4120 /* Set initial values */
4121 if (forWindow) {
4122 XmTextSetString(fd->primaryW, window->fontName);
4123 XmTextSetString(fd->boldW, window->boldFontName);
4124 XmTextSetString(fd->italicW, window->italicFontName);
4125 XmTextSetString(fd->boldItalicW, window->boldItalicFontName);
4126 } else {
4127 XmTextSetString(fd->primaryW, GetPrefFontName());
4128 XmTextSetString(fd->boldW, GetPrefBoldFontName());
4129 XmTextSetString(fd->italicW, GetPrefItalicFontName());
4130 XmTextSetString(fd->boldItalicW, GetPrefBoldItalicFontName());
4131 }
4132
4133 /* Handle mnemonic selection of buttons and focus to dialog */
4134 AddDialogMnemonicHandler(form, FALSE);
4135
4136 /* put up dialog */
4137 ManageDialogCenteredOnPointer(form);
4138 }
4139
fillFromPrimaryCB(Widget w,XtPointer clientData,XtPointer callData)4140 static void fillFromPrimaryCB(Widget w, XtPointer clientData,
4141 XtPointer callData)
4142 {
4143 fontDialog *fd = (fontDialog *)clientData;
4144 char *primaryName, *errMsg;
4145 char modifiedFontName[MAX_FONT_LEN];
4146 char *searchString = "(-[^-]*-[^-]*)-([^-]*)-([^-]*)-(.*)";
4147 char *italicReplaceString = "\\1-\\2-o-\\4";
4148 char *boldReplaceString = "\\1-bold-\\3-\\4";
4149 char *boldItalicReplaceString = "\\1-bold-o-\\4";
4150 regexp *compiledRE;
4151
4152 /* Match the primary font agains RE pattern for font names. If it
4153 doesn't match, we can't generate highlight font names, so return */
4154 compiledRE = CompileRE(searchString, &errMsg, REDFLT_STANDARD);
4155 primaryName = XmTextGetString(fd->primaryW);
4156 if (!ExecRE(compiledRE, primaryName, NULL, False, '\0', '\0', NULL, NULL, NULL)) {
4157 XBell(XtDisplay(fd->shell), 0);
4158 free(compiledRE);
4159 NEditFree(primaryName);
4160 return;
4161 }
4162
4163 /* Make up names for new fonts based on RE replace patterns */
4164 SubstituteRE(compiledRE, italicReplaceString, modifiedFontName,
4165 MAX_FONT_LEN);
4166 XmTextSetString(fd->italicW, modifiedFontName);
4167 SubstituteRE(compiledRE, boldReplaceString, modifiedFontName,
4168 MAX_FONT_LEN);
4169 XmTextSetString(fd->boldW, modifiedFontName);
4170 SubstituteRE(compiledRE, boldItalicReplaceString, modifiedFontName,
4171 MAX_FONT_LEN);
4172 XmTextSetString(fd->boldItalicW, modifiedFontName);
4173 NEditFree(primaryName);
4174 NEditFree(compiledRE);
4175 }
4176
primaryModifiedCB(Widget w,XtPointer clientData,XtPointer callData)4177 static void primaryModifiedCB(Widget w, XtPointer clientData,
4178 XtPointer callData)
4179 {
4180 fontDialog *fd = (fontDialog *)clientData;
4181
4182 showFontStatus(fd, fd->italicW, fd->italicErrW);
4183 showFontStatus(fd, fd->boldW, fd->boldErrW);
4184 showFontStatus(fd, fd->boldItalicW, fd->boldItalicErrW);
4185 }
italicModifiedCB(Widget w,XtPointer clientData,XtPointer callData)4186 static void italicModifiedCB(Widget w, XtPointer clientData, XtPointer callData)
4187 {
4188 fontDialog *fd = (fontDialog *)clientData;
4189
4190 showFontStatus(fd, fd->italicW, fd->italicErrW);
4191 }
boldModifiedCB(Widget w,XtPointer clientData,XtPointer callData)4192 static void boldModifiedCB(Widget w, XtPointer clientData, XtPointer callData)
4193 {
4194 fontDialog *fd = (fontDialog *)clientData;
4195
4196 showFontStatus(fd, fd->boldW, fd->boldErrW);
4197 }
boldItalicModifiedCB(Widget w,XtPointer clientData,XtPointer callData)4198 static void boldItalicModifiedCB(Widget w, XtPointer clientData,
4199 XtPointer callData)
4200 {
4201 fontDialog *fd = (fontDialog *)clientData;
4202
4203 showFontStatus(fd, fd->boldItalicW, fd->boldItalicErrW);
4204 }
4205
primaryBrowseCB(Widget w,XtPointer clientData,XtPointer callData)4206 static void primaryBrowseCB(Widget w, XtPointer clientData, XtPointer callData)
4207 {
4208 fontDialog *fd = (fontDialog *)clientData;
4209
4210 browseFont(fd->shell, fd->primaryW);
4211 }
italicBrowseCB(Widget w,XtPointer clientData,XtPointer callData)4212 static void italicBrowseCB(Widget w, XtPointer clientData, XtPointer callData)
4213 {
4214 fontDialog *fd = (fontDialog *)clientData;
4215
4216 browseFont(fd->shell, fd->italicW);
4217 }
boldBrowseCB(Widget w,XtPointer clientData,XtPointer callData)4218 static void boldBrowseCB(Widget w, XtPointer clientData, XtPointer callData)
4219 {
4220 fontDialog *fd = (fontDialog *)clientData;
4221
4222 browseFont(fd->shell, fd->boldW);
4223 }
boldItalicBrowseCB(Widget w,XtPointer clientData,XtPointer callData)4224 static void boldItalicBrowseCB(Widget w, XtPointer clientData,
4225 XtPointer callData)
4226 {
4227 fontDialog *fd = (fontDialog *)clientData;
4228
4229 browseFont(fd->shell, fd->boldItalicW);
4230 }
4231
fontDestroyCB(Widget w,XtPointer clientData,XtPointer callData)4232 static void fontDestroyCB(Widget w, XtPointer clientData, XtPointer callData)
4233 {
4234 fontDialog *fd = (fontDialog *)clientData;
4235
4236 fd->window->fontDialog = NULL;
4237 NEditFree(fd);
4238 }
4239
fontOkCB(Widget w,XtPointer clientData,XtPointer callData)4240 static void fontOkCB(Widget w, XtPointer clientData, XtPointer callData)
4241 {
4242 fontDialog *fd = (fontDialog *)clientData;
4243
4244 updateFonts(fd);
4245
4246 /* pop down and destroy the dialog */
4247 XtDestroyWidget(fd->shell);
4248 }
4249
fontApplyCB(Widget w,XtPointer clientData,XtPointer callData)4250 static void fontApplyCB(Widget w, XtPointer clientData, XtPointer callData)
4251 {
4252 fontDialog *fd = (fontDialog *)clientData;
4253
4254 updateFonts(fd);
4255 }
4256
fontCancelCB(Widget w,XtPointer clientData,XtPointer callData)4257 static void fontCancelCB(Widget w, XtPointer clientData, XtPointer callData)
4258 {
4259 fontDialog *fd = (fontDialog *)clientData;
4260
4261 /* pop down and destroy the dialog */
4262 XtDestroyWidget(fd->shell);
4263 }
4264
4265 /*
4266 ** Check over a font name in a text field to make sure it agrees with the
4267 ** primary font in height and spacing.
4268 */
checkFontStatus(fontDialog * fd,Widget fontTextFieldW)4269 static int checkFontStatus(fontDialog *fd, Widget fontTextFieldW)
4270 {
4271 char *primaryName, *testName;
4272 XFontStruct *primaryFont, *testFont;
4273 Display *display = XtDisplay(fontTextFieldW);
4274 int primaryWidth, primaryHeight, testWidth, testHeight;
4275
4276 /* Get width and height of the font to check. Note the test for empty
4277 name: X11R6 clients freak out X11R5 servers if they ask them to load
4278 an empty font name, and kill the whole application! */
4279 testName = XmTextGetString(fontTextFieldW);
4280 if (testName[0] == '\0') {
4281 NEditFree(testName);
4282 return BAD_FONT;
4283 }
4284 testFont = XLoadQueryFont(display, testName);
4285 if (testFont == NULL) {
4286 NEditFree(testName);
4287 return BAD_FONT;
4288 }
4289 NEditFree(testName);
4290 testWidth = testFont->min_bounds.width;
4291 testHeight = testFont->ascent + testFont->descent;
4292 XFreeFont(display, testFont);
4293
4294 /* Get width and height of the primary font */
4295 primaryName = XmTextGetString(fd->primaryW);
4296 if (primaryName[0] == '\0') {
4297 NEditFree(primaryName);
4298 return BAD_FONT;
4299 }
4300 primaryFont = XLoadQueryFont(display, primaryName);
4301 if (primaryFont == NULL) {
4302 NEditFree(primaryName);
4303 return BAD_PRIMARY;
4304 }
4305 NEditFree(primaryName);
4306 primaryWidth = primaryFont->min_bounds.width;
4307 primaryHeight = primaryFont->ascent + primaryFont->descent;
4308 XFreeFont(display, primaryFont);
4309
4310 /* Compare font information */
4311 if (testWidth != primaryWidth)
4312 return BAD_SPACING;
4313 if (testHeight != primaryHeight)
4314 return BAD_SIZE;
4315 return GOOD_FONT;
4316 }
4317
4318 /*
4319 ** Update the error label for a font text field to reflect its validity and degree
4320 ** of agreement with the currently selected primary font
4321 */
showFontStatus(fontDialog * fd,Widget fontTextFieldW,Widget errorLabelW)4322 static int showFontStatus(fontDialog *fd, Widget fontTextFieldW,
4323 Widget errorLabelW)
4324 {
4325 int status;
4326 XmString s;
4327 char *msg;
4328
4329 status = checkFontStatus(fd, fontTextFieldW);
4330 if (status == BAD_PRIMARY)
4331 msg = "(font below may not match primary font)";
4332 else if (status == BAD_FONT)
4333 msg = "(xxx font below is invalid xxx)";
4334 else if (status == BAD_SIZE)
4335 msg = "(height of font below does not match primary)";
4336 else if (status == BAD_SPACING)
4337 msg = "(spacing of font below does not match primary)";
4338 else
4339 msg = "";
4340
4341 XtVaSetValues(errorLabelW, XmNlabelString, s=XmStringCreateSimple(msg),
4342 NULL);
4343 XmStringFree(s);
4344 return status;
4345 }
4346
4347 /*
4348 ** Put up a font selector panel to set the font name in the text widget "fontTextW"
4349 */
browseFont(Widget parent,Widget fontTextW)4350 static void browseFont(Widget parent, Widget fontTextW)
4351 {
4352 char *origFontName, *newFontName;
4353 Pixel fgPixel, bgPixel;
4354 int dummy;
4355
4356 origFontName = XmTextGetString(fontTextW);
4357
4358 /* Get the values from the defaults */
4359 fgPixel = AllocColor(parent, GetPrefColorName(TEXT_FG_COLOR),
4360 &dummy, &dummy, &dummy);
4361 bgPixel = AllocColor(parent, GetPrefColorName(TEXT_BG_COLOR),
4362 &dummy, &dummy, &dummy);
4363
4364 newFontName = FontSel(parent, PREF_FIXED, origFontName, fgPixel, bgPixel);
4365 NEditFree(origFontName);
4366 if (newFontName == NULL)
4367 return;
4368 XmTextSetString(fontTextW, newFontName);
4369 NEditFree(newFontName);
4370 }
4371
4372 /*
4373 ** Accept the changes in the dialog and set the fonts regardless of errors
4374 */
updateFonts(fontDialog * fd)4375 static void updateFonts(fontDialog *fd)
4376 {
4377 char *fontName, *italicName, *boldName, *boldItalicName;
4378
4379 fontName = XmTextGetString(fd->primaryW);
4380 italicName = XmTextGetString(fd->italicW);
4381 boldName = XmTextGetString(fd->boldW);
4382 boldItalicName = XmTextGetString(fd->boldItalicW);
4383
4384 if (fd->forWindow) {
4385 char *params[4];
4386 params[0] = fontName;
4387 params[1] = italicName;
4388 params[2] = boldName;
4389 params[3] = boldItalicName;
4390 XtCallActionProc(fd->window->textArea, "set_fonts", NULL, params, 4);
4391 /*
4392 SetFonts(fd->window, fontName, italicName, boldName, boldItalicName);
4393 */
4394 }
4395 else {
4396 SetPrefFont(fontName);
4397 SetPrefItalicFont(italicName);
4398 SetPrefBoldFont(boldName);
4399 SetPrefBoldItalicFont(boldItalicName);
4400 }
4401 NEditFree(fontName);
4402 NEditFree(italicName);
4403 NEditFree(boldName);
4404 NEditFree(boldItalicName);
4405 }
4406
4407 /*
4408 ** Change the language mode to the one indexed by "mode", reseting word
4409 ** delimiters, syntax highlighting and other mode specific parameters
4410 */
reapplyLanguageMode(WindowInfo * window,int mode,int forceDefaults)4411 static void reapplyLanguageMode(WindowInfo *window, int mode, int forceDefaults)
4412 {
4413 char *delimiters;
4414 int i, wrapMode, indentStyle, tabDist, emTabDist, highlight, oldEmTabDist;
4415 int wrapModeIsDef, tabDistIsDef, emTabDistIsDef, indentStyleIsDef;
4416 int highlightIsDef, haveHighlightPatterns, haveSmartIndentMacros;
4417 int oldMode = window->languageMode;
4418
4419 /* If the mode is the same, and changes aren't being forced (as might
4420 happen with Save As...), don't mess with already correct settings */
4421 if (window->languageMode == mode && !forceDefaults)
4422 return;
4423
4424 /* Change the mode name stored in the window */
4425 window->languageMode = mode;
4426
4427 /* Decref oldMode's default calltips file if needed */
4428 if (oldMode != PLAIN_LANGUAGE_MODE && LanguageModes[oldMode]->defTipsFile) {
4429 DeleteTagsFile( LanguageModes[oldMode]->defTipsFile, TIP, False );
4430 }
4431
4432 /* Set delimiters for all text widgets */
4433 if (mode == PLAIN_LANGUAGE_MODE || LanguageModes[mode]->delimiters == NULL)
4434 delimiters = GetPrefDelimiters();
4435 else
4436 delimiters = LanguageModes[mode]->delimiters;
4437 XtVaSetValues(window->textArea, textNwordDelimiters, delimiters, NULL);
4438 for (i=0; i<window->nPanes; i++)
4439 XtVaSetValues(window->textPanes[i], textNautoIndent, delimiters, NULL);
4440
4441 /* Decide on desired values for language-specific parameters. If a
4442 parameter was set to its default value, set it to the new default,
4443 otherwise, leave it alone */
4444 wrapModeIsDef = window->wrapMode == GetPrefWrap(oldMode);
4445 tabDistIsDef = BufGetTabDistance(window->buffer) == GetPrefTabDist(oldMode);
4446 XtVaGetValues(window->textArea, textNemulateTabs, &oldEmTabDist, NULL);
4447 emTabDistIsDef = oldEmTabDist == GetPrefEmTabDist(oldMode);
4448 indentStyleIsDef = window->indentStyle == GetPrefAutoIndent(oldMode) ||
4449 (GetPrefAutoIndent(oldMode) == SMART_INDENT &&
4450 window->indentStyle == AUTO_INDENT &&
4451 !SmartIndentMacrosAvailable(LanguageModeName(oldMode)));
4452 highlightIsDef = window->highlightSyntax == GetPrefHighlightSyntax()
4453 || (GetPrefHighlightSyntax() &&
4454 FindPatternSet(LanguageModeName(oldMode)) == NULL);
4455 wrapMode = wrapModeIsDef || forceDefaults ?
4456 GetPrefWrap(mode) : window->wrapMode;
4457 tabDist = tabDistIsDef || forceDefaults ?
4458 GetPrefTabDist(mode) : BufGetTabDistance(window->buffer);
4459 emTabDist = emTabDistIsDef || forceDefaults ?
4460 GetPrefEmTabDist(mode) : oldEmTabDist;
4461 indentStyle = indentStyleIsDef || forceDefaults ?
4462 GetPrefAutoIndent(mode) : window->indentStyle;
4463 highlight = highlightIsDef || forceDefaults ?
4464 GetPrefHighlightSyntax() : window->highlightSyntax;
4465
4466 /* Dim/undim smart-indent and highlighting menu items depending on
4467 whether patterns/macros are available */
4468 haveHighlightPatterns = FindPatternSet(LanguageModeName(mode)) != NULL;
4469 haveSmartIndentMacros = SmartIndentMacrosAvailable(LanguageModeName(mode));
4470 if (IsTopDocument(window)) {
4471 XtSetSensitive(window->highlightItem, haveHighlightPatterns);
4472 XtSetSensitive(window->smartIndentItem, haveSmartIndentMacros);
4473 }
4474
4475 /* Turn off requested options which are not available */
4476 highlight = haveHighlightPatterns && highlight;
4477 if (indentStyle == SMART_INDENT && !haveSmartIndentMacros)
4478 indentStyle = AUTO_INDENT;
4479
4480 /* Change highlighting */
4481 window->highlightSyntax = highlight;
4482 SetToggleButtonState(window, window->highlightItem, highlight, False);
4483 StopHighlighting(window);
4484
4485 /* we defer highlighting to RaiseDocument() if doc is hidden */
4486 if (IsTopDocument(window) && highlight)
4487 StartHighlighting(window, False);
4488
4489 /* Force a change of smart indent macros (SetAutoIndent will re-start) */
4490 if (window->indentStyle == SMART_INDENT) {
4491 EndSmartIndent(window);
4492 window->indentStyle = AUTO_INDENT;
4493 }
4494
4495 /* set requested wrap, indent, and tabs */
4496 SetAutoWrap(window, wrapMode);
4497 SetAutoIndent(window, indentStyle);
4498 SetTabDist(window, tabDist);
4499 SetEmTabDist(window, emTabDist);
4500
4501 /* Load calltips files for new mode */
4502 if (mode != PLAIN_LANGUAGE_MODE && LanguageModes[mode]->defTipsFile) {
4503 AddTagsFile( LanguageModes[mode]->defTipsFile, TIP );
4504 }
4505
4506 /* Add/remove language specific menu items */
4507 UpdateUserMenus(window);
4508 }
4509
4510 /*
4511 ** Find and return the name of the appropriate languange mode for
4512 ** the file in "window". Returns a pointer to a string, which will
4513 ** remain valid until a change is made to the language modes list.
4514 */
matchLanguageMode(WindowInfo * window)4515 static int matchLanguageMode(WindowInfo *window)
4516 {
4517 char *ext, *first200;
4518 int i, j, fileNameLen, extLen, beginPos, endPos, start;
4519 const char *versionExtendedPath;
4520
4521 /*... look for an explicit mode statement first */
4522
4523 /* Do a regular expression search on for recognition pattern */
4524 first200 = BufGetRange(window->buffer, 0, 200);
4525 for (i=0; i<NLanguageModes; i++) {
4526 if (LanguageModes[i]->recognitionExpr != NULL) {
4527 if (SearchString(first200, LanguageModes[i]->recognitionExpr,
4528 SEARCH_FORWARD, SEARCH_REGEX, False, 0, &beginPos,
4529 &endPos, NULL, NULL, NULL))
4530 {
4531 NEditFree(first200);
4532 return i;
4533 }
4534 }
4535 }
4536 NEditFree(first200);
4537
4538 /* Look at file extension ("@@/" starts a ClearCase version extended path,
4539 which gets appended after the file extension, and therefore must be
4540 stripped off to recognize the extension to make ClearCase users happy) */
4541 fileNameLen = strlen(window->filename);
4542 #ifdef VMS
4543 if (strchr(window->filename, ';') != NULL)
4544 fileNameLen = strchr(window->filename, ';') - window->filename;
4545 #else
4546 if ((versionExtendedPath = GetClearCaseVersionExtendedPath(window->filename)) != NULL)
4547 fileNameLen = versionExtendedPath - window->filename;
4548 #endif
4549 for (i=0; i<NLanguageModes; i++) {
4550 for (j=0; j<LanguageModes[i]->nExtensions; j++) {
4551 ext = LanguageModes[i]->extensions[j];
4552 extLen = strlen(ext);
4553 start = fileNameLen - extLen;
4554 #if defined(__VMS) && (__VMS_VER >= 70200000)
4555 /* VMS v7.2 has case-preserving filenames */
4556 if (start >= 0 && !strncasecmp(&window->filename[start], ext, extLen))
4557 return i;
4558 #else
4559 if (start >= 0 && !strncmp(&window->filename[start], ext, extLen))
4560 return i;
4561 #endif
4562 }
4563 }
4564
4565 /* no appropriate mode was found */
4566 return PLAIN_LANGUAGE_MODE;
4567 }
4568
loadLanguageModesString(char * inString,int fileVer)4569 static int loadLanguageModesString(char *inString, int fileVer)
4570 {
4571 char *errMsg, *styleName, *inPtr = inString;
4572 languageModeRec *lm;
4573 int i;
4574
4575 for (;;) {
4576
4577 /* skip over blank space */
4578 inPtr += strspn(inPtr, " \t\n");
4579
4580 /* Allocate a language mode structure to return, set unread fields to
4581 empty so everything can be freed on errors by freeLanguageModeRec */
4582 lm = (languageModeRec *)NEditMalloc(sizeof(languageModeRec));
4583 lm->nExtensions = 0;
4584 lm->recognitionExpr = NULL;
4585 lm->defTipsFile = NULL;
4586 lm->delimiters = NULL;
4587
4588 /* read language mode name */
4589 lm->name = ReadSymbolicField(&inPtr);
4590 if (lm->name == NULL) {
4591 NEditFree(lm);
4592 return modeError(NULL,inString,inPtr,"language mode name required");
4593 }
4594 if (!SkipDelimiter(&inPtr, &errMsg))
4595 return modeError(lm, inString, inPtr, errMsg);
4596
4597 /* read list of extensions */
4598 lm->extensions = readExtensionList(&inPtr,
4599 &lm->nExtensions);
4600 if (!SkipDelimiter(&inPtr, &errMsg))
4601 return modeError(lm, inString, inPtr, errMsg);
4602
4603 /* read the recognition regular expression */
4604 if (*inPtr == '\n' || *inPtr == '\0' || *inPtr == ':')
4605 lm->recognitionExpr = NULL;
4606 else if (!ReadQuotedString(&inPtr, &errMsg, &lm->recognitionExpr))
4607 return modeError(lm, inString,inPtr, errMsg);
4608 if (!SkipDelimiter(&inPtr, &errMsg))
4609 return modeError(lm, inString, inPtr, errMsg);
4610
4611 /* read the indent style */
4612 styleName = ReadSymbolicField(&inPtr);
4613 if (styleName == NULL)
4614 lm->indentStyle = DEFAULT_INDENT;
4615 else {
4616 for (i=0; i<N_INDENT_STYLES; i++) {
4617 if (!strcmp(styleName, AutoIndentTypes[i])) {
4618 lm->indentStyle = i;
4619 break;
4620 }
4621 }
4622 NEditFree(styleName);
4623 if (i == N_INDENT_STYLES)
4624 return modeError(lm,inString,inPtr,"unrecognized indent style");
4625 }
4626 if (!SkipDelimiter(&inPtr, &errMsg))
4627 return modeError(lm, inString, inPtr, errMsg);
4628
4629 /* read the wrap style */
4630 styleName = ReadSymbolicField(&inPtr);
4631 if (styleName == NULL)
4632 lm->wrapStyle = DEFAULT_WRAP;
4633 else {
4634 for (i=0; i<N_WRAP_STYLES; i++) {
4635 if (!strcmp(styleName, AutoWrapTypes[i])) {
4636 lm->wrapStyle = i;
4637 break;
4638 }
4639 }
4640 NEditFree(styleName);
4641 if (i == N_WRAP_STYLES)
4642 return modeError(lm, inString, inPtr,"unrecognized wrap style");
4643 }
4644 if (!SkipDelimiter(&inPtr, &errMsg))
4645 return modeError(lm, inString, inPtr, errMsg);
4646
4647 /* read the tab distance */
4648 if (*inPtr == '\n' || *inPtr == '\0' || *inPtr == ':')
4649 lm->tabDist = DEFAULT_TAB_DIST;
4650 else if (!ReadNumericField(&inPtr, &lm->tabDist))
4651 return modeError(lm, inString, inPtr, "bad tab spacing");
4652 if (!SkipDelimiter(&inPtr, &errMsg))
4653 return modeError(lm, inString, inPtr, errMsg);
4654
4655 /* read emulated tab distance */
4656 if (*inPtr == '\n' || *inPtr == '\0' || *inPtr == ':')
4657 lm->emTabDist = DEFAULT_EM_TAB_DIST;
4658 else if (!ReadNumericField(&inPtr, &lm->emTabDist))
4659 return modeError(lm, inString, inPtr, "bad emulated tab spacing");
4660 if (!SkipDelimiter(&inPtr, &errMsg))
4661 return modeError(lm, inString, inPtr, errMsg);
4662
4663 /* read the delimiters string */
4664 if (*inPtr == '\n' || *inPtr == '\0' || *inPtr == ':')
4665 lm->delimiters = NULL;
4666 else if (!ReadQuotedString(&inPtr, &errMsg, &lm->delimiters))
4667 return modeError(lm, inString, inPtr, errMsg);
4668
4669 /* After 5.3 all language modes need a default tips file field */
4670 if (!SkipDelimiter(&inPtr, &errMsg))
4671 if (fileVer > 5003)
4672 return modeError(lm, inString, inPtr, errMsg);
4673
4674 /* read the default tips file */
4675 if (*inPtr == '\n' || *inPtr == '\0')
4676 lm->defTipsFile = NULL;
4677 else if (!ReadQuotedString(&inPtr, &errMsg, &lm->defTipsFile))
4678 return modeError(lm, inString, inPtr, errMsg);
4679
4680 /* pattern set was read correctly, add/replace it in the list */
4681 for (i=0; i<NLanguageModes; i++) {
4682 if (!strcmp(LanguageModes[i]->name, lm->name)) {
4683 freeLanguageModeRec(LanguageModes[i]);
4684 LanguageModes[i] = lm;
4685 break;
4686 }
4687 }
4688 if (i == NLanguageModes) {
4689 LanguageModes[NLanguageModes++] = lm;
4690 if (NLanguageModes > MAX_LANGUAGE_MODES)
4691 return modeError(NULL, inString, inPtr,
4692 "maximum allowable number of language modes exceeded");
4693 }
4694
4695 /* if the string ends here, we're done */
4696 inPtr += strspn(inPtr, " \t\n");
4697 if (*inPtr == '\0')
4698 return True;
4699 } /* End for(;;) */
4700 }
4701
writeLanguageModesString(void)4702 static char *writeLanguageModesString(void)
4703 {
4704 int i;
4705 char *outStr, *escapedStr, *str, numBuf[25];
4706 textBuffer *outBuf;
4707
4708 outBuf = BufCreate();
4709 for (i=0; i<NLanguageModes; i++) {
4710 BufInsert(outBuf, outBuf->length, "\t");
4711 BufInsert(outBuf, outBuf->length, LanguageModes[i]->name);
4712 BufInsert(outBuf, outBuf->length, ":");
4713 BufInsert(outBuf, outBuf->length, str = createExtString(
4714 LanguageModes[i]->extensions, LanguageModes[i]->nExtensions));
4715 NEditFree(str);
4716 BufInsert(outBuf, outBuf->length, ":");
4717 if (LanguageModes[i]->recognitionExpr != NULL) {
4718 BufInsert(outBuf, outBuf->length,
4719 str=MakeQuotedString(LanguageModes[i]->recognitionExpr));
4720 NEditFree(str);
4721 }
4722 BufInsert(outBuf, outBuf->length, ":");
4723 if (LanguageModes[i]->indentStyle != DEFAULT_INDENT)
4724 BufInsert(outBuf, outBuf->length,
4725 AutoIndentTypes[LanguageModes[i]->indentStyle]);
4726 BufInsert(outBuf, outBuf->length, ":");
4727 if (LanguageModes[i]->wrapStyle != DEFAULT_WRAP)
4728 BufInsert(outBuf, outBuf->length,
4729 AutoWrapTypes[LanguageModes[i]->wrapStyle]);
4730 BufInsert(outBuf, outBuf->length, ":");
4731 if (LanguageModes[i]->tabDist != DEFAULT_TAB_DIST) {
4732 sprintf(numBuf, "%d", LanguageModes[i]->tabDist);
4733 BufInsert(outBuf, outBuf->length, numBuf);
4734 }
4735 BufInsert(outBuf, outBuf->length, ":");
4736 if (LanguageModes[i]->emTabDist != DEFAULT_EM_TAB_DIST) {
4737 sprintf(numBuf, "%d", LanguageModes[i]->emTabDist);
4738 BufInsert(outBuf, outBuf->length, numBuf);
4739 }
4740 BufInsert(outBuf, outBuf->length, ":");
4741 if (LanguageModes[i]->delimiters != NULL) {
4742 BufInsert(outBuf, outBuf->length,
4743 str=MakeQuotedString(LanguageModes[i]->delimiters));
4744 NEditFree(str);
4745 }
4746 BufInsert(outBuf, outBuf->length, ":");
4747 if (LanguageModes[i]->defTipsFile != NULL) {
4748 BufInsert(outBuf, outBuf->length,
4749 str=MakeQuotedString(LanguageModes[i]->defTipsFile));
4750 NEditFree(str);
4751 }
4752
4753 BufInsert(outBuf, outBuf->length, "\n");
4754 }
4755
4756 /* Get the output, and lop off the trailing newline */
4757 outStr = BufGetRange(outBuf, 0, outBuf->length - 1);
4758 BufFree(outBuf);
4759 escapedStr = EscapeSensitiveChars(outStr);
4760 NEditFree(outStr);
4761 return escapedStr;
4762 }
4763
createExtString(char ** extensions,int nExtensions)4764 static char *createExtString(char **extensions, int nExtensions)
4765 {
4766 int e, length = 1;
4767 char *outStr, *outPtr;
4768
4769 for (e=0; e<nExtensions; e++)
4770 length += strlen(extensions[e]) + 1;
4771 outStr = outPtr = (char*)NEditMalloc(length);
4772 for (e=0; e<nExtensions; e++) {
4773 strcpy(outPtr, extensions[e]);
4774 outPtr += strlen(extensions[e]);
4775 *outPtr++ = ' ';
4776 }
4777 if (nExtensions == 0)
4778 *outPtr = '\0';
4779 else
4780 *(outPtr-1) = '\0';
4781 return outStr;
4782 }
4783
readExtensionList(char ** inPtr,int * nExtensions)4784 static char **readExtensionList(char **inPtr, int *nExtensions)
4785 {
4786 char *extensionList[MAX_FILE_EXTENSIONS];
4787 char **retList, *strStart;
4788 int i, len;
4789
4790 /* skip over blank space */
4791 *inPtr += strspn(*inPtr, " \t");
4792
4793 for (i=0; i<MAX_FILE_EXTENSIONS && **inPtr!=':' && **inPtr!='\0'; i++) {
4794 *inPtr += strspn(*inPtr, " \t");
4795 strStart = *inPtr;
4796 while (**inPtr!=' ' && **inPtr!='\t' && **inPtr!=':' && **inPtr!='\0')
4797 (*inPtr)++;
4798 len = *inPtr - strStart;
4799 extensionList[i] = (char*)NEditMalloc(len + 1);
4800 strncpy(extensionList[i], strStart, len);
4801 extensionList[i][len] = '\0';
4802 }
4803 *nExtensions = i;
4804 if (i == 0)
4805 return NULL;
4806 retList = (char **)NEditMalloc(sizeof(char *) * i);
4807 memcpy(retList, extensionList, sizeof(char *) * i);
4808 return retList;
4809 }
4810
ReadNumericField(char ** inPtr,int * value)4811 int ReadNumericField(char **inPtr, int *value)
4812 {
4813 int charsRead;
4814
4815 /* skip over blank space */
4816 *inPtr += strspn(*inPtr, " \t");
4817
4818 if (sscanf(*inPtr, "%d%n", value, &charsRead) != 1)
4819 return False;
4820 *inPtr += charsRead;
4821 return True;
4822 }
4823
4824 /*
4825 ** Parse a symbolic field, skipping initial and trailing whitespace,
4826 ** stops on first invalid character or end of string. Valid characters
4827 ** are letters, numbers, _, -, +, $, #, and internal whitespace. Internal
4828 ** whitespace is compressed to single space characters.
4829 */
ReadSymbolicField(char ** inPtr)4830 char *ReadSymbolicField(char **inPtr)
4831 {
4832 char *outStr, *outPtr, *strStart, *strPtr;
4833 int len;
4834
4835 /* skip over initial blank space */
4836 *inPtr += strspn(*inPtr, " \t");
4837
4838 /* Find the first invalid character or end of string to know how
4839 much memory to allocate for the returned string */
4840 strStart = *inPtr;
4841 while (isalnum((unsigned char)**inPtr) || **inPtr=='_' || **inPtr=='-' ||
4842 **inPtr=='+' || **inPtr=='$' || **inPtr=='#' || **inPtr==' ' ||
4843 **inPtr=='\t')
4844 (*inPtr)++;
4845 len = *inPtr - strStart;
4846 if (len == 0)
4847 return NULL;
4848 outStr = outPtr = (char*)NEditMalloc(len + 1);
4849
4850 /* Copy the string, compressing internal whitespace to a single space */
4851 strPtr = strStart;
4852 while (strPtr - strStart < len) {
4853 if (*strPtr == ' ' || *strPtr == '\t') {
4854 strPtr += strspn(strPtr, " \t");
4855 *outPtr++ = ' ';
4856 } else
4857 *outPtr++ = *strPtr++;
4858 }
4859
4860 /* If there's space on the end, take it back off */
4861 if (outPtr > outStr && *(outPtr-1) == ' ')
4862 outPtr--;
4863 if (outPtr == outStr) {
4864 NEditFree(outStr);
4865 return NULL;
4866 }
4867 *outPtr = '\0';
4868 return outStr;
4869 }
4870
4871 /*
4872 ** parse an individual quoted string. Anything between
4873 ** double quotes is acceptable, quote characters can be escaped by "".
4874 ** Returns allocated string "string" containing
4875 ** argument minus quotes. If not successful, returns False with
4876 ** (statically allocated) message in "errMsg".
4877 */
ReadQuotedString(char ** inPtr,char ** errMsg,char ** string)4878 int ReadQuotedString(char **inPtr, char **errMsg, char **string)
4879 {
4880 char *outPtr, *c;
4881
4882 /* skip over blank space */
4883 *inPtr += strspn(*inPtr, " \t");
4884
4885 /* look for initial quote */
4886 if (**inPtr != '\"') {
4887 *errMsg = "expecting quoted string";
4888 return False;
4889 }
4890 (*inPtr)++;
4891
4892 /* calculate max length and allocate returned string */
4893 for (c= *inPtr; ; c++) {
4894 if (*c == '\0') {
4895 *errMsg = "string not terminated";
4896 return False;
4897 } else if (*c == '\"') {
4898 if (*(c+1) == '\"')
4899 c++;
4900 else
4901 break;
4902 }
4903 }
4904
4905 /* copy string up to end quote, transforming escaped quotes into quotes */
4906 *string = (char*)NEditMalloc(c - *inPtr + 1);
4907 outPtr = *string;
4908 while (True) {
4909 if (**inPtr == '\"') {
4910 if (*(*inPtr+1) == '\"')
4911 (*inPtr)++;
4912 else
4913 break;
4914 }
4915 *outPtr++ = *(*inPtr)++;
4916 }
4917 *outPtr = '\0';
4918
4919 /* skip end quote */
4920 (*inPtr)++;
4921 return True;
4922 }
4923
4924 /*
4925 ** Replace characters which the X resource file reader considers control
4926 ** characters, such that a string will read back as it appears in "string".
4927 ** (So far, newline characters are replaced with with \n\<newline> and
4928 ** backslashes with \\. This has not been tested exhaustively, and
4929 ** probably should be. It would certainly be more asthetic if other
4930 ** control characters were replaced as well).
4931 **
4932 ** Returns an allocated string which must be freed by the caller with NEditFree.
4933 */
EscapeSensitiveChars(const char * string)4934 char *EscapeSensitiveChars(const char *string)
4935 {
4936 const char *c;
4937 char *outStr, *outPtr;
4938 int length = 0;
4939
4940 /* calculate length and allocate returned string */
4941 for (c=string; *c!='\0'; c++) {
4942 if (*c == '\\')
4943 length++;
4944 else if (*c == '\n')
4945 length += 3;
4946 length++;
4947 }
4948 outStr = (char*)NEditMalloc(length + 1);
4949 outPtr = outStr;
4950
4951 /* add backslashes */
4952 for (c=string; *c!='\0'; c++) {
4953 if (*c == '\\')
4954 *outPtr++ = '\\';
4955 else if (*c == '\n') {
4956 *outPtr++ = '\\';
4957 *outPtr++ = 'n';
4958 *outPtr++ = '\\';
4959 }
4960 *outPtr++ = *c;
4961 }
4962 *outPtr = '\0';
4963 return outStr;
4964 }
4965
4966 /*
4967 ** Adds double quotes around a string and escape existing double quote
4968 ** characters with two double quotes. Enables the string to be read back
4969 ** by ReadQuotedString.
4970 */
MakeQuotedString(const char * string)4971 char *MakeQuotedString(const char *string)
4972 {
4973 const char *c;
4974 char *outStr, *outPtr;
4975 int length = 0;
4976
4977 /* calculate length and allocate returned string */
4978 for (c=string; *c!='\0'; c++) {
4979 if (*c == '\"')
4980 length++;
4981 length++;
4982 }
4983 outStr = (char*)NEditMalloc(length + 3);
4984 outPtr = outStr;
4985
4986 /* add starting quote */
4987 *outPtr++ = '\"';
4988
4989 /* copy string, escaping quotes with "" */
4990 for (c=string; *c!='\0'; c++) {
4991 if (*c == '\"')
4992 *outPtr++ = '\"';
4993 *outPtr++ = *c;
4994 }
4995
4996 /* add ending quote */
4997 *outPtr++ = '\"';
4998
4999 /* terminate string and return */
5000 *outPtr = '\0';
5001 return outStr;
5002 }
5003
5004 /*
5005 ** Read a dialog text field containing a symbolic name (language mode names,
5006 ** style names, highlight pattern names, colors, and fonts), clean the
5007 ** entered text of leading and trailing whitespace, compress all
5008 ** internal whitespace to one space character, and check it over for
5009 ** colons, which interfere with the preferences file reader/writer syntax.
5010 ** Returns NULL on error, and puts up a dialog if silent is False. Returns
5011 ** an empty string if the text field is blank.
5012 */
ReadSymbolicFieldTextWidget(Widget textW,const char * fieldName,int silent)5013 char *ReadSymbolicFieldTextWidget(Widget textW, const char *fieldName, int silent)
5014 {
5015 char *string, *stringPtr, *parsedString;
5016
5017 /* read from the text widget */
5018 string = stringPtr = XmTextGetString(textW);
5019
5020 /* parse it with the same routine used to read symbolic fields from
5021 files. If the string is not read entirely, there are invalid
5022 characters, so warn the user if not in silent mode. */
5023 parsedString = ReadSymbolicField(&stringPtr);
5024 if (*stringPtr != '\0')
5025 {
5026 if (!silent)
5027 {
5028 *(stringPtr + 1) = '\0';
5029 DialogF(DF_WARN, textW, 1, "Invalid Character",
5030 "Invalid character \"%s\" in %s", "OK", stringPtr,
5031 fieldName);
5032 XmProcessTraversal(textW, XmTRAVERSE_CURRENT);
5033 }
5034 NEditFree(string);
5035 NEditFree(parsedString);
5036 return NULL;
5037 }
5038 NEditFree(string);
5039 if (parsedString == NULL) {
5040 parsedString = NEditStrdup("");
5041 }
5042 return parsedString;
5043 }
5044
5045 /*
5046 ** Create a pulldown menu pane with the names of the current language modes.
5047 ** XmNuserData for each item contains the language mode name.
5048 */
CreateLanguageModeMenu(Widget parent,XtCallbackProc cbProc,void * cbArg)5049 Widget CreateLanguageModeMenu(Widget parent, XtCallbackProc cbProc, void *cbArg)
5050 {
5051 Widget menu, btn;
5052 int i;
5053 XmString s1;
5054
5055 menu = CreatePulldownMenu(parent, "languageModes", NULL, 0);
5056 for (i=0; i<NLanguageModes; i++) {
5057 btn = XtVaCreateManagedWidget("languageMode", xmPushButtonGadgetClass,
5058 menu,
5059 XmNlabelString, s1=XmStringCreateSimple(LanguageModes[i]->name),
5060 XmNmarginHeight, 0,
5061 XmNuserData, (void *)LanguageModes[i]->name, NULL);
5062 XmStringFree(s1);
5063 XtAddCallback(btn, XmNactivateCallback, cbProc, cbArg);
5064 }
5065 return menu;
5066 }
5067
5068 /*
5069 ** Set the language mode menu in option menu "optMenu" to
5070 ** show a particular language mode
5071 */
SetLangModeMenu(Widget optMenu,const char * modeName)5072 void SetLangModeMenu(Widget optMenu, const char *modeName)
5073 {
5074 int i;
5075 Cardinal nItems;
5076 WidgetList items;
5077 Widget pulldown, selectedItem;
5078 char *itemName;
5079
5080 XtVaGetValues(optMenu, XmNsubMenuId, &pulldown, NULL);
5081 XtVaGetValues(pulldown, XmNchildren, &items, XmNnumChildren, &nItems, NULL);
5082 if (nItems == 0)
5083 return;
5084 selectedItem = items[0];
5085 for (i=0; i<(int)nItems; i++) {
5086 XtVaGetValues(items[i], XmNuserData, &itemName, NULL);
5087 if (!strcmp(itemName, modeName)) {
5088 selectedItem = items[i];
5089 break;
5090 }
5091 }
5092 XtVaSetValues(optMenu, XmNmenuHistory, selectedItem,NULL);
5093 }
5094
5095 /*
5096 ** Create a submenu for chosing language mode for the current window.
5097 */
CreateLanguageModeSubMenu(WindowInfo * window,const Widget parent,const char * name,const char * label,char mnemonic)5098 void CreateLanguageModeSubMenu(WindowInfo* window, const Widget parent,
5099 const char* name, const char* label, char mnemonic)
5100 {
5101 XmString string = XmStringCreateSimple((char*) label);
5102
5103 window->langModeCascade = XtVaCreateManagedWidget(name,
5104 xmCascadeButtonGadgetClass, parent,
5105 XmNlabelString, string,
5106 XmNmnemonic, mnemonic,
5107 XmNsubMenuId, NULL,
5108 NULL);
5109 XmStringFree(string);
5110
5111 updateLanguageModeSubmenu(window);
5112 }
5113
5114 /*
5115 ** Re-build the language mode sub-menu using the current data stored
5116 ** in the master list: LanguageModes.
5117 */
updateLanguageModeSubmenu(WindowInfo * window)5118 static void updateLanguageModeSubmenu(WindowInfo *window)
5119 {
5120 int i;
5121 XmString s1;
5122 Widget menu, btn;
5123 Arg args[1] = {{XmNradioBehavior, (XtArgVal)True}};
5124
5125 /* Destroy and re-create the menu pane */
5126 XtVaGetValues(window->langModeCascade, XmNsubMenuId, &menu, NULL);
5127 if (menu != NULL)
5128 XtDestroyWidget(menu);
5129 menu = CreatePulldownMenu(XtParent(window->langModeCascade),
5130 "languageModes", args, 1);
5131 btn = XtVaCreateManagedWidget("languageMode",
5132 xmToggleButtonGadgetClass, menu,
5133 XmNlabelString, s1=XmStringCreateSimple("Plain"),
5134 XmNuserData, (void *)PLAIN_LANGUAGE_MODE,
5135 XmNset, window->languageMode==PLAIN_LANGUAGE_MODE, NULL);
5136 XmStringFree(s1);
5137 XtAddCallback(btn, XmNvalueChangedCallback, setLangModeCB, window);
5138 for (i=0; i<NLanguageModes; i++) {
5139 btn = XtVaCreateManagedWidget("languageMode",
5140 xmToggleButtonGadgetClass, menu,
5141 XmNlabelString, s1=XmStringCreateSimple(LanguageModes[i]->name),
5142 XmNmarginHeight, 0,
5143 XmNuserData, (void *)(intptr_t)i,
5144 XmNset, window->languageMode==i, NULL);
5145 XmStringFree(s1);
5146 XtAddCallback(btn, XmNvalueChangedCallback, setLangModeCB, window);
5147 }
5148 XtVaSetValues(window->langModeCascade, XmNsubMenuId, menu, NULL);
5149 }
5150
setLangModeCB(Widget w,XtPointer clientData,XtPointer callData)5151 static void setLangModeCB(Widget w, XtPointer clientData, XtPointer callData)
5152 {
5153 WindowInfo *window = WidgetToWindow(MENU_WIDGET(w));
5154 char *params[1];
5155 void *mode;
5156
5157 if (!XmToggleButtonGetState(w))
5158 return;
5159
5160 /* get name of language mode stored in userData field of menu item */
5161 XtVaGetValues(w, XmNuserData, &mode, NULL);
5162
5163 /* If the mode didn't change, do nothing */
5164 if (window->languageMode == (int)(intptr_t)mode)
5165 return;
5166
5167 /* redo syntax highlighting word delimiters, etc. */
5168 /*
5169 reapplyLanguageMode(window, (int)mode, False);
5170 */
5171 params[0] = (((int)(intptr_t)mode) == PLAIN_LANGUAGE_MODE) ? "" : LanguageModes[(int)(intptr_t)mode]->name;
5172 XtCallActionProc(window->textArea, "set_language_mode", NULL, params, 1);
5173 }
5174
5175 /*
5176 ** Skip a delimiter and it's surrounding whitespace
5177 */
SkipDelimiter(char ** inPtr,char ** errMsg)5178 int SkipDelimiter(char **inPtr, char **errMsg)
5179 {
5180 *inPtr += strspn(*inPtr, " \t");
5181 if (**inPtr != ':') {
5182 *errMsg = "syntax error";
5183 return False;
5184 }
5185 (*inPtr)++;
5186 *inPtr += strspn(*inPtr, " \t");
5187 return True;
5188 }
5189
5190 /*
5191 ** Skip an optional separator and its surrounding whitespace
5192 ** return true if delimiter found
5193 */
SkipOptSeparator(char separator,char ** inPtr)5194 int SkipOptSeparator(char separator, char **inPtr)
5195 {
5196 *inPtr += strspn(*inPtr, " \t");
5197 if (**inPtr != separator) {
5198 return False;
5199 }
5200 (*inPtr)++;
5201 *inPtr += strspn(*inPtr, " \t");
5202 return True;
5203 }
5204
5205 /*
5206 ** Short-hand error processing for language mode parsing errors, frees
5207 ** lm (if non-null), prints a formatted message explaining where the
5208 ** error is, and returns False;
5209 */
modeError(languageModeRec * lm,const char * stringStart,const char * stoppedAt,const char * message)5210 static int modeError(languageModeRec *lm, const char *stringStart,
5211 const char *stoppedAt, const char *message)
5212 {
5213 if (lm != NULL)
5214 freeLanguageModeRec(lm);
5215 return ParseError(NULL, stringStart, stoppedAt,
5216 "language mode specification", message);
5217 }
5218
5219 /*
5220 ** Report parsing errors in resource strings or macros, formatted nicely so
5221 ** the user can tell where things became botched. Errors can be sent either
5222 ** to stderr, or displayed in a dialog. For stderr, pass toDialog as NULL.
5223 ** For a dialog, pass the dialog parent in toDialog.
5224 */
ParseError(Widget toDialog,const char * stringStart,const char * stoppedAt,const char * errorIn,const char * message)5225 int ParseError(Widget toDialog, const char *stringStart, const char *stoppedAt,
5226 const char *errorIn, const char *message)
5227 {
5228 int len, nNonWhite = 0;
5229 const char *c;
5230 char *errorLine;
5231
5232 for (c=stoppedAt; c>=stringStart; c--) {
5233 if (c == stringStart)
5234 break;
5235 else if (*c == '\n' && nNonWhite >= 5)
5236 break;
5237 else if (*c != ' ' && *c != '\t')
5238 nNonWhite++;
5239 }
5240 len = stoppedAt - c + (*stoppedAt == '\0' ? 0 : 1);
5241 errorLine = (char*)NEditMalloc(len+4);
5242 strncpy(errorLine, c, len);
5243 errorLine[len++] = '<';
5244 errorLine[len++] = '=';
5245 errorLine[len++] = '=';
5246 errorLine[len] = '\0';
5247 if (toDialog == NULL)
5248 {
5249 fprintf(stderr, "NEdit: %s in %s:\n%s\n", message, errorIn, errorLine);
5250 } else
5251 {
5252 DialogF(DF_WARN, toDialog, 1, "Parse Error", "%s in %s:\n%s", "OK",
5253 message, errorIn, errorLine);
5254 }
5255 NEditFree(errorLine);
5256 return False;
5257 }
5258
5259 /*
5260 ** Compare two strings which may be NULL
5261 */
AllocatedStringsDiffer(const char * s1,const char * s2)5262 int AllocatedStringsDiffer(const char *s1, const char *s2)
5263 {
5264 if (s1 == NULL && s2 == NULL)
5265 return False;
5266 if (s1 == NULL || s2 == NULL)
5267 return True;
5268 return strcmp(s1, s2);
5269 }
5270
updatePatternsTo5dot1(void)5271 static void updatePatternsTo5dot1(void)
5272 {
5273 const char *htmlDefaultExpr = "^[ \t]*HTML[ \t]*:[ \t]*Default[ \t]*$";
5274 const char *vhdlAnchorExpr = "^[ \t]*VHDL:";
5275
5276 /* Add new patterns if there aren't already existing patterns with
5277 the same name. If possible, insert before VHDL in language mode
5278 list. If not, just add to end */
5279 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*PostScript:"))
5280 spliceString(&TempStringPrefs.highlight, "PostScript:Default",
5281 vhdlAnchorExpr);
5282 if (!regexFind(TempStringPrefs.language, "^[ \t]*PostScript:"))
5283 spliceString(&TempStringPrefs.language,
5284 "PostScript:.ps .PS .eps .EPS .epsf .epsi::::::",
5285 vhdlAnchorExpr);
5286 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*Lex:"))
5287 spliceString(&TempStringPrefs.highlight, "Lex:Default",
5288 vhdlAnchorExpr);
5289 if (!regexFind(TempStringPrefs.language, "^[ \t]*Lex:"))
5290 spliceString(&TempStringPrefs.language, "Lex:.lex::::::",
5291 vhdlAnchorExpr);
5292 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*SQL:"))
5293 spliceString(&TempStringPrefs.highlight, "SQL:Default",
5294 vhdlAnchorExpr);
5295 if (!regexFind(TempStringPrefs.language, "^[ \t]*SQL:"))
5296 spliceString(&TempStringPrefs.language, "SQL:.sql::::::",
5297 vhdlAnchorExpr);
5298 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*Matlab:"))
5299 spliceString(&TempStringPrefs.highlight, "Matlab:Default",
5300 vhdlAnchorExpr);
5301 if (!regexFind(TempStringPrefs.language, "^[ \t]*Matlab:"))
5302 spliceString(&TempStringPrefs.language, "Matlab:..m .oct .sci::::::",
5303 vhdlAnchorExpr);
5304 if (!regexFind(TempStringPrefs.smartIndent, "^[ \t]*Matlab:"))
5305 spliceString(&TempStringPrefs.smartIndent, "Matlab:Default", NULL);
5306 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Label:"))
5307 spliceString(&TempStringPrefs.styles, "Label:red:Italic",
5308 "^[ \t]*Flag:");
5309 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Storage Type1:"))
5310 spliceString(&TempStringPrefs.styles, "Storage Type1:saddle brown:Bold",
5311 "^[ \t]*String:");
5312
5313 /* Replace html pattern with sgml html pattern, as long as there
5314 isn't an existing html pattern which will be overwritten */
5315 if (regexFind(TempStringPrefs.highlight, htmlDefaultExpr)) {
5316 regexReplace(&TempStringPrefs.highlight, htmlDefaultExpr,
5317 "SGML HTML:Default");
5318 if (!regexReplace(&TempStringPrefs.language, "^[ \t]*HTML:.*$",
5319 "SGML HTML:.sgml .sgm .html .htm:\"\\<(?ihtml)\\>\":::::\n")) {
5320 spliceString(&TempStringPrefs.language,
5321 "SGML HTML:.sgml .sgm .html .htm:\"\\<(?ihtml)\\>\":::::\n",
5322 vhdlAnchorExpr);
5323 }
5324 }
5325 }
5326
updatePatternsTo5dot2(void)5327 static void updatePatternsTo5dot2(void)
5328 {
5329 #ifdef VMS
5330 const char *cppLm5dot1 =
5331 "^[ \t]*C\\+\\+:\\.CC \\.HH \\.I::::::\"\\.,/\\\\`'!\\|@#%\\^&\\*\\(\\)-=\\+\\{\\}\\[\\]\"\":;\\<\\>\\?~\"";
5332 const char *perlLm5dot1 =
5333 "^[ \t]*Perl:\\.PL \\.PM \\.P5:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\.\\*perl\":::::";
5334 const char *psLm5dot1 =
5335 "^[ \t]*PostScript:\\.ps \\.PS \\.eps \\.EPS \\.epsf \\.epsi:\"\\^%!\":::::\"/%\\(\\)\\{\\}\\[\\]\\<\\>\"";
5336 const char *tclLm5dot1 = "^[ \t]*Tcl:\\.TCL::::::";
5337
5338 const char *cppLm5dot2 =
5339 "C++:.CC .HH .C .H .I .CXX .HXX .CPP::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\"";
5340 const char *perlLm5dot2 =
5341 "Perl:.PL .PM .P5:\"^[ \\t]*#[ \\t]*!.*perl\":Auto:None:::\".,/\\\\`'!$@#%^&*()-=+{}[]\"\":;<>?~|\"";
5342 const char *psLm5dot2 =
5343 "PostScript:.ps .PS .eps .EPS .epsf .epsi:\"^%!\":::::\"/%(){}[]<>\"";
5344 const char *tclLm5dot2 =
5345 "Tcl:.TCL::Smart:None:::";
5346 #else
5347 const char *cppLm5dot1 =
5348 "^[ \t]*C\\+\\+:\\.cc \\.hh \\.C \\.H \\.i \\.cxx \\.hxx::::::\"\\.,/\\\\`'!\\|@#%\\^&\\*\\(\\)-=\\+\\{\\}\\[\\]\"\":;\\<\\>\\?~\"";
5349 const char *perlLm5dot1 =
5350 "^[ \t]*Perl:\\.pl \\.pm \\.p5:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\.\\*perl\":::::";
5351 const char *psLm5dot1 =
5352 "^[ \t]*PostScript:\\.ps \\.PS \\.eps \\.EPS \\.epsf \\.epsi:\"\\^%!\":::::\"/%\\(\\)\\{\\}\\[\\]\\<\\>\"";
5353 const char *shLm5dot1 =
5354 "^[ \t]*Sh Ksh Bash:\\.sh \\.bash \\.ksh \\.profile:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\[ \\\\t\\]\\*/bin/\\(sh\\|ksh\\|bash\\)\":::::";
5355 const char *tclLm5dot1 = "^[ \t]*Tcl:\\.tcl::::::";
5356
5357 const char *cppLm5dot2 =
5358 "C++:.cc .hh .C .H .i .cxx .hxx .cpp::::::\".,/\\`'!|@#%^&*()-=+{}[]\"\":;<>?~\"";
5359 const char *perlLm5dot2 =
5360 "Perl:.pl .pm .p5 .PL:\"^[ \\t]*#[ \\t]*!.*perl\":Auto:None:::\".,/\\\\`'!$@#%^&*()-=+{}[]\"\":;<>?~|\"";
5361 const char *psLm5dot2 =
5362 "PostScript:.ps .eps .epsf .epsi:\"^%!\":::::\"/%(){}[]<>\"";
5363 const char *shLm5dot2 =
5364 "Sh Ksh Bash:.sh .bash .ksh .profile .bashrc .bash_logout .bash_login .bash_profile:\"^[ \\t]*#[ \\t]*![ \\t]*/.*bin/(sh|ksh|bash)\":::::";
5365 const char *tclLm5dot2 =
5366 "Tcl:.tcl .tk .itcl .itk::Smart:None:::";
5367 #endif /* VMS */
5368
5369 const char *cssLm5dot2 =
5370 "CSS:css::Auto:None:::\".,/\\`'!|@#%^&*()=+{}[]\"\":;<>?~\"";
5371 const char *reLm5dot2 =
5372 "Regex:.reg .regex:\"\\(\\?[:#=!iInN].+\\)\":None:Continuous:::";
5373 const char *xmlLm5dot2 =
5374 "XML:.xml .xsl .dtd:\"\\<(?i\\?xml|!doctype)\"::None:::\"<>/=\"\"'()+*?|\"";
5375
5376 const char *cssHl5dot2 = "CSS:Default";
5377 const char *reHl5dot2 = "Regex:Default";
5378 const char *xmlHl5dot2 = "XML:Default";
5379
5380 const char *ptrStyle = "Pointer:#660000:Bold";
5381 const char *reStyle = "Regex:#009944:Bold";
5382 const char *wrnStyle = "Warning:brown2:Italic";
5383
5384 /* First upgrade modified language modes, only if the user hasn't
5385 altered the default 5.1 definitions. */
5386 if (regexFind(TempStringPrefs.language, cppLm5dot1))
5387 regexReplace(&TempStringPrefs.language, cppLm5dot1, cppLm5dot2);
5388 if (regexFind(TempStringPrefs.language, perlLm5dot1))
5389 regexReplace(&TempStringPrefs.language, perlLm5dot1, perlLm5dot2);
5390 if (regexFind(TempStringPrefs.language, psLm5dot1))
5391 regexReplace(&TempStringPrefs.language, psLm5dot1, psLm5dot2);
5392 #ifndef VMS
5393 if (regexFind(TempStringPrefs.language, shLm5dot1))
5394 regexReplace(&TempStringPrefs.language, shLm5dot1, shLm5dot2);
5395 #endif
5396 if (regexFind(TempStringPrefs.language, tclLm5dot1))
5397 regexReplace(&TempStringPrefs.language, tclLm5dot1, tclLm5dot2);
5398
5399 /* Then append the new modes (trying to keep them in alphabetical order
5400 makes no sense, since 5.1 didn't use alphabetical order). */
5401 if (!regexFind(TempStringPrefs.language, "^[ \t]*CSS:"))
5402 spliceString(&TempStringPrefs.language, cssLm5dot2, NULL);
5403 if (!regexFind(TempStringPrefs.language, "^[ \t]*Regex:"))
5404 spliceString(&TempStringPrefs.language, reLm5dot2, NULL);
5405 if (!regexFind(TempStringPrefs.language, "^[ \t]*XML:"))
5406 spliceString(&TempStringPrefs.language, xmlLm5dot2, NULL);
5407
5408 /* Enable default highlighting patterns for these modes, unless already
5409 present */
5410 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*CSS:"))
5411 spliceString(&TempStringPrefs.highlight, cssHl5dot2, NULL);
5412 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*Regex:"))
5413 spliceString(&TempStringPrefs.highlight, reHl5dot2, NULL);
5414 if (!regexFind(TempStringPrefs.highlight, "^[ \t]*XML:"))
5415 spliceString(&TempStringPrefs.highlight, xmlHl5dot2, NULL);
5416
5417 /* Finally, append the new highlight styles */
5418
5419 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Warning:"))
5420 spliceString(&TempStringPrefs.styles, wrnStyle, NULL);
5421 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Regex:"))
5422 spliceString(&TempStringPrefs.styles, reStyle, "^[ \t]*Warning:");
5423 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Pointer:"))
5424 spliceString(&TempStringPrefs.styles, ptrStyle, "^[ \t]*Regex:");
5425 }
5426
updatePatternsTo5dot3(void)5427 static void updatePatternsTo5dot3(void)
5428 {
5429 /* This is a bogus function on non-VMS */
5430 #ifdef VMS
5431 const char *psLm5dot2 =
5432 "^[ \t]*PostScript:\\.ps \\.PS \\.eps \\.EPS \\.epsf \\.epsi:\"\\^%!\":::::\"/%\\(\\)\\{\\}\\[\\]\\<\\>\"";
5433
5434 const char *psLm5dot3 =
5435 "PostScript:.ps .PS .eps .EPS .epsf .EPSF .epsi .EPSI:\"^%!\":::::\"/%(){}[]<>\"";
5436
5437 /* Upgrade modified language modes, only if the user hasn't
5438 altered the default 5.2 definitions. */
5439 if (regexFind(TempStringPrefs.language, psLm5dot2))
5440 regexReplace(&TempStringPrefs.language, psLm5dot2, psLm5dot3);
5441 #endif
5442 }
5443
updatePatternsTo5dot4(void)5444 static void updatePatternsTo5dot4(void)
5445 {
5446 #ifdef VMS
5447 const char *pyLm5dot3 =
5448 "Python:\\.PY:\"\\^#!\\.\\*python\":Auto:None::::?\n";
5449 const char *xrLm5dot3 =
5450 "X Resources:\\.XRESOURCES \\.XDEFAULTS \\.NEDIT:\"\\^\\[!#\\]\\.\\*\\(\\[Aa\\]pp\\|\\[Xx\\]\\)\\.\\*\\[Dd\\]efaults\"::::::?\n";
5451
5452 const char *pyLm5dot4 =
5453 "Python:.PY:\"^#!.*python\":Auto:None:::\"!\"\"#$%&'()*+,-./:;<=>?@[\\\\]^`{|}~\":\n";
5454 const char *xrLm5dot4 =
5455 "X Resources:.XRESOURCES .XDEFAULTS .NEDIT NEDIT.RC:\"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults\"::::::\n";
5456 #else
5457 const char *pyLm5dot3 =
5458 "Python:\\.py:\"\\^#!\\.\\*python\":Auto:None::::?\n";
5459 const char *xrLm5dot3 =
5460 "X Resources:\\.Xresources \\.Xdefaults \\.nedit:\"\\^\\[!#\\]\\.\\*\\(\\[Aa\\]pp\\|\\[Xx\\]\\)\\.\\*\\[Dd\\]efaults\"::::::?\n";
5461
5462 const char *pyLm5dot4 =
5463 "Python:.py:\"^#!.*python\":Auto:None:::\"!\"\"#$%&'()*+,-./:;<=>?@[\\\\]^`{|}~\":\n";
5464 const char *xrLm5dot4 =
5465 "X Resources:.Xresources .Xdefaults .nedit nedit.rc:\"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults\"::::::\n";
5466 #endif
5467
5468 /* Upgrade modified language modes, only if the user hasn't
5469 altered the default 5.3 definitions. */
5470 if (regexFind(TempStringPrefs.language, pyLm5dot3))
5471 regexReplace(&TempStringPrefs.language, pyLm5dot3, pyLm5dot4);
5472 if (regexFind(TempStringPrefs.language, xrLm5dot3))
5473 regexReplace(&TempStringPrefs.language, xrLm5dot3, xrLm5dot4);
5474
5475 /* Add new styles */
5476 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Identifier2:"))
5477 spliceString(&TempStringPrefs.styles, "Identifier2:SteelBlue:Plain",
5478 "^[ \t]*Subroutine:");
5479 }
5480
updatePatternsTo5dot6(void)5481 static void updatePatternsTo5dot6(void)
5482 {
5483 const char *pats[] = {
5484 #ifndef VMS
5485 "Csh:\\.csh \\.cshrc \\.login \\.logout:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\[ \\\\t\\]\\*/bin/csh\"::::::\\n",
5486 "Csh:.csh .cshrc .tcshrc .login .logout:\"^[ \\t]*#[ \\t]*![ \\t]*/bin/t?csh\"::::::\n",
5487 "LaTeX:\\.tex \\.sty \\.cls \\.ltx \\.ins:::::::\\n",
5488 "LaTeX:.tex .sty .cls .ltx .ins .clo .fd:::::::\n",
5489 "X Resources:\\.Xresources \\.Xdefaults \\.nedit:\"\\^\\[!#\\]\\.\\*\\(\\[Aa\\]pp\\|\\[Xx\\]\\)\\.\\*\\[Dd\\]efaults\"::::::\\n",
5490 "X Resources:.Xresources .Xdefaults .nedit .pats nedit.rc:\"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults\"::::::\n",
5491 #else
5492 "Csh:\\.csh \\.cshrc \\.login \\.logout:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\[ \\\\t\\]\\*/bin/csh\"::::::\\n",
5493 "Csh:.CSH .CSHRC .TCSHRC .LOGIN .LOGOUT:\"^[ \\t]*#[ \\t]*![ \\t]*/bin/t?csh\"::::::\n",
5494 "LaTeX:\\.TEX \\.STY \\.CLS \\.LTX \\.INS:::::::\\n",
5495 "LaTeX:.TEX .STY .CLS .LTX .INS .CLO .FD:::::::\n",
5496 "Lex:\\.lex:::::::\\n",
5497 "Lex:.LEX:::::::\n",
5498 "Matlab:\\.m \\.oct \\.sci:::::::\\n",
5499 "Matlab:.M .OCT .SCI:::::::\n",
5500 "Regex:\\.reg \\.regex:\"\\\\\\(\\\\\\?\\[:#=!iInN\\]\\.\\+\\\\\\\)\":None:Continuous::::\\n",
5501 "Regex:.REG .REGEX:\"\\(\\?[:#=!iInN].+\\)\":None:Continuous::::\n",
5502 "SGML HTML:\\.sgml \\.sgm \\.html \\.htm:\"\\\\\\<\\[Hh\\]\\[Tt\\]\\[Mm\\]\\[Ll\\]\\\\\\>\"::::::\\n",
5503 "SGML HTML:.SGML .SGM .HTML .HTM:\"\\<[Hh][Tt][Mm][Ll]\\>\"::::::\n",
5504 "SQL:\\.sql:::::::\\n",
5505 "SQL:.SQL:::::::\n",
5506 "Sh Ksh Bash:\\.sh \\.bash \\.ksh \\.profile \\.bashrc \\.bash_logout \\.bash_login \\.bash_profile:\"\\^\\[ \\\\t\\]\\*#\\[ \\\\t\\]\\*!\\[ \\\\t\\]\\*/\\.\\*bin/\\(bash\\|ksh\\|sh\\|zsh\\)\"::::::\\n",
5507 "Sh Ksh Bash:.SH .BASH .KSH .PROFILE .BASHRC .BASH_LOGOUT .BASH_LOGIN .BASH_PROFILE:\"^[ \\t]*#[ \\t]*![ \\t]*/.*bin/(bash|ksh|sh|zsh)\"::::::\n",
5508 "XML:\\.xml \\.xsl \\.dtd:\"\\\\\\<\\(\\?i\\\\\\?xml\\|!doctype\\)\"::None:::\"\\<\\>/=\"\"'\\(\\)\\+\\*\\?\\|\":\\n",
5509 "XML:.XML .XSL .DTD:\"\\<(?i\\?xml|!doctype)\"::None:::\"<>/=\"\"'()+*?|\":\n",
5510 "X Resources:\\.XRESOURCES \\.XDEFAULTS \\.NEDIT:\"\\^\\[!#\\]\\.\\*\\(\\[Aa\\]pp\\|\\[Xx\\]\\)\\.\\*\\[Dd\\]efaults\"::::::\\n",
5511 "X Resources:.XRESOURCES .XDEFAULTS .NEDIT .PATS NEDIT.RC:\"^[!#].*([Aa]pp|[Xx]).*[Dd]efaults\"::::::\n",
5512 #endif
5513 NULL };
5514
5515 /* Upgrade modified language modes, only if the user hasn't
5516 altered the default 5.5 definitions. */
5517 int i;
5518 for (i = 0; pats[i]; i+=2) {
5519 if (regexFind(TempStringPrefs.language, pats[i]))
5520 regexReplace(&TempStringPrefs.language, pats[i], pats[i+1]);
5521 }
5522
5523 /* Add new styles */
5524 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Bracket:"))
5525 spliceString(&TempStringPrefs.styles, "Bracket:dark blue:Bold",
5526 "^[ \t]*Storage Type:");
5527 if (!regexFind(TempStringPrefs.styles, "^[ \t]*Operator:"))
5528 spliceString(&TempStringPrefs.styles, "Operator:dark blue:Bold",
5529 "^[ \t]*Bracket:");
5530 }
5531
5532
5533 /*
5534 * We migrate a color from the X resources to the prefs if:
5535 * 1. The prefs entry is equal to the default entry
5536 * 2. The X resource is not equal to the default entry
5537 */
migrateColor(XrmDatabase prefDB,XrmDatabase appDB,char * class,char * name,int color_index,char * default_val)5538 static void migrateColor(XrmDatabase prefDB, XrmDatabase appDB,
5539 char *class, char *name, int color_index, char *default_val)
5540 {
5541 char *type, *valueString;
5542 XrmValue rsrcValue;
5543
5544 /* If this color has been customized in the color dialog then use
5545 that value */
5546 if ( strcmp(default_val, PrefData.colorNames[color_index]) )
5547 return;
5548
5549 /* Retrieve the value of the resource from the DB */
5550 if (XrmGetResource(prefDB, name, class, &type, &rsrcValue)) {
5551 if (strcmp(type, XmRString)) {
5552 fprintf(stderr,"Internal Error: Unexpected resource type, %s\n",
5553 type);
5554 return;
5555 }
5556 valueString = rsrcValue.addr;
5557 } else if (XrmGetResource(appDB, name, class, &type, &rsrcValue)) {
5558 if (strcmp(type, XmRString)) {
5559 fprintf(stderr,"Internal Error: Unexpected resource type, %s\n",
5560 type);
5561 return;
5562 }
5563 valueString = rsrcValue.addr;
5564 } else
5565 /* No resources set */
5566 return;
5567
5568 /* An X resource is set. If it's non-default, update the prefs. */
5569 if ( strcmp(valueString, default_val) ) {
5570 strncpy(PrefData.colorNames[color_index], valueString,
5571 MAX_COLOR_LEN);
5572 }
5573 }
5574
5575 /*
5576 * In 5.4 we moved color preferences from X resources to a color dialog,
5577 * meaning they're in the normal prefs system. Users who have customized
5578 * their colors with X resources would probably prefer not to have to redo
5579 * the customization in the dialog, so we migrate them to the prefs for them.
5580 */
migrateColorResources(XrmDatabase prefDB,XrmDatabase appDB)5581 static void migrateColorResources(XrmDatabase prefDB, XrmDatabase appDB)
5582 {
5583 migrateColor(prefDB, appDB, APP_CLASS ".Text.Foreground",
5584 APP_NAME ".text.foreground", TEXT_FG_COLOR,
5585 NEDIT_DEFAULT_FG);
5586 migrateColor(prefDB, appDB, APP_CLASS ".Text.Background",
5587 APP_NAME ".text.background", TEXT_BG_COLOR,
5588 NEDIT_DEFAULT_TEXT_BG);
5589 migrateColor(prefDB, appDB, APP_CLASS ".Text.SelectForeground",
5590 APP_NAME ".text.selectForeground", SELECT_FG_COLOR,
5591 NEDIT_DEFAULT_SEL_FG);
5592 migrateColor(prefDB, appDB, APP_CLASS ".Text.SelectBackground",
5593 APP_NAME ".text.selectBackground", SELECT_BG_COLOR,
5594 NEDIT_DEFAULT_SEL_BG);
5595 migrateColor(prefDB, appDB, APP_CLASS ".Text.HighlightForeground",
5596 APP_NAME ".text.highlightForeground", HILITE_FG_COLOR,
5597 NEDIT_DEFAULT_HI_FG);
5598 migrateColor(prefDB, appDB, APP_CLASS ".Text.HighlightBackground",
5599 APP_NAME ".text.highlightBackground", HILITE_BG_COLOR,
5600 NEDIT_DEFAULT_HI_BG);
5601 migrateColor(prefDB, appDB, APP_CLASS ".Text.LineNumForeground",
5602 APP_NAME ".text.lineNumForeground", LINENO_FG_COLOR,
5603 NEDIT_DEFAULT_LINENO_FG);
5604 migrateColor(prefDB, appDB, APP_CLASS ".Text.CursorForeground",
5605 APP_NAME ".text.cursorForeground", CURSOR_FG_COLOR,
5606 NEDIT_DEFAULT_CURSOR_FG);
5607 }
5608
5609 /*
5610 ** Inserts a string into intoString, reallocating it with nedit_realloc. If
5611 ** regular expression atExpr is found, inserts the string before atExpr
5612 ** followed by a newline. If atExpr is not found, inserts insertString
5613 ** at the end, PRECEDED by a newline.
5614 */
spliceString(char ** intoString,const char * insertString,const char * atExpr)5615 static void spliceString(char **intoString, const char *insertString, const char *atExpr)
5616 {
5617 int beginPos, endPos;
5618 int intoLen = strlen(*intoString);
5619 int insertLen = strlen(insertString);
5620 char *newString = (char*)NEditMalloc(intoLen + insertLen + 2);
5621
5622 if (atExpr != NULL && SearchString(*intoString, atExpr,
5623 SEARCH_FORWARD, SEARCH_REGEX, False, 0, &beginPos, &endPos,
5624 NULL, NULL, NULL)) {
5625 strncpy(newString, *intoString, beginPos);
5626 strncpy(&newString[beginPos], insertString, insertLen);
5627 newString[beginPos+insertLen] = '\n';
5628 strncpy(&newString[beginPos+insertLen+1],
5629 &((*intoString)[beginPos]), intoLen - beginPos);
5630 } else {
5631 strncpy(newString, *intoString, intoLen);
5632 newString[intoLen] = '\n';
5633 strncpy(&newString[intoLen+1], insertString, insertLen);
5634 }
5635 newString[intoLen + insertLen + 1] = '\0';
5636 NEditFree(*intoString);
5637 *intoString = newString;
5638 }
5639
5640 /*
5641 ** Simplified regular expression search routine which just returns true
5642 ** or false depending on whether inString matches expr
5643 */
regexFind(const char * inString,const char * expr)5644 static int regexFind(const char *inString, const char *expr)
5645 {
5646 int beginPos, endPos;
5647 return SearchString(inString, expr, SEARCH_FORWARD, SEARCH_REGEX, False,
5648 0, &beginPos, &endPos, NULL, NULL, NULL);
5649 }
5650
5651 /*
5652 ** Simplified case-sensisitive string search routine which just
5653 ** returns true or false depending on whether inString matches expr
5654 */
caseFind(const char * inString,const char * expr)5655 static int caseFind(const char *inString, const char *expr)
5656 {
5657 int beginPos, endPos;
5658 return SearchString(inString, expr, SEARCH_FORWARD, SEARCH_CASE_SENSE,
5659 False, 0, &beginPos, &endPos, NULL, NULL, NULL);
5660 }
5661
5662 /*
5663 ** Common implementation for simplified string replacement routines.
5664 */
stringReplace(char ** inString,const char * expr,const char * replaceWith,int searchType,int replaceLen)5665 static int stringReplace(char **inString, const char *expr,
5666 const char *replaceWith, int searchType,
5667 int replaceLen)
5668 {
5669 int beginPos, endPos, newLen;
5670 char *newString;
5671 int inLen = strlen(*inString);
5672 if (0 >= replaceLen) replaceLen = strlen(replaceWith);
5673 if (!SearchString(*inString, expr, SEARCH_FORWARD, searchType, False,
5674 0, &beginPos, &endPos, NULL, NULL, NULL))
5675 return FALSE;
5676 newLen = inLen + replaceLen - (endPos-beginPos);
5677 newString = (char*)NEditMalloc(newLen + 1);
5678 strncpy(newString, *inString, beginPos);
5679 strncpy(&newString[beginPos], replaceWith, replaceLen);
5680 strncpy(&newString[beginPos+replaceLen],
5681 &((*inString)[endPos]), inLen - endPos);
5682 newString[newLen] = '\0';
5683 NEditFree(*inString);
5684 *inString = newString;
5685 return TRUE;
5686 }
5687
5688 /*
5689 ** Simplified regular expression replacement routine which replaces the
5690 ** first occurence of expr in inString with replaceWith, reallocating
5691 ** inString with NEditMalloc. If expr is not found, does nothing and
5692 ** returns false.
5693 */
regexReplace(char ** inString,const char * expr,const char * replaceWith)5694 static int regexReplace(char **inString, const char *expr,
5695 const char *replaceWith)
5696 {
5697 return stringReplace(inString, expr, replaceWith, SEARCH_REGEX, -1);
5698 }
5699
5700 /*
5701 ** Simplified case-sensisitive string replacement routine which
5702 ** replaces the first occurence of expr in inString with replaceWith,
5703 ** reallocating inString with NEditMalloc. If expr is not found, does nothing
5704 ** and returns false.
5705 */
caseReplace(char ** inString,const char * expr,const char * replaceWith,int replaceLen)5706 static int caseReplace(char **inString, const char *expr,
5707 const char *replaceWith, int replaceLen)
5708 {
5709 return stringReplace(inString, expr, replaceWith, SEARCH_CASE_SENSE,
5710 replaceLen);
5711 }
5712
5713 /*
5714 ** Looks for a (case-sensitive literal) match of an old macro text in a
5715 ** temporary macro commands buffer. If the text is found, it is replaced by
5716 ** a substring of the default macros, bounded by a given start and end pattern
5717 ** (inclusive). Returns the length of the replacement.
5718 */
replaceMacroIfUnchanged(const char * oldText,const char * newStart,const char * newEnd)5719 static int replaceMacroIfUnchanged(const char* oldText, const char* newStart,
5720 const char* newEnd)
5721 {
5722 if (caseFind(TempStringPrefs.macroCmds, oldText)) {
5723 #ifdef VMS
5724 const char *start = strstr(PrefDescrip[1].defaultString, newStart);
5725 #else
5726 const char *start = strstr(PrefDescrip[2].defaultString, newStart);
5727 #endif
5728 if (start) {
5729 const char *end = strstr(start, newEnd);
5730 if (end) {
5731 int length = (int)(end-start) + strlen(newEnd);
5732 caseReplace(&TempStringPrefs.macroCmds, oldText, start, length);
5733 return length;
5734 }
5735 }
5736 }
5737 return 0;
5738 }
5739
5740 #ifndef VMS
5741 /*
5742 ** Replace all '#' characters in shell commands by '##' to keep commands
5743 ** containing those working. '#' is a line number placeholder in 5.3 and
5744 ** had no special meaning before.
5745 */
updateShellCmdsTo5dot3(void)5746 static void updateShellCmdsTo5dot3(void)
5747 {
5748 char *cOld, *cNew, *pCol, *pNL;
5749 int nHash, isCmd;
5750 char *newString;
5751
5752 if(!TempStringPrefs.shellCmds)
5753 return;
5754
5755 /* Count number of '#'. If there are '#' characters in the non-command
5756 ** part of the definition we count too much and later allocate too much
5757 ** memory for the new string, but this doesn't hurt.
5758 */
5759 for(cOld=TempStringPrefs.shellCmds, nHash=0; *cOld; cOld++)
5760 if(*cOld == '#')
5761 nHash++;
5762
5763 /* No '#' -> no conversion necessary. */
5764 if(!nHash)
5765 return;
5766
5767 newString=(char*)NEditMalloc(strlen(TempStringPrefs.shellCmds) + 1 + nHash);
5768
5769 cOld = TempStringPrefs.shellCmds;
5770 cNew = newString;
5771 isCmd = 0;
5772 pCol = NULL;
5773 pNL = NULL;
5774
5775 /* Copy all characters from TempStringPrefs.shellCmds into newString
5776 ** and duplicate '#' in command parts. A simple check for really beeing
5777 ** inside a command part (starting with '\n', between the the two last
5778 ** '\n' a colon ':' must have been found) is preformed.
5779 */
5780 while(*cOld) {
5781 /* actually every 2nd line is a command. We additionally
5782 ** check if there is a colon ':' in the previous line.
5783 */
5784 if(*cOld=='\n') {
5785 if((pCol > pNL) && !isCmd)
5786 isCmd=1;
5787 else
5788 isCmd=0;
5789 pNL=cOld;
5790 }
5791
5792 if(!isCmd && *cOld ==':')
5793 pCol = cOld;
5794
5795 /* Duplicate hashes if we're in a command part */
5796 if(isCmd && *cOld=='#')
5797 *cNew++ = '#';
5798
5799 /* Copy every character */
5800 *cNew++ = *cOld++;
5801
5802 }
5803
5804 /* Terminate new preferences string */
5805 *cNew = 0;
5806
5807 /* free the old memory */
5808 NEditFree(TempStringPrefs.shellCmds);
5809
5810 /* exchange the string */
5811 TempStringPrefs.shellCmds = newString;
5812
5813 }
5814
5815 #else
5816
updateShellCmdsTo5dot3(void)5817 static void updateShellCmdsTo5dot3(void) {
5818 /* No shell commands in VMS ! */
5819 return;
5820 }
5821
5822 #endif
5823
updateShellCmdsTo5dot4(void)5824 static void updateShellCmdsTo5dot4(void)
5825 {
5826 #ifndef VMS /* No shell commands on VMS */
5827
5828 #ifdef __FreeBSD__
5829 const char* wc5dot3 =
5830 "^(\\s*)set wc=`wc`; echo \\$wc\\[1\\] \"words,\" \\$wc\\[2\\] \"lines,\" \\$wc\\[3\\] \"characters\"\\n";
5831 const char* wc5dot4 =
5832 "wc | awk '{print $2 \" lines, \" $1 \" words, \" $3 \" characters\"}'\n";
5833 #else
5834 const char* wc5dot3 =
5835 "^(\\s*)set wc=`wc`; echo \\$wc\\[1\\] \"lines,\" \\$wc\\[2\\] \"words,\" \\$wc\\[3\\] \"characters\"\\n";
5836 const char* wc5dot4 =
5837 "wc | awk '{print $1 \" lines, \" $2 \" words, \" $3 \" characters\"}'\n";
5838 #endif /* __FreeBSD__ */
5839
5840 if (regexFind(TempStringPrefs.shellCmds, wc5dot3))
5841 regexReplace(&TempStringPrefs.shellCmds, wc5dot3, wc5dot4);
5842
5843 #endif /* VMS */
5844
5845 return;
5846 }
5847
updateMacroCmdsTo5dot5(void)5848 static void updateMacroCmdsTo5dot5(void)
5849 {
5850 const char* uc5dot4 =
5851 "^(\\s*)if \\(substring\\(sel, keepEnd - 1, keepEnd == \" \"\\)\\)\\n";
5852 const char* uc5dot5 =
5853 " if (substring(sel, keepEnd - 1, keepEnd) == \" \")\n";
5854 if (regexFind(TempStringPrefs.macroCmds, uc5dot4))
5855 regexReplace(&TempStringPrefs.macroCmds, uc5dot4, uc5dot5);
5856
5857 return;
5858 }
5859
updateMacroCmdsTo5dot6(void)5860 static void updateMacroCmdsTo5dot6(void)
5861 {
5862 /*
5863 This is ridiculous. Macros don't belong in the default preferences
5864 string.
5865 This code is also likely to break when the macro commands are upgraded
5866 again in a next release, because it looks for patterns in the default
5867 macro string (which may change).
5868 Using a "Default" mechanism, like we do for highlighting patterns
5869 would simplify upgrading A LOT in the future, but changing the way
5870 default macros are stored, is a lot of work too, unfortunately.
5871 */
5872 const char *pats[] = {
5873 "Complete Word:Alt+D::: {\n\
5874 # Tuning parameters\n\
5875 ScanDistance = 200\n\
5876 \n\
5877 # Search back to a word boundary to find the word to complete\n\
5878 startScan = max(0, $cursor - ScanDistance)\n\
5879 endScan = min($text_length, $cursor + ScanDistance)\n\
5880 scanString = get_range(startScan, endScan)\n\
5881 keyEnd = $cursor-startScan\n\
5882 keyStart = search_string(scanString, \"<\", keyEnd, \"backward\", \"regex\")\n\
5883 if (keyStart == -1)\n\
5884 return\n\
5885 keyString = \"<\" substring(scanString, keyStart, keyEnd)\n\
5886 \n\
5887 # search both forward and backward from the cursor position. Note that\n\
5888 # using a regex search can lead to incorrect results if any of the special\n\
5889 # regex characters is encountered, which is not considered a delimiter\n\
5890 backwardSearchResult = search_string(scanString, keyString, keyStart-1, \\\n\
5891 \"backward\", \"regex\")\n\
5892 forwardSearchResult = search_string(scanString, keyString, keyEnd, \"regex\")\n\
5893 if (backwardSearchResult == -1 && forwardSearchResult == -1) {\n\
5894 beep()\n\
5895 return\n\
5896 }\n\
5897 \n\
5898 # if only one direction matched, use that, otherwise use the nearest\n\
5899 if (backwardSearchResult == -1)\n\
5900 matchStart = forwardSearchResult\n\
5901 else if (forwardSearchResult == -1)\n\
5902 matchStart = backwardSearchResult\n\
5903 else {\n\
5904 if (keyStart - backwardSearchResult <= forwardSearchResult - keyEnd)\n\
5905 matchStart = backwardSearchResult\n\
5906 else\n\
5907 matchStart = forwardSearchResult\n\
5908 }\n\
5909 \n\
5910 # find the complete word\n\
5911 matchEnd = search_string(scanString, \">\", matchStart, \"regex\")\n\
5912 completedWord = substring(scanString, matchStart, matchEnd)\n\
5913 \n\
5914 # replace it in the window\n\
5915 replace_range(startScan + keyStart, $cursor, completedWord)\n\
5916 }", "Complete Word:", "\n\t}",
5917 "Fill Sel. w/Char:::R: {\n\
5918 if ($selection_start == -1) {\n\
5919 beep()\n\
5920 return\n\
5921 }\n\
5922 \n\
5923 # Ask the user what character to fill with\n\
5924 fillChar = string_dialog(\"Fill selection with what character?\", \"OK\", \"Cancel\")\n\
5925 if ($string_dialog_button == 2 || $string_dialog_button == 0)\n\
5926 return\n\
5927 \n\
5928 # Count the number of lines in the selection\n\
5929 nLines = 0\n\
5930 for (i=$selection_start; i<$selection_end; i++)\n\
5931 if (get_character(i) == \"\\n\")\n\
5932 nLines++\n\
5933 \n\
5934 # Create the fill text\n\
5935 rectangular = $selection_left != -1\n\
5936 line = \"\"\n\
5937 fillText = \"\"\n\
5938 if (rectangular) {\n\
5939 for (i=0; i<$selection_right-$selection_left; i++)\n\
5940 line = line fillChar\n\
5941 for (i=0; i<nLines; i++)\n\
5942 fillText = fillText line \"\\n\"\n\
5943 fillText = fillText line\n\
5944 } else {\n\
5945 if (nLines == 0) {\n\
5946 for (i=$selection_start; i<$selection_end; i++)\n\
5947 fillText = fillText fillChar\n\
5948 } else {\n\
5949 startIndent = 0\n\
5950 for (i=$selection_start-1; i>=0 && get_character(i)!=\"\\n\"; i--)\n\
5951 startIndent++\n\
5952 for (i=0; i<$wrap_margin-startIndent; i++)\n\
5953 fillText = fillText fillChar\n\
5954 fillText = fillText \"\\n\"\n\
5955 for (i=0; i<$wrap_margin; i++)\n\
5956 line = line fillChar\n\
5957 for (i=0; i<nLines-1; i++)\n\
5958 fillText = fillText line \"\\n\"\n\
5959 for (i=$selection_end-1; i>=$selection_start && get_character(i)!=\"\\n\"; \\\n\
5960 i--)\n\
5961 fillText = fillText fillChar\n\
5962 }\n\
5963 }\n\
5964 \n\
5965 # Replace the selection with the fill text\n\
5966 replace_selection(fillText)\n\
5967 }", "Fill Sel. w/Char:", "\n\t}",
5968 "Comments>/* Uncomment */@C@C++@Java@CSS@JavaScript@Lex:::R: {\n\
5969 sel = get_selection()\n\
5970 selStart = $selection_start\n\
5971 selEnd = $selection_end\n\
5972 commentStart = search_string(sel, \"/*\", 0)\n\
5973 if (substring(sel, commentStart + 2, commentStart + 3) == \" \")\n\
5974 keepStart = commentStart + 3\n\
5975 else\n\
5976 keepStart = commentStart + 2\n\
5977 keepEnd = search_string(sel, \"*/\", length(sel), \"backward\")\n\
5978 commentEnd = keepEnd + 2\n\
5979 if (substring(sel, keepEnd - 1, keepEnd) == \" \")\n\
5980 keepEnd = keepEnd - 1\n\
5981 replace_range(selStart + commentStart, selStart + commentEnd, \\\n\
5982 substring(sel, keepStart, keepEnd))\n\
5983 select(selStart, selEnd - (keepStart-commentStart) - \\\n\
5984 (commentEnd - keepEnd))\n\
5985 }", "Comments>/* Uncomment */", "\n\t}",
5986 "Comments>Bar Uncomment@C:::R: {\n\
5987 selStart = $selection_start\n\
5988 selEnd = $selection_end\n\
5989 newText = get_range(selStart+3, selEnd-4)\n\
5990 newText = replace_in_string(newText, \"^ \\\\* \", \"\", \"regex\")\n\
5991 replace_range(selStart, selEnd, newText)\n\
5992 select(selStart, selStart + length(newText))\n\
5993 }","Comments>Bar Uncomment@C:", "\n\t}",
5994 "Make C Prototypes@C@C++:::: {\n\
5995 if ($selection_start == -1) {\n\
5996 start = 0\n\
5997 end = $text_length\n\
5998 } else {\n\
5999 start = $selection_start\n\
6000 end = $selection_end\n\
6001 }\n\
6002 string = get_range(start, end)\n\
6003 nDefs = 0", "Make C Prototypes@C@C++:", "\t\tnDefs = 0",
6004 NULL };
6005 int i;
6006 for (i = 0; pats[i]; i+=3)
6007 replaceMacroIfUnchanged(pats[i], pats[i+1], pats[i+2]);
6008 return;
6009 }
6010
6011 #ifdef SGI_CUSTOM
6012 /*
6013 ** Present the user a dialog for specifying whether or not a short
6014 ** menu mode preference should be applied toward the default setting.
6015 ** Return False (function value) if operation was canceled, return True
6016 ** in setDefault if requested to reset the default value.
6017 */
shortPrefToDefault(Widget parent,const char * settingName,int * setDefault)6018 static int shortPrefToDefault(Widget parent, const char *settingName, int *setDefault)
6019 {
6020 char msg[100] = "";
6021
6022 if (!GetPrefShortMenus()) {
6023 *setDefault = False;
6024 return True;
6025 }
6026
6027 sprintf(msg, "%s\nSave as default for future windows as well?", settingName);
6028 switch (DialogF (DF_QUES, parent, 3, "Save Default", msg, "Yes", "No",
6029 "Cancel"))
6030 {
6031 case 1: /* yes */
6032 *setDefault = True;
6033 return True;
6034 case 2: /* no */
6035 *setDefault = False;
6036 return True;
6037 case 3: /* cancel */
6038 return False;
6039 }
6040 return False; /* not reached */
6041 }
6042 #endif
6043
6044 /* Decref the default calltips file(s) for this window */
UnloadLanguageModeTipsFile(WindowInfo * window)6045 void UnloadLanguageModeTipsFile(WindowInfo *window)
6046 {
6047 int mode;
6048
6049 mode = window->languageMode;
6050 if (mode != PLAIN_LANGUAGE_MODE && LanguageModes[mode]->defTipsFile) {
6051 DeleteTagsFile( LanguageModes[mode]->defTipsFile, TIP, False );
6052 }
6053 }
6054
6055 /******************************************************************************
6056 * The Color selection dialog
6057 ******************************************************************************/
6058
6059 /*
6060 There are 8 colors: And 8 indices:
6061 textFg TEXT_FG_COLOR
6062 textBg TEXT_BG_COLOR
6063 selectFg SELECT_FG_COLOR
6064 selectBg SELECT_BG_COLOR
6065 hiliteFg HILITE_FG_COLOR
6066 hiliteBg HILITE_BG_COLOR
6067 lineNoFg LINENO_FG_COLOR
6068 cursorFg CURSOR_FG_COLOR
6069 */
6070
6071 #define MARGIN_SPACING 10
6072
6073 /*
6074 * Callbacks for field modifications
6075 */
textFgModifiedCB(Widget w,XtPointer clientData,XtPointer callData)6076 static void textFgModifiedCB(Widget w, XtPointer clientData,
6077 XtPointer callData)
6078 {
6079 colorDialog *cd = (colorDialog *)clientData;
6080 showColorStatus(cd, cd->textFgW, cd->textFgErrW);
6081 }
6082
textBgModifiedCB(Widget w,XtPointer clientData,XtPointer callData)6083 static void textBgModifiedCB(Widget w, XtPointer clientData,
6084 XtPointer callData)
6085 {
6086 colorDialog *cd = (colorDialog *)clientData;
6087 showColorStatus(cd, cd->textBgW, cd->textBgErrW);
6088 }
6089
selectFgModifiedCB(Widget w,XtPointer clientData,XtPointer callData)6090 static void selectFgModifiedCB(Widget w, XtPointer clientData,
6091 XtPointer callData)
6092 {
6093 colorDialog *cd = (colorDialog *)clientData;
6094 showColorStatus(cd, cd->selectFgW, cd->selectFgErrW);
6095 }
6096
selectBgModifiedCB(Widget w,XtPointer clientData,XtPointer callData)6097 static void selectBgModifiedCB(Widget w, XtPointer clientData,
6098 XtPointer callData)
6099 {
6100 colorDialog *cd = (colorDialog *)clientData;
6101 showColorStatus(cd, cd->selectBgW, cd->selectBgErrW);
6102 }
6103
hiliteFgModifiedCB(Widget w,XtPointer clientData,XtPointer callData)6104 static void hiliteFgModifiedCB(Widget w, XtPointer clientData,
6105 XtPointer callData)
6106 {
6107 colorDialog *cd = (colorDialog *)clientData;
6108 showColorStatus(cd, cd->hiliteFgW, cd->hiliteFgErrW);
6109 }
6110
hiliteBgModifiedCB(Widget w,XtPointer clientData,XtPointer callData)6111 static void hiliteBgModifiedCB(Widget w, XtPointer clientData,
6112 XtPointer callData)
6113 {
6114 colorDialog *cd = (colorDialog *)clientData;
6115 showColorStatus(cd, cd->hiliteBgW, cd->hiliteBgErrW);
6116 }
6117
lineNoFgModifiedCB(Widget w,XtPointer clientData,XtPointer callData)6118 static void lineNoFgModifiedCB(Widget w, XtPointer clientData,
6119 XtPointer callData)
6120 {
6121 colorDialog *cd = (colorDialog *)clientData;
6122 showColorStatus(cd, cd->lineNoFgW, cd->lineNoFgErrW);
6123 }
6124
cursorFgModifiedCB(Widget w,XtPointer clientData,XtPointer callData)6125 static void cursorFgModifiedCB(Widget w, XtPointer clientData,
6126 XtPointer callData)
6127 {
6128 colorDialog *cd = (colorDialog *)clientData;
6129 showColorStatus(cd, cd->cursorFgW, cd->cursorFgErrW);
6130 }
6131
6132
6133 /*
6134 * Helper functions for validating colors
6135 */
verifyAllColors(colorDialog * cd)6136 static int verifyAllColors(colorDialog *cd)
6137 {
6138 /* Maybe just check for empty strings in error widgets instead? */
6139 return (checkColorStatus(cd, cd->textFgW) &&
6140 checkColorStatus(cd, cd->textBgW) &&
6141 checkColorStatus(cd, cd->selectFgW) &&
6142 checkColorStatus(cd, cd->selectBgW) &&
6143 checkColorStatus(cd, cd->hiliteFgW) &&
6144 checkColorStatus(cd, cd->hiliteBgW) &&
6145 checkColorStatus(cd, cd->lineNoFgW) &&
6146 checkColorStatus(cd, cd->cursorFgW) );
6147 }
6148
6149 /* Returns True if the color is valid, False if it's not */
checkColorStatus(colorDialog * cd,Widget colorFieldW)6150 static Boolean checkColorStatus(colorDialog *cd, Widget colorFieldW)
6151 {
6152 Colormap cMap;
6153 XColor colorDef;
6154 Status status;
6155 Display *display = XtDisplay(cd->shell);
6156 char *text = XmTextGetString(colorFieldW);
6157 XtVaGetValues(cd->shell, XtNcolormap, &cMap, NULL);
6158 status = XParseColor(display, cMap, text, &colorDef);
6159 NEditFree(text);
6160 return (status != 0);
6161 }
6162
6163 /* Show or hide errorLabelW depending on whether or not colorFieldW
6164 contains a valid color name. */
showColorStatus(colorDialog * cd,Widget colorFieldW,Widget errorLabelW)6165 static void showColorStatus(colorDialog *cd, Widget colorFieldW,
6166 Widget errorLabelW)
6167 {
6168 /* Should set the OK/Apply button sensitivity here, instead
6169 of leaving is sensitive and then complaining if an error. */
6170 XtSetMappedWhenManaged( errorLabelW, !checkColorStatus(cd, colorFieldW) );
6171 }
6172
6173 /* Update the colors in the window or in the preferences */
updateColors(colorDialog * cd)6174 static void updateColors(colorDialog *cd)
6175 {
6176 WindowInfo *window;
6177
6178 char *textFg = XmTextGetString(cd->textFgW),
6179 *textBg = XmTextGetString(cd->textBgW),
6180 *selectFg = XmTextGetString(cd->selectFgW),
6181 *selectBg = XmTextGetString(cd->selectBgW),
6182 *hiliteFg = XmTextGetString(cd->hiliteFgW),
6183 *hiliteBg = XmTextGetString(cd->hiliteBgW),
6184 *lineNoFg = XmTextGetString(cd->lineNoFgW),
6185 *cursorFg = XmTextGetString(cd->cursorFgW);
6186
6187 for (window = WindowList; window != NULL; window = window->next)
6188 {
6189 SetColors(window, textFg, textBg, selectFg, selectBg, hiliteFg,
6190 hiliteBg, lineNoFg, cursorFg);
6191 }
6192
6193 SetPrefColorName(TEXT_FG_COLOR , textFg );
6194 SetPrefColorName(TEXT_BG_COLOR , textBg );
6195 SetPrefColorName(SELECT_FG_COLOR, selectFg);
6196 SetPrefColorName(SELECT_BG_COLOR, selectBg);
6197 SetPrefColorName(HILITE_FG_COLOR, hiliteFg);
6198 SetPrefColorName(HILITE_BG_COLOR, hiliteBg);
6199 SetPrefColorName(LINENO_FG_COLOR, lineNoFg);
6200 SetPrefColorName(CURSOR_FG_COLOR, cursorFg);
6201
6202 NEditFree(textFg);
6203 NEditFree(textBg);
6204 NEditFree(selectFg);
6205 NEditFree(selectBg);
6206 NEditFree(hiliteFg);
6207 NEditFree(hiliteBg);
6208 NEditFree(lineNoFg);
6209 NEditFree(cursorFg);
6210 }
6211
6212
6213 /*
6214 * Dialog button callbacks
6215 */
6216
colorDestroyCB(Widget w,XtPointer clientData,XtPointer callData)6217 static void colorDestroyCB(Widget w, XtPointer clientData, XtPointer callData)
6218 {
6219 colorDialog *cd = (colorDialog *)clientData;
6220
6221 cd->window->colorDialog = NULL;
6222 NEditFree(cd);
6223 }
6224
colorOkCB(Widget w,XtPointer clientData,XtPointer callData)6225 static void colorOkCB(Widget w, XtPointer clientData, XtPointer callData)
6226 {
6227 colorDialog *cd = (colorDialog *)clientData;
6228
6229 if(!verifyAllColors(cd))
6230 {
6231 DialogF(DF_ERR, w, 1, "Invalid Colors",
6232 "All colors must be valid to proceed.", "OK");
6233 return;
6234 }
6235 updateColors(cd);
6236
6237 /* pop down and destroy the dialog */
6238 XtDestroyWidget(cd->shell);
6239 }
6240
colorApplyCB(Widget w,XtPointer clientData,XtPointer callData)6241 static void colorApplyCB(Widget w, XtPointer clientData, XtPointer callData)
6242 {
6243 colorDialog *cd = (colorDialog *)clientData;
6244
6245 if(!verifyAllColors(cd))
6246 {
6247 DialogF(DF_ERR, w, 1, "Invalid Colors",
6248 "All colors must be valid to be applied.", "OK");
6249 return;
6250 }
6251 updateColors(cd);
6252 }
6253
colorCloseCB(Widget w,XtPointer clientData,XtPointer callData)6254 static void colorCloseCB(Widget w, XtPointer clientData, XtPointer callData)
6255 {
6256 colorDialog *cd = (colorDialog *)clientData;
6257
6258 /* pop down and destroy the dialog */
6259 XtDestroyWidget(cd->shell);
6260 }
6261
6262
6263 /* Add a label, error label, and text entry label with a validation
6264 callback */
addColorGroup(Widget parent,const char * name,char mnemonic,char * label,Widget * fieldW,Widget * errW,Widget topWidget,int leftPos,int rightPos,XtCallbackProc modCallback,colorDialog * cd)6265 static Widget addColorGroup( Widget parent, const char *name, char mnemonic,
6266 char *label, Widget *fieldW, Widget *errW, Widget topWidget,
6267 int leftPos, int rightPos, XtCallbackProc modCallback,
6268 colorDialog *cd )
6269 {
6270 Widget lblW;
6271 char *longerName;
6272 XmString s1;
6273 int nameLen = strlen(name);
6274
6275 /* The label widget */
6276 longerName = (char*)NEditMalloc(nameLen+7);
6277 strcpy(longerName, name);
6278 strcat(longerName, "Lbl");
6279 lblW = XtVaCreateManagedWidget(longerName,
6280 xmLabelGadgetClass, parent,
6281 XmNlabelString, s1=XmStringCreateSimple( label ),
6282 XmNmnemonic, mnemonic,
6283 XmNtopAttachment, XmATTACH_WIDGET,
6284 XmNtopWidget, topWidget,
6285 XmNtopOffset, MARGIN_SPACING,
6286 XmNleftAttachment, XmATTACH_POSITION,
6287 XmNleftPosition, leftPos, NULL);
6288 XmStringFree(s1);
6289
6290 /* The error label widget */
6291 strcpy(&(longerName[nameLen]), "ErrLbl");
6292 *errW = XtVaCreateManagedWidget(longerName,
6293 xmLabelWidgetClass, parent,
6294 XmNlabelString, s1=XmStringCreateSimple("(Invalid!)"),
6295 XmNalignment, XmALIGNMENT_END,
6296 XmNtopAttachment, XmATTACH_WIDGET,
6297 XmNtopWidget, topWidget,
6298 XmNtopOffset, MARGIN_SPACING,
6299 XmNleftAttachment, XmATTACH_WIDGET,
6300 XmNleftWidget, lblW,
6301 XmNrightAttachment, XmATTACH_POSITION,
6302 XmNrightPosition, rightPos, NULL);
6303 XmStringFree(s1);
6304
6305 /* The text field entry widget */
6306 *fieldW = XtVaCreateManagedWidget(name, xmTextWidgetClass,
6307 parent,
6308 XmNcolumns, MAX_COLOR_LEN-1,
6309 XmNmaxLength, MAX_COLOR_LEN-1,
6310 XmNleftAttachment, XmATTACH_POSITION,
6311 XmNleftPosition, leftPos,
6312 XmNrightAttachment, XmATTACH_POSITION,
6313 XmNrightPosition, rightPos,
6314 XmNtopAttachment, XmATTACH_WIDGET,
6315 XmNtopWidget, lblW, NULL);
6316 RemapDeleteKey(*fieldW);
6317 XtAddCallback(*fieldW, XmNvalueChangedCallback,
6318 modCallback, cd);
6319 XtVaSetValues(lblW, XmNuserData, *fieldW, NULL);
6320
6321 NEditFree(longerName);
6322 return *fieldW;
6323 }
6324
6325
6326 /*
6327 * Code for the dialog itself
6328 */
ChooseColors(WindowInfo * window)6329 void ChooseColors(WindowInfo *window)
6330 {
6331 Widget form, tmpW, topW, infoLbl;
6332 Widget okBtn, applyBtn, closeBtn;
6333 colorDialog *cd;
6334 XmString s1;
6335 int ac;
6336 Arg args[20];
6337
6338 /* if the dialog is already displayed, just pop it to the top and return */
6339 if (window->colorDialog != NULL) {
6340 RaiseDialogWindow(((colorDialog *)window->colorDialog)->shell);
6341 return;
6342 }
6343
6344 /* Create a structure for keeping track of dialog state */
6345 cd = NEditNew(colorDialog);
6346 window->colorDialog = (void*)cd;
6347
6348 /* Create a form widget in a dialog shell */
6349 ac = 0;
6350 XtSetArg(args[ac], XmNautoUnmanage, False); ac++;
6351 XtSetArg(args[ac], XmNresizePolicy, XmRESIZE_NONE); ac++;
6352 form = CreateFormDialog(window->shell, "choose colors", args, ac);
6353 XtVaSetValues(form, XmNshadowThickness, 0, NULL);
6354 cd->shell = XtParent(form);
6355 cd->window = window;
6356 XtVaSetValues(cd->shell, XmNtitle, "Colors", NULL);
6357 AddMotifCloseCallback(XtParent(form), colorCloseCB, cd);
6358 XtAddCallback(form, XmNdestroyCallback, colorDestroyCB, cd);
6359
6360 /* Information label */
6361 infoLbl = XtVaCreateManagedWidget("infoLbl",
6362 xmLabelGadgetClass, form,
6363 XmNtopAttachment, XmATTACH_POSITION,
6364 XmNtopPosition, 2,
6365 XmNleftAttachment, XmATTACH_POSITION,
6366 XmNleftPosition, 1,
6367 XmNrightAttachment, XmATTACH_POSITION,
6368 XmNrightPosition, 99,
6369 XmNalignment, XmALIGNMENT_CENTER,
6370 XmNlabelString, s1 = XmStringCreateLtoR(
6371 "Colors can be entered as names (e.g. red, blue) or "
6372 "as RGB triples\nin the format #RRGGBB, where each digit "
6373 "is in the range 0-f.", XmFONTLIST_DEFAULT_TAG),
6374 NULL);
6375 XmStringFree(s1);
6376
6377 topW = infoLbl;
6378
6379 /* The left column (foregrounds) of color entry groups */
6380 tmpW = addColorGroup( form, "textFg", 'P', "Plain Text Foreground",
6381 &(cd->textFgW), &(cd->textFgErrW), topW, 1, 49,
6382 textFgModifiedCB, cd );
6383 tmpW = addColorGroup( form, "selectFg", 'S', "Selection Foreground",
6384 &(cd->selectFgW), &(cd->selectFgErrW), tmpW, 1, 49,
6385 selectFgModifiedCB, cd );
6386 tmpW = addColorGroup( form, "hiliteFg", 'M', "Matching (..) Foreground",
6387 &(cd->hiliteFgW), &(cd->hiliteFgErrW), tmpW, 1, 49,
6388 hiliteFgModifiedCB, cd );
6389 tmpW = addColorGroup( form, "lineNoFg", 'L', "Line Numbers",
6390 &(cd->lineNoFgW), &(cd->lineNoFgErrW), tmpW, 1, 49,
6391 lineNoFgModifiedCB, cd );
6392
6393 /* The right column (backgrounds) */
6394 tmpW = addColorGroup( form, "textBg", 'T', "Text Area Background",
6395 &(cd->textBgW), &(cd->textBgErrW), topW, 51, 99,
6396 textBgModifiedCB, cd );
6397 tmpW = addColorGroup( form, "selectBg", 'B', "Selection Background",
6398 &(cd->selectBgW), &(cd->selectBgErrW), tmpW, 51, 99,
6399 selectBgModifiedCB, cd );
6400 tmpW = addColorGroup( form, "hiliteBg", 'h', "Matching (..) Background",
6401 &(cd->hiliteBgW), &(cd->hiliteBgErrW), tmpW, 51, 99,
6402 hiliteBgModifiedCB, cd );
6403 tmpW = addColorGroup( form, "cursorFg", 'C', "Cursor Color",
6404 &(cd->cursorFgW), &(cd->cursorFgErrW), tmpW, 51, 99,
6405 cursorFgModifiedCB, cd );
6406
6407 tmpW = XtVaCreateManagedWidget("infoLbl",
6408 xmLabelGadgetClass, form,
6409 XmNtopAttachment, XmATTACH_WIDGET,
6410 XmNtopWidget, tmpW,
6411 XmNtopOffset, MARGIN_SPACING,
6412 XmNleftAttachment, XmATTACH_POSITION,
6413 XmNleftPosition, 1,
6414 XmNrightAttachment, XmATTACH_POSITION,
6415 XmNrightPosition, 99,
6416 XmNalignment, XmALIGNMENT_CENTER,
6417 XmNlabelString, s1 = XmStringCreateLtoR(
6418 "NOTE: Foreground colors only apply when syntax highlighting "
6419 "is DISABLED.\n", XmFONTLIST_DEFAULT_TAG),
6420 NULL);
6421 XmStringFree(s1);
6422
6423 tmpW = XtVaCreateManagedWidget("sep",
6424 xmSeparatorGadgetClass, form,
6425 XmNtopAttachment, XmATTACH_WIDGET,
6426 XmNtopWidget, tmpW,
6427 XmNleftAttachment, XmATTACH_FORM,
6428 XmNrightAttachment, XmATTACH_FORM, NULL);
6429
6430 /* The OK, Apply, and Cancel buttons */
6431 okBtn = XtVaCreateManagedWidget("ok",
6432 xmPushButtonWidgetClass, form,
6433 XmNlabelString, s1=XmStringCreateSimple("OK"),
6434 XmNmarginWidth, BUTTON_WIDTH_MARGIN,
6435 XmNtopAttachment, XmATTACH_WIDGET,
6436 XmNtopWidget, tmpW,
6437 XmNtopOffset, MARGIN_SPACING,
6438 XmNleftAttachment, XmATTACH_POSITION,
6439 XmNleftPosition, 10,
6440 XmNrightAttachment, XmATTACH_POSITION,
6441 XmNrightPosition, 30,
6442 NULL);
6443 XtAddCallback(okBtn, XmNactivateCallback, colorOkCB, cd);
6444 XmStringFree(s1);
6445
6446 applyBtn = XtVaCreateManagedWidget(
6447 "apply", xmPushButtonWidgetClass, form,
6448 XmNlabelString, s1=XmStringCreateSimple("Apply"),
6449 XmNtopAttachment, XmATTACH_WIDGET,
6450 XmNtopWidget, tmpW,
6451 XmNtopOffset, MARGIN_SPACING,
6452 XmNmnemonic, 'A',
6453 XmNleftAttachment, XmATTACH_POSITION,
6454 XmNleftPosition, 40,
6455 XmNrightAttachment, XmATTACH_POSITION,
6456 XmNrightPosition, 60, NULL);
6457 XtAddCallback(applyBtn, XmNactivateCallback, colorApplyCB, cd);
6458 XmStringFree(s1);
6459
6460 closeBtn = XtVaCreateManagedWidget("close",
6461 xmPushButtonWidgetClass, form,
6462 XmNlabelString, s1=XmStringCreateSimple("Close"),
6463 XmNtopAttachment, XmATTACH_WIDGET,
6464 XmNtopWidget, tmpW,
6465 XmNtopOffset, MARGIN_SPACING,
6466 XmNleftAttachment, XmATTACH_POSITION,
6467 XmNleftPosition, 70,
6468 XmNrightAttachment, XmATTACH_POSITION,
6469 XmNrightPosition, 90,
6470 NULL);
6471 XtAddCallback(closeBtn, XmNactivateCallback, colorCloseCB, cd);
6472 XmStringFree(s1);
6473
6474 /* Set initial default button */
6475 XtVaSetValues(form, XmNdefaultButton, okBtn, NULL);
6476 XtVaSetValues(form, XmNcancelButton, closeBtn, NULL);
6477
6478 /* Set initial values */
6479 XmTextSetString(cd->textFgW, GetPrefColorName(TEXT_FG_COLOR ));
6480 XmTextSetString(cd->textBgW, GetPrefColorName(TEXT_BG_COLOR ));
6481 XmTextSetString(cd->selectFgW, GetPrefColorName(SELECT_FG_COLOR));
6482 XmTextSetString(cd->selectBgW, GetPrefColorName(SELECT_BG_COLOR));
6483 XmTextSetString(cd->hiliteFgW, GetPrefColorName(HILITE_FG_COLOR));
6484 XmTextSetString(cd->hiliteBgW, GetPrefColorName(HILITE_BG_COLOR));
6485 XmTextSetString(cd->lineNoFgW, GetPrefColorName(LINENO_FG_COLOR));
6486 XmTextSetString(cd->cursorFgW, GetPrefColorName(CURSOR_FG_COLOR));
6487
6488 /* Handle mnemonic selection of buttons and focus to dialog */
6489 AddDialogMnemonicHandler(form, FALSE);
6490
6491 /* put up dialog */
6492 ManageDialogCenteredOnPointer(form);
6493 }
6494
6495 /*
6496 ** This function passes up a pointer to the static name of the default
6497 ** shell, currently defined as the user's login shell.
6498 ** In case of errors, the fallback of "sh" will be returned.
6499 */
getDefaultShell(void)6500 static const char* getDefaultShell(void)
6501 {
6502 struct passwd* passwdEntry = NULL;
6503 static char shellBuffer[MAXPATHLEN + 1] = "sh";
6504
6505 passwdEntry = getpwuid(getuid()); /* getuid() never fails. */
6506
6507 if (NULL == passwdEntry)
6508 {
6509 /* Something bad happened! Do something, quick! */
6510 perror("nedit: Failed to get passwd entry (falling back to 'sh')");
6511 return "sh";
6512 }
6513
6514 /* *passwdEntry may be overwritten */
6515 /* TODO: To make this and other function calling getpwuid() more robust,
6516 passwdEntry should be kept in a central position (Core->sysinfo?).
6517 That way, local code would always get a current copy of passwdEntry,
6518 but could still be kept lean. The obvious alternative of a central
6519 facility within NEdit to access passwdEntry would increase coupling
6520 and would have to cover a lot of assumptions. */
6521 strncpy(shellBuffer, passwdEntry->pw_shell, MAXPATHLEN);
6522 shellBuffer[MAXPATHLEN] = '\0';
6523
6524 return shellBuffer;
6525 }
6526