InterpretDebug-mods: calculate OpName length
[nedit-bw.git] / enhanced-hooks.2008-01-20.1.diff
blob7e377679c57d758d4432b63b55575349ebab2820
1 ReleaseNotes | 34 +
2 doc/help.etx | 109 +++++
3 source/Makefile.common | 1
4 source/Makefile.dependencies | 3
5 source/calltips.c | 334 ++++++++++++----
6 source/calltips.h | 13
7 source/file.c | 337 ++++++-----------
8 source/file.h | 7
9 source/help.c | 63 ++-
10 source/highlightData.c | 4
11 source/interpret.c | 27 +
12 source/macro.c | 271 +++++++++++--
13 source/macro.h | 3
14 source/menu.c | 254 +++++++++++-
15 source/nedit.c | 16
16 source/nedit.h | 14
17 source/preferences.c | 279 ++++++++++++--
18 source/preferences.h | 8
19 source/search.c | 159 +++++---
20 source/search.h | 10
21 source/selection.c | 49 +-
22 source/server.c | 9
23 source/shell.c | 5
24 source/text.c | 72 ++-
25 source/text.h | 14
26 source/textDisp.c | 461 ++++++++++++++++++++---
27 source/textDisp.h | 53 +-
28 source/textP.h | 5
29 source/window.c | 179 +++++++--
30 source/window.h | 6
31 util/fileUtils.c | 2
32 util/getfiles.c | 847 ++++++++++++++++++++++++++++++++++++-------
33 util/getfiles.h | 47 ++
34 util/prefFile.c | 31 -
35 util/printUtils.c | 4
36 35 files changed, 2951 insertions(+), 779 deletions(-)
38 diff --quilt old/ReleaseNotes new/ReleaseNotes
39 --- old/ReleaseNotes
40 +++ new/ReleaseNotes
41 @@ -13,11 +13,43 @@ If you are upgrading NEdit from a versio
42 the README file which came with the (source or executable) distribution kit,
43 about updating macros and font settings in your .nedit file.
45 New Features in $NEXT_VERSION
47 - - The macro variable $VERSION returns NEdit's version number.
48 + - Hidden files (dotfiles) can now be excluded from the file and directory
49 + lists in the file selection box (SF patch #502840).
51 + - A 'Smart Case' toggles the regex search caseness depending on the occur-
52 + rence of upper case letters in the search expression (SF patch #685618).
54 + - The help window got some small changes to increase usability.
56 + - The number of selected characters is displayed in the status bar.
58 + - The resource nedit.prevOpenFilesMask can be set to a regex to exclude
59 + certain files from the Open Previous menu.
61 + - Changes to the macro language:
62 + - The macro variable $NEDIT_HOME returns the name of the directory where
63 + NEdit's run control files reside.
64 + - The macro variable $VERSION returns NEdit's version number.
65 + - The function highlight_calltip_line() can highlight single lines in
66 + a macro-created calltip.
67 + - The semicolon is now a valid command seperator.
68 + - The macro subroutine typeof() returns a string indicating the type of
69 + a macro value.
71 + - If the macro routine file_open_hook() exists, it is called when an existing
72 + file is opened.
74 + - A hairline can be displayed at the wrap column (SF patch #701337).
76 + - The current line is now optionally displayed with a colored background
77 + (SF patch #683567).
79 + - Documents can now be flagged 'transient'. This disables the warning
80 + NEdit usually gives when you try to close a document which is not saved.
82 - The new macro function filename_dialog() can be used to query a file
83 name from the user by using the usual file selection dialog.
86 diff --quilt old/doc/help.etx new/doc/help.etx
87 --- old/doc/help.etx
88 +++ new/doc/help.etx
89 @@ -127,10 +127,13 @@ Getting Started
90 If you already have an empty (Untitled) window displayed, just begin typing
91 in the window. To create a new Untitled window, choose New Window or New Tab
92 from the File menu. To give the file a name and save its contents to the
93 disk, choose Save or Save As... from the File menu.
95 + In both Open and Save File Dialogs you can choose whether hidden files and
96 + directories are shown in the lists. Just check/uncheck the toggle button.
98 3>Backup Files
100 NEdit maintains periodic backups of the file you are editing so that you can
101 recover the file in the event of a problem such as a system crash, network
102 failure, or X server crash. These files are saved under the name `~filename`
103 @@ -260,10 +263,15 @@ Finding and Replacing Text
104 button with an icon resembling "|<". Clicking on it empties the search text widget
105 without disturbing selections. A middle click on the clear button copies the
106 content of any existing selection into the search text widget and triggers a new
107 search.
109 + All searches will default to the search mode selected in the preference menu.
110 + (Default Setting -> Searching -> Default Search Style). You can choose a smart
111 + case sensitivity here; this let all searches start insensitive, but changes to
112 + case sensitive as soon as you enter an upper-case letter.
114 3>Searching Backwards
116 Holding down the shift key while choosing any of the search or replace
117 commands from the menu (or using the keyboard shortcut), will search in the
118 reverse direction. Users who have set the search direction using the buttons
119 @@ -1939,13 +1947,13 @@ Macro Language
122 3>Syntax
124 An NEdit macro language program consists of a list of statements, each
125 - terminated by a newline. Groups of statements which are executed together
126 - conditionally, such as the body of a loop, are surrounded by curly braces
127 - "{}".
128 + terminated by a newline or a semicolon (;). Groups of statements which
129 + are executed together conditionally, such as the body of a loop, are
130 + surrounded by curly braces "{}".
132 Blank lines and comments are also allowed. Comments begin with a "#" and end
133 with a newline, and can appear either on a line by themselves, or at the end
134 of a statement line.
136 @@ -2536,10 +2544,16 @@ Macro Subroutines
137 yet been saved.
139 **$VERSION**
140 Returns NEdit's version number ('5006' for NEdit 5.6).
142 +**$NEDIT_HOME**
143 + Returns the name of the directory where NEdit's run control files reside.
144 + This is either the value of the environmental variable $NEDIT_HOME, the
145 + default of ~/.nedit or $HOME. (See Preferences_ for details
146 + about the algorithm.)
148 **$n_display_lines**
149 The number of lines visible in the currently active pane.
151 **$n_panes**
152 The number of panes in the current window.
153 @@ -2660,11 +2674,11 @@ Macro Subroutines
154 **filename_dialog( [title[, mode[, defaultPath[, filter[, defaultName]]]]] )**
155 Presents a file selection dialog with the given title to the user that
156 prompts for a new or existing file.
158 Options are: ~title~ will be the title of the dialog, defaults to "Choose
159 - file". If ~mode~ is set to "exist" (default), the "New File Name"TextField
160 + file". If ~mode~ is set to "exist" (default), the "New File Name" TextField
161 of the FSB will be unmanaged. If "new", the TextField will be managed.
162 ~defaultPath~ is the default path to use. Default (or "") will use the
163 active document's directory. ~filter~ is the file glob which determines
164 which files to display. Is set to "*" if filter is "" and by default.
165 ~defaultName~ is the default filename that is filled in automatically.
166 @@ -2682,12 +2696,12 @@ Macro Subroutines
167 focused window (the first window being the one returned from calling
168 focus_window("last"). Returns the name of the newly-focused window, or an
169 empty string if the requested window was not found.
171 **get_character( position )**
172 - Returns the single character at the position
173 - indicated by the first argument to the routine from the current window.
174 + Returns the single character at the position indicated by the first argument
175 + to the routine from the current window.
177 **get_range( start, end )**
178 Returns the text between a starting and ending position from the current
179 window.
181 @@ -2697,10 +2711,14 @@ Macro Subroutines
182 the screen (keyword "any").
184 **getenv( name )**
185 Gets the value of an environment variable.
187 +**highlight_calltip_line(calltip_ID, line)**
188 + Highlights a single line in the given calltip. Set line to 0 to remove
189 + any existing highlighting.
191 **kill_calltip( [calltip_ID] )**
192 Kills any calltip that is being displayed in the window in which the macro is
193 running. If there is no displayed calltip this does nothing. If a calltip
194 ID is supplied then the calltip is killed only if its ID is calltip_ID.
196 @@ -2853,10 +2871,19 @@ Macro Subroutines
197 Return an all lower-case version of string.
199 **toupper( string )**
200 Return an all upper-case version of string.
202 +**typeof( value )**
203 + Returns a string indicating the type of a macro value. The value can be
204 + any NEdit macro language value except for the return value of functions
205 + without a return value. Examples:
206 + typeof(2) # -> "INTEGER"
207 + typeof($empty_array) # -> "ARRAY"
208 + typeof(get_range(10, 20)) # -> "STRING"
209 + typeof(myArray["doesnotexist"]) # -> "UNDEFINED"
211 **valid_number( string )**
212 Returns 1 if the string can be converted to a number without error
213 following the same rules that the implicit conversion would. Otherwise 0.
215 **write_file( string, filename )**
216 @@ -3226,11 +3253,11 @@ Action Routines
217 3>Menu Action Routine Arguments
219 Arguments are text strings enclosed in quotes. Below are the menu action
220 routines which take arguments. Optional arguments are enclosed in [].
222 - **new**( ["tab" | "window" | "prefs" | "opposite"] )
223 + **new**( ["tab" | "window" | "prefs" | "opposite"] [, "transient"] )
225 **close**( ["prompt" | "save" | "nosave"] )
227 **execute_command**( shell-command )
229 @@ -3293,10 +3320,19 @@ Action Routines
230 preference
231 "opposite": Opposite of user's tab/window
232 preference
233 Default behaviour is "prefs".
235 + "transient" [EXPERIMENTAL]: Open the new
236 + document in transient mode. This disables the
237 + warning NEdit usually gives when you try to
238 + close a file which is not saved.
240 + WARNING: This is an experimental feature.
241 + Make sure to use this setting only for
242 + documents which can easily be recreated.
244 ~filename~ Path names are relative to the directory from
245 which NEdit was started. Shell interpreted
246 wildcards and `~' are not expanded.
248 ~keep-dialog~ Either "keep" or "nokeep".
249 @@ -3730,10 +3766,35 @@ Action Routines
251 **self_insert()**
252 To be attached to a key-press event, inserts the character
253 equivalent of the key pressed.
256 +Hooks
257 +-----
259 + Hooks are macro routines which are called at specific points in NEdit's
260 + execution. You can use hooks to tie in user-defined functionality at these
261 + points.
263 + No hooks are provided. To use a hook, simply define a macro function with
264 + the name of the hook. The next time the hook will catch, the macro function
265 + is called.
267 + You don't have to provide any hook. If a certain hook does not exist, it is
268 + simply skipped.
270 +**file_open_hook()**
271 + Called when an existing file is opened.
273 +..**file_name_hook(filename)**
274 +.. Called before NEdit opens a file using a certain name. The parameter is
275 +.. the filename NEdit intends to open.
277 +.. Return a string to use instead of the original filename. Return 0 to tell
278 +.. NEdit to use the original filename.
280 ----------------------------------------------------------------------
282 Customizing
283 ===========
285 @@ -3830,10 +3891,18 @@ Preferences
286 **Wrap Margin**
287 Set margin for Auto Newline Wrap, Continuous Wrap, and Fill Paragraph. Lines
288 may, be wrapped at the right margin of the window, or the margin can be set
289 at a specific column.
291 +**Show Wrap Margin**
292 + Visually indicate which column is set as the wrap margin by drawing a vertical
293 + line. Choose between never, always and when wrap is enabled. "Never" turns
294 + this feature off. "Always" will show the wrap margin irrespecitive of the
295 + wrapping style. "When Wrap is Enabled" will show the wrap margin only if
296 + continuous or auto-newline wrap styles are choosen and does not show the wrap
297 + margin if wrapping is turned off.
299 **Tab Stops**
300 Set the tab distance (number of characters between tab stops) for tab
301 characters, and control tab emulation and use of tab characters in padding
302 and emulated tabs.
304 @@ -3873,10 +3942,17 @@ Preferences
305 **Read Only**
306 Lock the file against accidental modification. This temporarily prevents the
307 file from being modified in this NEdit session. Note that this is different
308 from setting the file protection.
310 +**Transient [EXPERIMENTAL]**
311 + Flags the document as transient. This disables the warning NEdit usually
312 + gives when you try to close a file which is not saved.
314 + WARNING: This is an experimental feature. Make sure to use this setting
315 + only for documents which can easily be recreated.
317 3>Preferences -> Default Settings Menu
319 Options in the Preferences -> Default Settings menu have the same meaning as
320 those in the top-level Preferences menu, except that they apply to future
321 NEdit windows and future NEdit sessions if saved with the Save Defaults
322 @@ -3974,10 +4050,16 @@ Preferences
324 **Terminate with Line Break on Save**
325 Some UNIX tools expect that files end with a line feed. If this option is
326 activated, NEdit will append one if required.
328 +**Show Hidden Files**
329 + Show hidden files by default in file selection boxes.
331 +**Show Cursorline**
332 + Background the current line with a colored bar.
334 **Sort Open Prev. Menu**
335 Option to order the File -> Open Previous menu alphabetically, versus in
336 order of last access.
338 **Popups Under Pointer**
339 @@ -4310,10 +4392,16 @@ X Resources
341 Number of files listed in the Open Previous sub-menu of the File menu.
342 Setting this to zero disables the Open Previous menu item and maintenance of
343 the NEdit file history file.
345 +**nedit.prevOpenFilesMask**: (not defined)
347 + Files not to be listed in the Open Previous sub-menu of the File menu.
348 + Setting this to a regular expression causes files matching the expression to
349 + be omitted from the Open Previous menu item and the .neditdb file.
351 **nedit.printCommand**: (system specific)
353 Command used by the print dialog to print a file, such as, lp, lpr, etc..
354 The command must be capable of accepting input via stdin (standard input).
356 @@ -4349,10 +4437,16 @@ X Resources
357 **nedit.printDefaultHost**: (system specific)
359 The node name of the default print host. Used only to display in the print
360 dialog, and has no effect on printing.
362 +**nedit.showScrolltip**: True
364 + If this resource is set to True, NEdit will show a tooltip displaying the
365 + line number if the user grabs and moves the scroll handle. Set to False to
366 + switch it off.
368 **nedit.visualID**: Best
370 If your screen supports multiple visuals (color mapping models), this
371 resource allows you to manually choose among them. The default value of
372 "Best" chooses the deepest (most colors) visual available. Since NEdit does
373 @@ -5993,10 +6087,11 @@ Problems/Defects
374 .. Menu: Macro Language # macro_lang
375 .. Menu: M_a_cro Subroutines # macro_subrs
376 .. Menu: Rangesets # rangeset
377 .. Menu: Highlighting Information # hiliteInfo
378 .. Menu: Action Routines # actions
379 +.. Menu: H_o_oks # hooks
381 .. Menu: Customizing # customizing
382 .. Menu: Customizing NEdit # customize
383 .. Menu: Preferences # preferences
384 .. Menu: X Resources # resources
385 diff --quilt old/source/Makefile.common new/source/Makefile.common
386 --- old/source/Makefile.common
387 +++ new/source/Makefile.common
388 @@ -6,10 +6,11 @@
389 OBJS = nedit.o file.o menu.o window.o selection.o search.o undo.o shift.o \
390 help.o preferences.o tags.o userCmds.o shell.o regularExp.o macro.o \
391 text.o textSel.o textDisp.o textBuf.o textDrag.o server.o highlight.o \
392 highlightData.o interpret.o parse.o smartIndent.o regexConvert.o \
393 rbTree.o windowTitle.o calltips.o server_common.o rangeset.o
394 +OBJS += backup.o
396 XLTLIB = ../Xlt/libXlt.a
397 XMLLIB = ../Microline/XmL/libXmL.a
399 .c.o:
400 diff --quilt old/source/Makefile.dependencies new/source/Makefile.dependencies
401 --- old/source/Makefile.dependencies
402 +++ new/source/Makefile.dependencies
403 @@ -1,12 +1,13 @@
404 # $Id: Makefile.dependencies,v 1.21 2003/05/02 18:18:41 edg Exp $
405 +backup.o: backup.c backup.h
406 calltips.o: calltips.c text.h textBuf.h textP.h textDisp.h calltips.h \
407 nedit.h ../util/misc.h
408 file.o: file.c file.h nedit.h textBuf.h text.h window.h preferences.h \
409 undo.h menu.h tags.h server.h ../util/misc.h ../util/DialogF.h \
410 ../util/fileUtils.h ../util/getfiles.h ../util/printUtils.h \
411 - ../util/utils.h
412 + ../util/utils.h macro.h
413 help.o: help.c help.h help_topic.h textBuf.h text.h textP.h textDisp.h \
414 textSel.h nedit.h search.h window.h preferences.h help_data.h file.h \
415 highlight.h ../util/misc.h ../util/DialogF.h ../util/system.h
416 highlight.o: highlight.c highlight.h nedit.h textBuf.h textDisp.h text.h \
417 textP.h regularExp.h highlightData.h preferences.h window.h \
418 diff --quilt old/source/calltips.c new/source/calltips.c
419 --- old/source/calltips.c
420 +++ new/source/calltips.c
421 @@ -1,15 +1,15 @@
422 /*******************************************************************************
424 * calltips.c -- Calltip UI functions (calltip *file* functions are in tags.c) *
426 -* Copyright (C) 2002 Nathaniel Gray *
427 +* Copyright (C) 2002, 2004, 2005 The NEdit Developers *
429 * This is free software; you can redistribute it and/or modify it under the *
430 * terms of the GNU General Public License as published by the Free Software *
431 * Foundation; either version 2 of the License, or (at your option) any later *
432 -* version. In addition, you may distribute version of this program linked to *
433 +* version. In addition, you may distribute versions of this program linked to *
434 * Motif or Open Motif. See README for details. *
436 * This software is distributed in the hope that it will be useful, but WITHOUT *
437 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
438 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
439 @@ -28,29 +28,35 @@
441 #ifdef HAVE_CONFIG_H
442 #include "../config.h"
443 #endif
445 +#include "calltips.h"
447 +#include "regularExp.h"
448 #include "text.h"
449 #include "textP.h"
450 -#include "calltips.h"
451 #include "../util/misc.h"
453 #include <stdio.h>
454 #include <stdlib.h>
455 #include <string.h>
456 #include <limits.h>
458 #include <Xm/Xm.h>
459 -#include <Xm/Label.h>
460 #include <X11/Shell.h>
461 +#include <Xm/Text.h>
463 #ifdef HAVE_DEBUG_H
464 #include "../debug.h"
465 #endif
467 -static char *expandAllTabs( char *text, int tab_width );
468 +static char* expandAllTabs(const char *text, const int tab_width);
469 +Boolean getRangeOfLine(const char* textString, const unsigned line,
470 + unsigned* begin, unsigned* end);
471 +Widget createTip(const Widget parent, const Pixel foreground,
472 + const Pixel background, const unsigned char alignment);
475 ** Pop-down a calltip if one exists, else do nothing
477 void KillCalltip(WindowInfo *window, int calltipID) {
478 @@ -60,31 +66,23 @@ void KillCalltip(WindowInfo *window, int
480 void TextDKillCalltip(textDisp *textD, int calltipID) {
481 if( textD->calltip.ID == 0 )
482 return;
483 if( calltipID == 0 || calltipID == textD->calltip.ID ) {
484 - XtPopdown( textD->calltipShell );
485 + XtPopdown(XtParent(textD->calltip.widget));
486 textD->calltip.ID = 0;
491 -** Is a calltip displayed? Returns the calltip ID of the currently displayed
492 -** calltip, or 0 if there is no calltip displayed. If called with
493 -** calltipID != 0, returns 0 unless there is a calltip being
494 -** displayed with that calltipID.
495 +** Returns the calltip ID of the currently displayed calltip, or 0 if
496 +** there is no calltip displayed.
498 -int GetCalltipID(WindowInfo *window, int calltipID) {
499 +int GetCalltipID(const WindowInfo *window) {
500 textDisp *textD = ((TextWidget)window->lastFocus)->text.textD;
501 - if( calltipID == 0 )
502 - return textD->calltip.ID;
503 - else {
504 - if( calltipID == textD->calltip.ID)
505 - return calltipID;
506 - else
507 - return 0;
510 + return textD->calltip.ID;
513 #define CALLTIP_EDGE_GUARD 5
514 static Boolean offscreenV(XWindowAttributes *screenAttr, int top, int height) {
515 return (top < CALLTIP_EDGE_GUARD ||
516 @@ -129,12 +127,15 @@ void TextDRedrawCalltip(textDisp *textD,
517 return;
519 rel_x = textD->calltip.pos;
522 - XtVaGetValues(textD->calltipShell, XmNwidth, &tipWidth, XmNheight,
523 - &tipHeight, XmNborderWidth, &borderWidth, NULL);
524 + XtVaGetValues(XtParent(textD->calltip.widget),
525 + XmNwidth, &tipWidth,
526 + XmNheight, &tipHeight,
527 + XmNborderWidth, &borderWidth,
528 + NULL);
529 rel_x += borderWidth;
530 rel_y += lineHeight/2 + borderWidth;
532 /* Adjust rel_x for horizontal alignment modes */
533 if (textD->calltip.hAlign == TIP_CENTER)
534 @@ -175,119 +176,110 @@ void TextDRedrawCalltip(textDisp *textD,
535 abs_y = screenAttr.height - tipHeight - CALLTIP_EDGE_GUARD;
536 /* If no case applied, just go with the default placement. */
540 - XtVaSetValues( textD->calltipShell, XmNx, abs_x, XmNy, abs_y, NULL );
541 + XtVaSetValues(XtParent(textD->calltip.widget), XmNx, abs_x, XmNy, abs_y, NULL);
545 ** Returns a new string with each \t replaced with tab_width spaces or
546 ** a pointer to text if there were no tabs. Returns NULL on malloc failure.
547 ** Note that this is dumb replacement, not smart tab-like behavior! The goal
548 ** is to prevent tabs from turning into squares in calltips, not to get the
549 ** formatting just right.
551 -static char *expandAllTabs( char *text, int tab_width ) {
552 - int i, nTabs=0;
553 +static char* expandAllTabs(const char* text, const int tab_width)
555 + int i, nTabs = 0;
556 size_t len;
557 - char *c, *cCpy, *textCpy;
558 + const char* c;
559 + char *cCpy, *textCpy;
561 /* First count 'em */
562 - for( c = text; *c; ++c )
563 - if( *c == '\t' )
564 + for (c = (char*) text; *c; ++c) {
565 + if ('\t' == *c)
566 ++nTabs;
567 - if( nTabs == 0 )
568 - return text;
570 + if (0 == nTabs) {
571 + return strdup(text);
574 /* Allocate the new string */
575 - len = strlen( text ) + ( tab_width - 1 )*nTabs;
576 - textCpy = (char*)malloc( len + 1 );
577 - if( !textCpy ) {
578 - fprintf(stderr,
579 - "nedit: Out of heap memory in expandAllTabs!\n");
580 + len = strlen(text) + (tab_width - 1) * nTabs;
581 + textCpy = (char*) malloc(len + 1);
582 + if (!textCpy) {
583 + fprintf(stderr, "nedit: Out of heap memory in expandAllTabs!\n");
584 return NULL;
587 /* Now replace 'em */
588 - for( c = text, cCpy = textCpy; *c; ++c, ++cCpy) {
589 - if( *c == '\t' ) {
590 - for( i = 0; i < tab_width; ++i, ++cCpy )
591 + for (c = text, cCpy = textCpy; *c; ++c, ++cCpy) {
592 + if (*c == '\t') {
593 + for (i = 0; i < tab_width; ++i, ++cCpy) {
594 *cCpy = ' ';
596 --cCpy; /* Will be incremented in outer for loop */
597 - } else
598 + } else {
599 *cCpy = *c;
602 *cCpy = '\0';
603 return textCpy;
607 -** Pop-up a calltip.
608 -** If a calltip is already being displayed it is destroyed and replaced with
609 -** the new calltip. Returns the ID of the calltip or 0 on failure.
610 +** Pop-up a calltip.
612 +** If a calltip is already being displayed it is destroyed and replaced
613 +** with the new calltip.
615 +** Returns the ID of the calltip or 0 on failure.
617 -int ShowCalltip(WindowInfo *window, char *text, Boolean anchored,
618 - int pos, int hAlign, int vAlign, int alignMode) {
619 - static int StaticCalltipID = 1;
620 +int ShowCalltip(const WindowInfo *window, const char *text,
621 + const Boolean anchored, const int pos, const int hAlign,
622 + const int vAlign, const int alignMode)
624 + static unsigned StaticCalltipID = 1;
625 textDisp *textD = ((TextWidget)window->lastFocus)->text.textD;
626 int rel_x, rel_y;
627 - Position txtX, txtY;
628 - char *textCpy;
629 - XmString str;
630 + char* tablessText;
632 /* Destroy any previous calltip */
633 - TextDKillCalltip( textD, 0 );
634 + TextDKillCalltip(textD, 0);
636 /* Make sure the text isn't NULL */
637 if (text == NULL) return 0;
639 - /* Expand any tabs in the calltip and make it an XmString */
640 - textCpy = expandAllTabs( text, BufGetTabDistance(textD->buffer) );
641 - if( textCpy == NULL )
642 + /* Expand any tabs in the calltip */
643 + tablessText = expandAllTabs(text, BufGetTabDistance(textD->buffer));
644 + if (NULL == tablessText) {
645 return 0; /* Out of memory */
646 - str = XmStringCreateLtoR(textCpy, XmFONTLIST_DEFAULT_TAG);
647 - if( textCpy != text )
648 - free( textCpy );
650 - /* Get the location/dimensions of the text area */
651 - XtVaGetValues(textD->w,
652 - XmNx, &txtX,
653 - XmNy, &txtY,
654 - NULL);
658 /* Create the calltip widget on first request */
659 - if (textD->calltipW == NULL) {
660 - Arg args[10];
661 - int argcnt = 0;
662 - XtSetArg(args[argcnt], XmNsaveUnder, True); argcnt++;
663 - XtSetArg(args[argcnt], XmNallowShellResize, True); argcnt++;
665 - textD->calltipShell = CreatePopupShellWithBestVis("calltipshell",
666 - overrideShellWidgetClass, textD->w, args, argcnt);
668 - /* Might want to make this a read-only XmText eventually so that
669 - users can copy from it */
670 - textD->calltipW = XtVaCreateManagedWidget(
671 - "calltip", xmLabelWidgetClass, textD->calltipShell,
672 - XmNborderWidth, 1, /* Thin borders */
673 - XmNhighlightThickness, 0,
674 - XmNalignment, XmALIGNMENT_BEGINNING,
675 - XmNforeground, textD->calltipFGPixel,
676 - XmNbackground, textD->calltipBGPixel,
677 - NULL );
680 - /* Set the text on the label */
681 - XtVaSetValues( textD->calltipW, XmNlabelString, str, NULL );
682 - XmStringFree( str );
683 + if (NULL == textD->calltip.widget) {
684 + textD->calltip.widget = createTip(textD->w, textD->calltipFGPixel,
685 + textD->calltipBGPixel, XmALIGNMENT_BEGINNING);
688 + /* The text widget will keep the size of the largest text it contained
689 + over its lifetime unless we do something about it. So we set it to
690 + minimum size and let the resize functionality do its work to get it
691 + back up again matching the current text. */
692 + XtVaSetValues(textD->calltip.widget,
693 + XmNheight, 10,
694 + XmNwidth, 10,
695 + NULL);
696 + XmTextSetString(textD->calltip.widget, tablessText);
697 + free(tablessText);
699 /* Figure out where to put the tip */
700 if (anchored) {
701 /* Put it at the specified position */
702 /* If position is not displayed, return 0 */
703 - if (pos < textD->firstChar || pos > textD->lastChar ) {
704 + if (pos < textD->firstChar || pos > textD->lastChar) {
705 XBell(TheDisplay, 0);
706 return 0;
708 textD->calltip.pos = pos;
709 } else {
710 @@ -311,15 +303,179 @@ int ShowCalltip(WindowInfo *window, char
711 textD->calltip.vAlign = vAlign;
712 textD->calltip.alignMode = alignMode;
714 /* Increment the static calltip ID. Macro variables can only be int,
715 not unsigned, so have to work to keep it > 0 on overflow */
716 - if(++StaticCalltipID <= 0)
717 + /* Macro variables can only be int, that's why you have to keep the ID
718 + in the unsigned range? */
719 + if (++StaticCalltipID <= 0) {
720 StaticCalltipID = 1;
723 /* Realize the calltip's shell so that its width & height are known */
724 - XtRealizeWidget( textD->calltipShell );
725 + XtRealizeWidget(XtParent(textD->calltip.widget));
727 /* Move the calltip and pop it up */
728 TextDRedrawCalltip(textD, 0);
729 - XtPopup( textD->calltipShell, XtGrabNone );
730 + XtPopup(XtParent(textD->calltip.widget), XtGrabNone);
732 return textD->calltip.ID;
736 +** Highlight a single line in a given calltip, erasing all other highlights.
738 +** Return values for this one need to be a bit more expressive. Some errors
739 +** might just be the result of sloppy parameters, and the caller should
740 +** decide whether to fail hard or not. The following results are possible:
742 +** - The calltip ID given is invalid (CT_INVALID_ID).
743 +** - The user requested to remove all highlightings (CT_OK).
744 +** - The requested line is highlighted (CT_OK).
745 +** - The requested line is not in the provided text (CT_NOLINE).
747 +int HighlightCalltipLine(const WindowInfo* window, const int calltipID,
748 + const unsigned line)
750 + textDisp* textD = ((TextWidget) window->lastFocus)->text.textD;
751 + Boolean result = False;
753 + if (calltipID == textD->calltip.ID) {
754 + Widget textWidget = textD->calltip.widget;
755 + char* textString = XmTextGetString(textWidget);
756 + XmTextPosition textLength = XmTextGetLastPosition(textWidget);
757 + unsigned begin = 0, end = 0;
758 + Boolean lineIsValid = False;
760 + /* First remove all existing highlights. */
761 + XmTextSetHighlight(textWidget, 0, textLength + 1, XmHIGHLIGHT_NORMAL);
763 + if (0 == line) {
764 + /* Just return without highlighting anything. */
765 + result = CT_OK;
766 + } else {
767 + lineIsValid = getRangeOfLine(textString, line, &begin, &end);
768 + if (lineIsValid) {
769 + XmTextSetHighlight(textWidget, (XmTextPosition) begin,
770 + (XmTextPosition) end, XmHIGHLIGHT_SELECTED);
772 + result = CT_OK;
773 + } else {
774 + /* The requested line is not in the provided text. */
775 + result = CT_NOLINE;
779 + XtFree(textString);
780 + } else {
781 + result = CT_INVALID_ID;
784 + return result;
788 +** Sets the parameters to beginning and end of the line. Returns False if
789 +** the line is not in the text, True otherwise.
791 +Boolean getRangeOfLine(const char* textString, const unsigned line,
792 + unsigned* begin, unsigned* end)
794 + int i;
795 + size_t position = 0;
797 + for (i = 0; i < line; i++)
799 + *end = strcspn(textString + position, "\n") + position;
800 + *begin = position;
801 + position = *end + 1;
803 + if (*begin == *end)
805 + /* Break if last line is found. */
806 + break;
810 + return (*begin != *end);
814 +** Pop up a scroll calltip.
816 +Boolean ShowScrolltip(textDisp* textD, const char* text, const int x,
817 + const int y)
819 + if (NULL == textD->scrolltip) {
820 + textD->scrolltip = createTip(textD->w, textD->calltipFGPixel,
821 + textD->calltipBGPixel, XmALIGNMENT_CENTER);
824 + /* Set the text on the tip's label. */
825 + XmTextSetString(textD->scrolltip, (char*) text);
827 + /* Realize the calltip's shell so that its width and height are known */
828 + XtRealizeWidget(XtParent(textD->scrolltip));
830 + /* Move the tip where it belongs and pop it up. */
831 + XtVaSetValues(XtParent(textD->scrolltip), XmNx, x, XmNy, y, NULL);
832 + XtPopup(XtParent(textD->scrolltip), XtGrabNone);
834 + return True;
838 +** Pop down scrolltip if it exists
840 +void KillScrolltip(textDisp* textD)
842 + if (NULL != textD->scrolltip && NULL != XtParent(textD->scrolltip)) {
843 + XtPopdown(XtParent(textD->scrolltip));
848 +** This creates a calltip of class XmText and its parent, a shell of class
849 +** OverrideShell (which in turn will be the child of the grandfather
850 +** parameter). The tip will have minimum size but will resize to match
851 +** the text entered (see XmNallowShellResize).
853 +** Color is picked by the two parameters foreground and background.
855 +** The alignment is on of XmALIGNMENT_BEGINNING, XmALIGNMENT_CENTER or
856 +** XmALIGNMENT_END, taken from the XmLabel class.
858 +** TODO: Some helper functions are still desirable to make this function
859 +** available from other parts of the code. At the moment the caller must
860 +** use calls to Motif/Intrinsics functions to handle it.
863 +Widget createTip(const Widget grandfather, const Pixel foreground,
864 + const Pixel background, const unsigned char alignment)
866 + Widget tip = NULL;
867 + Widget shell = NULL;
868 + Arg args[10];
869 + int argc = 0;
871 + XtSetArg(args[argc], XmNsaveUnder, True); argc++;
872 + XtSetArg(args[argc], XmNallowShellResize, True); argc++;
874 + shell = CreatePopupShellWithBestVis("tipshell", overrideShellWidgetClass,
875 + grandfather, args, argc);
877 + tip = XtVaCreateManagedWidget("tip",
878 + xmTextWidgetClass, shell,
879 + XmNhighlightThickness, 0,
880 + XmNalignment, alignment,
881 + XmNeditable, False,
882 + XmNeditMode, XmMULTI_LINE_EDIT,
883 + XmNcursorPositionVisible, False,
884 + XmNresizeHeight, True,
885 + XmNresizeWidth, True,
886 + XmNforeground, foreground,
887 + XmNbackground, background,
888 + XmNheight, 10, /* will be resized automatically */
889 + XmNwidth, 10, /* will be resized automatically */
890 + NULL);
891 + return tip;
893 diff --quilt old/source/calltips.h new/source/calltips.h
894 --- old/source/calltips.h
895 +++ new/source/calltips.h
896 @@ -36,14 +36,21 @@
899 enum TipHAlignMode {TIP_LEFT, TIP_CENTER, TIP_RIGHT};
900 enum TipVAlignMode {TIP_ABOVE, TIP_BELOW};
901 enum TipAlignStrict {TIP_SLOPPY, TIP_STRICT};
902 +enum TipHighlightError {CT_OK, CT_INVALID_ID, CT_NOLINE};
904 -int ShowCalltip(WindowInfo *window, char *text, Boolean anchored,
905 - int pos, int hAlign, int vAlign, int alignMode);
906 +int ShowCalltip(const WindowInfo *window, const char *text,
907 + const Boolean anchored, const int pos, const int hAlign,
908 + const int vAlign, const int alignMode);
909 void KillCalltip(WindowInfo *window, int calltipID);
910 +Boolean ShowScrolltip(textDisp* textD, const char* text, const int x,
911 + const int y);
912 +void KillScrolltip(textDisp* textD);
913 void TextDKillCalltip(textDisp *textD, int calltipID);
914 -int GetCalltipID(WindowInfo *window, int calltipID);
915 +int GetCalltipID(const WindowInfo *window);
916 void TextDRedrawCalltip(textDisp *textD, int calltipID);
917 +int HighlightCalltipLine(const WindowInfo* window, const int calltipID,
918 + const unsigned line);
920 #endif /* ifndef NEDIT_CALLTIPS_H_INCLUDED */
921 diff --quilt old/source/file.c new/source/file.c
922 --- old/source/file.c
923 +++ new/source/file.c
924 @@ -30,19 +30,22 @@ static const char CVSID[] = "$Id: file.c
925 #ifdef HAVE_CONFIG_H
926 #include "../config.h"
927 #endif
929 #include "file.h"
931 +#include "backup.h"
932 #include "textBuf.h"
933 #include "text.h"
934 #include "window.h"
935 #include "preferences.h"
936 #include "undo.h"
937 #include "menu.h"
938 #include "tags.h"
939 #include "server.h"
940 #include "interpret.h"
941 +#include "macro.h"
942 #include "../util/misc.h"
943 #include "../util/DialogF.h"
944 #include "../util/fileUtils.h"
945 #include "../util/getfiles.h"
946 #include "../util/printUtils.h"
947 @@ -73,10 +76,15 @@ static const char CVSID[] = "$Id: file.c
948 #include <Xm/ToggleB.h>
949 #include <Xm/FileSB.h>
950 #include <Xm/RowColumn.h>
951 #include <Xm/Form.h>
952 #include <Xm/Label.h>
953 +#include <Xm/PushB.h>
955 +/* What kinds of backup files to make -- see
956 + table `version_control_values' in backup.c. */
957 +static enum backup_mode version_control;
959 #ifdef HAVE_DEBUG_H
960 #include "../debug.h"
961 #endif
963 @@ -84,22 +92,22 @@ static const char CVSID[] = "$Id: file.c
964 The periodic check is only performed on buffer modification, and the check
965 interval is only to prevent checking on every keystroke in case of a file
966 system which is slow to process stat requests (which I'm not sure exists) */
967 #define MOD_CHECK_INTERVAL 3000
969 +#define MAX_X_ARGS 20 /* Maximum number of X arguments */
971 static int doSave(WindowInfo *window);
972 static void safeClose(WindowInfo *window);
973 static int doOpen(WindowInfo *window, const char *name, const char *path,
974 int flags);
975 static void backupFileName(WindowInfo *window, char *name, size_t len);
976 static int writeBckVersion(WindowInfo *window);
977 static int bckError(WindowInfo *window, const char *errString, const char *file);
978 static int fileWasModifiedExternally(WindowInfo *window);
979 static const char *errorString(void);
980 static void addWrapNewlines(WindowInfo *window);
981 -static void setFormatCB(Widget w, XtPointer clientData, XtPointer callData);
982 -static void addWrapCB(Widget w, XtPointer clientData, XtPointer callData);
983 static int cmpWinAgainstFile(WindowInfo *window, const char *fileName);
984 static int min(int i1, int i2);
985 static void modifiedWindowDestroyedCB(Widget w, XtPointer clientData,
986 XtPointer callData);
987 static void forceShowLineNumbers(WindowInfo *window);
988 @@ -107,11 +115,11 @@ static void forceShowLineNumbers(WindowI
989 #ifdef VMS
990 void removeVersionNumber(char *fileName);
991 #endif /*VMS*/
993 WindowInfo *EditNewFile(WindowInfo *inWindow, char *geometry, int iconic,
994 - const char *languageMode, const char *defaultPath)
995 + const char* languageMode, const char* defaultPath, Boolean transient)
997 char name[MAXPATHLEN];
998 WindowInfo *window;
1000 /*... test for creatability? */
1001 @@ -143,11 +151,19 @@ WindowInfo *EditNewFile(WindowInfo *inWi
1003 if (iconic && IsIconic(window))
1004 RaiseDocument(window);
1005 else
1006 RaiseDocumentWindow(window);
1009 + if (transient) {
1010 + /* Set the window to transient mode. */
1011 + String apParams[1];
1013 + apParams[0] = "1";
1014 + XtCallActionProc(window->lastFocus, "set_transient", NULL, apParams, 1);
1017 SortTabBar(window);
1018 return window;
1022 @@ -173,11 +189,11 @@ WindowInfo *EditExistingFile(WindowInfo
1023 const char *path, int flags, char *geometry, int iconic,
1024 const char *languageMode, int tabbed, int bgOpen)
1026 WindowInfo *window;
1027 char fullname[MAXPATHLEN];
1030 /* first look to see if file is already displayed in a window */
1031 window = FindWindowWithFile(name, path);
1032 if (window != NULL) {
1033 if (!bgOpen) {
1034 if (iconic)
1035 @@ -248,10 +264,13 @@ WindowInfo *EditExistingFile(WindowInfo
1036 strcat(fullname, name);
1037 if(GetPrefAlwaysCheckRelTagsSpecs())
1038 AddRelTagsFile(GetPrefTagFile(), path, TAG);
1039 AddToPrevOpenMenu(fullname);
1041 + /* file_open_hook() */
1042 + MacroApplyHook(window, "file_open_hook", 0, NULL, NULL);
1044 return window;
1047 void RevertToSaved(WindowInfo *window)
1049 @@ -337,11 +356,11 @@ static int doOpen(WindowInfo *window, co
1050 int fileLen, readLen;
1051 char *fileString, *c;
1052 FILE *fp = NULL;
1053 int fd;
1054 int resp;
1057 /* initialize lock reasons */
1058 CLEAR_ALL_LOCKS(window->lockReasons);
1060 /* Update the window data structure */
1061 strcpy(window->filename, name);
1062 @@ -536,10 +555,14 @@ static int doOpen(WindowInfo *window, co
1065 SET_TMBD_LOCKED(window->lockReasons, TRUE);
1066 for (c = fileString; c < &fileString[readLen]; c++) {
1067 if (*c == '\0') {
1068 + /* Looks like every NUL character is replaced with:
1069 + ISO 8859-1: LATIN SMALL LETTER THORN
1070 + ISO 8859-7: GREEK SMALL LETTER OMEGA WITH TONOS
1071 + UTF-8: <unused> */
1072 *c = (char) 0xfe;
1075 window->buffer->nullSubsChar = (char) 0xfe;
1077 @@ -705,20 +728,21 @@ int CloseFileAndWindow(WindowInfo *windo
1079 /* Make sure that the window is not in iconified state */
1080 if (window->fileChanged)
1081 RaiseDocumentWindow(window);
1083 - /* If the window is a normal & unmodified file or an empty new file,
1084 - or if the user wants to ignore external modifications then
1085 - just close it. Otherwise ask for confirmation first. */
1086 - if (!window->fileChanged &&
1087 - /* Normal File */
1088 - ((!window->fileMissing && window->lastModTime > 0) ||
1089 - /* New File*/
1090 - (window->fileMissing && window->lastModTime == 0) ||
1091 - /* File deleted/modified externally, ignored by user. */
1092 - !GetPrefWarnFileMods()))
1093 + /* If the document is transient, belongs to a normal & unmodified file
1094 + or is empty and unchanged, or if the user wants to ignore external
1095 + modifications then just close it. Otherwise ask for confirmation first. */
1096 + if (window->transient
1097 + || (!window->fileChanged
1098 + /* Normal document, already saved */
1099 + && ((!window->fileMissing && window->lastModTime > 0)
1100 + /* New document, unchanged yet */
1101 + || (window->fileMissing && window->lastModTime == 0)
1102 + /* File deleted/modified externally, ignored by user. */
1103 + || !GetPrefWarnFileMods())))
1105 CloseWindow(window);
1106 /* up-to-date windows don't have outstanding backup files to close */
1107 } else
1109 @@ -908,10 +932,11 @@ static int doSave(WindowInfo *window)
1110 char *fileString = NULL;
1111 char fullname[MAXPATHLEN];
1112 struct stat statbuf;
1113 FILE *fp;
1114 int fileLen, result;
1115 + DataValue* fileNameArg = (DataValue*) XtMalloc(sizeof(DataValue));
1117 /* Get the full name of the file */
1118 strcpy(fullname, window->path);
1119 strcat(fullname, window->filename);
1121 @@ -1045,10 +1070,14 @@ static int doSave(WindowInfo *window)
1122 window->fileMissing = TRUE;
1123 window->device = 0;
1124 window->inode = 0;
1127 + fileNameArg->tag = STRING_TAG;
1128 + AllocNStringNCpy(&fileNameArg->val.str, fullname, MAXPATHLEN);
1129 + MacroApplyHook(window, "post_save_hook", 1, fileNameArg, NULL);
1131 return TRUE;
1135 ** Create a backup file for the current window. The name for the backup file
1136 @@ -1182,38 +1211,52 @@ static void backupFileName(WindowInfo *w
1138 static int writeBckVersion(WindowInfo *window)
1140 #ifndef VMS
1141 char fullname[MAXPATHLEN], bckname[MAXPATHLEN];
1142 + char* backname;
1143 struct stat statbuf;
1144 int in_fd, out_fd;
1145 char *io_buffer;
1146 + off_t fileLen;
1147 #define IO_BUFFER_SIZE ((size_t)(1024*1024))
1149 /* Do only if version backups are turned on */
1150 if (!window->saveOldVersion) {
1151 return False;
1154 + /* First fime numbered backup files are used. */
1155 + if (unset == version_control) {
1156 + initialize_backups();
1159 /* Get the full name of the file */
1160 strcpy(fullname, window->path);
1161 strcat(fullname, window->filename);
1163 + backname = generate_backup_filename(version_control, fullname);
1164 + if ((fileLen = strlen(backname)) < MAXPATHLEN) {
1165 + strncpy(bckname, backname, sizeof(bckname));
1167 + free(backname);
1169 /* Generate name for old version */
1170 - if ((strlen(fullname) + 5) > (size_t) MAXPATHLEN) {
1171 + if (fileLen >= (size_t) MAXPATHLEN) {
1172 return bckError(window, "file name too long", window->filename);
1174 - sprintf(bckname, "%s.bck", fullname);
1176 /* Delete the old backup file */
1177 /* Errors are ignored; we'll notice them later. */
1178 remove(bckname);
1180 /* open the file being edited. If there are problems with the
1181 old file, don't bother the user, just skip the backup */
1182 in_fd = open(fullname, O_RDONLY);
1183 if (in_fd<0) {
1184 + /* This is rather surprising behavior. Let's see more about the error. */
1185 + perror("nedit: Error reading edited file");
1186 return FALSE;
1189 /* Get permissions of the file.
1190 We preserve the normal permissions but not ownership, extended
1191 @@ -1415,162 +1458,98 @@ void PrintString(const char *string, int
1192 #endif /*VMS*/
1193 return;
1197 -** Wrapper for GetExistingFilename which uses the current window's path
1198 -** (if set) as the default directory.
1199 +** Wrapper for GetFilenameByDialog()
1201 +** TODO: I stopped the refactoring here for now, but these two could
1202 +** be combined into some sort of PromptFor.*File().
1204 int PromptForExistingFile(WindowInfo *window, char *prompt, char *fullname)
1206 - char *savedDefaultDir;
1207 - int retVal;
1209 - /* Temporarily set default directory to window->path, prompt for file,
1210 - then, if the call was unsuccessful, restore the original default
1211 - directory */
1212 - savedDefaultDir = GetFileDialogDefaultDirectory();
1213 - if (*window->path != '\0')
1214 - SetFileDialogDefaultDirectory(window->path);
1215 - retVal = GetExistingFilename(window->shell, prompt, fullname);
1216 - if (retVal != GFN_OK)
1217 - SetFileDialogDefaultDirectory(savedDefaultDir);
1219 - XtFree(savedDefaultDir);
1220 + gfbdParams params;
1221 + gfbdValue* gfbdrc;
1222 + int rc = GFN_ERROR;
1224 + params.dialogTitle = prompt;
1225 + params.parentShell = window->shell;
1226 + params.fileExists = True;
1227 + params.textfieldLabel = (GetPrefStdOpenDialog() ? "File Name" : NULL);
1228 + params.defaultName = NULL;
1229 + params.haveFormatButtons = False;
1230 + /* ...so no file format for wrap info necessary. */
1231 + params.showHidden = GetPrefShowHiddenFiles();
1233 + gfbdrc = GetFilenameByDialog(params);
1235 + switch(gfbdrc->status) {
1236 + case GFDB_OK:
1237 + strncpy(fullname, gfbdrc->payload, MAXPATHLEN);
1238 + rc = GFN_OK;
1239 + break;
1240 + case GFDB_CANCEL:
1241 + rc = GFN_CANCEL;
1242 + break;
1243 + case GFDB_ERROR:
1244 + fprintf(stderr, "nedit: Error while calling GetFilenameByDialog(): %s\n", gfbdrc->payload);
1245 + rc = GFN_ERROR;
1246 + break;
1247 + default:
1248 + /* fallback */
1249 + fprintf(stderr, "nedit: Unexpected error in GetFilenameByDialog().\n");
1250 + rc = GFN_ERROR;
1251 + break;
1254 - return retVal;
1255 + return rc;
1259 -** Wrapper for HandleCustomNewFileSB which uses the current window's path
1260 -** (if set) as the default directory, and asks about embedding newlines
1261 -** to make wrapping permanent.
1262 +** Wrapper for GetFilenameByDialog()
1264 int PromptForNewFile(WindowInfo *window, char *prompt, char *fullname,
1265 int *fileFormat, int *addWrap)
1267 - int n, retVal;
1268 - Arg args[20];
1269 - XmString s1, s2;
1270 - Widget fileSB, wrapToggle;
1271 - Widget formatForm, formatBtns, unixFormat, dosFormat, macFormat;
1272 - char *savedDefaultDir;
1274 - *fileFormat = window->fileFormat;
1276 - /* Temporarily set default directory to window->path, prompt for file,
1277 - then, if the call was unsuccessful, restore the original default
1278 - directory */
1279 - savedDefaultDir = GetFileDialogDefaultDirectory();
1280 - if (*window->path != '\0')
1281 - SetFileDialogDefaultDirectory(window->path);
1283 - /* Present a file selection dialog with an added field for requesting
1284 - long line wrapping to become permanent via inserted newlines */
1285 - n = 0;
1286 - XtSetArg(args[n],
1287 - XmNselectionLabelString,
1288 - s1 = XmStringCreateLocalized("New File Name:")); n++;
1289 - XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
1290 - XtSetArg(args[n],
1291 - XmNdialogTitle,
1292 - s2 = XmStringCreateSimple(prompt)); n++;
1293 - fileSB = CreateFileSelectionDialog(window->shell,"FileSelect",args,n);
1294 - XmStringFree(s1);
1295 - XmStringFree(s2);
1296 - formatForm = XtVaCreateManagedWidget("formatForm", xmFormWidgetClass,
1297 - fileSB, NULL);
1298 - formatBtns = XtVaCreateManagedWidget("formatBtns",
1299 - xmRowColumnWidgetClass, formatForm,
1300 - XmNradioBehavior, XmONE_OF_MANY,
1301 - XmNorientation, XmHORIZONTAL,
1302 - XmNpacking, XmPACK_TIGHT,
1303 - XmNtopAttachment, XmATTACH_FORM,
1304 - XmNleftAttachment, XmATTACH_FORM,
1305 - NULL);
1306 - XtVaCreateManagedWidget("formatBtns", xmLabelWidgetClass, formatBtns,
1307 - XmNlabelString, s1=XmStringCreateSimple("Format:"), NULL);
1308 - XmStringFree(s1);
1309 - unixFormat = XtVaCreateManagedWidget("unixFormat",
1310 - xmToggleButtonWidgetClass, formatBtns,
1311 - XmNlabelString, s1 = XmStringCreateSimple("Unix"),
1312 - XmNset, *fileFormat == UNIX_FILE_FORMAT,
1313 - XmNuserData, (XtPointer)UNIX_FILE_FORMAT,
1314 - XmNmarginHeight, 0,
1315 - XmNalignment, XmALIGNMENT_BEGINNING,
1316 - XmNmnemonic, 'U',
1317 - NULL);
1318 - XmStringFree(s1);
1319 - XtAddCallback(unixFormat, XmNvalueChangedCallback, setFormatCB,
1320 - fileFormat);
1321 - dosFormat = XtVaCreateManagedWidget("dosFormat",
1322 - xmToggleButtonWidgetClass, formatBtns,
1323 - XmNlabelString, s1 = XmStringCreateSimple("DOS"),
1324 - XmNset, *fileFormat == DOS_FILE_FORMAT,
1325 - XmNuserData, (XtPointer)DOS_FILE_FORMAT,
1326 - XmNmarginHeight, 0,
1327 - XmNalignment, XmALIGNMENT_BEGINNING,
1328 - XmNmnemonic, 'O',
1329 - NULL);
1330 - XmStringFree(s1);
1331 - XtAddCallback(dosFormat, XmNvalueChangedCallback, setFormatCB,
1332 - fileFormat);
1333 - macFormat = XtVaCreateManagedWidget("macFormat",
1334 - xmToggleButtonWidgetClass, formatBtns,
1335 - XmNlabelString, s1 = XmStringCreateSimple("Macintosh"),
1336 - XmNset, *fileFormat == MAC_FILE_FORMAT,
1337 - XmNuserData, (XtPointer)MAC_FILE_FORMAT,
1338 - XmNmarginHeight, 0,
1339 - XmNalignment, XmALIGNMENT_BEGINNING,
1340 - XmNmnemonic, 'M',
1341 - NULL);
1342 - XmStringFree(s1);
1343 - XtAddCallback(macFormat, XmNvalueChangedCallback, setFormatCB,
1344 - fileFormat);
1345 - if (window->wrapMode == CONTINUOUS_WRAP) {
1346 - wrapToggle = XtVaCreateManagedWidget("addWrap",
1347 - xmToggleButtonWidgetClass, formatForm,
1348 - XmNlabelString, s1 = XmStringCreateSimple("Add line breaks where wrapped"),
1349 - XmNalignment, XmALIGNMENT_BEGINNING,
1350 - XmNmnemonic, 'A',
1351 - XmNtopAttachment, XmATTACH_WIDGET,
1352 - XmNtopWidget, formatBtns,
1353 - XmNleftAttachment, XmATTACH_FORM,
1354 - NULL);
1355 - XtAddCallback(wrapToggle, XmNvalueChangedCallback, addWrapCB,
1356 - addWrap);
1357 - XmStringFree(s1);
1359 - *addWrap = False;
1360 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_FILTER_LABEL),
1361 - XmNmnemonic, 'l',
1362 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_FILTER_TEXT),
1363 - NULL);
1364 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST_LABEL),
1365 - XmNmnemonic, 'D',
1366 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST),
1367 - NULL);
1368 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST_LABEL),
1369 - XmNmnemonic, 'F',
1370 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST),
1371 - NULL);
1372 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_SELECTION_LABEL),
1373 - XmNmnemonic, prompt[strspn(prompt, "lFD")],
1374 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_TEXT),
1375 - NULL);
1376 - AddDialogMnemonicHandler(fileSB, FALSE);
1377 - RemapDeleteKey(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_FILTER_TEXT));
1378 - RemapDeleteKey(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_TEXT));
1379 - retVal = HandleCustomNewFileSB(fileSB, fullname,
1380 - window->filenameSet ? window->filename : NULL);
1381 + gfbdParams params;
1382 + gfbdValue* gfbdrc;
1383 + int rc = GFN_ERROR;
1385 + params.dialogTitle = prompt;
1386 + params.parentShell = window->shell;
1387 + params.fileExists = False;
1388 + params.textfieldLabel = "New File Name";
1389 + params.defaultName = window->filenameSet ? window->filename : NULL;
1390 + params.haveFormatButtons = True;
1391 + params.fileFormat = window->fileFormat;
1392 + params.isContWrapped = (CONTINUOUS_WRAP == window->wrapMode);
1393 + params.showHidden = GetPrefShowHiddenFiles();
1395 - if (retVal != GFN_OK)
1396 - SetFileDialogDefaultDirectory(savedDefaultDir);
1397 + gfbdrc = GetFilenameByDialog(params);
1398 + *addWrap = False;
1400 - XtFree(savedDefaultDir);
1401 + switch(gfbdrc->status) {
1402 + case GFDB_OK:
1403 + strncpy(fullname, gfbdrc->payload, MAXPATHLEN);
1404 + *addWrap = gfbdrc->addWrap;
1405 + rc = GFN_OK;
1406 + break;
1407 + case GFDB_CANCEL:
1408 + rc = GFN_CANCEL;
1409 + break;
1410 + case GFDB_ERROR:
1411 + fprintf(stderr, "nedit: Error while calling GetFilenameByDialog(): %s\n", gfbdrc->payload);
1412 + rc = GFN_ERROR;
1413 + break;
1414 + default:
1415 + /* fallback */
1416 + fprintf(stderr, "nedit: Unexpected error in GetFilenameByDialog().\n");
1417 + rc = GFN_ERROR;
1418 + break;
1421 - return retVal;
1422 + return rc;
1426 ** Find a name for an untitled file, unique in the name space of in the opened
1427 ** files in this session, i.e. Untitled or Untitled_nn, and write it into
1428 @@ -1882,56 +1861,10 @@ void removeVersionNumber(char *fileName)
1429 *versionStart = '\0';
1431 #endif /*VMS*/
1434 -** Callback procedure for File Format toggle buttons. Format is stored
1435 -** in userData field of widget button
1437 -static void setFormatCB(Widget w, XtPointer clientData, XtPointer callData)
1439 - if (XmToggleButtonGetState(w)) {
1440 - XtPointer userData;
1441 - XtVaGetValues(w, XmNuserData, &userData, NULL);
1442 - *(int*) clientData = (int) userData;
1447 -** Callback procedure for toggle button requesting newlines to be inserted
1448 -** to emulate continuous wrapping.
1450 -static void addWrapCB(Widget w, XtPointer clientData, XtPointer callData)
1452 - int resp;
1453 - int *addWrap = (int *)clientData;
1455 - if (XmToggleButtonGetState(w))
1457 - resp = DialogF(DF_WARN, w, 2, "Add Wrap",
1458 - "This operation adds permanent line breaks to\n"
1459 - "match the automatic wrapping done by the\n"
1460 - "Continuous Wrap mode Preferences Option.\n\n"
1461 - "*** This Option is Irreversable ***\n\n"
1462 - "Once newlines are inserted, continuous wrapping\n"
1463 - "will no longer work automatically on these lines", "OK",
1464 - "Cancel");
1465 - if (resp == 2)
1467 - XmToggleButtonSetState(w, False, False);
1468 - *addWrap = False;
1469 - } else
1471 - *addWrap = True;
1473 - } else
1475 - *addWrap = False;
1480 ** Change a window created in NEdit's continuous wrap mode to the more
1481 ** conventional Unix format of embedded newlines. Indicate to the user
1482 ** by turning off Continuous Wrap mode.
1484 static void addWrapNewlines(WindowInfo *window)
1485 diff --quilt old/source/file.h new/source/file.h
1486 --- old/source/file.h
1487 +++ new/source/file.h
1488 @@ -35,16 +35,21 @@
1489 /* flags for EditExistingFile */
1490 #define CREATE 1
1491 #define SUPPRESS_CREATE_WARN 2
1492 #define PREF_READ_ONLY 4
1494 +/* These were once set in util/getfiles.h and used throughout NEdit; they
1495 + were moved here to lower coupling between util/getfiles.c and the rest
1496 + of NEdit. */
1497 +enum gfnResult {GFN_OK, GFN_CANCEL, GFN_ERROR};
1499 #define PROMPT_SBC_DIALOG_RESPONSE 0
1500 #define YES_SBC_DIALOG_RESPONSE 1
1501 #define NO_SBC_DIALOG_RESPONSE 2
1503 WindowInfo *EditNewFile(WindowInfo *inWindow, char *geometry, int iconic,
1504 - const char *languageMode, const char *defaultPath);
1505 + const char *languageMode, const char *defaultPath, Boolean transient);
1506 WindowInfo *EditExistingFile(WindowInfo *inWindow, const char *name,
1507 const char *path, int flags, char *geometry, int iconic,
1508 const char *languageMode, int tabbed, int bgOpen);
1509 void RevertToSaved(WindowInfo *window);
1510 int SaveWindow(WindowInfo *window);
1511 diff --quilt old/source/help.c new/source/help.c
1512 --- old/source/help.c
1513 +++ new/source/help.c
1514 @@ -6,11 +6,11 @@ static const char CVSID[] = "$Id: help.c
1515 * Copyright (C) 1999 Mark Edel *
1517 * This is free software; you can redistribute it and/or modify it under the *
1518 * terms of the GNU General Public License as published by the Free Software *
1519 * Foundation; either version 2 of the License, or (at your option) any later *
1520 -* version. In addition, you may distribute version of this program linked to *
1521 +* version. In addition, you may distribute versions of this program linked to *
1522 * Motif or Open Motif. See README for details. *
1524 * This software is distributed in the hope that it will be useful, but WITHOUT *
1525 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
1526 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
1527 @@ -598,42 +598,48 @@ static Widget createHelpPanel(enum HelpT
1528 form = XtVaCreateManagedWidget("helpForm", xmFormWidgetClass, appShell,
1529 NULL);
1530 XtVaSetValues(form, XmNshadowThickness, 0, NULL);
1532 /* Create the bottom row of buttons */
1533 - btn = XtVaCreateManagedWidget("find", xmPushButtonWidgetClass, form,
1534 + btn = XtVaCreateManagedWidget("find",
1535 + xmPushButtonWidgetClass, form,
1536 XmNlabelString, st1=XmStringCreateSimple("Find..."),
1537 XmNmnemonic, 'F',
1538 XmNbottomAttachment, XmATTACH_FORM,
1539 XmNleftAttachment, XmATTACH_POSITION,
1540 XmNleftPosition, 3,
1541 XmNrightAttachment, XmATTACH_POSITION,
1542 XmNrightPosition, 25,
1543 + XmNtraversalOn, False,
1544 NULL);
1545 XtAddCallback(btn, XmNactivateCallback, searchHelpCB, appShell);
1546 XmStringFree(st1);
1548 - btn = XtVaCreateManagedWidget("findAgain", xmPushButtonWidgetClass, form,
1549 + btn = XtVaCreateManagedWidget("findAgain",
1550 + xmPushButtonWidgetClass, form,
1551 XmNlabelString, st1=XmStringCreateSimple("Find Again"),
1552 XmNmnemonic, 'A',
1553 XmNbottomAttachment, XmATTACH_FORM,
1554 XmNleftAttachment, XmATTACH_POSITION,
1555 XmNleftPosition, 27,
1556 XmNrightAttachment, XmATTACH_POSITION,
1557 XmNrightPosition, 49,
1558 + XmNtraversalOn, False,
1559 NULL);
1560 XtAddCallback(btn, XmNactivateCallback, searchHelpAgainCB, appShell);
1561 XmStringFree(st1);
1563 - btn = XtVaCreateManagedWidget("print", xmPushButtonWidgetClass, form,
1564 + btn = XtVaCreateManagedWidget("print",
1565 + xmPushButtonWidgetClass, form,
1566 XmNlabelString, st1=XmStringCreateSimple("Print..."),
1567 XmNmnemonic, 'P',
1568 XmNbottomAttachment, XmATTACH_FORM,
1569 XmNleftAttachment, XmATTACH_POSITION,
1570 XmNleftPosition, 51,
1571 XmNrightAttachment, XmATTACH_POSITION,
1572 XmNrightPosition, 73,
1573 + XmNtraversalOn, False,
1574 NULL);
1575 XtAddCallback(btn, XmNactivateCallback, printCB, appShell);
1576 XmStringFree(st1);
1578 closeBtn = XtVaCreateManagedWidget("close",
1579 @@ -642,79 +648,89 @@ static Widget createHelpPanel(enum HelpT
1580 XmNbottomAttachment, XmATTACH_FORM,
1581 XmNleftAttachment, XmATTACH_POSITION,
1582 XmNleftPosition, 75,
1583 XmNrightAttachment, XmATTACH_POSITION,
1584 XmNrightPosition, 97,
1585 + XmNtraversalOn, False,
1586 NULL);
1587 XtAddCallback(closeBtn, XmNactivateCallback, closeCB, appShell);
1588 XmStringFree(st1);
1590 /* Create the next row of buttons (for navigation) */
1591 - btn = XtVaCreateManagedWidget("prevTopic", xmPushButtonWidgetClass, form,
1592 + btn = XtVaCreateManagedWidget("prevTopic",
1593 + xmPushButtonWidgetClass, form,
1594 XmNlabelString, st1=XmStringCreateSimple("<< Browse"),
1595 XmNmnemonic, 'o',
1596 XmNbottomAttachment, XmATTACH_WIDGET,
1597 XmNbottomWidget, closeBtn,
1598 XmNleftAttachment, XmATTACH_POSITION,
1599 XmNleftPosition, 51,
1600 XmNrightAttachment, XmATTACH_POSITION,
1601 XmNrightPosition, 73,
1602 + XmNtraversalOn, False,
1603 NULL);
1604 XtAddCallback(btn, XmNactivateCallback, prevTopicCB, appShell);
1605 XmStringFree(st1);
1607 - btn = XtVaCreateManagedWidget("nextTopic", xmPushButtonWidgetClass, form,
1608 + btn = XtVaCreateManagedWidget("nextTopic",
1609 + xmPushButtonWidgetClass, form,
1610 XmNlabelString, st1=XmStringCreateSimple("Browse >>"),
1611 XmNmnemonic, 'e',
1612 XmNbottomAttachment, XmATTACH_WIDGET,
1613 XmNbottomWidget, closeBtn,
1614 XmNleftAttachment, XmATTACH_POSITION,
1615 XmNleftPosition, 75,
1616 XmNrightAttachment, XmATTACH_POSITION,
1617 XmNrightPosition, 97,
1618 + XmNtraversalOn, False,
1619 NULL);
1620 XtAddCallback(btn, XmNactivateCallback, nextTopicCB, appShell);
1621 XmStringFree(st1);
1623 - btn = XtVaCreateManagedWidget("histBack", xmPushButtonWidgetClass, form,
1624 + btn = XtVaCreateManagedWidget("histBack",
1625 + xmPushButtonWidgetClass, form,
1626 XmNlabelString, st1=XmStringCreateSimple("Back"),
1627 XmNmnemonic, 'B',
1628 XmNbottomAttachment, XmATTACH_WIDGET,
1629 XmNbottomWidget, closeBtn,
1630 XmNleftAttachment, XmATTACH_POSITION,
1631 XmNleftPosition, 3,
1632 XmNrightAttachment, XmATTACH_POSITION,
1633 XmNrightPosition, 25,
1634 + XmNtraversalOn, False,
1635 NULL);
1636 XtAddCallback(btn, XmNactivateCallback, bwHistoryCB, appShell);
1637 XmStringFree(st1);
1639 - btnFW = XtVaCreateManagedWidget("histForw", xmPushButtonWidgetClass, form,
1640 + btnFW = XtVaCreateManagedWidget("histForw",
1641 + xmPushButtonWidgetClass, form,
1642 XmNlabelString, st1=XmStringCreateSimple("Forward"),
1643 XmNmnemonic, 'w',
1644 XmNbottomAttachment, XmATTACH_WIDGET,
1645 XmNbottomWidget, closeBtn,
1646 XmNleftAttachment, XmATTACH_POSITION,
1647 XmNleftPosition, 27,
1648 XmNrightAttachment, XmATTACH_POSITION,
1649 XmNrightPosition, 49,
1650 + XmNtraversalOn, False,
1651 NULL);
1652 XtAddCallback(btnFW, XmNactivateCallback, fwHistoryCB, appShell);
1653 XmStringFree(st1);
1655 /* Create a text widget inside of a scrolled window widget */
1656 - sw = XtVaCreateManagedWidget("sw", xmScrolledWindowWidgetClass, form,
1657 + sw = XtVaCreateManagedWidget("sw",
1658 + xmScrolledWindowWidgetClass, form,
1659 XmNshadowThickness, 2,
1660 XmNtopAttachment, XmATTACH_FORM,
1661 XmNleftAttachment, XmATTACH_FORM,
1662 XmNrightAttachment, XmATTACH_FORM,
1663 XmNbottomAttachment, XmATTACH_WIDGET,
1664 XmNbottomWidget, btnFW,
1665 NULL);
1666 hScrollBar = XtVaCreateManagedWidget("hScrollBar",
1667 xmScrollBarWidgetClass, sw,
1668 - XmNorientation, XmHORIZONTAL,
1669 + XmNorientation, XmHORIZONTAL,
1670 XmNrepeatDelay, 10,
1671 NULL);
1672 vScrollBar = XtVaCreateManagedWidget("vScrollBar",
1673 xmScrollBarWidgetClass, sw,
1674 XmNorientation, XmVERTICAL,
1675 @@ -733,15 +749,16 @@ static Widget createHelpPanel(enum HelpT
1676 textNvScrollBar, vScrollBar,
1677 textNreadOnly, True,
1678 textNcontinuousWrap, True,
1679 textNautoShowInsertPos, True,
1680 NULL);
1681 - XtVaSetValues(sw, XmNworkWindow, HelpTextPanes[topic],
1682 + XtVaSetValues(sw,
1683 + XmNworkWindow, HelpTextPanes[topic],
1684 XmNhorizontalScrollBar, hScrollBar,
1685 XmNverticalScrollBar, vScrollBar,
1686 NULL);
1689 /* Initialize help style information, if it hasn't already been init'd */
1690 initHelpStyles (HelpTextPanes[topic]);
1692 /* Put together the text to display and separate it into parallel text
1693 and style data for display by the widget */
1694 @@ -802,11 +819,10 @@ static void changeTopicOrRaise(int exist
1696 RaiseShellWindow(HelpWindows[newTopic], True);
1697 adaptNavigationButtons(existingTopic);
1698 adaptNavigationButtons(newTopic);
1704 ** Callbacks for window controls
1706 @@ -900,12 +916,22 @@ static void searchHelpCB(Widget w, XtPoi
1707 static void searchHelpAgainCB(Widget w, XtPointer clientData,
1708 XtPointer callData)
1710 int topic;
1712 - if ((topic = findTopicFromShellWidget((Widget)clientData)) == -1)
1713 - return; /* shouldn't happen */
1714 + if ((topic = findTopicFromShellWidget((Widget)clientData)) == -1) {
1715 + /* shouldn't happen */
1716 + fprintf(stderr, "nedit: Unexpected location found in help.c\n");
1717 + return;
1720 + if (0 == strcmp(LastSearchString, "")) {
1721 + /* no previous search */
1722 + XBell(TheDisplay, 0);
1723 + return;
1726 searchHelpText(HelpWindows[topic], topic, LastSearchString,
1727 LastSearchWasAllTopics, LastSearchPos, LastSearchTopic);
1730 static void printCB(Widget w, XtPointer clientData, XtPointer callData)
1731 @@ -1005,16 +1031,10 @@ static void followHyperlink(int topic, i
1732 adaptNavigationButtons(topic);
1734 XtFree (link_text);
1737 -static void helpFocusButtonsAP(Widget w, XEvent *event, String *args,
1738 - Cardinal *nArgs)
1740 - XmProcessTraversal(w, XmTRAVERSE_NEXT_TAB_GROUP);
1744 * handler for help-button-action(<button-name>)
1745 * Calls the activate callback for the named button widget of the help text win.
1747 static void helpButtonActionAP(Widget w, XEvent *event, String *args,
1748 @@ -1148,11 +1168,10 @@ static void helpHyperlinkAP(Widget w, XE
1749 void InstallHelpLinkActions(XtAppContext context)
1751 static XtActionsRec Actions[] =
1753 {"help-hyperlink", helpHyperlinkAP},
1754 - {"help-focus-buttons", helpFocusButtonsAP},
1755 {"help-button-action", helpButtonActionAP}
1758 XtAppAddActions(context, Actions, XtNumber(Actions));
1760 diff --quilt old/source/highlightData.c new/source/highlightData.c
1761 --- old/source/highlightData.c
1762 +++ new/source/highlightData.c
1763 @@ -546,14 +546,14 @@ static char *DefaultPatternSets[] = {
1764 Wrong logical ops:\"&&|\\|\\|\":::Plain::\n\
1765 Logical operators:\"~|&|\\|\":::Text Arg2::}",
1766 "NEdit Macro:2:0{\n\
1767 README:\"NEdit Macro syntax highlighting patterns, version 2.6, maintainer Thorsten Haude, nedit at thorstenhau.de\":::Flag::D\n\
1768 Comment:\"#\":\"$\"::Comment::\n\
1769 - Built-in Misc Vars:\"(?<!\\Y)\\$(?:active_pane|args|calltip_ID|column|cursor|display_width|empty_array|file_name|file_path|language_mode|line|locked|max_font_width|min_font_width|modified|n_display_lines|n_panes|rangeset_list|read_only|selection_(?:start|end|left|right)|server_name|text_length|top_line|VERSION)>\":::Identifier::\n\
1770 + Built-in Misc Vars:\"(?<!\\Y)\\$(?:active_pane|args|calltip_ID|column|cursor|display_width|empty_array|file_name|file_path|language_mode|line|locked|max_font_width|min_font_width|modified|n_display_lines|n_panes|rangeset_list|read_only|selection_(?:start|end|left|right)|server_name|text_length|top_line|VERSION|NEDIT_HOME)>\":::Identifier::\n\
1771 Built-in Pref Vars:\"(?<!\\Y)\\$(?:auto_indent|em_tab_dist|file_format|font_name|font_name_bold|font_name_bold_italic|font_name_italic|highlight_syntax|incremental_backup|incremental_search_line|make_backup_copy|match_syntax_based|overtype_mode|show_line_numbers|show_matching|statistics_line|tab_dist|use_tabs|wrap_margin|wrap_text)>\":::Identifier2::\n\
1772 Built-in Special Vars:\"(?<!\\Y)\\$(?:[1-9]|list_dialog_button|n_args|read_status|search_end|shell_cmd_status|string_dialog_button|sub_sep)>\":::String1::\n\
1773 - Built-in Subrs:\"<(?:append_file|beep|call|calltip|clipboard_to_string|dialog|filename_dialog|focus_window|get_character|get_pattern_(by_name|at_pos)|get_range|get_selection|get_style_(by_name|at_pos)|getenv|kill_calltip|length|list_dialog|max|min|rangeset_(?:add|create|destroy|get_by_name|includes|info|invert|range|set_color|set_mode|set_name|subtract)|read_file|replace_in_string|replace_range|replace_selection|replace_substring|search|search_string|select|select_rectangle|set_cursor_pos|shell_command|split|string_compare|string_dialog|string_to_clipboard|substring|t_print|tolower|toupper|valid_number|write_file)(?=\\s*\\()\":::Subroutine::\n\
1774 + Built-in Subrs:\"<(?:append_file|beep|call|calltip|clipboard_to_string|dialog|filename_dialog|focus_window|get_character|get_pattern_(by_name|at_pos)|get_range|get_selection|get_style_(by_name|at_pos)|getenv|highlight_calltip_line|kill_calltip|length|list_dialog|max|min|rangeset_(?:add|create|destroy|get_by_name|includes|info|invert|range|set_color|set_mode|set_name|subtract)|read_file|replace_in_string|replace_range|replace_selection|replace_substring|search|search_string|select|select_rectangle|set_cursor_pos|set_transient|shell_command|split|string_compare|string_dialog|string_to_clipboard|substring|t_print|tolower|toupper|typeof|valid_number|write_file)(?=\\s*\\()\":::Subroutine::\n\
1775 Menu Actions:\"<(?:new(?:_tab|_opposite)?|open|open-dialog|open_dialog|open-selected|open_selected|close|save|save-as|save_as|save-as-dialog|save_as_dialog|revert-to-saved|revert_to_saved|revert_to_saved_dialog|include-file|include_file|include-file-dialog|include_file_dialog|load-macro-file|load_macro_file|load-macro-file-dialog|load_macro_file_dialog|load-tags-file|load_tags_file|load-tags-file-dialog|load_tags_file_dialog|unload_tags_file|load_tips_file|load_tips_file_dialog|unload_tips_file|print|print-selection|print_selection|exit|undo|redo|delete|select-all|select_all|shift-left|shift_left|shift-left-by-tab|shift_left_by_tab|shift-right|shift_right|shift-right-by-tab|shift_right_by_tab|find|find-dialog|find_dialog|find-again|find_again|find-selection|find_selection|find_incremental|start_incremental_find|replace|replace-dialog|replace_dialog|replace-all|replace_all|replace-in-selection|replace_in_selection|replace-again|replace_again|replace_find|replace_find_same|replace_find_again|goto-line-number|goto_line_number|goto-line-number-dialog|goto_line_number_dialog|goto-selected|goto_selected|mark|mark-dialog|mark_dialog|goto-mark|goto_mark|goto-mark-dialog|goto_mark_dialog|match|select_to_matching|goto_matching|find-definition|find_definition|show_tip|split-pane|split_pane|close-pane|close_pane|detach_document(?:_dialog)?|move_document_dialog|(?:next|previous|last)_document|uppercase|lowercase|fill-paragraph|fill_paragraph|control-code-dialog|control_code_dialog|filter-selection-dialog|filter_selection_dialog|filter-selection|filter_selection|execute-command|execute_command|execute-command-dialog|execute_command_dialog|execute-command-line|execute_command_line|shell-menu-command|shell_menu_command|macro-menu-command|macro_menu_command|bg_menu_command|post_window_bg_menu|post_tab_context_menu|beginning-of-selection|beginning_of_selection|end-of-selection|end_of_selection|repeat_macro|repeat_dialog|raise_window|focus_pane|set_statistics_line|set_incremental_search_line|set_show_line_numbers|set_auto_indent|set_wrap_text|set_wrap_margin|set_highlight_syntax|set_make_backup_copy|set_incremental_backup|set_show_matching|set_match_syntax_based|set_overtype_mode|set_locked|set_tab_dist|set_em_tab_dist|set_use_tabs|set_fonts|set_language_mode)(?=\\s*\\()\":::Subroutine::\n\
1776 Text Actions:\"<(?:self-insert|self_insert|grab-focus|grab_focus|extend-adjust|extend_adjust|extend-start|extend_start|extend-end|extend_end|secondary-adjust|secondary_adjust|secondary-or-drag-adjust|secondary_or_drag_adjust|secondary-start|secondary_start|secondary-or-drag-start|secondary_or_drag_start|process-bdrag|process_bdrag|move-destination|move_destination|move-to|move_to|move-to-or-end-drag|move_to_or_end_drag|end_drag|copy-to|copy_to|copy-to-or-end-drag|copy_to_or_end_drag|exchange|process-cancel|process_cancel|paste-clipboard|paste_clipboard|copy-clipboard|copy_clipboard|cut-clipboard|cut_clipboard|copy-primary|copy_primary|cut-primary|cut_primary|newline|newline-and-indent|newline_and_indent|newline-no-indent|newline_no_indent|delete-selection|delete_selection|delete-previous-character|delete_previous_character|delete-next-character|delete_next_character|delete-previous-word|delete_previous_word|delete-next-word|delete_next_word|delete-to-start-of-line|delete_to_start_of_line|delete-to-end-of-line|delete_to_end_of_line|forward-character|forward_character|backward-character|backward_character|key-select|key_select|process-up|process_up|process-down|process_down|process-shift-up|process_shift_up|process-shift-down|process_shift_down|process-home|process_home|forward-word|forward_word|backward-word|backward_word|forward-paragraph|forward_paragraph|backward-paragraph|backward_paragraph|beginning-of-line|beginning_of_line|end-of-line|end_of_line|beginning-of-file|beginning_of_file|end-of-file|end_of_file|next-page|next_page|previous-page|previous_page|page-left|page_left|page-right|page_right|toggle-overstrike|toggle_overstrike|scroll-up|scroll_up|scroll-down|scroll_down|scroll_left|scroll_right|scroll-to-line|scroll_to_line|select-all|select_all|deselect-all|deselect_all|focusIn|focusOut|process-return|process_return|process-tab|process_tab|insert-string|insert_string|mouse_pan)(?=\\s*\\()\":::Subroutine::\n\
1777 Keyword:\"<(?:break|continue|define|delete|else|for|if|in|return|while)>\":::Keyword::\n\
1778 Braces:\"[{}\\[\\]]\":::Keyword::\n\
1779 Global Variable:\"\\$[A-Za-z0-9_]+\":::Identifier1::\n\
1780 diff --quilt old/source/interpret.c new/source/interpret.c
1781 --- old/source/interpret.c
1782 +++ new/source/interpret.c
1783 @@ -199,11 +199,11 @@ static SparseArrayEntryWrapper *Allocate
1785 /* Message strings used in macros (so they don't get repeated every time
1786 the macros are used */
1787 static const char *StackOverflowMsg = "macro stack overflow";
1788 static const char *StackUnderflowMsg = "macro stack underflow";
1789 -static const char *StringToNumberMsg = "string could not be converted to number";
1790 +static const char* StringToNumberMsg = "string '%s' could not be converted to number";
1792 /* Temporary global data for use while accumulating programs */
1793 static Symbol *LocalSymList = NULL; /* symbols local to the program */
1794 static Inst Prog[PROGRAM_SIZE]; /* the program */
1795 static Inst *ProgP; /* next free spot for code gen. */
1796 @@ -597,10 +597,13 @@ int ContinueMacro(RestartData *continuat
1797 ErrMsg = NULL;
1798 for (;;) {
1800 /* Execute an instruction */
1801 inst = PC++;
1802 +// fprintf(stderr, "inst->sym->name: %s\n", inst->sym->name);
1803 +// fprintf(stderr, "inst->sym->type: %d\n", inst->sym->type);
1804 +// fprintf(stderr, "inst->sym->value.tag: %d\n", inst->sym->value.tag);
1805 status = (inst->func)();
1807 /* If error return was not STAT_OK, return to caller */
1808 if (status != STAT_OK) {
1809 if (status == STAT_PREEMPT) {
1810 @@ -1198,12 +1201,13 @@ static void freeSymbolTable(Symbol *symT
1811 #define POP_INT(number) \
1812 if (StackP == TheStack) \
1813 return execError(StackUnderflowMsg, ""); \
1814 --StackP; \
1815 if (StackP->tag == STRING_TAG) { \
1816 - if (!StringToNum(StackP->val.str.rep, &number)) \
1817 - return execError(StringToNumberMsg, ""); \
1818 + if (!StringToNum(StackP->val.str.rep, &number)) {\
1819 + return execError(StringToNumberMsg, StackP->val.str.rep); \
1820 + } \
1821 } else if (StackP->tag == INT_TAG) \
1822 number = StackP->val.n; \
1823 else \
1824 return(execError("can't convert array to integer", NULL));
1826 @@ -1316,13 +1320,17 @@ static int pushSymVal(void)
1827 return execError(errMsg, s->name);
1829 *StackP = result;
1830 } else
1831 return execError("reading non-variable: %s", s->name);
1833 +/* typeof()
1834 if (StackP->tag == NO_TAG) {
1835 - return execError("variable not set: %s", s->name);
1836 + return execError("variable not set: %s", s->name);
1840 StackP++;
1841 if (StackP >= &TheStack[STACK_SIZE]) {
1842 return execError(StackOverflowMsg, "");
1844 return STAT_OK;
1845 @@ -1423,13 +1431,15 @@ static int pushArraySymVal(void)
1846 if (initEmpty && dataPtr->tag == NO_TAG) {
1847 dataPtr->tag = ARRAY_TAG;
1848 dataPtr->val.arrayPtr = ArrayNew();
1851 +/* typeof()
1852 if (dataPtr->tag == NO_TAG) {
1853 return execError("variable not set: %s", sym->name);
1857 *StackP = *dataPtr;
1858 StackP++;
1860 if (StackP >= &TheStack[STACK_SIZE]) {
1861 @@ -3081,17 +3091,21 @@ static int arrayRef(void)
1864 POP(srcArray)
1865 if (srcArray.tag == ARRAY_TAG) {
1866 if (!ArrayGet(&srcArray, keyString, &valueItem)) {
1867 - return(execError("referenced array value not in array: %s", keyString));
1868 +/*typeof() return(execError("referenced array value not in array: %s", keyString));*/
1869 + valueItem.tag = NO_TAG;
1871 PUSH(valueItem)
1872 return(STAT_OK);
1874 else {
1875 - return(execError("operator [] on non-array", NULL));
1876 +/*typeof() return(execError("operator [] on non-array", NULL));*/
1877 + valueItem.tag = NO_TAG;
1878 + PUSH(valueItem)
1879 + return(STAT_OK);
1882 else {
1883 POP(srcArray)
1884 if (srcArray.tag == ARRAY_TAG) {
1885 @@ -3494,10 +3508,11 @@ static int execError(const char *s1, con
1886 static char msg[MAX_ERR_MSG_LEN];
1887 static char *err = NULL;
1888 static int errlen = 0;
1890 sprintf(msg, s1, s2);
1891 + msg[MAX_ERR_MSG_LEN - 1] = '\0';
1892 ErrMsg = stackDumpStr(FrameP, msg, &err, &errlen);
1893 return STAT_ERROR;
1896 int StringToNum(const char *string, int *number)
1897 diff --quilt old/source/macro.c new/source/macro.c
1898 --- old/source/macro.c
1899 +++ new/source/macro.c
1900 @@ -30,35 +30,35 @@ static const char CVSID[] = "$Id: macro.
1902 #ifdef HAVE_CONFIG_H
1903 #include "../config.h"
1904 #endif
1906 +#include "calltips.h"
1907 +#include "highlightData.h"
1908 +#include "highlight.h"
1909 +#include "interpret.h"
1910 #include "macro.h"
1911 -#include "textBuf.h"
1912 -#include "text.h"
1913 #include "nedit.h"
1914 -#include "window.h"
1915 -#include "preferences.h"
1916 -#include "interpret.h"
1917 #include "parse.h"
1918 +#include "preferences.h"
1919 +#include "rangeset.h"
1920 +#include "rbTree.h"
1921 #include "search.h"
1922 +#include "selection.h"
1923 #include "server.h"
1924 #include "shell.h"
1925 #include "smartIndent.h"
1926 -#include "userCmds.h"
1927 -#include "selection.h"
1928 -#include "rbTree.h"
1929 #include "tags.h"
1930 -#include "calltips.h"
1931 +#include "textBuf.h"
1932 +#include "text.h"
1933 +#include "userCmds.h"
1934 +#include "window.h"
1935 #include "../util/DialogF.h"
1936 -#include "../util/misc.h"
1937 #include "../util/fileUtils.h"
1938 -#include "../util/utils.h"
1939 #include "../util/getfiles.h"
1940 -#include "highlight.h"
1941 -#include "highlightData.h"
1942 -#include "rangeset.h"
1943 +#include "../util/misc.h"
1944 +#include "../util/utils.h"
1946 #include <stdio.h>
1947 #include <stdlib.h>
1948 #include <string.h>
1949 #include <ctype.h>
1950 @@ -75,26 +75,27 @@ static const char CVSID[] = "$Id: macro.
1951 #ifndef __MVS__
1952 #include <sys/param.h>
1953 #endif
1954 #include <fcntl.h>
1955 #endif /*VMS*/
1956 +#include <stdarg.h>
1958 #include <X11/Intrinsic.h>
1959 #include <X11/keysym.h>
1960 #include <Xm/Xm.h>
1961 #include <Xm/CutPaste.h>
1962 +#include <Xm/DialogS.h>
1963 #include <Xm/Form.h>
1964 -#include <Xm/RowColumn.h>
1965 #include <Xm/LabelG.h>
1966 #include <Xm/List.h>
1967 -#include <Xm/ToggleB.h>
1968 -#include <Xm/DialogS.h>
1969 #include <Xm/MessageB.h>
1970 -#include <Xm/SelectioB.h>
1971 #include <Xm/PushB.h>
1972 -#include <Xm/Text.h>
1973 +#include <Xm/RowColumn.h>
1974 +#include <Xm/SelectioB.h>
1975 #include <Xm/Separator.h>
1976 +#include <Xm/Text.h>
1977 +#include <Xm/ToggleB.h>
1979 #ifdef HAVE_DEBUG_H
1980 #include "../debug.h"
1981 #endif
1983 @@ -233,10 +234,12 @@ static void stringDialogCloseCB(Widget w
1984 static void stringDialogEscCB(Widget w, XtPointer clientData, XEvent *event,
1985 Boolean *cont);
1986 #endif /* LESSTIF_VERSION */
1987 static int calltipMS(WindowInfo *window, DataValue *argList, int nArgs,
1988 DataValue *result, char **errMsg);
1989 +static int highlightCTLineMS(WindowInfo* window, DataValue* argList, int nArgs,
1990 + DataValue* result, char** errMsg);
1991 static int killCalltipMS(WindowInfo *window, DataValue *argList, int nArgs,
1992 DataValue *result, char **errMsg);
1993 /* T Balinski */
1994 static int listDialogMS(WindowInfo *window, DataValue *argList, int nArgs,
1995 DataValue *result, char **errMsg);
1996 @@ -350,19 +353,21 @@ static int calltipIDMV(WindowInfo *windo
1997 static int readSearchArgs(DataValue *argList, int nArgs, int*searchDirection,
1998 int *searchType, int *wrap, char **errMsg);
1999 static int wrongNArgsErr(char **errMsg);
2000 static int tooFewArgsErr(char **errMsg);
2001 static int strCaseCmp(char *str1, char *str2);
2002 -static int readIntArg(DataValue dv, int *result, char **errMsg);
2003 +static Boolean readIntArg(DataValue dv, int *result, char **errMsg);
2004 static int readStringArg(DataValue dv, char **result, char *stringStorage,
2005 char **errMsg);
2006 /* DISABLED FOR 5.4
2007 static int backlightStringMV(WindowInfo *window, DataValue *argList,
2008 int nArgs, DataValue *result, char **errMsg);
2010 static int rangesetListMV(WindowInfo *window, DataValue *argList,
2011 int nArgs, DataValue *result, char **errMsg);
2012 +static int neditHomeMV(WindowInfo* window, DataValue* argList, int nArgs,
2013 + DataValue* result, char** errMsg);
2014 static int versionMV(WindowInfo* window, DataValue* argList, int nArgs,
2015 DataValue* result, char** errMsg);
2016 static int rangesetCreateMS(WindowInfo *window, DataValue *argList, int nArgs,
2017 DataValue *result, char **errMsg);
2018 static int rangesetDestroyMS(WindowInfo *window, DataValue *argList, int nArgs,
2019 @@ -405,10 +410,12 @@ static int getStyleAtPosMS(WindowInfo *w
2020 DataValue *result, char **errMsg);
2021 static int filenameDialogMS(WindowInfo* window, DataValue* argList, int nArgs,
2022 DataValue* result, char** errMsg);
2023 static int callMS(WindowInfo *window, DataValue *argList,
2024 int nArgs, DataValue *result, char **errMsg);
2025 +static int typeofMS(WindowInfo* window, DataValue* argList, int nArgs,
2026 + DataValue* result, char** errMsg);
2028 /* Built-in subroutines and variables for the macro language */
2029 static const BuiltInSubrName MacroSubrs[] = {
2030 { "length", lengthMS },
2031 { "get_range", getRangeMS },
2032 @@ -444,10 +451,11 @@ static const BuiltInSubrName MacroSubrs[
2033 { "getenv", getenvMS },
2034 { "string_compare", stringCompareMS },
2035 { "split", splitMS },
2036 { "calltip", calltipMS },
2037 { "kill_calltip", killCalltipMS },
2038 + { "highlight_calltip_line", highlightCTLineMS },
2039 /* DISABLED for 5.4
2040 { "set_backlight_string", setBacklightStringMS },
2042 { "rangeset_create", rangesetCreateMS },
2043 { "rangeset_destroy", rangesetDestroyMS },
2044 @@ -465,10 +473,11 @@ static const BuiltInSubrName MacroSubrs[
2045 { "get_pattern_at_pos", getPatternAtPosMS },
2046 { "get_style_by_name", getStyleByNameMS },
2047 { "get_style_at_pos", getStyleAtPosMS },
2048 { "filename_dialog", filenameDialogMS },
2049 { "call", callMS },
2050 + { "typeof", typeofMS },
2051 { NULL, NULL } /* sentinel */
2054 static const BuiltInSubrName SpecialVars[] = {
2055 { "$cursor", cursorMV },
2056 @@ -519,10 +528,11 @@ static const BuiltInSubrName SpecialVars
2057 /* DISABLED for 5.4
2058 { "$backlight_string", backlightStringMV },
2060 { "$rangeset_list", rangesetListMV },
2061 { "$VERSION", versionMV },
2062 + { "$NEDIT_HOME", neditHomeMV },
2063 { NULL, NULL } /* sentinel */
2066 /* Global symbols for "returning" secondary values from built-in functions */
2067 static int STRING_DIALOG_BUTTON, SEARCH_END, READ_STATUS,
2068 @@ -3420,10 +3430,61 @@ bad_arg:
2069 *errMsg = "unrecognized argument to %s";
2070 return False;
2074 +** highlight_calltip_line(ctID, line)
2076 +static int highlightCTLineMS(WindowInfo* window, DataValue* argList, int nArgs,
2077 + DataValue* result, char** errMsg)
2079 + int calltipID = 0;
2080 + int line;
2081 + int highlightResult;
2083 + if (2 != nArgs) {
2084 + *errMsg = "%s() called with wrong number of arguments";
2085 + return False;
2088 + if (!readIntArg(argList[0], &calltipID, errMsg)) {
2089 + *errMsg = "%s(): Could not read calltip ID from argument 1";
2090 + return False;
2093 + /* The macro function calltip() uses 0 to report an error. Catch sloppy
2094 + programmers who just feed this value into this function. */
2095 + if (0 == calltipID) {
2096 + *errMsg = "%s(): Invalid calltip ID 0";
2097 + return False;
2100 + if (!readIntArg(argList[1], &line, errMsg) || line < 0) {
2101 + *errMsg = "%s(): Could not read line number from argument 2";
2102 + return False;
2105 + result->tag = NO_TAG;
2107 + highlightResult = HighlightCalltipLine(window, calltipID, (unsigned) line);
2109 + if (CT_INVALID_ID == highlightResult) {
2110 + /* Fail only if the calltip ID given is invalid. */
2111 + *errMsg = "%s(): Invalid calltip ID";
2112 + return False;
2115 + /* In case NEdit ever gets a warning (!= error) mechanism:
2116 + if (CT_NOLINE == highlightResult) {
2117 + *warnMsg = "%s(): Calltip line out of range";
2119 + */
2121 + return True;
2125 ** A subroutine to kill the current calltip
2127 static int killCalltipMS(WindowInfo *window, DataValue *argList, int nArgs,
2128 DataValue *result, char **errMsg)
2130 @@ -3449,11 +3510,11 @@ static int killCalltipMS(WindowInfo *win
2132 static int calltipIDMV(WindowInfo *window, DataValue *argList,
2133 int nArgs, DataValue *result, char **errMsg)
2135 result->tag = INT_TAG;
2136 - result->val.n = GetCalltipID(window, 0);
2137 + result->val.n = GetCalltipID(window);
2138 return True;
2142 ** filename_dialog([title[, mode[, defaultPath[, filter[, defaultName]]]]])
2143 @@ -3478,19 +3539,20 @@ static int calltipIDMV(WindowInfo *windo
2145 static int filenameDialogMS(WindowInfo* window, DataValue* argList, int nArgs,
2146 DataValue* result, char** errMsg)
2148 char stringStorage[5][TYPE_INT_STR_SIZE(int)];
2149 - char filename[MAXPATHLEN + 1];
2150 char* title = "Choose Filename";
2151 char* mode = "exist";
2152 char* defaultPath = "";
2153 char* filter = "";
2154 char* defaultName = "";
2155 char* orgDefaultPath;
2156 char* orgFilter;
2157 - int gfnResult;
2158 + gfbdParams params;
2159 + gfbdValue* gfbdrc;
2160 + int rc = False;
2162 /* Ignore the focused window passed as the function argument and put
2163 the dialog up over the window which is executing the macro */
2164 window = MacroRunWindow();
2166 @@ -3545,37 +3607,56 @@ static int filenameDialogMS(WindowInfo*
2167 orgFilter = GetFileDialogDefaultPattern();
2168 if ('\0' != filter[0]) {
2169 SetFileDialogDefaultPattern(filter);
2172 - /* Fork to one of the worker methods from util/getfiles.c.
2173 - (This should obviously be refactored.) */
2174 - if (0 == strcmp(mode, "exist")) {
2175 - gfnResult = GetExistingFilename(window->shell, title, filename);
2176 - } else {
2177 - gfnResult = GetNewFilename(window->shell, title, filename, defaultName);
2178 - } /* Invalid values are weeded out above. */
2179 + params.dialogTitle = title;
2180 + params.parentShell = window->shell;
2181 + params.fileExists = (0 == strcmp(mode, "exist")) ? True : False;
2182 + params.textfieldLabel = "New File Name";
2183 + params.defaultName = (0 == strcmp("", defaultName)) ? NULL : defaultName;
2184 + params.haveFormatButtons = False;
2185 + /* ...so no file format for wrap info necessary. */
2186 + params.showHidden = GetPrefShowHiddenFiles();
2188 + gfbdrc = GetFilenameByDialog(params);
2190 /* Reset original values and free temps */
2191 SetFileDialogDefaultDirectory(orgDefaultPath);
2192 SetFileDialogDefaultPattern(orgFilter);
2193 XtFree(orgDefaultPath);
2194 XtFree(orgFilter);
2196 result->tag = STRING_TAG;
2197 - if (GFN_OK == gfnResult) {
2198 - /* Got a string, copy it to the result */
2199 - if (!AllocNStringNCpy(&result->val.str, filename, MAXPATHLEN)) {
2200 - M_FAILURE("failed to allocate return value: %s");
2202 - } else {
2203 - /* User cancelled. Return "" */
2204 - result->val.str.rep = PERM_ALLOC_STR("");
2205 - result->val.str.len = 0;
2206 + switch(gfbdrc->status) {
2207 + case GFDB_OK:
2208 + /* Got a filename, copy it to the result */
2209 + if (!AllocNStringNCpy(&result->val.str, gfbdrc->payload, MAXPATHLEN)) {
2210 + M_FAILURE("failed to allocate return value: %s");
2212 + rc = True;
2213 + break;
2214 + case GFDB_CANCEL:
2215 + /* User cancelled. Return "" */
2216 + result->val.str.rep = PERM_ALLOC_STR("");
2217 + result->val.str.len = 0;
2218 + rc = True;
2219 + break;
2220 + case GFDB_ERROR:
2221 + fprintf(stderr, "nedit: Error while calling GetFilenameByDialog(): %s\n", gfbdrc->payload);
2222 + *errMsg = "Error while calling GetFilenameByDialog() in %s";
2223 + rc = False;
2224 + break;
2225 + default:
2226 + /* fallback */
2227 + fprintf(stderr, "nedit: Unexpected error in GetFilenameByDialog().\n");
2228 + *errMsg = "Unexpected error in GetFilenameByDialog() in %s";
2229 + rc = False;
2230 + break;
2233 - return True;
2234 + return rc;
2238 * call(fnname, arg, ...)
2240 @@ -4764,10 +4845,31 @@ static int versionMV(WindowInfo* window,
2241 result->val.n = version;
2242 return True;
2246 +** Returns the name of the directory where NEdit's run control files reside.
2247 +** This is either the value of the environmental variable $NEDIT_HOME, the
2248 +** default of ~/.nedit or $HOME. (See the online documentation for details
2249 +** about the algorithm.)
2251 +static int neditHomeMV(WindowInfo* window, DataValue* argList, int nArgs,
2252 + DataValue* result, char** errMsg)
2254 + const char* neditRCName = GetRCFileName(NEDIT_RC);
2255 + char nedit_home[MAXPATHLEN];
2257 + if (0 != ParseFilename(neditRCName, NULL, nedit_home)) {
2258 + M_FAILURE("Unable to parse nedit rc file name in %s");
2261 + result->tag = STRING_TAG;
2262 + AllocNStringCpy(&result->val.str, nedit_home);
2263 + return True;
2267 ** Built-in macro subroutine to create a new rangeset or rangesets.
2268 ** If called with one argument: $1 is the number of rangesets required and
2269 ** return value is an array indexed 0 to n, with the rangeset labels as values;
2270 ** (or an empty array if the requested number of rangesets are not available).
2271 ** If called with no arguments, returns a single rangeset label (not an array),
2272 @@ -5854,10 +5956,56 @@ static int getPatternAtPosMS(WindowInfo
2273 return fillPatternResult(result, errMsg, window,
2274 HighlightNameOfCode(window, patCode), False, True,
2275 HighlightStyleOfCode(window, patCode), bufferPos);
2279 +** Returns a string containing a flag indicating the arguments type:
2280 +** ARRAY - Argument is an array
2281 +** INTEGER - Argument is an integer or a string that can be cleanly
2282 +** transformed into an integer.
2283 +** STRING - Argument is a string that cannot be cleanly transformed
2284 +** into an integer.
2285 +** UNDEFINED - Argument is undefined. No support for void functions though.
2287 +static int typeofMS(WindowInfo* window, DataValue* argList, int nArgs,
2288 + DataValue* result, char** errMsg)
2290 + int buffer;
2292 + /* Validate number of arguments. */
2293 + if (1 != nArgs) {
2294 + return wrongNArgsErr(errMsg);
2297 + /* Prepare result. */
2298 + result->tag = STRING_TAG;
2300 + switch (argList[0].tag) {
2301 + case STRING_TAG:
2302 + if (readIntArg(argList[0], &buffer, errMsg)) {
2303 + AllocNStringCpy(&result->val.str, "INTEGER");
2304 + } else {
2305 + AllocNStringCpy(&result->val.str, "STRING");
2307 + break;
2308 + case INT_TAG:
2309 + AllocNStringCpy(&result->val.str, "INTEGER");
2310 + break;
2311 + case ARRAY_TAG:
2312 + AllocNStringCpy(&result->val.str, "ARRAY");
2313 + break;
2314 + case NO_TAG:
2315 + AllocNStringCpy(&result->val.str, "UNDEFINED");
2316 + break;
2317 + default:
2318 + fprintf(stderr, "nedit: Internal error: Invalid type in typeofMS().\n");
2321 + return True;
2324 static int wrongNArgsErr(char **errMsg)
2326 *errMsg = "Wrong number of arguments to function %s";
2327 return False;
2329 @@ -5901,11 +6049,11 @@ static int strCaseCmp(char *str1, char *
2331 ** Get an integer value from a tagged DataValue structure. Return True
2332 ** if conversion succeeded, and store result in *result, otherwise
2333 ** return False with an error message in *errMsg.
2335 -static int readIntArg(DataValue dv, int *result, char **errMsg)
2336 +static Boolean readIntArg(DataValue dv, int *result, char **errMsg)
2338 char *c;
2340 if (dv.tag == INT_TAG) {
2341 *result = dv.val.n;
2342 @@ -5944,5 +6092,46 @@ static int readStringArg(DataValue dv, c
2343 return True;
2345 *errMsg = "%s called with unknown object";
2346 return False;
2349 +/* rough hack */
2350 +void MacroApplyHook(const WindowInfo* document, const char* hook, int argc,
2351 + DataValue* argv, DataValue* resultDV)
2353 + Symbol* hookSymbol;
2355 + hookSymbol = LookupSymbol(hook);
2356 + if (NULL != hookSymbol && MACRO_FUNCTION_SYM == hookSymbol->type) {
2357 + Program* hookProg = hookSymbol->value.val.prog;
2358 + RestartData* restartData;
2359 + DataValue dummyResultDV; /* Passed to ExecuteMacro() if no result requested */
2360 + int status;
2361 + char* errMsg;
2362 +// char statusT[1024];
2364 + /* Let 'er rip */
2365 + status = ExecuteMacro((WindowInfo*) document, hookProg, argc, argv,
2366 + (NULL == resultDV) ? &dummyResultDV : resultDV, &restartData,
2367 + &errMsg);
2368 +// switch (status)
2369 +// {
2370 +// case 0: strncpy(statusT, "MACRO_TIME_LIMIT", 1024); break;
2371 +// case 1: strncpy(statusT, "MACRO_PREEMPT", 1024); break;
2372 +// case 2: strncpy(statusT, "MACRO_DONE", 1024); break;
2373 +// case 3: strncpy(statusT, "MACRO_ERROR", 1024); break;
2374 +// default: strncpy(statusT, "UNKNOWN_ERROR", 1024);
2375 +// }
2376 +// fprintf(stderr, "\tstatus: %s\n", statusT);
2377 + while (MACRO_TIME_LIMIT == status) {
2378 + status = ContinueMacro(restartData,
2379 + (NULL == resultDV) ? &dummyResultDV : resultDV, &errMsg);
2382 + if (MACRO_PREEMPT == status || MACRO_ERROR == status) {
2383 + fprintf(stderr, "nedit: \"%s\" error: %s\n", hook, (MACRO_ERROR == status) ? errMsg : "No dialogs");
2384 + } else {
2385 + /* Macro is done here */
2389 diff --quilt old/source/macro.h new/source/macro.h
2390 --- old/source/macro.h
2391 +++ new/source/macro.h
2392 @@ -71,7 +71,10 @@ int ReadMacroString(WindowInfo *window,
2393 int CheckMacroString(Widget dialogParent, char *string, const char *errIn,
2394 char **errPos);
2395 char *GetReplayMacro(void);
2396 void ReadMacroInitFile(WindowInfo *window);
2397 void ReturnShellCommandOutput(WindowInfo *window, const char *outText, int status);
2398 +struct DataValueTag;
2399 +void MacroApplyHook(const WindowInfo* document, const char *hook, int argc,
2400 + struct DataValueTag* argv, struct DataValueTag* resultDV);
2402 #endif /* NEDIT_MACRO_H_INCLUDED */
2403 diff --quilt old/source/menu.c new/source/menu.c
2404 --- old/source/menu.c
2405 +++ new/source/menu.c
2406 @@ -50,10 +50,11 @@ static const char CVSID[] = "$Id: menu.c
2407 #include "highlight.h"
2408 #include "highlightData.h"
2409 #include "interpret.h"
2410 #include "smartIndent.h"
2411 #include "windowTitle.h"
2412 +#include "regularExp.h"
2413 #include "../util/getfiles.h"
2414 #include "../util/DialogF.h"
2415 #include "../util/misc.h"
2416 #include "../util/fileUtils.h"
2417 #include "../util/utils.h"
2418 @@ -177,10 +178,13 @@ static void bgMenuDefCB(Widget w, Window
2419 static void searchDlogsDefCB(Widget w, WindowInfo *window, caddr_t callData);
2420 static void beepOnSearchWrapDefCB(Widget w, WindowInfo *window, caddr_t callData);
2421 static void keepSearchDlogsDefCB(Widget w, WindowInfo *window,
2422 caddr_t callData);
2423 static void searchWrapsDefCB(Widget w, WindowInfo *window, caddr_t callData);
2424 +static void showHiddenFilesCB(Widget w, WindowInfo* window, caddr_t callData);
2425 +static void showCursorlineCB(Widget widget, WindowInfo* window,
2426 + caddr_t callData);
2427 static void appendLFCB(Widget w, WindowInfo* window, caddr_t callData);
2428 static void sortOpenPrevDefCB(Widget w, WindowInfo *window, caddr_t callData);
2429 static void reposDlogsDefCB(Widget w, WindowInfo *window, caddr_t callData);
2430 static void autoScrollDefCB(Widget w, WindowInfo *window, caddr_t callData);
2431 static void modWarnDefCB(Widget w, WindowInfo *window, caddr_t callData);
2432 @@ -189,10 +193,12 @@ static void exitWarnDefCB(Widget w, Wind
2433 static void searchLiteralCB(Widget w, WindowInfo *window, caddr_t callData);
2434 static void searchCaseSenseCB(Widget w, WindowInfo *window, caddr_t callData);
2435 static void searchLiteralWordCB(Widget w, WindowInfo *window, caddr_t callData);
2436 static void searchCaseSenseWordCB(Widget w, WindowInfo *window, caddr_t callData);
2437 static void searchRegexNoCaseCB(Widget w, WindowInfo *window, caddr_t callData);
2438 +static void searchRegexSmartCaseCB(Widget toggleButton, WindowInfo* windowInfo,
2439 + caddr_t callData);
2440 static void searchRegexCB(Widget w, WindowInfo *window, caddr_t callData);
2441 #ifdef REPLACE_SCOPE
2442 static void replaceScopeWindowCB(Widget w, WindowInfo *window, caddr_t callData);
2443 static void replaceScopeSelectionCB(Widget w, WindowInfo *window, caddr_t callData);
2444 static void replaceScopeSmartCB(Widget w, WindowInfo *window, caddr_t callData);
2445 @@ -392,10 +398,12 @@ static void setAutoIndentAP(Widget w, XE
2446 Cardinal *nArgs);
2447 static void setWrapTextAP(Widget w, XEvent *event, String *args,
2448 Cardinal *nArgs);
2449 static void setWrapMarginAP(Widget w, XEvent *event, String *args,
2450 Cardinal *nArgs);
2451 +static void setShowWrapMarginAP(Widget w, XEvent *event, String *args,
2452 + Cardinal *nArgs);
2453 static void setHighlightSyntaxAP(Widget w, XEvent *event, String *args,
2454 Cardinal *nArgs);
2455 static void setMakeBackupCopyAP(Widget w, XEvent *event, String *args,
2456 Cardinal *nArgs);
2457 static void setIncrementalBackupAP(Widget w, XEvent *event, String *args,
2458 @@ -406,10 +414,12 @@ static void setMatchSyntaxBasedAP(Widget
2459 Cardinal *nArgs);
2460 static void setOvertypeModeAP(Widget w, XEvent *event, String *args,
2461 Cardinal *nArgs);
2462 static void setLockedAP(Widget w, XEvent *event, String *args,
2463 Cardinal *nArgs);
2464 +static void setTransientAP(Widget text, XEvent* event, String* args,
2465 + Cardinal* nArgs);
2466 static void setUseTabsAP(Widget w, XEvent *event, String *args,
2467 Cardinal *nArgs);
2468 static void setEmTabDistAP(Widget w, XEvent *event, String *args,
2469 Cardinal *nArgs);
2470 static void setTabDistAP(Widget w, XEvent *event, String *args,
2471 @@ -566,19 +576,21 @@ static XtActionsRec Actions[] = {
2472 {"set_incremental_search_line", setIncrementalSearchLineAP},
2473 {"set_show_line_numbers", setShowLineNumbersAP},
2474 {"set_auto_indent", setAutoIndentAP},
2475 {"set_wrap_text", setWrapTextAP},
2476 {"set_wrap_margin", setWrapMarginAP},
2477 + {"set_show_wrap_margin", setShowWrapMarginAP},
2478 {"set_highlight_syntax", setHighlightSyntaxAP},
2479 #ifndef VMS
2480 {"set_make_backup_copy", setMakeBackupCopyAP},
2481 #endif
2482 {"set_incremental_backup", setIncrementalBackupAP},
2483 {"set_show_matching", setShowMatchingAP},
2484 {"set_match_syntax_based", setMatchSyntaxBasedAP},
2485 {"set_overtype_mode", setOvertypeModeAP},
2486 {"set_locked", setLockedAP},
2487 + {"set_transient", setTransientAP},
2488 {"set_tab_dist", setTabDistAP},
2489 {"set_em_tab_dist", setEmTabDistAP},
2490 {"set_use_tabs", setUseTabsAP},
2491 {"set_fonts", setFontsAP},
2492 {"set_language_mode", setLanguageModeAP}
2493 @@ -813,10 +825,13 @@ Widget CreateMenuBar(Widget parent, Wind
2494 XtSetSensitive(window->showTipItem, (TagsFileList != NULL ||
2495 TipsFileList != NULL) );
2498 ** Preferences menu, Default Settings sub menu
2499 + **
2500 + ** Mnemonics: L, A, W, C, T, F, u, d, g, H, S, i, N, e, B, M, o, P, r, z
2501 + ** A, B, C, d, e, F, g, H, i, L, M, N, o, P, r, S, T, u, W, z
2503 menuPane = createMenu(menuBar, "preferencesMenu", "Preferences", 0, NULL,
2504 SHORT);
2505 subPane = createMenu(menuPane, "defaultSettings", "Default Settings", 'D',
2506 NULL, FULL);
2507 @@ -926,12 +941,17 @@ Widget CreateMenuBar(Widget parent, Wind
2508 GetPrefSearch() == SEARCH_CASE_SENSE_WORD, FULL);
2509 window->searchRegexDefItem = createMenuToggle(subSubSubPane,
2510 "regularExpression", "Regular Expression", 'R', searchRegexCB,
2511 window, GetPrefSearch() == SEARCH_REGEX, FULL);
2512 window->searchRegexNoCaseDefItem = createMenuToggle(subSubSubPane,
2513 - "regularExpressionNoCase", "Regular Expression, Case Insensitive", 'I', searchRegexNoCaseCB, window,
2514 - GetPrefSearch() == SEARCH_REGEX_NOCASE, FULL);
2515 + "regularExpressionNoCase", "Regular Expression, Case Insensitive",
2516 + 'I', searchRegexNoCaseCB, window,
2517 + GetPrefSearch() == SEARCH_REGEX_NOCASE, FULL);
2518 + window->searchRegexSmartCaseDefItem = createMenuToggle(subSubSubPane,
2519 + "regularExpressionSmartCase", "Regular Expression, Smart Case",
2520 + 'S', searchRegexSmartCaseCB, window,
2521 + GetPrefSearch() == SEARCH_REGEX_SMARTCASE, FULL);
2522 #ifdef REPLACE_SCOPE
2523 subSubSubPane = createMenu(subSubPane, "defaultReplaceScope",
2524 "Default Replace Scope", 'R', NULL, FULL);
2525 XtVaSetValues(subSubSubPane, XmNradioBehavior, True, NULL);
2526 window->replScopeWinDefItem = createMenuToggle(subSubSubPane, "window",
2527 @@ -1015,10 +1035,20 @@ Widget CreateMenuBar(Widget parent, Wind
2528 createMenuSeparator(subSubPane, "sep", SHORT);
2529 window->matchSyntaxBasedDefItem = createMenuToggle(subSubPane,
2530 "matchSyntax", "Syntax Based", 'S', matchSyntaxBasedDefCB, window,
2531 GetPrefMatchSyntaxBased(), SHORT);
2533 + /* Show Hidden Files */
2534 + window->showHiddenFilesItem = createMenuToggle(subPane,
2535 + "showHiddenFilesItem", "Show hidden Files", 'y', showHiddenFilesCB,
2536 + NULL, GetPrefShowHiddenFiles(), FULL);
2538 + /* Show Cursorline */
2539 + window->showCursorlineItem = createMenuToggle(subPane,
2540 + "showCursorlineItem", "Show Cursorline", 'x', showCursorlineCB,
2541 + NULL, GetPrefShowCursorline(), FULL);
2543 /* Append LF at end of files on save */
2544 window->appendLFItem = createMenuToggle(subPane, "appendLFItem",
2545 "Terminate with Line Break on Save", 'v', appendLFCB, NULL,
2546 GetPrefAppendLF(), FULL);
2548 @@ -1141,10 +1171,12 @@ Widget CreateMenuBar(Widget parent, Wind
2549 createMenuSeparator(menuPane, "sep2", SHORT);
2550 window->overtypeModeItem = createMenuToggle(menuPane, "overtype", "Overtype", 'O',
2551 doActionCB, "set_overtype_mode", False, SHORT);
2552 window->readOnlyItem = createMenuToggle(menuPane, "readOnly", "Read Only",
2553 'y', doActionCB, "set_locked", IS_USER_LOCKED(window->lockReasons), FULL);
2554 + window->transientItem = createMenuToggle(menuPane, "transient", "Transient",
2555 + 'r', doActionCB, "set_transient", window->transient, FULL);
2556 #endif
2558 #ifndef VMS
2560 ** Create the Shell menu
2561 @@ -1999,16 +2031,17 @@ static void showMatchingRangeDefCB(Widge
2563 WindowInfo *win;
2565 /* Set the preference and make the other windows' menus agree */
2566 SetPrefShowMatching(FLASH_RANGE);
2567 - for (win=WindowList; win!=NULL; win=win->next) {
2568 - if (!IsTopDocument(win))
2569 - continue;
2570 - XmToggleButtonSetState(win->showMatchingOffDefItem, False, False);
2571 - XmToggleButtonSetState(win->showMatchingDelimitDefItem, False, False);
2572 - XmToggleButtonSetState(win->showMatchingRangeDefItem, True, False);
2573 + for (win = WindowList; win != NULL; win = win->next) {
2574 + if (!IsTopDocument(win)) {
2575 + continue;
2577 + XmToggleButtonSetState(win->showMatchingOffDefItem, False, False);
2578 + XmToggleButtonSetState(win->showMatchingDelimitDefItem, False, False);
2579 + XmToggleButtonSetState(win->showMatchingRangeDefItem, True, False);
2583 static void matchSyntaxBasedDefCB(Widget w, WindowInfo *window, caddr_t callData)
2585 @@ -2175,10 +2208,41 @@ static void searchWrapsDefCB(Widget w, W
2586 if (IsTopDocument(win))
2587 XmToggleButtonSetState(win->searchWrapsDefItem, state, False);
2591 +static void showHiddenFilesCB(Widget widget, WindowInfo* unused,
2592 + caddr_t callData)
2594 + WindowInfo *window;
2595 + Boolean state = XmToggleButtonGetState(widget);
2597 + SetPrefShowHiddenFiles(state);
2598 + for (window = WindowList; window != NULL; window = window->next) {
2599 + XmToggleButtonSetState(window->showHiddenFilesItem, state, False);
2603 +static void showCursorlineCB(Widget widget, WindowInfo* unused,
2604 + caddr_t callData)
2606 + WindowInfo* window;
2607 + Boolean state = XmToggleButtonGetState(widget);
2609 + SetPrefShowCursorline(state);
2610 + for (window = WindowList; window != NULL; window = window->next) {
2611 + XmToggleButtonSetState(window->showCursorlineItem, state, False);
2613 + if (IsTopDocument(window)) {
2614 + Widget pane = (NULL == window->lastFocus
2615 + ? window->textArea
2616 + : window->lastFocus);
2617 + XtVaSetValues(pane, textNshowCursorline, state, NULL);
2622 static void appendLFCB(Widget w, WindowInfo* window, caddr_t callData)
2624 WindowInfo *win;
2625 int state = XmToggleButtonGetState(w);
2627 @@ -2537,10 +2601,39 @@ static void searchRegexNoCaseCB(Widget w
2628 XmToggleButtonSetState(win->searchRegexNoCaseDefItem, True, False);
2633 +static void searchRegexSmartCaseCB(Widget toggleButton, WindowInfo* window,
2634 + caddr_t callData)
2636 + WindowInfo* windowInfo;
2638 + /* Set the preference and make the other windows' menus agree */
2639 + if (XmToggleButtonGetState(toggleButton)) {
2640 + SetPrefSearch(SEARCH_REGEX_SMARTCASE);
2641 + for (windowInfo = WindowList;
2642 + windowInfo != NULL;
2643 + windowInfo = windowInfo->next) {
2644 + XmToggleButtonSetState(windowInfo->searchLiteralDefItem,
2645 + False, False);
2646 + XmToggleButtonSetState(windowInfo->searchCaseSenseDefItem,
2647 + False, False);
2648 + XmToggleButtonSetState(windowInfo->searchLiteralWordDefItem,
2649 + False, False);
2650 + XmToggleButtonSetState(windowInfo->searchCaseSenseWordDefItem,
2651 + False, False);
2652 + XmToggleButtonSetState(windowInfo->searchRegexDefItem,
2653 + False, False);
2654 + XmToggleButtonSetState(windowInfo->searchRegexNoCaseDefItem,
2655 + False, False);
2656 + XmToggleButtonSetState(windowInfo->searchRegexSmartCaseDefItem,
2657 + True, False);
2662 #ifdef REPLACE_SCOPE
2663 static void replaceScopeWindowCB(Widget w, WindowInfo *window, caddr_t callData)
2665 WindowInfo *win;
2667 @@ -2714,51 +2807,59 @@ static void unloadTipsFileMenuCB(Widget
2669 static void newAP(Widget w, XEvent *event, String *args, Cardinal *nArgs)
2671 WindowInfo *window = WidgetToWindow(w);
2672 int openInTab = GetPrefOpenInTab();
2673 + Boolean transient = False;
2675 + /* Look for arguments managing the type of window requested and whether
2676 + or not the user wants to have a transient window. */
2677 if (*nArgs > 0) {
2678 - if (strcmp(args[0], "prefs") == 0) {
2679 + if (0 == strcmp(args[0], "prefs")) {
2680 /* accept default */;
2682 - else if (strcmp(args[0], "tab") == 0) {
2683 + } else if (0 == strcmp(args[0], "tab")) {
2684 openInTab = 1;
2686 - else if (strcmp(args[0], "window") == 0) {
2687 + } else if (0 == strcmp(args[0], "window")) {
2688 openInTab = 0;
2690 - else if (strcmp(args[0], "opposite") == 0) {
2691 + } else if (0 == strcmp(args[0], "opposite")) {
2692 openInTab = !openInTab;
2694 - else {
2695 + } else if (0 == strcmp(args[0], "transient")) {
2696 + transient = True;
2697 + } else {
2698 fprintf(stderr, "nedit: Unknown argument to action procedure \"new\": %s\n", args[0]);
2702 - EditNewFile(openInTab? window : NULL, NULL, False, NULL, window->path);
2704 + /* Catch transient if it comes after a window type argument */
2705 + if (2 == *nArgs && (0 == strcmp(args[1], "transient"))) {
2706 + transient = True;
2709 + EditNewFile(openInTab? window : NULL, NULL, False, NULL, window->path,
2710 + transient);
2711 CheckCloseDim();
2715 -** These are just here because our techniques make it hard to bind a menu item
2716 -** to an action procedure that takes arguments. The user doesn't need to know
2717 -** about them -- they can use new( "opposite" ) or new( "tab" ).
2718 +** newOppositeAP() and newTabAP() are just here because our techniques make
2719 +** it hard to bind a menu item to an action procedure that takes arguments.
2720 +** The user doesn't need to know about them -- they can use new("opposite")
2721 +** or new("tab").
2723 static void newOppositeAP(Widget w, XEvent *event, String *args, Cardinal *nArgs)
2725 WindowInfo *window = WidgetToWindow(w);
2727 EditNewFile(GetPrefOpenInTab()? NULL : window, NULL, False, NULL,
2728 - window->path);
2729 + window->path, False);
2730 CheckCloseDim();
2732 static void newTabAP(Widget w, XEvent *event, String *args, Cardinal *nArgs)
2734 WindowInfo *window = WidgetToWindow(w);
2736 - EditNewFile(window, NULL, False, NULL, window->path);
2737 + EditNewFile(window, NULL, False, NULL, window->path, False);
2738 CheckCloseDim();
2741 static void openDialogAP(Widget w, XEvent *event, String *args, Cardinal *nArgs)
2743 @@ -2781,21 +2882,31 @@ static void openDialogAP(Widget w, XEven
2745 static void openAP(Widget w, XEvent *event, String *args, Cardinal *nArgs)
2747 WindowInfo *window = WidgetToWindow(w);
2748 char filename[MAXPATHLEN], pathname[MAXPATHLEN];
2749 + DataValue* fileNameArg = (DataValue*) XtMalloc(sizeof(DataValue));
2750 + DataValue* resultDV = (DataValue*) XtMalloc(sizeof(DataValue));
2752 if (*nArgs == 0) {
2753 fprintf(stderr, "nedit: open action requires file argument\n");
2754 return;
2756 - if (0 != ParseFilename(args[0], filename, pathname)
2758 + fileNameArg->tag = STRING_TAG;
2759 + AllocNStringNCpy(&fileNameArg->val.str, args[0], MAXPATHLEN);
2760 + MacroApplyHook(window, "file_name_hook", 1, fileNameArg, resultDV);
2761 + XtFree((char*) fileNameArg);
2763 + if (0 != ParseFilename(resultDV->val.str.rep, filename, pathname)
2764 || strlen(filename) + strlen(pathname) > MAXPATHLEN - 1) {
2765 fprintf(stderr, "nedit: invalid file name for open action: %s\n",
2766 args[0]);
2767 return;
2769 + XtFree((char*) resultDV);
2771 EditExistingFile(window, filename, pathname, 0, NULL, False,
2772 NULL, GetPrefOpenInTab(), False);
2773 CheckCloseDim();
2776 @@ -3942,11 +4053,11 @@ static void focusPaneAP(Widget w, XEvent
2778 if (paneIndex >= 0 && paneIndex <= window->nPanes) {
2779 newFocusPane = GetPaneByIndex(window, paneIndex);
2781 if (newFocusPane != NULL) {
2782 - window->lastFocus = newFocusPane;
2783 + ChangeLastFocus(window, newFocusPane);
2784 XmProcessTraversal(window->lastFocus, XmTRAVERSE_CURRENT);
2786 else {
2787 XBell(TheDisplay, 0);
2789 @@ -4085,10 +4196,23 @@ static void setWrapMarginAP(Widget w, XE
2790 else {
2791 fprintf(stderr, "nedit: set_wrap_margin requires argument\n");
2795 +static void setShowWrapMarginAP(Widget w, XEvent *event, String *args,
2796 + Cardinal *nArgs)
2798 + WindowInfo *window = WidgetToWindow(w);
2799 + int showWrapMargin = 0;
2801 + if (*nArgs > 0) {
2802 + if (sscanf(args[0], "%d", &showWrapMargin) == 1) {
2803 + SetShowWrapMargin(window, showWrapMargin);
2808 static void setHighlightSyntaxAP(Widget w, XEvent *event, String *args,
2809 Cardinal *nArgs)
2811 WindowInfo *window = WidgetToWindow(w);
2812 Boolean newState;
2813 @@ -4209,10 +4333,28 @@ static void setLockedAP(Widget w, XEvent
2814 XmToggleButtonSetState(window->readOnlyItem, IS_ANY_LOCKED(window->lockReasons), False);
2815 UpdateWindowTitle(window);
2816 UpdateWindowReadOnly(window);
2820 +** Action procedure for setting or toggling the transient flag.
2822 +static void setTransientAP(Widget text, XEvent* event, String* args,
2823 + Cardinal* nArgs)
2825 + WindowInfo* window = WidgetToWindow(text);
2826 + Boolean newState;
2828 + ACTION_BOOL_PARAM_OR_TOGGLE(newState, *nArgs, args,
2829 + window->transient, "set_transient");
2831 + window->transient = newState;
2832 + if (IsTopDocument(window)) {
2833 + XmToggleButtonSetState(window->transientItem, window->transient, False);
2837 static void setTabDistAP(Widget w, XEvent *event, String *args,
2838 Cardinal *nArgs)
2840 WindowInfo *window = WidgetToWindow(w);
2842 @@ -4511,17 +4653,40 @@ static void invalidatePrevOpenMenus(void
2844 void AddToPrevOpenMenu(const char *filename)
2846 int i;
2847 char *nameCopy;
2848 + char *fileMask, *compileMsg;
2849 + regexp *compiledRE;
2850 WindowInfo *w;
2852 /* If the Open Previous command is disabled, just return */
2853 if (GetPrefMaxPrevOpenFiles() < 1) {
2854 return;
2857 + /* If the name is to be omitted, return */
2858 + if ((fileMask = GetPrevOpenFilesMask()) && *fileMask)
2860 + compiledRE = CompileRE(fileMask, &compileMsg, REDFLT_STANDARD);
2861 + if (compiledRE == NULL)
2863 + fprintf(stderr, "nedit: %s\n", compileMsg);
2864 + } else
2866 + if (ExecRE(compiledRE, filename, NULL, FALSE, '\0', '\0', NULL,
2867 + NULL, NULL))
2869 + free((char *)compiledRE);
2870 + return;
2871 + } else
2873 + free((char *)compiledRE);
2878 /* Refresh list of previously opened files to avoid Big Race Condition,
2879 where two sessions overwrite each other's changes in NEdit's
2880 history file.
2881 Of course there is still Little Race Condition, which occurs if a
2882 Session A reads the list, then Session B reads the list and writes
2883 @@ -4864,10 +5029,12 @@ static int cmpStrPtr(const void *strA, c
2884 void WriteNEditDB(void)
2886 const char* fullName = GetRCFileName(NEDIT_HISTORY);
2887 FILE *fp;
2888 int i;
2889 + char *fileMask, *compileMsg;
2890 + regexp *compiledRE=NULL;
2891 static char fileHeader[] =
2892 "# File name database for NEdit Open Previous command\n";
2894 if (fullName == NULL) {
2895 /* GetRCFileName() might return NULL if an error occurs during
2896 @@ -4900,23 +5067,48 @@ void WriteNEditDB(void)
2897 #else
2898 return;
2899 #endif
2902 + /* set up removal of any files matching prevOpenFilesMask */
2903 + if ((fileMask = GetPrevOpenFilesMask()) && *fileMask)
2905 + compiledRE = CompileRE(fileMask, &compileMsg, REDFLT_STANDARD);
2906 + if (compiledRE == NULL)
2908 + fprintf(stderr, "%s\n", compileMsg);
2912 /* write the file header text to the file */
2913 fprintf(fp, "%s", fileHeader);
2915 /* Write the list of file names */
2916 - for (i = 0; i < NPrevOpen; ++i) {
2917 - size_t lineLen = strlen(PrevOpen[i]);
2918 + for (i = 0; i < NPrevOpen; i++)
2920 + /* omitting any files matching prevOpenFilesMask */
2921 + if (NULL == compiledRE
2922 + || 0 == ExecRE(compiledRE, PrevOpen[i], NULL, FALSE, '\0', '\0',
2923 + NULL, NULL, NULL))
2925 + size_t lineLen = strlen(PrevOpen[i]);
2927 - if (lineLen > 0 && PrevOpen[i][0] != '#' &&
2928 - strcspn(PrevOpen[i], neditDBBadFilenameChars) == lineLen) {
2929 - fprintf(fp, "%s\n", PrevOpen[i]);
2930 + /* omitting any files with invalid filenames */
2931 + if (lineLen > 0 && '#' != PrevOpen[i][0]
2932 + && strcspn(PrevOpen[i], neditDBBadFilenameChars) == lineLen)
2934 + fprintf(fp, "%s\n", PrevOpen[i]);
2940 + if (compiledRE != NULL) {
2941 + free((char *)compiledRE);
2944 + /* Close the file */
2945 fclose(fp);
2949 ** Read database of file names for 'Open Previous' submenu.
2950 diff --quilt old/source/nedit.c new/source/nedit.c
2951 --- old/source/nedit.c
2952 +++ new/source/nedit.c
2953 @@ -352,15 +352,21 @@ static char *fallbackResources[] = {
2954 "*windowsMenu.splitPane.acceleratorText: Ctrl+2",
2955 "*windowsMenu.closePane.accelerator: Ctrl<Key>1",
2956 "*windowsMenu.closePane.acceleratorText: Ctrl+1",
2957 "*helpMenu.mnemonic: H",
2958 "nedit.help.helpForm.sw.helpText*baseTranslations: #override\
2959 -<Key>Tab:help-focus-buttons()\\n\
2960 +<Key>space: scroll_down(1, \"pages\")\\n\
2961 +~Alt~Shift~Ctrl~Meta<KeyPress>osfUp: scroll_up(1)\\n\
2962 +~Alt~Shift~Ctrl~Meta<KeyPress>osfDown: scroll_down(1)\\n\
2963 +~Alt ~Shift ~Ctrl ~Meta<KeyPress>osfPageUp: scroll_up(1, \"pages\")\\n\
2964 +~Alt ~Shift ~Ctrl ~Meta<KeyPress>osfPageDown: scroll_down(1, \"pages\")\\n\
2965 +~Alt~Shift~Ctrl~Meta<KeyPress>osfLeft: help-button-action(\"prevTopic\")\\n\
2966 +~Alt~Shift~Ctrl~Meta<KeyPress>osfRight: help-button-action(\"nextTopic\")\\n\
2967 <Key>Return:help-button-action(\"close\")\\n\
2968 -Ctrl<Key>F:help-button-action(\"find\")\\n\
2969 -Ctrl<Key>G:help-button-action(\"findAgain\")\\n\
2970 <KeyPress>osfCancel:help-button-action(\"close\")\\n\
2971 +Ctrl<Key>f:help-button-action(\"find\")\\n\
2972 +Ctrl<Key>g:help-button-action(\"findAgain\")\\n\
2973 ~Meta~Ctrl~Shift<Btn1Down>:\
2974 grab-focus() help-hyperlink()\\n\
2975 ~Meta~Ctrl~Shift<Btn1Up>:\
2976 help-hyperlink(\"current\", \"process-cancel\", \"extend-end\")\\n\
2977 ~Meta~Ctrl~Shift<Btn2Down>:\
2978 @@ -489,11 +495,11 @@ int main(int argc, char **argv)
2980 /* Initialize global symbols and subroutines used in the macro language */
2981 InitMacroGlobals();
2982 RegisterMacroSubroutines();
2984 - /* Store preferences from the command line and .nedit file,
2985 + /* Store preferences from the command line and the nedit.rc file,
2986 and set the appropriate preferences */
2987 RestoreNEditPrefs(prefDB, XtDatabase(TheDisplay));
2989 /* Intercept syntactically invalid virtual key bindings BEFORE we
2990 create any shells. */
2991 @@ -775,11 +781,11 @@ int main(int argc, char **argv)
2993 CheckCloseDim();
2995 /* If no file to edit was specified, open a window to edit "Untitled" */
2996 if (!fileSpecified) {
2997 - EditNewFile(NULL, geometry, iconic, langMode, NULL);
2998 + EditNewFile(NULL, geometry, iconic, langMode, NULL, False);
2999 ReadMacroInitFile(WindowList);
3000 CheckCloseDim();
3001 if (toDoCommand != NULL)
3002 DoMacro(WindowList, toDoCommand, "-do macro");
3004 diff --quilt old/source/nedit.h new/source/nedit.h
3005 --- old/source/nedit.h
3006 +++ new/source/nedit.h
3007 @@ -52,13 +52,14 @@
3008 #define NEDIT_DEFAULT_SEL_BG "rgb:cc/cc/cc"
3009 #define NEDIT_DEFAULT_HI_FG "white" /* These are colors for flashing */
3010 #define NEDIT_DEFAULT_HI_BG "red" /* matching parens. */
3011 #define NEDIT_DEFAULT_LINENO_FG "black"
3012 #define NEDIT_DEFAULT_CURSOR_FG "black"
3013 +#define NEDIT_DEFAULT_WRAPMARGIN_FG "black"
3014 #define NEDIT_DEFAULT_HELP_FG "black"
3015 #define NEDIT_DEFAULT_HELP_BG "rgb:cc/cc/cc"
3017 +#define NEDIT_DEFAULT_CURSORLINE_BG "LightSteelBlue2"
3019 /* Tuning parameters */
3020 #define SEARCHMAX 5119 /* Maximum length of search/replace strings */
3021 #define MAX_SEARCH_HISTORY 100 /* Maximum length of search string history */
3022 #define MAX_PANES 6 /* Max # of ADDITIONAL text editing panes
3023 @@ -103,10 +104,12 @@
3024 enum indentStyle {NO_AUTO_INDENT, AUTO_INDENT, SMART_INDENT};
3025 enum wrapStyle {NO_WRAP, NEWLINE_WRAP, CONTINUOUS_WRAP};
3026 enum showMatchingStyle {NO_FLASH, FLASH_DELIMIT, FLASH_RANGE};
3027 enum virtKeyOverride { VIRT_KEY_OVERRIDE_NEVER, VIRT_KEY_OVERRIDE_AUTO,
3028 VIRT_KEY_OVERRIDE_ALWAYS };
3029 +enum showWrapMarginEnums {SHOW_WRAP_MARGIN_NEVER, SHOW_WRAP_MARGIN_ALWAYS,
3030 + SHOW_WRAP_MARGIN_ON_WRAP};
3032 /* This enum must be kept in parallel to the array TruncSubstitutionModes[]
3033 in preferences.c */
3034 enum truncSubstitution {TRUNCSUBST_SILENT, TRUNCSUBST_FAIL, TRUNCSUBST_WARN, TRUNCSUBST_IGNORE};
3036 @@ -191,10 +194,12 @@ enum colorTypes {
3037 SELECT_BG_COLOR,
3038 HILITE_FG_COLOR,
3039 HILITE_BG_COLOR,
3040 LINENO_FG_COLOR,
3041 CURSOR_FG_COLOR,
3042 + WRAPMARGIN_FG_COLOR,
3043 + CURSORLINE_BG_COLOR,
3044 NUM_COLORS
3047 /* cache user menus: manage mode of user menu list element */
3048 typedef enum {
3049 @@ -325,10 +330,11 @@ typedef struct _WindowInfo {
3050 Widget replaceMultiFileList;
3051 Widget replaceMultiFilePathBtn;
3052 Widget fontDialog; /* NULL, unless font dialog is up */
3053 Widget colorDialog; /* NULL, unless color dialog is up */
3054 Widget readOnlyItem; /* menu bar settable widgets... */
3055 + Widget transientItem;
3056 Widget autoSaveItem;
3057 Widget saveLastItem;
3058 Widget openSelItem;
3059 Widget newOppositeItem;
3060 Widget closeItem;
3061 @@ -393,10 +399,12 @@ typedef struct _WindowInfo {
3062 Widget backlightCharsDefItem;
3063 Widget searchDlogsDefItem;
3064 Widget beepOnSearchWrapDefItem;
3065 Widget keepSearchDlogsDefItem;
3066 Widget searchWrapsDefItem;
3067 + Widget showHiddenFilesItem;
3068 + Widget showCursorlineItem;
3069 Widget appendLFItem;
3070 Widget sortOpenPrevDefItem;
3071 Widget allTagsDefItem;
3072 Widget smartTagsDefItem;
3073 Widget reposDlogsDefItem;
3074 @@ -417,10 +425,11 @@ typedef struct _WindowInfo {
3075 Widget searchLiteralDefItem;
3076 Widget searchCaseSenseDefItem;
3077 Widget searchLiteralWordDefItem;
3078 Widget searchCaseSenseWordDefItem;
3079 Widget searchRegexNoCaseDefItem;
3080 + Widget searchRegexSmartCaseDefItem;
3081 Widget searchRegexDefItem;
3082 #ifdef REPLACE_SCOPE
3083 Widget replScopeWinDefItem;
3084 Widget replScopeSelDefItem;
3085 Widget replScopeSmartDefItem;
3086 @@ -495,10 +504,12 @@ typedef struct _WindowInfo {
3087 Boolean autoSave; /* is autosave turned on? */
3088 Boolean saveOldVersion; /* keep old version in filename.bck */
3089 char indentStyle; /* whether/how to auto indent */
3090 char wrapMode; /* line wrap style: NO_WRAP,
3091 NEWLINE_WRAP or CONTINUOUS_WRAP */
3092 + int showWrapMargin; /* show wrap margin style: NEVER,
3093 + ALWAYS, ON-WRAP as enums */
3094 Boolean overstrike; /* is overstrike mode turned on ? */
3095 char showMatchingStyle; /* How to show matching parens:
3096 NO_FLASH, FLASH_DELIMIT, or
3097 FLASH_RANGE */
3098 char matchSyntaxBased; /* Use syntax info to show matching */
3099 @@ -555,10 +566,11 @@ typedef struct _WindowInfo {
3100 #endif
3101 UserMenuCache *userMenuCache; /* cache user menus: */
3102 UserBGMenuCache userBGMenuCache; /* shell & macro menu are shared over all
3103 "tabbed" documents, while each document
3104 has its own background menu. */
3105 + Boolean transient;
3106 } WindowInfo;
3108 extern WindowInfo *WindowList;
3109 extern Display *TheDisplay;
3110 extern Widget TheAppShell;
3111 diff --quilt old/source/preferences.c new/source/preferences.c
3112 --- old/source/preferences.c
3113 +++ new/source/preferences.c
3114 @@ -115,13 +115,13 @@ enum fontStatus {GOOD_FONT, BAD_PRIMARY,
3115 ** The order of the elements in this array must be exactly the same
3116 ** as the order of the corresponding integers of the enum SearchType
3117 ** defined in search.h (!!)
3119 static char *SearchMethodStrings[] = {
3120 - "Literal", "CaseSense", "RegExp",
3121 - "LiteralWord", "CaseSenseWord", "RegExpNoCase",
3122 - NULL
3123 + "Literal", "CaseSense", "RegExp",
3124 + "LiteralWord", "CaseSenseWord", "RegExpNoCase", "RegExSmartCase",
3125 + NULL
3128 #ifdef REPLACE_SCOPE
3129 /* enumerated default scope for replace dialog if a selection exists when
3130 ** the dialog is popped up.
3131 @@ -138,10 +138,13 @@ static char *AutoWrapTypes[N_WRAP_STYLES
3132 static char *AutoIndentTypes[N_INDENT_STYLES+3] = {"None", "Auto",
3133 "Smart", "True", "False", NULL};
3134 #define N_VIRTKEY_OVERRIDE_MODES 3
3135 static char *VirtKeyOverrideModes[N_VIRTKEY_OVERRIDE_MODES+1] = { "Never",
3136 "Auto", "Always", NULL};
3137 +#define N_SHOW_WRAP_MARGIN_STYLES 3
3138 +static char *ShowWrapMarginStrings[N_SHOW_WRAP_MARGIN_STYLES+1] = { "Never",
3139 + "Always", "When Wrap is Enabled", NULL};
3141 #define N_SHOW_MATCHING_STYLES 3
3142 /* For backward compatibility, "False" and "True" are still accepted.
3143 They are internally converted to "Off" and "Delimiter" respectively.
3144 NOTE: N_SHOW_MATCHING_STYLES must correspond to the number of
3145 @@ -233,18 +236,23 @@ typedef struct {
3146 Widget hiliteBgErrW;
3147 Widget lineNoFgW;
3148 Widget lineNoFgErrW;
3149 Widget cursorFgW;
3150 Widget cursorFgErrW;
3151 + Widget wrapMarginFgW;
3152 + Widget wrapMarginFgErrW;
3153 + Widget cursorlineBgW;
3154 + Widget cursorlineBgErrW;
3155 WindowInfo *window;
3156 } colorDialog;
3158 /* Repository for simple preferences settings */
3159 static struct prefData {
3160 int openInTab; /* open files in new tabs */
3161 int wrapStyle; /* what kind of wrapping to do */
3162 int wrapMargin; /* 0=wrap at window width, other=wrap margin */
3163 + int showWrapMargin; /* whether to draw line at wrap margin */
3164 int autoIndent; /* style for auto-indent */
3165 int autoSave; /* whether automatic backup feature is on */
3166 int saveOldVersion; /* whether to preserve a copy of last version */
3167 int searchDlogs; /* whether to show explanatory search dialogs */
3168 int searchWrapBeep; /* 1=beep when search restarts at begin/end */
3169 @@ -293,14 +301,17 @@ static struct prefData {
3170 int sortTabs; /* sort tabs alphabetically */
3171 int repositionDialogs; /* w. to reposition dialogs under the pointer */
3172 int autoScroll; /* w. to autoscroll near top/bottom of screen */
3173 int autoScrollVPadding; /* how close to get before autoscrolling */
3174 int sortOpenPrevMenu; /* whether to sort the "Open Previous" menu */
3175 + int showHiddenFiles; /* whether to show hidden files in the FSBs */
3176 + int showCursorline; /* show cursorline */
3177 int appendLF; /* Whether to append LF at the end of each file */
3178 int mapDelete; /* whether to map delete to backspace */
3179 int stdOpenDialog; /* w. to retain redundant text field in Open */
3180 char tagFile[MAXPATHLEN]; /* name of tags file to look for at startup */
3181 + char prevOpenFilesMask[MAXPATHLEN]; /* regex to omit from Open Previous menu */
3182 int maxPrevOpenFiles; /* limit to size of Open Previous menu */
3183 int typingHidesPointer; /* hide mouse pointer when typing */
3184 char delimiters[MAX_WORD_DELIMITERS]; /* punctuation characters */
3185 char shell[MAXPATHLEN + 1]; /* shell to use for executing commands */
3186 char geometry[MAX_GEOM_STRING_LEN]; /* per-application geometry string,
3187 @@ -319,10 +330,11 @@ static struct prefData {
3188 char helpLinkColor[MAX_COLOR_LEN]; /* Color for hyperlinks in the help system */
3189 char colorNames[NUM_COLORS][MAX_COLOR_LEN];
3190 char tooltipBgColor[MAX_COLOR_LEN];
3191 int undoModifiesSelection;
3192 int focusOnRaise;
3193 + Boolean showScrolltip;
3194 Boolean honorSymlinks;
3195 int truncSubstitution;
3196 Boolean forceOSConversion;
3197 } PrefData;
3199 @@ -845,10 +857,12 @@ static PrefDescripRec PrefDescrip[] = {
3200 "Default", &TempStringPrefs.smartIndentCommon, NULL, True},
3201 {"autoWrap", "AutoWrap", PREF_ENUM, "Continuous",
3202 &PrefData.wrapStyle, AutoWrapTypes, True},
3203 {"wrapMargin", "WrapMargin", PREF_INT, "0",
3204 &PrefData.wrapMargin, NULL, True},
3205 + {"showWrapMargin", "ShowWrapMargin", PREF_ENUM, "Never",
3206 + &PrefData.showWrapMargin, ShowWrapMarginStrings, True},
3207 {"autoIndent", "AutoIndent", PREF_ENUM, "Auto",
3208 &PrefData.autoIndent, AutoIndentTypes, True},
3209 {"autoSave", "AutoSave", PREF_BOOLEAN, "True",
3210 &PrefData.autoSave, NULL, True},
3211 {"openInTab", "OpenInTab", PREF_BOOLEAN, "True",
3212 @@ -882,10 +896,12 @@ static PrefDescripRec PrefDescrip[] = {
3213 &PrefData.repositionDialogs, NULL, True},
3214 #else
3215 {"repositionDialogs", "RepositionDialogs", PREF_BOOLEAN, "True",
3216 &PrefData.repositionDialogs, NULL, True},
3217 #endif
3218 + {"showHiddenFiles", "ShowHiddenFiles", PREF_BOOLEAN, "True",
3219 + &PrefData.showHiddenFiles, NULL, True},
3220 {"autoScroll", "AutoScroll", PREF_BOOLEAN, "False",
3221 &PrefData.autoScroll, NULL, True},
3222 {"autoScrollVPadding", "AutoScrollVPadding", PREF_INT, "4",
3223 &PrefData.autoScrollVPadding, NULL, False},
3224 {"appendLF", "AppendLF", PREF_BOOLEAN, "True",
3225 @@ -1020,13 +1036,20 @@ static PrefDescripRec PrefDescrip[] = {
3226 PrefData.colorNames[LINENO_FG_COLOR],
3227 (void *)sizeof(PrefData.colorNames[LINENO_FG_COLOR]), True},
3228 {"cursorFgColor", "CursorFgColor", PREF_STRING, NEDIT_DEFAULT_CURSOR_FG,
3229 PrefData.colorNames[CURSOR_FG_COLOR],
3230 (void *)sizeof(PrefData.colorNames[CURSOR_FG_COLOR]), True},
3231 + {"cursorlineBGColor", "CursorlineBGColor", PREF_STRING,
3232 + NEDIT_DEFAULT_CURSORLINE_BG,
3233 + PrefData.colorNames[CURSORLINE_BG_COLOR],
3234 + (void *)sizeof(PrefData.colorNames[CURSORLINE_BG_COLOR]), True},
3235 {"tooltipBgColor", "TooltipBgColor", PREF_STRING, "LemonChiffon1",
3236 PrefData.tooltipBgColor,
3237 (void *)sizeof(PrefData.tooltipBgColor), False},
3238 + {"wrapMarginForeground", "wrapMarginForeground", PREF_STRING,
3239 + NEDIT_DEFAULT_LINENO_FG, PrefData.colorNames[WRAPMARGIN_FG_COLOR],
3240 + (void *)sizeof(PrefData.colorNames[WRAPMARGIN_FG_COLOR]), True},
3241 {"shell", "Shell", PREF_STRING, "DEFAULT", PrefData.shell,
3242 (void*) sizeof(PrefData.shell), True},
3243 {"geometry", "Geometry", PREF_STRING, "",
3244 PrefData.geometry, (void *)sizeof(PrefData.geometry), False},
3245 {"remapDeleteKey", "RemapDeleteKey", PREF_BOOLEAN, "False",
3246 @@ -1038,10 +1061,13 @@ static PrefDescripRec PrefDescrip[] = {
3247 {"wordDelimiters", "WordDelimiters", PREF_STRING,
3248 ".,/\\`'!|@#%^&*()-=+{}[]\":;<>?",
3249 PrefData.delimiters, (void *)sizeof(PrefData.delimiters), False},
3250 {"serverName", "ServerName", PREF_STRING, "", PrefData.serverName,
3251 (void *)sizeof(PrefData.serverName), False},
3252 + {"prevOpenFilesMask", "PrevOpenFilesMask", PREF_STRING, "",
3253 + PrefData.prevOpenFilesMask,
3254 + (void*) sizeof(PrefData.prevOpenFilesMask), False},
3255 {"maxPrevOpenFiles", "MaxPrevOpenFiles", PREF_INT, "30",
3256 &PrefData.maxPrevOpenFiles, NULL, False},
3257 {"bgMenuButton", "BGMenuButton" , PREF_STRING,
3258 "~Shift~Ctrl~Meta~Alt<Btn3Down>", PrefData.bgMenuBtn,
3259 (void *)sizeof(PrefData.bgMenuBtn), False},
3260 @@ -1069,10 +1095,14 @@ static PrefDescripRec PrefDescrip[] = {
3261 "False", &PrefData.focusOnRaise, NULL, False},
3262 {"forceOSConversion", "ForceOSConversion", PREF_BOOLEAN, "True",
3263 &PrefData.forceOSConversion, NULL, False},
3264 {"truncSubstitution", "TruncSubstitution", PREF_ENUM, "Fail",
3265 &PrefData.truncSubstitution, TruncSubstitutionModes, False},
3266 + {"showCursorline", "ShowCursorline", PREF_BOOLEAN, "True",
3267 + &PrefData.showCursorline, NULL, True},
3268 + {"showScrolltip", "ShowScrolltip", PREF_BOOLEAN, "True",
3269 + &PrefData.showScrolltip, NULL, False},
3270 {"honorSymlinks", "HonorSymlinks", PREF_BOOLEAN, "True",
3271 &PrefData.honorSymlinks, NULL, False}
3274 static XrmOptionDescRec OpTable[] = {
3275 @@ -1124,11 +1154,13 @@ static WindowInfo *TabsDialogForWindow;
3276 static Widget TabDistText, EmTabText, EmTabToggle, UseTabsToggle, EmTabLabel;
3278 /* Module-global variables for Wrap Margin dialog */
3279 static int DoneWithWrapDialog;
3280 static WindowInfo *WrapDialogForWindow;
3281 -static Widget WrapText, WrapTextLabel, WrapWindowToggle;
3282 +static Widget WrapText, WrapTextLabel, WrapWindowToggle, ShowWrapMarginPulldown,
3283 + ShowWrapMarginPulldownItems[N_SHOW_WRAP_MARGIN_STYLES],
3284 + ShowWrapMarginOptMenu, ShowWrapMarginLabel;
3286 /* Module-global variables for shell selection dialog */
3287 static int DoneWithShellSelDialog = False;
3289 static void translatePrefFormats(int convertOld, int fileVer);
3290 @@ -1234,22 +1266,22 @@ static void updatePatternsTo5dot6(void);
3291 static void updateMacroCmdsTo5dot6(void);
3292 static void migrateColorResources(XrmDatabase prefDB, XrmDatabase appDB);
3293 static void spliceString(char **intoString, const char *insertString, const char *atExpr);
3294 static int regexFind(const char *inString, const char *expr);
3295 static int regexReplace(char **inString, const char *expr,
3296 - const char *replaceWith);
3297 + const char *replaceWith);
3298 +static void initPrefDefaultsFromResources(XrmDatabase prefDB, XrmDatabase appDB);
3299 static int caseFind(const char *inString, const char *expr);
3300 static int caseReplace(char **inString, const char *expr,
3301 const char *replaceWith, int replaceLen);
3302 static int stringReplace(char **inString, const char *expr,
3303 const char *replaceWith, int searchType,
3304 int replaceLen);
3305 static int replaceMacroIfUnchanged(const char* oldText, const char* newStart,
3306 const char* newEnd);
3307 static const char* getDefaultShell(void);
3310 #ifdef SGI_CUSTOM
3311 static int shortPrefToDefault(Widget parent, const char *settingName, int *setDefault);
3312 #endif
3314 XrmDatabase CreateNEditPrefDB(int *argcInOut, char **argvInOut)
3315 @@ -1264,10 +1296,14 @@ void RestoreNEditPrefs(XrmDatabase prefD
3316 int major; /* The integral part of version number */
3317 int minor; /* fractional part of version number */
3318 int fileVer = 0; /* Both combined into an integer */
3319 int nparsed;
3321 + /* Default values of certain preferences are derived from Motif resources,
3322 + if these resources are set. */
3323 + initPrefDefaultsFromResources(prefDB, appDB);
3325 /* Load preferences */
3326 RestorePreferences(prefDB, appDB, APP_NAME,
3327 APP_CLASS, PrefDescrip, XtNumber(PrefDescrip));
3329 /* If the preferences file was written by an older version of NEdit,
3330 @@ -1559,10 +1595,20 @@ void SetPrefWrapMargin(int margin)
3331 int GetPrefWrapMargin(void)
3333 return PrefData.wrapMargin;
3336 +void SetPrefShowWrapMargin(int state)
3338 + setIntPref(&PrefData.showWrapMargin, state);
3341 +int GetPrefShowWrapMargin(void)
3343 + return PrefData.showWrapMargin;
3346 void SetPrefSearch(int searchType)
3348 setIntPref(&PrefData.searchMethod, searchType);
3351 @@ -1930,10 +1976,20 @@ void SetPrefRepositionDialogs(int state)
3352 int GetPrefRepositionDialogs(void)
3354 return PrefData.repositionDialogs;
3357 +void SetPrefShowHiddenFiles(int state)
3359 + setIntPref(&PrefData.showHiddenFiles, state);
3362 +int GetPrefShowHiddenFiles(void)
3364 + return PrefData.showHiddenFiles;
3367 void SetPrefAutoScroll(int state)
3369 WindowInfo *w = WindowList;
3370 int margin = state ? PrefData.autoScrollVPadding : 0;
3372 @@ -2118,10 +2174,15 @@ char *GetPrefServerName(void)
3373 char *GetPrefBGMenuBtn(void)
3375 return PrefData.bgMenuBtn;
3378 +char *GetPrevOpenFilesMask(void)
3380 + return PrefData.prevOpenFilesMask;
3383 int GetPrefMaxPrevOpenFiles(void)
3385 return PrefData.maxPrevOpenFiles;
3388 @@ -2186,10 +2247,25 @@ int GetPrefOverrideVirtKeyBindings(void)
3389 int GetPrefTruncSubstitution(void)
3391 return PrefData.truncSubstitution;
3394 +void SetPrefShowCursorline(Boolean value)
3396 + setIntPref(&PrefData.showCursorline, (int) value);
3399 +Boolean GetPrefShowCursorline(void)
3401 + return (Boolean) PrefData.showCursorline;
3404 +Boolean GetPrefShowScrolltip(void)
3406 + return (Boolean) PrefData.showScrolltip;
3410 ** If preferences don't get saved, ask the user on exit whether to save
3412 void MarkPrefsChanged(void)
3414 @@ -2678,10 +2754,13 @@ void WrapMarginDialog(Widget parent, Win
3416 Widget form, selBox;
3417 Arg selBoxArgs[2];
3418 XmString s1;
3419 int margin;
3420 + int showWrapMargin;
3421 + int i, n;
3422 + Arg args[20];
3424 XtSetArg(selBoxArgs[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
3425 XtSetArg(selBoxArgs[1], XmNautoUnmanage, False);
3426 selBox = CreatePromptDialog(parent, "wrapMargin", selBoxArgs, 2);
3427 XtAddCallback(selBox, XmNokCallback, (XtCallbackProc)wrapOKCB, NULL);
3428 @@ -2720,20 +2799,74 @@ void WrapMarginDialog(Widget parent, Win
3429 XmNrightWidget, WrapText,
3430 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
3431 XmNbottomWidget, WrapText, NULL);
3432 XmStringFree(s1);
3434 + ShowWrapMarginPulldown = CreatePulldownMenu(form, "ShowWrapMarginPulldown",
3435 + NULL, 0);
3436 + for(i=0; i<N_SHOW_WRAP_MARGIN_STYLES; i++) {
3437 + s1 = XmStringCreateSimple(ShowWrapMarginStrings[i]);
3438 + ShowWrapMarginPulldownItems[i] = XtVaCreateManagedWidget(
3439 + "ShowWrapMarginPulldown",
3440 + xmPushButtonWidgetClass, ShowWrapMarginPulldown,
3441 + XmNlabelString, s1,
3442 + XmNmarginHeight, 0,
3443 + XmNuserData, i,
3444 + NULL);
3445 + XmStringFree(s1);
3447 + n = 0;
3448 + XtSetArg(args[n], XmNspacing, 0); n++;
3449 + XtSetArg(args[n], XmNmarginWidth, 0); n++;
3450 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
3451 + XtSetArg(args[n], XmNtopWidget, WrapText); n++;
3452 + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
3453 + XtSetArg(args[n], XmNsubMenuId, ShowWrapMarginPulldown); n++;
3454 + ShowWrapMarginOptMenu = XmCreateOptionMenu(form,
3455 + "ShowWrapMarginOptMenu", args, n);
3456 + XtManageChild(ShowWrapMarginOptMenu);
3458 + ShowWrapMarginLabel = XtVaCreateManagedWidget("ShowWrapMarginLabel",
3459 + xmLabelGadgetClass, form,
3460 + XmNlabelString, s1=XmStringCreateSimple("Show Wrap Margin"),
3461 + XmNmnemonic, 'S',
3462 + XmNuserData, XtParent(ShowWrapMarginOptMenu),
3463 + XmNalignment, XmALIGNMENT_END,
3464 + XmNtopAttachment, XmATTACH_WIDGET,
3465 + XmNtopWidget, WrapText,
3466 + XmNleftAttachment, XmATTACH_FORM,
3467 + XmNrightAttachment, XmATTACH_WIDGET,
3468 + XmNrightWidget, ShowWrapMarginOptMenu,
3469 + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
3470 + XmNbottomWidget, ShowWrapMarginOptMenu,
3471 + NULL);
3472 + XmStringFree(s1);
3474 /* Set default value */
3475 - if (forWindow == NULL)
3476 + if (forWindow == NULL) {
3477 margin = GetPrefWrapMargin();
3478 - else
3479 + showWrapMargin = GetPrefShowWrapMargin();
3480 + } else {
3481 XtVaGetValues(forWindow->textArea, textNwrapMargin, &margin, NULL);
3482 + showWrapMargin = forWindow->showWrapMargin;
3485 + if (showWrapMargin > N_SHOW_WRAP_MARGIN_STYLES || showWrapMargin < 0)
3487 + fprintf(stderr, "nedit: internal error: illegal value for showWrapMargin: %d\n", showWrapMargin);
3488 + showWrapMargin = SHOW_WRAP_MARGIN_NEVER;
3491 XmToggleButtonSetState(WrapWindowToggle, margin==0, True);
3492 + XtVaSetValues(ShowWrapMarginOptMenu, XmNmenuHistory,
3493 + ShowWrapMarginPulldownItems[showWrapMargin], NULL);
3494 if (margin != 0)
3495 SetIntText(WrapText, margin);
3496 XtSetSensitive(WrapText, margin!=0);
3497 XtSetSensitive(WrapTextLabel, margin!=0);
3498 + XtSetSensitive(ShowWrapMarginOptMenu, margin!=0);
3499 + XtSetSensitive(ShowWrapMarginLabel, margin!=0);
3501 /* Handle mnemonic selection of buttons and focus to dialog */
3502 AddDialogMnemonicHandler(form, FALSE);
3504 /* put up dialog and wait for user to press ok or cancel */
3505 @@ -2752,10 +2885,12 @@ void WrapMarginDialog(Widget parent, Win
3507 static void wrapOKCB(Widget w, XtPointer clientData, XtPointer callData)
3509 int wrapAtWindow, margin, stat;
3510 WindowInfo *window = WrapDialogForWindow;
3511 + int showWrapMargin;
3512 + Widget showWrapMarginSelectedItem;
3514 /* get the values that the user entered and make sure they're ok */
3515 wrapAtWindow = XmToggleButtonGetState(WrapWindowToggle);
3516 if (wrapAtWindow)
3517 margin = 0;
3518 @@ -2771,10 +2906,17 @@ static void wrapOKCB(Widget w, XtPointer
3519 return;
3524 + XtVaGetValues(ShowWrapMarginOptMenu, XmNmenuHistory,
3525 + &showWrapMarginSelectedItem, NULL);
3526 + XtVaGetValues(showWrapMarginSelectedItem, XmNuserData, &showWrapMargin, NULL);
3527 + if (showWrapMargin > N_SHOW_WRAP_MARGIN_STYLES || showWrapMargin < 0) {
3528 + showWrapMargin = SHOW_WRAP_MARGIN_NEVER;
3531 #ifdef SGI_CUSTOM
3532 /* Ask the user about saving as a default preference */
3533 if (WrapDialogForWindow != NULL) {
3534 int setDefault;
3535 if (!shortPrefToDefault(window->shell, "Wrap Margin Settings",
3536 @@ -2782,24 +2924,29 @@ static void wrapOKCB(Widget w, XtPointer
3537 DoneWithWrapDialog = True;
3538 return;
3540 if (setDefault) {
3541 SetPrefWrapMargin(margin);
3542 + SetPrefShowWrapMargin(showWrapMargin);
3543 SaveNEditPrefs(window->shell, GetPrefShortMenus());
3546 #endif
3548 /* Set the value in either the requested window or default preferences */
3549 - if (WrapDialogForWindow == NULL)
3550 + if (WrapDialogForWindow == NULL) {
3551 SetPrefWrapMargin(margin);
3552 - else {
3553 + SetPrefShowWrapMargin(showWrapMargin);
3554 + } else {
3555 char *params[1];
3556 char marginStr[25];
3557 sprintf(marginStr, "%d", margin);
3558 params[0] = marginStr;
3559 XtCallActionProc(window->textArea, "set_wrap_margin", NULL, params, 1);
3560 + sprintf(marginStr, "%d", showWrapMargin);
3561 + params[0] = marginStr;
3562 + XtCallActionProc(window->textArea, "set_show_wrap_margin", NULL, params, 1);
3564 DoneWithWrapDialog = True;
3567 static void wrapCancelCB(Widget w, XtPointer clientData, XtPointer callData)
3568 @@ -2811,10 +2958,12 @@ static void wrapWindowCB(Widget w, XtPoi
3570 int wrapAtWindow = XmToggleButtonGetState(w);
3572 XtSetSensitive(WrapTextLabel, !wrapAtWindow);
3573 XtSetSensitive(WrapText, !wrapAtWindow);
3574 + XtSetSensitive(ShowWrapMarginOptMenu, !wrapAtWindow);
3575 + XtSetSensitive(ShowWrapMarginLabel, !wrapAtWindow);
3579 ** Create and show a dialog for selecting the shell
3581 @@ -6072,10 +6221,11 @@ selectFg SELECT_FG_COLOR
3582 selectBg SELECT_BG_COLOR
3583 hiliteFg HILITE_FG_COLOR
3584 hiliteBg HILITE_BG_COLOR
3585 lineNoFg LINENO_FG_COLOR
3586 cursorFg CURSOR_FG_COLOR
3587 +cursorlineBg CURSORLINE_BG_COLOR
3590 #define MARGIN_SPACING 10
3593 @@ -6135,10 +6285,24 @@ static void cursorFgModifiedCB(Widget w,
3595 colorDialog *cd = (colorDialog *)clientData;
3596 showColorStatus(cd, cd->cursorFgW, cd->cursorFgErrW);
3599 +static void wrapMarginFgModifiedCB(Widget w, XtPointer clientData,
3600 + XtPointer callData)
3602 + colorDialog *cd = (colorDialog *)clientData;
3603 + showColorStatus(cd, cd->wrapMarginFgW, cd->wrapMarginFgErrW);
3606 +static void cursorlineBgModifiedCB(Widget w, XtPointer clientData,
3607 + XtPointer callData)
3609 + colorDialog *cd = (colorDialog *)clientData;
3610 + showColorStatus(cd, cd->cursorlineBgW, cd->cursorlineBgErrW);
3615 * Helper functions for validating colors
3617 static int verifyAllColors(colorDialog *cd)
3618 @@ -6149,11 +6313,12 @@ static int verifyAllColors(colorDialog *
3619 checkColorStatus(cd, cd->selectFgW) &&
3620 checkColorStatus(cd, cd->selectBgW) &&
3621 checkColorStatus(cd, cd->hiliteFgW) &&
3622 checkColorStatus(cd, cd->hiliteBgW) &&
3623 checkColorStatus(cd, cd->lineNoFgW) &&
3624 - checkColorStatus(cd, cd->cursorFgW) );
3625 + checkColorStatus(cd, cd->cursorFgW) &&
3626 + checkColorStatus(cd, cd->cursorlineBgW));
3629 /* Returns True if the color is valid, False if it's not */
3630 static Boolean checkColorStatus(colorDialog *cd, Widget colorFieldW)
3632 @@ -6188,35 +6353,41 @@ static void updateColors(colorDialog *cd
3633 *selectFg = XmTextGetString(cd->selectFgW),
3634 *selectBg = XmTextGetString(cd->selectBgW),
3635 *hiliteFg = XmTextGetString(cd->hiliteFgW),
3636 *hiliteBg = XmTextGetString(cd->hiliteBgW),
3637 *lineNoFg = XmTextGetString(cd->lineNoFgW),
3638 - *cursorFg = XmTextGetString(cd->cursorFgW);
3639 + *cursorFg = XmTextGetString(cd->cursorFgW),
3640 + *wrapMarginFg = XmTextGetString(cd->wrapMarginFgW),
3641 + *cursorlineBg = XmTextGetString(cd->cursorlineBgW);
3643 for (window = WindowList; window != NULL; window = window->next)
3645 SetColors(window, textFg, textBg, selectFg, selectBg, hiliteFg,
3646 - hiliteBg, lineNoFg, cursorFg);
3647 + hiliteBg, lineNoFg, cursorFg, wrapMarginFg, cursorlineBg);
3650 SetPrefColorName(TEXT_FG_COLOR , textFg );
3651 SetPrefColorName(TEXT_BG_COLOR , textBg );
3652 SetPrefColorName(SELECT_FG_COLOR, selectFg);
3653 SetPrefColorName(SELECT_BG_COLOR, selectBg);
3654 SetPrefColorName(HILITE_FG_COLOR, hiliteFg);
3655 SetPrefColorName(HILITE_BG_COLOR, hiliteBg);
3656 SetPrefColorName(LINENO_FG_COLOR, lineNoFg);
3657 SetPrefColorName(CURSOR_FG_COLOR, cursorFg);
3658 + SetPrefColorName(WRAPMARGIN_FG_COLOR, wrapMarginFg);
3659 + SetPrefColorName(CURSORLINE_BG_COLOR, cursorlineBg);
3661 XtFree(textFg);
3662 XtFree(textBg);
3663 XtFree(selectFg);
3664 XtFree(selectBg);
3665 XtFree(hiliteFg);
3666 XtFree(hiliteBg);
3667 XtFree(lineNoFg);
3668 XtFree(cursorFg);
3669 + XtFree(wrapMarginFg);
3670 + XtFree(cursorlineBg);
3675 * Dialog button callbacks
3676 @@ -6382,10 +6553,27 @@ void ChooseColors(WindowInfo *window)
3677 NULL);
3678 XmStringFree(s1);
3680 topW = infoLbl;
3682 + /* The right column (backgrounds) */
3683 + tmpW = addColorGroup( form, "textBg", 'T', "Text Area Background",
3684 + &(cd->textBgW), &(cd->textBgErrW), topW, 51, 99,
3685 + textBgModifiedCB, cd );
3686 + tmpW = addColorGroup( form, "selectBg", 'B', "Selection Background",
3687 + &(cd->selectBgW), &(cd->selectBgErrW), tmpW, 51, 99,
3688 + selectBgModifiedCB, cd );
3689 + tmpW = addColorGroup( form, "hiliteBg", 'h', "Matching (..) Background",
3690 + &(cd->hiliteBgW), &(cd->hiliteBgErrW), tmpW, 51, 99,
3691 + hiliteBgModifiedCB, cd );
3692 + tmpW = addColorGroup( form, "wrapMarginFg", 'w', "Wrap Margin Color",
3693 + &(cd->wrapMarginFgW), &(cd->wrapMarginFgErrW), tmpW, 51, 99,
3694 + wrapMarginFgModifiedCB, cd );
3695 + tmpW = addColorGroup( form, "cursorlineBg", 'r', "Cursorline Highlighting",
3696 + &(cd->cursorlineBgW), &(cd->cursorlineBgErrW), tmpW, 51, 99,
3697 + cursorlineBgModifiedCB, cd );
3699 /* The left column (foregrounds) of color entry groups */
3700 tmpW = addColorGroup( form, "textFg", 'P', "Plain Text Foreground",
3701 &(cd->textFgW), &(cd->textFgErrW), topW, 1, 49,
3702 textFgModifiedCB, cd );
3703 tmpW = addColorGroup( form, "selectFg", 'S', "Selection Foreground",
3704 @@ -6395,23 +6583,12 @@ void ChooseColors(WindowInfo *window)
3705 &(cd->hiliteFgW), &(cd->hiliteFgErrW), tmpW, 1, 49,
3706 hiliteFgModifiedCB, cd );
3707 tmpW = addColorGroup( form, "lineNoFg", 'L', "Line Numbers",
3708 &(cd->lineNoFgW), &(cd->lineNoFgErrW), tmpW, 1, 49,
3709 lineNoFgModifiedCB, cd );
3711 - /* The right column (backgrounds) */
3712 - tmpW = addColorGroup( form, "textBg", 'T', "Text Area Background",
3713 - &(cd->textBgW), &(cd->textBgErrW), topW, 51, 99,
3714 - textBgModifiedCB, cd );
3715 - tmpW = addColorGroup( form, "selectBg", 'B', "Selection Background",
3716 - &(cd->selectBgW), &(cd->selectBgErrW), tmpW, 51, 99,
3717 - selectBgModifiedCB, cd );
3718 - tmpW = addColorGroup( form, "hiliteBg", 'h', "Matching (..) Background",
3719 - &(cd->hiliteBgW), &(cd->hiliteBgErrW), tmpW, 51, 99,
3720 - hiliteBgModifiedCB, cd );
3721 tmpW = addColorGroup( form, "cursorFg", 'C', "Cursor Color",
3722 - &(cd->cursorFgW), &(cd->cursorFgErrW), tmpW, 51, 99,
3723 + &(cd->cursorFgW), &(cd->cursorFgErrW), tmpW, 1, 49,
3724 cursorFgModifiedCB, cd );
3726 tmpW = XtVaCreateManagedWidget("infoLbl",
3727 xmLabelGadgetClass, form,
3728 XmNtopAttachment, XmATTACH_WIDGET,
3729 @@ -6490,18 +6667,70 @@ void ChooseColors(WindowInfo *window)
3730 XmTextSetString(cd->selectBgW, GetPrefColorName(SELECT_BG_COLOR));
3731 XmTextSetString(cd->hiliteFgW, GetPrefColorName(HILITE_FG_COLOR));
3732 XmTextSetString(cd->hiliteBgW, GetPrefColorName(HILITE_BG_COLOR));
3733 XmTextSetString(cd->lineNoFgW, GetPrefColorName(LINENO_FG_COLOR));
3734 XmTextSetString(cd->cursorFgW, GetPrefColorName(CURSOR_FG_COLOR));
3735 + XmTextSetString(cd->wrapMarginFgW, GetPrefColorName(WRAPMARGIN_FG_COLOR));
3736 + XmTextSetString(cd->cursorlineBgW, GetPrefColorName(CURSORLINE_BG_COLOR));
3738 /* Handle mnemonic selection of buttons and focus to dialog */
3739 AddDialogMnemonicHandler(form, FALSE);
3741 /* put up dialog */
3742 ManageDialogCenteredOnPointer(form);
3745 +/* Overrides the defaults for certain preferences with values obtained from
3746 + obsoleted resources. */
3747 +static void initPrefDefaultsFromResources(XrmDatabase prefDB, XrmDatabase appDB)
3749 + char *type, *valueString;
3750 + XrmValue rsrcValue;
3752 + /* XmFileSelectionBox.fileFilterStyle is now obsolete since it is
3753 + overridden by nedit.showHiddenFiles, but this code tries to make
3754 + the transition painless by translating the resource value, if set,
3755 + to a matching default for the preferences */
3756 + const char* showHiddenResName =
3757 + APP_NAME "*XmFileSelectionBox.fileFilterStyle";
3758 + const char* showHiddenClassName =
3759 + APP_CLASS "*XmFileSelectionBox.FileFilterStyle";
3761 + /* Retrieve the value of the resource from the DB */
3762 + if (XrmGetResource(prefDB, showHiddenResName, showHiddenClassName, &type,
3763 + &rsrcValue)) {
3764 + if (strcmp(type, XmRString)) {
3765 + fprintf(stderr, "nedit: Internal Error: Unexpected resource type, %s\n",
3766 + type);
3767 + return;
3769 + valueString = rsrcValue.addr;
3770 + } else if (XrmGetResource(appDB, showHiddenResName, showHiddenClassName,
3771 + &type, &rsrcValue)) {
3772 + if (strcmp(type, XmRString)) {
3773 + fprintf(stderr, "nedit: Internal Error: Unexpected resource type, %s\n",
3774 + type);
3775 + return;
3777 + valueString = rsrcValue.addr;
3778 + } else {
3779 + /* No resources set */
3780 + return;
3783 + /* An X resource is set. If it's non-default, update the prefs default. */
3784 + if (0 == strcmp(valueString, "XmFILTER_HIDDEN_FILES")) {
3785 + unsigned int i;
3786 + for (i = 0; i < XtNumber(PrefDescrip); ++i) {
3787 + if (0 == strcmp(PrefDescrip[i].name, "showHiddenFiles")) {
3788 + PrefDescrip[i].defaultString = "False";
3789 + break;
3796 ** This function passes up a pointer to the static name of the default
3797 ** shell, currently defined as the user's login shell.
3798 ** In case of errors, the fallback of "sh" will be returned.
3800 diff --quilt old/source/preferences.h new/source/preferences.h
3801 --- old/source/preferences.h
3802 +++ new/source/preferences.h
3803 @@ -57,10 +57,12 @@ void MarkPrefsChanged(void);
3804 int CheckPrefsChangesSaved(Widget dialogParent);
3805 void SetPrefWrap(int state);
3806 int GetPrefWrap(int langMode);
3807 void SetPrefWrapMargin(int margin);
3808 int GetPrefWrapMargin(void);
3809 +void SetPrefShowWrapMargin(int state);
3810 +int GetPrefShowWrapMargin(void);
3811 void SetPrefSearchDlogs(int state);
3812 int GetPrefSearchDlogs(void);
3813 void SetPrefKeepSearchDlogs(int state);
3814 int GetPrefKeepSearchDlogs(void);
3815 void SetPrefSearchWraps(int state);
3816 @@ -117,10 +119,12 @@ void SetPrefBacklightChars(int state);
3817 int GetPrefBacklightChars(void);
3818 void SetPrefBacklightCharTypes(char *types);
3819 char *GetPrefBacklightCharTypes(void);
3820 void SetPrefRepositionDialogs(int state);
3821 int GetPrefRepositionDialogs(void);
3822 +void SetPrefShowHiddenFiles(int state);
3823 +int GetPrefShowHiddenFiles(void);
3824 void SetPrefAutoScroll(int state);
3825 int GetPrefAutoScroll(void);
3826 int GetVerticalAutoScroll(void);
3827 void SetPrefAppendLF(int state);
3828 int GetPrefAppendLF(void);
3829 @@ -156,10 +160,11 @@ void RowColumnPrefDialog(Widget parent);
3830 void TabsPrefDialog(Widget parent, WindowInfo *forWindow);
3831 void WrapMarginDialog(Widget parent, WindowInfo *forWindow);
3832 int GetPrefMapDelete(void);
3833 int GetPrefStdOpenDialog(void);
3834 char *GetPrefDelimiters(void);
3835 +char *GetPrevOpenFilesMask(void);
3836 int GetPrefMaxPrevOpenFiles(void);
3837 int GetPrefTypingHidesPointer(void);
3838 #ifdef SGI_CUSTOM
3839 void SetPrefShortMenus(int state);
3840 int GetPrefShortMenus(void);
3841 @@ -209,7 +214,10 @@ void SetPrefOpenInTab(int state);
3842 Boolean GetPrefUndoModifiesSelection(void);
3843 Boolean GetPrefFocusOnRaise(void);
3844 Boolean GetPrefHonorSymlinks(void);
3845 Boolean GetPrefForceOSConversion(void);
3846 void SetPrefFocusOnRaise(Boolean);
3847 +void SetPrefShowCursorline(Boolean value);
3848 +Boolean GetPrefShowCursorline(void);
3849 +Boolean GetPrefShowScrolltip(void);
3851 #endif /* NEDIT_PREFERENCES_H_INCLUDED */
3852 diff --quilt old/source/search.c new/source/search.c
3853 --- old/source/search.c
3854 +++ new/source/search.c
3855 @@ -241,10 +241,11 @@ static void iSearchCaseToggleCB(Widget w
3856 XtPointer callData);
3857 static void iSearchTryBeepOnWrap(WindowInfo *window, int direction,
3858 int beginPos, int startPos);
3859 static void iSearchRecordLastBeginPos(WindowInfo *window, int direction,
3860 int initPos);
3861 +static void smartCaseToggle(const char* searchString, Widget toggleButton);
3862 static Boolean prefOrUserCancelsSubst(const Widget parent,
3863 const Display* display);
3865 typedef struct _charMatchTable {
3866 char c;
3867 @@ -279,10 +280,11 @@ static char *searchTypeStrings[] = {
3868 "case", /* SEARCH_CASE_SENSE */
3869 "regex", /* SEARCH_REGEX */
3870 "word", /* SEARCH_LITERAL_WORD */
3871 "caseWord", /* SEARCH_CASE_SENSE_WORD */
3872 "regexNoCase", /* SEARCH_REGEX_NOCASE */
3873 + "regexSmartCase", /* SEARCH_REGEX_SMARTCASE */
3874 NULL
3878 ** Window for which a search dialog callback is currently active. That window
3879 @@ -317,70 +319,77 @@ static void initToggleButtons(int search
3880 Bool* lastRegexCase)
3882 /* Set the initial search type and remember the corresponding case
3883 sensitivity states in case sticky case sensitivity is required. */
3884 switch (searchType) {
3885 - case SEARCH_LITERAL:
3886 + case SEARCH_LITERAL:
3887 *lastLiteralCase = False;
3888 *lastRegexCase = True;
3889 XmToggleButtonSetState(regexToggle, False, False);
3890 XmToggleButtonSetState(caseToggle, False, False);
3891 if (wordToggle) {
3892 XmToggleButtonSetState(*wordToggle, False, False);
3893 XtSetSensitive(*wordToggle, True);
3895 - break;
3896 - case SEARCH_CASE_SENSE:
3897 + break;
3899 + case SEARCH_CASE_SENSE:
3900 *lastLiteralCase = True;
3901 *lastRegexCase = True;
3902 XmToggleButtonSetState(regexToggle, False, False);
3903 XmToggleButtonSetState(caseToggle, True, False);
3904 if (wordToggle) {
3905 XmToggleButtonSetState(*wordToggle, False, False);
3906 XtSetSensitive(*wordToggle, True);
3908 - break;
3909 - case SEARCH_LITERAL_WORD:
3910 + break;
3912 + case SEARCH_LITERAL_WORD:
3913 *lastLiteralCase = False;
3914 *lastRegexCase = True;
3915 XmToggleButtonSetState(regexToggle, False, False);
3916 XmToggleButtonSetState(caseToggle, False, False);
3917 if (wordToggle) {
3918 XmToggleButtonSetState(*wordToggle, True, False);
3919 XtSetSensitive(*wordToggle, True);
3921 - break;
3922 - case SEARCH_CASE_SENSE_WORD:
3923 + break;
3925 + case SEARCH_CASE_SENSE_WORD:
3926 *lastLiteralCase = True;
3927 *lastRegexCase = True;
3928 XmToggleButtonSetState(regexToggle, False, False);
3929 XmToggleButtonSetState(caseToggle, True, False);
3930 if (wordToggle) {
3931 XmToggleButtonSetState(*wordToggle, True, False);
3932 XtSetSensitive(*wordToggle, True);
3934 - break;
3935 - case SEARCH_REGEX:
3936 + break;
3938 + case SEARCH_REGEX:
3939 *lastLiteralCase = False;
3940 *lastRegexCase = True;
3941 XmToggleButtonSetState(regexToggle, True, False);
3942 XmToggleButtonSetState(caseToggle, True, False);
3943 if (wordToggle) {
3944 XmToggleButtonSetState(*wordToggle, False, False);
3945 XtSetSensitive(*wordToggle, False);
3947 - break;
3948 - case SEARCH_REGEX_NOCASE:
3949 - *lastLiteralCase = False;
3950 - *lastRegexCase = False;
3951 - XmToggleButtonSetState(regexToggle, True, False);
3952 - XmToggleButtonSetState(caseToggle, False, False);
3953 - if (wordToggle) {
3954 - XmToggleButtonSetState(*wordToggle, False, False);
3955 - XtSetSensitive(*wordToggle, False);
3957 - break;
3958 + break;
3960 + case SEARCH_REGEX_NOCASE:
3961 + case SEARCH_REGEX_SMARTCASE:
3962 + /* Smart case is no case for default setting */
3963 + *lastLiteralCase = False;
3964 + *lastRegexCase = False;
3965 + XmToggleButtonSetState(regexToggle, True, False);
3966 + XmToggleButtonSetState(caseToggle, False, False);
3967 + if (wordToggle) {
3968 + XmToggleButtonSetState(*wordToggle, False, False);
3969 + XtSetSensitive(*wordToggle, False);
3971 + break;
3975 #ifdef REPLACE_SCOPE
3977 @@ -2404,14 +2413,23 @@ static int textFieldNonEmpty(Widget w)
3978 int nonEmpty = (str[0] != '\0');
3979 XtFree(str);
3980 return(nonEmpty);
3983 -static void rFindTextValueChangedCB(Widget w, WindowInfo *window, XKeyEvent *event)
3984 +static void rFindTextValueChangedCB(Widget textWidget, WindowInfo* window,
3985 + XKeyEvent* event)
3987 - window = WidgetToWindow(w);
3988 + char* searchString = XmTextGetString(textWidget);
3990 + window = WidgetToWindow(textWidget);
3991 UpdateReplaceActionButtons(window);
3993 + /* Switch to case-sensitive as soon as the user enters an upper-case
3994 + letter. We have check the whole string each time to catch clipboard
3995 + or selection inserts. */
3996 + smartCaseToggle(searchString, window->replaceCaseToggle);
3997 + XtFree(searchString);
4000 static void rFindArrowKeyCB(Widget w, WindowInfo *window, XKeyEvent *event)
4002 KeySym keysym = XLookupKeysym(event, 0);
4003 @@ -2499,14 +2517,23 @@ static void fUpdateActionButtons(WindowI
4005 int buttonState = textFieldNonEmpty(window->findText);
4006 XtSetSensitive(window->findBtn, buttonState);
4009 -static void findTextValueChangedCB(Widget w, WindowInfo *window, XKeyEvent *event)
4010 +static void findTextValueChangedCB(Widget textWidget, WindowInfo* window,
4011 + XKeyEvent* event)
4013 - window = WidgetToWindow(w);
4014 + char* searchString = XmTextGetString(textWidget);
4016 + window = WidgetToWindow(textWidget);
4017 fUpdateActionButtons(window);
4019 + /* Switch to case-sensitive as soon as the user enters an upper-case
4020 + letter. We have check the whole string each time to catch clipboard
4021 + or selection inserts. */
4022 + smartCaseToggle(searchString, window->findCaseToggle);
4023 + XtFree(searchString);
4026 static void findArrowKeyCB(Widget w, WindowInfo *window, XKeyEvent *event)
4028 KeySym keysym = XLookupKeysym(event, 0);
4029 @@ -2527,11 +2554,10 @@ static void findArrowKeyCB(Widget w, Win
4030 /* if the index is out of range, beep and return */
4031 if (index != 0 && historyIndex(index) == -1) {
4032 XBell(TheDisplay, 0);
4033 return;
4037 /* determine the strings and button settings to use */
4038 if (index == 0) {
4039 searchStr = "";
4040 searchType = GetPrefSearch();
4041 @@ -2874,36 +2900,45 @@ static void selectedSearchCB(Widget w, X
4042 XtFree(value);
4044 /* Use the passed method for searching, unless it is regex, since this
4045 kind of search is by definition a literal search */
4046 searchType = callDataItems->searchType;
4047 - if (searchType == SEARCH_REGEX )
4048 - searchType = SEARCH_CASE_SENSE;
4049 - else if (searchType == SEARCH_REGEX_NOCASE)
4050 - searchType = SEARCH_LITERAL;
4051 + if (searchType == SEARCH_REGEX || searchType == SEARCH_REGEX_SMARTCASE) {
4052 + /* Here smart case must be sensitive, because the user
4053 + cannot modify the string to search for. */
4054 + searchType = SEARCH_CASE_SENSE;
4055 + } else if (searchType == SEARCH_REGEX_NOCASE) {
4056 + searchType = SEARCH_LITERAL;
4059 /* search for it in the window */
4060 SearchAndSelect(window, callDataItems->direction, searchString,
4061 searchType, callDataItems->searchWrap);
4062 XtFree(callData);
4066 ** Pop up and clear the incremental search line and prepare to search.
4068 -void BeginISearch(WindowInfo *window, int direction)
4069 +void BeginISearch(WindowInfo* window, int direction)
4071 window->iSearchStartPos = -1;
4072 XmTextSetString(window->iSearchText, "");
4073 XmToggleButtonSetState(window->iSearchRevToggle,
4074 - direction == SEARCH_BACKWARD, FALSE);
4075 + direction == SEARCH_BACKWARD, FALSE);
4077 /* Note: in contrast to the replace and find dialogs, the regex and
4078 case toggles are not reset to their default state when the incremental
4079 search bar is redisplayed. I'm not sure whether this is the best
4080 choice. If not, an initToggleButtons() call should be inserted
4081 here. But in that case, it might be appropriate to have different
4082 default search modes for i-search and replace/find. */
4084 + /* The 'Case' toggle button must be deactivated for smart cases. */
4085 + if (GetPrefSearch() == SEARCH_REGEX_SMARTCASE) {
4086 + XmToggleButtonSetState(window->iSearchCaseToggle, False, False);
4088 TempShowISearch(window, TRUE);
4089 XmProcessTraversal(window->iSearchText, XmTRAVERSE_CURRENT);
4093 @@ -3181,32 +3216,40 @@ static void iSearchTextActivateCB(Widget
4096 ** Called when user types in the incremental search line. Redoes the
4097 ** search for the new search string.
4099 -static void iSearchTextValueChangedCB(Widget w, WindowInfo *window,
4100 - XmAnyCallbackStruct *callData)
4101 +static void iSearchTextValueChangedCB(Widget widget, WindowInfo *window,
4102 + XmAnyCallbackStruct *callData)
4104 char *params[5];
4105 char *searchString;
4106 int searchType, direction, nParams;
4108 - window = WidgetToWindow(w);
4111 + window = WidgetToWindow(widget);
4113 /* Fetch the string, search type and direction from the incremental
4114 search bar widgets at the top of the window */
4115 searchString = XmTextGetString(window->iSearchText);
4117 + /* Switch to case-sensitive as soon as the user enters an upper-case
4118 + letter. We have check the whole string each time to catch clipboard
4119 + or selection inserts. */
4120 + smartCaseToggle(searchString, window->iSearchCaseToggle);
4122 if(XmToggleButtonGetState(window->iSearchCaseToggle)) {
4123 - if(XmToggleButtonGetState(window->iSearchRegexToggle))
4124 - searchType = SEARCH_REGEX;
4125 - else
4126 - searchType = SEARCH_CASE_SENSE;
4127 + if(XmToggleButtonGetState(window->iSearchRegexToggle)) {
4128 + searchType = SEARCH_REGEX;
4129 + } else {
4130 + searchType = SEARCH_CASE_SENSE;
4132 } else {
4133 - if(XmToggleButtonGetState(window->iSearchRegexToggle))
4134 - searchType = SEARCH_REGEX_NOCASE;
4135 - else
4136 - searchType = SEARCH_LITERAL;
4137 + if(XmToggleButtonGetState(window->iSearchRegexToggle)) {
4138 + searchType = SEARCH_REGEX_NOCASE;
4139 + } else {
4140 + searchType = SEARCH_LITERAL;
4143 direction = XmToggleButtonGetState(window->iSearchRevToggle) ?
4144 SEARCH_BACKWARD : SEARCH_FORWARD;
4146 /* If the search type is a regular expression, test compile it. If it
4147 @@ -4872,11 +4915,13 @@ static char *directionArg(int direction)
4149 ** Checks whether a search mode in one of the regular expression modes.
4151 static int isRegexType(int searchType)
4153 - return searchType == SEARCH_REGEX || searchType == SEARCH_REGEX_NOCASE;
4154 + return searchType == SEARCH_REGEX
4155 + || searchType == SEARCH_REGEX_NOCASE
4156 + || searchType == SEARCH_REGEX_SMARTCASE;
4160 ** Returns the default flags for regular expression matching, given a
4161 ** regular expression search mode.
4162 @@ -5003,17 +5048,35 @@ static void replaceCaseToggleCB(Widget w
4163 window->replaceLastRegexCase = searchCaseSense;
4164 else
4165 window->replaceLastLiteralCase = searchCaseSense;
4168 -static void iSearchCaseToggleCB(Widget w, XtPointer clientData, XtPointer callData)
4169 +static void iSearchCaseToggleCB(Widget toggleButton, XtPointer clientData,
4170 + XtPointer callData)
4172 - WindowInfo * window = WidgetToWindow(w);
4173 - int searchCaseSense = XmToggleButtonGetState(w);
4174 + WindowInfo * window = WidgetToWindow(toggleButton);
4175 + int searchCaseSense = XmToggleButtonGetState(toggleButton);
4177 /* Save the state of the Case Sensitive button
4178 depending on the state of the Regex button*/
4179 if(XmToggleButtonGetState(window->iSearchRegexToggle))
4180 window->iSearchLastRegexCase = searchCaseSense;
4181 else
4182 window->iSearchLastLiteralCase = searchCaseSense;
4186 +** Will search a string for uppercase characters. If there is one,
4187 +** The toggleButton will be set to True.
4189 +static void smartCaseToggle(const char* searchString, Widget toggleButton)
4191 + if (GetPrefSearch() == SEARCH_REGEX_SMARTCASE) {
4192 + int i;
4193 + for (i = 0; i < strlen(searchString); i++) {
4194 + if (isupper(*(searchString + i))) {
4195 + XmToggleButtonSetState(toggleButton, True, False);
4196 + break;
4201 diff --quilt old/source/search.h new/source/search.h
4202 --- old/source/search.h
4203 +++ new/source/search.h
4204 @@ -85,14 +85,16 @@ Boolean WindowCanBeClosed(WindowInfo *wi
4205 ** The order of the integers in this enumeration must be exactly
4206 ** the same as the order of the coressponding strings of the
4207 ** array SearchMethodStrings defined in preferences.c (!!)
4210 -enum SearchType {
4211 - SEARCH_LITERAL, SEARCH_CASE_SENSE, SEARCH_REGEX,
4212 - SEARCH_LITERAL_WORD, SEARCH_CASE_SENSE_WORD, SEARCH_REGEX_NOCASE,
4213 - N_SEARCH_TYPES /* must be last in enum SearchType */ };
4214 +enum SearchType
4216 + SEARCH_LITERAL, SEARCH_CASE_SENSE, SEARCH_REGEX, SEARCH_LITERAL_WORD,
4217 + SEARCH_CASE_SENSE_WORD, SEARCH_REGEX_NOCASE, SEARCH_REGEX_SMARTCASE,
4218 + N_SEARCH_TYPES /* must be last in enum SearchType */
4221 #ifdef REPLACE_SCOPE
4222 /* Scope on which the replace operations apply */
4223 enum ReplaceScope { REPL_SCOPE_WIN, REPL_SCOPE_SEL, REPL_SCOPE_MULTI };
4225 diff --quilt old/source/selection.c new/source/selection.c
4226 --- old/source/selection.c
4227 +++ new/source/selection.c
4228 @@ -27,21 +27,23 @@ static const char CVSID[] = "$Id: select
4230 #ifdef HAVE_CONFIG_H
4231 #include "../config.h"
4232 #endif
4234 -#include "selection.h"
4235 -#include "textBuf.h"
4236 -#include "text.h"
4237 -#include "nedit.h"
4238 #include "file.h"
4239 -#include "window.h"
4240 +#include "interpret.h"
4241 +#include "macro.h"
4242 #include "menu.h"
4243 +#include "nedit.h"
4244 #include "preferences.h"
4245 +#include "selection.h"
4246 #include "server.h"
4247 +#include "textBuf.h"
4248 +#include "text.h"
4249 #include "../util/DialogF.h"
4250 #include "../util/fileUtils.h"
4251 +#include "window.h"
4253 #include <stdlib.h>
4254 #include <stdio.h>
4255 #include <ctype.h>
4256 #include <string.h>
4257 @@ -349,23 +351,34 @@ static void fileCB(Widget widget, Window
4258 XtFree(nameList[i]);
4260 XtFree((char *)nameList);
4262 #else
4263 - { glob_t globbuf;
4264 - int i;
4266 - glob(nameText, GLOB_NOCHECK, NULL, &globbuf);
4267 - for (i=0; i<(int)globbuf.gl_pathc; i++) {
4268 - if (ParseFilename(globbuf.gl_pathv[i], filename, pathname) != 0)
4269 - XBell(TheDisplay, 0);
4270 - else
4271 - EditExistingFile(GetPrefOpenInTab()? window : NULL,
4272 - filename, pathname, 0, NULL, False, NULL,
4273 - GetPrefOpenInTab(), False);
4275 - globfree(&globbuf);
4277 + glob_t globbuf;
4278 + int i;
4280 + glob(nameText, GLOB_NOCHECK, NULL, &globbuf);
4281 + for (i = 0; i < (int) globbuf.gl_pathc; i++) {
4282 + DataValue* fileNameArg = (DataValue*) XtMalloc(sizeof(DataValue));
4283 + DataValue* resultDV = (DataValue*) XtMalloc(sizeof(DataValue));
4285 + fileNameArg->tag = STRING_TAG;
4286 + AllocNStringNCpy(&fileNameArg->val.str, globbuf.gl_pathv[i], MAXPATHLEN);
4287 + MacroApplyHook(window, "file_name_hook", 1, fileNameArg, resultDV);
4288 + XtFree((char*) fileNameArg);
4290 + if (ParseFilename(resultDV->val.str.rep, filename, pathname) != 0) {
4291 + XBell(TheDisplay, 0);
4292 + } else {
4293 + EditExistingFile(GetPrefOpenInTab() ? window : NULL, filename,
4294 + pathname, 0, NULL, False, NULL, GetPrefOpenInTab(),
4295 + False);
4297 + XtFree((char*) resultDV);
4299 + globfree(&globbuf);
4301 #endif
4302 CheckCloseDim();
4305 diff --quilt old/source/server.c new/source/server.c
4306 --- old/source/server.c
4307 +++ new/source/server.c
4308 @@ -242,12 +242,10 @@ static void deleteFileOpenProperty2(cons
4310 Atom atom = findFileOpenProperty(filename, pathname);
4311 deleteProperty(&atom);
4316 /* Try to find existing 'FileClosed' property atom for path. */
4317 static Atom findFileClosedProperty(const char* filename,
4318 const char* pathname)
4320 char path[MAXPATHLEN];
4321 @@ -354,11 +352,11 @@ static void processServerCommandString(c
4322 if (!window->filenameSet && !window->fileChanged &&
4323 isLocatedOnDesktop(window, currentDesktop))
4324 break;
4325 if (window == NULL) {
4326 EditNewFile(findWindowOnDesktop(tabbed, currentDesktop), NULL,
4327 - False, NULL, NULL);
4328 + False, NULL, NULL, False);
4329 CheckCloseDim();
4331 else {
4332 RaiseDocument(window);
4333 XMapRaised(TheDisplay, XtWindow(window->shell));
4334 @@ -417,12 +415,13 @@ static void processServerCommandString(c
4335 isLocatedOnDesktop(window, currentDesktop))
4336 break;
4338 if (*doCommand == '\0') {
4339 if (window == NULL) {
4340 - EditNewFile(findWindowOnDesktop(tabbed, currentDesktop),
4341 - NULL, iconicFlag, lmLen==0?NULL:langMode, NULL);
4342 + EditNewFile(findWindowOnDesktop(tabbed, currentDesktop),
4343 + NULL, iconicFlag, lmLen==0?NULL:langMode, NULL,
4344 + False);
4345 } else {
4346 if (iconicFlag)
4347 RaiseDocument(window);
4348 else
4349 RaiseDocumentWindow(window);
4350 diff --quilt old/source/shell.c new/source/shell.c
4351 --- old/source/shell.c
4352 +++ new/source/shell.c
4353 @@ -387,11 +387,12 @@ void DoShellMenuCmd(WindowInfo *window,
4354 if (output == TO_DIALOG) {
4355 outWidget = NULL;
4356 flags |= OUTPUT_TO_DIALOG;
4357 left = right = 0;
4358 } else if (output == TO_NEW_WINDOW) {
4359 - EditNewFile(GetPrefOpenInTab()?inWindow:NULL, NULL, False, NULL, window->path);
4360 + EditNewFile(GetPrefOpenInTab()?inWindow:NULL, NULL, False, NULL,
4361 + window->path, False);
4362 outWidget = WindowList->textArea;
4363 inWindow = WindowList;
4364 left = right = 0;
4365 CheckCloseDim();
4366 } else { /* TO_SAME_WINDOW */
4367 @@ -478,11 +479,11 @@ void AbortShellCommand(WindowInfo *windo
4369 static void issueCommand(WindowInfo *window, const char *command, char *input,
4370 int inputLen, int flags, Widget textW, int replaceLeft,
4371 int replaceRight, int fromMacro)
4373 - int stdinFD, stdoutFD, stderrFD = 0;
4374 + int stdinFD = 0, stdoutFD = 0, stderrFD = 0;
4375 XtAppContext context = XtWidgetToApplicationContext(window->shell);
4376 shellCmdInfo *cmdData;
4377 pid_t childPid;
4379 /* verify consistency of input parameters */
4380 diff --quilt old/source/text.c new/source/text.c
4381 --- old/source/text.c
4382 +++ new/source/text.c
4383 @@ -629,10 +629,17 @@ static XtResource resources[] = {
4384 XtOffset(TextWidget, text.highlightFGPixel), XmRString,
4385 NEDIT_DEFAULT_HI_FG},
4386 {textNhighlightBackground, textCHighlightBackground, XmRPixel,sizeof(Pixel),
4387 XtOffset(TextWidget, text.highlightBGPixel), XmRString,
4388 NEDIT_DEFAULT_HI_BG},
4389 + {textNcursorlineBackground, textCCursorlineBackground, XmRPixel,sizeof(Pixel),
4390 + XtOffset(TextWidget, text.cursorlineBGPixel), XmRString,
4391 + NEDIT_DEFAULT_CURSORLINE_BG},
4392 + {textNshowCursorline, textCshowCursorline, XmRBoolean, sizeof(Boolean),
4393 + XtOffset(TextWidget, text.showCursorline), XmRString, "False"},
4394 + {textNshowScrolltip, textCshowScrolltip, XmRBoolean, sizeof(Boolean),
4395 + XtOffset(TextWidget, text.showScrolltip), XmRString, "False"},
4396 {textNlineNumForeground, textCLineNumForeground, XmRPixel,sizeof(Pixel),
4397 XtOffset(TextWidget, text.lineNumFGPixel), XmRString,
4398 NEDIT_DEFAULT_LINENO_FG},
4399 {textNcursorForeground, textCCursorForeground, XmRPixel,sizeof(Pixel),
4400 XtOffset(TextWidget, text.cursorFGPixel), XmRString,
4401 @@ -641,10 +648,13 @@ static XtResource resources[] = {
4402 XtOffset(TextWidget, text.calltipFGPixel), XmRString,
4403 NEDIT_DEFAULT_CALLTIP_FG},
4404 {textNcalltipBackground, textCcalltipBackground, XmRPixel,sizeof(Pixel),
4405 XtOffset(TextWidget, text.calltipBGPixel), XmRString,
4406 NEDIT_DEFAULT_CALLTIP_BG},
4407 + {textNwrapMarginForeground, textCWrapMarginForeground, XmRPixel,sizeof(Pixel),
4408 + XtOffset(TextWidget, text.wrapMarginFGPixel), XmRString,
4409 + NEDIT_DEFAULT_WRAPMARGIN_FG},
4410 {textNbacklightCharTypes,textCBacklightCharTypes,XmRString,sizeof(XmString),
4411 XtOffset(TextWidget, text.backlightCharTypes), XmRString, NULL},
4412 {textNrows, textCRows, XmRInt,sizeof(int),
4413 XtOffset(TextWidget, text.rows), XmRString, "24"},
4414 {textNcolumns, textCColumns, XmRInt, sizeof(int),
4415 @@ -671,10 +681,12 @@ static XtResource resources[] = {
4416 XtOffset(TextWidget, text.readOnly), XmRString, "False"},
4417 {textNhidePointer, textCHidePointer, XmRBoolean, sizeof(Boolean),
4418 XtOffset(TextWidget, text.hidePointer), XmRString, "False"},
4419 {textNwrapMargin, textCWrapMargin, XmRInt, sizeof(int),
4420 XtOffset(TextWidget, text.wrapMargin), XmRString, "0"},
4421 + {textNshowWrapMargin, textCShowWrapMargin, XmRBoolean, sizeof(Boolean),
4422 + XtOffset(TextWidget, text.showWrapMargin), XmRString, "True"},
4423 {textNhScrollBar, textCHScrollBar, XmRWidget, sizeof(Widget),
4424 XtOffset(TextWidget, text.hScrollBar), XmRString, ""},
4425 {textNvScrollBar, textCVScrollBar, XmRWidget, sizeof(Widget),
4426 XtOffset(TextWidget, text.vScrollBar), XmRString, ""},
4427 {textNlineNumCols, textCLineNumCols, XmRInt, sizeof(int),
4428 @@ -810,24 +822,34 @@ static void initialize(TextWidget reques
4429 buf = BufCreate();
4431 /* Create and initialize the text-display part of the widget */
4432 textLeft = new->text.marginWidth +
4433 (lineNumCols == 0 ? 0 : marginWidth + charWidth * lineNumCols);
4434 - new->text.textD = TextDCreate((Widget)new, new->text.hScrollBar,
4435 - new->text.vScrollBar, textLeft, new->text.marginHeight,
4436 - new->core.width - marginWidth - textLeft,
4437 - new->core.height - new->text.marginHeight * 2,
4438 - lineNumCols == 0 ? 0 : marginWidth,
4439 - lineNumCols == 0 ? 0 : lineNumCols * charWidth,
4440 - buf, new->text.fontStruct, new->core.background_pixel,
4441 - new->primitive.foreground, new->text.selectFGPixel,
4442 - new->text.selectBGPixel, new->text.highlightFGPixel,
4443 - new->text.highlightBGPixel, new->text.cursorFGPixel,
4444 - new->text.lineNumFGPixel,
4445 - new->text.continuousWrap, new->text.wrapMargin,
4446 - new->text.backlightCharTypes, new->text.calltipFGPixel,
4447 - new->text.calltipBGPixel);
4448 + new->text.textD = TextDCreate(
4449 + /* Widgets */
4450 + (Widget)new, new->text.hScrollBar, new->text.vScrollBar,
4451 + /* Positions */
4452 + textLeft, new->text.marginHeight,
4453 + new->core.width - marginWidth - textLeft,
4454 + new->core.height - new->text.marginHeight * 2,
4455 + lineNumCols == 0 ? 0 : marginWidth,
4456 + lineNumCols == 0 ? 0 : lineNumCols * charWidth,
4457 + /* buffer */
4458 + buf,
4459 + /* font */
4460 + new->text.fontStruct,
4461 + /* Pixels */
4462 + new->core.background_pixel, new->primitive.foreground,
4463 + new->text.selectFGPixel, new->text.selectBGPixel,
4464 + new->text.highlightFGPixel, new->text.highlightBGPixel,
4465 + new->text.cursorFGPixel, new->text.lineNumFGPixel,
4466 + new->text.wrapMarginFGPixel, new->text.calltipFGPixel,
4467 + new->text.calltipBGPixel, new->text.cursorlineBGPixel,
4468 + /* misc */
4469 + new->text.continuousWrap, new->text.wrapMargin,
4470 + new->text.showWrapMargin, new->text.backlightCharTypes,
4471 + new->text.showCursorline, new->text.showScrolltip);
4473 /* Add mandatory delimiters blank, tab, and newline to the list of
4474 delimiters. The memory use scheme here is that new values are
4475 always copied, and can therefore be safely freed on subsequent
4476 set-values calls or destroy */
4477 @@ -1121,10 +1143,25 @@ static Boolean setValues(TextWidget curr
4478 if (new->text.wrapMargin != current->text.wrapMargin ||
4479 new->text.continuousWrap != current->text.continuousWrap)
4480 TextDSetWrapMode(current->text.textD, new->text.continuousWrap,
4481 new->text.wrapMargin);
4483 + if (new->text.showWrapMargin != current->text.showWrapMargin)
4484 + TextDSetShowWrapMargin(current->text.textD, new->text.showWrapMargin);
4486 + if (new->text.showCursorline != current->text.showCursorline) {
4487 + current->text.showCursorline = new->text.showCursorline;
4488 + if (current->text.textD)
4490 + current->text.textD->showCursorline = new->text.showCursorline;
4493 + /* jegub
4494 + redraw = True; */
4495 + TextDSetShowCursorline(current->text.textD, new->text.showCursorline);
4498 /* When delimiters are changed, copy the memory, so that the caller
4499 doesn't have to manage it, and add mandatory delimiters blank,
4500 tab, and newline to the list */
4501 if (new->text.delimiters != current->text.delimiters) {
4502 char *delimiters = XtMalloc(strlen(new->text.delimiters) + 4);
4503 @@ -3750,12 +3787,15 @@ static void selectWord(Widget w, int poi
4504 TextWidget tw = (TextWidget)w;
4505 textBuffer *buf = tw->text.textD->buffer;
4506 int x, y, insertPos = TextDGetInsertPosition(tw->text.textD);
4508 TextPosToXY(w, insertPos, &x, &y);
4509 - if (pointerX < x && insertPos > 0 && BufGetCharacter(buf, insertPos-1) != '\n')
4510 - insertPos--;
4511 + if (pointerX < x && insertPos > 0
4512 + && BufGetCharacter(buf, insertPos-1) != '\n')
4514 + insertPos--;
4516 BufSelect(buf, startOfWord(tw, insertPos), endOfWord(tw, insertPos));
4519 static int startOfWord(TextWidget w, int pos)
4521 diff --quilt old/source/text.h new/source/text.h
4522 --- old/source/text.h
4523 +++ new/source/text.h
4524 @@ -51,18 +51,30 @@
4525 #define textCSelectBackground "SelectBackground"
4526 #define textNhighlightForeground "highlightForeground"
4527 #define textCHighlightForeground "HighlightForeground"
4528 #define textNhighlightBackground "highlightBackground"
4529 #define textCHighlightBackground "HighlightBackground"
4531 +#define textNcursorlineBackground "cursorlineBackground"
4532 +#define textCCursorlineBackground "CursorlineBackground"
4534 +#define textNshowCursorline "showCursorline"
4535 +#define textCshowCursorline "ShowCursorline"
4537 +#define textNshowScrolltip "showScrolltip"
4538 +#define textCshowScrolltip "ShowScrolltip"
4540 #define textNcursorForeground "cursorForeground"
4541 #define textCCursorForeground "CursorForeground"
4542 #define textNlineNumForeground "lineNumForeground"
4543 #define textCLineNumForeground "LineNumForeground"
4544 #define textNcalltipForeground "calltipForeground"
4545 #define textCcalltipForeground "CalltipForeground"
4546 #define textNcalltipBackground "calltipBackground"
4547 #define textCcalltipBackground "CalltipBackground"
4548 +#define textNwrapMarginForeground "wrapMarginForeground"
4549 +#define textCWrapMarginForeground "WrapMarginForeground"
4550 #define textNpendingDelete "pendingDelete"
4551 #define textCPendingDelete "PendingDelete"
4552 #define textNhScrollBar "hScrollBar"
4553 #define textCHScrollBar "HScrollBar"
4554 #define textNvScrollBar "vScrollBar"
4555 @@ -93,10 +105,12 @@
4556 #define textCAutoWrap "AutoWrap"
4557 #define textNcontinuousWrap "continuousWrap"
4558 #define textCContinuousWrap "ContinuousWrap"
4559 #define textNwrapMargin "wrapMargin"
4560 #define textCWrapMargin "WrapMargin"
4561 +#define textNshowWrapMargin "showWrapMargin"
4562 +#define textCShowWrapMargin "ShowWrapMargin"
4563 #define textNautoIndent "autoIndent"
4564 #define textCAutoIndent "AutoIndent"
4565 #define textNsmartIndent "smartIndent"
4566 #define textCSmartIndent "SmartIndent"
4567 #define textNoverstrike "overstrike"
4568 diff --quilt old/source/textDisp.c new/source/textDisp.c
4569 --- old/source/textDisp.c
4570 +++ new/source/textDisp.c
4571 @@ -62,41 +62,44 @@ static const char CVSID[] = "$Id: textDi
4572 #include "../debug.h"
4573 #endif
4575 /* Masks for text drawing methods. These are or'd together to form an
4576 integer which describes what drawing calls to use to draw a string */
4577 +#define STYLE_LOOKUP_SHIFT 0
4578 #define FILL_SHIFT 8
4579 #define SECONDARY_SHIFT 9
4580 #define PRIMARY_SHIFT 10
4581 #define HIGHLIGHT_SHIFT 11
4582 -#define STYLE_LOOKUP_SHIFT 0
4583 #define BACKLIGHT_SHIFT 12
4584 +#define RANGESET_SHIFT 20
4585 +#define CURSORLINE_SHIFT 26
4587 #define FILL_MASK (1 << FILL_SHIFT)
4588 #define SECONDARY_MASK (1 << SECONDARY_SHIFT)
4589 #define PRIMARY_MASK (1 << PRIMARY_SHIFT)
4590 #define HIGHLIGHT_MASK (1 << HIGHLIGHT_SHIFT)
4591 #define STYLE_LOOKUP_MASK (0xff << STYLE_LOOKUP_SHIFT)
4592 #define BACKLIGHT_MASK (0xff << BACKLIGHT_SHIFT)
4594 -#define RANGESET_SHIFT (20)
4595 #define RANGESET_MASK (0x3F << RANGESET_SHIFT)
4596 +#define CURSORLINE_MASK (1 << CURSORLINE_SHIFT)
4598 /* If you use both 32-Bit Style mask layout:
4599 Bits +----------------+----------------+----------------+----------------+
4600 hex |1F1E1D1C1B1A1918|1716151413121110| F E D C B A 9 8| 7 6 5 4 3 2 1 0|
4601 dec |3130292827262524|2322212019181716|151413121110 9 8| 7 6 5 4 3 2 1 0|
4602 +----------------+----------------+----------------+----------------+
4603 - Type | r r| r r r r b b b b| b b b b H 1 2 F| s s s s s s s s|
4604 + Type | c r r| r r r r b b b b| b b b b H 1 2 F| s s s s s s s s|
4605 +----------------+----------------+----------------+----------------+
4606 - where: s - style lookup value (8 bits)
4607 + where:
4608 + s - style lookup value (8 bits)
4609 F - fill (1 bit)
4610 2 - secondary selection (1 bit)
4611 1 - primary selection (1 bit)
4612 H - highlight (1 bit)
4613 b - backlighting index (8 bits)
4614 r - rangeset index (6 bits)
4615 + c - cursorline coloring (1 bit)
4616 This leaves 6 "unused" bits */
4618 /* Maximum displayable line length (how many characters will fit across the
4619 widest window). This amount of memory is temporarily allocated from the
4620 stack in the redisplayLine routine for drawing strings */
4621 @@ -113,10 +116,12 @@ static void offsetLineStarts(textDisp *t
4622 static void calcLineStarts(textDisp *textD, int startLine, int endLine);
4623 static void calcLastChar(textDisp *textD);
4624 static int posToVisibleLineNum(textDisp *textD, int pos, int *lineNum);
4625 static void redisplayLine(textDisp *textD, int visLineNum, int leftClip,
4626 int rightClip, int leftCharIndex, int rightCharIndex);
4627 +static void redisplayLineCur(textDisp *textD, int visLineNum, int leftClip,
4628 + int rightClip, int leftCharIndex, int rightCharIndex, Boolean curLine);
4629 static void drawString(textDisp *textD, int style, int x, int y, int toX,
4630 char *string, int nChars);
4631 static void clearRect(textDisp *textD, GC gc, int x, int y,
4632 int width, int height);
4633 static void drawCursor(textDisp *textD, int x, int y);
4634 @@ -147,11 +152,12 @@ static int countLines(const char *string
4635 static int measureVisLine(textDisp *textD, int visLineNum);
4636 static int emptyLinesVisible(textDisp *textD);
4637 static void blankCursorProtrusions(textDisp *textD);
4638 static void allocateFixedFontGCs(textDisp *textD, XFontStruct *fontStruct,
4639 Pixel bgPixel, Pixel fgPixel, Pixel selectFGPixel, Pixel selectBGPixel,
4640 - Pixel highlightFGPixel, Pixel highlightBGPixel, Pixel lineNumFGPixel);
4641 + Pixel highlightFGPixel, Pixel highlightBGPixel, Pixel lineNumFGPixel,
4642 + Pixel wrapMarginFGPixel, Pixel cursorlineBGPixel);
4643 static GC allocateGC(Widget w, unsigned long valueMask,
4644 unsigned long foreground, unsigned long background, Font font,
4645 unsigned long dynamicMask, unsigned long dontCareMask);
4646 static void releaseGC(Widget w, GC gc);
4647 static void resetClipRectangles(textDisp *textD);
4648 @@ -177,19 +183,24 @@ static void resetAbsLineNum(textDisp *te
4649 static int measurePropChar(const textDisp* textD, const char c,
4650 const int colNum, const int pos);
4651 static Pixel allocBGColor(Widget w, char *colorName, int *ok);
4652 static Pixel getRangesetColor(textDisp *textD, int ind, Pixel bground);
4653 static void textDRedisplayRange(textDisp *textD, int start, int end);
4654 +static void drawWrapMargin(textDisp* textD);
4655 +static void redisplayCursor(textDisp* textD);
4657 textDisp *TextDCreate(Widget widget, Widget hScrollBar, Widget vScrollBar,
4658 Position left, Position top, Position width, Position height,
4659 - Position lineNumLeft, Position lineNumWidth, textBuffer *buffer,
4660 - XFontStruct *fontStruct, Pixel bgPixel, Pixel fgPixel,
4661 - Pixel selectFGPixel, Pixel selectBGPixel, Pixel highlightFGPixel,
4662 - Pixel highlightBGPixel, Pixel cursorFGPixel, Pixel lineNumFGPixel,
4663 - int continuousWrap, int wrapMargin, XmString bgClassString,
4664 - Pixel calltipFGPixel, Pixel calltipBGPixel)
4665 + Position lineNumLeft, Position lineNumWidth,
4666 + textBuffer *buffer,
4667 + XFontStruct *fontStruct,
4668 + Pixel bgPixel, Pixel fgPixel, Pixel selectFGPixel, Pixel selectBGPixel,
4669 + Pixel highlightFGPixel, Pixel highlightBGPixel, Pixel cursorFGPixel,
4670 + Pixel lineNumFGPixel, Pixel wrapMarginFGPixel, Pixel calltipFGPixel,
4671 + Pixel calltipBGPixel, Pixel cursorlineBGPixel,
4672 + int continuousWrap, int wrapMargin, Boolean showWrapMargin,
4673 + XmString bgClassString, Boolean showCursorline, Boolean showScrolltip)
4675 textDisp *textD;
4676 XGCValues gcValues;
4677 int i;
4679 @@ -230,29 +241,34 @@ textDisp *TextDCreate(Widget widget, Wid
4680 textD->selectFGPixel = selectFGPixel;
4681 textD->highlightFGPixel = highlightFGPixel;
4682 textD->selectBGPixel = selectBGPixel;
4683 textD->highlightBGPixel = highlightBGPixel;
4684 textD->lineNumFGPixel = lineNumFGPixel;
4685 + textD->wrapMarginFGPixel = wrapMarginFGPixel;
4686 textD->cursorFGPixel = cursorFGPixel;
4687 textD->wrapMargin = wrapMargin;
4688 textD->continuousWrap = continuousWrap;
4689 + textD->showWrapMargin = showWrapMargin;
4690 + textD->cursorlineBGPixel = cursorlineBGPixel;
4691 allocateFixedFontGCs(textD, fontStruct, bgPixel, fgPixel, selectFGPixel,
4692 - selectBGPixel, highlightFGPixel, highlightBGPixel, lineNumFGPixel);
4693 + selectBGPixel, highlightFGPixel, highlightBGPixel, lineNumFGPixel,
4694 + wrapMarginFGPixel, cursorlineBGPixel);
4695 textD->styleGC = allocateGC(textD->w, 0, 0, 0, fontStruct->fid,
4696 GCClipMask|GCForeground|GCBackground, GCArcMode);
4697 textD->lineNumLeft = lineNumLeft;
4698 textD->lineNumWidth = lineNumWidth;
4699 textD->nVisibleLines = (height - 1) / (textD->ascent + textD->descent) + 1;
4700 gcValues.foreground = cursorFGPixel;
4701 textD->cursorFGGC = XtGetGC(widget, GCForeground, &gcValues);
4702 textD->lineStarts = (int *)XtMalloc(sizeof(int) * textD->nVisibleLines);
4703 textD->lineStarts[0] = 0;
4704 - textD->calltipW = NULL;
4705 - textD->calltipShell = NULL;
4706 + textD->calltip.widget = NULL;
4707 textD->calltip.ID = 0;
4708 textD->calltipFGPixel = calltipFGPixel;
4709 textD->calltipBGPixel = calltipBGPixel;
4710 + textD->showScrolltip = showScrolltip;
4711 + textD->scrolltip = NULL;
4712 for (i=1; i<textD->nVisibleLines; i++)
4713 textD->lineStarts[i] = -1;
4714 textD->bgClassPixel = NULL;
4715 textD->bgClass = NULL;
4716 TextDSetupBGClasses(widget, bgClassString, &textD->bgClassPixel,
4717 @@ -260,10 +276,13 @@ textDisp *TextDCreate(Widget widget, Wid
4718 textD->suppressResync = 0;
4719 textD->nLinesDeleted = 0;
4720 textD->modifyingTabDist = 0;
4721 textD->pointerHidden = False;
4722 textD->graphicsExposeQueue = NULL;
4723 + textD->showCursorline = showCursorline;
4724 + textD->oldCursorPos = 0;
4725 + textD->oldLineStart = 0;
4727 /* Attach an event handler to the widget so we can know the visibility
4728 (used for choosing the fastest drawing method) */
4729 XtAddEventHandler(widget, VisibilityChangeMask, False,
4730 visibilityEH, textD);
4731 @@ -316,13 +335,18 @@ void TextDFree(textDisp *textD)
4732 releaseGC(textD->w, textD->highlightGC);
4733 releaseGC(textD->w, textD->selectBGGC);
4734 releaseGC(textD->w, textD->highlightBGGC);
4735 releaseGC(textD->w, textD->styleGC);
4736 releaseGC(textD->w, textD->lineNumGC);
4737 + releaseGC(textD->w, textD->wrapMarginGC);
4738 + releaseGC(textD->w, textD->cursorlineGC);
4739 + releaseGC(textD->w, textD->cursorlineBGGC);
4741 XtFree((char *)textD->lineStarts);
4742 while (TextDPopGraphicExposeQueueEntry(textD)) {
4745 XtFree((char *)textD->bgClassPixel);
4746 XtFree((char *)textD->bgClass);
4747 XtFree((char *)textD);
4750 @@ -380,11 +404,12 @@ void TextDAttachHighlightData(textDisp *
4753 /* Change the (non syntax-highlit) colors */
4754 void TextDSetColors(textDisp *textD, Pixel textFgP, Pixel textBgP,
4755 Pixel selectFgP, Pixel selectBgP, Pixel hiliteFgP, Pixel hiliteBgP,
4756 - Pixel lineNoFgP, Pixel cursorFgP)
4757 + Pixel lineNoFgP, Pixel cursorFgP, Pixel wrapMarginFgP,
4758 + Pixel cursorlineBgP)
4760 XGCValues values;
4761 Display *d = XtDisplay(textD->w);
4763 /* Update the stored pixels */
4764 @@ -394,19 +419,24 @@ void TextDSetColors(textDisp *textD, Pix
4765 textD->selectBGPixel = selectBgP;
4766 textD->highlightFGPixel = hiliteFgP;
4767 textD->highlightBGPixel = hiliteBgP;
4768 textD->lineNumFGPixel = lineNoFgP;
4769 textD->cursorFGPixel = cursorFgP;
4770 + textD->wrapMarginFGPixel = wrapMarginFgP;
4771 + textD->cursorlineBGPixel = cursorlineBgP;
4773 releaseGC(textD->w, textD->gc);
4774 releaseGC(textD->w, textD->selectGC);
4775 releaseGC(textD->w, textD->selectBGGC);
4776 releaseGC(textD->w, textD->highlightGC);
4777 releaseGC(textD->w, textD->highlightBGGC);
4778 releaseGC(textD->w, textD->lineNumGC);
4779 + releaseGC(textD->w, textD->wrapMarginGC);
4780 + releaseGC(textD->w, textD->cursorlineBGGC);
4781 allocateFixedFontGCs(textD, textD->fontStruct, textBgP, textFgP, selectFgP,
4782 - selectBgP, hiliteFgP, hiliteBgP, lineNoFgP);
4783 + selectBgP, hiliteFgP, hiliteBgP, lineNoFgP, wrapMarginFgP,
4784 + cursorlineBgP);
4786 /* Change the cursor GC (the cursor GC is not shared). */
4787 values.foreground = cursorFgP;
4788 XChangeGC( d, textD->cursorFGGC, GCForeground, &values );
4790 @@ -414,20 +444,32 @@ void TextDSetColors(textDisp *textD, Pix
4791 TextDRedisplayRect(textD, textD->left, textD->top, textD->width,
4792 textD->height);
4793 redrawLineNumbers(textD, True);
4796 +void TextDSetShowCursorline(textDisp* textD, const Boolean showCursorline)
4798 + textD->showCursorline = showCursorline;
4800 + /* Redisplay */
4801 + TextDRedisplayRect(textD, textD->left, textD->top, textD->width,
4802 + textD->height);
4803 + redrawLineNumbers(textD, True);
4807 ** Change the (non highlight) font
4809 void TextDSetFont(textDisp *textD, XFontStruct *fontStruct)
4811 Display *display = XtDisplay(textD->w);
4812 int i, maxAscent = fontStruct->ascent, maxDescent = fontStruct->descent;
4813 int width, height, fontWidth;
4814 Pixel bgPixel, fgPixel, selectFGPixel, selectBGPixel;
4815 Pixel highlightFGPixel, highlightBGPixel, lineNumFGPixel;
4816 + Pixel wrapMarginFGPixel;
4817 + Pixel cursorlineBGPixel;
4818 XGCValues values;
4819 XFontStruct *styleFont;
4821 /* If font size changes, cursor will be redrawn in a new position */
4822 blankCursorProtrusions(textD);
4823 @@ -475,20 +517,30 @@ void TextDSetFont(textDisp *textD, XFont
4824 selectFGPixel = values.foreground;
4825 selectBGPixel = values.background;
4826 XGetGCValues(display, textD->highlightGC,GCForeground|GCBackground,&values);
4827 highlightFGPixel = values.foreground;
4828 highlightBGPixel = values.background;
4829 + XGetGCValues(display, textD->cursorlineGC,
4830 + GCForeground|GCBackground, &values);
4831 + cursorlineBGPixel = values.background;
4832 XGetGCValues(display, textD->lineNumGC, GCForeground, &values);
4833 lineNumFGPixel = values.foreground;
4834 + XGetGCValues(display, textD->wrapMarginGC, GCForeground, &values);
4835 + wrapMarginFGPixel = values.foreground;
4837 releaseGC(textD->w, textD->gc);
4838 releaseGC(textD->w, textD->selectGC);
4839 releaseGC(textD->w, textD->highlightGC);
4840 releaseGC(textD->w, textD->selectBGGC);
4841 releaseGC(textD->w, textD->highlightBGGC);
4842 releaseGC(textD->w, textD->lineNumGC);
4843 + releaseGC(textD->w, textD->wrapMarginGC);
4844 + releaseGC(textD->w, textD->cursorlineGC);
4845 + releaseGC(textD->w, textD->cursorlineBGGC);
4846 allocateFixedFontGCs(textD, fontStruct, bgPixel, fgPixel, selectFGPixel,
4847 - selectBGPixel, highlightFGPixel, highlightBGPixel, lineNumFGPixel);
4848 + selectBGPixel, highlightFGPixel, highlightBGPixel, lineNumFGPixel,
4849 + wrapMarginFGPixel, cursorlineBGPixel);
4850 XSetFont(display, textD->styleGC, fontStruct->fid);
4852 /* Do a full resize to force recalculation of font related parameters */
4853 width = textD->width;
4854 height = textD->height;
4855 @@ -642,10 +694,13 @@ void TextDRedisplayRect(textDisp *textD,
4856 redisplayLine(textD, line, left, left+width, 0, INT_MAX);
4858 /* draw the line numbers if exposed area includes them */
4859 if (textD->lineNumWidth != 0 && left <= textD->lineNumLeft + textD->lineNumWidth)
4860 redrawLineNumbers(textD, False);
4862 + /* draw wrap margin incase it got erased */
4863 + drawWrapMargin(textD);
4867 ** Refresh all of the text between buffer positions "start" and "end"
4868 ** not including the character at the position "end".
4869 @@ -654,11 +709,11 @@ void TextDRedisplayRect(textDisp *textD,
4870 ** any range of characters.
4872 static void textDRedisplayRange(textDisp *textD, int start, int end)
4874 int i, startLine, lastLine, startIndex, endIndex;
4877 /* If the range is outside of the displayed text, just return */
4878 if (end < textD->firstChar || (start > textD->lastChar &&
4879 !emptyLinesVisible(textD)))
4880 return;
4882 @@ -711,23 +766,103 @@ static void textDRedisplayRange(textDisp
4883 resetClipRectangles(textD);
4885 /* If the starting and ending lines are the same, redisplay the single
4886 line between "start" and "end" */
4887 if (startLine == lastLine) {
4888 + /* Add one to endIndex to catch the caret at the end of a range. */
4889 redisplayLine(textD, startLine, 0, INT_MAX, startIndex, endIndex);
4890 - return;
4892 + if (-1 != textD->lineStarts[startLine] ||
4893 + (BufCountDispChars(textD->buffer, textD->lineStarts[startLine],
4894 + start) <= textD->wrapMargin &&
4895 + BufCountDispChars(textD->buffer, textD->lineStarts[startLine],
4896 + end) >= textD->wrapMargin))
4898 + /* redraw wrap margin if it got erased */
4899 + drawWrapMargin(textD);
4901 + } else {
4902 + /* Redisplay the first line from "start" */
4903 + redisplayLine(textD, startLine, 0, INT_MAX, startIndex, INT_MAX);
4905 + /* Redisplay the lines in between at their full width */
4906 + for (i = startLine+1; i < lastLine; i++) {
4907 + redisplayLine(textD, i, 0, INT_MAX, 0, INT_MAX);
4910 + /* Redisplay the last line to "end". Add one to the endIndex to catch
4911 + the caret at the end of a range. */
4912 + redisplayLine(textD, lastLine, 0, INT_MAX, 0, endIndex);
4914 + /* redraw wrap margin */
4915 + drawWrapMargin(textD);
4918 - /* Redisplay the first line from "start" */
4919 - redisplayLine(textD, startLine, 0, INT_MAX, startIndex, INT_MAX);
4921 - /* Redisplay the lines in between at their full width */
4922 - for (i=startLine+1; i<lastLine; i++)
4923 - redisplayLine(textD, i, 0, INT_MAX, 0, INT_MAX);
4926 - /* Redisplay the last line to "end" */
4927 - redisplayLine(textD, lastLine, 0, INT_MAX, 0, endIndex);
4929 +** Custom version of TextDRedisplayRange that only updates the area around
4930 +** the cursor.
4932 +static void redisplayCursor(textDisp* textD)
4934 + int cursorLine, lineStart, start, end, startIndex, endIndex;
4935 + int pos = textD->cursorPos;
4936 + Boolean cursorLineChanged;
4938 + /* If the cursor is outside of the displayed text, just return */
4939 + if (pos + 1 < textD->firstChar || pos - 1 > textD->lastChar) {
4940 + return;
4943 + if (!posToVisibleLineNum(textD, pos, &cursorLine)) {
4944 + /* At first sight, this can only be reached when redisplayCursor()
4945 + is miscalled or when the catch above didn't work. There is at
4946 + least one situation though which makes the catch helpless: If
4947 + your caret is in the last line, column 1 and you move it down,
4948 + textD->cursorPos will be changed *before* this function is
4949 + called, the automatic scroll will be done after. */
4950 + return;
4953 + /* Find the position right before and after the cursor,
4954 + but make sure that we stay on the same line. */
4955 + lineStart = TextDStartOfLine(textD, pos);
4956 + start = max(lineStart, pos - 1);
4957 + end = min(pos + 1, TextDEndOfLine(textD, lineStart, True) + 1);
4959 + /* Get the starting and ending positions within the line. */
4960 + startIndex = start - lineStart;
4961 + endIndex = end - lineStart;
4963 + /* Reset the clipping rectangles for the drawing GCs which are shared
4964 + using XtAllocateGC, and may have changed since the last use */
4965 + resetClipRectangles(textD);
4967 + /* jegub */
4968 + cursorLineChanged = (textD->oldCursorPos != textD->cursorPos
4969 + || textD->oldLineStart != lineStart);
4971 + redisplayLine(textD, cursorLine, 0, INT_MAX, startIndex, endIndex);
4973 + /* jegub */
4974 + if (cursorLineChanged) {
4975 + /* Hairline destroyed in old cursor line! Redraw neccessary. */
4976 + drawWrapMargin(textD);
4977 + return;
4980 + if (BufCountDispChars(textD->buffer, lineStart, end) < textD->wrapMargin) {
4981 + /* hairline is off-screen, most common case */
4982 + return;
4985 + if (BufCountDispChars(textD->buffer, lineStart, start)
4986 + > textD->wrapMargin) {
4987 + return;
4990 + drawWrapMargin(textD);
4994 ** Set the scroll position of the text display vertically by line number and
4995 ** horizontally by pixel offset from the left margin
4996 @@ -769,12 +904,14 @@ void TextDGetScroll(textDisp *textD, int
4997 ** Set the position of the text insertion cursor for text display "textD"
4999 void TextDSetInsertPosition(textDisp *textD, int newPos)
5001 /* make sure new position is ok, do nothing if it hasn't changed */
5002 - if (newPos == textD->cursorPos)
5003 - return;
5004 + if (newPos == textD->cursorPos) {
5005 + return;
5008 if (newPos < 0) newPos = 0;
5009 if (newPos > textD->buffer->length) newPos = textD->buffer->length;
5011 /* cursor movement cancels vertical cursor motion column */
5012 textD->cursorPreferredCol = -1;
5013 @@ -783,37 +920,45 @@ void TextDSetInsertPosition(textDisp *te
5014 TextDBlankCursor(textD);
5016 /* draw it at its new position */
5017 textD->cursorPos = newPos;
5018 textD->cursorOn = True;
5019 - textDRedisplayRange(textD, textD->cursorPos-1, textD->cursorPos + 1);
5021 + redisplayCursor(textD);
5023 + /* We have to force redraw of the hairline here: The hairline will be
5024 + erased if the cursorline changes, but will not be redrawn by
5025 + redisplayCursor() (only works on the area immedietely surrounding
5026 + the cursor). */
5027 + drawWrapMargin(textD);
5030 void TextDBlankCursor(textDisp *textD)
5032 if (!textD->cursorOn)
5033 return;
5035 blankCursorProtrusions(textD);
5036 textD->cursorOn = False;
5037 - textDRedisplayRange(textD, textD->cursorPos-1, textD->cursorPos+1);
5038 + redisplayCursor(textD);
5041 void TextDUnblankCursor(textDisp *textD)
5043 if (!textD->cursorOn) {
5044 textD->cursorOn = True;
5045 - textDRedisplayRange(textD, textD->cursorPos-1, textD->cursorPos+1);
5046 + redisplayCursor(textD);
5050 void TextDSetCursorStyle(textDisp *textD, int style)
5052 textD->cursorStyle = style;
5053 blankCursorProtrusions(textD);
5054 - if (textD->cursorOn) {
5055 - textDRedisplayRange(textD, textD->cursorPos-1, textD->cursorPos + 1);
5056 + if (textD->cursorOn)
5058 + redisplayCursor(textD);
5062 void TextDSetWrapMode(textDisp *textD, int wrap, int wrapMargin)
5064 @@ -845,10 +990,19 @@ void TextDSetWrapMode(textDisp *textD, i
5065 /* Do a full redraw */
5066 TextDRedisplayRect(textD, 0, textD->top, textD->width + textD->left,
5067 textD->height);
5070 +void TextDSetShowWrapMargin(textDisp* textD, int state)
5072 + textD->showWrapMargin = state;
5074 + /* Do a full redraw */
5075 + TextDRedisplayRect(textD, 0, textD->top, textD->width + textD->left,
5076 + textD->height);
5079 int TextDGetInsertPosition(textDisp *textD)
5081 return textD->cursorPos;
5084 @@ -1341,15 +1495,15 @@ int TextDMoveDown(textDisp *textD, int a
5087 column = textD->cursorPreferredCol >= 0
5088 ? textD->cursorPreferredCol
5089 : BufCountDispChars(textD->buffer, lineStartPos, textD->cursorPos);
5091 - if (absolute)
5092 + if (absolute) {
5093 nextLineStartPos = BufCountForwardNLines(textD->buffer, lineStartPos, 1);
5094 - else
5095 + } else {
5096 nextLineStartPos = TextDCountForwardNLines(textD, lineStartPos, 1, True);
5099 newPos = BufCountForwardDispChars(textD->buffer, nextLineStartPos, column);
5101 if (textD->continuousWrap && !absolute) {
5102 newPos = min(newPos, TextDEndOfLine(textD, nextLineStartPos, True));
5103 @@ -1520,11 +1674,11 @@ static void bufModifiedCB(int pos, int n
5104 textDisp *textD = (textDisp *)cbArg;
5105 textBuffer *buf = textD->buffer;
5106 int oldFirstChar = textD->firstChar;
5107 int scrolled, origCursorPos = textD->cursorPos;
5108 int wrapModStart, wrapModEnd;
5111 /* buffer modification cancels vertical cursor motion column */
5112 if (nInserted != 0 || nDeleted != 0)
5113 textD->cursorPreferredCol = -1;
5115 /* Count the number of lines inserted and deleted, and in the case
5116 @@ -1745,14 +1899,29 @@ static int posToVisibleLineNum(textDisp
5117 ** "leftClip" and "rightClip" window coordinates and "leftCharIndex" and
5118 ** "rightCharIndex" character positions (not including the character at
5119 ** position "rightCharIndex").
5121 ** The cursor is also drawn if it appears on the line.
5123 +** The function actually forwards to redisplayLineCur(), passing the
5124 +** showCursorline setting as appropriate.
5126 static void redisplayLine(textDisp *textD, int visLineNum, int leftClip,
5127 int rightClip, int leftCharIndex, int rightCharIndex)
5129 + redisplayLineCur(textD, visLineNum, leftClip, rightClip, leftCharIndex,
5130 + rightCharIndex, textD->showCursorline);
5134 +** The meat of redisplayLine() is handled here. The extra curLine parameter
5135 +** tells redisplayLineCur() whether it should attempt to reset the previous
5136 +** "current line" to a non-current line state.
5138 +static void redisplayLineCur(textDisp* textD, int visLineNum, int leftClip,
5139 + int rightClip, int leftCharIndex, int rightCharIndex, Boolean curLine)
5141 textBuffer *buf = textD->buffer;
5142 int i, x, y, startX, charIndex, lineStartPos, lineLen, fontHeight;
5143 int stdCharWidth, charWidth, startIndex, charStyle, style;
5144 int charLen, outStartIndex, outIndex, cursorX = 0, hasCursor = False;
5145 int dispIndexOffset, cursorPos = textD->cursorPos, y_orig;
5146 @@ -1784,10 +1953,104 @@ static void redisplayLine(textDisp *text
5147 } else {
5148 lineLen = visLineLength(textD, visLineNum);
5149 lineStr = BufGetRange(buf, lineStartPos, lineStartPos + lineLen);
5152 + /* handle case of leftCharIndex == rightCharIndex */
5153 + if (leftCharIndex == rightCharIndex) {
5154 + if (lineStartPos + leftCharIndex == cursorPos)
5156 + /* we're at the cursor position */
5157 + if (leftCharIndex > 0)
5158 + --leftCharIndex;
5159 + if (rightCharIndex < lineLen)
5160 + ++rightCharIndex;
5161 + if (rightCharIndex >= lineLen)
5162 + rightCharIndex = INT_MAX;
5163 + } else {
5164 + /* hmm: not sure what gets us here, but it happens - redraw line */
5165 + leftCharIndex = 0;
5166 + rightCharIndex = INT_MAX;
5167 + return;
5171 + /* for cursorline tracking, if this is the current line, check it against
5172 + the last cursorline - if different, we need to display the whole line
5173 + plus anything to the extreme right */
5174 + if (curLine
5175 + && (textD->oldCursorPos != cursorPos
5176 + || textD->oldLineStart != lineStartPos)) {
5177 + int oldCursor = textD->oldCursorPos;
5178 + int lineEndPos = lineStartPos + lineLen;
5179 + int oldLineStart = textD->oldLineStart;
5180 + int gotLineCurdiff = -1;
5181 + /* store new values if we need to call redisplayLine() again */
5182 + textD->oldCursorPos = cursorPos;
5184 + if (lineStartPos <= cursorPos
5185 + && cursorPos <= lineEndPos
5186 + && !(lineStartPos <= oldCursor
5187 + && oldCursor <= lineEndPos)) {
5188 + /* find visible line number for oldCursor */
5189 + int lineNum, startPos = -1, oldLen, endPos;
5190 + int gotLine = -1;
5192 + for (lineNum = 0; lineNum < textD->nVisibleLines; lineNum++) {
5193 + startPos = textD->lineStarts[lineNum];
5194 + if (startPos >= 0) {
5195 + oldLen = visLineLength(textD, lineNum);
5196 + endPos = startPos + oldLen;
5197 + if (startPos >= 0
5198 + && startPos <= oldCursor && oldCursor <= endPos) {
5199 + gotLine = lineNum;
5200 + break;
5205 + if (gotLine >= 0 && gotLine != visLineNum) {
5206 + redisplayLineCur(textD, gotLine, 0, INT_MAX, 0, INT_MAX, False);
5207 + gotLineCurdiff = gotLine;
5210 + /* right: that was the old line done - now the current line */
5211 + leftCharIndex = 0;
5212 + rightCharIndex = INT_MAX;
5214 + /* only update oldLineStart if cursor has moved */
5215 + textD->oldLineStart = lineStartPos;
5218 + if (lineStartPos != oldLineStart) {
5219 + /* find visible line number for oldLineStart */
5220 + int lineNum;
5221 + int gotLine = -1;
5223 + for (lineNum = 0; lineNum < textD->nVisibleLines; lineNum++) {
5224 + if (textD->lineStarts[lineNum] == oldLineStart) {
5225 + gotLine = lineNum;
5226 + break;
5230 + if (gotLine >= 0
5231 + && gotLine != visLineNum
5232 + && gotLineCurdiff != gotLine) {
5233 + redisplayLineCur(textD, gotLine, 0, INT_MAX, 0, INT_MAX, False);
5236 + /* right: that was the old line done - now the current line */
5237 + leftCharIndex = 0;
5238 + rightCharIndex = INT_MAX;
5240 + /* jegub */
5241 + /* only update oldLineStart if cursor has moved */
5242 + textD->oldLineStart = lineStartPos;
5246 /* Space beyond the end of the line is still counted in units of characters
5247 of a standardized character width (this is done mostly because style
5248 changes based on character position can still occur in this region due
5249 to rectangular selections). stdCharWidth must be non-zero to prevent a
5250 potential infinite loop if x does not advance */
5251 @@ -1949,11 +2212,12 @@ static void drawString(textDisp *textD,
5252 XGCValues gcValues;
5253 XFontStruct *fs = textD->fontStruct;
5254 Pixel bground = textD->bgPixel;
5255 Pixel fground = textD->fgPixel;
5256 int underlineStyle = FALSE;
5258 + int cursorline_mask = textD->showCursorline ? CURSORLINE_MASK : 0;
5260 /* Don't draw if widget isn't realized */
5261 if (XtWindow(textD->w) == 0)
5262 return;
5264 /* select a GC */
5265 @@ -1966,16 +2230,20 @@ static void drawString(textDisp *textD,
5267 else if (style & PRIMARY_MASK) {
5268 gc = textD->selectGC;
5269 bgGC = textD->selectBGGC;
5271 + else if (style & cursorline_mask) {
5272 + gc = textD->cursorlineGC;
5273 + bgGC = textD->cursorlineBGGC;
5275 else {
5276 gc = bgGC = textD->gc;
5279 + /* Syntax highlighting, backlighting and rangesets need a bit more work.*/
5280 if (gc == textD->styleGC) {
5281 - /* we have work to do */
5282 styleTableEntry *styleRec;
5283 /* Set font, color, and gc depending on style. For normal text, GCs
5284 for normal drawing, or drawing within a selection or highlight are
5285 pre-allocated and pre-configured. For syntax highlighting, GCs are
5286 configured here, on the fly. */
5287 @@ -1990,24 +2258,27 @@ static void drawString(textDisp *textD,
5288 else {
5289 styleRec = NULL;
5290 gcValues.font = fs->fid;
5291 fground = textD->fgPixel;
5293 - /* Background color priority order is:
5294 - 1 Primary(Selection), 2 Highlight(Parens),
5295 - 3 Rangeset, 4 SyntaxHighlightStyle,
5296 - 5 Backlight (if NOT fill), 6 DefaultBackground */
5297 + /* Background color priority order is:
5298 + 1. PRIMARY (selection)
5299 + 2. Highlight (flash matching parens)
5300 + 3. Rangeset
5301 + 4. SyntaxHighlightStyle
5302 + 5. Cursorline
5303 + 6. Backlight (if NOT fill)
5304 + 7. DefaultBackground */
5305 bground =
5306 style & PRIMARY_MASK ? textD->selectBGPixel :
5307 style & HIGHLIGHT_MASK ? textD->highlightBGPixel :
5308 - style & RANGESET_MASK ?
5309 - getRangesetColor(textD,
5310 - (style&RANGESET_MASK)>>RANGESET_SHIFT,
5311 - bground) :
5312 + style & RANGESET_MASK ? getRangesetColor(textD,
5313 + (style&RANGESET_MASK)>>RANGESET_SHIFT, bground) :
5314 styleRec && styleRec->bgColorName ? styleRec->bgColor :
5315 + style & cursorline_mask ? textD->cursorlineBGPixel :
5316 (style & BACKLIGHT_MASK) && !(style & FILL_MASK) ?
5317 - textD->bgClassPixel[(style>>BACKLIGHT_SHIFT) & 0xff] :
5318 + textD->bgClassPixel[(style>>BACKLIGHT_SHIFT) & 0xff] :
5319 textD->bgPixel;
5320 if (fground == bground) /* B&W kludge */
5321 fground = textD->bgPixel;
5322 /* set up gc for clearing using the foreground color entry */
5323 gcValues.foreground = gcValues.background = bground;
5324 @@ -2159,10 +2430,11 @@ static void drawCursor(textDisp *textD,
5325 static int styleOfPos(textDisp *textD, int lineStartPos,
5326 int lineLen, int lineIndex, int dispIndex, int thisChar)
5328 textBuffer *buf = textD->buffer;
5329 textBuffer *styleBuf = textD->styleBuffer;
5330 + int cursorPos = textD->cursorPos;
5331 int pos, style = 0;
5333 if (lineStartPos == -1 || buf == NULL)
5334 return FILL_MASK;
5336 @@ -2180,10 +2452,12 @@ static int styleOfPos(textDisp *textD, i
5338 if (inSelection(&buf->primary, pos, lineStartPos, dispIndex))
5339 style |= PRIMARY_MASK;
5340 if (inSelection(&buf->highlight, pos, lineStartPos, dispIndex))
5341 style |= HIGHLIGHT_MASK;
5342 + if (lineStartPos <= cursorPos && cursorPos <= lineStartPos + lineLen)
5343 + style |= CURSORLINE_MASK;
5344 if (inSelection(&buf->secondary, pos, lineStartPos, dispIndex))
5345 style |= SECONDARY_MASK;
5346 /* store in the RANGESET_MASK portion of style the rangeset index for pos */
5347 if (buf->rangesetTable) {
5348 int rangesetIndex = RangesetIndex1ofPos(buf->rangesetTable, pos, True);
5349 @@ -2720,12 +2994,13 @@ static void setScroll(textDisp *textD, i
5351 else if (xOffset < 0) {
5352 TextDRedisplayRect(textD, textD->left + textD->width + xOffset,
5353 textD->top, -xOffset, textD->height);
5356 /* Restore protruding parts of the cursor */
5357 - textDRedisplayRange(textD, textD->cursorPos-1, textD->cursorPos+1);
5358 + redisplayCursor(textD);
5361 /* Refresh line number/calltip display if its up and we've scrolled
5362 vertically */
5363 if (lineDelta != 0) {
5364 @@ -2886,14 +3161,34 @@ static void redrawLineNumbers(textDisp *
5366 static void vScrollCB(Widget w, XtPointer clientData, XtPointer callData)
5368 textDisp *textD = (textDisp *)clientData;
5369 int newValue = ((XmScrollBarCallbackStruct *)callData)->value;
5370 + int reason = ((XmScrollBarCallbackStruct*) callData)->reason;
5371 int lineDelta = newValue - textD->topLineNum;
5373 - if (lineDelta == 0)
5375 + if (0 == lineDelta) {
5376 + KillScrolltip(textD);
5377 return;
5380 + /* lineDelta is always != 0 for XmCR_DRAG */
5381 + /* Scrolltip does not work for continuous wrap. The only way to get the
5382 + line number is through textDisp->absTopLineNum, but this value is very
5383 + inaccurate for large files. So no tip. */
5384 + if (XmCR_DRAG == reason && !textD->continuousWrap && textD->showScrolltip) {
5385 + /* Display a scrolltip showing the line number about one third down
5386 + from the top, the position a search jumps to. */
5387 + XEvent* event = ((XmScrollBarCallbackStruct*) callData)->event;
5388 + XMotionEvent* motionEvent = (XMotionEvent*) event;
5389 + char valueBuffer[TYPE_INT_STR_SIZE(int)];
5391 + sprintf(valueBuffer, "%i", newValue + (textD->nVisibleLines / 3));
5392 + ShowScrolltip(textD, valueBuffer, motionEvent->x_root - 50,
5393 + motionEvent->y_root);
5396 setScroll(textD, newValue, textD->horizOffset, False, True);
5398 static void hScrollCB(Widget w, XtPointer clientData, XtPointer callData)
5400 textDisp *textD = (textDisp *)clientData;
5401 @@ -3008,11 +3303,12 @@ static void blankCursorProtrusions(textD
5402 ** Allocate shared graphics contexts used by the widget, which must be
5403 ** re-allocated on a font change.
5405 static void allocateFixedFontGCs(textDisp *textD, XFontStruct *fontStruct,
5406 Pixel bgPixel, Pixel fgPixel, Pixel selectFGPixel, Pixel selectBGPixel,
5407 - Pixel highlightFGPixel, Pixel highlightBGPixel, Pixel lineNumFGPixel)
5408 + Pixel highlightFGPixel, Pixel highlightBGPixel, Pixel lineNumFGPixel,
5409 + Pixel wrapMarginFGPixel, Pixel cursorlineBGPixel)
5411 textD->gc = allocateGC(textD->w, GCFont | GCForeground | GCBackground,
5412 fgPixel, bgPixel, fontStruct->fid, GCClipMask, GCArcMode);
5413 textD->selectGC = allocateGC(textD->w, GCFont | GCForeground | GCBackground,
5414 selectFGPixel, selectBGPixel, fontStruct->fid, GCClipMask,
5415 @@ -3022,13 +3318,20 @@ static void allocateFixedFontGCs(textDis
5416 textD->highlightGC = allocateGC(textD->w, GCFont|GCForeground|GCBackground,
5417 highlightFGPixel, highlightBGPixel, fontStruct->fid, GCClipMask,
5418 GCArcMode);
5419 textD->highlightBGGC = allocateGC(textD->w, GCForeground, highlightBGPixel,
5420 0, fontStruct->fid, GCClipMask, GCArcMode);
5421 + textD->cursorlineGC = allocateGC(textD->w, GCFont|GCForeground|GCBackground,
5422 + fgPixel, cursorlineBGPixel, fontStruct->fid, GCClipMask,
5423 + GCArcMode);
5424 + textD->cursorlineBGGC = allocateGC(textD->w, GCForeground,
5425 + cursorlineBGPixel, 0, fontStruct->fid, GCClipMask, GCArcMode);
5426 textD->lineNumGC = allocateGC(textD->w, GCFont | GCForeground |
5427 GCBackground, lineNumFGPixel, bgPixel, fontStruct->fid,
5428 GCClipMask, GCArcMode);
5429 + textD->wrapMarginGC = allocateGC(textD->w, GCForeground | GCBackground,
5430 + wrapMarginFGPixel, bgPixel, fontStruct->fid, GCClipMask, GCArcMode);
5434 ** X11R4 does not have the XtAllocateGC function for sharing graphics contexts
5435 ** with changeable fields. Unfortunately the R4 call for creating shared
5436 @@ -3097,10 +3400,16 @@ static void resetClipRectangles(textDisp
5437 &clipRect, 1, Unsorted);
5438 XSetClipRectangles(display, textD->highlightBGGC, 0, 0,
5439 &clipRect, 1, Unsorted);
5440 XSetClipRectangles(display, textD->styleGC, 0, 0,
5441 &clipRect, 1, Unsorted);
5442 + XSetClipRectangles(display, textD->cursorlineGC, 0, 0,
5443 + &clipRect, 1, Unsorted);
5444 + XSetClipRectangles(display, textD->cursorlineBGGC, 0, 0,
5445 + &clipRect, 1, Unsorted);
5446 + XSetClipRectangles(display, textD->wrapMarginGC, 0, 0,
5447 + &clipRect, 1, Unsorted);
5451 ** Return the length of a line (number of displayable characters) by examining
5452 ** entries in the line starts array rather than by scanning for newlines
5453 @@ -3800,5 +4109,47 @@ void TextDSetupBGClasses(Widget w, XmStr
5454 return;
5456 memcpy(*pp_bgClass, bgClass, 256);
5457 memcpy(*pp_bgClassPixel, bgClassPixel, class_no * sizeof (Pixel));
5461 +** Draw wrap margin if requested
5463 +static void drawWrapMargin(textDisp *textD)
5465 + int fromX, fromY;
5466 + int fontHeight, lineHeight;
5469 + /* attempt to draw the wrap margin # only if
5470 + - widget has been realized
5471 + - font width is not -1, ie. not using different/proportional width fonts
5472 + - show wrap margins is enabled */
5473 + if (XtWindow(textD->w) != 0
5474 + && textD->fixedFontWidth != -1
5475 + && textD->showWrapMargin)
5477 + fromX = textD->left + (textD->fixedFontWidth * textD->wrapMargin)
5478 + - textD->horizOffset - 1;
5480 + /* compute rest of coordinates if line is to right of left margin */
5481 + if (fromX > textD->left)
5483 + fromY = textD->top;
5484 + fontHeight = textD->ascent + textD->descent;
5485 + lineHeight = textD->nVisibleLines * fontHeight - 1;
5486 + XDrawLine(XtDisplay(textD->w), XtWindow(textD->w),
5487 + textD->wrapMarginGC, fromX, fromY, fromX,
5488 + fromY + lineHeight);
5490 + Handle to move wrap margin around with the mouse.
5491 + XDrawLine(XtDisplay(textD->w), XtWindow(textD->w),
5492 + textD->wrapMarginGC, fromX - 1, fromY, fromX - 1,
5493 + fromY + 3);
5494 + XDrawLine(XtDisplay(textD->w), XtWindow(textD->w),
5495 + textD->wrapMarginGC, fromX + 1, fromY, fromX + 1,
5496 + fromY + 3);
5501 diff --quilt old/source/textDisp.h new/source/textDisp.h
5502 --- old/source/textDisp.h
5503 +++ new/source/textDisp.h
5504 @@ -72,10 +72,11 @@ typedef struct _calltipStruct {
5505 Boolean anchored; /* Is it anchored to a position */
5506 int pos; /* Position tip is anchored to */
5507 int hAlign; /* horizontal alignment */
5508 int vAlign; /* vertical alignment */
5509 int alignMode; /* Strict or sloppy alignment */
5510 + Widget widget; /* calltip's widget */
5511 } calltipStruct;
5513 typedef struct _textDisp {
5514 Widget w;
5515 int top, left, width, height, lineNumLeft, lineNumWidth;
5516 @@ -101,17 +102,21 @@ typedef struct _textDisp {
5517 either to a newline or one character
5518 beyond the end of the buffer) */
5519 int continuousWrap; /* Wrap long lines when displaying */
5520 int wrapMargin; /* Margin in # of char positions for
5521 wrapping in continuousWrap mode */
5522 + int showWrapMargin; /* draw line at wrap margin */
5523 int *lineStarts;
5524 - int topLineNum; /* Line number of top displayed line
5525 - of file (first line of file is 1) */
5526 - int absTopLineNum; /* In continuous wrap mode, the line
5527 - number of the top line if the text
5528 - were not wrapped (note that this is
5529 - only maintained as needed). */
5530 + int topLineNum; /* Almost the line number of top displayed line
5531 + of file (first line of file is 1). Actually
5532 + it's off by one screenful or so most of the
5533 + times. */
5534 + int absTopLineNum; /* In continuous wrap mode, almost the line
5535 + number of the top line if the text were not
5536 + wrapped. Actually it's off by one screenful
5537 + most of the times. (Note that this is only
5538 + maintained as needed). */
5539 int needAbsTopLineNum; /* Externally settable flag to continue
5540 maintaining absTopLineNum even if
5541 it isn't needed for line # display */
5542 int horizOffset; /* Horizontal scroll pos. in pixels */
5543 int visibility; /* Window visibility (see XVisibility event) */
5544 @@ -127,12 +132,15 @@ typedef struct _textDisp {
5545 int ascent, descent; /* Composite ascent and descent for
5546 primary font + all-highlight fonts */
5547 int fixedFontWidth; /* Font width if all current fonts are
5548 fixed and match in width, else -1 */
5549 Widget hScrollBar, vScrollBar;
5550 - GC gc, selectGC, highlightGC; /* GCs for drawing text */
5551 - GC selectBGGC, highlightBGGC; /* GCs for erasing text */
5552 + int oldCursorPos;
5553 + int oldLineStart;
5554 + Pixel cursorlineBGPixel;
5555 + GC gc, selectGC, highlightGC, cursorlineGC; /* GCs for drawing text */
5556 + GC selectBGGC, highlightBGGC, cursorlineBGGC; /* GCs for erasing text */
5557 GC cursorFGGC; /* GC for drawing the cursor */
5558 GC lineNumGC; /* GC for drawing line numbers */
5559 GC styleGC; /* GC with color and font unspecified
5560 for drawing colored/styled text */
5561 Pixel fgPixel, bgPixel; /* Foreground/Background colors */
5562 @@ -143,15 +151,15 @@ typedef struct _textDisp {
5563 Pixel lineNumFGPixel; /* Color for drawing line numbers */
5564 Pixel cursorFGPixel;
5565 Pixel *bgClassPixel; /* table of colors for each BG class */
5566 unsigned char *bgClass; /* obtains index into bgClassPixel[] */
5568 - Widget calltipW; /* The Label widget for the calltip */
5569 - Widget calltipShell; /* The Shell that holds the calltip */
5570 calltipStruct calltip; /* The info for the calltip itself */
5571 Pixel calltipFGPixel;
5572 Pixel calltipBGPixel;
5573 + Pixel wrapMarginFGPixel; /* color for drawing wrap margin */
5574 + GC wrapMarginGC; /* GC for drawing wrap margin */
5575 int suppressResync; /* Suppress resynchronization of line
5576 starts during buffer updates */
5577 int nLinesDeleted; /* Number of lines deleted during
5578 buffer modification (only used
5579 when resynchronization is
5580 @@ -159,28 +167,36 @@ typedef struct _textDisp {
5581 int modifyingTabDist; /* Whether tab distance is being
5582 modified */
5583 Boolean pointerHidden; /* true if the mouse pointer is
5584 hidden */
5585 graphicExposeTranslationEntry *graphicsExposeQueue;
5586 + Boolean showCursorline;
5587 + Boolean showScrolltip;
5588 + Widget scrolltip;
5589 } textDisp;
5591 textDisp *TextDCreate(Widget widget, Widget hScrollBar, Widget vScrollBar,
5592 - Position left, Position top, Position width, Position height,
5593 - Position lineNumLeft, Position lineNumWidth, textBuffer *buffer,
5594 - XFontStruct *fontStruct, Pixel bgPixel, Pixel fgPixel,
5595 - Pixel selectFGPixel, Pixel selectBGPixel, Pixel highlightFGPixel,
5596 - Pixel highlightBGPixel, Pixel cursorFGPixel, Pixel lineNumFGPixel,
5597 - int continuousWrap, int wrapMargin, XmString bgClassString,
5598 - Pixel calltipFGPixel, Pixel calltipBGPixel);
5599 + Position left, Position top, Position width, Position height,
5600 + Position lineNumLeft, Position lineNumWidth,
5601 + textBuffer *buffer,
5602 + XFontStruct *fontStruct,
5603 + Pixel bgPixel, Pixel fgPixel, Pixel selectFGPixel, Pixel selectBGPixel,
5604 + Pixel highlightFGPixel, Pixel highlightBGPixel, Pixel cursorFGPixel,
5605 + Pixel lineNumFGPixel, Pixel wrapMarginFGPixel, Pixel calltipFGPixel,
5606 + Pixel calltipBGPixel, Pixel cursorlineBGPixel,
5607 + int continuousWrap, int wrapMargin, Boolean showWrapMargin,
5608 + XmString bgClassString, Boolean showCursorline, Boolean showScrolltip);
5609 void TextDFree(textDisp *textD);
5610 void TextDSetBuffer(textDisp *textD, textBuffer *buffer);
5611 void TextDAttachHighlightData(textDisp *textD, textBuffer *styleBuffer,
5612 styleTableEntry *styleTable, int nStyles, char unfinishedStyle,
5613 unfinishedStyleCBProc unfinishedHighlightCB, void *cbArg);
5614 void TextDSetColors(textDisp *textD, Pixel textFgP, Pixel textBgP,
5615 Pixel selectFgP, Pixel selectBgP, Pixel hiliteFgP, Pixel hiliteBgP,
5616 - Pixel lineNoFgP, Pixel cursorFgP);
5617 + Pixel lineNoFgP, Pixel cursorFgP, Pixel wrapMarginFgP,
5618 + Pixel cursorlineBgP);
5619 +void TextDSetShowCursorline(textDisp* textD, const Boolean showCursorline);
5620 void TextDSetFont(textDisp *textD, XFontStruct *fontStruct);
5621 int TextDMinFontWidth(textDisp *textD, Boolean considerStyles);
5622 int TextDMaxFontWidth(textDisp *textD, Boolean considerStyles);
5623 void TextDResize(textDisp *textD, int width, int height);
5624 void TextDRedisplayRect(textDisp *textD, int left, int top, int width,
5625 @@ -208,10 +224,11 @@ int TextDMoveUp(textDisp *textD, int abs
5626 int TextDMoveDown(textDisp *textD, int absolute);
5627 void TextDBlankCursor(textDisp *textD);
5628 void TextDUnblankCursor(textDisp *textD);
5629 void TextDSetCursorStyle(textDisp *textD, int style);
5630 void TextDSetWrapMode(textDisp *textD, int wrap, int wrapMargin);
5631 +void TextDSetShowWrapMargin(textDisp *textD, int state);
5632 int TextDEndOfLine(const textDisp* textD, const int pos,
5633 const Boolean startPosIsLineStart);
5634 int TextDStartOfLine(const textDisp* textD, const int pos);
5635 int TextDCountForwardNLines(const textDisp* textD, const int startPos,
5636 const unsigned nLines, const Boolean startPosIsLineStart);
5637 diff --quilt old/source/textP.h new/source/textP.h
5638 --- old/source/textP.h
5639 +++ new/source/textP.h
5640 @@ -57,10 +57,12 @@ extern TextClassRec nTextClassRec;
5642 typedef struct _TextPart {
5643 /* resources */
5644 Pixel selectFGPixel, selectBGPixel, highlightFGPixel, highlightBGPixel;
5645 Pixel cursorFGPixel, lineNumFGPixel, calltipFGPixel, calltipBGPixel;
5646 + Pixel wrapMarginFGPixel;
5647 + Pixel cursorlineBGPixel;
5648 XFontStruct *fontStruct;
5649 Boolean pendingDelete;
5650 Boolean autoShowInsertPos;
5651 Boolean autoWrap;
5652 Boolean autoWrapPastedText;
5653 @@ -69,14 +71,17 @@ typedef struct _TextPart {
5654 Boolean smartIndent;
5655 Boolean overstrike;
5656 Boolean heavyCursor;
5657 Boolean readOnly;
5658 Boolean hidePointer;
5659 + Boolean showCursorline;
5660 + Boolean showScrolltip;
5661 int rows, columns;
5662 int marginWidth, marginHeight;
5663 int cursorBlinkRate;
5664 int wrapMargin;
5665 + Boolean showWrapMargin;
5666 int emulateTabs;
5667 int lineNumCols;
5668 char *delimiters;
5669 Cardinal cursorVPadding;
5670 Widget hScrollBar, vScrollBar;
5671 diff --quilt old/source/window.c new/source/window.c
5672 --- old/source/window.c
5673 +++ new/source/window.c
5674 @@ -6,11 +6,11 @@ static const char CVSID[] = "$Id: window
5675 * Copyright (C) 1999 Mark Edel *
5677 * This is free software; you can redistribute it and/or modify it under the *
5678 * terms of the GNU General Public License as published by the Free Software *
5679 * Foundation; either version 2 of the License, or (at your option) any later *
5680 -* version. In addition, you may distribute version of this program linked to *
5681 +* version. In addition, you may distribute versions of this program linked to *
5682 * Motif or Open Motif. See README for details. *
5684 * This software is distributed in the hope that it will be useful, but WITHOUT *
5685 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
5686 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
5687 @@ -167,10 +167,11 @@ static void showStats(WindowInfo *window
5688 static void showISearch(WindowInfo *window, int state);
5689 static void showStatsForm(WindowInfo *window);
5690 static void addToWindowList(WindowInfo *window);
5691 static void removeFromWindowList(WindowInfo *window);
5692 static void focusCB(Widget w, WindowInfo *window, XtPointer callData);
5693 +static void loosingFocusCB(Widget w, WindowInfo *window, XtPointer callData);
5694 static void modifiedCB(int pos, int nInserted, int nDeleted, int nRestyled,
5695 const char *deletedText, void *cbArg);
5696 static void movedCB(Widget w, WindowInfo *window, XtPointer callData);
5697 static void dragStartCB(Widget w, WindowInfo *window, XtPointer callData);
5698 static void dragEndCB(Widget w, WindowInfo *window, dragEndCBStruct *callData);
5699 @@ -257,19 +258,22 @@ WindowInfo *CreateWindow(const char *nam
5700 window->fileMissing = True;
5701 strcpy(window->filename, name);
5702 window->undo = NULL;
5703 window->redo = NULL;
5704 window->nPanes = 0;
5705 + window->lastFocus = NULL;
5706 window->autoSaveCharCount = 0;
5707 window->autoSaveOpCount = 0;
5708 window->undoOpCount = 0;
5709 window->undoMemUsed = 0;
5710 CLEAR_ALL_LOCKS(window->lockReasons);
5711 + window->transient = False;
5712 window->indentStyle = GetPrefAutoIndent(PLAIN_LANGUAGE_MODE);
5713 window->autoSave = GetPrefAutoSave();
5714 window->saveOldVersion = GetPrefSaveOldVersion();
5715 window->wrapMode = GetPrefWrap(PLAIN_LANGUAGE_MODE);
5716 + window->showWrapMargin = GetPrefShowWrapMargin();
5717 window->overstrike = False;
5718 window->showMatchingStyle = GetPrefShowMatching();
5719 window->matchSyntaxBased = GetPrefMatchSyntaxBased();
5720 window->showStats = GetPrefStatsLine();
5721 window->showISearchLine = GetPrefISearchLine();
5722 @@ -465,11 +469,12 @@ WindowInfo *CreateWindow(const char *nam
5724 window->iSearchRegexToggle = XtVaCreateManagedWidget("iSearchREToggle",
5725 xmToggleButtonWidgetClass, window->iSearchForm,
5726 XmNlabelString, s1=XmStringCreateSimple("RegExp"),
5727 XmNset, GetPrefSearch() == SEARCH_REGEX_NOCASE
5728 - || GetPrefSearch() == SEARCH_REGEX,
5729 + || GetPrefSearch() == SEARCH_REGEX
5730 + || GetPrefSearch() == SEARCH_REGEX_SMARTCASE,
5731 XmNtopAttachment, XmATTACH_FORM,
5732 XmNbottomAttachment, XmATTACH_FORM,
5733 XmNtopOffset, 1, /* see openmotif note above */
5734 XmNrightAttachment, XmATTACH_WIDGET,
5735 XmNrightWidget, window->iSearchCaseToggle,
5736 @@ -695,23 +700,25 @@ WindowInfo *CreateWindow(const char *nam
5737 text = createTextArea(pane, window, rows,cols,
5738 GetPrefEmTabDist(PLAIN_LANGUAGE_MODE), GetPrefDelimiters(),
5739 GetPrefWrapMargin(), window->showLineNumbers?MIN_LINE_NUM_COLS:0);
5740 XtManageChild(text);
5741 window->textArea = text;
5742 - window->lastFocus = text;
5743 + ChangeLastFocus(window, text);
5745 /* Set the initial colors from the globals. */
5746 SetColors(window,
5747 GetPrefColorName(TEXT_FG_COLOR ),
5748 GetPrefColorName(TEXT_BG_COLOR ),
5749 GetPrefColorName(SELECT_FG_COLOR),
5750 GetPrefColorName(SELECT_BG_COLOR),
5751 GetPrefColorName(HILITE_FG_COLOR),
5752 GetPrefColorName(HILITE_BG_COLOR),
5753 GetPrefColorName(LINENO_FG_COLOR),
5754 - GetPrefColorName(CURSOR_FG_COLOR));
5756 + GetPrefColorName(CURSOR_FG_COLOR),
5757 + GetPrefColorName(WRAPMARGIN_FG_COLOR),
5758 + GetPrefColorName(CURSORLINE_BG_COLOR));
5760 /* Create the right button popup menu (note: order is important here,
5761 since the translation for popping up this menu was probably already
5762 added in createTextArea, but CreateBGMenu requires window->textArea
5763 to be set so it can attach the menu to it (because menu shells are
5764 finicky about the kinds of widgets they are attached to)) */
5765 @@ -1214,14 +1221,15 @@ void SplitPane(WindowInfo *window)
5766 newTextD = ((TextWidget)text)->text.textD;
5767 XtVaSetValues(text,
5768 XmNforeground, textD->fgPixel,
5769 XmNbackground, textD->bgPixel,
5770 NULL);
5771 - TextDSetColors( newTextD, textD->fgPixel, textD->bgPixel,
5772 - textD->selectFGPixel, textD->selectBGPixel, textD->highlightFGPixel,
5773 - textD->highlightBGPixel, textD->lineNumFGPixel,
5774 - textD->cursorFGPixel );
5775 + TextDSetColors(newTextD, textD->fgPixel, textD->bgPixel,
5776 + textD->selectFGPixel, textD->selectBGPixel,
5777 + textD->highlightFGPixel, textD->highlightBGPixel,
5778 + textD->lineNumFGPixel, textD->cursorFGPixel,
5779 + textD->wrapMarginFGPixel, textD->cursorlineBGPixel);
5781 /* Set the minimum pane height in the new pane */
5782 UpdateMinPaneHeights(window);
5784 /* adjust the heights, scroll positions, etc., to split the focus pane */
5785 @@ -1292,11 +1300,11 @@ void ClosePane(WindowInfo *window)
5787 short paneHeights[MAX_PANES+1];
5788 int insertPositions[MAX_PANES+1], topLines[MAX_PANES+1];
5789 int horizOffsets[MAX_PANES+1];
5790 int i, focusPane;
5791 - Widget text;
5792 + Widget text = NULL;
5794 /* Don't delete the last pane */
5795 if (window->nPanes <= 0)
5796 return;
5798 @@ -1322,14 +1330,19 @@ void ClosePane(WindowInfo *window)
5799 the remaining panes, simply detroying it didn't seem enough */
5800 window->nPanes--;
5801 XtUnmanageChild(containingPane(window->textPanes[window->nPanes]));
5802 XtDestroyWidget(containingPane(window->textPanes[window->nPanes]));
5804 - if (window->nPanes == 0)
5805 - window->lastFocus = window->textArea;
5806 - else if (focusPane > window->nPanes)
5807 - window->lastFocus = window->textPanes[window->nPanes-1];
5808 + if (window->nPanes == 0) {
5809 + text = window->textArea;
5810 + } else if (focusPane > window->nPanes) {
5811 + text = window->textPanes[window->nPanes - 1];
5812 + } else {
5813 + text = window->textPanes[focusPane - 1];
5816 + ChangeLastFocus(window, text);
5818 /* adjust the heights, scroll positions, etc., to make it look
5819 like the pane with the input focus was closed */
5820 for (i=focusPane; i<=window->nPanes; i++) {
5821 insertPositions[i] = insertPositions[i+1];
5822 @@ -1853,11 +1866,12 @@ void SetFonts(WindowInfo *window, const
5823 UpdateMinPaneHeights(window);
5826 void SetColors(WindowInfo *window, const char *textFg, const char *textBg,
5827 const char *selectFg, const char *selectBg, const char *hiliteFg,
5828 - const char *hiliteBg, const char *lineNoFg, const char *cursorFg)
5829 + const char *hiliteBg, const char *lineNoFg, const char *cursorFg,
5830 + const char* wrapMarginFg, const char* cursorlineBg)
5832 int i, dummy;
5833 Pixel textFgPix = AllocColor( window->textArea, textFg,
5834 &dummy, &dummy, &dummy),
5835 textBgPix = AllocColor( window->textArea, textBg,
5836 @@ -1871,30 +1885,36 @@ void SetColors(WindowInfo *window, const
5837 hiliteBgPix = AllocColor( window->textArea, hiliteBg,
5838 &dummy, &dummy, &dummy),
5839 lineNoFgPix = AllocColor( window->textArea, lineNoFg,
5840 &dummy, &dummy, &dummy),
5841 cursorFgPix = AllocColor( window->textArea, cursorFg,
5842 + &dummy, &dummy, &dummy),
5843 + wrapMarginFgPix = AllocColor( window->textArea, wrapMarginFg,
5844 + &dummy, &dummy, &dummy),
5845 + cursorlineBgPix = AllocColor( window->textArea, cursorlineBg,
5846 &dummy, &dummy, &dummy);
5847 textDisp *textD;
5849 /* Update the main pane */
5850 XtVaSetValues(window->textArea,
5851 XmNforeground, textFgPix,
5852 XmNbackground, textBgPix,
5853 NULL);
5854 textD = ((TextWidget)window->textArea)->text.textD;
5855 TextDSetColors( textD, textFgPix, textBgPix, selectFgPix, selectBgPix,
5856 - hiliteFgPix, hiliteBgPix, lineNoFgPix, cursorFgPix );
5857 + hiliteFgPix, hiliteBgPix, lineNoFgPix, cursorFgPix,
5858 + wrapMarginFgPix, cursorlineBgPix);
5859 /* Update any additional panes */
5860 for (i=0; i<window->nPanes; i++) {
5861 XtVaSetValues(window->textPanes[i],
5862 XmNforeground, textFgPix,
5863 XmNbackground, textBgPix,
5864 NULL);
5865 textD = ((TextWidget)window->textPanes[i])->text.textD;
5866 TextDSetColors( textD, textFgPix, textBgPix, selectFgPix, selectBgPix,
5867 - hiliteFgPix, hiliteBgPix, lineNoFgPix, cursorFgPix );
5868 + hiliteFgPix, hiliteBgPix, lineNoFgPix, cursorFgPix,
5869 + wrapMarginFgPix, cursorlineBgPix);
5872 /* Redo any syntax highlighting */
5873 if (window->highlightData != NULL)
5874 UpdateHighlightStyles(window);
5875 @@ -1926,15 +1946,18 @@ void SetAutoWrap(WindowInfo *window, int
5876 for (i=0; i<window->nPanes; i++)
5877 XtVaSetValues(window->textPanes[i], textNautoWrap, autoWrap,
5878 textNcontinuousWrap, contWrap, NULL);
5879 window->wrapMode = state;
5881 - if (IsTopDocument(window)) {
5882 - XmToggleButtonSetState(window->newlineWrapItem, autoWrap, False);
5883 - XmToggleButtonSetState(window->continuousWrapItem, contWrap, False);
5884 - XmToggleButtonSetState(window->noWrapItem, state == NO_WRAP, False);
5885 + if (IsTopDocument(window))
5887 + XmToggleButtonSetState(window->newlineWrapItem, autoWrap, False);
5888 + XmToggleButtonSetState(window->continuousWrapItem, contWrap, False);
5889 + XmToggleButtonSetState(window->noWrapItem, state == NO_WRAP, False);
5892 + SetShowWrapMargin(window, window->showWrapMargin);
5896 ** Set the auto-scroll margin
5898 @@ -1946,10 +1969,37 @@ void SetAutoScroll(WindowInfo *window, i
5899 for (i=0; i<window->nPanes; i++)
5900 XtVaSetValues(window->textPanes[i], textNcursorVPadding, margin, NULL);
5904 +** Set show-wrap-margin style, one of NEVER, ALWAYS, ON-WRAP
5906 +void SetShowWrapMargin(WindowInfo* window, int state)
5908 + int i;
5909 + int alwaysShowWrapMargin = (SHOW_WRAP_MARGIN_ALWAYS == state);
5910 + int onWrapShowWrapMargin = (SHOW_WRAP_MARGIN_ON_WRAP == state);
5911 + int autoWrap = (NEWLINE_WRAP == window->wrapMode);
5912 + int contWrap = (CONTINUOUS_WRAP == window->wrapMode);
5913 + /* true or false only. not never/always/on-wrap. text widget does need to know
5914 + exact details. it just needs to know that wrap margin should be shown */
5915 + int showWrapMargin = (alwaysShowWrapMargin
5916 + || (onWrapShowWrapMargin && autoWrap)
5917 + || (onWrapShowWrapMargin && contWrap));
5919 + XtVaSetValues(window->textArea, textNshowWrapMargin, showWrapMargin, NULL);
5920 + for (i = 0; i < window->nPanes; i++) {
5921 + XtVaSetValues(window->textPanes[i],
5922 + textNshowWrapMargin, showWrapMargin,
5923 + NULL);
5925 + /* never/always/on-wrap needs to be stored in window settings, for generating
5926 + menu, etc */
5927 + window->showWrapMargin = state;
5931 ** Recover the window pointer from any widget in the window, by searching
5932 ** up the widget hierarcy for the top level container widget where the
5933 ** window pointer is stored in the userData field. In a tabbed window,
5934 ** this is the window pointer of the top (active) document, which is
5935 ** returned if w is 'shell-level' widget - menus, find/replace dialogs, etc.
5936 @@ -2203,10 +2253,19 @@ void MakeSelectionVisible(WindowInfo *wi
5937 static Widget createTextArea(Widget parent, WindowInfo *window, int rows,
5938 int cols, int emTabDist, char *delimiters, int wrapMargin,
5939 int lineNumCols)
5941 Widget text, sw, hScrollBar, vScrollBar, frame;
5942 + int alwaysShowWrapMargin = (window->showWrapMargin == SHOW_WRAP_MARGIN_ALWAYS);
5943 + int onWrapShowWrapMargin = (window->showWrapMargin == SHOW_WRAP_MARGIN_ON_WRAP);
5944 + int autoWrap = (window->wrapMode == NEWLINE_WRAP);
5945 + int contWrap = (window->wrapMode == CONTINUOUS_WRAP);
5946 + /* true or false only. not never/always/on-wrap. text widget does need to know
5947 + exact details. it just needs to know that wrap margin should be shown */
5948 + int showWrapMargin = (alwaysShowWrapMargin ||
5949 + (onWrapShowWrapMargin && autoWrap) ||
5950 + (onWrapShowWrapMargin && contWrap) );
5952 /* Create a text widget inside of a scrolled window widget */
5953 sw = XtVaCreateManagedWidget("scrolledW", xmScrolledWindowWidgetClass,
5954 parent, XmNpaneMaximum, SHRT_MAX,
5955 XmNpaneMinimum, PANE_MIN_HEIGHT, XmNhighlightThickness, 0, NULL);
5956 @@ -2226,24 +2285,29 @@ static Widget createTextArea(Widget pare
5957 textNfont, GetDefaultFontStruct(window->fontList),
5958 textNhScrollBar, hScrollBar, textNvScrollBar, vScrollBar,
5959 textNreadOnly, IS_ANY_LOCKED(window->lockReasons),
5960 textNwordDelimiters, delimiters,
5961 textNwrapMargin, wrapMargin,
5962 + textNshowWrapMargin, showWrapMargin,
5963 textNautoIndent, window->indentStyle == AUTO_INDENT,
5964 textNsmartIndent, window->indentStyle == SMART_INDENT,
5965 textNautoWrap, window->wrapMode == NEWLINE_WRAP,
5966 textNcontinuousWrap, window->wrapMode == CONTINUOUS_WRAP,
5967 textNoverstrike, window->overstrike,
5968 + textNshowCursorline, False,
5969 textNhidePointer, (Boolean) GetPrefTypingHidesPointer(),
5970 textNcursorVPadding, GetVerticalAutoScroll(),
5971 + textNshowScrolltip, GetPrefShowScrolltip(),
5972 NULL);
5974 XtVaSetValues(sw, XmNworkWindow, frame, XmNhorizontalScrollBar,
5975 hScrollBar, XmNverticalScrollBar, vScrollBar, NULL);
5977 /* add focus, drag, cursor tracking, and smart indent callbacks */
5978 XtAddCallback(text, textNfocusCallback, (XtCallbackProc)focusCB, window);
5979 + XtAddCallback(text, textNlosingFocusCallback,
5980 + (XtCallbackProc) loosingFocusCB, window);
5981 XtAddCallback(text, textNcursorMovementCallback, (XtCallbackProc)movedCB,
5982 window);
5983 XtAddCallback(text, textNdragStartCallback, (XtCallbackProc)dragStartCB,
5984 window);
5985 XtAddCallback(text, textNdragEndCallback, (XtCallbackProc)dragEndCB,
5986 @@ -2292,18 +2356,20 @@ static void movedCB(Widget w, WindowInfo
5987 if (0 != textWidget->text.cursorBlinkProcID)
5989 /* Start blinking the caret again. */
5990 ResetCursorBlink(textWidget, False);
5993 + MacroApplyHook(window, "cursor_moved_hook", 0, NULL, NULL);
5996 static void modifiedCB(int pos, int nInserted, int nDeleted, int nRestyled,
5997 const char *deletedText, void *cbArg)
5999 WindowInfo *window = (WindowInfo *)cbArg;
6000 int selected = window->buffer->primary.selected;
6003 /* update the table of bookmarks */
6004 if (!window->ignoreModify) {
6005 UpdateMarkTable(window, pos, nInserted, nDeleted);
6008 @@ -2363,25 +2429,34 @@ static void modifiedCB(int pos, int nIns
6009 /* Update # of bytes, and line and col statistics */
6010 UpdateStatsLine(window);
6012 /* Check if external changes have been made to file and warn user */
6013 CheckForChangesToFile(window);
6015 + MacroApplyHook(window, "modified_hook", 0, NULL, NULL);
6018 static void focusCB(Widget w, WindowInfo *window, XtPointer callData)
6020 /* record which window pane last had the keyboard focus */
6021 - window->lastFocus = w;
6022 + ChangeLastFocus(window, w);
6024 /* update line number statistic to reflect current focus pane */
6025 UpdateStatsLine(window);
6027 /* finish off the current incremental search */
6028 EndISearch(window);
6030 /* Check for changes to read-only status and/or file modifications */
6031 CheckForChangesToFile(window);
6033 + MacroApplyHook(window, "focus_hook", 0, NULL, NULL);
6036 +static void loosingFocusCB(Widget w, WindowInfo *window, XtPointer callData)
6038 + MacroApplyHook(window, "loosing_focus_hook", 0, NULL, NULL);
6041 static void dragStartCB(Widget w, WindowInfo *window, XtPointer callData)
6043 /* don't record all of the intermediate drag steps for undo */
6044 @@ -2519,20 +2594,25 @@ void AttachSessionMgrHandler(Widget appS
6045 ** on the shell window. I think this is the most reliable way to tell,
6046 ** but if someone has a better idea please send me a note).
6048 int IsIconic(WindowInfo *window)
6050 - unsigned long *property = NULL;
6051 + /* We expect back a CARD32 (see ICCCM 4.1.3.1) so we use type long to
6052 + get enough room for it, even if it's casted down later on. */
6053 + unsigned long* property = NULL;
6054 unsigned long nItems;
6055 unsigned long leftover;
6056 static Atom wmStateAtom = 0;
6057 Atom actualType;
6058 int actualFormat;
6059 int result;
6061 - if (wmStateAtom == 0)
6062 - wmStateAtom = XInternAtom(XtDisplay(window->shell), "WM_STATE", False);
6063 + if (0 == wmStateAtom) {
6064 + /* Get Atom for WM_STATE, create if it does not exist. */
6065 + wmStateAtom = XInternAtom(XtDisplay(window->shell), "WM_STATE", False);
6068 if (XGetWindowProperty(XtDisplay(window->shell), XtWindow(window->shell),
6069 wmStateAtom, 0L, 1L, False, wmStateAtom, &actualType, &actualFormat,
6070 &nItems, &leftover, (unsigned char **)&property) != Success ||
6071 nItems != 1 || property == NULL)
6072 return FALSE;
6073 @@ -2699,11 +2779,19 @@ void UpdateStatsLine(WindowInfo *window)
6074 if (!TextPosToLineAndCol(window->lastFocus, pos, &line, &colNum)) {
6075 sprintf(string, "%s%s%s %d bytes", window->path, window->filename,
6076 format, window->buffer->length);
6077 sprintf(slinecol, "L: --- C: ---");
6078 } else {
6079 - sprintf(slinecol, "L: %d C: %d", line, colNum);
6080 + int start, end, isRect, rectStart, rectEnd, bytesSelected = 0;
6081 + if (BufGetSelectionPos(window->buffer, &start, &end, &isRect, &rectStart, &rectEnd)) {
6082 + bytesSelected = isRect ? 0 : end - start;
6084 + if (bytesSelected > 0) {
6085 + sprintf(slinecol, "[%d] L: %d C: %2d", bytesSelected, line, colNum);
6086 + } else {
6087 + sprintf(slinecol, "L: %d C: %2d", line, colNum);
6089 if (window->showLineNumbers)
6090 sprintf(string, "%s%s%s byte %d of %d", window->path,
6091 window->filename, format, pos,
6092 window->buffer->length);
6093 else
6094 @@ -3276,19 +3364,22 @@ WindowInfo* CreateDocument(WindowInfo* s
6095 window->lastModTime = 0;
6096 strcpy(window->filename, name);
6097 window->undo = NULL;
6098 window->redo = NULL;
6099 window->nPanes = 0;
6100 + window->lastFocus = NULL;
6101 window->autoSaveCharCount = 0;
6102 window->autoSaveOpCount = 0;
6103 window->undoOpCount = 0;
6104 window->undoMemUsed = 0;
6105 CLEAR_ALL_LOCKS(window->lockReasons);
6106 + window->transient = False;
6107 window->indentStyle = GetPrefAutoIndent(PLAIN_LANGUAGE_MODE);
6108 window->autoSave = GetPrefAutoSave();
6109 window->saveOldVersion = GetPrefSaveOldVersion();
6110 window->wrapMode = GetPrefWrap(PLAIN_LANGUAGE_MODE);
6111 + window->showWrapMargin = GetPrefShowWrapMargin();
6112 window->overstrike = False;
6113 window->showMatchingStyle = GetPrefShowMatching();
6114 window->matchSyntaxBased = GetPrefMatchSyntaxBased();
6115 window->highlightSyntax = GetPrefHighlightSyntax();
6116 window->backlightCharTypes = NULL;
6117 @@ -3378,23 +3469,25 @@ WindowInfo* CreateDocument(WindowInfo* s
6118 text = createTextArea(pane, window, nRows, nCols,
6119 GetPrefEmTabDist(PLAIN_LANGUAGE_MODE), GetPrefDelimiters(),
6120 GetPrefWrapMargin(), window->showLineNumbers?MIN_LINE_NUM_COLS:0);
6121 XtManageChild(text);
6122 window->textArea = text;
6123 - window->lastFocus = text;
6124 + ChangeLastFocus(window, text);
6126 /* Set the initial colors from the globals. */
6127 SetColors(window,
6128 GetPrefColorName(TEXT_FG_COLOR ),
6129 GetPrefColorName(TEXT_BG_COLOR ),
6130 GetPrefColorName(SELECT_FG_COLOR),
6131 GetPrefColorName(SELECT_BG_COLOR),
6132 GetPrefColorName(HILITE_FG_COLOR),
6133 GetPrefColorName(HILITE_BG_COLOR),
6134 GetPrefColorName(LINENO_FG_COLOR),
6135 - GetPrefColorName(CURSOR_FG_COLOR));
6137 + GetPrefColorName(CURSOR_FG_COLOR),
6138 + GetPrefColorName(WRAPMARGIN_FG_COLOR),
6139 + GetPrefColorName(CURSORLINE_BG_COLOR));
6141 /* Create the right button popup menu (note: order is important here,
6142 since the translation for popping up this menu was probably already
6143 added in createTextArea, but CreateBGMenu requires window->textArea
6144 to be set so it can attach the menu to it (because menu shells are
6145 finicky about the kinds of widgets they are attached to)) */
6146 @@ -3717,10 +3810,11 @@ void RefreshMenuToggleStates(WindowInfo
6147 #endif
6148 XmToggleButtonSetState(window->autoSaveItem, window->autoSave, False);
6149 XmToggleButtonSetState(window->overtypeModeItem, window->overstrike, False);
6150 XmToggleButtonSetState(window->matchSyntaxBasedItem, window->matchSyntaxBased, False);
6151 XmToggleButtonSetState(window->readOnlyItem, IS_USER_LOCKED(window->lockReasons), False);
6152 + XmToggleButtonSetState(window->transientItem, window->transient, False);
6154 XtSetSensitive(window->smartIndentItem,
6155 SmartIndentMacrosAvailable(LanguageModeName(window->languageMode)));
6157 SetAutoIndent(window, window->indentStyle);
6158 @@ -4178,11 +4272,12 @@ static void cloneTextPanes(WindowInfo *w
6159 XtVaSetValues(text, XmNforeground, textD->fgPixel,
6160 XmNbackground, textD->bgPixel, NULL);
6161 TextDSetColors(newTextD, textD->fgPixel, textD->bgPixel,
6162 textD->selectFGPixel, textD->selectBGPixel,
6163 textD->highlightFGPixel,textD->highlightBGPixel,
6164 - textD->lineNumFGPixel, textD->cursorFGPixel);
6165 + textD->lineNumFGPixel, textD->cursorFGPixel,
6166 + textD->wrapMarginFGPixel, textD->cursorlineBGPixel);
6169 /* Set the minimum pane height in the new pane */
6170 UpdateMinPaneHeights(window);
6172 @@ -4211,11 +4306,11 @@ static void cloneTextPanes(WindowInfo *w
6174 /* set the focus pane */
6175 for (i=0; i<=window->nPanes; i++) {
6176 text = i==0 ? window->textArea : window->textPanes[i-1];
6177 if(i == focusPane) {
6178 - window->lastFocus = text;
6179 + ChangeLastFocus(window, text);
6180 XmProcessTraversal(text, XmTRAVERSE_CURRENT);
6181 break;
6185 @@ -4330,10 +4425,11 @@ static void cloneDocument(WindowInfo *wi
6186 window->findLastLiteralCase = orgWin->findLastLiteralCase;
6187 window->device = orgWin->device;
6188 window->inode = orgWin->inode;
6189 window->fileClosedAtom = orgWin->fileClosedAtom;
6190 orgWin->fileClosedAtom = None;
6191 + window->transient = orgWin->transient;
6193 /* copy the text/split panes settings, cursor pos & selection */
6194 cloneTextPanes(window, orgWin);
6196 /* copy undo & redo list */
6197 @@ -4742,5 +4838,24 @@ void CleanUpTabBarExposeQueue(WindowInfo
6198 ev.count = 0;
6199 XSendEvent(TheDisplay, XtWindow(window->tabBar), False,
6200 ExposureMask, (XEvent *)&ev);
6205 +** Track which text pane in this widget is/was last active (with focus).
6206 +** Also perform any tasks relating to changing pane focus.
6208 +void ChangeLastFocus(WindowInfo *window, Widget text)
6210 + Boolean showCursorline = GetPrefShowCursorline();
6212 + if (NULL != window->lastFocus) {
6213 + /* Remove cursorline from last focussed pane. */
6214 + XtVaSetValues(window->lastFocus,
6215 + textNshowCursorline, False,
6216 + NULL);
6218 + XtVaSetValues(text, textNshowCursorline, showCursorline, NULL);
6220 + window->lastFocus = text;
6222 diff --quilt old/source/window.h new/source/window.h
6223 --- old/source/window.h
6224 +++ new/source/window.h
6225 @@ -51,13 +51,16 @@ void SetAutoIndent(WindowInfo *window, i
6226 void SetShowMatching(WindowInfo *window, int state);
6227 void SetFonts(WindowInfo *window, const char *fontName, const char *italicName,
6228 const char *boldName, const char *boldItalicName);
6229 void SetColors(WindowInfo *window, const char *textFg, const char *textBg,
6230 const char *selectFg, const char *selectBg, const char *hiliteFg,
6231 - const char *hiliteBg, const char *lineNoFg, const char *cursorFg);
6232 + const char *hiliteBg, const char *lineNoFg, const char *cursorFg,
6233 + const char* wrapMarginFg, const char* cursorlineBg);
6234 void SetOverstrike(WindowInfo *window, int overstrike);
6235 void SetAutoWrap(WindowInfo *window, int state);
6236 +void SetWrapMargin(WindowInfo *window, int margin);
6237 +void SetShowWrapMargin(WindowInfo *window, int state);
6238 void SetAutoScroll(WindowInfo *window, int margin);
6239 void SplitPane(WindowInfo *window);
6240 Widget GetPaneByIndex(WindowInfo *window, int paneIndex);
6241 int WidgetToPaneIndex(WindowInfo *window, Widget w);
6242 void ClosePane(WindowInfo *window);
6243 @@ -102,6 +105,7 @@ void SortTabBar(WindowInfo *window);
6244 void SetBacklightChars(WindowInfo *window, char *applyBacklightTypes);
6245 void SetToggleButtonState(WindowInfo *window, Widget w, Boolean state,
6246 Boolean notify);
6247 void SetSensitive(WindowInfo *window, Widget w, Boolean sensitive);
6248 void CleanUpTabBarExposeQueue(WindowInfo *window);
6249 +void ChangeLastFocus(WindowInfo *window, Widget text);
6250 #endif /* NEDIT_WINDOW_H_INCLUDED */
6251 diff --quilt old/util/fileUtils.c new/util/fileUtils.c
6252 --- old/util/fileUtils.c
6253 +++ new/util/fileUtils.c
6254 @@ -83,11 +83,11 @@ static void copyThruSlash(char **toStrin
6257 ** Decompose a Unix file name into a file name and a path.
6258 ** Return non-zero value if it fails, zero else.
6259 ** For now we assume that filename and pathname are at
6260 -** least MAXPATHLEN chars long.
6261 +** most MAXPATHLEN chars long.
6262 ** To skip setting filename or pathname pass NULL for that argument.
6265 ParseFilename(const char *fullname, char *filename, char *pathname)
6267 diff --quilt old/util/getfiles.c new/util/getfiles.c
6268 --- old/util/getfiles.c
6269 +++ new/util/getfiles.c
6270 @@ -6,11 +6,11 @@ static const char CVSID[] = "$Id: getfil
6271 * Copyright (C) 1999 Mark Edel *
6273 * This is free software; you can redistribute it and/or modify it under the *
6274 * terms of the GNU General Public License as published by the Free Software *
6275 * Foundation; either version 2 of the License, or (at your option) any later *
6276 -* version. In addition, you may distribute version of this program linked to *
6277 +* version. In addition, you may distribute versions of this program linked to *
6278 * Motif or Open Motif. See README for details. *
6280 * This software is distributed in the hope that it will be useful, but WITHOUT *
6281 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
6282 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
6283 @@ -35,23 +35,19 @@ static const char CVSID[] = "$Id: getfil
6284 * a directory when no filename was specified *
6285 * 6/24/92 by MWE: Made filename list and directory list typeable, *
6286 * set initial focus to filename list *
6287 * 6/25/93 by JMK: Fix memory leaks found by Purify. *
6289 -* Included are two routines written using Motif for accessing files: *
6290 -* *
6291 -* GetExistingFilename presents a FileSelectionBox dialog where users can *
6292 -* choose an existing file to open. *
6293 -* *
6294 *******************************************************************************/
6296 #ifdef HAVE_CONFIG_H
6297 #include "../config.h"
6298 #endif
6300 -#include "getfiles.h"
6301 +#include "DialogF.h"
6302 #include "fileUtils.h"
6303 +#include "getfiles.h"
6304 #include "misc.h"
6306 #include <stdio.h>
6307 #include <stdlib.h>
6308 #include <string.h>
6309 @@ -73,15 +69,19 @@ static const char CVSID[] = "$Id: getfil
6311 #include <X11/keysym.h>
6312 #include <Xm/Xm.h>
6313 #include <Xm/FileSB.h>
6314 #include <Xm/Form.h>
6315 +#include <Xm/Label.h>
6316 #include <Xm/List.h>
6317 #include <Xm/MessageB.h>
6318 +#include <Xm/PushB.h>
6319 #include <Xm/PushBG.h>
6320 -#include <Xm/Text.h>
6321 +#include <Xm/RowColumn.h>
6322 #include <Xm/TextF.h>
6323 +#include <Xm/Text.h>
6324 +#include <Xm/ToggleB.h>
6326 #ifdef HAVE_DEBUG_H
6327 #include "../debug.h"
6328 #endif
6330 @@ -93,26 +93,29 @@ static const char CVSID[] = "$Id: getfil
6331 #define MAX_LIST_KESTROKE_WAIT 2000 /* Allowable delay in milliseconds
6332 between characters typed to a list
6333 before starting over (throwing
6334 out the accumulated characters */
6336 +#define HFSB_OK 1 /* Get Filename OK constant */
6337 +#define HFSB_CANCEL 2 /* Get Filename Cancel constant */
6339 #define SET_ONE_RSRC(widget, name, newValue) \
6341 static Arg tmpargs[1] = {{name, (XtArgVal)0}}; \
6342 tmpargs[0].value = (XtArgVal)newValue; \
6343 XtSetValues(widget, tmpargs, 1); \
6347 enum yesNoValues {ynNone, ynYes, ynNo};
6349 /* Saved default directory and pattern from last successful call */
6350 static XmString DefaultDirectory = NULL;
6351 static XmString DefaultPattern = NULL;
6353 -/* User settable option for leaving the file name text field in
6354 - GetExistingFilename dialogs. Off by default so new users will get
6355 - used to typing in the list rather than in the text field */
6356 +/* User settable option for leaving the file name text field in file
6357 + dialogs. Off by default so new users will get used to typing in the
6358 + list rather than in the text field */
6359 static int RemoveRedundantTextField = True;
6361 /* Text for help button help display */
6362 /* ... needs variant for VMS */
6363 #ifndef SGI_CUSTOM
6364 @@ -131,11 +134,14 @@ If you use the filter field, remember to
6365 either a file name, \"*\" is acceptable, or a trailing \"/\". If \
6366 you don't, the name after the last \"/\" is interpreted as the file name to \
6367 match. When you leave off the file name or trailing \"/\", you won't see \
6368 any files to open in the list \
6369 because the filter specification matched the directory file itself, rather \
6370 -than the files in the directory.";
6371 +than the files in the directory.\n"
6372 +"\n"
6373 +"Hidden files and directories (those whose names begin with a dot) will only "
6374 +"be shown if the 'Show hidden Files' button is activated.";
6376 static const char *HelpNew =
6377 "This dialog allows you to create a new file, or to save the current file \
6378 under a new name. To specify a file \
6379 name in the current directory, complete the name displayed in the \"Save File \
6380 @@ -151,11 +157,14 @@ to move around in the file system hierar
6381 directory names in the list, or selecting them and pressing the \
6382 \"Filter\" button will select that directory. To move upwards \
6383 in the directory tree, double \
6384 click on the directory entry ending in \"..\". You can also move directly \
6385 to a directory by typing the file specification of the path in the \"Filter\" \
6386 -field and pressing the \"Filter\" button.";
6387 +field and pressing the \"Filter\" button."
6388 +"\n"
6389 +"Hidden files and directories (those whose names begins with a dot) will only "
6390 +"be shown if the 'Show hidden Files' button is activated.";
6392 #else /* SGI_CUSTOM */
6393 static const char *HelpExist =
6394 "The \"File to Edit:\" field shows a list of directories and files in the \
6395 current directory.\n\
6396 @@ -175,11 +184,14 @@ will accept icons dragged from the deskt
6397 arrows, to the right, of the field recalls previously selected \
6398 directories.\n\
6400 The \"Filter\" button allows you to narrow down the list of files and \
6401 directories shown in the \"File to Edit:\" field. The default filter of \
6402 -\"*\" allows all files to be listed.";
6403 +\"*\" allows all files to be listed."
6404 +"\n"
6405 +"Hidden files and directories (those whose names begins with a dot) will only "
6406 +"be shown if the 'Show hidden Files' button is activated.";
6408 static const char *HelpNew =
6409 "This dialog allows you to create a new file or to save the current file \
6410 under a new name.\n\
6412 @@ -206,15 +218,20 @@ will accept icons dragged from the deskt
6413 arrows, to the right, of the field recalls previously selected \
6414 directories.\n\
6416 The \"Filter\" button allows you to narrow down the list of files and \
6417 directories shown in the \"Files\" field. The default filter of \
6418 -\"*\" allows all files to be listed.";
6419 -#endif /* SGI_CUSTOM */
6420 +\"*\" allows all files to be listed."
6421 +"\n"
6422 +"Hidden files and directories (those whose names begins with a dot) will only "
6423 +"be shown if the 'Show hidden Files' button is activated.";
6425 -/* Local Callback Routines and variables */
6426 +#endif /* SGI_CUSTOM */
6429 +** Local Callback Routines and variables
6431 static void newFileOKCB(Widget w, Boolean *client_data,
6432 XmFileSelectionBoxCallbackStruct *call_data);
6433 static void newFileCancelCB(Widget w, Boolean *client_data, caddr_t
6434 call_data);
6435 static void newHelpCB(Widget w, Widget helpPanel, caddr_t call_data);
6436 @@ -236,104 +253,441 @@ static void listCharEH(Widget w, XtPoint
6437 Boolean *continueDispatch);
6438 static void replacementDirSearchProc(Widget w, XtPointer searchData);
6439 static void replacementFileSearchProc(Widget w, XtPointer searchData);
6440 static void sortWidgetList(Widget listWidget);
6441 static int compareXmStrings(const void *string1, const void *string2);
6442 +static unsigned removeHiddenFiles(Widget listWidget);
6443 +static Boolean removeDotEntry(Widget listWidget);
6444 +static int isHiddenFile(const char* filename);
6445 +static int handleCustomExistFileSB(Widget existFileSB, char *filename);
6446 +static int handleCustomNewFileSB(Widget newFileSB, char *filename, char *defaultName);
6448 -static int SelectResult = GFN_CANCEL; /* Initialize results as cancel */
6449 +static int SelectResult = HFSB_CANCEL; /* Initialize results as cancel */
6450 static Widget YesNoDialog; /* "Overwrite?" dialog widget */
6451 static int YesNoResult; /* Result of overwrite dialog */
6452 static Widget ErrorDialog; /* Dialog widget for error msgs */
6453 static int ErrorDone; /* Flag to mark dialog completed */
6454 static void (*OrigDirSearchProc)(); /* Built in Motif directory search */
6455 static void (*OrigFileSearchProc)(); /* Built in Motif file search proc */
6456 +static void freeFileList(char** list);
6458 -/*
6459 - * Do the hard work of setting up a file selection dialog
6460 - */
6461 -Widget getFilenameHelper(Widget parent, char *promptString, char *filename,
6462 - int existing)
6464 - int n; /* number of arguments */
6465 - Arg args[MAX_ARGS]; /* arg list */
6466 - Widget fileSB; /* widget file select box */
6467 - XmString titleString; /* compound string for dialog title */
6468 +static Widget addUtilForm(const Widget fsd, const Boolean showHidden,
6469 + const Boolean haveFormatButtons, const Boolean isContWrapped,
6470 + Boolean* addWrap, int* fileFormat);
6471 +static void hiddenFilesCB(Widget widget, XtPointer client_data,
6472 + XtPointer call_data);
6473 +static void showOptionsCB(Widget pushButton, XtPointer client_data,
6474 + XtPointer call_data);
6475 +static void setFormatCB(Widget widget, XtPointer clientData, XtPointer callData);
6476 +static void addWrapCB(Widget w, XtPointer clientData, XtPointer callData);
6479 +** GetFilenameByDialog()
6481 +** Façade for file dialogs.
6483 +** TODO: Refactor the whole module
6484 +** TODO: The original saved/restored a default directory, but I don't see any
6485 +** adverse effects on OM 2.2.3 or Lesstif 0.95 by just skipping that
6486 +** part. Does this depend on the toolkit and/or version used?
6488 +gfbdValue* GetFilenameByDialog(const gfbdParams params)
6490 + /* Values */
6491 + gfbdValue* retValue;
6493 + /* widgets and other GUI stuff */
6494 + Widget fsd;
6495 + XmString titleString;
6497 + /* helpers */
6498 + unsigned n; /* arg list */
6499 + Arg args[MAX_ARGS]; /* arg list */
6500 + int rc; /* return code of handleCustomExistFileSB() */
6502 + /* Can probably be refactored away. */
6503 + fsbUserDataStruct userData;
6505 + /* some initialization */
6506 + retValue = (gfbdValue*) XtMalloc(sizeof(gfbdValue));
6507 + retValue->status = GFDB_ERROR;
6509 n = 0;
6510 - titleString = XmStringCreateSimple(promptString);
6511 + titleString = XmStringCreateLocalized(params.dialogTitle);
6512 XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
6513 XtSetArg(args[n], XmNdialogTitle, titleString); n++;
6514 - fileSB = CreateFileSelectionDialog(parent,"FileSelect",args,n);
6515 + XtSetArg(args[n], XmNresizePolicy, XmRESIZE_GROW); n++;
6516 + fsd = CreateFileSelectionDialog(params.parentShell, "fsd", args, n);
6517 XmStringFree(titleString);
6518 -#ifndef SGI_CUSTOM
6519 - if (existing && RemoveRedundantTextField)
6520 - XtUnmanageChild(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_TEXT));
6521 - XtUnmanageChild(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_SELECTION_LABEL));
6523 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_FILTER_LABEL),
6524 + /* Put mnemonic on labels; this will put the focus in the labeled widget
6525 + if activated. See misc.c:findAndActivateMnemonic() for details. */
6526 + XtVaSetValues(XmFileSelectionBoxGetChild(fsd, XmDIALOG_FILTER_LABEL),
6527 XmNmnemonic, 'l',
6528 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_FILTER_TEXT),
6529 + XmNuserData, XmFileSelectionBoxGetChild(fsd, XmDIALOG_FILTER_TEXT),
6530 NULL);
6531 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST_LABEL),
6532 + XtVaSetValues(XmFileSelectionBoxGetChild(fsd, XmDIALOG_DIR_LIST_LABEL),
6533 XmNmnemonic, 'D',
6534 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST),
6535 + XmNuserData, XmFileSelectionBoxGetChild(fsd, XmDIALOG_DIR_LIST),
6536 + NULL);
6537 + XtVaSetValues(XmFileSelectionBoxGetChild(fsd, XmDIALOG_LIST_LABEL),
6538 + XmNmnemonic, 'F',
6539 + XmNuserData, XmFileSelectionBoxGetChild(fsd, XmDIALOG_LIST),
6540 + NULL);
6541 + /* The last mnemonic originally used strspn() to find the last mnemonic,
6542 + but used the dialog's title instead of the list's label. Since it broke
6543 + user's GUI expectations I replaced it with a plain letter. */
6545 + /* Unmanage text field and label unless a label is given. */
6546 + if (NULL == params.textfieldLabel) {
6547 + XtUnmanageChild(XmFileSelectionBoxGetChild(fsd, XmDIALOG_TEXT));
6548 + XtUnmanageChild(XmFileSelectionBoxGetChild(fsd, XmDIALOG_SELECTION_LABEL));
6549 + } else {
6550 + XmString labelString = XmStringCreateLocalized(params.textfieldLabel);
6552 + XtVaSetValues(XmFileSelectionBoxGetChild(fsd, XmDIALOG_SELECTION_LABEL),
6553 + XmNlabelString, labelString,
6554 + NULL);
6555 + XtVaSetValues(XmFileSelectionBoxGetChild(fsd, XmDIALOG_SELECTION_LABEL),
6556 + XmNmnemonic, params.textfieldLabel[strspn(params.textfieldLabel, "lDF")],
6557 + XmNuserData, XmFileSelectionBoxGetChild(fsd, XmDIALOG_TEXT),
6558 + NULL);
6559 + XmStringFree(labelString);
6562 + retValue->fileFormat = params.fileFormat;
6563 + addUtilForm(fsd, params.showHidden, params.haveFormatButtons,
6564 + params.isContWrapped, &(retValue->addWrap), &(retValue->fileFormat));
6566 + /* Do the mnemonic magic. Wait until all mnemonics are prepared. */
6567 + AddDialogMnemonicHandler(fsd, FALSE);
6569 + /* Fix some ancient hardware/toolkit quirks. */
6570 + RemapDeleteKey(XmFileSelectionBoxGetChild(fsd, XmDIALOG_FILTER_TEXT));
6571 + RemapDeleteKey(XmFileSelectionBoxGetChild(fsd, XmDIALOG_TEXT));
6573 + userData.showHidden = params.showHidden;
6574 + XtVaSetValues(fsd, XmNuserData, &userData, NULL);
6576 + /* Refactor this. */
6577 + if (params.fileExists) {
6578 + rc = handleCustomExistFileSB(fsd, retValue->payload);
6579 + } else {
6580 + rc = handleCustomNewFileSB(fsd, retValue->payload, params.defaultName);
6583 + switch(rc) {
6584 + case HFSB_OK:
6585 + retValue->status = GFDB_OK;
6586 + break;
6587 + case HFSB_CANCEL:
6588 + retValue->status = GFDB_CANCEL;
6589 + break;
6590 + default:
6591 + /* fallback */
6592 + strncpy(retValue->payload, "Something murphied in GetFilenameByDialog, sorry.", MAXPATHLEN);
6593 + retValue->status = GFDB_ERROR;
6594 + break;
6597 + return retValue;
6601 +** Helper for GetFilenameByDialog()
6603 +** Note: Since mnemonics are set here, wait with your call to activate them
6604 +** via AddDialogMnemonicHandler() until this is done.
6606 +** TODO: The reliance on AddDialogMnemonicHandler() (called in the caller
6607 +** after addUtilForm()) breaks low coupling.
6609 +static Widget addUtilForm(const Widget fsd, const Boolean showHidden,
6610 + const Boolean haveFormatButtons, const Boolean isContWrapped,
6611 + Boolean* addWrap, int* fileFormat)
6613 + Widget utilForm; /* form containing utility widgets */
6614 + Widget optionsForm; /* container for option widgets */
6616 + Widget showOptionsCheckBox; /* (un)display additional options */
6617 + Widget showOptionsPushButton; /* (un)display additional options */
6618 + XmString showOptionsLabel; /* PushButton label */
6620 + Widget hiddenFilesCheckBox; /* (un)displaying hidden files */
6621 + Widget hiddenFilesToggleButton; /* (un)displaying hidden files */
6622 + XmString hiddenFilesLabel; /* ToggleButton label */
6624 + Widget formatBtnsRow;
6625 + Widget unixFormatButton, dosFormatButton, macFormatButton;
6626 + Widget wrapToggle;
6627 + Widget topWidget = NULL;
6629 + XmString s1 = NULL;
6631 + /* Creates a Form containing additional widgets */
6632 + utilForm = XtVaCreateManagedWidget("utilForm", xmFormWidgetClass, fsd, NULL);
6634 + /* Creates a RowColumn containing a PushButton to (un)display the
6635 + other options. */
6636 + showOptionsCheckBox = XtVaCreateManagedWidget("showOptionsCheckBox",
6637 + xmRowColumnWidgetClass, utilForm,
6638 + NULL);
6639 + showOptionsLabel = XmStringCreateLocalized("Less...");
6640 + showOptionsPushButton = XtVaCreateManagedWidget("showOptionsPushButton",
6641 + xmPushButtonWidgetClass, showOptionsCheckBox,
6642 + XmNmnemonic, 'M',
6643 + XmNlabelString, showOptionsLabel,
6644 + XmNuserData, 1,
6645 + NULL);
6646 + XmStringFree(showOptionsLabel);
6647 + XtAddCallback(showOptionsPushButton,
6648 + XmNactivateCallback, showOptionsCB,
6649 + (XtPointer) &fsd);
6651 + /* Creates a Form containing all options. */
6652 + optionsForm = XtVaCreateManagedWidget("optionsForm",
6653 + xmFormWidgetClass, utilForm,
6654 + XmNtopAttachment, XmATTACH_WIDGET,
6655 + XmNtopWidget, showOptionsCheckBox,
6656 + XmNbottomAttachment, XmATTACH_FORM,
6657 + XmNleftAttachment, XmATTACH_FORM,
6658 + XmNrightAttachment, XmATTACH_FORM,
6659 + NULL);
6661 + /* Adds format buttons. */
6662 + if (haveFormatButtons) {
6663 + /* Create RowColumn containing a number of push buttons for file format. */
6664 + formatBtnsRow = XtVaCreateManagedWidget("formatBtnsRow",
6665 + xmRowColumnWidgetClass, optionsForm,
6666 + XmNradioBehavior, XmONE_OF_MANY,
6667 + XmNorientation, XmHORIZONTAL,
6668 + XmNpacking, XmPACK_TIGHT,
6669 + XmNtopAttachment, XmATTACH_FORM,
6670 + XmNleftAttachment, XmATTACH_FORM,
6671 + NULL);
6673 + XtVaCreateManagedWidget("formatBtns",
6674 + xmLabelWidgetClass, formatBtnsRow,
6675 + XmNlabelString, s1 = XmStringCreateSimple("Format:"),
6676 + NULL);
6677 + XmStringFree(s1);
6679 + unixFormatButton = XtVaCreateManagedWidget("unixFormat",
6680 + xmToggleButtonWidgetClass, formatBtnsRow,
6681 + XmNlabelString, s1 = XmStringCreateSimple("Unix"),
6682 + XmNset, UNIX_FILE_FORMAT == *fileFormat,
6683 + XmNuserData, (XtPointer) UNIX_FILE_FORMAT,
6684 + XmNmarginHeight, 0,
6685 + XmNalignment, XmALIGNMENT_BEGINNING,
6686 + XmNmnemonic, 'U',
6687 + NULL);
6688 + XmStringFree(s1);
6689 + XtAddCallback(unixFormatButton, XmNvalueChangedCallback, setFormatCB,
6690 + fileFormat);
6692 + dosFormatButton = XtVaCreateManagedWidget("dosFormat",
6693 + xmToggleButtonWidgetClass, formatBtnsRow,
6694 + XmNlabelString, s1 = XmStringCreateSimple("DOS"),
6695 + XmNset, DOS_FILE_FORMAT == *fileFormat,
6696 + XmNuserData, (XtPointer) DOS_FILE_FORMAT,
6697 + XmNmarginHeight, 0,
6698 + XmNalignment, XmALIGNMENT_BEGINNING,
6699 + XmNmnemonic, 'O',
6700 + NULL);
6701 + XmStringFree(s1);
6702 + XtAddCallback(dosFormatButton, XmNvalueChangedCallback, setFormatCB,
6703 + fileFormat);
6705 + macFormatButton = XtVaCreateManagedWidget("macFormat",
6706 + xmToggleButtonWidgetClass, formatBtnsRow,
6707 + XmNlabelString, s1 = XmStringCreateSimple("Macintosh"),
6708 + XmNset, MAC_FILE_FORMAT == *fileFormat,
6709 + XmNuserData, (XtPointer) MAC_FILE_FORMAT,
6710 + XmNmarginHeight, 0,
6711 + XmNalignment, XmALIGNMENT_BEGINNING,
6712 + XmNmnemonic, 'M',
6713 + NULL);
6714 + XmStringFree(s1);
6715 + XtAddCallback(macFormatButton, XmNvalueChangedCallback, setFormatCB,
6716 + fileFormat);
6718 + if (isContWrapped) {
6719 + wrapToggle = XtVaCreateManagedWidget("addWrap",
6720 + xmToggleButtonWidgetClass, optionsForm,
6721 + XmNlabelString,
6722 + s1 = XmStringCreateSimple("Add line breaks where wrapped"),
6723 + XmNalignment, XmALIGNMENT_BEGINNING,
6724 + XmNmnemonic, 'A',
6725 + XmNtopAttachment, XmATTACH_WIDGET,
6726 + XmNtopWidget, formatBtnsRow,
6727 + XmNleftAttachment, XmATTACH_FORM, NULL);
6728 + XtAddCallback(wrapToggle, XmNvalueChangedCallback, addWrapCB, addWrap);
6729 + XmStringFree(s1);
6731 + topWidget = wrapToggle;
6732 + } else {
6733 + topWidget = formatBtnsRow;
6737 + /* Creates a RowColumn containing a ToggleButton to show/hide
6738 + hidden files in the file lists. */
6739 + hiddenFilesCheckBox = XtVaCreateManagedWidget("hiddenFilesCheckBox",
6740 + xmRowColumnWidgetClass,
6741 + optionsForm,
6742 + XmNtopAttachment, XmATTACH_WIDGET,
6743 + XmNtopWidget, topWidget,
6744 + XmNbottomAttachment, XmATTACH_FORM,
6745 + XmNleftAttachment, XmATTACH_FORM,
6746 + XmNrightAttachment, XmATTACH_FORM,
6747 NULL);
6748 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST_LABEL),
6749 - XmNmnemonic, promptString[strspn(promptString, "lD")],
6750 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST),
6751 + hiddenFilesLabel = XmStringCreateLocalized("Show hidden Files");
6752 + hiddenFilesToggleButton = XtVaCreateManagedWidget("hiddenFilesToggleButton",
6753 + xmToggleButtonWidgetClass,
6754 + hiddenFilesCheckBox,
6755 + XmNmnemonic, 'h',
6756 + XmNlabelString, hiddenFilesLabel,
6757 + XmNset, showHidden,
6758 NULL);
6759 - AddDialogMnemonicHandler(fileSB, FALSE);
6760 - RemapDeleteKey(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_FILTER_TEXT));
6761 - RemapDeleteKey(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_TEXT));
6762 + XmStringFree(hiddenFilesLabel);
6763 + XtAddCallback(hiddenFilesToggleButton,
6764 + XmNvalueChangedCallback, hiddenFilesCB,
6765 + (XtPointer) &fsd);
6767 + return optionsForm;
6771 +** Callback for hiddenFilesToggleButton
6772 +** The ToggleButton's state is saved in the FileSelectionBox' XmNuserData
6773 +** field, so that it can be used in the XmN*searchProcs.
6775 +static void hiddenFilesCB(Widget widget,
6776 + XtPointer client_data,
6777 + XtPointer call_data)
6779 + XmToggleButtonCallbackStruct* state =
6780 + (XmToggleButtonCallbackStruct *) call_data;
6781 + Widget* fsbParent = (Widget*) client_data;
6782 + fsbUserDataStruct* userData;
6784 + /* Remember the button's setting for the sort routines */
6785 + XtVaGetValues(*fsbParent, XmNuserData, &userData, NULL);
6786 + userData->showHidden = state->set;
6788 +#if XmVERSION >= 2
6789 + /* This will take care of the the Motif FSB resource fileFilterStyle. It
6790 + is still honored by NEdit by using it to override the compiled-in
6791 + default (see source/preferences.c, initPrefDefaultsFromResources()),
6792 + but the internal resource will override it. */
6794 + int fileFilterStyle =
6795 + (state->set ? XmFILTER_NONE : XmFILTER_HIDDEN_FILES);
6796 + XtVaSetValues(*fsbParent, XmNfileFilterStyle, fileFilterStyle, NULL);
6798 #endif
6799 - return fileSB;
6801 + /* Reinitialize lists */
6802 + XmFileSelectionDoSearch(*fsbParent, NULL);
6806 +** Callback for showOptionsPushButton
6808 +** client_data ist supposed to carry a pointer to the FSB
6810 +static void showOptionsCB(Widget pushButton,
6811 + XtPointer client_data,
6812 + XtPointer call_data)
6814 + Boolean isShown;
6815 + XmString buttonLabel;
6816 + Widget* fsb = (Widget*) client_data;
6817 + Dimension optionFormHeight;
6818 + Widget optionsForm = XtNameToWidget(*fsb, "*optionsForm");
6819 + Dimension fsbHeight;
6821 + XtVaGetValues(pushButton, XmNuserData, &isShown, NULL);
6823 + /* Get initial size of FSB */
6824 + XtVaGetValues(*fsb, XmNheight, &fsbHeight, NULL);
6826 + if (isShown) {
6827 + isShown = False;
6829 + /* We change the size here because the Less/More button should
6830 + stay under the mouse pointer. */
6831 + XtVaGetValues(optionsForm, XmNheight, &optionFormHeight, NULL);
6832 + XtUnmanageChild(optionsForm);
6833 + XtVaSetValues(*fsb, XmNheight, fsbHeight - optionFormHeight, NULL);
6835 + /* FIXME: Is this a leak? Do we have to delete the old string? */
6836 + buttonLabel = XmStringCreateLocalized("More...");
6837 + XtVaSetValues(pushButton, XmNlabelString, buttonLabel, NULL);
6838 + XmStringFree(buttonLabel);
6839 + } else {
6840 + isShown = True;
6842 + /* We change the size here because the Less/More button should
6843 + stay under the mouse pointer. */
6844 + XtManageChild(optionsForm);
6845 + XtVaGetValues(optionsForm, XmNheight, &optionFormHeight, NULL);
6846 + XtVaSetValues(*fsb, XmNheight, fsbHeight + optionFormHeight, NULL);
6848 + /* FIXME: Is this a leak? Do we have to delete the old string? */
6849 + buttonLabel = XmStringCreateLocalized("Less...");
6850 + XtVaSetValues(pushButton, XmNlabelString, buttonLabel, NULL);
6851 + XmStringFree(buttonLabel);
6854 + XtVaSetValues(pushButton, XmNuserData, isShown, NULL);
6857 -/* GetExistingFilename */
6858 -/* */
6859 -/* This routine will popup a file selection box so that the user can */
6860 -/* select an existing file from the scrollable list. The user is */
6861 -/* prevented from entering a new filename because the edittable text */
6862 -/* area of the file selection box widget is unmanaged. After the user */
6863 -/* selects a file, GetExistingFilename returns the selected filename and */
6864 -/* GFN_OK, indicating that the OK button was pressed. If the user */
6865 -/* pressed the cancel button, the return value is GFN_CANCEL, and the */
6866 -/* filename character string supplied in the call is not altered. */
6867 -/* */
6868 -/* Arguments: */
6869 -/* */
6870 -/* Widget parent - parent widget id */
6871 -/* char * promptString - prompt string */
6872 -/* char * filename - a string to receive the selected filename */
6873 -/* (this string will not be altered if the */
6874 -/* user pressed the cancel button) */
6875 -/* */
6876 -/* Returns: GFN_OK - file was selected and OK button pressed */
6877 -/* GFN_CANCEL - Cancel button pressed and no returned file */
6878 -/* */
6879 -int GetExistingFilename(Widget parent, char *promptString, char *filename)
6881 - Widget existFileSB = getFilenameHelper(parent, promptString, filename,
6882 - True);
6883 - return HandleCustomExistFileSB(existFileSB, filename);
6886 -/* GetNewFilename
6888 - * Same as GetExistingFilename but pick a new file instead of an existing one.
6889 - * In this case the text area of the FSB is *not* unmanaged, so the user can
6890 - * enter a new filename.
6891 - */
6892 -int GetNewFilename(Widget parent, char *promptString, char *filename,
6893 - char *defaultName)
6895 +** Callback procedure for toggle button requesting newlines to be inserted
6896 +** to emulate continuous wrapping.
6898 +static void addWrapCB(Widget w, XtPointer clientData, XtPointer callData)
6900 - Widget fileSB = getFilenameHelper(parent, promptString, filename, False);
6901 - return HandleCustomNewFileSB(fileSB, filename, defaultName);
6902 + int resp;
6903 + int *addWrap = (int *)clientData;
6905 + if (XmToggleButtonGetState(w)) {
6906 + resp = DialogF(DF_WARN, w, 2, "Add Wrap",
6907 + "This operation adds permanent line breaks to\n"
6908 + "match the automatic wrapping done by the\n"
6909 + "Continuous Wrap mode Preferences Option.\n\n"
6910 + "*** This Option is Irreversable ***\n\n"
6911 + "Once newlines are inserted, continuous wrapping\n"
6912 + "will no longer work automatically on these lines", "OK",
6913 + "Cancel");
6914 + if (1 == resp) {
6915 + *addWrap = True;
6916 + } else {
6917 + XmToggleButtonSetState(w, False, False);
6918 + *addWrap = False;
6920 + } else {
6921 + *addWrap = False;
6926 -** HandleCustomExistFileSB
6927 +** Callback procedure for File Format toggle buttons. Format is stored
6928 +** in userData field of widget button
6930 +static void setFormatCB(Widget widget, XtPointer clientData, XtPointer callData)
6932 + if (XmToggleButtonGetState(widget)) {
6933 + XtPointer userData;
6934 + XtVaGetValues(widget, XmNuserData, &userData, NULL);
6935 + *((int*) clientData) = (int) userData;
6940 +** handleCustomExistFileSB
6942 ** Manage a customized file selection box for opening existing files.
6943 ** Use this if you want to change the standard file selection dialog
6944 ** from the defaults provided in GetExistingFilename, but still
6945 ** want take advantage of the button processing, help messages, and
6946 @@ -344,23 +698,24 @@ int GetNewFilename(Widget parent, char *
6947 ** Widget existFileSB - your custom file selection box widget id
6948 ** char * filename - a string to receive the selected filename
6949 ** (this string will not be altered if the
6950 ** user pressed the cancel button)
6952 -** Returns: GFN_OK - file was selected and OK button pressed
6953 -** GFN_CANCEL - Cancel button pressed and no returned file
6954 +** Returns: HFSB_OK - file was selected and OK button pressed
6955 +** HFSB_CANCEL - Cancel button pressed and no returned file
6958 -int HandleCustomExistFileSB(Widget existFileSB, char *filename)
6959 +int handleCustomExistFileSB(Widget existFileSB, char *filename)
6961 Boolean done_with_dialog=False; /* ok to destroy dialog flag */
6962 char *fileString; /* C string for file selected */
6963 char *dirString; /* C string for dir of file selected */
6964 XmString cFileString; /* compound string for file selected */
6965 XmString cDir; /* compound directory selected */
6966 XmString cPattern; /* compound filter pattern */
6967 Widget help; /* help window form dialog */
6968 + fsbUserDataStruct* userData;
6969 #if XmVersion < 1002
6970 int i;
6971 #endif
6973 XtAddCallback(existFileSB, XmNokCallback, (XtCallbackProc)existOkCB,
6974 @@ -382,10 +737,17 @@ int HandleCustomExistFileSB(Widget exist
6975 #if XmVersion >= 1002
6976 XtVaSetValues(existFileSB, XmNinitialFocus, XtParent(
6977 XmFileSelectionBoxGetChild(existFileSB, XmDIALOG_LIST)), NULL);
6978 #endif
6979 #endif
6981 + XtVaGetValues(existFileSB, XmNuserData, &userData, NULL);
6982 + /* FIXME: The nice hidden file patch is broken by Nate's non-factoring. */
6983 + userData->cachedDirList = NULL;
6984 + userData->cachedFileList = NULL;
6985 + XtVaSetValues(existFileSB, XmNuserData, userData, NULL);
6987 ManageDialogCenteredOnPointer(existFileSB);
6989 #ifndef SGI_CUSTOM
6990 /* Typing in the directory list is dependent on the list being in the
6991 same form of alphabetical order expected by the character processing
6992 @@ -413,11 +775,11 @@ int HandleCustomExistFileSB(Widget exist
6993 #endif /* SGI_CUSTOM */
6995 while (!done_with_dialog)
6996 XtAppProcessEvent(XtWidgetToApplicationContext(existFileSB), XtIMAll);
6998 - if (SelectResult == GFN_OK) {
6999 + if (SelectResult == HFSB_OK) {
7000 XtVaGetValues(existFileSB, XmNdirSpec, &cFileString, XmNdirectory,
7001 &cDir, XmNpattern, &cPattern, NULL);
7002 /* Undocumented: file selection box widget allocates copies of these
7003 strings on getValues calls. I have risked freeing them to avoid
7004 memory leaks, since I assume other developers have made this same
7005 @@ -457,16 +819,20 @@ int HandleCustomExistFileSB(Widget exist
7006 be necessary as the shell is destroyed automatically when the dialog
7007 is. However, due to a bug in various Lesstif versions, the latter
7008 messes up the grab cascades and leaves new windows without grabs, such
7009 that they appear to be frozen. */
7010 XtDestroyWidget(XtParent(existFileSB));
7012 + freeFileList(userData->cachedDirList);
7013 + freeFileList(userData->cachedFileList);
7015 return SelectResult;
7020 -** HandleCustomNewFileSB
7021 +** handleCustomNewFileSB
7023 ** Manage a customized file selection box for opening new files.
7025 ** Arguments:
7027 @@ -475,23 +841,24 @@ int HandleCustomExistFileSB(Widget exist
7028 ** (this string will not be altered if the
7029 ** user pressed the cancel button)
7030 ** char* defaultName - default name to be pre-entered in filename
7031 ** text field.
7033 -** Returns: GFN_OK - file was selected and OK button pressed
7034 -** GFN_CANCEL - Cancel button pressed and no returned file
7035 +** Returns: HFSB_OK - file was selected and OK button pressed
7036 +** HFSB_CANCEL - Cancel button pressed and no returned file
7039 -int HandleCustomNewFileSB(Widget newFileSB, char *filename, char *defaultName)
7040 +int handleCustomNewFileSB(Widget newFileSB, char *filename, char *defaultName)
7042 Boolean done_with_dialog=False; /* ok to destroy dialog flag */
7043 Widget help; /* help window form dialog */
7044 XmString cFileString; /* compound string for file selected */
7045 XmString cDir; /* compound directory selected */
7046 XmString cPattern; /* compound filter pattern */
7047 char *fileString; /* C string for file selected */
7048 char *dirString; /* C string for dir of file selected */
7049 + fsbUserDataStruct* userData;
7050 #if XmVersion < 1002
7051 int i;
7052 #endif
7054 XtAddCallback(newFileSB, XmNokCallback, (XtCallbackProc)newFileOKCB,
7055 @@ -520,10 +887,16 @@ int HandleCustomNewFileSB(Widget newFile
7056 if ( finder != NULL )
7057 XtVaSetValues(newFileSB, XmNinitialFocus, finder, NULL);
7059 #endif
7060 #endif
7062 + XtVaGetValues(newFileSB, XmNuserData, &userData, NULL);
7063 + userData->cachedDirList = NULL;
7064 + userData->cachedFileList = NULL;
7065 + XtVaSetValues(newFileSB, XmNuserData, userData, NULL);
7067 ManageDialogCenteredOnPointer(newFileSB);
7069 #ifndef SGI_CUSTOM
7070 #if XmVersion < 1002
7071 /* To give filename text initial focus, revoke default button status for
7072 @@ -571,11 +944,11 @@ int HandleCustomNewFileSB(Widget newFile
7075 while (!done_with_dialog)
7076 XtAppProcessEvent (XtWidgetToApplicationContext(newFileSB), XtIMAll);
7078 - if (SelectResult == GFN_OK) {
7079 + if (SelectResult == HFSB_OK) {
7080 /* See note in existing file routines about freeing the values
7081 obtained in the following call */
7082 XtVaGetValues(newFileSB, XmNdirSpec, &cFileString, XmNdirectory,
7083 &cDir, XmNpattern, &cPattern, NULL);
7084 if (DefaultDirectory != NULL) XmStringFree(DefaultDirectory);
7085 @@ -603,10 +976,14 @@ int HandleCustomNewFileSB(Widget newFile
7087 XmStringFree(cFileString);
7088 XtFree(fileString);
7090 XtDestroyWidget(newFileSB);
7092 + freeFileList(userData->cachedDirList);
7093 + freeFileList(userData->cachedFileList);
7095 return SelectResult;
7099 ** Return current default directory used by GetExistingFilename.
7100 @@ -663,11 +1040,11 @@ void SetFileDialogDefaultPattern(char *p
7101 XmStringFree(DefaultPattern);
7102 DefaultPattern = pattern==NULL ? NULL : XmStringCreateSimple(pattern);
7106 -** Turn on or off the text fiend in the GetExistingFilename file selection
7107 +** Turn on or off the text field in the GetExistingFilename file selection
7108 ** box, where users can enter the filename by typing. This is redundant
7109 ** with typing in the list, and leads users who are new to nedit to miss
7110 ** the more powerful feature in favor of changing the focus and typing
7111 ** in the text field.
7113 @@ -791,11 +1168,11 @@ static void newFileOKCB(Widget w, Boolea
7114 int length; /* length of file name */
7115 int response; /* response to dialog */
7116 struct stat buf; /* status from fstat */
7118 XmStringGetLtoR(call_data->value, XmSTRING_DEFAULT_CHARSET, &filename);
7119 - SelectResult = GFN_OK;
7120 + SelectResult = HFSB_OK;
7121 length = strlen(filename);
7122 if (length == 0 || filename[length-1] == '/') {
7123 doErrorDialog("Please supply a name for the file", NULL);
7124 XtFree(filename);
7125 return;
7126 @@ -842,11 +1219,11 @@ static void newFileOKCB(Widget w, Boolea
7130 static void newFileCancelCB(Widget w, Boolean *client_data, caddr_t call_data)
7132 - SelectResult = GFN_CANCEL;
7133 + SelectResult = HFSB_CANCEL;
7134 *client_data = True;
7137 static void newHelpCB(Widget w, Widget helpPanel, caddr_t call_data)
7139 @@ -859,11 +1236,11 @@ static void existOkCB(Widget w, Boolean
7140 char *filename; /* name of chosen file */
7141 int fd; /* file descriptor */
7142 int length; /* length of file name */
7144 XmStringGetLtoR(call_data->value, XmSTRING_DEFAULT_CHARSET, &filename);
7145 - SelectResult = GFN_OK;
7146 + SelectResult = HFSB_OK;
7147 length = strlen(filename);
7148 if (length == 0 || filename[length-1] == '/') {
7149 doErrorDialog("Please select a file to open", NULL);
7150 XtFree(filename);
7151 return;
7152 @@ -879,11 +1256,11 @@ static void existOkCB(Widget w, Boolean
7156 static void existCancelCB(Widget w, Boolean * client_data, caddr_t call_data)
7158 - SelectResult = GFN_CANCEL;
7159 + SelectResult = HFSB_CANCEL;
7160 *client_data = True; /* done with dialog */
7163 static void yesNoOKCB(Widget w, caddr_t client_data, caddr_t call_data)
7165 @@ -1066,40 +1443,115 @@ static void listCharEH(Widget w, XtPoint
7166 ** and should be removed. These routines also leak memory like a seive,
7167 ** because Motif's inconsistent treatment of memory in list widgets does
7168 ** not allow us to free lists that we pass in, and most Motif versions
7169 ** don't clean it up properly.
7171 -static void replacementDirSearchProc(Widget w, XtPointer searchData)
7173 +static int restorePreviousList(Widget list, char** prevList)
7175 - Boolean updated;
7177 + int count = 0, i;
7179 + while (prevList[count]) {
7180 + ++count;
7182 + XmListDeleteAllItems(list);
7184 + for (i = 0; i < count; ++i) {
7185 + XmString s;
7186 + XmListAddItem(list, s = XmStringCreateSimple(prevList[i]), i + 1);
7187 + XtFree(prevList[i]);
7188 + XmStringFree(s);
7190 + XtFree((char*) prevList);
7191 + return count;
7194 +static int saveCurrentList(Widget list, char*** saveList)
7196 + XmString *items;
7197 + int nItems, i;
7199 + XtVaGetValues(list, XmNitems, &items, XmNitemCount, &nItems, NULL);
7200 + *saveList = (char**) XtMalloc(sizeof(char*) * (nItems + 1));
7202 + for (i = 0; i < nItems; ++i) {
7203 + char* s;
7204 + XmStringGetLtoR(items[i], XmSTRING_DEFAULT_CHARSET, &s);
7205 + (*saveList)[i] = s;
7208 + (*saveList)[nItems] = 0;
7209 + return nItems;
7212 +static void replacementDirSearchProc(Widget fileSB, XtPointer searchData)
7214 + int fileCount, newFileCount;
7215 + fsbUserDataStruct* userData;
7217 + XtVaGetValues(fileSB, XmNuserData, &userData, NULL);
7219 + if (userData->cachedDirList) {
7220 + restorePreviousList(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST),
7221 + userData->cachedDirList);
7222 + userData->cachedDirList = NULL;
7225 /* Call the original search procedure to do the actual search */
7226 - (*OrigDirSearchProc)(w, searchData);
7227 - /* Refreshing a list clears the keystroke history, even if no update. */
7228 + (*OrigDirSearchProc)(fileSB, searchData);
7229 nKeystrokes = 0;
7230 - XtVaGetValues(w, XmNlistUpdated, &updated, NULL);
7231 - if (!updated)
7232 - return;
7235 + fileCount = saveCurrentList(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST),
7236 + &userData->cachedDirList);
7238 + if (userData->showHidden)
7240 + /* Remove '.' entry */
7241 + if (removeDotEntry(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST))) {
7242 + newFileCount = fileCount -1;
7243 + } else {
7244 + newFileCount = fileCount;
7247 + } else {
7248 + /* Remove hidden files from list */
7249 + removeHiddenFiles(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST));
7251 + XtVaSetValues(fileSB, XmNlistUpdated, True, NULL);
7253 /* Sort the items in the list */
7254 - sortWidgetList(XmFileSelectionBoxGetChild(w, XmDIALOG_DIR_LIST));
7255 + sortWidgetList(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST));
7258 -static void replacementFileSearchProc(Widget w, XtPointer searchData)
7259 +static void replacementFileSearchProc(Widget fileSB, XtPointer searchData)
7261 - Boolean updated;
7263 + int fileCount;
7264 + fsbUserDataStruct* userData;
7266 + XtVaGetValues(fileSB, XmNuserData, &userData, NULL);
7268 + if (userData->cachedFileList) {
7269 + restorePreviousList(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST),
7270 + userData->cachedFileList);
7271 + userData->cachedFileList = NULL;
7274 /* Call the original search procedure to do the actual search */
7275 - (*OrigFileSearchProc)(w, searchData);
7276 - /* Refreshing a list clears the keystroke history, even if no update. */
7277 + (*OrigFileSearchProc)(fileSB, searchData);
7278 nKeystrokes = 0;
7279 - XtVaGetValues(w, XmNlistUpdated, &updated, NULL);
7280 - if (!updated)
7281 - return;
7284 + fileCount = saveCurrentList(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST),
7285 + &userData->cachedFileList);
7287 + if (!userData->showHidden) {
7288 + /* Remove hidden files from list */
7289 + removeHiddenFiles(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST));
7291 + XtVaSetValues(fileSB, XmNlistUpdated, True, NULL);
7293 /* Sort the items in the list */
7294 - sortWidgetList(XmFileSelectionBoxGetChild(w, XmDIALOG_LIST));
7295 + sortWidgetList(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST));
7299 ** Sort the items in a list widget "listWidget"
7301 @@ -1132,5 +1584,160 @@ static int compareXmStrings(const void *
7302 result = strcmp(s1, s2);
7303 XtFree(s1);
7304 XtFree(s2);
7305 return result;
7309 +** Removes the '.' entry from a listWidget
7311 +** Preconditions:
7312 +** listWidget is an XmList containing filenames
7314 +** Postcondition:
7315 +** first dotEntry in listWidget is removed
7317 +static Boolean removeDotEntry(Widget listWidget)
7319 + /* Items currently in the listWidget */
7320 + XmString* items;
7321 + int nItems;
7323 + int i;
7325 + /* read values in List into array. */
7326 + XtVaGetValues(listWidget,
7327 + XmNitems, &items,
7328 + XmNitemCount, &nItems,
7329 + NULL);
7331 + /* Traverse over items; for every item, check whether it's the dotfile;
7332 + if yes, delete it and return True. */
7333 + for (i = 0; i < nItems; i++) {
7334 + /* C string of current list item */
7335 + char* filename;
7337 + /* basename of current list item */
7338 + char basename[MAXPATHLEN + 1];
7340 + /* Convert Motif compound string to C string */
7341 + XmStringGetLtoR(items[i], XmSTRING_DEFAULT_CHARSET, &filename);
7343 + /* Get basename from list item */
7344 + ParseFilename(filename, basename, NULL);
7346 + /* Free C string, allocated by XmStringGetLtoR(). */
7347 + XtFree(filename);
7349 + /* if this is the dotEntry... */
7350 + if (0 == strcmp(basename, ".")) {
7351 + /* ...delete it and break. */
7352 + XmListDeletePos(listWidget, i + 1);
7353 + return True;
7357 + return False;
7361 +** Removes hidden files from an XmList. Hidden files are all list entries
7362 +** which are recognized as such by isHiddenFile().
7364 +** Preconditions:
7365 +** listWidget is an XmList containing filenames
7366 +** 'int isHiddenFile(const char* fullname)' exists and works.
7368 +** Postcondition:
7369 +** Hidden files in listWidget are removed
7371 +** Returns
7372 +** number of hidden files removed
7374 +static unsigned removeHiddenFiles(Widget listWidget)
7376 + /* Items currently in the listWidget */
7377 + XmString* items;
7378 + int nItems;
7380 + /* Array holding list positions of hidden files. It is allocated based
7381 + on the current number of items in the List. */
7382 + int* hiddenFilePositions;
7384 + /* Number of hidden files found */
7385 + unsigned hiddenFileCount = 0;
7387 + int i;
7389 + /* read values in List into array. */
7390 + XtVaGetValues(listWidget, XmNitems, &items, XmNitemCount, &nItems, NULL);
7392 + /* Allocate array based on number of items in List. */
7393 + hiddenFilePositions = (int*) XtMalloc(sizeof(int*) * nItems);
7395 + /* Traverse over items; for every item, check whether it's a hidden file;
7396 + if yes, put it in hiddenFilePositions[]. */
7397 + for (i = 0; i < nItems; i++) {
7398 + char* filename;
7399 + XmStringGetLtoR(items[i], XmSTRING_DEFAULT_CHARSET, &filename);
7400 + if (isHiddenFile(filename)) {
7401 + /* Add one because XmListDeletePositions expects values > 0. */
7402 + hiddenFilePositions[hiddenFileCount++] = i + 1;
7404 + XtFree(filename);
7407 + /* Do the removal. */
7408 + XmListDeletePositions(listWidget, hiddenFilePositions, hiddenFileCount);
7410 + /* Free array of positions. */
7411 + XtFree((char*) hiddenFilePositions);
7413 + return hiddenFileCount;
7417 +** Checks whether fullname is a dotfile, ie. starts with a '.'
7419 +** Preconditions:
7420 +** fullname < MAXPATHLEN
7421 +** 'void ParseFilename(fullname, filename, NULL)' exists and works
7423 +** Postcondition:
7424 +** Returns False for '..' and non-dotfiles, True for other dotfiles.
7426 +static int isHiddenFile(const char* fullname)
7428 + /* array to hold basename */
7429 + char basename[MAXPATHLEN + 1];
7431 + /* Extract basename from full filename */
7432 + ParseFilename(fullname, basename, NULL);
7434 + if (0 == strcmp(basename, "..")) {
7435 + /* Return False for parent directory */
7436 + return False;
7437 + } else {
7438 + /* Return True for dotfiles, False for other files */
7439 + return (basename[0] == '.');
7443 +static void freeFileList(char** list)
7445 + int count = 0;
7446 + int i;
7448 + if (!list) {
7449 + return;
7452 + while (list[count]) {
7453 + ++count;
7456 + for (i = 0; i < count; i++) {
7457 + XtFree(list[i]);
7460 + XtFree((char*) list);
7462 diff --quilt old/util/getfiles.h new/util/getfiles.h
7463 --- old/util/getfiles.h
7464 +++ new/util/getfiles.h
7465 @@ -26,22 +26,55 @@
7466 *******************************************************************************/
7468 #ifndef NEDIT_GETFILES_H_INCLUDED
7469 #define NEDIT_GETFILES_H_INCLUDED
7471 +#include <sys/param.h>
7473 #include <X11/Intrinsic.h>
7475 -#define GFN_OK 1 /* Get Filename OK constant */
7476 -#define GFN_CANCEL 2 /* Get Filename Cancel constant */
7478 +** The interface got smaller on functions and bigger on parameters. It's still
7479 +** a big too large for my tastes, but that's what you get.
7481 +typedef struct {
7482 + /* GUI customization */
7483 + String dialogTitle;
7484 + Boolean showHidden;
7486 + Boolean fileExists;
7487 + /* Usually only used for potentially unexisting files. */
7488 + String textfieldLabel; /* only set on new file || GetPrefStdOpenDialog() */
7489 + Boolean haveFormatButtons; /* only makes sense for new files */
7490 + String defaultName;
7492 + /* document details */
7493 + int fileFormat;
7494 + Boolean isContWrapped;
7496 + /* GUI handling */
7497 + Widget parentShell;
7498 +} gfbdParams;
7500 +enum gfdbResult {GFDB_OK, GFDB_CANCEL, GFDB_ERROR};
7501 +typedef struct {
7502 + int status;
7503 + char payload[MAXPATHLEN + 1]; /* Usually carries the filename */
7504 + Boolean addWrap;
7505 + int fileFormat;
7506 +} gfbdValue;
7508 -int GetExistingFilename(Widget parent, char *promptString, char *filename);
7509 -int GetNewFilename(Widget parent, char *promptString, char *filename,
7510 - char *defaultName);
7511 -int HandleCustomExistFileSB(Widget existFileSB, char *filename);
7512 -int HandleCustomNewFileSB(Widget newFileSB, char *filename, char *defaultName);
7513 char *GetFileDialogDefaultDirectory(void);
7514 char *GetFileDialogDefaultPattern(void);
7515 void SetFileDialogDefaultDirectory(char *dir);
7516 void SetFileDialogDefaultPattern(char *pattern);
7517 void SetGetEFTextFieldRemoval(int state);
7518 +gfbdValue* GetFilenameByDialog(const gfbdParams params);
7520 +typedef struct
7522 + Bool showHidden;
7523 + char** cachedDirList;
7524 + char** cachedFileList;
7525 +} fsbUserDataStruct;
7527 #endif /* NEDIT_GETFILES_H_INCLUDED */
7528 diff --quilt old/util/prefFile.c new/util/prefFile.c
7529 --- old/util/prefFile.c
7530 +++ new/util/prefFile.c
7531 @@ -6,11 +6,11 @@ static const char CVSID[] = "$Id: prefFi
7532 * Copyright (C) 1999 Mark Edel *
7534 * This is free software; you can redistribute it and/or modify it under the *
7535 * terms of the GNU General Public License as published by the Free Software *
7536 * Foundation; either version 2 of the License, or (at your option) any later *
7537 -* version. In addition, you may distribute version of this program linked to *
7538 +* version. In addition, you may distribute versions of this program linked to *
7539 * Motif or Open Motif. See README for details. *
7541 * This software is distributed in the hope that it will be useful, but WITHOUT *
7542 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
7543 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
7544 @@ -302,11 +302,11 @@ int SavePreferences(Display *display, co
7547 static int stringToPref(const char *string, PrefDescripRec *rsrcDescrip)
7549 int i;
7550 - char *cleanStr, *endPtr, **enumStrings;
7551 + char *cleanStr, *endPtr, **enumStrings, *cleanEnumStr;
7553 switch (rsrcDescrip->dataType) {
7554 case PREF_INT:
7555 cleanStr = removeWhiteSpace(string);
7556 *(int *)rsrcDescrip->valueAddr =
7557 @@ -338,22 +338,25 @@ static int stringToPref(const char *stri
7559 XtFree(cleanStr);
7560 *(int *)rsrcDescrip->valueAddr = False;
7561 return False;
7562 case PREF_ENUM:
7563 - cleanStr = removeWhiteSpace(string);
7564 - enumStrings = (char **)rsrcDescrip->arg;
7565 - for (i=0; enumStrings[i]!=NULL; i++) {
7566 - if (!strcmp(enumStrings[i], cleanStr)) {
7567 - *(int *)rsrcDescrip->valueAddr = i;
7568 - XtFree(cleanStr);
7569 - return True;
7572 - XtFree(cleanStr);
7573 - *(int *)rsrcDescrip->valueAddr = 0;
7574 - return False;
7575 + cleanStr = removeWhiteSpace(string);
7576 + enumStrings = (char **)rsrcDescrip->arg;
7577 + for (i=0; enumStrings[i]!=NULL; i++) {
7578 + cleanEnumStr = removeWhiteSpace(enumStrings[i]);
7579 + if (!strcmp(cleanEnumStr, cleanStr)) {
7580 + *(int *)rsrcDescrip->valueAddr = i;
7581 + XtFree(cleanStr);
7582 + XtFree(cleanEnumStr);
7583 + return True;
7585 + XtFree(cleanEnumStr);
7587 + XtFree(cleanStr);
7588 + *(int *)rsrcDescrip->valueAddr = 0;
7589 + return False;
7590 case PREF_STRING:
7591 if ((int)strlen(string) >= (int)rsrcDescrip->arg)
7592 return False;
7593 strncpy(rsrcDescrip->valueAddr, string, (int)rsrcDescrip->arg);
7594 return True;
7595 diff --quilt old/util/printUtils.c new/util/printUtils.c
7596 --- old/util/printUtils.c
7597 +++ new/util/printUtils.c
7598 @@ -6,11 +6,11 @@ static const char CVSID[] = "$Id: printU
7599 * Copyright (C) 1999 Mark Edel *
7601 * This is free software; you can redistribute it and/or modify it under the *
7602 * terms of the GNU General Public License as published by the Free Software *
7603 * Foundation; either version 2 of the License, or (at your option) any later *
7604 -* version. In addition, you may distribute version of this program linked to *
7605 +* version. In addition, you may distribute versions of this program linked to *
7606 * Motif or Open Motif. See README for details. *
7608 * This software is distributed in the hope that it will be useful, but WITHOUT *
7609 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
7610 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
7611 @@ -324,10 +324,12 @@ static Widget createForm(Widget parent)
7612 argcnt++;
7613 XtSetArg(args[argcnt], XmNdialogTitle, (st0=XmStringCreateLtoR(
7614 "Print", XmSTRING_DEFAULT_CHARSET))); argcnt++;
7615 XtSetArg(args[argcnt], XmNautoUnmanage, False); argcnt++;
7616 form = CreateFormDialog(parent, "printForm", args, argcnt);
7618 + /* Why is this not part of the arg vector? */
7619 XtVaSetValues(form, XmNshadowThickness, 0, NULL);
7621 XmStringFree( st0 );
7623 /*********************** LABEL 1 and TEXT BOX 1 *********************/