push up read_from_pipes.patch
[nedit-bw.git] / enhanced-hooks.2008-01-20.1.diff
blob708622b243a1e57ec84fecab0977952f8b2417fc
1 ReleaseNotes | 34 +
2 doc/help.etx | 109 +++++
3 source/Makefile.common | 1
4 source/Makefile.dependencies | 3
5 source/backup.c | 313 +++++++++++++++
6 source/backup.h | 66 +++
7 source/calltips.c | 334 ++++++++++++----
8 source/calltips.h | 13
9 source/file.c | 337 ++++++-----------
10 source/file.h | 7
11 source/help.c | 63 ++-
12 source/highlightData.c | 4
13 source/interpret.c | 27 +
14 source/macro.c | 271 +++++++++++--
15 source/macro.h | 3
16 source/menu.c | 254 +++++++++++-
17 source/nedit.c | 16
18 source/nedit.h | 14
19 source/preferences.c | 279 ++++++++++++--
20 source/preferences.h | 8
21 source/search.c | 159 +++++---
22 source/search.h | 10
23 source/selection.c | 49 +-
24 source/server.c | 9
25 source/shell.c | 5
26 source/text.c | 72 ++-
27 source/text.h | 14
28 source/textDisp.c | 461 ++++++++++++++++++++---
29 source/textDisp.h | 53 +-
30 source/textP.h | 5
31 source/window.c | 179 +++++++--
32 source/window.h | 6
33 util/fileUtils.c | 2
34 util/getfiles.c | 847 ++++++++++++++++++++++++++++++++++++-------
35 util/getfiles.h | 47 ++
36 util/prefFile.c | 31 -
37 util/printUtils.c | 4
38 37 files changed, 3330 insertions(+), 779 deletions(-)
40 diff --quilt old/ReleaseNotes new/ReleaseNotes
41 --- old/ReleaseNotes
42 +++ new/ReleaseNotes
43 @@ -13,11 +13,43 @@ If you are upgrading NEdit from a versio
44 the README file which came with the (source or executable) distribution kit,
45 about updating macros and font settings in your .nedit file.
47 New Features in $NEXT_VERSION
49 - - The macro variable $VERSION returns NEdit's version number.
50 + - Hidden files (dotfiles) can now be excluded from the file and directory
51 + lists in the file selection box (SF patch #502840).
53 + - A 'Smart Case' toggles the regex search caseness depending on the occur-
54 + rence of upper case letters in the search expression (SF patch #685618).
56 + - The help window got some small changes to increase usability.
58 + - The number of selected characters is displayed in the status bar.
60 + - The resource nedit.prevOpenFilesMask can be set to a regex to exclude
61 + certain files from the Open Previous menu.
63 + - Changes to the macro language:
64 + - The macro variable $NEDIT_HOME returns the name of the directory where
65 + NEdit's run control files reside.
66 + - The macro variable $VERSION returns NEdit's version number.
67 + - The function highlight_calltip_line() can highlight single lines in
68 + a macro-created calltip.
69 + - The semicolon is now a valid command seperator.
70 + - The macro subroutine typeof() returns a string indicating the type of
71 + a macro value.
73 + - If the macro routine file_open_hook() exists, it is called when an existing
74 + file is opened.
76 + - A hairline can be displayed at the wrap column (SF patch #701337).
78 + - The current line is now optionally displayed with a colored background
79 + (SF patch #683567).
81 + - Documents can now be flagged 'transient'. This disables the warning
82 + NEdit usually gives when you try to close a document which is not saved.
84 - The new macro function filename_dialog() can be used to query a file
85 name from the user by using the usual file selection dialog.
88 diff --quilt old/doc/help.etx new/doc/help.etx
89 --- old/doc/help.etx
90 +++ new/doc/help.etx
91 @@ -127,10 +127,13 @@ Getting Started
92 If you already have an empty (Untitled) window displayed, just begin typing
93 in the window. To create a new Untitled window, choose New Window or New Tab
94 from the File menu. To give the file a name and save its contents to the
95 disk, choose Save or Save As... from the File menu.
97 + In both Open and Save File Dialogs you can choose whether hidden files and
98 + directories are shown in the lists. Just check/uncheck the toggle button.
100 3>Backup Files
102 NEdit maintains periodic backups of the file you are editing so that you can
103 recover the file in the event of a problem such as a system crash, network
104 failure, or X server crash. These files are saved under the name `~filename`
105 @@ -260,10 +263,15 @@ Finding and Replacing Text
106 button with an icon resembling "|<". Clicking on it empties the search text widget
107 without disturbing selections. A middle click on the clear button copies the
108 content of any existing selection into the search text widget and triggers a new
109 search.
111 + All searches will default to the search mode selected in the preference menu.
112 + (Default Setting -> Searching -> Default Search Style). You can choose a smart
113 + case sensitivity here; this let all searches start insensitive, but changes to
114 + case sensitive as soon as you enter an upper-case letter.
116 3>Searching Backwards
118 Holding down the shift key while choosing any of the search or replace
119 commands from the menu (or using the keyboard shortcut), will search in the
120 reverse direction. Users who have set the search direction using the buttons
121 @@ -1939,13 +1947,13 @@ Macro Language
124 3>Syntax
126 An NEdit macro language program consists of a list of statements, each
127 - terminated by a newline. Groups of statements which are executed together
128 - conditionally, such as the body of a loop, are surrounded by curly braces
129 - "{}".
130 + terminated by a newline or a semicolon (;). Groups of statements which
131 + are executed together conditionally, such as the body of a loop, are
132 + surrounded by curly braces "{}".
134 Blank lines and comments are also allowed. Comments begin with a "#" and end
135 with a newline, and can appear either on a line by themselves, or at the end
136 of a statement line.
138 @@ -2536,10 +2544,16 @@ Macro Subroutines
139 yet been saved.
141 **$VERSION**
142 Returns NEdit's version number ('5006' for NEdit 5.6).
144 +**$NEDIT_HOME**
145 + Returns the name of the directory where NEdit's run control files reside.
146 + This is either the value of the environmental variable $NEDIT_HOME, the
147 + default of ~/.nedit or $HOME. (See Preferences_ for details
148 + about the algorithm.)
150 **$n_display_lines**
151 The number of lines visible in the currently active pane.
153 **$n_panes**
154 The number of panes in the current window.
155 @@ -2660,11 +2674,11 @@ Macro Subroutines
156 **filename_dialog( [title[, mode[, defaultPath[, filter[, defaultName]]]]] )**
157 Presents a file selection dialog with the given title to the user that
158 prompts for a new or existing file.
160 Options are: ~title~ will be the title of the dialog, defaults to "Choose
161 - file". If ~mode~ is set to "exist" (default), the "New File Name"TextField
162 + file". If ~mode~ is set to "exist" (default), the "New File Name" TextField
163 of the FSB will be unmanaged. If "new", the TextField will be managed.
164 ~defaultPath~ is the default path to use. Default (or "") will use the
165 active document's directory. ~filter~ is the file glob which determines
166 which files to display. Is set to "*" if filter is "" and by default.
167 ~defaultName~ is the default filename that is filled in automatically.
168 @@ -2682,12 +2696,12 @@ Macro Subroutines
169 focused window (the first window being the one returned from calling
170 focus_window("last"). Returns the name of the newly-focused window, or an
171 empty string if the requested window was not found.
173 **get_character( position )**
174 - Returns the single character at the position
175 - indicated by the first argument to the routine from the current window.
176 + Returns the single character at the position indicated by the first argument
177 + to the routine from the current window.
179 **get_range( start, end )**
180 Returns the text between a starting and ending position from the current
181 window.
183 @@ -2697,10 +2711,14 @@ Macro Subroutines
184 the screen (keyword "any").
186 **getenv( name )**
187 Gets the value of an environment variable.
189 +**highlight_calltip_line(calltip_ID, line)**
190 + Highlights a single line in the given calltip. Set line to 0 to remove
191 + any existing highlighting.
193 **kill_calltip( [calltip_ID] )**
194 Kills any calltip that is being displayed in the window in which the macro is
195 running. If there is no displayed calltip this does nothing. If a calltip
196 ID is supplied then the calltip is killed only if its ID is calltip_ID.
198 @@ -2853,10 +2871,19 @@ Macro Subroutines
199 Return an all lower-case version of string.
201 **toupper( string )**
202 Return an all upper-case version of string.
204 +**typeof( value )**
205 + Returns a string indicating the type of a macro value. The value can be
206 + any NEdit macro language value except for the return value of functions
207 + without a return value. Examples:
208 + typeof(2) # -> "INTEGER"
209 + typeof($empty_array) # -> "ARRAY"
210 + typeof(get_range(10, 20)) # -> "STRING"
211 + typeof(myArray["doesnotexist"]) # -> "UNDEFINED"
213 **valid_number( string )**
214 Returns 1 if the string can be converted to a number without error
215 following the same rules that the implicit conversion would. Otherwise 0.
217 **write_file( string, filename )**
218 @@ -3226,11 +3253,11 @@ Action Routines
219 3>Menu Action Routine Arguments
221 Arguments are text strings enclosed in quotes. Below are the menu action
222 routines which take arguments. Optional arguments are enclosed in [].
224 - **new**( ["tab" | "window" | "prefs" | "opposite"] )
225 + **new**( ["tab" | "window" | "prefs" | "opposite"] [, "transient"] )
227 **close**( ["prompt" | "save" | "nosave"] )
229 **execute_command**( shell-command )
231 @@ -3293,10 +3320,19 @@ Action Routines
232 preference
233 "opposite": Opposite of user's tab/window
234 preference
235 Default behaviour is "prefs".
237 + "transient" [EXPERIMENTAL]: Open the new
238 + document in transient mode. This disables the
239 + warning NEdit usually gives when you try to
240 + close a file which is not saved.
242 + WARNING: This is an experimental feature.
243 + Make sure to use this setting only for
244 + documents which can easily be recreated.
246 ~filename~ Path names are relative to the directory from
247 which NEdit was started. Shell interpreted
248 wildcards and `~' are not expanded.
250 ~keep-dialog~ Either "keep" or "nokeep".
251 @@ -3730,10 +3766,35 @@ Action Routines
253 **self_insert()**
254 To be attached to a key-press event, inserts the character
255 equivalent of the key pressed.
258 +Hooks
259 +-----
261 + Hooks are macro routines which are called at specific points in NEdit's
262 + execution. You can use hooks to tie in user-defined functionality at these
263 + points.
265 + No hooks are provided. To use a hook, simply define a macro function with
266 + the name of the hook. The next time the hook will catch, the macro function
267 + is called.
269 + You don't have to provide any hook. If a certain hook does not exist, it is
270 + simply skipped.
272 +**file_open_hook()**
273 + Called when an existing file is opened.
275 +..**file_name_hook(filename)**
276 +.. Called before NEdit opens a file using a certain name. The parameter is
277 +.. the filename NEdit intends to open.
279 +.. Return a string to use instead of the original filename. Return 0 to tell
280 +.. NEdit to use the original filename.
282 ----------------------------------------------------------------------
284 Customizing
285 ===========
287 @@ -3830,10 +3891,18 @@ Preferences
288 **Wrap Margin**
289 Set margin for Auto Newline Wrap, Continuous Wrap, and Fill Paragraph. Lines
290 may, be wrapped at the right margin of the window, or the margin can be set
291 at a specific column.
293 +**Show Wrap Margin**
294 + Visually indicate which column is set as the wrap margin by drawing a vertical
295 + line. Choose between never, always and when wrap is enabled. "Never" turns
296 + this feature off. "Always" will show the wrap margin irrespecitive of the
297 + wrapping style. "When Wrap is Enabled" will show the wrap margin only if
298 + continuous or auto-newline wrap styles are choosen and does not show the wrap
299 + margin if wrapping is turned off.
301 **Tab Stops**
302 Set the tab distance (number of characters between tab stops) for tab
303 characters, and control tab emulation and use of tab characters in padding
304 and emulated tabs.
306 @@ -3873,10 +3942,17 @@ Preferences
307 **Read Only**
308 Lock the file against accidental modification. This temporarily prevents the
309 file from being modified in this NEdit session. Note that this is different
310 from setting the file protection.
312 +**Transient [EXPERIMENTAL]**
313 + Flags the document as transient. This disables the warning NEdit usually
314 + gives when you try to close a file which is not saved.
316 + WARNING: This is an experimental feature. Make sure to use this setting
317 + only for documents which can easily be recreated.
319 3>Preferences -> Default Settings Menu
321 Options in the Preferences -> Default Settings menu have the same meaning as
322 those in the top-level Preferences menu, except that they apply to future
323 NEdit windows and future NEdit sessions if saved with the Save Defaults
324 @@ -3974,10 +4050,16 @@ Preferences
326 **Terminate with Line Break on Save**
327 Some UNIX tools expect that files end with a line feed. If this option is
328 activated, NEdit will append one if required.
330 +**Show Hidden Files**
331 + Show hidden files by default in file selection boxes.
333 +**Show Cursorline**
334 + Background the current line with a colored bar.
336 **Sort Open Prev. Menu**
337 Option to order the File -> Open Previous menu alphabetically, versus in
338 order of last access.
340 **Popups Under Pointer**
341 @@ -4310,10 +4392,16 @@ X Resources
343 Number of files listed in the Open Previous sub-menu of the File menu.
344 Setting this to zero disables the Open Previous menu item and maintenance of
345 the NEdit file history file.
347 +**nedit.prevOpenFilesMask**: (not defined)
349 + Files not to be listed in the Open Previous sub-menu of the File menu.
350 + Setting this to a regular expression causes files matching the expression to
351 + be omitted from the Open Previous menu item and the .neditdb file.
353 **nedit.printCommand**: (system specific)
355 Command used by the print dialog to print a file, such as, lp, lpr, etc..
356 The command must be capable of accepting input via stdin (standard input).
358 @@ -4349,10 +4437,16 @@ X Resources
359 **nedit.printDefaultHost**: (system specific)
361 The node name of the default print host. Used only to display in the print
362 dialog, and has no effect on printing.
364 +**nedit.showScrolltip**: True
366 + If this resource is set to True, NEdit will show a tooltip displaying the
367 + line number if the user grabs and moves the scroll handle. Set to False to
368 + switch it off.
370 **nedit.visualID**: Best
372 If your screen supports multiple visuals (color mapping models), this
373 resource allows you to manually choose among them. The default value of
374 "Best" chooses the deepest (most colors) visual available. Since NEdit does
375 @@ -5993,10 +6087,11 @@ Problems/Defects
376 .. Menu: Macro Language # macro_lang
377 .. Menu: M_a_cro Subroutines # macro_subrs
378 .. Menu: Rangesets # rangeset
379 .. Menu: Highlighting Information # hiliteInfo
380 .. Menu: Action Routines # actions
381 +.. Menu: H_o_oks # hooks
383 .. Menu: Customizing # customizing
384 .. Menu: Customizing NEdit # customize
385 .. Menu: Preferences # preferences
386 .. Menu: X Resources # resources
387 diff --quilt old/source/Makefile.common new/source/Makefile.common
388 --- old/source/Makefile.common
389 +++ new/source/Makefile.common
390 @@ -6,10 +6,11 @@
391 OBJS = nedit.o file.o menu.o window.o selection.o search.o undo.o shift.o \
392 help.o preferences.o tags.o userCmds.o shell.o regularExp.o macro.o \
393 text.o textSel.o textDisp.o textBuf.o textDrag.o server.o highlight.o \
394 highlightData.o interpret.o parse.o smartIndent.o regexConvert.o \
395 rbTree.o windowTitle.o calltips.o server_common.o rangeset.o
396 +OBJS += backup.o
398 XLTLIB = ../Xlt/libXlt.a
399 XMLLIB = ../Microline/XmL/libXmL.a
401 .c.o:
402 diff --quilt old/source/Makefile.dependencies new/source/Makefile.dependencies
403 --- old/source/Makefile.dependencies
404 +++ new/source/Makefile.dependencies
405 @@ -1,12 +1,13 @@
406 # $Id: Makefile.dependencies,v 1.21 2003/05/02 18:18:41 edg Exp $
407 +backup.o: backup.c backup.h
408 calltips.o: calltips.c text.h textBuf.h textP.h textDisp.h calltips.h \
409 nedit.h ../util/misc.h
410 file.o: file.c file.h nedit.h textBuf.h text.h window.h preferences.h \
411 undo.h menu.h tags.h server.h ../util/misc.h ../util/DialogF.h \
412 ../util/fileUtils.h ../util/getfiles.h ../util/printUtils.h \
413 - ../util/utils.h
414 + ../util/utils.h macro.h
415 help.o: help.c help.h help_topic.h textBuf.h text.h textP.h textDisp.h \
416 textSel.h nedit.h search.h window.h preferences.h help_data.h file.h \
417 highlight.h ../util/misc.h ../util/DialogF.h ../util/system.h
418 highlight.o: highlight.c highlight.h nedit.h textBuf.h textDisp.h text.h \
419 textP.h regularExp.h highlightData.h preferences.h window.h \
420 diff --quilt old/source/calltips.c new/source/calltips.c
421 --- old/source/calltips.c
422 +++ new/source/calltips.c
423 @@ -1,15 +1,15 @@
424 /*******************************************************************************
426 * calltips.c -- Calltip UI functions (calltip *file* functions are in tags.c) *
428 -* Copyright (C) 2002 Nathaniel Gray *
429 +* Copyright (C) 2002, 2004, 2005 The NEdit Developers *
431 * This is free software; you can redistribute it and/or modify it under the *
432 * terms of the GNU General Public License as published by the Free Software *
433 * Foundation; either version 2 of the License, or (at your option) any later *
434 -* version. In addition, you may distribute version of this program linked to *
435 +* version. In addition, you may distribute versions of this program linked to *
436 * Motif or Open Motif. See README for details. *
438 * This software is distributed in the hope that it will be useful, but WITHOUT *
439 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
440 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
441 @@ -28,29 +28,35 @@
443 #ifdef HAVE_CONFIG_H
444 #include "../config.h"
445 #endif
447 +#include "calltips.h"
449 +#include "regularExp.h"
450 #include "text.h"
451 #include "textP.h"
452 -#include "calltips.h"
453 #include "../util/misc.h"
455 #include <stdio.h>
456 #include <stdlib.h>
457 #include <string.h>
458 #include <limits.h>
460 #include <Xm/Xm.h>
461 -#include <Xm/Label.h>
462 #include <X11/Shell.h>
463 +#include <Xm/Text.h>
465 #ifdef HAVE_DEBUG_H
466 #include "../debug.h"
467 #endif
469 -static char *expandAllTabs( char *text, int tab_width );
470 +static char* expandAllTabs(const char *text, const int tab_width);
471 +Boolean getRangeOfLine(const char* textString, const unsigned line,
472 + unsigned* begin, unsigned* end);
473 +Widget createTip(const Widget parent, const Pixel foreground,
474 + const Pixel background, const unsigned char alignment);
477 ** Pop-down a calltip if one exists, else do nothing
479 void KillCalltip(WindowInfo *window, int calltipID) {
480 @@ -60,31 +66,23 @@ void KillCalltip(WindowInfo *window, int
482 void TextDKillCalltip(textDisp *textD, int calltipID) {
483 if( textD->calltip.ID == 0 )
484 return;
485 if( calltipID == 0 || calltipID == textD->calltip.ID ) {
486 - XtPopdown( textD->calltipShell );
487 + XtPopdown(XtParent(textD->calltip.widget));
488 textD->calltip.ID = 0;
493 -** Is a calltip displayed? Returns the calltip ID of the currently displayed
494 -** calltip, or 0 if there is no calltip displayed. If called with
495 -** calltipID != 0, returns 0 unless there is a calltip being
496 -** displayed with that calltipID.
497 +** Returns the calltip ID of the currently displayed calltip, or 0 if
498 +** there is no calltip displayed.
500 -int GetCalltipID(WindowInfo *window, int calltipID) {
501 +int GetCalltipID(const WindowInfo *window) {
502 textDisp *textD = ((TextWidget)window->lastFocus)->text.textD;
503 - if( calltipID == 0 )
504 - return textD->calltip.ID;
505 - else {
506 - if( calltipID == textD->calltip.ID)
507 - return calltipID;
508 - else
509 - return 0;
512 + return textD->calltip.ID;
515 #define CALLTIP_EDGE_GUARD 5
516 static Boolean offscreenV(XWindowAttributes *screenAttr, int top, int height) {
517 return (top < CALLTIP_EDGE_GUARD ||
518 @@ -129,12 +127,15 @@ void TextDRedrawCalltip(textDisp *textD,
519 return;
521 rel_x = textD->calltip.pos;
524 - XtVaGetValues(textD->calltipShell, XmNwidth, &tipWidth, XmNheight,
525 - &tipHeight, XmNborderWidth, &borderWidth, NULL);
526 + XtVaGetValues(XtParent(textD->calltip.widget),
527 + XmNwidth, &tipWidth,
528 + XmNheight, &tipHeight,
529 + XmNborderWidth, &borderWidth,
530 + NULL);
531 rel_x += borderWidth;
532 rel_y += lineHeight/2 + borderWidth;
534 /* Adjust rel_x for horizontal alignment modes */
535 if (textD->calltip.hAlign == TIP_CENTER)
536 @@ -175,119 +176,110 @@ void TextDRedrawCalltip(textDisp *textD,
537 abs_y = screenAttr.height - tipHeight - CALLTIP_EDGE_GUARD;
538 /* If no case applied, just go with the default placement. */
542 - XtVaSetValues( textD->calltipShell, XmNx, abs_x, XmNy, abs_y, NULL );
543 + XtVaSetValues(XtParent(textD->calltip.widget), XmNx, abs_x, XmNy, abs_y, NULL);
547 ** Returns a new string with each \t replaced with tab_width spaces or
548 ** a pointer to text if there were no tabs. Returns NULL on malloc failure.
549 ** Note that this is dumb replacement, not smart tab-like behavior! The goal
550 ** is to prevent tabs from turning into squares in calltips, not to get the
551 ** formatting just right.
553 -static char *expandAllTabs( char *text, int tab_width ) {
554 - int i, nTabs=0;
555 +static char* expandAllTabs(const char* text, const int tab_width)
557 + int i, nTabs = 0;
558 size_t len;
559 - char *c, *cCpy, *textCpy;
560 + const char* c;
561 + char *cCpy, *textCpy;
563 /* First count 'em */
564 - for( c = text; *c; ++c )
565 - if( *c == '\t' )
566 + for (c = (char*) text; *c; ++c) {
567 + if ('\t' == *c)
568 ++nTabs;
569 - if( nTabs == 0 )
570 - return text;
572 + if (0 == nTabs) {
573 + return strdup(text);
576 /* Allocate the new string */
577 - len = strlen( text ) + ( tab_width - 1 )*nTabs;
578 - textCpy = (char*)malloc( len + 1 );
579 - if( !textCpy ) {
580 - fprintf(stderr,
581 - "nedit: Out of heap memory in expandAllTabs!\n");
582 + len = strlen(text) + (tab_width - 1) * nTabs;
583 + textCpy = (char*) malloc(len + 1);
584 + if (!textCpy) {
585 + fprintf(stderr, "nedit: Out of heap memory in expandAllTabs!\n");
586 return NULL;
589 /* Now replace 'em */
590 - for( c = text, cCpy = textCpy; *c; ++c, ++cCpy) {
591 - if( *c == '\t' ) {
592 - for( i = 0; i < tab_width; ++i, ++cCpy )
593 + for (c = text, cCpy = textCpy; *c; ++c, ++cCpy) {
594 + if (*c == '\t') {
595 + for (i = 0; i < tab_width; ++i, ++cCpy) {
596 *cCpy = ' ';
598 --cCpy; /* Will be incremented in outer for loop */
599 - } else
600 + } else {
601 *cCpy = *c;
604 *cCpy = '\0';
605 return textCpy;
609 -** Pop-up a calltip.
610 -** If a calltip is already being displayed it is destroyed and replaced with
611 -** the new calltip. Returns the ID of the calltip or 0 on failure.
612 +** Pop-up a calltip.
614 +** If a calltip is already being displayed it is destroyed and replaced
615 +** with the new calltip.
617 +** Returns the ID of the calltip or 0 on failure.
619 -int ShowCalltip(WindowInfo *window, char *text, Boolean anchored,
620 - int pos, int hAlign, int vAlign, int alignMode) {
621 - static int StaticCalltipID = 1;
622 +int ShowCalltip(const WindowInfo *window, const char *text,
623 + const Boolean anchored, const int pos, const int hAlign,
624 + const int vAlign, const int alignMode)
626 + static unsigned StaticCalltipID = 1;
627 textDisp *textD = ((TextWidget)window->lastFocus)->text.textD;
628 int rel_x, rel_y;
629 - Position txtX, txtY;
630 - char *textCpy;
631 - XmString str;
632 + char* tablessText;
634 /* Destroy any previous calltip */
635 - TextDKillCalltip( textD, 0 );
636 + TextDKillCalltip(textD, 0);
638 /* Make sure the text isn't NULL */
639 if (text == NULL) return 0;
641 - /* Expand any tabs in the calltip and make it an XmString */
642 - textCpy = expandAllTabs( text, BufGetTabDistance(textD->buffer) );
643 - if( textCpy == NULL )
644 + /* Expand any tabs in the calltip */
645 + tablessText = expandAllTabs(text, BufGetTabDistance(textD->buffer));
646 + if (NULL == tablessText) {
647 return 0; /* Out of memory */
648 - str = XmStringCreateLtoR(textCpy, XmFONTLIST_DEFAULT_TAG);
649 - if( textCpy != text )
650 - free( textCpy );
652 - /* Get the location/dimensions of the text area */
653 - XtVaGetValues(textD->w,
654 - XmNx, &txtX,
655 - XmNy, &txtY,
656 - NULL);
660 /* Create the calltip widget on first request */
661 - if (textD->calltipW == NULL) {
662 - Arg args[10];
663 - int argcnt = 0;
664 - XtSetArg(args[argcnt], XmNsaveUnder, True); argcnt++;
665 - XtSetArg(args[argcnt], XmNallowShellResize, True); argcnt++;
667 - textD->calltipShell = CreatePopupShellWithBestVis("calltipshell",
668 - overrideShellWidgetClass, textD->w, args, argcnt);
670 - /* Might want to make this a read-only XmText eventually so that
671 - users can copy from it */
672 - textD->calltipW = XtVaCreateManagedWidget(
673 - "calltip", xmLabelWidgetClass, textD->calltipShell,
674 - XmNborderWidth, 1, /* Thin borders */
675 - XmNhighlightThickness, 0,
676 - XmNalignment, XmALIGNMENT_BEGINNING,
677 - XmNforeground, textD->calltipFGPixel,
678 - XmNbackground, textD->calltipBGPixel,
679 - NULL );
682 - /* Set the text on the label */
683 - XtVaSetValues( textD->calltipW, XmNlabelString, str, NULL );
684 - XmStringFree( str );
685 + if (NULL == textD->calltip.widget) {
686 + textD->calltip.widget = createTip(textD->w, textD->calltipFGPixel,
687 + textD->calltipBGPixel, XmALIGNMENT_BEGINNING);
690 + /* The text widget will keep the size of the largest text it contained
691 + over its lifetime unless we do something about it. So we set it to
692 + minimum size and let the resize functionality do its work to get it
693 + back up again matching the current text. */
694 + XtVaSetValues(textD->calltip.widget,
695 + XmNheight, 10,
696 + XmNwidth, 10,
697 + NULL);
698 + XmTextSetString(textD->calltip.widget, tablessText);
699 + free(tablessText);
701 /* Figure out where to put the tip */
702 if (anchored) {
703 /* Put it at the specified position */
704 /* If position is not displayed, return 0 */
705 - if (pos < textD->firstChar || pos > textD->lastChar ) {
706 + if (pos < textD->firstChar || pos > textD->lastChar) {
707 XBell(TheDisplay, 0);
708 return 0;
710 textD->calltip.pos = pos;
711 } else {
712 @@ -311,15 +303,179 @@ int ShowCalltip(WindowInfo *window, char
713 textD->calltip.vAlign = vAlign;
714 textD->calltip.alignMode = alignMode;
716 /* Increment the static calltip ID. Macro variables can only be int,
717 not unsigned, so have to work to keep it > 0 on overflow */
718 - if(++StaticCalltipID <= 0)
719 + /* Macro variables can only be int, that's why you have to keep the ID
720 + in the unsigned range? */
721 + if (++StaticCalltipID <= 0) {
722 StaticCalltipID = 1;
725 /* Realize the calltip's shell so that its width & height are known */
726 - XtRealizeWidget( textD->calltipShell );
727 + XtRealizeWidget(XtParent(textD->calltip.widget));
729 /* Move the calltip and pop it up */
730 TextDRedrawCalltip(textD, 0);
731 - XtPopup( textD->calltipShell, XtGrabNone );
732 + XtPopup(XtParent(textD->calltip.widget), XtGrabNone);
734 return textD->calltip.ID;
738 +** Highlight a single line in a given calltip, erasing all other highlights.
740 +** Return values for this one need to be a bit more expressive. Some errors
741 +** might just be the result of sloppy parameters, and the caller should
742 +** decide whether to fail hard or not. The following results are possible:
744 +** - The calltip ID given is invalid (CT_INVALID_ID).
745 +** - The user requested to remove all highlightings (CT_OK).
746 +** - The requested line is highlighted (CT_OK).
747 +** - The requested line is not in the provided text (CT_NOLINE).
749 +int HighlightCalltipLine(const WindowInfo* window, const int calltipID,
750 + const unsigned line)
752 + textDisp* textD = ((TextWidget) window->lastFocus)->text.textD;
753 + Boolean result = False;
755 + if (calltipID == textD->calltip.ID) {
756 + Widget textWidget = textD->calltip.widget;
757 + char* textString = XmTextGetString(textWidget);
758 + XmTextPosition textLength = XmTextGetLastPosition(textWidget);
759 + unsigned begin = 0, end = 0;
760 + Boolean lineIsValid = False;
762 + /* First remove all existing highlights. */
763 + XmTextSetHighlight(textWidget, 0, textLength + 1, XmHIGHLIGHT_NORMAL);
765 + if (0 == line) {
766 + /* Just return without highlighting anything. */
767 + result = CT_OK;
768 + } else {
769 + lineIsValid = getRangeOfLine(textString, line, &begin, &end);
770 + if (lineIsValid) {
771 + XmTextSetHighlight(textWidget, (XmTextPosition) begin,
772 + (XmTextPosition) end, XmHIGHLIGHT_SELECTED);
774 + result = CT_OK;
775 + } else {
776 + /* The requested line is not in the provided text. */
777 + result = CT_NOLINE;
781 + XtFree(textString);
782 + } else {
783 + result = CT_INVALID_ID;
786 + return result;
790 +** Sets the parameters to beginning and end of the line. Returns False if
791 +** the line is not in the text, True otherwise.
793 +Boolean getRangeOfLine(const char* textString, const unsigned line,
794 + unsigned* begin, unsigned* end)
796 + int i;
797 + size_t position = 0;
799 + for (i = 0; i < line; i++)
801 + *end = strcspn(textString + position, "\n") + position;
802 + *begin = position;
803 + position = *end + 1;
805 + if (*begin == *end)
807 + /* Break if last line is found. */
808 + break;
812 + return (*begin != *end);
816 +** Pop up a scroll calltip.
818 +Boolean ShowScrolltip(textDisp* textD, const char* text, const int x,
819 + const int y)
821 + if (NULL == textD->scrolltip) {
822 + textD->scrolltip = createTip(textD->w, textD->calltipFGPixel,
823 + textD->calltipBGPixel, XmALIGNMENT_CENTER);
826 + /* Set the text on the tip's label. */
827 + XmTextSetString(textD->scrolltip, (char*) text);
829 + /* Realize the calltip's shell so that its width and height are known */
830 + XtRealizeWidget(XtParent(textD->scrolltip));
832 + /* Move the tip where it belongs and pop it up. */
833 + XtVaSetValues(XtParent(textD->scrolltip), XmNx, x, XmNy, y, NULL);
834 + XtPopup(XtParent(textD->scrolltip), XtGrabNone);
836 + return True;
840 +** Pop down scrolltip if it exists
842 +void KillScrolltip(textDisp* textD)
844 + if (NULL != textD->scrolltip && NULL != XtParent(textD->scrolltip)) {
845 + XtPopdown(XtParent(textD->scrolltip));
850 +** This creates a calltip of class XmText and its parent, a shell of class
851 +** OverrideShell (which in turn will be the child of the grandfather
852 +** parameter). The tip will have minimum size but will resize to match
853 +** the text entered (see XmNallowShellResize).
855 +** Color is picked by the two parameters foreground and background.
857 +** The alignment is on of XmALIGNMENT_BEGINNING, XmALIGNMENT_CENTER or
858 +** XmALIGNMENT_END, taken from the XmLabel class.
860 +** TODO: Some helper functions are still desirable to make this function
861 +** available from other parts of the code. At the moment the caller must
862 +** use calls to Motif/Intrinsics functions to handle it.
865 +Widget createTip(const Widget grandfather, const Pixel foreground,
866 + const Pixel background, const unsigned char alignment)
868 + Widget tip = NULL;
869 + Widget shell = NULL;
870 + Arg args[10];
871 + int argc = 0;
873 + XtSetArg(args[argc], XmNsaveUnder, True); argc++;
874 + XtSetArg(args[argc], XmNallowShellResize, True); argc++;
876 + shell = CreatePopupShellWithBestVis("tipshell", overrideShellWidgetClass,
877 + grandfather, args, argc);
879 + tip = XtVaCreateManagedWidget("tip",
880 + xmTextWidgetClass, shell,
881 + XmNhighlightThickness, 0,
882 + XmNalignment, alignment,
883 + XmNeditable, False,
884 + XmNeditMode, XmMULTI_LINE_EDIT,
885 + XmNcursorPositionVisible, False,
886 + XmNresizeHeight, True,
887 + XmNresizeWidth, True,
888 + XmNforeground, foreground,
889 + XmNbackground, background,
890 + XmNheight, 10, /* will be resized automatically */
891 + XmNwidth, 10, /* will be resized automatically */
892 + NULL);
893 + return tip;
895 diff --quilt old/source/calltips.h new/source/calltips.h
896 --- old/source/calltips.h
897 +++ new/source/calltips.h
898 @@ -36,14 +36,21 @@
901 enum TipHAlignMode {TIP_LEFT, TIP_CENTER, TIP_RIGHT};
902 enum TipVAlignMode {TIP_ABOVE, TIP_BELOW};
903 enum TipAlignStrict {TIP_SLOPPY, TIP_STRICT};
904 +enum TipHighlightError {CT_OK, CT_INVALID_ID, CT_NOLINE};
906 -int ShowCalltip(WindowInfo *window, char *text, Boolean anchored,
907 - int pos, int hAlign, int vAlign, int alignMode);
908 +int ShowCalltip(const WindowInfo *window, const char *text,
909 + const Boolean anchored, const int pos, const int hAlign,
910 + const int vAlign, const int alignMode);
911 void KillCalltip(WindowInfo *window, int calltipID);
912 +Boolean ShowScrolltip(textDisp* textD, const char* text, const int x,
913 + const int y);
914 +void KillScrolltip(textDisp* textD);
915 void TextDKillCalltip(textDisp *textD, int calltipID);
916 -int GetCalltipID(WindowInfo *window, int calltipID);
917 +int GetCalltipID(const WindowInfo *window);
918 void TextDRedrawCalltip(textDisp *textD, int calltipID);
919 +int HighlightCalltipLine(const WindowInfo* window, const int calltipID,
920 + const unsigned line);
922 #endif /* ifndef NEDIT_CALLTIPS_H_INCLUDED */
923 diff --quilt old/source/file.c new/source/file.c
924 --- old/source/file.c
925 +++ new/source/file.c
926 @@ -30,19 +30,22 @@ static const char CVSID[] = "$Id: file.c
927 #ifdef HAVE_CONFIG_H
928 #include "../config.h"
929 #endif
931 #include "file.h"
933 +#include "backup.h"
934 #include "textBuf.h"
935 #include "text.h"
936 #include "window.h"
937 #include "preferences.h"
938 #include "undo.h"
939 #include "menu.h"
940 #include "tags.h"
941 #include "server.h"
942 #include "interpret.h"
943 +#include "macro.h"
944 #include "../util/misc.h"
945 #include "../util/DialogF.h"
946 #include "../util/fileUtils.h"
947 #include "../util/getfiles.h"
948 #include "../util/printUtils.h"
949 @@ -73,10 +76,15 @@ static const char CVSID[] = "$Id: file.c
950 #include <Xm/ToggleB.h>
951 #include <Xm/FileSB.h>
952 #include <Xm/RowColumn.h>
953 #include <Xm/Form.h>
954 #include <Xm/Label.h>
955 +#include <Xm/PushB.h>
957 +/* What kinds of backup files to make -- see
958 + table `version_control_values' in backup.c. */
959 +static enum backup_mode version_control;
961 #ifdef HAVE_DEBUG_H
962 #include "../debug.h"
963 #endif
965 @@ -84,22 +92,22 @@ static const char CVSID[] = "$Id: file.c
966 The periodic check is only performed on buffer modification, and the check
967 interval is only to prevent checking on every keystroke in case of a file
968 system which is slow to process stat requests (which I'm not sure exists) */
969 #define MOD_CHECK_INTERVAL 3000
971 +#define MAX_X_ARGS 20 /* Maximum number of X arguments */
973 static int doSave(WindowInfo *window);
974 static void safeClose(WindowInfo *window);
975 static int doOpen(WindowInfo *window, const char *name, const char *path,
976 int flags);
977 static void backupFileName(WindowInfo *window, char *name, size_t len);
978 static int writeBckVersion(WindowInfo *window);
979 static int bckError(WindowInfo *window, const char *errString, const char *file);
980 static int fileWasModifiedExternally(WindowInfo *window);
981 static const char *errorString(void);
982 static void addWrapNewlines(WindowInfo *window);
983 -static void setFormatCB(Widget w, XtPointer clientData, XtPointer callData);
984 -static void addWrapCB(Widget w, XtPointer clientData, XtPointer callData);
985 static int cmpWinAgainstFile(WindowInfo *window, const char *fileName);
986 static int min(int i1, int i2);
987 static void modifiedWindowDestroyedCB(Widget w, XtPointer clientData,
988 XtPointer callData);
989 static void forceShowLineNumbers(WindowInfo *window);
990 @@ -107,11 +115,11 @@ static void forceShowLineNumbers(WindowI
991 #ifdef VMS
992 void removeVersionNumber(char *fileName);
993 #endif /*VMS*/
995 WindowInfo *EditNewFile(WindowInfo *inWindow, char *geometry, int iconic,
996 - const char *languageMode, const char *defaultPath)
997 + const char* languageMode, const char* defaultPath, Boolean transient)
999 char name[MAXPATHLEN];
1000 WindowInfo *window;
1002 /*... test for creatability? */
1003 @@ -143,11 +151,19 @@ WindowInfo *EditNewFile(WindowInfo *inWi
1005 if (iconic && IsIconic(window))
1006 RaiseDocument(window);
1007 else
1008 RaiseDocumentWindow(window);
1011 + if (transient) {
1012 + /* Set the window to transient mode. */
1013 + String apParams[1];
1015 + apParams[0] = "1";
1016 + XtCallActionProc(window->lastFocus, "set_transient", NULL, apParams, 1);
1019 SortTabBar(window);
1020 return window;
1024 @@ -173,11 +189,11 @@ WindowInfo *EditExistingFile(WindowInfo
1025 const char *path, int flags, char *geometry, int iconic,
1026 const char *languageMode, int tabbed, int bgOpen)
1028 WindowInfo *window;
1029 char fullname[MAXPATHLEN];
1032 /* first look to see if file is already displayed in a window */
1033 window = FindWindowWithFile(name, path);
1034 if (window != NULL) {
1035 if (!bgOpen) {
1036 if (iconic)
1037 @@ -248,10 +264,13 @@ WindowInfo *EditExistingFile(WindowInfo
1038 strcat(fullname, name);
1039 if(GetPrefAlwaysCheckRelTagsSpecs())
1040 AddRelTagsFile(GetPrefTagFile(), path, TAG);
1041 AddToPrevOpenMenu(fullname);
1043 + /* file_open_hook() */
1044 + MacroApplyHook(window, "file_open_hook", 0, NULL, NULL);
1046 return window;
1049 void RevertToSaved(WindowInfo *window)
1051 @@ -337,11 +356,11 @@ static int doOpen(WindowInfo *window, co
1052 int fileLen, readLen;
1053 char *fileString, *c;
1054 FILE *fp = NULL;
1055 int fd;
1056 int resp;
1059 /* initialize lock reasons */
1060 CLEAR_ALL_LOCKS(window->lockReasons);
1062 /* Update the window data structure */
1063 strcpy(window->filename, name);
1064 @@ -536,10 +555,14 @@ static int doOpen(WindowInfo *window, co
1067 SET_TMBD_LOCKED(window->lockReasons, TRUE);
1068 for (c = fileString; c < &fileString[readLen]; c++) {
1069 if (*c == '\0') {
1070 + /* Looks like every NUL character is replaced with:
1071 + ISO 8859-1: LATIN SMALL LETTER THORN
1072 + ISO 8859-7: GREEK SMALL LETTER OMEGA WITH TONOS
1073 + UTF-8: <unused> */
1074 *c = (char) 0xfe;
1077 window->buffer->nullSubsChar = (char) 0xfe;
1079 @@ -705,20 +728,21 @@ int CloseFileAndWindow(WindowInfo *windo
1081 /* Make sure that the window is not in iconified state */
1082 if (window->fileChanged)
1083 RaiseDocumentWindow(window);
1085 - /* If the window is a normal & unmodified file or an empty new file,
1086 - or if the user wants to ignore external modifications then
1087 - just close it. Otherwise ask for confirmation first. */
1088 - if (!window->fileChanged &&
1089 - /* Normal File */
1090 - ((!window->fileMissing && window->lastModTime > 0) ||
1091 - /* New File*/
1092 - (window->fileMissing && window->lastModTime == 0) ||
1093 - /* File deleted/modified externally, ignored by user. */
1094 - !GetPrefWarnFileMods()))
1095 + /* If the document is transient, belongs to a normal & unmodified file
1096 + or is empty and unchanged, or if the user wants to ignore external
1097 + modifications then just close it. Otherwise ask for confirmation first. */
1098 + if (window->transient
1099 + || (!window->fileChanged
1100 + /* Normal document, already saved */
1101 + && ((!window->fileMissing && window->lastModTime > 0)
1102 + /* New document, unchanged yet */
1103 + || (window->fileMissing && window->lastModTime == 0)
1104 + /* File deleted/modified externally, ignored by user. */
1105 + || !GetPrefWarnFileMods())))
1107 CloseWindow(window);
1108 /* up-to-date windows don't have outstanding backup files to close */
1109 } else
1111 @@ -908,10 +932,11 @@ static int doSave(WindowInfo *window)
1112 char *fileString = NULL;
1113 char fullname[MAXPATHLEN];
1114 struct stat statbuf;
1115 FILE *fp;
1116 int fileLen, result;
1117 + DataValue* fileNameArg = (DataValue*) XtMalloc(sizeof(DataValue));
1119 /* Get the full name of the file */
1120 strcpy(fullname, window->path);
1121 strcat(fullname, window->filename);
1123 @@ -1045,10 +1070,14 @@ static int doSave(WindowInfo *window)
1124 window->fileMissing = TRUE;
1125 window->device = 0;
1126 window->inode = 0;
1129 + fileNameArg->tag = STRING_TAG;
1130 + AllocNStringNCpy(&fileNameArg->val.str, fullname, MAXPATHLEN);
1131 + MacroApplyHook(window, "post_save_hook", 1, fileNameArg, NULL);
1133 return TRUE;
1137 ** Create a backup file for the current window. The name for the backup file
1138 @@ -1182,38 +1211,52 @@ static void backupFileName(WindowInfo *w
1140 static int writeBckVersion(WindowInfo *window)
1142 #ifndef VMS
1143 char fullname[MAXPATHLEN], bckname[MAXPATHLEN];
1144 + char* backname;
1145 struct stat statbuf;
1146 int in_fd, out_fd;
1147 char *io_buffer;
1148 + off_t fileLen;
1149 #define IO_BUFFER_SIZE ((size_t)(1024*1024))
1151 /* Do only if version backups are turned on */
1152 if (!window->saveOldVersion) {
1153 return False;
1156 + /* First fime numbered backup files are used. */
1157 + if (unset == version_control) {
1158 + initialize_backups();
1161 /* Get the full name of the file */
1162 strcpy(fullname, window->path);
1163 strcat(fullname, window->filename);
1165 + backname = generate_backup_filename(version_control, fullname);
1166 + if ((fileLen = strlen(backname)) < MAXPATHLEN) {
1167 + strncpy(bckname, backname, sizeof(bckname));
1169 + free(backname);
1171 /* Generate name for old version */
1172 - if ((strlen(fullname) + 5) > (size_t) MAXPATHLEN) {
1173 + if (fileLen >= (size_t) MAXPATHLEN) {
1174 return bckError(window, "file name too long", window->filename);
1176 - sprintf(bckname, "%s.bck", fullname);
1178 /* Delete the old backup file */
1179 /* Errors are ignored; we'll notice them later. */
1180 remove(bckname);
1182 /* open the file being edited. If there are problems with the
1183 old file, don't bother the user, just skip the backup */
1184 in_fd = open(fullname, O_RDONLY);
1185 if (in_fd<0) {
1186 + /* This is rather surprising behavior. Let's see more about the error. */
1187 + perror("nedit: Error reading edited file");
1188 return FALSE;
1191 /* Get permissions of the file.
1192 We preserve the normal permissions but not ownership, extended
1193 @@ -1415,162 +1458,98 @@ void PrintString(const char *string, int
1194 #endif /*VMS*/
1195 return;
1199 -** Wrapper for GetExistingFilename which uses the current window's path
1200 -** (if set) as the default directory.
1201 +** Wrapper for GetFilenameByDialog()
1203 +** TODO: I stopped the refactoring here for now, but these two could
1204 +** be combined into some sort of PromptFor.*File().
1206 int PromptForExistingFile(WindowInfo *window, char *prompt, char *fullname)
1208 - char *savedDefaultDir;
1209 - int retVal;
1211 - /* Temporarily set default directory to window->path, prompt for file,
1212 - then, if the call was unsuccessful, restore the original default
1213 - directory */
1214 - savedDefaultDir = GetFileDialogDefaultDirectory();
1215 - if (*window->path != '\0')
1216 - SetFileDialogDefaultDirectory(window->path);
1217 - retVal = GetExistingFilename(window->shell, prompt, fullname);
1218 - if (retVal != GFN_OK)
1219 - SetFileDialogDefaultDirectory(savedDefaultDir);
1221 - XtFree(savedDefaultDir);
1222 + gfbdParams params;
1223 + gfbdValue* gfbdrc;
1224 + int rc = GFN_ERROR;
1226 + params.dialogTitle = prompt;
1227 + params.parentShell = window->shell;
1228 + params.fileExists = True;
1229 + params.textfieldLabel = (GetPrefStdOpenDialog() ? "File Name" : NULL);
1230 + params.defaultName = NULL;
1231 + params.haveFormatButtons = False;
1232 + /* ...so no file format for wrap info necessary. */
1233 + params.showHidden = GetPrefShowHiddenFiles();
1235 + gfbdrc = GetFilenameByDialog(params);
1237 + switch(gfbdrc->status) {
1238 + case GFDB_OK:
1239 + strncpy(fullname, gfbdrc->payload, MAXPATHLEN);
1240 + rc = GFN_OK;
1241 + break;
1242 + case GFDB_CANCEL:
1243 + rc = GFN_CANCEL;
1244 + break;
1245 + case GFDB_ERROR:
1246 + fprintf(stderr, "nedit: Error while calling GetFilenameByDialog(): %s\n", gfbdrc->payload);
1247 + rc = GFN_ERROR;
1248 + break;
1249 + default:
1250 + /* fallback */
1251 + fprintf(stderr, "nedit: Unexpected error in GetFilenameByDialog().\n");
1252 + rc = GFN_ERROR;
1253 + break;
1256 - return retVal;
1257 + return rc;
1261 -** Wrapper for HandleCustomNewFileSB which uses the current window's path
1262 -** (if set) as the default directory, and asks about embedding newlines
1263 -** to make wrapping permanent.
1264 +** Wrapper for GetFilenameByDialog()
1266 int PromptForNewFile(WindowInfo *window, char *prompt, char *fullname,
1267 int *fileFormat, int *addWrap)
1269 - int n, retVal;
1270 - Arg args[20];
1271 - XmString s1, s2;
1272 - Widget fileSB, wrapToggle;
1273 - Widget formatForm, formatBtns, unixFormat, dosFormat, macFormat;
1274 - char *savedDefaultDir;
1276 - *fileFormat = window->fileFormat;
1278 - /* Temporarily set default directory to window->path, prompt for file,
1279 - then, if the call was unsuccessful, restore the original default
1280 - directory */
1281 - savedDefaultDir = GetFileDialogDefaultDirectory();
1282 - if (*window->path != '\0')
1283 - SetFileDialogDefaultDirectory(window->path);
1285 - /* Present a file selection dialog with an added field for requesting
1286 - long line wrapping to become permanent via inserted newlines */
1287 - n = 0;
1288 - XtSetArg(args[n],
1289 - XmNselectionLabelString,
1290 - s1 = XmStringCreateLocalized("New File Name:")); n++;
1291 - XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
1292 - XtSetArg(args[n],
1293 - XmNdialogTitle,
1294 - s2 = XmStringCreateSimple(prompt)); n++;
1295 - fileSB = CreateFileSelectionDialog(window->shell,"FileSelect",args,n);
1296 - XmStringFree(s1);
1297 - XmStringFree(s2);
1298 - formatForm = XtVaCreateManagedWidget("formatForm", xmFormWidgetClass,
1299 - fileSB, NULL);
1300 - formatBtns = XtVaCreateManagedWidget("formatBtns",
1301 - xmRowColumnWidgetClass, formatForm,
1302 - XmNradioBehavior, XmONE_OF_MANY,
1303 - XmNorientation, XmHORIZONTAL,
1304 - XmNpacking, XmPACK_TIGHT,
1305 - XmNtopAttachment, XmATTACH_FORM,
1306 - XmNleftAttachment, XmATTACH_FORM,
1307 - NULL);
1308 - XtVaCreateManagedWidget("formatBtns", xmLabelWidgetClass, formatBtns,
1309 - XmNlabelString, s1=XmStringCreateSimple("Format:"), NULL);
1310 - XmStringFree(s1);
1311 - unixFormat = XtVaCreateManagedWidget("unixFormat",
1312 - xmToggleButtonWidgetClass, formatBtns,
1313 - XmNlabelString, s1 = XmStringCreateSimple("Unix"),
1314 - XmNset, *fileFormat == UNIX_FILE_FORMAT,
1315 - XmNuserData, (XtPointer)UNIX_FILE_FORMAT,
1316 - XmNmarginHeight, 0,
1317 - XmNalignment, XmALIGNMENT_BEGINNING,
1318 - XmNmnemonic, 'U',
1319 - NULL);
1320 - XmStringFree(s1);
1321 - XtAddCallback(unixFormat, XmNvalueChangedCallback, setFormatCB,
1322 - fileFormat);
1323 - dosFormat = XtVaCreateManagedWidget("dosFormat",
1324 - xmToggleButtonWidgetClass, formatBtns,
1325 - XmNlabelString, s1 = XmStringCreateSimple("DOS"),
1326 - XmNset, *fileFormat == DOS_FILE_FORMAT,
1327 - XmNuserData, (XtPointer)DOS_FILE_FORMAT,
1328 - XmNmarginHeight, 0,
1329 - XmNalignment, XmALIGNMENT_BEGINNING,
1330 - XmNmnemonic, 'O',
1331 - NULL);
1332 - XmStringFree(s1);
1333 - XtAddCallback(dosFormat, XmNvalueChangedCallback, setFormatCB,
1334 - fileFormat);
1335 - macFormat = XtVaCreateManagedWidget("macFormat",
1336 - xmToggleButtonWidgetClass, formatBtns,
1337 - XmNlabelString, s1 = XmStringCreateSimple("Macintosh"),
1338 - XmNset, *fileFormat == MAC_FILE_FORMAT,
1339 - XmNuserData, (XtPointer)MAC_FILE_FORMAT,
1340 - XmNmarginHeight, 0,
1341 - XmNalignment, XmALIGNMENT_BEGINNING,
1342 - XmNmnemonic, 'M',
1343 - NULL);
1344 - XmStringFree(s1);
1345 - XtAddCallback(macFormat, XmNvalueChangedCallback, setFormatCB,
1346 - fileFormat);
1347 - if (window->wrapMode == CONTINUOUS_WRAP) {
1348 - wrapToggle = XtVaCreateManagedWidget("addWrap",
1349 - xmToggleButtonWidgetClass, formatForm,
1350 - XmNlabelString, s1 = XmStringCreateSimple("Add line breaks where wrapped"),
1351 - XmNalignment, XmALIGNMENT_BEGINNING,
1352 - XmNmnemonic, 'A',
1353 - XmNtopAttachment, XmATTACH_WIDGET,
1354 - XmNtopWidget, formatBtns,
1355 - XmNleftAttachment, XmATTACH_FORM,
1356 - NULL);
1357 - XtAddCallback(wrapToggle, XmNvalueChangedCallback, addWrapCB,
1358 - addWrap);
1359 - XmStringFree(s1);
1361 - *addWrap = False;
1362 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_FILTER_LABEL),
1363 - XmNmnemonic, 'l',
1364 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_FILTER_TEXT),
1365 - NULL);
1366 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST_LABEL),
1367 - XmNmnemonic, 'D',
1368 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST),
1369 - NULL);
1370 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST_LABEL),
1371 - XmNmnemonic, 'F',
1372 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST),
1373 - NULL);
1374 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_SELECTION_LABEL),
1375 - XmNmnemonic, prompt[strspn(prompt, "lFD")],
1376 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_TEXT),
1377 - NULL);
1378 - AddDialogMnemonicHandler(fileSB, FALSE);
1379 - RemapDeleteKey(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_FILTER_TEXT));
1380 - RemapDeleteKey(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_TEXT));
1381 - retVal = HandleCustomNewFileSB(fileSB, fullname,
1382 - window->filenameSet ? window->filename : NULL);
1383 + gfbdParams params;
1384 + gfbdValue* gfbdrc;
1385 + int rc = GFN_ERROR;
1387 + params.dialogTitle = prompt;
1388 + params.parentShell = window->shell;
1389 + params.fileExists = False;
1390 + params.textfieldLabel = "New File Name";
1391 + params.defaultName = window->filenameSet ? window->filename : NULL;
1392 + params.haveFormatButtons = True;
1393 + params.fileFormat = window->fileFormat;
1394 + params.isContWrapped = (CONTINUOUS_WRAP == window->wrapMode);
1395 + params.showHidden = GetPrefShowHiddenFiles();
1397 - if (retVal != GFN_OK)
1398 - SetFileDialogDefaultDirectory(savedDefaultDir);
1399 + gfbdrc = GetFilenameByDialog(params);
1400 + *addWrap = False;
1402 - XtFree(savedDefaultDir);
1403 + switch(gfbdrc->status) {
1404 + case GFDB_OK:
1405 + strncpy(fullname, gfbdrc->payload, MAXPATHLEN);
1406 + *addWrap = gfbdrc->addWrap;
1407 + rc = GFN_OK;
1408 + break;
1409 + case GFDB_CANCEL:
1410 + rc = GFN_CANCEL;
1411 + break;
1412 + case GFDB_ERROR:
1413 + fprintf(stderr, "nedit: Error while calling GetFilenameByDialog(): %s\n", gfbdrc->payload);
1414 + rc = GFN_ERROR;
1415 + break;
1416 + default:
1417 + /* fallback */
1418 + fprintf(stderr, "nedit: Unexpected error in GetFilenameByDialog().\n");
1419 + rc = GFN_ERROR;
1420 + break;
1423 - return retVal;
1424 + return rc;
1428 ** Find a name for an untitled file, unique in the name space of in the opened
1429 ** files in this session, i.e. Untitled or Untitled_nn, and write it into
1430 @@ -1882,56 +1861,10 @@ void removeVersionNumber(char *fileName)
1431 *versionStart = '\0';
1433 #endif /*VMS*/
1436 -** Callback procedure for File Format toggle buttons. Format is stored
1437 -** in userData field of widget button
1439 -static void setFormatCB(Widget w, XtPointer clientData, XtPointer callData)
1441 - if (XmToggleButtonGetState(w)) {
1442 - XtPointer userData;
1443 - XtVaGetValues(w, XmNuserData, &userData, NULL);
1444 - *(int*) clientData = (int) userData;
1449 -** Callback procedure for toggle button requesting newlines to be inserted
1450 -** to emulate continuous wrapping.
1452 -static void addWrapCB(Widget w, XtPointer clientData, XtPointer callData)
1454 - int resp;
1455 - int *addWrap = (int *)clientData;
1457 - if (XmToggleButtonGetState(w))
1459 - resp = DialogF(DF_WARN, w, 2, "Add Wrap",
1460 - "This operation adds permanent line breaks to\n"
1461 - "match the automatic wrapping done by the\n"
1462 - "Continuous Wrap mode Preferences Option.\n\n"
1463 - "*** This Option is Irreversable ***\n\n"
1464 - "Once newlines are inserted, continuous wrapping\n"
1465 - "will no longer work automatically on these lines", "OK",
1466 - "Cancel");
1467 - if (resp == 2)
1469 - XmToggleButtonSetState(w, False, False);
1470 - *addWrap = False;
1471 - } else
1473 - *addWrap = True;
1475 - } else
1477 - *addWrap = False;
1482 ** Change a window created in NEdit's continuous wrap mode to the more
1483 ** conventional Unix format of embedded newlines. Indicate to the user
1484 ** by turning off Continuous Wrap mode.
1486 static void addWrapNewlines(WindowInfo *window)
1487 diff --quilt old/source/file.h new/source/file.h
1488 --- old/source/file.h
1489 +++ new/source/file.h
1490 @@ -35,16 +35,21 @@
1491 /* flags for EditExistingFile */
1492 #define CREATE 1
1493 #define SUPPRESS_CREATE_WARN 2
1494 #define PREF_READ_ONLY 4
1496 +/* These were once set in util/getfiles.h and used throughout NEdit; they
1497 + were moved here to lower coupling between util/getfiles.c and the rest
1498 + of NEdit. */
1499 +enum gfnResult {GFN_OK, GFN_CANCEL, GFN_ERROR};
1501 #define PROMPT_SBC_DIALOG_RESPONSE 0
1502 #define YES_SBC_DIALOG_RESPONSE 1
1503 #define NO_SBC_DIALOG_RESPONSE 2
1505 WindowInfo *EditNewFile(WindowInfo *inWindow, char *geometry, int iconic,
1506 - const char *languageMode, const char *defaultPath);
1507 + const char *languageMode, const char *defaultPath, Boolean transient);
1508 WindowInfo *EditExistingFile(WindowInfo *inWindow, const char *name,
1509 const char *path, int flags, char *geometry, int iconic,
1510 const char *languageMode, int tabbed, int bgOpen);
1511 void RevertToSaved(WindowInfo *window);
1512 int SaveWindow(WindowInfo *window);
1513 diff --quilt old/source/help.c new/source/help.c
1514 --- old/source/help.c
1515 +++ new/source/help.c
1516 @@ -6,11 +6,11 @@ static const char CVSID[] = "$Id: help.c
1517 * Copyright (C) 1999 Mark Edel *
1519 * This is free software; you can redistribute it and/or modify it under the *
1520 * terms of the GNU General Public License as published by the Free Software *
1521 * Foundation; either version 2 of the License, or (at your option) any later *
1522 -* version. In addition, you may distribute version of this program linked to *
1523 +* version. In addition, you may distribute versions of this program linked to *
1524 * Motif or Open Motif. See README for details. *
1526 * This software is distributed in the hope that it will be useful, but WITHOUT *
1527 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
1528 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
1529 @@ -598,42 +598,48 @@ static Widget createHelpPanel(enum HelpT
1530 form = XtVaCreateManagedWidget("helpForm", xmFormWidgetClass, appShell,
1531 NULL);
1532 XtVaSetValues(form, XmNshadowThickness, 0, NULL);
1534 /* Create the bottom row of buttons */
1535 - btn = XtVaCreateManagedWidget("find", xmPushButtonWidgetClass, form,
1536 + btn = XtVaCreateManagedWidget("find",
1537 + xmPushButtonWidgetClass, form,
1538 XmNlabelString, st1=XmStringCreateSimple("Find..."),
1539 XmNmnemonic, 'F',
1540 XmNbottomAttachment, XmATTACH_FORM,
1541 XmNleftAttachment, XmATTACH_POSITION,
1542 XmNleftPosition, 3,
1543 XmNrightAttachment, XmATTACH_POSITION,
1544 XmNrightPosition, 25,
1545 + XmNtraversalOn, False,
1546 NULL);
1547 XtAddCallback(btn, XmNactivateCallback, searchHelpCB, appShell);
1548 XmStringFree(st1);
1550 - btn = XtVaCreateManagedWidget("findAgain", xmPushButtonWidgetClass, form,
1551 + btn = XtVaCreateManagedWidget("findAgain",
1552 + xmPushButtonWidgetClass, form,
1553 XmNlabelString, st1=XmStringCreateSimple("Find Again"),
1554 XmNmnemonic, 'A',
1555 XmNbottomAttachment, XmATTACH_FORM,
1556 XmNleftAttachment, XmATTACH_POSITION,
1557 XmNleftPosition, 27,
1558 XmNrightAttachment, XmATTACH_POSITION,
1559 XmNrightPosition, 49,
1560 + XmNtraversalOn, False,
1561 NULL);
1562 XtAddCallback(btn, XmNactivateCallback, searchHelpAgainCB, appShell);
1563 XmStringFree(st1);
1565 - btn = XtVaCreateManagedWidget("print", xmPushButtonWidgetClass, form,
1566 + btn = XtVaCreateManagedWidget("print",
1567 + xmPushButtonWidgetClass, form,
1568 XmNlabelString, st1=XmStringCreateSimple("Print..."),
1569 XmNmnemonic, 'P',
1570 XmNbottomAttachment, XmATTACH_FORM,
1571 XmNleftAttachment, XmATTACH_POSITION,
1572 XmNleftPosition, 51,
1573 XmNrightAttachment, XmATTACH_POSITION,
1574 XmNrightPosition, 73,
1575 + XmNtraversalOn, False,
1576 NULL);
1577 XtAddCallback(btn, XmNactivateCallback, printCB, appShell);
1578 XmStringFree(st1);
1580 closeBtn = XtVaCreateManagedWidget("close",
1581 @@ -642,79 +648,89 @@ static Widget createHelpPanel(enum HelpT
1582 XmNbottomAttachment, XmATTACH_FORM,
1583 XmNleftAttachment, XmATTACH_POSITION,
1584 XmNleftPosition, 75,
1585 XmNrightAttachment, XmATTACH_POSITION,
1586 XmNrightPosition, 97,
1587 + XmNtraversalOn, False,
1588 NULL);
1589 XtAddCallback(closeBtn, XmNactivateCallback, closeCB, appShell);
1590 XmStringFree(st1);
1592 /* Create the next row of buttons (for navigation) */
1593 - btn = XtVaCreateManagedWidget("prevTopic", xmPushButtonWidgetClass, form,
1594 + btn = XtVaCreateManagedWidget("prevTopic",
1595 + xmPushButtonWidgetClass, form,
1596 XmNlabelString, st1=XmStringCreateSimple("<< Browse"),
1597 XmNmnemonic, 'o',
1598 XmNbottomAttachment, XmATTACH_WIDGET,
1599 XmNbottomWidget, closeBtn,
1600 XmNleftAttachment, XmATTACH_POSITION,
1601 XmNleftPosition, 51,
1602 XmNrightAttachment, XmATTACH_POSITION,
1603 XmNrightPosition, 73,
1604 + XmNtraversalOn, False,
1605 NULL);
1606 XtAddCallback(btn, XmNactivateCallback, prevTopicCB, appShell);
1607 XmStringFree(st1);
1609 - btn = XtVaCreateManagedWidget("nextTopic", xmPushButtonWidgetClass, form,
1610 + btn = XtVaCreateManagedWidget("nextTopic",
1611 + xmPushButtonWidgetClass, form,
1612 XmNlabelString, st1=XmStringCreateSimple("Browse >>"),
1613 XmNmnemonic, 'e',
1614 XmNbottomAttachment, XmATTACH_WIDGET,
1615 XmNbottomWidget, closeBtn,
1616 XmNleftAttachment, XmATTACH_POSITION,
1617 XmNleftPosition, 75,
1618 XmNrightAttachment, XmATTACH_POSITION,
1619 XmNrightPosition, 97,
1620 + XmNtraversalOn, False,
1621 NULL);
1622 XtAddCallback(btn, XmNactivateCallback, nextTopicCB, appShell);
1623 XmStringFree(st1);
1625 - btn = XtVaCreateManagedWidget("histBack", xmPushButtonWidgetClass, form,
1626 + btn = XtVaCreateManagedWidget("histBack",
1627 + xmPushButtonWidgetClass, form,
1628 XmNlabelString, st1=XmStringCreateSimple("Back"),
1629 XmNmnemonic, 'B',
1630 XmNbottomAttachment, XmATTACH_WIDGET,
1631 XmNbottomWidget, closeBtn,
1632 XmNleftAttachment, XmATTACH_POSITION,
1633 XmNleftPosition, 3,
1634 XmNrightAttachment, XmATTACH_POSITION,
1635 XmNrightPosition, 25,
1636 + XmNtraversalOn, False,
1637 NULL);
1638 XtAddCallback(btn, XmNactivateCallback, bwHistoryCB, appShell);
1639 XmStringFree(st1);
1641 - btnFW = XtVaCreateManagedWidget("histForw", xmPushButtonWidgetClass, form,
1642 + btnFW = XtVaCreateManagedWidget("histForw",
1643 + xmPushButtonWidgetClass, form,
1644 XmNlabelString, st1=XmStringCreateSimple("Forward"),
1645 XmNmnemonic, 'w',
1646 XmNbottomAttachment, XmATTACH_WIDGET,
1647 XmNbottomWidget, closeBtn,
1648 XmNleftAttachment, XmATTACH_POSITION,
1649 XmNleftPosition, 27,
1650 XmNrightAttachment, XmATTACH_POSITION,
1651 XmNrightPosition, 49,
1652 + XmNtraversalOn, False,
1653 NULL);
1654 XtAddCallback(btnFW, XmNactivateCallback, fwHistoryCB, appShell);
1655 XmStringFree(st1);
1657 /* Create a text widget inside of a scrolled window widget */
1658 - sw = XtVaCreateManagedWidget("sw", xmScrolledWindowWidgetClass, form,
1659 + sw = XtVaCreateManagedWidget("sw",
1660 + xmScrolledWindowWidgetClass, form,
1661 XmNshadowThickness, 2,
1662 XmNtopAttachment, XmATTACH_FORM,
1663 XmNleftAttachment, XmATTACH_FORM,
1664 XmNrightAttachment, XmATTACH_FORM,
1665 XmNbottomAttachment, XmATTACH_WIDGET,
1666 XmNbottomWidget, btnFW,
1667 NULL);
1668 hScrollBar = XtVaCreateManagedWidget("hScrollBar",
1669 xmScrollBarWidgetClass, sw,
1670 - XmNorientation, XmHORIZONTAL,
1671 + XmNorientation, XmHORIZONTAL,
1672 XmNrepeatDelay, 10,
1673 NULL);
1674 vScrollBar = XtVaCreateManagedWidget("vScrollBar",
1675 xmScrollBarWidgetClass, sw,
1676 XmNorientation, XmVERTICAL,
1677 @@ -733,15 +749,16 @@ static Widget createHelpPanel(enum HelpT
1678 textNvScrollBar, vScrollBar,
1679 textNreadOnly, True,
1680 textNcontinuousWrap, True,
1681 textNautoShowInsertPos, True,
1682 NULL);
1683 - XtVaSetValues(sw, XmNworkWindow, HelpTextPanes[topic],
1684 + XtVaSetValues(sw,
1685 + XmNworkWindow, HelpTextPanes[topic],
1686 XmNhorizontalScrollBar, hScrollBar,
1687 XmNverticalScrollBar, vScrollBar,
1688 NULL);
1691 /* Initialize help style information, if it hasn't already been init'd */
1692 initHelpStyles (HelpTextPanes[topic]);
1694 /* Put together the text to display and separate it into parallel text
1695 and style data for display by the widget */
1696 @@ -802,11 +819,10 @@ static void changeTopicOrRaise(int exist
1698 RaiseShellWindow(HelpWindows[newTopic], True);
1699 adaptNavigationButtons(existingTopic);
1700 adaptNavigationButtons(newTopic);
1706 ** Callbacks for window controls
1708 @@ -900,12 +916,22 @@ static void searchHelpCB(Widget w, XtPoi
1709 static void searchHelpAgainCB(Widget w, XtPointer clientData,
1710 XtPointer callData)
1712 int topic;
1714 - if ((topic = findTopicFromShellWidget((Widget)clientData)) == -1)
1715 - return; /* shouldn't happen */
1716 + if ((topic = findTopicFromShellWidget((Widget)clientData)) == -1) {
1717 + /* shouldn't happen */
1718 + fprintf(stderr, "nedit: Unexpected location found in help.c\n");
1719 + return;
1722 + if (0 == strcmp(LastSearchString, "")) {
1723 + /* no previous search */
1724 + XBell(TheDisplay, 0);
1725 + return;
1728 searchHelpText(HelpWindows[topic], topic, LastSearchString,
1729 LastSearchWasAllTopics, LastSearchPos, LastSearchTopic);
1732 static void printCB(Widget w, XtPointer clientData, XtPointer callData)
1733 @@ -1005,16 +1031,10 @@ static void followHyperlink(int topic, i
1734 adaptNavigationButtons(topic);
1736 XtFree (link_text);
1739 -static void helpFocusButtonsAP(Widget w, XEvent *event, String *args,
1740 - Cardinal *nArgs)
1742 - XmProcessTraversal(w, XmTRAVERSE_NEXT_TAB_GROUP);
1746 * handler for help-button-action(<button-name>)
1747 * Calls the activate callback for the named button widget of the help text win.
1749 static void helpButtonActionAP(Widget w, XEvent *event, String *args,
1750 @@ -1148,11 +1168,10 @@ static void helpHyperlinkAP(Widget w, XE
1751 void InstallHelpLinkActions(XtAppContext context)
1753 static XtActionsRec Actions[] =
1755 {"help-hyperlink", helpHyperlinkAP},
1756 - {"help-focus-buttons", helpFocusButtonsAP},
1757 {"help-button-action", helpButtonActionAP}
1760 XtAppAddActions(context, Actions, XtNumber(Actions));
1762 diff --quilt old/source/highlightData.c new/source/highlightData.c
1763 --- old/source/highlightData.c
1764 +++ new/source/highlightData.c
1765 @@ -546,14 +546,14 @@ static char *DefaultPatternSets[] = {
1766 Wrong logical ops:\"&&|\\|\\|\":::Plain::\n\
1767 Logical operators:\"~|&|\\|\":::Text Arg2::}",
1768 "NEdit Macro:2:0{\n\
1769 README:\"NEdit Macro syntax highlighting patterns, version 2.6, maintainer Thorsten Haude, nedit at thorstenhau.de\":::Flag::D\n\
1770 Comment:\"#\":\"$\"::Comment::\n\
1771 - 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\
1772 + 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\
1773 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\
1774 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\
1775 - 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\
1776 + 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\
1777 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\
1778 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\
1779 Keyword:\"<(?:break|continue|define|delete|else|for|if|in|return|while)>\":::Keyword::\n\
1780 Braces:\"[{}\\[\\]]\":::Keyword::\n\
1781 Global Variable:\"\\$[A-Za-z0-9_]+\":::Identifier1::\n\
1782 diff --quilt old/source/interpret.c new/source/interpret.c
1783 --- old/source/interpret.c
1784 +++ new/source/interpret.c
1785 @@ -199,11 +199,11 @@ static SparseArrayEntryWrapper *Allocate
1787 /* Message strings used in macros (so they don't get repeated every time
1788 the macros are used */
1789 static const char *StackOverflowMsg = "macro stack overflow";
1790 static const char *StackUnderflowMsg = "macro stack underflow";
1791 -static const char *StringToNumberMsg = "string could not be converted to number";
1792 +static const char* StringToNumberMsg = "string '%s' could not be converted to number";
1794 /* Temporary global data for use while accumulating programs */
1795 static Symbol *LocalSymList = NULL; /* symbols local to the program */
1796 static Inst Prog[PROGRAM_SIZE]; /* the program */
1797 static Inst *ProgP; /* next free spot for code gen. */
1798 @@ -594,10 +594,13 @@ int ContinueMacro(RestartData *continuat
1799 ErrMsg = NULL;
1800 for (;;) {
1802 /* Execute an instruction */
1803 inst = PC++;
1804 +// fprintf(stderr, "inst->sym->name: %s\n", inst->sym->name);
1805 +// fprintf(stderr, "inst->sym->type: %d\n", inst->sym->type);
1806 +// fprintf(stderr, "inst->sym->value.tag: %d\n", inst->sym->value.tag);
1807 status = (inst->func)();
1809 /* If error return was not STAT_OK, return to caller */
1810 if (status != STAT_OK) {
1811 if (status == STAT_PREEMPT) {
1812 @@ -1195,12 +1198,13 @@ static void freeSymbolTable(Symbol *symT
1813 #define POP_INT(number) \
1814 if (StackP == TheStack) \
1815 return execError(StackUnderflowMsg, ""); \
1816 --StackP; \
1817 if (StackP->tag == STRING_TAG) { \
1818 - if (!StringToNum(StackP->val.str.rep, &number)) \
1819 - return execError(StringToNumberMsg, ""); \
1820 + if (!StringToNum(StackP->val.str.rep, &number)) {\
1821 + return execError(StringToNumberMsg, StackP->val.str.rep); \
1822 + } \
1823 } else if (StackP->tag == INT_TAG) \
1824 number = StackP->val.n; \
1825 else \
1826 return(execError("can't convert array to integer", NULL));
1828 @@ -1313,13 +1317,17 @@ static int pushSymVal(void)
1829 return execError(errMsg, s->name);
1831 *StackP = result;
1832 } else
1833 return execError("reading non-variable: %s", s->name);
1835 +/* typeof()
1836 if (StackP->tag == NO_TAG) {
1837 - return execError("variable not set: %s", s->name);
1838 + return execError("variable not set: %s", s->name);
1842 StackP++;
1843 if (StackP >= &TheStack[STACK_SIZE]) {
1844 return execError(StackOverflowMsg, "");
1846 return STAT_OK;
1847 @@ -1417,13 +1425,15 @@ static int pushArraySymVal(void)
1848 if (initEmpty && dataPtr->tag == NO_TAG) {
1849 dataPtr->tag = ARRAY_TAG;
1850 dataPtr->val.arrayPtr = ArrayNew();
1853 +/* typeof()
1854 if (dataPtr->tag == NO_TAG) {
1855 return execError("variable not set: %s", sym->name);
1859 *StackP = *dataPtr;
1860 StackP++;
1862 if (StackP >= &TheStack[STACK_SIZE]) {
1863 @@ -3067,17 +3077,21 @@ static int arrayRef(void)
1866 POP(srcArray)
1867 if (srcArray.tag == ARRAY_TAG) {
1868 if (!ArrayGet(&srcArray, keyString, &valueItem)) {
1869 - return(execError("referenced array value not in array: %s", keyString));
1870 +/*typeof() return(execError("referenced array value not in array: %s", keyString));*/
1871 + valueItem.tag = NO_TAG;
1873 PUSH(valueItem)
1874 return(STAT_OK);
1876 else {
1877 - return(execError("operator [] on non-array", NULL));
1878 +/*typeof() return(execError("operator [] on non-array", NULL));*/
1879 + valueItem.tag = NO_TAG;
1880 + PUSH(valueItem)
1881 + return(STAT_OK);
1884 else {
1885 POP(srcArray)
1886 if (srcArray.tag == ARRAY_TAG) {
1887 @@ -3480,10 +3494,11 @@ static int execError(const char *s1, con
1888 static char msg[MAX_ERR_MSG_LEN];
1889 static char *err = NULL;
1890 static int errlen = 0;
1892 sprintf(msg, s1, s2);
1893 + msg[MAX_ERR_MSG_LEN - 1] = '\0';
1894 ErrMsg = stackDumpStr(FrameP, msg, &err, &errlen);
1895 return STAT_ERROR;
1898 int StringToNum(const char *string, int *number)
1899 diff --quilt old/source/macro.c new/source/macro.c
1900 --- old/source/macro.c
1901 +++ new/source/macro.c
1902 @@ -30,35 +30,35 @@ static const char CVSID[] = "$Id: macro.
1904 #ifdef HAVE_CONFIG_H
1905 #include "../config.h"
1906 #endif
1908 +#include "calltips.h"
1909 +#include "highlightData.h"
1910 +#include "highlight.h"
1911 +#include "interpret.h"
1912 #include "macro.h"
1913 -#include "textBuf.h"
1914 -#include "text.h"
1915 #include "nedit.h"
1916 -#include "window.h"
1917 -#include "preferences.h"
1918 -#include "interpret.h"
1919 #include "parse.h"
1920 +#include "preferences.h"
1921 +#include "rangeset.h"
1922 +#include "rbTree.h"
1923 #include "search.h"
1924 +#include "selection.h"
1925 #include "server.h"
1926 #include "shell.h"
1927 #include "smartIndent.h"
1928 -#include "userCmds.h"
1929 -#include "selection.h"
1930 -#include "rbTree.h"
1931 #include "tags.h"
1932 -#include "calltips.h"
1933 +#include "textBuf.h"
1934 +#include "text.h"
1935 +#include "userCmds.h"
1936 +#include "window.h"
1937 #include "../util/DialogF.h"
1938 -#include "../util/misc.h"
1939 #include "../util/fileUtils.h"
1940 -#include "../util/utils.h"
1941 #include "../util/getfiles.h"
1942 -#include "highlight.h"
1943 -#include "highlightData.h"
1944 -#include "rangeset.h"
1945 +#include "../util/misc.h"
1946 +#include "../util/utils.h"
1948 #include <stdio.h>
1949 #include <stdlib.h>
1950 #include <string.h>
1951 #include <ctype.h>
1952 @@ -75,26 +75,27 @@ static const char CVSID[] = "$Id: macro.
1953 #ifndef __MVS__
1954 #include <sys/param.h>
1955 #endif
1956 #include <fcntl.h>
1957 #endif /*VMS*/
1958 +#include <stdarg.h>
1960 #include <X11/Intrinsic.h>
1961 #include <X11/keysym.h>
1962 #include <Xm/Xm.h>
1963 #include <Xm/CutPaste.h>
1964 +#include <Xm/DialogS.h>
1965 #include <Xm/Form.h>
1966 -#include <Xm/RowColumn.h>
1967 #include <Xm/LabelG.h>
1968 #include <Xm/List.h>
1969 -#include <Xm/ToggleB.h>
1970 -#include <Xm/DialogS.h>
1971 #include <Xm/MessageB.h>
1972 -#include <Xm/SelectioB.h>
1973 #include <Xm/PushB.h>
1974 -#include <Xm/Text.h>
1975 +#include <Xm/RowColumn.h>
1976 +#include <Xm/SelectioB.h>
1977 #include <Xm/Separator.h>
1978 +#include <Xm/Text.h>
1979 +#include <Xm/ToggleB.h>
1981 #ifdef HAVE_DEBUG_H
1982 #include "../debug.h"
1983 #endif
1985 @@ -233,10 +234,12 @@ static void stringDialogCloseCB(Widget w
1986 static void stringDialogEscCB(Widget w, XtPointer clientData, XEvent *event,
1987 Boolean *cont);
1988 #endif /* LESSTIF_VERSION */
1989 static int calltipMS(WindowInfo *window, DataValue *argList, int nArgs,
1990 DataValue *result, char **errMsg);
1991 +static int highlightCTLineMS(WindowInfo* window, DataValue* argList, int nArgs,
1992 + DataValue* result, char** errMsg);
1993 static int killCalltipMS(WindowInfo *window, DataValue *argList, int nArgs,
1994 DataValue *result, char **errMsg);
1995 /* T Balinski */
1996 static int listDialogMS(WindowInfo *window, DataValue *argList, int nArgs,
1997 DataValue *result, char **errMsg);
1998 @@ -350,19 +353,21 @@ static int calltipIDMV(WindowInfo *windo
1999 static int readSearchArgs(DataValue *argList, int nArgs, int*searchDirection,
2000 int *searchType, int *wrap, char **errMsg);
2001 static int wrongNArgsErr(char **errMsg);
2002 static int tooFewArgsErr(char **errMsg);
2003 static int strCaseCmp(char *str1, char *str2);
2004 -static int readIntArg(DataValue dv, int *result, char **errMsg);
2005 +static Boolean readIntArg(DataValue dv, int *result, char **errMsg);
2006 static int readStringArg(DataValue dv, char **result, char *stringStorage,
2007 char **errMsg);
2008 /* DISABLED FOR 5.4
2009 static int backlightStringMV(WindowInfo *window, DataValue *argList,
2010 int nArgs, DataValue *result, char **errMsg);
2012 static int rangesetListMV(WindowInfo *window, DataValue *argList,
2013 int nArgs, DataValue *result, char **errMsg);
2014 +static int neditHomeMV(WindowInfo* window, DataValue* argList, int nArgs,
2015 + DataValue* result, char** errMsg);
2016 static int versionMV(WindowInfo* window, DataValue* argList, int nArgs,
2017 DataValue* result, char** errMsg);
2018 static int rangesetCreateMS(WindowInfo *window, DataValue *argList, int nArgs,
2019 DataValue *result, char **errMsg);
2020 static int rangesetDestroyMS(WindowInfo *window, DataValue *argList, int nArgs,
2021 @@ -405,10 +410,12 @@ static int getStyleAtPosMS(WindowInfo *w
2022 DataValue *result, char **errMsg);
2023 static int filenameDialogMS(WindowInfo* window, DataValue* argList, int nArgs,
2024 DataValue* result, char** errMsg);
2025 static int callMS(WindowInfo *window, DataValue *argList,
2026 int nArgs, DataValue *result, char **errMsg);
2027 +static int typeofMS(WindowInfo* window, DataValue* argList, int nArgs,
2028 + DataValue* result, char** errMsg);
2030 /* Built-in subroutines and variables for the macro language */
2031 static const BuiltInSubrName MacroSubrs[] = {
2032 { "length", lengthMS },
2033 { "get_range", getRangeMS },
2034 @@ -444,10 +451,11 @@ static const BuiltInSubrName MacroSubrs[
2035 { "getenv", getenvMS },
2036 { "string_compare", stringCompareMS },
2037 { "split", splitMS },
2038 { "calltip", calltipMS },
2039 { "kill_calltip", killCalltipMS },
2040 + { "highlight_calltip_line", highlightCTLineMS },
2041 /* DISABLED for 5.4
2042 { "set_backlight_string", setBacklightStringMS },
2044 { "rangeset_create", rangesetCreateMS },
2045 { "rangeset_destroy", rangesetDestroyMS },
2046 @@ -465,10 +473,11 @@ static const BuiltInSubrName MacroSubrs[
2047 { "get_pattern_at_pos", getPatternAtPosMS },
2048 { "get_style_by_name", getStyleByNameMS },
2049 { "get_style_at_pos", getStyleAtPosMS },
2050 { "filename_dialog", filenameDialogMS },
2051 { "call", callMS },
2052 + { "typeof", typeofMS },
2053 { NULL, NULL } /* sentinel */
2056 static const BuiltInSubrName SpecialVars[] = {
2057 { "$cursor", cursorMV },
2058 @@ -519,10 +528,11 @@ static const BuiltInSubrName SpecialVars
2059 /* DISABLED for 5.4
2060 { "$backlight_string", backlightStringMV },
2062 { "$rangeset_list", rangesetListMV },
2063 { "$VERSION", versionMV },
2064 + { "$NEDIT_HOME", neditHomeMV },
2065 { NULL, NULL } /* sentinel */
2068 /* Global symbols for "returning" secondary values from built-in functions */
2069 static int STRING_DIALOG_BUTTON, SEARCH_END, READ_STATUS,
2070 @@ -3420,10 +3430,61 @@ bad_arg:
2071 *errMsg = "unrecognized argument to %s";
2072 return False;
2076 +** highlight_calltip_line(ctID, line)
2078 +static int highlightCTLineMS(WindowInfo* window, DataValue* argList, int nArgs,
2079 + DataValue* result, char** errMsg)
2081 + int calltipID = 0;
2082 + int line;
2083 + int highlightResult;
2085 + if (2 != nArgs) {
2086 + *errMsg = "%s() called with wrong number of arguments";
2087 + return False;
2090 + if (!readIntArg(argList[0], &calltipID, errMsg)) {
2091 + *errMsg = "%s(): Could not read calltip ID from argument 1";
2092 + return False;
2095 + /* The macro function calltip() uses 0 to report an error. Catch sloppy
2096 + programmers who just feed this value into this function. */
2097 + if (0 == calltipID) {
2098 + *errMsg = "%s(): Invalid calltip ID 0";
2099 + return False;
2102 + if (!readIntArg(argList[1], &line, errMsg) || line < 0) {
2103 + *errMsg = "%s(): Could not read line number from argument 2";
2104 + return False;
2107 + result->tag = NO_TAG;
2109 + highlightResult = HighlightCalltipLine(window, calltipID, (unsigned) line);
2111 + if (CT_INVALID_ID == highlightResult) {
2112 + /* Fail only if the calltip ID given is invalid. */
2113 + *errMsg = "%s(): Invalid calltip ID";
2114 + return False;
2117 + /* In case NEdit ever gets a warning (!= error) mechanism:
2118 + if (CT_NOLINE == highlightResult) {
2119 + *warnMsg = "%s(): Calltip line out of range";
2121 + */
2123 + return True;
2127 ** A subroutine to kill the current calltip
2129 static int killCalltipMS(WindowInfo *window, DataValue *argList, int nArgs,
2130 DataValue *result, char **errMsg)
2132 @@ -3449,11 +3510,11 @@ static int killCalltipMS(WindowInfo *win
2134 static int calltipIDMV(WindowInfo *window, DataValue *argList,
2135 int nArgs, DataValue *result, char **errMsg)
2137 result->tag = INT_TAG;
2138 - result->val.n = GetCalltipID(window, 0);
2139 + result->val.n = GetCalltipID(window);
2140 return True;
2144 ** filename_dialog([title[, mode[, defaultPath[, filter[, defaultName]]]]])
2145 @@ -3478,19 +3539,20 @@ static int calltipIDMV(WindowInfo *windo
2147 static int filenameDialogMS(WindowInfo* window, DataValue* argList, int nArgs,
2148 DataValue* result, char** errMsg)
2150 char stringStorage[5][TYPE_INT_STR_SIZE(int)];
2151 - char filename[MAXPATHLEN + 1];
2152 char* title = "Choose Filename";
2153 char* mode = "exist";
2154 char* defaultPath = "";
2155 char* filter = "";
2156 char* defaultName = "";
2157 char* orgDefaultPath;
2158 char* orgFilter;
2159 - int gfnResult;
2160 + gfbdParams params;
2161 + gfbdValue* gfbdrc;
2162 + int rc = False;
2164 /* Ignore the focused window passed as the function argument and put
2165 the dialog up over the window which is executing the macro */
2166 window = MacroRunWindow();
2168 @@ -3545,37 +3607,56 @@ static int filenameDialogMS(WindowInfo*
2169 orgFilter = GetFileDialogDefaultPattern();
2170 if ('\0' != filter[0]) {
2171 SetFileDialogDefaultPattern(filter);
2174 - /* Fork to one of the worker methods from util/getfiles.c.
2175 - (This should obviously be refactored.) */
2176 - if (0 == strcmp(mode, "exist")) {
2177 - gfnResult = GetExistingFilename(window->shell, title, filename);
2178 - } else {
2179 - gfnResult = GetNewFilename(window->shell, title, filename, defaultName);
2180 - } /* Invalid values are weeded out above. */
2181 + params.dialogTitle = title;
2182 + params.parentShell = window->shell;
2183 + params.fileExists = (0 == strcmp(mode, "exist")) ? True : False;
2184 + params.textfieldLabel = "New File Name";
2185 + params.defaultName = (0 == strcmp("", defaultName)) ? NULL : defaultName;
2186 + params.haveFormatButtons = False;
2187 + /* ...so no file format for wrap info necessary. */
2188 + params.showHidden = GetPrefShowHiddenFiles();
2190 + gfbdrc = GetFilenameByDialog(params);
2192 /* Reset original values and free temps */
2193 SetFileDialogDefaultDirectory(orgDefaultPath);
2194 SetFileDialogDefaultPattern(orgFilter);
2195 XtFree(orgDefaultPath);
2196 XtFree(orgFilter);
2198 result->tag = STRING_TAG;
2199 - if (GFN_OK == gfnResult) {
2200 - /* Got a string, copy it to the result */
2201 - if (!AllocNStringNCpy(&result->val.str, filename, MAXPATHLEN)) {
2202 - M_FAILURE("failed to allocate return value: %s");
2204 - } else {
2205 - /* User cancelled. Return "" */
2206 - result->val.str.rep = PERM_ALLOC_STR("");
2207 - result->val.str.len = 0;
2208 + switch(gfbdrc->status) {
2209 + case GFDB_OK:
2210 + /* Got a filename, copy it to the result */
2211 + if (!AllocNStringNCpy(&result->val.str, gfbdrc->payload, MAXPATHLEN)) {
2212 + M_FAILURE("failed to allocate return value: %s");
2214 + rc = True;
2215 + break;
2216 + case GFDB_CANCEL:
2217 + /* User cancelled. Return "" */
2218 + result->val.str.rep = PERM_ALLOC_STR("");
2219 + result->val.str.len = 0;
2220 + rc = True;
2221 + break;
2222 + case GFDB_ERROR:
2223 + fprintf(stderr, "nedit: Error while calling GetFilenameByDialog(): %s\n", gfbdrc->payload);
2224 + *errMsg = "Error while calling GetFilenameByDialog() in %s";
2225 + rc = False;
2226 + break;
2227 + default:
2228 + /* fallback */
2229 + fprintf(stderr, "nedit: Unexpected error in GetFilenameByDialog().\n");
2230 + *errMsg = "Unexpected error in GetFilenameByDialog() in %s";
2231 + rc = False;
2232 + break;
2235 - return True;
2236 + return rc;
2240 * call(fnname, arg, ...)
2242 @@ -4764,10 +4845,31 @@ static int versionMV(WindowInfo* window,
2243 result->val.n = version;
2244 return True;
2248 +** Returns the name of the directory where NEdit's run control files reside.
2249 +** This is either the value of the environmental variable $NEDIT_HOME, the
2250 +** default of ~/.nedit or $HOME. (See the online documentation for details
2251 +** about the algorithm.)
2253 +static int neditHomeMV(WindowInfo* window, DataValue* argList, int nArgs,
2254 + DataValue* result, char** errMsg)
2256 + const char* neditRCName = GetRCFileName(NEDIT_RC);
2257 + char nedit_home[MAXPATHLEN];
2259 + if (0 != ParseFilename(neditRCName, NULL, nedit_home)) {
2260 + M_FAILURE("Unable to parse nedit rc file name in %s");
2263 + result->tag = STRING_TAG;
2264 + AllocNStringCpy(&result->val.str, nedit_home);
2265 + return True;
2269 ** Built-in macro subroutine to create a new rangeset or rangesets.
2270 ** If called with one argument: $1 is the number of rangesets required and
2271 ** return value is an array indexed 0 to n, with the rangeset labels as values;
2272 ** (or an empty array if the requested number of rangesets are not available).
2273 ** If called with no arguments, returns a single rangeset label (not an array),
2274 @@ -5854,10 +5956,56 @@ static int getPatternAtPosMS(WindowInfo
2275 return fillPatternResult(result, errMsg, window,
2276 HighlightNameOfCode(window, patCode), False, True,
2277 HighlightStyleOfCode(window, patCode), bufferPos);
2281 +** Returns a string containing a flag indicating the arguments type:
2282 +** ARRAY - Argument is an array
2283 +** INTEGER - Argument is an integer or a string that can be cleanly
2284 +** transformed into an integer.
2285 +** STRING - Argument is a string that cannot be cleanly transformed
2286 +** into an integer.
2287 +** UNDEFINED - Argument is undefined. No support for void functions though.
2289 +static int typeofMS(WindowInfo* window, DataValue* argList, int nArgs,
2290 + DataValue* result, char** errMsg)
2292 + int buffer;
2294 + /* Validate number of arguments. */
2295 + if (1 != nArgs) {
2296 + return wrongNArgsErr(errMsg);
2299 + /* Prepare result. */
2300 + result->tag = STRING_TAG;
2302 + switch (argList[0].tag) {
2303 + case STRING_TAG:
2304 + if (readIntArg(argList[0], &buffer, errMsg)) {
2305 + AllocNStringCpy(&result->val.str, "INTEGER");
2306 + } else {
2307 + AllocNStringCpy(&result->val.str, "STRING");
2309 + break;
2310 + case INT_TAG:
2311 + AllocNStringCpy(&result->val.str, "INTEGER");
2312 + break;
2313 + case ARRAY_TAG:
2314 + AllocNStringCpy(&result->val.str, "ARRAY");
2315 + break;
2316 + case NO_TAG:
2317 + AllocNStringCpy(&result->val.str, "UNDEFINED");
2318 + break;
2319 + default:
2320 + fprintf(stderr, "nedit: Internal error: Invalid type in typeofMS().\n");
2323 + return True;
2326 static int wrongNArgsErr(char **errMsg)
2328 *errMsg = "Wrong number of arguments to function %s";
2329 return False;
2331 @@ -5901,11 +6049,11 @@ static int strCaseCmp(char *str1, char *
2333 ** Get an integer value from a tagged DataValue structure. Return True
2334 ** if conversion succeeded, and store result in *result, otherwise
2335 ** return False with an error message in *errMsg.
2337 -static int readIntArg(DataValue dv, int *result, char **errMsg)
2338 +static Boolean readIntArg(DataValue dv, int *result, char **errMsg)
2340 char *c;
2342 if (dv.tag == INT_TAG) {
2343 *result = dv.val.n;
2344 @@ -5944,5 +6092,46 @@ static int readStringArg(DataValue dv, c
2345 return True;
2347 *errMsg = "%s called with unknown object";
2348 return False;
2351 +/* rough hack */
2352 +void MacroApplyHook(const WindowInfo* document, const char* hook, int argc,
2353 + DataValue* argv, DataValue* resultDV)
2355 + Symbol* hookSymbol;
2357 + hookSymbol = LookupSymbol(hook);
2358 + if (NULL != hookSymbol && MACRO_FUNCTION_SYM == hookSymbol->type) {
2359 + Program* hookProg = hookSymbol->value.val.prog;
2360 + RestartData* restartData;
2361 + DataValue dummyResultDV; /* Passed to ExecuteMacro() if no result requested */
2362 + int status;
2363 + char* errMsg;
2364 +// char statusT[1024];
2366 + /* Let 'er rip */
2367 + status = ExecuteMacro((WindowInfo*) document, hookProg, argc, argv,
2368 + (NULL == resultDV) ? &dummyResultDV : resultDV, &restartData,
2369 + &errMsg);
2370 +// switch (status)
2371 +// {
2372 +// case 0: strncpy(statusT, "MACRO_TIME_LIMIT", 1024); break;
2373 +// case 1: strncpy(statusT, "MACRO_PREEMPT", 1024); break;
2374 +// case 2: strncpy(statusT, "MACRO_DONE", 1024); break;
2375 +// case 3: strncpy(statusT, "MACRO_ERROR", 1024); break;
2376 +// default: strncpy(statusT, "UNKNOWN_ERROR", 1024);
2377 +// }
2378 +// fprintf(stderr, "\tstatus: %s\n", statusT);
2379 + while (MACRO_TIME_LIMIT == status) {
2380 + status = ContinueMacro(restartData,
2381 + (NULL == resultDV) ? &dummyResultDV : resultDV, &errMsg);
2384 + if (MACRO_PREEMPT == status || MACRO_ERROR == status) {
2385 + fprintf(stderr, "nedit: \"%s\" error: %s\n", hook, (MACRO_ERROR == status) ? errMsg : "No dialogs");
2386 + } else {
2387 + /* Macro is done here */
2391 diff --quilt old/source/macro.h new/source/macro.h
2392 --- old/source/macro.h
2393 +++ new/source/macro.h
2394 @@ -71,7 +71,10 @@ int ReadMacroString(WindowInfo *window,
2395 int CheckMacroString(Widget dialogParent, char *string, const char *errIn,
2396 char **errPos);
2397 char *GetReplayMacro(void);
2398 void ReadMacroInitFile(WindowInfo *window);
2399 void ReturnShellCommandOutput(WindowInfo *window, const char *outText, int status);
2400 +struct DataValueTag;
2401 +void MacroApplyHook(const WindowInfo* document, const char *hook, int argc,
2402 + struct DataValueTag* argv, struct DataValueTag* resultDV);
2404 #endif /* NEDIT_MACRO_H_INCLUDED */
2405 diff --quilt old/source/menu.c new/source/menu.c
2406 --- old/source/menu.c
2407 +++ new/source/menu.c
2408 @@ -50,10 +50,11 @@ static const char CVSID[] = "$Id: menu.c
2409 #include "highlight.h"
2410 #include "highlightData.h"
2411 #include "interpret.h"
2412 #include "smartIndent.h"
2413 #include "windowTitle.h"
2414 +#include "regularExp.h"
2415 #include "../util/getfiles.h"
2416 #include "../util/DialogF.h"
2417 #include "../util/misc.h"
2418 #include "../util/fileUtils.h"
2419 #include "../util/utils.h"
2420 @@ -177,10 +178,13 @@ static void bgMenuDefCB(Widget w, Window
2421 static void searchDlogsDefCB(Widget w, WindowInfo *window, caddr_t callData);
2422 static void beepOnSearchWrapDefCB(Widget w, WindowInfo *window, caddr_t callData);
2423 static void keepSearchDlogsDefCB(Widget w, WindowInfo *window,
2424 caddr_t callData);
2425 static void searchWrapsDefCB(Widget w, WindowInfo *window, caddr_t callData);
2426 +static void showHiddenFilesCB(Widget w, WindowInfo* window, caddr_t callData);
2427 +static void showCursorlineCB(Widget widget, WindowInfo* window,
2428 + caddr_t callData);
2429 static void appendLFCB(Widget w, WindowInfo* window, caddr_t callData);
2430 static void sortOpenPrevDefCB(Widget w, WindowInfo *window, caddr_t callData);
2431 static void reposDlogsDefCB(Widget w, WindowInfo *window, caddr_t callData);
2432 static void autoScrollDefCB(Widget w, WindowInfo *window, caddr_t callData);
2433 static void modWarnDefCB(Widget w, WindowInfo *window, caddr_t callData);
2434 @@ -189,10 +193,12 @@ static void exitWarnDefCB(Widget w, Wind
2435 static void searchLiteralCB(Widget w, WindowInfo *window, caddr_t callData);
2436 static void searchCaseSenseCB(Widget w, WindowInfo *window, caddr_t callData);
2437 static void searchLiteralWordCB(Widget w, WindowInfo *window, caddr_t callData);
2438 static void searchCaseSenseWordCB(Widget w, WindowInfo *window, caddr_t callData);
2439 static void searchRegexNoCaseCB(Widget w, WindowInfo *window, caddr_t callData);
2440 +static void searchRegexSmartCaseCB(Widget toggleButton, WindowInfo* windowInfo,
2441 + caddr_t callData);
2442 static void searchRegexCB(Widget w, WindowInfo *window, caddr_t callData);
2443 #ifdef REPLACE_SCOPE
2444 static void replaceScopeWindowCB(Widget w, WindowInfo *window, caddr_t callData);
2445 static void replaceScopeSelectionCB(Widget w, WindowInfo *window, caddr_t callData);
2446 static void replaceScopeSmartCB(Widget w, WindowInfo *window, caddr_t callData);
2447 @@ -392,10 +398,12 @@ static void setAutoIndentAP(Widget w, XE
2448 Cardinal *nArgs);
2449 static void setWrapTextAP(Widget w, XEvent *event, String *args,
2450 Cardinal *nArgs);
2451 static void setWrapMarginAP(Widget w, XEvent *event, String *args,
2452 Cardinal *nArgs);
2453 +static void setShowWrapMarginAP(Widget w, XEvent *event, String *args,
2454 + Cardinal *nArgs);
2455 static void setHighlightSyntaxAP(Widget w, XEvent *event, String *args,
2456 Cardinal *nArgs);
2457 static void setMakeBackupCopyAP(Widget w, XEvent *event, String *args,
2458 Cardinal *nArgs);
2459 static void setIncrementalBackupAP(Widget w, XEvent *event, String *args,
2460 @@ -406,10 +414,12 @@ static void setMatchSyntaxBasedAP(Widget
2461 Cardinal *nArgs);
2462 static void setOvertypeModeAP(Widget w, XEvent *event, String *args,
2463 Cardinal *nArgs);
2464 static void setLockedAP(Widget w, XEvent *event, String *args,
2465 Cardinal *nArgs);
2466 +static void setTransientAP(Widget text, XEvent* event, String* args,
2467 + Cardinal* nArgs);
2468 static void setUseTabsAP(Widget w, XEvent *event, String *args,
2469 Cardinal *nArgs);
2470 static void setEmTabDistAP(Widget w, XEvent *event, String *args,
2471 Cardinal *nArgs);
2472 static void setTabDistAP(Widget w, XEvent *event, String *args,
2473 @@ -566,19 +576,21 @@ static XtActionsRec Actions[] = {
2474 {"set_incremental_search_line", setIncrementalSearchLineAP},
2475 {"set_show_line_numbers", setShowLineNumbersAP},
2476 {"set_auto_indent", setAutoIndentAP},
2477 {"set_wrap_text", setWrapTextAP},
2478 {"set_wrap_margin", setWrapMarginAP},
2479 + {"set_show_wrap_margin", setShowWrapMarginAP},
2480 {"set_highlight_syntax", setHighlightSyntaxAP},
2481 #ifndef VMS
2482 {"set_make_backup_copy", setMakeBackupCopyAP},
2483 #endif
2484 {"set_incremental_backup", setIncrementalBackupAP},
2485 {"set_show_matching", setShowMatchingAP},
2486 {"set_match_syntax_based", setMatchSyntaxBasedAP},
2487 {"set_overtype_mode", setOvertypeModeAP},
2488 {"set_locked", setLockedAP},
2489 + {"set_transient", setTransientAP},
2490 {"set_tab_dist", setTabDistAP},
2491 {"set_em_tab_dist", setEmTabDistAP},
2492 {"set_use_tabs", setUseTabsAP},
2493 {"set_fonts", setFontsAP},
2494 {"set_language_mode", setLanguageModeAP}
2495 @@ -813,10 +825,13 @@ Widget CreateMenuBar(Widget parent, Wind
2496 XtSetSensitive(window->showTipItem, (TagsFileList != NULL ||
2497 TipsFileList != NULL) );
2500 ** Preferences menu, Default Settings sub menu
2501 + **
2502 + ** Mnemonics: L, A, W, C, T, F, u, d, g, H, S, i, N, e, B, M, o, P, r, z
2503 + ** A, B, C, d, e, F, g, H, i, L, M, N, o, P, r, S, T, u, W, z
2505 menuPane = createMenu(menuBar, "preferencesMenu", "Preferences", 0, NULL,
2506 SHORT);
2507 subPane = createMenu(menuPane, "defaultSettings", "Default Settings", 'D',
2508 NULL, FULL);
2509 @@ -926,12 +941,17 @@ Widget CreateMenuBar(Widget parent, Wind
2510 GetPrefSearch() == SEARCH_CASE_SENSE_WORD, FULL);
2511 window->searchRegexDefItem = createMenuToggle(subSubSubPane,
2512 "regularExpression", "Regular Expression", 'R', searchRegexCB,
2513 window, GetPrefSearch() == SEARCH_REGEX, FULL);
2514 window->searchRegexNoCaseDefItem = createMenuToggle(subSubSubPane,
2515 - "regularExpressionNoCase", "Regular Expression, Case Insensitive", 'I', searchRegexNoCaseCB, window,
2516 - GetPrefSearch() == SEARCH_REGEX_NOCASE, FULL);
2517 + "regularExpressionNoCase", "Regular Expression, Case Insensitive",
2518 + 'I', searchRegexNoCaseCB, window,
2519 + GetPrefSearch() == SEARCH_REGEX_NOCASE, FULL);
2520 + window->searchRegexSmartCaseDefItem = createMenuToggle(subSubSubPane,
2521 + "regularExpressionSmartCase", "Regular Expression, Smart Case",
2522 + 'S', searchRegexSmartCaseCB, window,
2523 + GetPrefSearch() == SEARCH_REGEX_SMARTCASE, FULL);
2524 #ifdef REPLACE_SCOPE
2525 subSubSubPane = createMenu(subSubPane, "defaultReplaceScope",
2526 "Default Replace Scope", 'R', NULL, FULL);
2527 XtVaSetValues(subSubSubPane, XmNradioBehavior, True, NULL);
2528 window->replScopeWinDefItem = createMenuToggle(subSubSubPane, "window",
2529 @@ -1015,10 +1035,20 @@ Widget CreateMenuBar(Widget parent, Wind
2530 createMenuSeparator(subSubPane, "sep", SHORT);
2531 window->matchSyntaxBasedDefItem = createMenuToggle(subSubPane,
2532 "matchSyntax", "Syntax Based", 'S', matchSyntaxBasedDefCB, window,
2533 GetPrefMatchSyntaxBased(), SHORT);
2535 + /* Show Hidden Files */
2536 + window->showHiddenFilesItem = createMenuToggle(subPane,
2537 + "showHiddenFilesItem", "Show hidden Files", 'y', showHiddenFilesCB,
2538 + NULL, GetPrefShowHiddenFiles(), FULL);
2540 + /* Show Cursorline */
2541 + window->showCursorlineItem = createMenuToggle(subPane,
2542 + "showCursorlineItem", "Show Cursorline", 'x', showCursorlineCB,
2543 + NULL, GetPrefShowCursorline(), FULL);
2545 /* Append LF at end of files on save */
2546 window->appendLFItem = createMenuToggle(subPane, "appendLFItem",
2547 "Terminate with Line Break on Save", 'v', appendLFCB, NULL,
2548 GetPrefAppendLF(), FULL);
2550 @@ -1141,10 +1171,12 @@ Widget CreateMenuBar(Widget parent, Wind
2551 createMenuSeparator(menuPane, "sep2", SHORT);
2552 window->overtypeModeItem = createMenuToggle(menuPane, "overtype", "Overtype", 'O',
2553 doActionCB, "set_overtype_mode", False, SHORT);
2554 window->readOnlyItem = createMenuToggle(menuPane, "readOnly", "Read Only",
2555 'y', doActionCB, "set_locked", IS_USER_LOCKED(window->lockReasons), FULL);
2556 + window->transientItem = createMenuToggle(menuPane, "transient", "Transient",
2557 + 'r', doActionCB, "set_transient", window->transient, FULL);
2558 #endif
2560 #ifndef VMS
2562 ** Create the Shell menu
2563 @@ -1999,16 +2031,17 @@ static void showMatchingRangeDefCB(Widge
2565 WindowInfo *win;
2567 /* Set the preference and make the other windows' menus agree */
2568 SetPrefShowMatching(FLASH_RANGE);
2569 - for (win=WindowList; win!=NULL; win=win->next) {
2570 - if (!IsTopDocument(win))
2571 - continue;
2572 - XmToggleButtonSetState(win->showMatchingOffDefItem, False, False);
2573 - XmToggleButtonSetState(win->showMatchingDelimitDefItem, False, False);
2574 - XmToggleButtonSetState(win->showMatchingRangeDefItem, True, False);
2575 + for (win = WindowList; win != NULL; win = win->next) {
2576 + if (!IsTopDocument(win)) {
2577 + continue;
2579 + XmToggleButtonSetState(win->showMatchingOffDefItem, False, False);
2580 + XmToggleButtonSetState(win->showMatchingDelimitDefItem, False, False);
2581 + XmToggleButtonSetState(win->showMatchingRangeDefItem, True, False);
2585 static void matchSyntaxBasedDefCB(Widget w, WindowInfo *window, caddr_t callData)
2587 @@ -2175,10 +2208,41 @@ static void searchWrapsDefCB(Widget w, W
2588 if (IsTopDocument(win))
2589 XmToggleButtonSetState(win->searchWrapsDefItem, state, False);
2593 +static void showHiddenFilesCB(Widget widget, WindowInfo* unused,
2594 + caddr_t callData)
2596 + WindowInfo *window;
2597 + Boolean state = XmToggleButtonGetState(widget);
2599 + SetPrefShowHiddenFiles(state);
2600 + for (window = WindowList; window != NULL; window = window->next) {
2601 + XmToggleButtonSetState(window->showHiddenFilesItem, state, False);
2605 +static void showCursorlineCB(Widget widget, WindowInfo* unused,
2606 + caddr_t callData)
2608 + WindowInfo* window;
2609 + Boolean state = XmToggleButtonGetState(widget);
2611 + SetPrefShowCursorline(state);
2612 + for (window = WindowList; window != NULL; window = window->next) {
2613 + XmToggleButtonSetState(window->showCursorlineItem, state, False);
2615 + if (IsTopDocument(window)) {
2616 + Widget pane = (NULL == window->lastFocus
2617 + ? window->textArea
2618 + : window->lastFocus);
2619 + XtVaSetValues(pane, textNshowCursorline, state, NULL);
2624 static void appendLFCB(Widget w, WindowInfo* window, caddr_t callData)
2626 WindowInfo *win;
2627 int state = XmToggleButtonGetState(w);
2629 @@ -2537,10 +2601,39 @@ static void searchRegexNoCaseCB(Widget w
2630 XmToggleButtonSetState(win->searchRegexNoCaseDefItem, True, False);
2635 +static void searchRegexSmartCaseCB(Widget toggleButton, WindowInfo* window,
2636 + caddr_t callData)
2638 + WindowInfo* windowInfo;
2640 + /* Set the preference and make the other windows' menus agree */
2641 + if (XmToggleButtonGetState(toggleButton)) {
2642 + SetPrefSearch(SEARCH_REGEX_SMARTCASE);
2643 + for (windowInfo = WindowList;
2644 + windowInfo != NULL;
2645 + windowInfo = windowInfo->next) {
2646 + XmToggleButtonSetState(windowInfo->searchLiteralDefItem,
2647 + False, False);
2648 + XmToggleButtonSetState(windowInfo->searchCaseSenseDefItem,
2649 + False, False);
2650 + XmToggleButtonSetState(windowInfo->searchLiteralWordDefItem,
2651 + False, False);
2652 + XmToggleButtonSetState(windowInfo->searchCaseSenseWordDefItem,
2653 + False, False);
2654 + XmToggleButtonSetState(windowInfo->searchRegexDefItem,
2655 + False, False);
2656 + XmToggleButtonSetState(windowInfo->searchRegexNoCaseDefItem,
2657 + False, False);
2658 + XmToggleButtonSetState(windowInfo->searchRegexSmartCaseDefItem,
2659 + True, False);
2664 #ifdef REPLACE_SCOPE
2665 static void replaceScopeWindowCB(Widget w, WindowInfo *window, caddr_t callData)
2667 WindowInfo *win;
2669 @@ -2714,51 +2807,59 @@ static void unloadTipsFileMenuCB(Widget
2671 static void newAP(Widget w, XEvent *event, String *args, Cardinal *nArgs)
2673 WindowInfo *window = WidgetToWindow(w);
2674 int openInTab = GetPrefOpenInTab();
2675 + Boolean transient = False;
2677 + /* Look for arguments managing the type of window requested and whether
2678 + or not the user wants to have a transient window. */
2679 if (*nArgs > 0) {
2680 - if (strcmp(args[0], "prefs") == 0) {
2681 + if (0 == strcmp(args[0], "prefs")) {
2682 /* accept default */;
2684 - else if (strcmp(args[0], "tab") == 0) {
2685 + } else if (0 == strcmp(args[0], "tab")) {
2686 openInTab = 1;
2688 - else if (strcmp(args[0], "window") == 0) {
2689 + } else if (0 == strcmp(args[0], "window")) {
2690 openInTab = 0;
2692 - else if (strcmp(args[0], "opposite") == 0) {
2693 + } else if (0 == strcmp(args[0], "opposite")) {
2694 openInTab = !openInTab;
2696 - else {
2697 + } else if (0 == strcmp(args[0], "transient")) {
2698 + transient = True;
2699 + } else {
2700 fprintf(stderr, "nedit: Unknown argument to action procedure \"new\": %s\n", args[0]);
2704 - EditNewFile(openInTab? window : NULL, NULL, False, NULL, window->path);
2706 + /* Catch transient if it comes after a window type argument */
2707 + if (2 == *nArgs && (0 == strcmp(args[1], "transient"))) {
2708 + transient = True;
2711 + EditNewFile(openInTab? window : NULL, NULL, False, NULL, window->path,
2712 + transient);
2713 CheckCloseDim();
2717 -** These are just here because our techniques make it hard to bind a menu item
2718 -** to an action procedure that takes arguments. The user doesn't need to know
2719 -** about them -- they can use new( "opposite" ) or new( "tab" ).
2720 +** newOppositeAP() and newTabAP() are just here because our techniques make
2721 +** it hard to bind a menu item to an action procedure that takes arguments.
2722 +** The user doesn't need to know about them -- they can use new("opposite")
2723 +** or new("tab").
2725 static void newOppositeAP(Widget w, XEvent *event, String *args, Cardinal *nArgs)
2727 WindowInfo *window = WidgetToWindow(w);
2729 EditNewFile(GetPrefOpenInTab()? NULL : window, NULL, False, NULL,
2730 - window->path);
2731 + window->path, False);
2732 CheckCloseDim();
2734 static void newTabAP(Widget w, XEvent *event, String *args, Cardinal *nArgs)
2736 WindowInfo *window = WidgetToWindow(w);
2738 - EditNewFile(window, NULL, False, NULL, window->path);
2739 + EditNewFile(window, NULL, False, NULL, window->path, False);
2740 CheckCloseDim();
2743 static void openDialogAP(Widget w, XEvent *event, String *args, Cardinal *nArgs)
2745 @@ -2781,21 +2882,31 @@ static void openDialogAP(Widget w, XEven
2747 static void openAP(Widget w, XEvent *event, String *args, Cardinal *nArgs)
2749 WindowInfo *window = WidgetToWindow(w);
2750 char filename[MAXPATHLEN], pathname[MAXPATHLEN];
2751 + DataValue* fileNameArg = (DataValue*) XtMalloc(sizeof(DataValue));
2752 + DataValue* resultDV = (DataValue*) XtMalloc(sizeof(DataValue));
2754 if (*nArgs == 0) {
2755 fprintf(stderr, "nedit: open action requires file argument\n");
2756 return;
2758 - if (0 != ParseFilename(args[0], filename, pathname)
2760 + fileNameArg->tag = STRING_TAG;
2761 + AllocNStringNCpy(&fileNameArg->val.str, args[0], MAXPATHLEN);
2762 + MacroApplyHook(window, "file_name_hook", 1, fileNameArg, resultDV);
2763 + XtFree((char*) fileNameArg);
2765 + if (0 != ParseFilename(resultDV->val.str.rep, filename, pathname)
2766 || strlen(filename) + strlen(pathname) > MAXPATHLEN - 1) {
2767 fprintf(stderr, "nedit: invalid file name for open action: %s\n",
2768 args[0]);
2769 return;
2771 + XtFree((char*) resultDV);
2773 EditExistingFile(window, filename, pathname, 0, NULL, False,
2774 NULL, GetPrefOpenInTab(), False);
2775 CheckCloseDim();
2778 @@ -3942,11 +4053,11 @@ static void focusPaneAP(Widget w, XEvent
2780 if (paneIndex >= 0 && paneIndex <= window->nPanes) {
2781 newFocusPane = GetPaneByIndex(window, paneIndex);
2783 if (newFocusPane != NULL) {
2784 - window->lastFocus = newFocusPane;
2785 + ChangeLastFocus(window, newFocusPane);
2786 XmProcessTraversal(window->lastFocus, XmTRAVERSE_CURRENT);
2788 else {
2789 XBell(TheDisplay, 0);
2791 @@ -4085,10 +4196,23 @@ static void setWrapMarginAP(Widget w, XE
2792 else {
2793 fprintf(stderr, "nedit: set_wrap_margin requires argument\n");
2797 +static void setShowWrapMarginAP(Widget w, XEvent *event, String *args,
2798 + Cardinal *nArgs)
2800 + WindowInfo *window = WidgetToWindow(w);
2801 + int showWrapMargin = 0;
2803 + if (*nArgs > 0) {
2804 + if (sscanf(args[0], "%d", &showWrapMargin) == 1) {
2805 + SetShowWrapMargin(window, showWrapMargin);
2810 static void setHighlightSyntaxAP(Widget w, XEvent *event, String *args,
2811 Cardinal *nArgs)
2813 WindowInfo *window = WidgetToWindow(w);
2814 Boolean newState;
2815 @@ -4209,10 +4333,28 @@ static void setLockedAP(Widget w, XEvent
2816 XmToggleButtonSetState(window->readOnlyItem, IS_ANY_LOCKED(window->lockReasons), False);
2817 UpdateWindowTitle(window);
2818 UpdateWindowReadOnly(window);
2822 +** Action procedure for setting or toggling the transient flag.
2824 +static void setTransientAP(Widget text, XEvent* event, String* args,
2825 + Cardinal* nArgs)
2827 + WindowInfo* window = WidgetToWindow(text);
2828 + Boolean newState;
2830 + ACTION_BOOL_PARAM_OR_TOGGLE(newState, *nArgs, args,
2831 + window->transient, "set_transient");
2833 + window->transient = newState;
2834 + if (IsTopDocument(window)) {
2835 + XmToggleButtonSetState(window->transientItem, window->transient, False);
2839 static void setTabDistAP(Widget w, XEvent *event, String *args,
2840 Cardinal *nArgs)
2842 WindowInfo *window = WidgetToWindow(w);
2844 @@ -4511,17 +4653,40 @@ static void invalidatePrevOpenMenus(void
2846 void AddToPrevOpenMenu(const char *filename)
2848 int i;
2849 char *nameCopy;
2850 + char *fileMask, *compileMsg;
2851 + regexp *compiledRE;
2852 WindowInfo *w;
2854 /* If the Open Previous command is disabled, just return */
2855 if (GetPrefMaxPrevOpenFiles() < 1) {
2856 return;
2859 + /* If the name is to be omitted, return */
2860 + if ((fileMask = GetPrevOpenFilesMask()) && *fileMask)
2862 + compiledRE = CompileRE(fileMask, &compileMsg, REDFLT_STANDARD);
2863 + if (compiledRE == NULL)
2865 + fprintf(stderr, "nedit: %s\n", compileMsg);
2866 + } else
2868 + if (ExecRE(compiledRE, filename, NULL, FALSE, '\0', '\0', NULL,
2869 + NULL, NULL))
2871 + free((char *)compiledRE);
2872 + return;
2873 + } else
2875 + free((char *)compiledRE);
2880 /* Refresh list of previously opened files to avoid Big Race Condition,
2881 where two sessions overwrite each other's changes in NEdit's
2882 history file.
2883 Of course there is still Little Race Condition, which occurs if a
2884 Session A reads the list, then Session B reads the list and writes
2885 @@ -4864,10 +5029,12 @@ static int cmpStrPtr(const void *strA, c
2886 void WriteNEditDB(void)
2888 const char* fullName = GetRCFileName(NEDIT_HISTORY);
2889 FILE *fp;
2890 int i;
2891 + char *fileMask, *compileMsg;
2892 + regexp *compiledRE=NULL;
2893 static char fileHeader[] =
2894 "# File name database for NEdit Open Previous command\n";
2896 if (fullName == NULL) {
2897 /* GetRCFileName() might return NULL if an error occurs during
2898 @@ -4900,23 +5067,48 @@ void WriteNEditDB(void)
2899 #else
2900 return;
2901 #endif
2904 + /* set up removal of any files matching prevOpenFilesMask */
2905 + if ((fileMask = GetPrevOpenFilesMask()) && *fileMask)
2907 + compiledRE = CompileRE(fileMask, &compileMsg, REDFLT_STANDARD);
2908 + if (compiledRE == NULL)
2910 + fprintf(stderr, "%s\n", compileMsg);
2914 /* write the file header text to the file */
2915 fprintf(fp, "%s", fileHeader);
2917 /* Write the list of file names */
2918 - for (i = 0; i < NPrevOpen; ++i) {
2919 - size_t lineLen = strlen(PrevOpen[i]);
2920 + for (i = 0; i < NPrevOpen; i++)
2922 + /* omitting any files matching prevOpenFilesMask */
2923 + if (NULL == compiledRE
2924 + || 0 == ExecRE(compiledRE, PrevOpen[i], NULL, FALSE, '\0', '\0',
2925 + NULL, NULL, NULL))
2927 + size_t lineLen = strlen(PrevOpen[i]);
2929 - if (lineLen > 0 && PrevOpen[i][0] != '#' &&
2930 - strcspn(PrevOpen[i], neditDBBadFilenameChars) == lineLen) {
2931 - fprintf(fp, "%s\n", PrevOpen[i]);
2932 + /* omitting any files with invalid filenames */
2933 + if (lineLen > 0 && '#' != PrevOpen[i][0]
2934 + && strcspn(PrevOpen[i], neditDBBadFilenameChars) == lineLen)
2936 + fprintf(fp, "%s\n", PrevOpen[i]);
2942 + if (compiledRE != NULL) {
2943 + free((char *)compiledRE);
2946 + /* Close the file */
2947 fclose(fp);
2951 ** Read database of file names for 'Open Previous' submenu.
2952 diff --quilt old/source/nedit.c new/source/nedit.c
2953 --- old/source/nedit.c
2954 +++ new/source/nedit.c
2955 @@ -352,15 +352,21 @@ static char *fallbackResources[] = {
2956 "*windowsMenu.splitPane.acceleratorText: Ctrl+2",
2957 "*windowsMenu.closePane.accelerator: Ctrl<Key>1",
2958 "*windowsMenu.closePane.acceleratorText: Ctrl+1",
2959 "*helpMenu.mnemonic: H",
2960 "nedit.help.helpForm.sw.helpText*baseTranslations: #override\
2961 -<Key>Tab:help-focus-buttons()\\n\
2962 +<Key>space: scroll_down(1, \"pages\")\\n\
2963 +~Alt~Shift~Ctrl~Meta<KeyPress>osfUp: scroll_up(1)\\n\
2964 +~Alt~Shift~Ctrl~Meta<KeyPress>osfDown: scroll_down(1)\\n\
2965 +~Alt ~Shift ~Ctrl ~Meta<KeyPress>osfPageUp: scroll_up(1, \"pages\")\\n\
2966 +~Alt ~Shift ~Ctrl ~Meta<KeyPress>osfPageDown: scroll_down(1, \"pages\")\\n\
2967 +~Alt~Shift~Ctrl~Meta<KeyPress>osfLeft: help-button-action(\"prevTopic\")\\n\
2968 +~Alt~Shift~Ctrl~Meta<KeyPress>osfRight: help-button-action(\"nextTopic\")\\n\
2969 <Key>Return:help-button-action(\"close\")\\n\
2970 -Ctrl<Key>F:help-button-action(\"find\")\\n\
2971 -Ctrl<Key>G:help-button-action(\"findAgain\")\\n\
2972 <KeyPress>osfCancel:help-button-action(\"close\")\\n\
2973 +Ctrl<Key>f:help-button-action(\"find\")\\n\
2974 +Ctrl<Key>g:help-button-action(\"findAgain\")\\n\
2975 ~Meta~Ctrl~Shift<Btn1Down>:\
2976 grab-focus() help-hyperlink()\\n\
2977 ~Meta~Ctrl~Shift<Btn1Up>:\
2978 help-hyperlink(\"current\", \"process-cancel\", \"extend-end\")\\n\
2979 ~Meta~Ctrl~Shift<Btn2Down>:\
2980 @@ -489,11 +495,11 @@ int main(int argc, char **argv)
2982 /* Initialize global symbols and subroutines used in the macro language */
2983 InitMacroGlobals();
2984 RegisterMacroSubroutines();
2986 - /* Store preferences from the command line and .nedit file,
2987 + /* Store preferences from the command line and the nedit.rc file,
2988 and set the appropriate preferences */
2989 RestoreNEditPrefs(prefDB, XtDatabase(TheDisplay));
2991 /* Intercept syntactically invalid virtual key bindings BEFORE we
2992 create any shells. */
2993 @@ -775,11 +781,11 @@ int main(int argc, char **argv)
2995 CheckCloseDim();
2997 /* If no file to edit was specified, open a window to edit "Untitled" */
2998 if (!fileSpecified) {
2999 - EditNewFile(NULL, geometry, iconic, langMode, NULL);
3000 + EditNewFile(NULL, geometry, iconic, langMode, NULL, False);
3001 ReadMacroInitFile(WindowList);
3002 CheckCloseDim();
3003 if (toDoCommand != NULL)
3004 DoMacro(WindowList, toDoCommand, "-do macro");
3006 diff --quilt old/source/nedit.h new/source/nedit.h
3007 --- old/source/nedit.h
3008 +++ new/source/nedit.h
3009 @@ -52,13 +52,14 @@
3010 #define NEDIT_DEFAULT_SEL_BG "rgb:cc/cc/cc"
3011 #define NEDIT_DEFAULT_HI_FG "white" /* These are colors for flashing */
3012 #define NEDIT_DEFAULT_HI_BG "red" /* matching parens. */
3013 #define NEDIT_DEFAULT_LINENO_FG "black"
3014 #define NEDIT_DEFAULT_CURSOR_FG "black"
3015 +#define NEDIT_DEFAULT_WRAPMARGIN_FG "black"
3016 #define NEDIT_DEFAULT_HELP_FG "black"
3017 #define NEDIT_DEFAULT_HELP_BG "rgb:cc/cc/cc"
3019 +#define NEDIT_DEFAULT_CURSORLINE_BG "LightSteelBlue2"
3021 /* Tuning parameters */
3022 #define SEARCHMAX 5119 /* Maximum length of search/replace strings */
3023 #define MAX_SEARCH_HISTORY 100 /* Maximum length of search string history */
3024 #define MAX_PANES 6 /* Max # of ADDITIONAL text editing panes
3025 @@ -103,10 +104,12 @@
3026 enum indentStyle {NO_AUTO_INDENT, AUTO_INDENT, SMART_INDENT};
3027 enum wrapStyle {NO_WRAP, NEWLINE_WRAP, CONTINUOUS_WRAP};
3028 enum showMatchingStyle {NO_FLASH, FLASH_DELIMIT, FLASH_RANGE};
3029 enum virtKeyOverride { VIRT_KEY_OVERRIDE_NEVER, VIRT_KEY_OVERRIDE_AUTO,
3030 VIRT_KEY_OVERRIDE_ALWAYS };
3031 +enum showWrapMarginEnums {SHOW_WRAP_MARGIN_NEVER, SHOW_WRAP_MARGIN_ALWAYS,
3032 + SHOW_WRAP_MARGIN_ON_WRAP};
3034 /* This enum must be kept in parallel to the array TruncSubstitutionModes[]
3035 in preferences.c */
3036 enum truncSubstitution {TRUNCSUBST_SILENT, TRUNCSUBST_FAIL, TRUNCSUBST_WARN, TRUNCSUBST_IGNORE};
3038 @@ -191,10 +194,12 @@ enum colorTypes {
3039 SELECT_BG_COLOR,
3040 HILITE_FG_COLOR,
3041 HILITE_BG_COLOR,
3042 LINENO_FG_COLOR,
3043 CURSOR_FG_COLOR,
3044 + WRAPMARGIN_FG_COLOR,
3045 + CURSORLINE_BG_COLOR,
3046 NUM_COLORS
3049 /* cache user menus: manage mode of user menu list element */
3050 typedef enum {
3051 @@ -325,10 +330,11 @@ typedef struct _WindowInfo {
3052 Widget replaceMultiFileList;
3053 Widget replaceMultiFilePathBtn;
3054 Widget fontDialog; /* NULL, unless font dialog is up */
3055 Widget colorDialog; /* NULL, unless color dialog is up */
3056 Widget readOnlyItem; /* menu bar settable widgets... */
3057 + Widget transientItem;
3058 Widget autoSaveItem;
3059 Widget saveLastItem;
3060 Widget openSelItem;
3061 Widget newOppositeItem;
3062 Widget closeItem;
3063 @@ -393,10 +399,12 @@ typedef struct _WindowInfo {
3064 Widget backlightCharsDefItem;
3065 Widget searchDlogsDefItem;
3066 Widget beepOnSearchWrapDefItem;
3067 Widget keepSearchDlogsDefItem;
3068 Widget searchWrapsDefItem;
3069 + Widget showHiddenFilesItem;
3070 + Widget showCursorlineItem;
3071 Widget appendLFItem;
3072 Widget sortOpenPrevDefItem;
3073 Widget allTagsDefItem;
3074 Widget smartTagsDefItem;
3075 Widget reposDlogsDefItem;
3076 @@ -417,10 +425,11 @@ typedef struct _WindowInfo {
3077 Widget searchLiteralDefItem;
3078 Widget searchCaseSenseDefItem;
3079 Widget searchLiteralWordDefItem;
3080 Widget searchCaseSenseWordDefItem;
3081 Widget searchRegexNoCaseDefItem;
3082 + Widget searchRegexSmartCaseDefItem;
3083 Widget searchRegexDefItem;
3084 #ifdef REPLACE_SCOPE
3085 Widget replScopeWinDefItem;
3086 Widget replScopeSelDefItem;
3087 Widget replScopeSmartDefItem;
3088 @@ -495,10 +504,12 @@ typedef struct _WindowInfo {
3089 Boolean autoSave; /* is autosave turned on? */
3090 Boolean saveOldVersion; /* keep old version in filename.bck */
3091 char indentStyle; /* whether/how to auto indent */
3092 char wrapMode; /* line wrap style: NO_WRAP,
3093 NEWLINE_WRAP or CONTINUOUS_WRAP */
3094 + int showWrapMargin; /* show wrap margin style: NEVER,
3095 + ALWAYS, ON-WRAP as enums */
3096 Boolean overstrike; /* is overstrike mode turned on ? */
3097 char showMatchingStyle; /* How to show matching parens:
3098 NO_FLASH, FLASH_DELIMIT, or
3099 FLASH_RANGE */
3100 char matchSyntaxBased; /* Use syntax info to show matching */
3101 @@ -555,10 +566,11 @@ typedef struct _WindowInfo {
3102 #endif
3103 UserMenuCache *userMenuCache; /* cache user menus: */
3104 UserBGMenuCache userBGMenuCache; /* shell & macro menu are shared over all
3105 "tabbed" documents, while each document
3106 has its own background menu. */
3107 + Boolean transient;
3108 } WindowInfo;
3110 extern WindowInfo *WindowList;
3111 extern Display *TheDisplay;
3112 extern Widget TheAppShell;
3113 diff --quilt old/source/preferences.c new/source/preferences.c
3114 --- old/source/preferences.c
3115 +++ new/source/preferences.c
3116 @@ -115,13 +115,13 @@ enum fontStatus {GOOD_FONT, BAD_PRIMARY,
3117 ** The order of the elements in this array must be exactly the same
3118 ** as the order of the corresponding integers of the enum SearchType
3119 ** defined in search.h (!!)
3121 static char *SearchMethodStrings[] = {
3122 - "Literal", "CaseSense", "RegExp",
3123 - "LiteralWord", "CaseSenseWord", "RegExpNoCase",
3124 - NULL
3125 + "Literal", "CaseSense", "RegExp",
3126 + "LiteralWord", "CaseSenseWord", "RegExpNoCase", "RegExSmartCase",
3127 + NULL
3130 #ifdef REPLACE_SCOPE
3131 /* enumerated default scope for replace dialog if a selection exists when
3132 ** the dialog is popped up.
3133 @@ -138,10 +138,13 @@ static char *AutoWrapTypes[N_WRAP_STYLES
3134 static char *AutoIndentTypes[N_INDENT_STYLES+3] = {"None", "Auto",
3135 "Smart", "True", "False", NULL};
3136 #define N_VIRTKEY_OVERRIDE_MODES 3
3137 static char *VirtKeyOverrideModes[N_VIRTKEY_OVERRIDE_MODES+1] = { "Never",
3138 "Auto", "Always", NULL};
3139 +#define N_SHOW_WRAP_MARGIN_STYLES 3
3140 +static char *ShowWrapMarginStrings[N_SHOW_WRAP_MARGIN_STYLES+1] = { "Never",
3141 + "Always", "When Wrap is Enabled", NULL};
3143 #define N_SHOW_MATCHING_STYLES 3
3144 /* For backward compatibility, "False" and "True" are still accepted.
3145 They are internally converted to "Off" and "Delimiter" respectively.
3146 NOTE: N_SHOW_MATCHING_STYLES must correspond to the number of
3147 @@ -233,18 +236,23 @@ typedef struct {
3148 Widget hiliteBgErrW;
3149 Widget lineNoFgW;
3150 Widget lineNoFgErrW;
3151 Widget cursorFgW;
3152 Widget cursorFgErrW;
3153 + Widget wrapMarginFgW;
3154 + Widget wrapMarginFgErrW;
3155 + Widget cursorlineBgW;
3156 + Widget cursorlineBgErrW;
3157 WindowInfo *window;
3158 } colorDialog;
3160 /* Repository for simple preferences settings */
3161 static struct prefData {
3162 int openInTab; /* open files in new tabs */
3163 int wrapStyle; /* what kind of wrapping to do */
3164 int wrapMargin; /* 0=wrap at window width, other=wrap margin */
3165 + int showWrapMargin; /* whether to draw line at wrap margin */
3166 int autoIndent; /* style for auto-indent */
3167 int autoSave; /* whether automatic backup feature is on */
3168 int saveOldVersion; /* whether to preserve a copy of last version */
3169 int searchDlogs; /* whether to show explanatory search dialogs */
3170 int searchWrapBeep; /* 1=beep when search restarts at begin/end */
3171 @@ -293,14 +301,17 @@ static struct prefData {
3172 int sortTabs; /* sort tabs alphabetically */
3173 int repositionDialogs; /* w. to reposition dialogs under the pointer */
3174 int autoScroll; /* w. to autoscroll near top/bottom of screen */
3175 int autoScrollVPadding; /* how close to get before autoscrolling */
3176 int sortOpenPrevMenu; /* whether to sort the "Open Previous" menu */
3177 + int showHiddenFiles; /* whether to show hidden files in the FSBs */
3178 + int showCursorline; /* show cursorline */
3179 int appendLF; /* Whether to append LF at the end of each file */
3180 int mapDelete; /* whether to map delete to backspace */
3181 int stdOpenDialog; /* w. to retain redundant text field in Open */
3182 char tagFile[MAXPATHLEN]; /* name of tags file to look for at startup */
3183 + char prevOpenFilesMask[MAXPATHLEN]; /* regex to omit from Open Previous menu */
3184 int maxPrevOpenFiles; /* limit to size of Open Previous menu */
3185 int typingHidesPointer; /* hide mouse pointer when typing */
3186 char delimiters[MAX_WORD_DELIMITERS]; /* punctuation characters */
3187 char shell[MAXPATHLEN + 1]; /* shell to use for executing commands */
3188 char geometry[MAX_GEOM_STRING_LEN]; /* per-application geometry string,
3189 @@ -319,10 +330,11 @@ static struct prefData {
3190 char helpLinkColor[MAX_COLOR_LEN]; /* Color for hyperlinks in the help system */
3191 char colorNames[NUM_COLORS][MAX_COLOR_LEN];
3192 char tooltipBgColor[MAX_COLOR_LEN];
3193 int undoModifiesSelection;
3194 int focusOnRaise;
3195 + Boolean showScrolltip;
3196 Boolean honorSymlinks;
3197 int truncSubstitution;
3198 Boolean forceOSConversion;
3199 } PrefData;
3201 @@ -845,10 +857,12 @@ static PrefDescripRec PrefDescrip[] = {
3202 "Default", &TempStringPrefs.smartIndentCommon, NULL, True},
3203 {"autoWrap", "AutoWrap", PREF_ENUM, "Continuous",
3204 &PrefData.wrapStyle, AutoWrapTypes, True},
3205 {"wrapMargin", "WrapMargin", PREF_INT, "0",
3206 &PrefData.wrapMargin, NULL, True},
3207 + {"showWrapMargin", "ShowWrapMargin", PREF_ENUM, "Never",
3208 + &PrefData.showWrapMargin, ShowWrapMarginStrings, True},
3209 {"autoIndent", "AutoIndent", PREF_ENUM, "Auto",
3210 &PrefData.autoIndent, AutoIndentTypes, True},
3211 {"autoSave", "AutoSave", PREF_BOOLEAN, "True",
3212 &PrefData.autoSave, NULL, True},
3213 {"openInTab", "OpenInTab", PREF_BOOLEAN, "True",
3214 @@ -882,10 +896,12 @@ static PrefDescripRec PrefDescrip[] = {
3215 &PrefData.repositionDialogs, NULL, True},
3216 #else
3217 {"repositionDialogs", "RepositionDialogs", PREF_BOOLEAN, "True",
3218 &PrefData.repositionDialogs, NULL, True},
3219 #endif
3220 + {"showHiddenFiles", "ShowHiddenFiles", PREF_BOOLEAN, "True",
3221 + &PrefData.showHiddenFiles, NULL, True},
3222 {"autoScroll", "AutoScroll", PREF_BOOLEAN, "False",
3223 &PrefData.autoScroll, NULL, True},
3224 {"autoScrollVPadding", "AutoScrollVPadding", PREF_INT, "4",
3225 &PrefData.autoScrollVPadding, NULL, False},
3226 {"appendLF", "AppendLF", PREF_BOOLEAN, "True",
3227 @@ -1020,13 +1036,20 @@ static PrefDescripRec PrefDescrip[] = {
3228 PrefData.colorNames[LINENO_FG_COLOR],
3229 (void *)sizeof(PrefData.colorNames[LINENO_FG_COLOR]), True},
3230 {"cursorFgColor", "CursorFgColor", PREF_STRING, NEDIT_DEFAULT_CURSOR_FG,
3231 PrefData.colorNames[CURSOR_FG_COLOR],
3232 (void *)sizeof(PrefData.colorNames[CURSOR_FG_COLOR]), True},
3233 + {"cursorlineBGColor", "CursorlineBGColor", PREF_STRING,
3234 + NEDIT_DEFAULT_CURSORLINE_BG,
3235 + PrefData.colorNames[CURSORLINE_BG_COLOR],
3236 + (void *)sizeof(PrefData.colorNames[CURSORLINE_BG_COLOR]), True},
3237 {"tooltipBgColor", "TooltipBgColor", PREF_STRING, "LemonChiffon1",
3238 PrefData.tooltipBgColor,
3239 (void *)sizeof(PrefData.tooltipBgColor), False},
3240 + {"wrapMarginForeground", "wrapMarginForeground", PREF_STRING,
3241 + NEDIT_DEFAULT_LINENO_FG, PrefData.colorNames[WRAPMARGIN_FG_COLOR],
3242 + (void *)sizeof(PrefData.colorNames[WRAPMARGIN_FG_COLOR]), True},
3243 {"shell", "Shell", PREF_STRING, "DEFAULT", PrefData.shell,
3244 (void*) sizeof(PrefData.shell), True},
3245 {"geometry", "Geometry", PREF_STRING, "",
3246 PrefData.geometry, (void *)sizeof(PrefData.geometry), False},
3247 {"remapDeleteKey", "RemapDeleteKey", PREF_BOOLEAN, "False",
3248 @@ -1038,10 +1061,13 @@ static PrefDescripRec PrefDescrip[] = {
3249 {"wordDelimiters", "WordDelimiters", PREF_STRING,
3250 ".,/\\`'!|@#%^&*()-=+{}[]\":;<>?",
3251 PrefData.delimiters, (void *)sizeof(PrefData.delimiters), False},
3252 {"serverName", "ServerName", PREF_STRING, "", PrefData.serverName,
3253 (void *)sizeof(PrefData.serverName), False},
3254 + {"prevOpenFilesMask", "PrevOpenFilesMask", PREF_STRING, "",
3255 + PrefData.prevOpenFilesMask,
3256 + (void*) sizeof(PrefData.prevOpenFilesMask), False},
3257 {"maxPrevOpenFiles", "MaxPrevOpenFiles", PREF_INT, "30",
3258 &PrefData.maxPrevOpenFiles, NULL, False},
3259 {"bgMenuButton", "BGMenuButton" , PREF_STRING,
3260 "~Shift~Ctrl~Meta~Alt<Btn3Down>", PrefData.bgMenuBtn,
3261 (void *)sizeof(PrefData.bgMenuBtn), False},
3262 @@ -1069,10 +1095,14 @@ static PrefDescripRec PrefDescrip[] = {
3263 "False", &PrefData.focusOnRaise, NULL, False},
3264 {"forceOSConversion", "ForceOSConversion", PREF_BOOLEAN, "True",
3265 &PrefData.forceOSConversion, NULL, False},
3266 {"truncSubstitution", "TruncSubstitution", PREF_ENUM, "Fail",
3267 &PrefData.truncSubstitution, TruncSubstitutionModes, False},
3268 + {"showCursorline", "ShowCursorline", PREF_BOOLEAN, "True",
3269 + &PrefData.showCursorline, NULL, True},
3270 + {"showScrolltip", "ShowScrolltip", PREF_BOOLEAN, "True",
3271 + &PrefData.showScrolltip, NULL, False},
3272 {"honorSymlinks", "HonorSymlinks", PREF_BOOLEAN, "True",
3273 &PrefData.honorSymlinks, NULL, False}
3276 static XrmOptionDescRec OpTable[] = {
3277 @@ -1124,11 +1154,13 @@ static WindowInfo *TabsDialogForWindow;
3278 static Widget TabDistText, EmTabText, EmTabToggle, UseTabsToggle, EmTabLabel;
3280 /* Module-global variables for Wrap Margin dialog */
3281 static int DoneWithWrapDialog;
3282 static WindowInfo *WrapDialogForWindow;
3283 -static Widget WrapText, WrapTextLabel, WrapWindowToggle;
3284 +static Widget WrapText, WrapTextLabel, WrapWindowToggle, ShowWrapMarginPulldown,
3285 + ShowWrapMarginPulldownItems[N_SHOW_WRAP_MARGIN_STYLES],
3286 + ShowWrapMarginOptMenu, ShowWrapMarginLabel;
3288 /* Module-global variables for shell selection dialog */
3289 static int DoneWithShellSelDialog = False;
3291 static void translatePrefFormats(int convertOld, int fileVer);
3292 @@ -1234,22 +1266,22 @@ static void updatePatternsTo5dot6(void);
3293 static void updateMacroCmdsTo5dot6(void);
3294 static void migrateColorResources(XrmDatabase prefDB, XrmDatabase appDB);
3295 static void spliceString(char **intoString, const char *insertString, const char *atExpr);
3296 static int regexFind(const char *inString, const char *expr);
3297 static int regexReplace(char **inString, const char *expr,
3298 - const char *replaceWith);
3299 + const char *replaceWith);
3300 +static void initPrefDefaultsFromResources(XrmDatabase prefDB, XrmDatabase appDB);
3301 static int caseFind(const char *inString, const char *expr);
3302 static int caseReplace(char **inString, const char *expr,
3303 const char *replaceWith, int replaceLen);
3304 static int stringReplace(char **inString, const char *expr,
3305 const char *replaceWith, int searchType,
3306 int replaceLen);
3307 static int replaceMacroIfUnchanged(const char* oldText, const char* newStart,
3308 const char* newEnd);
3309 static const char* getDefaultShell(void);
3312 #ifdef SGI_CUSTOM
3313 static int shortPrefToDefault(Widget parent, const char *settingName, int *setDefault);
3314 #endif
3316 XrmDatabase CreateNEditPrefDB(int *argcInOut, char **argvInOut)
3317 @@ -1264,10 +1296,14 @@ void RestoreNEditPrefs(XrmDatabase prefD
3318 int major; /* The integral part of version number */
3319 int minor; /* fractional part of version number */
3320 int fileVer = 0; /* Both combined into an integer */
3321 int nparsed;
3323 + /* Default values of certain preferences are derived from Motif resources,
3324 + if these resources are set. */
3325 + initPrefDefaultsFromResources(prefDB, appDB);
3327 /* Load preferences */
3328 RestorePreferences(prefDB, appDB, APP_NAME,
3329 APP_CLASS, PrefDescrip, XtNumber(PrefDescrip));
3331 /* If the preferences file was written by an older version of NEdit,
3332 @@ -1559,10 +1595,20 @@ void SetPrefWrapMargin(int margin)
3333 int GetPrefWrapMargin(void)
3335 return PrefData.wrapMargin;
3338 +void SetPrefShowWrapMargin(int state)
3340 + setIntPref(&PrefData.showWrapMargin, state);
3343 +int GetPrefShowWrapMargin(void)
3345 + return PrefData.showWrapMargin;
3348 void SetPrefSearch(int searchType)
3350 setIntPref(&PrefData.searchMethod, searchType);
3353 @@ -1930,10 +1976,20 @@ void SetPrefRepositionDialogs(int state)
3354 int GetPrefRepositionDialogs(void)
3356 return PrefData.repositionDialogs;
3359 +void SetPrefShowHiddenFiles(int state)
3361 + setIntPref(&PrefData.showHiddenFiles, state);
3364 +int GetPrefShowHiddenFiles(void)
3366 + return PrefData.showHiddenFiles;
3369 void SetPrefAutoScroll(int state)
3371 WindowInfo *w = WindowList;
3372 int margin = state ? PrefData.autoScrollVPadding : 0;
3374 @@ -2118,10 +2174,15 @@ char *GetPrefServerName(void)
3375 char *GetPrefBGMenuBtn(void)
3377 return PrefData.bgMenuBtn;
3380 +char *GetPrevOpenFilesMask(void)
3382 + return PrefData.prevOpenFilesMask;
3385 int GetPrefMaxPrevOpenFiles(void)
3387 return PrefData.maxPrevOpenFiles;
3390 @@ -2186,10 +2247,25 @@ int GetPrefOverrideVirtKeyBindings(void)
3391 int GetPrefTruncSubstitution(void)
3393 return PrefData.truncSubstitution;
3396 +void SetPrefShowCursorline(Boolean value)
3398 + setIntPref(&PrefData.showCursorline, (int) value);
3401 +Boolean GetPrefShowCursorline(void)
3403 + return (Boolean) PrefData.showCursorline;
3406 +Boolean GetPrefShowScrolltip(void)
3408 + return (Boolean) PrefData.showScrolltip;
3412 ** If preferences don't get saved, ask the user on exit whether to save
3414 void MarkPrefsChanged(void)
3416 @@ -2678,10 +2754,13 @@ void WrapMarginDialog(Widget parent, Win
3418 Widget form, selBox;
3419 Arg selBoxArgs[2];
3420 XmString s1;
3421 int margin;
3422 + int showWrapMargin;
3423 + int i, n;
3424 + Arg args[20];
3426 XtSetArg(selBoxArgs[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
3427 XtSetArg(selBoxArgs[1], XmNautoUnmanage, False);
3428 selBox = CreatePromptDialog(parent, "wrapMargin", selBoxArgs, 2);
3429 XtAddCallback(selBox, XmNokCallback, (XtCallbackProc)wrapOKCB, NULL);
3430 @@ -2720,20 +2799,74 @@ void WrapMarginDialog(Widget parent, Win
3431 XmNrightWidget, WrapText,
3432 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
3433 XmNbottomWidget, WrapText, NULL);
3434 XmStringFree(s1);
3436 + ShowWrapMarginPulldown = CreatePulldownMenu(form, "ShowWrapMarginPulldown",
3437 + NULL, 0);
3438 + for(i=0; i<N_SHOW_WRAP_MARGIN_STYLES; i++) {
3439 + s1 = XmStringCreateSimple(ShowWrapMarginStrings[i]);
3440 + ShowWrapMarginPulldownItems[i] = XtVaCreateManagedWidget(
3441 + "ShowWrapMarginPulldown",
3442 + xmPushButtonWidgetClass, ShowWrapMarginPulldown,
3443 + XmNlabelString, s1,
3444 + XmNmarginHeight, 0,
3445 + XmNuserData, i,
3446 + NULL);
3447 + XmStringFree(s1);
3449 + n = 0;
3450 + XtSetArg(args[n], XmNspacing, 0); n++;
3451 + XtSetArg(args[n], XmNmarginWidth, 0); n++;
3452 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
3453 + XtSetArg(args[n], XmNtopWidget, WrapText); n++;
3454 + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
3455 + XtSetArg(args[n], XmNsubMenuId, ShowWrapMarginPulldown); n++;
3456 + ShowWrapMarginOptMenu = XmCreateOptionMenu(form,
3457 + "ShowWrapMarginOptMenu", args, n);
3458 + XtManageChild(ShowWrapMarginOptMenu);
3460 + ShowWrapMarginLabel = XtVaCreateManagedWidget("ShowWrapMarginLabel",
3461 + xmLabelGadgetClass, form,
3462 + XmNlabelString, s1=XmStringCreateSimple("Show Wrap Margin"),
3463 + XmNmnemonic, 'S',
3464 + XmNuserData, XtParent(ShowWrapMarginOptMenu),
3465 + XmNalignment, XmALIGNMENT_END,
3466 + XmNtopAttachment, XmATTACH_WIDGET,
3467 + XmNtopWidget, WrapText,
3468 + XmNleftAttachment, XmATTACH_FORM,
3469 + XmNrightAttachment, XmATTACH_WIDGET,
3470 + XmNrightWidget, ShowWrapMarginOptMenu,
3471 + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
3472 + XmNbottomWidget, ShowWrapMarginOptMenu,
3473 + NULL);
3474 + XmStringFree(s1);
3476 /* Set default value */
3477 - if (forWindow == NULL)
3478 + if (forWindow == NULL) {
3479 margin = GetPrefWrapMargin();
3480 - else
3481 + showWrapMargin = GetPrefShowWrapMargin();
3482 + } else {
3483 XtVaGetValues(forWindow->textArea, textNwrapMargin, &margin, NULL);
3484 + showWrapMargin = forWindow->showWrapMargin;
3487 + if (showWrapMargin > N_SHOW_WRAP_MARGIN_STYLES || showWrapMargin < 0)
3489 + fprintf(stderr, "nedit: internal error: illegal value for showWrapMargin: %d\n", showWrapMargin);
3490 + showWrapMargin = SHOW_WRAP_MARGIN_NEVER;
3493 XmToggleButtonSetState(WrapWindowToggle, margin==0, True);
3494 + XtVaSetValues(ShowWrapMarginOptMenu, XmNmenuHistory,
3495 + ShowWrapMarginPulldownItems[showWrapMargin], NULL);
3496 if (margin != 0)
3497 SetIntText(WrapText, margin);
3498 XtSetSensitive(WrapText, margin!=0);
3499 XtSetSensitive(WrapTextLabel, margin!=0);
3500 + XtSetSensitive(ShowWrapMarginOptMenu, margin!=0);
3501 + XtSetSensitive(ShowWrapMarginLabel, margin!=0);
3503 /* Handle mnemonic selection of buttons and focus to dialog */
3504 AddDialogMnemonicHandler(form, FALSE);
3506 /* put up dialog and wait for user to press ok or cancel */
3507 @@ -2752,10 +2885,12 @@ void WrapMarginDialog(Widget parent, Win
3509 static void wrapOKCB(Widget w, XtPointer clientData, XtPointer callData)
3511 int wrapAtWindow, margin, stat;
3512 WindowInfo *window = WrapDialogForWindow;
3513 + int showWrapMargin;
3514 + Widget showWrapMarginSelectedItem;
3516 /* get the values that the user entered and make sure they're ok */
3517 wrapAtWindow = XmToggleButtonGetState(WrapWindowToggle);
3518 if (wrapAtWindow)
3519 margin = 0;
3520 @@ -2771,10 +2906,17 @@ static void wrapOKCB(Widget w, XtPointer
3521 return;
3526 + XtVaGetValues(ShowWrapMarginOptMenu, XmNmenuHistory,
3527 + &showWrapMarginSelectedItem, NULL);
3528 + XtVaGetValues(showWrapMarginSelectedItem, XmNuserData, &showWrapMargin, NULL);
3529 + if (showWrapMargin > N_SHOW_WRAP_MARGIN_STYLES || showWrapMargin < 0) {
3530 + showWrapMargin = SHOW_WRAP_MARGIN_NEVER;
3533 #ifdef SGI_CUSTOM
3534 /* Ask the user about saving as a default preference */
3535 if (WrapDialogForWindow != NULL) {
3536 int setDefault;
3537 if (!shortPrefToDefault(window->shell, "Wrap Margin Settings",
3538 @@ -2782,24 +2924,29 @@ static void wrapOKCB(Widget w, XtPointer
3539 DoneWithWrapDialog = True;
3540 return;
3542 if (setDefault) {
3543 SetPrefWrapMargin(margin);
3544 + SetPrefShowWrapMargin(showWrapMargin);
3545 SaveNEditPrefs(window->shell, GetPrefShortMenus());
3548 #endif
3550 /* Set the value in either the requested window or default preferences */
3551 - if (WrapDialogForWindow == NULL)
3552 + if (WrapDialogForWindow == NULL) {
3553 SetPrefWrapMargin(margin);
3554 - else {
3555 + SetPrefShowWrapMargin(showWrapMargin);
3556 + } else {
3557 char *params[1];
3558 char marginStr[25];
3559 sprintf(marginStr, "%d", margin);
3560 params[0] = marginStr;
3561 XtCallActionProc(window->textArea, "set_wrap_margin", NULL, params, 1);
3562 + sprintf(marginStr, "%d", showWrapMargin);
3563 + params[0] = marginStr;
3564 + XtCallActionProc(window->textArea, "set_show_wrap_margin", NULL, params, 1);
3566 DoneWithWrapDialog = True;
3569 static void wrapCancelCB(Widget w, XtPointer clientData, XtPointer callData)
3570 @@ -2811,10 +2958,12 @@ static void wrapWindowCB(Widget w, XtPoi
3572 int wrapAtWindow = XmToggleButtonGetState(w);
3574 XtSetSensitive(WrapTextLabel, !wrapAtWindow);
3575 XtSetSensitive(WrapText, !wrapAtWindow);
3576 + XtSetSensitive(ShowWrapMarginOptMenu, !wrapAtWindow);
3577 + XtSetSensitive(ShowWrapMarginLabel, !wrapAtWindow);
3581 ** Create and show a dialog for selecting the shell
3583 @@ -6072,10 +6221,11 @@ selectFg SELECT_FG_COLOR
3584 selectBg SELECT_BG_COLOR
3585 hiliteFg HILITE_FG_COLOR
3586 hiliteBg HILITE_BG_COLOR
3587 lineNoFg LINENO_FG_COLOR
3588 cursorFg CURSOR_FG_COLOR
3589 +cursorlineBg CURSORLINE_BG_COLOR
3592 #define MARGIN_SPACING 10
3595 @@ -6135,10 +6285,24 @@ static void cursorFgModifiedCB(Widget w,
3597 colorDialog *cd = (colorDialog *)clientData;
3598 showColorStatus(cd, cd->cursorFgW, cd->cursorFgErrW);
3601 +static void wrapMarginFgModifiedCB(Widget w, XtPointer clientData,
3602 + XtPointer callData)
3604 + colorDialog *cd = (colorDialog *)clientData;
3605 + showColorStatus(cd, cd->wrapMarginFgW, cd->wrapMarginFgErrW);
3608 +static void cursorlineBgModifiedCB(Widget w, XtPointer clientData,
3609 + XtPointer callData)
3611 + colorDialog *cd = (colorDialog *)clientData;
3612 + showColorStatus(cd, cd->cursorlineBgW, cd->cursorlineBgErrW);
3617 * Helper functions for validating colors
3619 static int verifyAllColors(colorDialog *cd)
3620 @@ -6149,11 +6313,12 @@ static int verifyAllColors(colorDialog *
3621 checkColorStatus(cd, cd->selectFgW) &&
3622 checkColorStatus(cd, cd->selectBgW) &&
3623 checkColorStatus(cd, cd->hiliteFgW) &&
3624 checkColorStatus(cd, cd->hiliteBgW) &&
3625 checkColorStatus(cd, cd->lineNoFgW) &&
3626 - checkColorStatus(cd, cd->cursorFgW) );
3627 + checkColorStatus(cd, cd->cursorFgW) &&
3628 + checkColorStatus(cd, cd->cursorlineBgW));
3631 /* Returns True if the color is valid, False if it's not */
3632 static Boolean checkColorStatus(colorDialog *cd, Widget colorFieldW)
3634 @@ -6188,35 +6353,41 @@ static void updateColors(colorDialog *cd
3635 *selectFg = XmTextGetString(cd->selectFgW),
3636 *selectBg = XmTextGetString(cd->selectBgW),
3637 *hiliteFg = XmTextGetString(cd->hiliteFgW),
3638 *hiliteBg = XmTextGetString(cd->hiliteBgW),
3639 *lineNoFg = XmTextGetString(cd->lineNoFgW),
3640 - *cursorFg = XmTextGetString(cd->cursorFgW);
3641 + *cursorFg = XmTextGetString(cd->cursorFgW),
3642 + *wrapMarginFg = XmTextGetString(cd->wrapMarginFgW),
3643 + *cursorlineBg = XmTextGetString(cd->cursorlineBgW);
3645 for (window = WindowList; window != NULL; window = window->next)
3647 SetColors(window, textFg, textBg, selectFg, selectBg, hiliteFg,
3648 - hiliteBg, lineNoFg, cursorFg);
3649 + hiliteBg, lineNoFg, cursorFg, wrapMarginFg, cursorlineBg);
3652 SetPrefColorName(TEXT_FG_COLOR , textFg );
3653 SetPrefColorName(TEXT_BG_COLOR , textBg );
3654 SetPrefColorName(SELECT_FG_COLOR, selectFg);
3655 SetPrefColorName(SELECT_BG_COLOR, selectBg);
3656 SetPrefColorName(HILITE_FG_COLOR, hiliteFg);
3657 SetPrefColorName(HILITE_BG_COLOR, hiliteBg);
3658 SetPrefColorName(LINENO_FG_COLOR, lineNoFg);
3659 SetPrefColorName(CURSOR_FG_COLOR, cursorFg);
3660 + SetPrefColorName(WRAPMARGIN_FG_COLOR, wrapMarginFg);
3661 + SetPrefColorName(CURSORLINE_BG_COLOR, cursorlineBg);
3663 XtFree(textFg);
3664 XtFree(textBg);
3665 XtFree(selectFg);
3666 XtFree(selectBg);
3667 XtFree(hiliteFg);
3668 XtFree(hiliteBg);
3669 XtFree(lineNoFg);
3670 XtFree(cursorFg);
3671 + XtFree(wrapMarginFg);
3672 + XtFree(cursorlineBg);
3677 * Dialog button callbacks
3678 @@ -6382,10 +6553,27 @@ void ChooseColors(WindowInfo *window)
3679 NULL);
3680 XmStringFree(s1);
3682 topW = infoLbl;
3684 + /* The right column (backgrounds) */
3685 + tmpW = addColorGroup( form, "textBg", 'T', "Text Area Background",
3686 + &(cd->textBgW), &(cd->textBgErrW), topW, 51, 99,
3687 + textBgModifiedCB, cd );
3688 + tmpW = addColorGroup( form, "selectBg", 'B', "Selection Background",
3689 + &(cd->selectBgW), &(cd->selectBgErrW), tmpW, 51, 99,
3690 + selectBgModifiedCB, cd );
3691 + tmpW = addColorGroup( form, "hiliteBg", 'h', "Matching (..) Background",
3692 + &(cd->hiliteBgW), &(cd->hiliteBgErrW), tmpW, 51, 99,
3693 + hiliteBgModifiedCB, cd );
3694 + tmpW = addColorGroup( form, "wrapMarginFg", 'w', "Wrap Margin Color",
3695 + &(cd->wrapMarginFgW), &(cd->wrapMarginFgErrW), tmpW, 51, 99,
3696 + wrapMarginFgModifiedCB, cd );
3697 + tmpW = addColorGroup( form, "cursorlineBg", 'r', "Cursorline Highlighting",
3698 + &(cd->cursorlineBgW), &(cd->cursorlineBgErrW), tmpW, 51, 99,
3699 + cursorlineBgModifiedCB, cd );
3701 /* The left column (foregrounds) of color entry groups */
3702 tmpW = addColorGroup( form, "textFg", 'P', "Plain Text Foreground",
3703 &(cd->textFgW), &(cd->textFgErrW), topW, 1, 49,
3704 textFgModifiedCB, cd );
3705 tmpW = addColorGroup( form, "selectFg", 'S', "Selection Foreground",
3706 @@ -6395,23 +6583,12 @@ void ChooseColors(WindowInfo *window)
3707 &(cd->hiliteFgW), &(cd->hiliteFgErrW), tmpW, 1, 49,
3708 hiliteFgModifiedCB, cd );
3709 tmpW = addColorGroup( form, "lineNoFg", 'L', "Line Numbers",
3710 &(cd->lineNoFgW), &(cd->lineNoFgErrW), tmpW, 1, 49,
3711 lineNoFgModifiedCB, cd );
3713 - /* The right column (backgrounds) */
3714 - tmpW = addColorGroup( form, "textBg", 'T', "Text Area Background",
3715 - &(cd->textBgW), &(cd->textBgErrW), topW, 51, 99,
3716 - textBgModifiedCB, cd );
3717 - tmpW = addColorGroup( form, "selectBg", 'B', "Selection Background",
3718 - &(cd->selectBgW), &(cd->selectBgErrW), tmpW, 51, 99,
3719 - selectBgModifiedCB, cd );
3720 - tmpW = addColorGroup( form, "hiliteBg", 'h', "Matching (..) Background",
3721 - &(cd->hiliteBgW), &(cd->hiliteBgErrW), tmpW, 51, 99,
3722 - hiliteBgModifiedCB, cd );
3723 tmpW = addColorGroup( form, "cursorFg", 'C', "Cursor Color",
3724 - &(cd->cursorFgW), &(cd->cursorFgErrW), tmpW, 51, 99,
3725 + &(cd->cursorFgW), &(cd->cursorFgErrW), tmpW, 1, 49,
3726 cursorFgModifiedCB, cd );
3728 tmpW = XtVaCreateManagedWidget("infoLbl",
3729 xmLabelGadgetClass, form,
3730 XmNtopAttachment, XmATTACH_WIDGET,
3731 @@ -6490,18 +6667,70 @@ void ChooseColors(WindowInfo *window)
3732 XmTextSetString(cd->selectBgW, GetPrefColorName(SELECT_BG_COLOR));
3733 XmTextSetString(cd->hiliteFgW, GetPrefColorName(HILITE_FG_COLOR));
3734 XmTextSetString(cd->hiliteBgW, GetPrefColorName(HILITE_BG_COLOR));
3735 XmTextSetString(cd->lineNoFgW, GetPrefColorName(LINENO_FG_COLOR));
3736 XmTextSetString(cd->cursorFgW, GetPrefColorName(CURSOR_FG_COLOR));
3737 + XmTextSetString(cd->wrapMarginFgW, GetPrefColorName(WRAPMARGIN_FG_COLOR));
3738 + XmTextSetString(cd->cursorlineBgW, GetPrefColorName(CURSORLINE_BG_COLOR));
3740 /* Handle mnemonic selection of buttons and focus to dialog */
3741 AddDialogMnemonicHandler(form, FALSE);
3743 /* put up dialog */
3744 ManageDialogCenteredOnPointer(form);
3747 +/* Overrides the defaults for certain preferences with values obtained from
3748 + obsoleted resources. */
3749 +static void initPrefDefaultsFromResources(XrmDatabase prefDB, XrmDatabase appDB)
3751 + char *type, *valueString;
3752 + XrmValue rsrcValue;
3754 + /* XmFileSelectionBox.fileFilterStyle is now obsolete since it is
3755 + overridden by nedit.showHiddenFiles, but this code tries to make
3756 + the transition painless by translating the resource value, if set,
3757 + to a matching default for the preferences */
3758 + const char* showHiddenResName =
3759 + APP_NAME "*XmFileSelectionBox.fileFilterStyle";
3760 + const char* showHiddenClassName =
3761 + APP_CLASS "*XmFileSelectionBox.FileFilterStyle";
3763 + /* Retrieve the value of the resource from the DB */
3764 + if (XrmGetResource(prefDB, showHiddenResName, showHiddenClassName, &type,
3765 + &rsrcValue)) {
3766 + if (strcmp(type, XmRString)) {
3767 + fprintf(stderr, "nedit: Internal Error: Unexpected resource type, %s\n",
3768 + type);
3769 + return;
3771 + valueString = rsrcValue.addr;
3772 + } else if (XrmGetResource(appDB, showHiddenResName, showHiddenClassName,
3773 + &type, &rsrcValue)) {
3774 + if (strcmp(type, XmRString)) {
3775 + fprintf(stderr, "nedit: Internal Error: Unexpected resource type, %s\n",
3776 + type);
3777 + return;
3779 + valueString = rsrcValue.addr;
3780 + } else {
3781 + /* No resources set */
3782 + return;
3785 + /* An X resource is set. If it's non-default, update the prefs default. */
3786 + if (0 == strcmp(valueString, "XmFILTER_HIDDEN_FILES")) {
3787 + unsigned int i;
3788 + for (i = 0; i < XtNumber(PrefDescrip); ++i) {
3789 + if (0 == strcmp(PrefDescrip[i].name, "showHiddenFiles")) {
3790 + PrefDescrip[i].defaultString = "False";
3791 + break;
3798 ** This function passes up a pointer to the static name of the default
3799 ** shell, currently defined as the user's login shell.
3800 ** In case of errors, the fallback of "sh" will be returned.
3802 diff --quilt old/source/preferences.h new/source/preferences.h
3803 --- old/source/preferences.h
3804 +++ new/source/preferences.h
3805 @@ -57,10 +57,12 @@ void MarkPrefsChanged(void);
3806 int CheckPrefsChangesSaved(Widget dialogParent);
3807 void SetPrefWrap(int state);
3808 int GetPrefWrap(int langMode);
3809 void SetPrefWrapMargin(int margin);
3810 int GetPrefWrapMargin(void);
3811 +void SetPrefShowWrapMargin(int state);
3812 +int GetPrefShowWrapMargin(void);
3813 void SetPrefSearchDlogs(int state);
3814 int GetPrefSearchDlogs(void);
3815 void SetPrefKeepSearchDlogs(int state);
3816 int GetPrefKeepSearchDlogs(void);
3817 void SetPrefSearchWraps(int state);
3818 @@ -117,10 +119,12 @@ void SetPrefBacklightChars(int state);
3819 int GetPrefBacklightChars(void);
3820 void SetPrefBacklightCharTypes(char *types);
3821 char *GetPrefBacklightCharTypes(void);
3822 void SetPrefRepositionDialogs(int state);
3823 int GetPrefRepositionDialogs(void);
3824 +void SetPrefShowHiddenFiles(int state);
3825 +int GetPrefShowHiddenFiles(void);
3826 void SetPrefAutoScroll(int state);
3827 int GetPrefAutoScroll(void);
3828 int GetVerticalAutoScroll(void);
3829 void SetPrefAppendLF(int state);
3830 int GetPrefAppendLF(void);
3831 @@ -156,10 +160,11 @@ void RowColumnPrefDialog(Widget parent);
3832 void TabsPrefDialog(Widget parent, WindowInfo *forWindow);
3833 void WrapMarginDialog(Widget parent, WindowInfo *forWindow);
3834 int GetPrefMapDelete(void);
3835 int GetPrefStdOpenDialog(void);
3836 char *GetPrefDelimiters(void);
3837 +char *GetPrevOpenFilesMask(void);
3838 int GetPrefMaxPrevOpenFiles(void);
3839 int GetPrefTypingHidesPointer(void);
3840 #ifdef SGI_CUSTOM
3841 void SetPrefShortMenus(int state);
3842 int GetPrefShortMenus(void);
3843 @@ -209,7 +214,10 @@ void SetPrefOpenInTab(int state);
3844 Boolean GetPrefUndoModifiesSelection(void);
3845 Boolean GetPrefFocusOnRaise(void);
3846 Boolean GetPrefHonorSymlinks(void);
3847 Boolean GetPrefForceOSConversion(void);
3848 void SetPrefFocusOnRaise(Boolean);
3849 +void SetPrefShowCursorline(Boolean value);
3850 +Boolean GetPrefShowCursorline(void);
3851 +Boolean GetPrefShowScrolltip(void);
3853 #endif /* NEDIT_PREFERENCES_H_INCLUDED */
3854 diff --quilt old/source/search.c new/source/search.c
3855 --- old/source/search.c
3856 +++ new/source/search.c
3857 @@ -241,10 +241,11 @@ static void iSearchCaseToggleCB(Widget w
3858 XtPointer callData);
3859 static void iSearchTryBeepOnWrap(WindowInfo *window, int direction,
3860 int beginPos, int startPos);
3861 static void iSearchRecordLastBeginPos(WindowInfo *window, int direction,
3862 int initPos);
3863 +static void smartCaseToggle(const char* searchString, Widget toggleButton);
3864 static Boolean prefOrUserCancelsSubst(const Widget parent,
3865 const Display* display);
3867 typedef struct _charMatchTable {
3868 char c;
3869 @@ -279,10 +280,11 @@ static char *searchTypeStrings[] = {
3870 "case", /* SEARCH_CASE_SENSE */
3871 "regex", /* SEARCH_REGEX */
3872 "word", /* SEARCH_LITERAL_WORD */
3873 "caseWord", /* SEARCH_CASE_SENSE_WORD */
3874 "regexNoCase", /* SEARCH_REGEX_NOCASE */
3875 + "regexSmartCase", /* SEARCH_REGEX_SMARTCASE */
3876 NULL
3880 ** Window for which a search dialog callback is currently active. That window
3881 @@ -317,70 +319,77 @@ static void initToggleButtons(int search
3882 Bool* lastRegexCase)
3884 /* Set the initial search type and remember the corresponding case
3885 sensitivity states in case sticky case sensitivity is required. */
3886 switch (searchType) {
3887 - case SEARCH_LITERAL:
3888 + case SEARCH_LITERAL:
3889 *lastLiteralCase = False;
3890 *lastRegexCase = True;
3891 XmToggleButtonSetState(regexToggle, False, False);
3892 XmToggleButtonSetState(caseToggle, False, False);
3893 if (wordToggle) {
3894 XmToggleButtonSetState(*wordToggle, False, False);
3895 XtSetSensitive(*wordToggle, True);
3897 - break;
3898 - case SEARCH_CASE_SENSE:
3899 + break;
3901 + case SEARCH_CASE_SENSE:
3902 *lastLiteralCase = True;
3903 *lastRegexCase = True;
3904 XmToggleButtonSetState(regexToggle, False, False);
3905 XmToggleButtonSetState(caseToggle, True, False);
3906 if (wordToggle) {
3907 XmToggleButtonSetState(*wordToggle, False, False);
3908 XtSetSensitive(*wordToggle, True);
3910 - break;
3911 - case SEARCH_LITERAL_WORD:
3912 + break;
3914 + case SEARCH_LITERAL_WORD:
3915 *lastLiteralCase = False;
3916 *lastRegexCase = True;
3917 XmToggleButtonSetState(regexToggle, False, False);
3918 XmToggleButtonSetState(caseToggle, False, False);
3919 if (wordToggle) {
3920 XmToggleButtonSetState(*wordToggle, True, False);
3921 XtSetSensitive(*wordToggle, True);
3923 - break;
3924 - case SEARCH_CASE_SENSE_WORD:
3925 + break;
3927 + case SEARCH_CASE_SENSE_WORD:
3928 *lastLiteralCase = True;
3929 *lastRegexCase = True;
3930 XmToggleButtonSetState(regexToggle, False, False);
3931 XmToggleButtonSetState(caseToggle, True, False);
3932 if (wordToggle) {
3933 XmToggleButtonSetState(*wordToggle, True, False);
3934 XtSetSensitive(*wordToggle, True);
3936 - break;
3937 - case SEARCH_REGEX:
3938 + break;
3940 + case SEARCH_REGEX:
3941 *lastLiteralCase = False;
3942 *lastRegexCase = True;
3943 XmToggleButtonSetState(regexToggle, True, False);
3944 XmToggleButtonSetState(caseToggle, True, False);
3945 if (wordToggle) {
3946 XmToggleButtonSetState(*wordToggle, False, False);
3947 XtSetSensitive(*wordToggle, False);
3949 - break;
3950 - case SEARCH_REGEX_NOCASE:
3951 - *lastLiteralCase = False;
3952 - *lastRegexCase = False;
3953 - XmToggleButtonSetState(regexToggle, True, False);
3954 - XmToggleButtonSetState(caseToggle, False, False);
3955 - if (wordToggle) {
3956 - XmToggleButtonSetState(*wordToggle, False, False);
3957 - XtSetSensitive(*wordToggle, False);
3959 - break;
3960 + break;
3962 + case SEARCH_REGEX_NOCASE:
3963 + case SEARCH_REGEX_SMARTCASE:
3964 + /* Smart case is no case for default setting */
3965 + *lastLiteralCase = False;
3966 + *lastRegexCase = False;
3967 + XmToggleButtonSetState(regexToggle, True, False);
3968 + XmToggleButtonSetState(caseToggle, False, False);
3969 + if (wordToggle) {
3970 + XmToggleButtonSetState(*wordToggle, False, False);
3971 + XtSetSensitive(*wordToggle, False);
3973 + break;
3977 #ifdef REPLACE_SCOPE
3979 @@ -2404,14 +2413,23 @@ static int textFieldNonEmpty(Widget w)
3980 int nonEmpty = (str[0] != '\0');
3981 XtFree(str);
3982 return(nonEmpty);
3985 -static void rFindTextValueChangedCB(Widget w, WindowInfo *window, XKeyEvent *event)
3986 +static void rFindTextValueChangedCB(Widget textWidget, WindowInfo* window,
3987 + XKeyEvent* event)
3989 - window = WidgetToWindow(w);
3990 + char* searchString = XmTextGetString(textWidget);
3992 + window = WidgetToWindow(textWidget);
3993 UpdateReplaceActionButtons(window);
3995 + /* Switch to case-sensitive as soon as the user enters an upper-case
3996 + letter. We have check the whole string each time to catch clipboard
3997 + or selection inserts. */
3998 + smartCaseToggle(searchString, window->replaceCaseToggle);
3999 + XtFree(searchString);
4002 static void rFindArrowKeyCB(Widget w, WindowInfo *window, XKeyEvent *event)
4004 KeySym keysym = XLookupKeysym(event, 0);
4005 @@ -2499,14 +2517,23 @@ static void fUpdateActionButtons(WindowI
4007 int buttonState = textFieldNonEmpty(window->findText);
4008 XtSetSensitive(window->findBtn, buttonState);
4011 -static void findTextValueChangedCB(Widget w, WindowInfo *window, XKeyEvent *event)
4012 +static void findTextValueChangedCB(Widget textWidget, WindowInfo* window,
4013 + XKeyEvent* event)
4015 - window = WidgetToWindow(w);
4016 + char* searchString = XmTextGetString(textWidget);
4018 + window = WidgetToWindow(textWidget);
4019 fUpdateActionButtons(window);
4021 + /* Switch to case-sensitive as soon as the user enters an upper-case
4022 + letter. We have check the whole string each time to catch clipboard
4023 + or selection inserts. */
4024 + smartCaseToggle(searchString, window->findCaseToggle);
4025 + XtFree(searchString);
4028 static void findArrowKeyCB(Widget w, WindowInfo *window, XKeyEvent *event)
4030 KeySym keysym = XLookupKeysym(event, 0);
4031 @@ -2527,11 +2554,10 @@ static void findArrowKeyCB(Widget w, Win
4032 /* if the index is out of range, beep and return */
4033 if (index != 0 && historyIndex(index) == -1) {
4034 XBell(TheDisplay, 0);
4035 return;
4039 /* determine the strings and button settings to use */
4040 if (index == 0) {
4041 searchStr = "";
4042 searchType = GetPrefSearch();
4043 @@ -2874,36 +2900,45 @@ static void selectedSearchCB(Widget w, X
4044 XtFree(value);
4046 /* Use the passed method for searching, unless it is regex, since this
4047 kind of search is by definition a literal search */
4048 searchType = callDataItems->searchType;
4049 - if (searchType == SEARCH_REGEX )
4050 - searchType = SEARCH_CASE_SENSE;
4051 - else if (searchType == SEARCH_REGEX_NOCASE)
4052 - searchType = SEARCH_LITERAL;
4053 + if (searchType == SEARCH_REGEX || searchType == SEARCH_REGEX_SMARTCASE) {
4054 + /* Here smart case must be sensitive, because the user
4055 + cannot modify the string to search for. */
4056 + searchType = SEARCH_CASE_SENSE;
4057 + } else if (searchType == SEARCH_REGEX_NOCASE) {
4058 + searchType = SEARCH_LITERAL;
4061 /* search for it in the window */
4062 SearchAndSelect(window, callDataItems->direction, searchString,
4063 searchType, callDataItems->searchWrap);
4064 XtFree(callData);
4068 ** Pop up and clear the incremental search line and prepare to search.
4070 -void BeginISearch(WindowInfo *window, int direction)
4071 +void BeginISearch(WindowInfo* window, int direction)
4073 window->iSearchStartPos = -1;
4074 XmTextSetString(window->iSearchText, "");
4075 XmToggleButtonSetState(window->iSearchRevToggle,
4076 - direction == SEARCH_BACKWARD, FALSE);
4077 + direction == SEARCH_BACKWARD, FALSE);
4079 /* Note: in contrast to the replace and find dialogs, the regex and
4080 case toggles are not reset to their default state when the incremental
4081 search bar is redisplayed. I'm not sure whether this is the best
4082 choice. If not, an initToggleButtons() call should be inserted
4083 here. But in that case, it might be appropriate to have different
4084 default search modes for i-search and replace/find. */
4086 + /* The 'Case' toggle button must be deactivated for smart cases. */
4087 + if (GetPrefSearch() == SEARCH_REGEX_SMARTCASE) {
4088 + XmToggleButtonSetState(window->iSearchCaseToggle, False, False);
4090 TempShowISearch(window, TRUE);
4091 XmProcessTraversal(window->iSearchText, XmTRAVERSE_CURRENT);
4095 @@ -3181,32 +3216,40 @@ static void iSearchTextActivateCB(Widget
4098 ** Called when user types in the incremental search line. Redoes the
4099 ** search for the new search string.
4101 -static void iSearchTextValueChangedCB(Widget w, WindowInfo *window,
4102 - XmAnyCallbackStruct *callData)
4103 +static void iSearchTextValueChangedCB(Widget widget, WindowInfo *window,
4104 + XmAnyCallbackStruct *callData)
4106 char *params[5];
4107 char *searchString;
4108 int searchType, direction, nParams;
4110 - window = WidgetToWindow(w);
4113 + window = WidgetToWindow(widget);
4115 /* Fetch the string, search type and direction from the incremental
4116 search bar widgets at the top of the window */
4117 searchString = XmTextGetString(window->iSearchText);
4119 + /* Switch to case-sensitive as soon as the user enters an upper-case
4120 + letter. We have check the whole string each time to catch clipboard
4121 + or selection inserts. */
4122 + smartCaseToggle(searchString, window->iSearchCaseToggle);
4124 if(XmToggleButtonGetState(window->iSearchCaseToggle)) {
4125 - if(XmToggleButtonGetState(window->iSearchRegexToggle))
4126 - searchType = SEARCH_REGEX;
4127 - else
4128 - searchType = SEARCH_CASE_SENSE;
4129 + if(XmToggleButtonGetState(window->iSearchRegexToggle)) {
4130 + searchType = SEARCH_REGEX;
4131 + } else {
4132 + searchType = SEARCH_CASE_SENSE;
4134 } else {
4135 - if(XmToggleButtonGetState(window->iSearchRegexToggle))
4136 - searchType = SEARCH_REGEX_NOCASE;
4137 - else
4138 - searchType = SEARCH_LITERAL;
4139 + if(XmToggleButtonGetState(window->iSearchRegexToggle)) {
4140 + searchType = SEARCH_REGEX_NOCASE;
4141 + } else {
4142 + searchType = SEARCH_LITERAL;
4145 direction = XmToggleButtonGetState(window->iSearchRevToggle) ?
4146 SEARCH_BACKWARD : SEARCH_FORWARD;
4148 /* If the search type is a regular expression, test compile it. If it
4149 @@ -4872,11 +4915,13 @@ static char *directionArg(int direction)
4151 ** Checks whether a search mode in one of the regular expression modes.
4153 static int isRegexType(int searchType)
4155 - return searchType == SEARCH_REGEX || searchType == SEARCH_REGEX_NOCASE;
4156 + return searchType == SEARCH_REGEX
4157 + || searchType == SEARCH_REGEX_NOCASE
4158 + || searchType == SEARCH_REGEX_SMARTCASE;
4162 ** Returns the default flags for regular expression matching, given a
4163 ** regular expression search mode.
4164 @@ -5003,17 +5048,35 @@ static void replaceCaseToggleCB(Widget w
4165 window->replaceLastRegexCase = searchCaseSense;
4166 else
4167 window->replaceLastLiteralCase = searchCaseSense;
4170 -static void iSearchCaseToggleCB(Widget w, XtPointer clientData, XtPointer callData)
4171 +static void iSearchCaseToggleCB(Widget toggleButton, XtPointer clientData,
4172 + XtPointer callData)
4174 - WindowInfo * window = WidgetToWindow(w);
4175 - int searchCaseSense = XmToggleButtonGetState(w);
4176 + WindowInfo * window = WidgetToWindow(toggleButton);
4177 + int searchCaseSense = XmToggleButtonGetState(toggleButton);
4179 /* Save the state of the Case Sensitive button
4180 depending on the state of the Regex button*/
4181 if(XmToggleButtonGetState(window->iSearchRegexToggle))
4182 window->iSearchLastRegexCase = searchCaseSense;
4183 else
4184 window->iSearchLastLiteralCase = searchCaseSense;
4188 +** Will search a string for uppercase characters. If there is one,
4189 +** The toggleButton will be set to True.
4191 +static void smartCaseToggle(const char* searchString, Widget toggleButton)
4193 + if (GetPrefSearch() == SEARCH_REGEX_SMARTCASE) {
4194 + int i;
4195 + for (i = 0; i < strlen(searchString); i++) {
4196 + if (isupper(*(searchString + i))) {
4197 + XmToggleButtonSetState(toggleButton, True, False);
4198 + break;
4203 diff --quilt old/source/search.h new/source/search.h
4204 --- old/source/search.h
4205 +++ new/source/search.h
4206 @@ -85,14 +85,16 @@ Boolean WindowCanBeClosed(WindowInfo *wi
4207 ** The order of the integers in this enumeration must be exactly
4208 ** the same as the order of the coressponding strings of the
4209 ** array SearchMethodStrings defined in preferences.c (!!)
4212 -enum SearchType {
4213 - SEARCH_LITERAL, SEARCH_CASE_SENSE, SEARCH_REGEX,
4214 - SEARCH_LITERAL_WORD, SEARCH_CASE_SENSE_WORD, SEARCH_REGEX_NOCASE,
4215 - N_SEARCH_TYPES /* must be last in enum SearchType */ };
4216 +enum SearchType
4218 + SEARCH_LITERAL, SEARCH_CASE_SENSE, SEARCH_REGEX, SEARCH_LITERAL_WORD,
4219 + SEARCH_CASE_SENSE_WORD, SEARCH_REGEX_NOCASE, SEARCH_REGEX_SMARTCASE,
4220 + N_SEARCH_TYPES /* must be last in enum SearchType */
4223 #ifdef REPLACE_SCOPE
4224 /* Scope on which the replace operations apply */
4225 enum ReplaceScope { REPL_SCOPE_WIN, REPL_SCOPE_SEL, REPL_SCOPE_MULTI };
4227 diff --quilt old/source/selection.c new/source/selection.c
4228 --- old/source/selection.c
4229 +++ new/source/selection.c
4230 @@ -27,21 +27,23 @@ static const char CVSID[] = "$Id: select
4232 #ifdef HAVE_CONFIG_H
4233 #include "../config.h"
4234 #endif
4236 -#include "selection.h"
4237 -#include "textBuf.h"
4238 -#include "text.h"
4239 -#include "nedit.h"
4240 #include "file.h"
4241 -#include "window.h"
4242 +#include "interpret.h"
4243 +#include "macro.h"
4244 #include "menu.h"
4245 +#include "nedit.h"
4246 #include "preferences.h"
4247 +#include "selection.h"
4248 #include "server.h"
4249 +#include "textBuf.h"
4250 +#include "text.h"
4251 #include "../util/DialogF.h"
4252 #include "../util/fileUtils.h"
4253 +#include "window.h"
4255 #include <stdlib.h>
4256 #include <stdio.h>
4257 #include <ctype.h>
4258 #include <string.h>
4259 @@ -349,23 +351,34 @@ static void fileCB(Widget widget, Window
4260 XtFree(nameList[i]);
4262 XtFree((char *)nameList);
4264 #else
4265 - { glob_t globbuf;
4266 - int i;
4268 - glob(nameText, GLOB_NOCHECK, NULL, &globbuf);
4269 - for (i=0; i<(int)globbuf.gl_pathc; i++) {
4270 - if (ParseFilename(globbuf.gl_pathv[i], filename, pathname) != 0)
4271 - XBell(TheDisplay, 0);
4272 - else
4273 - EditExistingFile(GetPrefOpenInTab()? window : NULL,
4274 - filename, pathname, 0, NULL, False, NULL,
4275 - GetPrefOpenInTab(), False);
4277 - globfree(&globbuf);
4279 + glob_t globbuf;
4280 + int i;
4282 + glob(nameText, GLOB_NOCHECK, NULL, &globbuf);
4283 + for (i = 0; i < (int) globbuf.gl_pathc; i++) {
4284 + DataValue* fileNameArg = (DataValue*) XtMalloc(sizeof(DataValue));
4285 + DataValue* resultDV = (DataValue*) XtMalloc(sizeof(DataValue));
4287 + fileNameArg->tag = STRING_TAG;
4288 + AllocNStringNCpy(&fileNameArg->val.str, globbuf.gl_pathv[i], MAXPATHLEN);
4289 + MacroApplyHook(window, "file_name_hook", 1, fileNameArg, resultDV);
4290 + XtFree((char*) fileNameArg);
4292 + if (ParseFilename(resultDV->val.str.rep, filename, pathname) != 0) {
4293 + XBell(TheDisplay, 0);
4294 + } else {
4295 + EditExistingFile(GetPrefOpenInTab() ? window : NULL, filename,
4296 + pathname, 0, NULL, False, NULL, GetPrefOpenInTab(),
4297 + False);
4299 + XtFree((char*) resultDV);
4301 + globfree(&globbuf);
4303 #endif
4304 CheckCloseDim();
4307 diff --quilt old/source/server.c new/source/server.c
4308 --- old/source/server.c
4309 +++ new/source/server.c
4310 @@ -242,12 +242,10 @@ static void deleteFileOpenProperty2(cons
4312 Atom atom = findFileOpenProperty(filename, pathname);
4313 deleteProperty(&atom);
4318 /* Try to find existing 'FileClosed' property atom for path. */
4319 static Atom findFileClosedProperty(const char* filename,
4320 const char* pathname)
4322 char path[MAXPATHLEN];
4323 @@ -354,11 +352,11 @@ static void processServerCommandString(c
4324 if (!window->filenameSet && !window->fileChanged &&
4325 isLocatedOnDesktop(window, currentDesktop))
4326 break;
4327 if (window == NULL) {
4328 EditNewFile(findWindowOnDesktop(tabbed, currentDesktop), NULL,
4329 - False, NULL, NULL);
4330 + False, NULL, NULL, False);
4331 CheckCloseDim();
4333 else {
4334 RaiseDocument(window);
4335 XMapRaised(TheDisplay, XtWindow(window->shell));
4336 @@ -417,12 +415,13 @@ static void processServerCommandString(c
4337 isLocatedOnDesktop(window, currentDesktop))
4338 break;
4340 if (*doCommand == '\0') {
4341 if (window == NULL) {
4342 - EditNewFile(findWindowOnDesktop(tabbed, currentDesktop),
4343 - NULL, iconicFlag, lmLen==0?NULL:langMode, NULL);
4344 + EditNewFile(findWindowOnDesktop(tabbed, currentDesktop),
4345 + NULL, iconicFlag, lmLen==0?NULL:langMode, NULL,
4346 + False);
4347 } else {
4348 if (iconicFlag)
4349 RaiseDocument(window);
4350 else
4351 RaiseDocumentWindow(window);
4352 diff --quilt old/source/shell.c new/source/shell.c
4353 --- old/source/shell.c
4354 +++ new/source/shell.c
4355 @@ -387,11 +387,12 @@ void DoShellMenuCmd(WindowInfo *window,
4356 if (output == TO_DIALOG) {
4357 outWidget = NULL;
4358 flags |= OUTPUT_TO_DIALOG;
4359 left = right = 0;
4360 } else if (output == TO_NEW_WINDOW) {
4361 - EditNewFile(GetPrefOpenInTab()?inWindow:NULL, NULL, False, NULL, window->path);
4362 + EditNewFile(GetPrefOpenInTab()?inWindow:NULL, NULL, False, NULL,
4363 + window->path, False);
4364 outWidget = WindowList->textArea;
4365 inWindow = WindowList;
4366 left = right = 0;
4367 CheckCloseDim();
4368 } else { /* TO_SAME_WINDOW */
4369 @@ -478,11 +479,11 @@ void AbortShellCommand(WindowInfo *windo
4371 static void issueCommand(WindowInfo *window, const char *command, char *input,
4372 int inputLen, int flags, Widget textW, int replaceLeft,
4373 int replaceRight, int fromMacro)
4375 - int stdinFD, stdoutFD, stderrFD = 0;
4376 + int stdinFD = 0, stdoutFD = 0, stderrFD = 0;
4377 XtAppContext context = XtWidgetToApplicationContext(window->shell);
4378 shellCmdInfo *cmdData;
4379 pid_t childPid;
4381 /* verify consistency of input parameters */
4382 diff --quilt old/source/text.c new/source/text.c
4383 --- old/source/text.c
4384 +++ new/source/text.c
4385 @@ -629,10 +629,17 @@ static XtResource resources[] = {
4386 XtOffset(TextWidget, text.highlightFGPixel), XmRString,
4387 NEDIT_DEFAULT_HI_FG},
4388 {textNhighlightBackground, textCHighlightBackground, XmRPixel,sizeof(Pixel),
4389 XtOffset(TextWidget, text.highlightBGPixel), XmRString,
4390 NEDIT_DEFAULT_HI_BG},
4391 + {textNcursorlineBackground, textCCursorlineBackground, XmRPixel,sizeof(Pixel),
4392 + XtOffset(TextWidget, text.cursorlineBGPixel), XmRString,
4393 + NEDIT_DEFAULT_CURSORLINE_BG},
4394 + {textNshowCursorline, textCshowCursorline, XmRBoolean, sizeof(Boolean),
4395 + XtOffset(TextWidget, text.showCursorline), XmRString, "False"},
4396 + {textNshowScrolltip, textCshowScrolltip, XmRBoolean, sizeof(Boolean),
4397 + XtOffset(TextWidget, text.showScrolltip), XmRString, "False"},
4398 {textNlineNumForeground, textCLineNumForeground, XmRPixel,sizeof(Pixel),
4399 XtOffset(TextWidget, text.lineNumFGPixel), XmRString,
4400 NEDIT_DEFAULT_LINENO_FG},
4401 {textNcursorForeground, textCCursorForeground, XmRPixel,sizeof(Pixel),
4402 XtOffset(TextWidget, text.cursorFGPixel), XmRString,
4403 @@ -641,10 +648,13 @@ static XtResource resources[] = {
4404 XtOffset(TextWidget, text.calltipFGPixel), XmRString,
4405 NEDIT_DEFAULT_CALLTIP_FG},
4406 {textNcalltipBackground, textCcalltipBackground, XmRPixel,sizeof(Pixel),
4407 XtOffset(TextWidget, text.calltipBGPixel), XmRString,
4408 NEDIT_DEFAULT_CALLTIP_BG},
4409 + {textNwrapMarginForeground, textCWrapMarginForeground, XmRPixel,sizeof(Pixel),
4410 + XtOffset(TextWidget, text.wrapMarginFGPixel), XmRString,
4411 + NEDIT_DEFAULT_WRAPMARGIN_FG},
4412 {textNbacklightCharTypes,textCBacklightCharTypes,XmRString,sizeof(XmString),
4413 XtOffset(TextWidget, text.backlightCharTypes), XmRString, NULL},
4414 {textNrows, textCRows, XmRInt,sizeof(int),
4415 XtOffset(TextWidget, text.rows), XmRString, "24"},
4416 {textNcolumns, textCColumns, XmRInt, sizeof(int),
4417 @@ -671,10 +681,12 @@ static XtResource resources[] = {
4418 XtOffset(TextWidget, text.readOnly), XmRString, "False"},
4419 {textNhidePointer, textCHidePointer, XmRBoolean, sizeof(Boolean),
4420 XtOffset(TextWidget, text.hidePointer), XmRString, "False"},
4421 {textNwrapMargin, textCWrapMargin, XmRInt, sizeof(int),
4422 XtOffset(TextWidget, text.wrapMargin), XmRString, "0"},
4423 + {textNshowWrapMargin, textCShowWrapMargin, XmRBoolean, sizeof(Boolean),
4424 + XtOffset(TextWidget, text.showWrapMargin), XmRString, "True"},
4425 {textNhScrollBar, textCHScrollBar, XmRWidget, sizeof(Widget),
4426 XtOffset(TextWidget, text.hScrollBar), XmRString, ""},
4427 {textNvScrollBar, textCVScrollBar, XmRWidget, sizeof(Widget),
4428 XtOffset(TextWidget, text.vScrollBar), XmRString, ""},
4429 {textNlineNumCols, textCLineNumCols, XmRInt, sizeof(int),
4430 @@ -810,24 +822,34 @@ static void initialize(TextWidget reques
4431 buf = BufCreate();
4433 /* Create and initialize the text-display part of the widget */
4434 textLeft = new->text.marginWidth +
4435 (lineNumCols == 0 ? 0 : marginWidth + charWidth * lineNumCols);
4436 - new->text.textD = TextDCreate((Widget)new, new->text.hScrollBar,
4437 - new->text.vScrollBar, textLeft, new->text.marginHeight,
4438 - new->core.width - marginWidth - textLeft,
4439 - new->core.height - new->text.marginHeight * 2,
4440 - lineNumCols == 0 ? 0 : marginWidth,
4441 - lineNumCols == 0 ? 0 : lineNumCols * charWidth,
4442 - buf, new->text.fontStruct, new->core.background_pixel,
4443 - new->primitive.foreground, new->text.selectFGPixel,
4444 - new->text.selectBGPixel, new->text.highlightFGPixel,
4445 - new->text.highlightBGPixel, new->text.cursorFGPixel,
4446 - new->text.lineNumFGPixel,
4447 - new->text.continuousWrap, new->text.wrapMargin,
4448 - new->text.backlightCharTypes, new->text.calltipFGPixel,
4449 - new->text.calltipBGPixel);
4450 + new->text.textD = TextDCreate(
4451 + /* Widgets */
4452 + (Widget)new, new->text.hScrollBar, new->text.vScrollBar,
4453 + /* Positions */
4454 + textLeft, new->text.marginHeight,
4455 + new->core.width - marginWidth - textLeft,
4456 + new->core.height - new->text.marginHeight * 2,
4457 + lineNumCols == 0 ? 0 : marginWidth,
4458 + lineNumCols == 0 ? 0 : lineNumCols * charWidth,
4459 + /* buffer */
4460 + buf,
4461 + /* font */
4462 + new->text.fontStruct,
4463 + /* Pixels */
4464 + new->core.background_pixel, new->primitive.foreground,
4465 + new->text.selectFGPixel, new->text.selectBGPixel,
4466 + new->text.highlightFGPixel, new->text.highlightBGPixel,
4467 + new->text.cursorFGPixel, new->text.lineNumFGPixel,
4468 + new->text.wrapMarginFGPixel, new->text.calltipFGPixel,
4469 + new->text.calltipBGPixel, new->text.cursorlineBGPixel,
4470 + /* misc */
4471 + new->text.continuousWrap, new->text.wrapMargin,
4472 + new->text.showWrapMargin, new->text.backlightCharTypes,
4473 + new->text.showCursorline, new->text.showScrolltip);
4475 /* Add mandatory delimiters blank, tab, and newline to the list of
4476 delimiters. The memory use scheme here is that new values are
4477 always copied, and can therefore be safely freed on subsequent
4478 set-values calls or destroy */
4479 @@ -1121,10 +1143,25 @@ static Boolean setValues(TextWidget curr
4480 if (new->text.wrapMargin != current->text.wrapMargin ||
4481 new->text.continuousWrap != current->text.continuousWrap)
4482 TextDSetWrapMode(current->text.textD, new->text.continuousWrap,
4483 new->text.wrapMargin);
4485 + if (new->text.showWrapMargin != current->text.showWrapMargin)
4486 + TextDSetShowWrapMargin(current->text.textD, new->text.showWrapMargin);
4488 + if (new->text.showCursorline != current->text.showCursorline) {
4489 + current->text.showCursorline = new->text.showCursorline;
4490 + if (current->text.textD)
4492 + current->text.textD->showCursorline = new->text.showCursorline;
4495 + /* jegub
4496 + redraw = True; */
4497 + TextDSetShowCursorline(current->text.textD, new->text.showCursorline);
4500 /* When delimiters are changed, copy the memory, so that the caller
4501 doesn't have to manage it, and add mandatory delimiters blank,
4502 tab, and newline to the list */
4503 if (new->text.delimiters != current->text.delimiters) {
4504 char *delimiters = XtMalloc(strlen(new->text.delimiters) + 4);
4505 @@ -3750,12 +3787,15 @@ static void selectWord(Widget w, int poi
4506 TextWidget tw = (TextWidget)w;
4507 textBuffer *buf = tw->text.textD->buffer;
4508 int x, y, insertPos = TextDGetInsertPosition(tw->text.textD);
4510 TextPosToXY(w, insertPos, &x, &y);
4511 - if (pointerX < x && insertPos > 0 && BufGetCharacter(buf, insertPos-1) != '\n')
4512 - insertPos--;
4513 + if (pointerX < x && insertPos > 0
4514 + && BufGetCharacter(buf, insertPos-1) != '\n')
4516 + insertPos--;
4518 BufSelect(buf, startOfWord(tw, insertPos), endOfWord(tw, insertPos));
4521 static int startOfWord(TextWidget w, int pos)
4523 diff --quilt old/source/text.h new/source/text.h
4524 --- old/source/text.h
4525 +++ new/source/text.h
4526 @@ -51,18 +51,30 @@
4527 #define textCSelectBackground "SelectBackground"
4528 #define textNhighlightForeground "highlightForeground"
4529 #define textCHighlightForeground "HighlightForeground"
4530 #define textNhighlightBackground "highlightBackground"
4531 #define textCHighlightBackground "HighlightBackground"
4533 +#define textNcursorlineBackground "cursorlineBackground"
4534 +#define textCCursorlineBackground "CursorlineBackground"
4536 +#define textNshowCursorline "showCursorline"
4537 +#define textCshowCursorline "ShowCursorline"
4539 +#define textNshowScrolltip "showScrolltip"
4540 +#define textCshowScrolltip "ShowScrolltip"
4542 #define textNcursorForeground "cursorForeground"
4543 #define textCCursorForeground "CursorForeground"
4544 #define textNlineNumForeground "lineNumForeground"
4545 #define textCLineNumForeground "LineNumForeground"
4546 #define textNcalltipForeground "calltipForeground"
4547 #define textCcalltipForeground "CalltipForeground"
4548 #define textNcalltipBackground "calltipBackground"
4549 #define textCcalltipBackground "CalltipBackground"
4550 +#define textNwrapMarginForeground "wrapMarginForeground"
4551 +#define textCWrapMarginForeground "WrapMarginForeground"
4552 #define textNpendingDelete "pendingDelete"
4553 #define textCPendingDelete "PendingDelete"
4554 #define textNhScrollBar "hScrollBar"
4555 #define textCHScrollBar "HScrollBar"
4556 #define textNvScrollBar "vScrollBar"
4557 @@ -93,10 +105,12 @@
4558 #define textCAutoWrap "AutoWrap"
4559 #define textNcontinuousWrap "continuousWrap"
4560 #define textCContinuousWrap "ContinuousWrap"
4561 #define textNwrapMargin "wrapMargin"
4562 #define textCWrapMargin "WrapMargin"
4563 +#define textNshowWrapMargin "showWrapMargin"
4564 +#define textCShowWrapMargin "ShowWrapMargin"
4565 #define textNautoIndent "autoIndent"
4566 #define textCAutoIndent "AutoIndent"
4567 #define textNsmartIndent "smartIndent"
4568 #define textCSmartIndent "SmartIndent"
4569 #define textNoverstrike "overstrike"
4570 diff --quilt old/source/textDisp.c new/source/textDisp.c
4571 --- old/source/textDisp.c
4572 +++ new/source/textDisp.c
4573 @@ -62,41 +62,44 @@ static const char CVSID[] = "$Id: textDi
4574 #include "../debug.h"
4575 #endif
4577 /* Masks for text drawing methods. These are or'd together to form an
4578 integer which describes what drawing calls to use to draw a string */
4579 +#define STYLE_LOOKUP_SHIFT 0
4580 #define FILL_SHIFT 8
4581 #define SECONDARY_SHIFT 9
4582 #define PRIMARY_SHIFT 10
4583 #define HIGHLIGHT_SHIFT 11
4584 -#define STYLE_LOOKUP_SHIFT 0
4585 #define BACKLIGHT_SHIFT 12
4586 +#define RANGESET_SHIFT 20
4587 +#define CURSORLINE_SHIFT 26
4589 #define FILL_MASK (1 << FILL_SHIFT)
4590 #define SECONDARY_MASK (1 << SECONDARY_SHIFT)
4591 #define PRIMARY_MASK (1 << PRIMARY_SHIFT)
4592 #define HIGHLIGHT_MASK (1 << HIGHLIGHT_SHIFT)
4593 #define STYLE_LOOKUP_MASK (0xff << STYLE_LOOKUP_SHIFT)
4594 #define BACKLIGHT_MASK (0xff << BACKLIGHT_SHIFT)
4596 -#define RANGESET_SHIFT (20)
4597 #define RANGESET_MASK (0x3F << RANGESET_SHIFT)
4598 +#define CURSORLINE_MASK (1 << CURSORLINE_SHIFT)
4600 /* If you use both 32-Bit Style mask layout:
4601 Bits +----------------+----------------+----------------+----------------+
4602 hex |1F1E1D1C1B1A1918|1716151413121110| F E D C B A 9 8| 7 6 5 4 3 2 1 0|
4603 dec |3130292827262524|2322212019181716|151413121110 9 8| 7 6 5 4 3 2 1 0|
4604 +----------------+----------------+----------------+----------------+
4605 - 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|
4606 + 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|
4607 +----------------+----------------+----------------+----------------+
4608 - where: s - style lookup value (8 bits)
4609 + where:
4610 + s - style lookup value (8 bits)
4611 F - fill (1 bit)
4612 2 - secondary selection (1 bit)
4613 1 - primary selection (1 bit)
4614 H - highlight (1 bit)
4615 b - backlighting index (8 bits)
4616 r - rangeset index (6 bits)
4617 + c - cursorline coloring (1 bit)
4618 This leaves 6 "unused" bits */
4620 /* Maximum displayable line length (how many characters will fit across the
4621 widest window). This amount of memory is temporarily allocated from the
4622 stack in the redisplayLine routine for drawing strings */
4623 @@ -113,10 +116,12 @@ static void offsetLineStarts(textDisp *t
4624 static void calcLineStarts(textDisp *textD, int startLine, int endLine);
4625 static void calcLastChar(textDisp *textD);
4626 static int posToVisibleLineNum(textDisp *textD, int pos, int *lineNum);
4627 static void redisplayLine(textDisp *textD, int visLineNum, int leftClip,
4628 int rightClip, int leftCharIndex, int rightCharIndex);
4629 +static void redisplayLineCur(textDisp *textD, int visLineNum, int leftClip,
4630 + int rightClip, int leftCharIndex, int rightCharIndex, Boolean curLine);
4631 static void drawString(textDisp *textD, int style, int x, int y, int toX,
4632 char *string, int nChars);
4633 static void clearRect(textDisp *textD, GC gc, int x, int y,
4634 int width, int height);
4635 static void drawCursor(textDisp *textD, int x, int y);
4636 @@ -147,11 +152,12 @@ static int countLines(const char *string
4637 static int measureVisLine(textDisp *textD, int visLineNum);
4638 static int emptyLinesVisible(textDisp *textD);
4639 static void blankCursorProtrusions(textDisp *textD);
4640 static void allocateFixedFontGCs(textDisp *textD, XFontStruct *fontStruct,
4641 Pixel bgPixel, Pixel fgPixel, Pixel selectFGPixel, Pixel selectBGPixel,
4642 - Pixel highlightFGPixel, Pixel highlightBGPixel, Pixel lineNumFGPixel);
4643 + Pixel highlightFGPixel, Pixel highlightBGPixel, Pixel lineNumFGPixel,
4644 + Pixel wrapMarginFGPixel, Pixel cursorlineBGPixel);
4645 static GC allocateGC(Widget w, unsigned long valueMask,
4646 unsigned long foreground, unsigned long background, Font font,
4647 unsigned long dynamicMask, unsigned long dontCareMask);
4648 static void releaseGC(Widget w, GC gc);
4649 static void resetClipRectangles(textDisp *textD);
4650 @@ -177,19 +183,24 @@ static void resetAbsLineNum(textDisp *te
4651 static int measurePropChar(const textDisp* textD, const char c,
4652 const int colNum, const int pos);
4653 static Pixel allocBGColor(Widget w, char *colorName, int *ok);
4654 static Pixel getRangesetColor(textDisp *textD, int ind, Pixel bground);
4655 static void textDRedisplayRange(textDisp *textD, int start, int end);
4656 +static void drawWrapMargin(textDisp* textD);
4657 +static void redisplayCursor(textDisp* textD);
4659 textDisp *TextDCreate(Widget widget, Widget hScrollBar, Widget vScrollBar,
4660 Position left, Position top, Position width, Position height,
4661 - Position lineNumLeft, Position lineNumWidth, textBuffer *buffer,
4662 - XFontStruct *fontStruct, Pixel bgPixel, Pixel fgPixel,
4663 - Pixel selectFGPixel, Pixel selectBGPixel, Pixel highlightFGPixel,
4664 - Pixel highlightBGPixel, Pixel cursorFGPixel, Pixel lineNumFGPixel,
4665 - int continuousWrap, int wrapMargin, XmString bgClassString,
4666 - Pixel calltipFGPixel, Pixel calltipBGPixel)
4667 + Position lineNumLeft, Position lineNumWidth,
4668 + textBuffer *buffer,
4669 + XFontStruct *fontStruct,
4670 + Pixel bgPixel, Pixel fgPixel, Pixel selectFGPixel, Pixel selectBGPixel,
4671 + Pixel highlightFGPixel, Pixel highlightBGPixel, Pixel cursorFGPixel,
4672 + Pixel lineNumFGPixel, Pixel wrapMarginFGPixel, Pixel calltipFGPixel,
4673 + Pixel calltipBGPixel, Pixel cursorlineBGPixel,
4674 + int continuousWrap, int wrapMargin, Boolean showWrapMargin,
4675 + XmString bgClassString, Boolean showCursorline, Boolean showScrolltip)
4677 textDisp *textD;
4678 XGCValues gcValues;
4679 int i;
4681 @@ -230,29 +241,34 @@ textDisp *TextDCreate(Widget widget, Wid
4682 textD->selectFGPixel = selectFGPixel;
4683 textD->highlightFGPixel = highlightFGPixel;
4684 textD->selectBGPixel = selectBGPixel;
4685 textD->highlightBGPixel = highlightBGPixel;
4686 textD->lineNumFGPixel = lineNumFGPixel;
4687 + textD->wrapMarginFGPixel = wrapMarginFGPixel;
4688 textD->cursorFGPixel = cursorFGPixel;
4689 textD->wrapMargin = wrapMargin;
4690 textD->continuousWrap = continuousWrap;
4691 + textD->showWrapMargin = showWrapMargin;
4692 + textD->cursorlineBGPixel = cursorlineBGPixel;
4693 allocateFixedFontGCs(textD, fontStruct, bgPixel, fgPixel, selectFGPixel,
4694 - selectBGPixel, highlightFGPixel, highlightBGPixel, lineNumFGPixel);
4695 + selectBGPixel, highlightFGPixel, highlightBGPixel, lineNumFGPixel,
4696 + wrapMarginFGPixel, cursorlineBGPixel);
4697 textD->styleGC = allocateGC(textD->w, 0, 0, 0, fontStruct->fid,
4698 GCClipMask|GCForeground|GCBackground, GCArcMode);
4699 textD->lineNumLeft = lineNumLeft;
4700 textD->lineNumWidth = lineNumWidth;
4701 textD->nVisibleLines = (height - 1) / (textD->ascent + textD->descent) + 1;
4702 gcValues.foreground = cursorFGPixel;
4703 textD->cursorFGGC = XtGetGC(widget, GCForeground, &gcValues);
4704 textD->lineStarts = (int *)XtMalloc(sizeof(int) * textD->nVisibleLines);
4705 textD->lineStarts[0] = 0;
4706 - textD->calltipW = NULL;
4707 - textD->calltipShell = NULL;
4708 + textD->calltip.widget = NULL;
4709 textD->calltip.ID = 0;
4710 textD->calltipFGPixel = calltipFGPixel;
4711 textD->calltipBGPixel = calltipBGPixel;
4712 + textD->showScrolltip = showScrolltip;
4713 + textD->scrolltip = NULL;
4714 for (i=1; i<textD->nVisibleLines; i++)
4715 textD->lineStarts[i] = -1;
4716 textD->bgClassPixel = NULL;
4717 textD->bgClass = NULL;
4718 TextDSetupBGClasses(widget, bgClassString, &textD->bgClassPixel,
4719 @@ -260,10 +276,13 @@ textDisp *TextDCreate(Widget widget, Wid
4720 textD->suppressResync = 0;
4721 textD->nLinesDeleted = 0;
4722 textD->modifyingTabDist = 0;
4723 textD->pointerHidden = False;
4724 textD->graphicsExposeQueue = NULL;
4725 + textD->showCursorline = showCursorline;
4726 + textD->oldCursorPos = 0;
4727 + textD->oldLineStart = 0;
4729 /* Attach an event handler to the widget so we can know the visibility
4730 (used for choosing the fastest drawing method) */
4731 XtAddEventHandler(widget, VisibilityChangeMask, False,
4732 visibilityEH, textD);
4733 @@ -316,13 +335,18 @@ void TextDFree(textDisp *textD)
4734 releaseGC(textD->w, textD->highlightGC);
4735 releaseGC(textD->w, textD->selectBGGC);
4736 releaseGC(textD->w, textD->highlightBGGC);
4737 releaseGC(textD->w, textD->styleGC);
4738 releaseGC(textD->w, textD->lineNumGC);
4739 + releaseGC(textD->w, textD->wrapMarginGC);
4740 + releaseGC(textD->w, textD->cursorlineGC);
4741 + releaseGC(textD->w, textD->cursorlineBGGC);
4743 XtFree((char *)textD->lineStarts);
4744 while (TextDPopGraphicExposeQueueEntry(textD)) {
4747 XtFree((char *)textD->bgClassPixel);
4748 XtFree((char *)textD->bgClass);
4749 XtFree((char *)textD);
4752 @@ -380,11 +404,12 @@ void TextDAttachHighlightData(textDisp *
4755 /* Change the (non syntax-highlit) colors */
4756 void TextDSetColors(textDisp *textD, Pixel textFgP, Pixel textBgP,
4757 Pixel selectFgP, Pixel selectBgP, Pixel hiliteFgP, Pixel hiliteBgP,
4758 - Pixel lineNoFgP, Pixel cursorFgP)
4759 + Pixel lineNoFgP, Pixel cursorFgP, Pixel wrapMarginFgP,
4760 + Pixel cursorlineBgP)
4762 XGCValues values;
4763 Display *d = XtDisplay(textD->w);
4765 /* Update the stored pixels */
4766 @@ -394,19 +419,24 @@ void TextDSetColors(textDisp *textD, Pix
4767 textD->selectBGPixel = selectBgP;
4768 textD->highlightFGPixel = hiliteFgP;
4769 textD->highlightBGPixel = hiliteBgP;
4770 textD->lineNumFGPixel = lineNoFgP;
4771 textD->cursorFGPixel = cursorFgP;
4772 + textD->wrapMarginFGPixel = wrapMarginFgP;
4773 + textD->cursorlineBGPixel = cursorlineBgP;
4775 releaseGC(textD->w, textD->gc);
4776 releaseGC(textD->w, textD->selectGC);
4777 releaseGC(textD->w, textD->selectBGGC);
4778 releaseGC(textD->w, textD->highlightGC);
4779 releaseGC(textD->w, textD->highlightBGGC);
4780 releaseGC(textD->w, textD->lineNumGC);
4781 + releaseGC(textD->w, textD->wrapMarginGC);
4782 + releaseGC(textD->w, textD->cursorlineBGGC);
4783 allocateFixedFontGCs(textD, textD->fontStruct, textBgP, textFgP, selectFgP,
4784 - selectBgP, hiliteFgP, hiliteBgP, lineNoFgP);
4785 + selectBgP, hiliteFgP, hiliteBgP, lineNoFgP, wrapMarginFgP,
4786 + cursorlineBgP);
4788 /* Change the cursor GC (the cursor GC is not shared). */
4789 values.foreground = cursorFgP;
4790 XChangeGC( d, textD->cursorFGGC, GCForeground, &values );
4792 @@ -414,20 +444,32 @@ void TextDSetColors(textDisp *textD, Pix
4793 TextDRedisplayRect(textD, textD->left, textD->top, textD->width,
4794 textD->height);
4795 redrawLineNumbers(textD, True);
4798 +void TextDSetShowCursorline(textDisp* textD, const Boolean showCursorline)
4800 + textD->showCursorline = showCursorline;
4802 + /* Redisplay */
4803 + TextDRedisplayRect(textD, textD->left, textD->top, textD->width,
4804 + textD->height);
4805 + redrawLineNumbers(textD, True);
4809 ** Change the (non highlight) font
4811 void TextDSetFont(textDisp *textD, XFontStruct *fontStruct)
4813 Display *display = XtDisplay(textD->w);
4814 int i, maxAscent = fontStruct->ascent, maxDescent = fontStruct->descent;
4815 int width, height, fontWidth;
4816 Pixel bgPixel, fgPixel, selectFGPixel, selectBGPixel;
4817 Pixel highlightFGPixel, highlightBGPixel, lineNumFGPixel;
4818 + Pixel wrapMarginFGPixel;
4819 + Pixel cursorlineBGPixel;
4820 XGCValues values;
4821 XFontStruct *styleFont;
4823 /* If font size changes, cursor will be redrawn in a new position */
4824 blankCursorProtrusions(textD);
4825 @@ -475,20 +517,30 @@ void TextDSetFont(textDisp *textD, XFont
4826 selectFGPixel = values.foreground;
4827 selectBGPixel = values.background;
4828 XGetGCValues(display, textD->highlightGC,GCForeground|GCBackground,&values);
4829 highlightFGPixel = values.foreground;
4830 highlightBGPixel = values.background;
4831 + XGetGCValues(display, textD->cursorlineGC,
4832 + GCForeground|GCBackground, &values);
4833 + cursorlineBGPixel = values.background;
4834 XGetGCValues(display, textD->lineNumGC, GCForeground, &values);
4835 lineNumFGPixel = values.foreground;
4836 + XGetGCValues(display, textD->wrapMarginGC, GCForeground, &values);
4837 + wrapMarginFGPixel = values.foreground;
4839 releaseGC(textD->w, textD->gc);
4840 releaseGC(textD->w, textD->selectGC);
4841 releaseGC(textD->w, textD->highlightGC);
4842 releaseGC(textD->w, textD->selectBGGC);
4843 releaseGC(textD->w, textD->highlightBGGC);
4844 releaseGC(textD->w, textD->lineNumGC);
4845 + releaseGC(textD->w, textD->wrapMarginGC);
4846 + releaseGC(textD->w, textD->cursorlineGC);
4847 + releaseGC(textD->w, textD->cursorlineBGGC);
4848 allocateFixedFontGCs(textD, fontStruct, bgPixel, fgPixel, selectFGPixel,
4849 - selectBGPixel, highlightFGPixel, highlightBGPixel, lineNumFGPixel);
4850 + selectBGPixel, highlightFGPixel, highlightBGPixel, lineNumFGPixel,
4851 + wrapMarginFGPixel, cursorlineBGPixel);
4852 XSetFont(display, textD->styleGC, fontStruct->fid);
4854 /* Do a full resize to force recalculation of font related parameters */
4855 width = textD->width;
4856 height = textD->height;
4857 @@ -642,10 +694,13 @@ void TextDRedisplayRect(textDisp *textD,
4858 redisplayLine(textD, line, left, left+width, 0, INT_MAX);
4860 /* draw the line numbers if exposed area includes them */
4861 if (textD->lineNumWidth != 0 && left <= textD->lineNumLeft + textD->lineNumWidth)
4862 redrawLineNumbers(textD, False);
4864 + /* draw wrap margin incase it got erased */
4865 + drawWrapMargin(textD);
4869 ** Refresh all of the text between buffer positions "start" and "end"
4870 ** not including the character at the position "end".
4871 @@ -654,11 +709,11 @@ void TextDRedisplayRect(textDisp *textD,
4872 ** any range of characters.
4874 static void textDRedisplayRange(textDisp *textD, int start, int end)
4876 int i, startLine, lastLine, startIndex, endIndex;
4879 /* If the range is outside of the displayed text, just return */
4880 if (end < textD->firstChar || (start > textD->lastChar &&
4881 !emptyLinesVisible(textD)))
4882 return;
4884 @@ -711,23 +766,103 @@ static void textDRedisplayRange(textDisp
4885 resetClipRectangles(textD);
4887 /* If the starting and ending lines are the same, redisplay the single
4888 line between "start" and "end" */
4889 if (startLine == lastLine) {
4890 + /* Add one to endIndex to catch the caret at the end of a range. */
4891 redisplayLine(textD, startLine, 0, INT_MAX, startIndex, endIndex);
4892 - return;
4894 + if (-1 != textD->lineStarts[startLine] ||
4895 + (BufCountDispChars(textD->buffer, textD->lineStarts[startLine],
4896 + start) <= textD->wrapMargin &&
4897 + BufCountDispChars(textD->buffer, textD->lineStarts[startLine],
4898 + end) >= textD->wrapMargin))
4900 + /* redraw wrap margin if it got erased */
4901 + drawWrapMargin(textD);
4903 + } else {
4904 + /* Redisplay the first line from "start" */
4905 + redisplayLine(textD, startLine, 0, INT_MAX, startIndex, INT_MAX);
4907 + /* Redisplay the lines in between at their full width */
4908 + for (i = startLine+1; i < lastLine; i++) {
4909 + redisplayLine(textD, i, 0, INT_MAX, 0, INT_MAX);
4912 + /* Redisplay the last line to "end". Add one to the endIndex to catch
4913 + the caret at the end of a range. */
4914 + redisplayLine(textD, lastLine, 0, INT_MAX, 0, endIndex);
4916 + /* redraw wrap margin */
4917 + drawWrapMargin(textD);
4920 - /* Redisplay the first line from "start" */
4921 - redisplayLine(textD, startLine, 0, INT_MAX, startIndex, INT_MAX);
4923 - /* Redisplay the lines in between at their full width */
4924 - for (i=startLine+1; i<lastLine; i++)
4925 - redisplayLine(textD, i, 0, INT_MAX, 0, INT_MAX);
4928 - /* Redisplay the last line to "end" */
4929 - redisplayLine(textD, lastLine, 0, INT_MAX, 0, endIndex);
4931 +** Custom version of TextDRedisplayRange that only updates the area around
4932 +** the cursor.
4934 +static void redisplayCursor(textDisp* textD)
4936 + int cursorLine, lineStart, start, end, startIndex, endIndex;
4937 + int pos = textD->cursorPos;
4938 + Boolean cursorLineChanged;
4940 + /* If the cursor is outside of the displayed text, just return */
4941 + if (pos + 1 < textD->firstChar || pos - 1 > textD->lastChar) {
4942 + return;
4945 + if (!posToVisibleLineNum(textD, pos, &cursorLine)) {
4946 + /* At first sight, this can only be reached when redisplayCursor()
4947 + is miscalled or when the catch above didn't work. There is at
4948 + least one situation though which makes the catch helpless: If
4949 + your caret is in the last line, column 1 and you move it down,
4950 + textD->cursorPos will be changed *before* this function is
4951 + called, the automatic scroll will be done after. */
4952 + return;
4955 + /* Find the position right before and after the cursor,
4956 + but make sure that we stay on the same line. */
4957 + lineStart = TextDStartOfLine(textD, pos);
4958 + start = max(lineStart, pos - 1);
4959 + end = min(pos + 1, TextDEndOfLine(textD, lineStart, True) + 1);
4961 + /* Get the starting and ending positions within the line. */
4962 + startIndex = start - lineStart;
4963 + endIndex = end - lineStart;
4965 + /* Reset the clipping rectangles for the drawing GCs which are shared
4966 + using XtAllocateGC, and may have changed since the last use */
4967 + resetClipRectangles(textD);
4969 + /* jegub */
4970 + cursorLineChanged = (textD->oldCursorPos != textD->cursorPos
4971 + || textD->oldLineStart != lineStart);
4973 + redisplayLine(textD, cursorLine, 0, INT_MAX, startIndex, endIndex);
4975 + /* jegub */
4976 + if (cursorLineChanged) {
4977 + /* Hairline destroyed in old cursor line! Redraw neccessary. */
4978 + drawWrapMargin(textD);
4979 + return;
4982 + if (BufCountDispChars(textD->buffer, lineStart, end) < textD->wrapMargin) {
4983 + /* hairline is off-screen, most common case */
4984 + return;
4987 + if (BufCountDispChars(textD->buffer, lineStart, start)
4988 + > textD->wrapMargin) {
4989 + return;
4992 + drawWrapMargin(textD);
4996 ** Set the scroll position of the text display vertically by line number and
4997 ** horizontally by pixel offset from the left margin
4998 @@ -769,12 +904,14 @@ void TextDGetScroll(textDisp *textD, int
4999 ** Set the position of the text insertion cursor for text display "textD"
5001 void TextDSetInsertPosition(textDisp *textD, int newPos)
5003 /* make sure new position is ok, do nothing if it hasn't changed */
5004 - if (newPos == textD->cursorPos)
5005 - return;
5006 + if (newPos == textD->cursorPos) {
5007 + return;
5010 if (newPos < 0) newPos = 0;
5011 if (newPos > textD->buffer->length) newPos = textD->buffer->length;
5013 /* cursor movement cancels vertical cursor motion column */
5014 textD->cursorPreferredCol = -1;
5015 @@ -783,37 +920,45 @@ void TextDSetInsertPosition(textDisp *te
5016 TextDBlankCursor(textD);
5018 /* draw it at its new position */
5019 textD->cursorPos = newPos;
5020 textD->cursorOn = True;
5021 - textDRedisplayRange(textD, textD->cursorPos-1, textD->cursorPos + 1);
5023 + redisplayCursor(textD);
5025 + /* We have to force redraw of the hairline here: The hairline will be
5026 + erased if the cursorline changes, but will not be redrawn by
5027 + redisplayCursor() (only works on the area immedietely surrounding
5028 + the cursor). */
5029 + drawWrapMargin(textD);
5032 void TextDBlankCursor(textDisp *textD)
5034 if (!textD->cursorOn)
5035 return;
5037 blankCursorProtrusions(textD);
5038 textD->cursorOn = False;
5039 - textDRedisplayRange(textD, textD->cursorPos-1, textD->cursorPos+1);
5040 + redisplayCursor(textD);
5043 void TextDUnblankCursor(textDisp *textD)
5045 if (!textD->cursorOn) {
5046 textD->cursorOn = True;
5047 - textDRedisplayRange(textD, textD->cursorPos-1, textD->cursorPos+1);
5048 + redisplayCursor(textD);
5052 void TextDSetCursorStyle(textDisp *textD, int style)
5054 textD->cursorStyle = style;
5055 blankCursorProtrusions(textD);
5056 - if (textD->cursorOn) {
5057 - textDRedisplayRange(textD, textD->cursorPos-1, textD->cursorPos + 1);
5058 + if (textD->cursorOn)
5060 + redisplayCursor(textD);
5064 void TextDSetWrapMode(textDisp *textD, int wrap, int wrapMargin)
5066 @@ -845,10 +990,19 @@ void TextDSetWrapMode(textDisp *textD, i
5067 /* Do a full redraw */
5068 TextDRedisplayRect(textD, 0, textD->top, textD->width + textD->left,
5069 textD->height);
5072 +void TextDSetShowWrapMargin(textDisp* textD, int state)
5074 + textD->showWrapMargin = state;
5076 + /* Do a full redraw */
5077 + TextDRedisplayRect(textD, 0, textD->top, textD->width + textD->left,
5078 + textD->height);
5081 int TextDGetInsertPosition(textDisp *textD)
5083 return textD->cursorPos;
5086 @@ -1341,15 +1495,15 @@ int TextDMoveDown(textDisp *textD, int a
5089 column = textD->cursorPreferredCol >= 0
5090 ? textD->cursorPreferredCol
5091 : BufCountDispChars(textD->buffer, lineStartPos, textD->cursorPos);
5093 - if (absolute)
5094 + if (absolute) {
5095 nextLineStartPos = BufCountForwardNLines(textD->buffer, lineStartPos, 1);
5096 - else
5097 + } else {
5098 nextLineStartPos = TextDCountForwardNLines(textD, lineStartPos, 1, True);
5101 newPos = BufCountForwardDispChars(textD->buffer, nextLineStartPos, column);
5103 if (textD->continuousWrap && !absolute) {
5104 newPos = min(newPos, TextDEndOfLine(textD, nextLineStartPos, True));
5105 @@ -1520,11 +1674,11 @@ static void bufModifiedCB(int pos, int n
5106 textDisp *textD = (textDisp *)cbArg;
5107 textBuffer *buf = textD->buffer;
5108 int oldFirstChar = textD->firstChar;
5109 int scrolled, origCursorPos = textD->cursorPos;
5110 int wrapModStart, wrapModEnd;
5113 /* buffer modification cancels vertical cursor motion column */
5114 if (nInserted != 0 || nDeleted != 0)
5115 textD->cursorPreferredCol = -1;
5117 /* Count the number of lines inserted and deleted, and in the case
5118 @@ -1745,14 +1899,29 @@ static int posToVisibleLineNum(textDisp
5119 ** "leftClip" and "rightClip" window coordinates and "leftCharIndex" and
5120 ** "rightCharIndex" character positions (not including the character at
5121 ** position "rightCharIndex").
5123 ** The cursor is also drawn if it appears on the line.
5125 +** The function actually forwards to redisplayLineCur(), passing the
5126 +** showCursorline setting as appropriate.
5128 static void redisplayLine(textDisp *textD, int visLineNum, int leftClip,
5129 int rightClip, int leftCharIndex, int rightCharIndex)
5131 + redisplayLineCur(textD, visLineNum, leftClip, rightClip, leftCharIndex,
5132 + rightCharIndex, textD->showCursorline);
5136 +** The meat of redisplayLine() is handled here. The extra curLine parameter
5137 +** tells redisplayLineCur() whether it should attempt to reset the previous
5138 +** "current line" to a non-current line state.
5140 +static void redisplayLineCur(textDisp* textD, int visLineNum, int leftClip,
5141 + int rightClip, int leftCharIndex, int rightCharIndex, Boolean curLine)
5143 textBuffer *buf = textD->buffer;
5144 int i, x, y, startX, charIndex, lineStartPos, lineLen, fontHeight;
5145 int stdCharWidth, charWidth, startIndex, charStyle, style;
5146 int charLen, outStartIndex, outIndex, cursorX = 0, hasCursor = False;
5147 int dispIndexOffset, cursorPos = textD->cursorPos, y_orig;
5148 @@ -1784,10 +1953,104 @@ static void redisplayLine(textDisp *text
5149 } else {
5150 lineLen = visLineLength(textD, visLineNum);
5151 lineStr = BufGetRange(buf, lineStartPos, lineStartPos + lineLen);
5154 + /* handle case of leftCharIndex == rightCharIndex */
5155 + if (leftCharIndex == rightCharIndex) {
5156 + if (lineStartPos + leftCharIndex == cursorPos)
5158 + /* we're at the cursor position */
5159 + if (leftCharIndex > 0)
5160 + --leftCharIndex;
5161 + if (rightCharIndex < lineLen)
5162 + ++rightCharIndex;
5163 + if (rightCharIndex >= lineLen)
5164 + rightCharIndex = INT_MAX;
5165 + } else {
5166 + /* hmm: not sure what gets us here, but it happens - redraw line */
5167 + leftCharIndex = 0;
5168 + rightCharIndex = INT_MAX;
5169 + return;
5173 + /* for cursorline tracking, if this is the current line, check it against
5174 + the last cursorline - if different, we need to display the whole line
5175 + plus anything to the extreme right */
5176 + if (curLine
5177 + && (textD->oldCursorPos != cursorPos
5178 + || textD->oldLineStart != lineStartPos)) {
5179 + int oldCursor = textD->oldCursorPos;
5180 + int lineEndPos = lineStartPos + lineLen;
5181 + int oldLineStart = textD->oldLineStart;
5182 + int gotLineCurdiff = -1;
5183 + /* store new values if we need to call redisplayLine() again */
5184 + textD->oldCursorPos = cursorPos;
5186 + if (lineStartPos <= cursorPos
5187 + && cursorPos <= lineEndPos
5188 + && !(lineStartPos <= oldCursor
5189 + && oldCursor <= lineEndPos)) {
5190 + /* find visible line number for oldCursor */
5191 + int lineNum, startPos = -1, oldLen, endPos;
5192 + int gotLine = -1;
5194 + for (lineNum = 0; lineNum < textD->nVisibleLines; lineNum++) {
5195 + startPos = textD->lineStarts[lineNum];
5196 + if (startPos >= 0) {
5197 + oldLen = visLineLength(textD, lineNum);
5198 + endPos = startPos + oldLen;
5199 + if (startPos >= 0
5200 + && startPos <= oldCursor && oldCursor <= endPos) {
5201 + gotLine = lineNum;
5202 + break;
5207 + if (gotLine >= 0 && gotLine != visLineNum) {
5208 + redisplayLineCur(textD, gotLine, 0, INT_MAX, 0, INT_MAX, False);
5209 + gotLineCurdiff = gotLine;
5212 + /* right: that was the old line done - now the current line */
5213 + leftCharIndex = 0;
5214 + rightCharIndex = INT_MAX;
5216 + /* only update oldLineStart if cursor has moved */
5217 + textD->oldLineStart = lineStartPos;
5220 + if (lineStartPos != oldLineStart) {
5221 + /* find visible line number for oldLineStart */
5222 + int lineNum;
5223 + int gotLine = -1;
5225 + for (lineNum = 0; lineNum < textD->nVisibleLines; lineNum++) {
5226 + if (textD->lineStarts[lineNum] == oldLineStart) {
5227 + gotLine = lineNum;
5228 + break;
5232 + if (gotLine >= 0
5233 + && gotLine != visLineNum
5234 + && gotLineCurdiff != gotLine) {
5235 + redisplayLineCur(textD, gotLine, 0, INT_MAX, 0, INT_MAX, False);
5238 + /* right: that was the old line done - now the current line */
5239 + leftCharIndex = 0;
5240 + rightCharIndex = INT_MAX;
5242 + /* jegub */
5243 + /* only update oldLineStart if cursor has moved */
5244 + textD->oldLineStart = lineStartPos;
5248 /* Space beyond the end of the line is still counted in units of characters
5249 of a standardized character width (this is done mostly because style
5250 changes based on character position can still occur in this region due
5251 to rectangular selections). stdCharWidth must be non-zero to prevent a
5252 potential infinite loop if x does not advance */
5253 @@ -1949,11 +2212,12 @@ static void drawString(textDisp *textD,
5254 XGCValues gcValues;
5255 XFontStruct *fs = textD->fontStruct;
5256 Pixel bground = textD->bgPixel;
5257 Pixel fground = textD->fgPixel;
5258 int underlineStyle = FALSE;
5260 + int cursorline_mask = textD->showCursorline ? CURSORLINE_MASK : 0;
5262 /* Don't draw if widget isn't realized */
5263 if (XtWindow(textD->w) == 0)
5264 return;
5266 /* select a GC */
5267 @@ -1966,16 +2230,20 @@ static void drawString(textDisp *textD,
5269 else if (style & PRIMARY_MASK) {
5270 gc = textD->selectGC;
5271 bgGC = textD->selectBGGC;
5273 + else if (style & cursorline_mask) {
5274 + gc = textD->cursorlineGC;
5275 + bgGC = textD->cursorlineBGGC;
5277 else {
5278 gc = bgGC = textD->gc;
5281 + /* Syntax highlighting, backlighting and rangesets need a bit more work.*/
5282 if (gc == textD->styleGC) {
5283 - /* we have work to do */
5284 styleTableEntry *styleRec;
5285 /* Set font, color, and gc depending on style. For normal text, GCs
5286 for normal drawing, or drawing within a selection or highlight are
5287 pre-allocated and pre-configured. For syntax highlighting, GCs are
5288 configured here, on the fly. */
5289 @@ -1990,24 +2258,27 @@ static void drawString(textDisp *textD,
5290 else {
5291 styleRec = NULL;
5292 gcValues.font = fs->fid;
5293 fground = textD->fgPixel;
5295 - /* Background color priority order is:
5296 - 1 Primary(Selection), 2 Highlight(Parens),
5297 - 3 Rangeset, 4 SyntaxHighlightStyle,
5298 - 5 Backlight (if NOT fill), 6 DefaultBackground */
5299 + /* Background color priority order is:
5300 + 1. PRIMARY (selection)
5301 + 2. Highlight (flash matching parens)
5302 + 3. Rangeset
5303 + 4. SyntaxHighlightStyle
5304 + 5. Cursorline
5305 + 6. Backlight (if NOT fill)
5306 + 7. DefaultBackground */
5307 bground =
5308 style & PRIMARY_MASK ? textD->selectBGPixel :
5309 style & HIGHLIGHT_MASK ? textD->highlightBGPixel :
5310 - style & RANGESET_MASK ?
5311 - getRangesetColor(textD,
5312 - (style&RANGESET_MASK)>>RANGESET_SHIFT,
5313 - bground) :
5314 + style & RANGESET_MASK ? getRangesetColor(textD,
5315 + (style&RANGESET_MASK)>>RANGESET_SHIFT, bground) :
5316 styleRec && styleRec->bgColorName ? styleRec->bgColor :
5317 + style & cursorline_mask ? textD->cursorlineBGPixel :
5318 (style & BACKLIGHT_MASK) && !(style & FILL_MASK) ?
5319 - textD->bgClassPixel[(style>>BACKLIGHT_SHIFT) & 0xff] :
5320 + textD->bgClassPixel[(style>>BACKLIGHT_SHIFT) & 0xff] :
5321 textD->bgPixel;
5322 if (fground == bground) /* B&W kludge */
5323 fground = textD->bgPixel;
5324 /* set up gc for clearing using the foreground color entry */
5325 gcValues.foreground = gcValues.background = bground;
5326 @@ -2159,10 +2430,11 @@ static void drawCursor(textDisp *textD,
5327 static int styleOfPos(textDisp *textD, int lineStartPos,
5328 int lineLen, int lineIndex, int dispIndex, int thisChar)
5330 textBuffer *buf = textD->buffer;
5331 textBuffer *styleBuf = textD->styleBuffer;
5332 + int cursorPos = textD->cursorPos;
5333 int pos, style = 0;
5335 if (lineStartPos == -1 || buf == NULL)
5336 return FILL_MASK;
5338 @@ -2180,10 +2452,12 @@ static int styleOfPos(textDisp *textD, i
5340 if (inSelection(&buf->primary, pos, lineStartPos, dispIndex))
5341 style |= PRIMARY_MASK;
5342 if (inSelection(&buf->highlight, pos, lineStartPos, dispIndex))
5343 style |= HIGHLIGHT_MASK;
5344 + if (lineStartPos <= cursorPos && cursorPos <= lineStartPos + lineLen)
5345 + style |= CURSORLINE_MASK;
5346 if (inSelection(&buf->secondary, pos, lineStartPos, dispIndex))
5347 style |= SECONDARY_MASK;
5348 /* store in the RANGESET_MASK portion of style the rangeset index for pos */
5349 if (buf->rangesetTable) {
5350 int rangesetIndex = RangesetIndex1ofPos(buf->rangesetTable, pos, True);
5351 @@ -2720,12 +2994,13 @@ static void setScroll(textDisp *textD, i
5353 else if (xOffset < 0) {
5354 TextDRedisplayRect(textD, textD->left + textD->width + xOffset,
5355 textD->top, -xOffset, textD->height);
5358 /* Restore protruding parts of the cursor */
5359 - textDRedisplayRange(textD, textD->cursorPos-1, textD->cursorPos+1);
5360 + redisplayCursor(textD);
5363 /* Refresh line number/calltip display if its up and we've scrolled
5364 vertically */
5365 if (lineDelta != 0) {
5366 @@ -2886,14 +3161,34 @@ static void redrawLineNumbers(textDisp *
5368 static void vScrollCB(Widget w, XtPointer clientData, XtPointer callData)
5370 textDisp *textD = (textDisp *)clientData;
5371 int newValue = ((XmScrollBarCallbackStruct *)callData)->value;
5372 + int reason = ((XmScrollBarCallbackStruct*) callData)->reason;
5373 int lineDelta = newValue - textD->topLineNum;
5375 - if (lineDelta == 0)
5377 + if (0 == lineDelta) {
5378 + KillScrolltip(textD);
5379 return;
5382 + /* lineDelta is always != 0 for XmCR_DRAG */
5383 + /* Scrolltip does not work for continuous wrap. The only way to get the
5384 + line number is through textDisp->absTopLineNum, but this value is very
5385 + inaccurate for large files. So no tip. */
5386 + if (XmCR_DRAG == reason && !textD->continuousWrap && textD->showScrolltip) {
5387 + /* Display a scrolltip showing the line number about one third down
5388 + from the top, the position a search jumps to. */
5389 + XEvent* event = ((XmScrollBarCallbackStruct*) callData)->event;
5390 + XMotionEvent* motionEvent = (XMotionEvent*) event;
5391 + char valueBuffer[TYPE_INT_STR_SIZE(int)];
5393 + sprintf(valueBuffer, "%i", newValue + (textD->nVisibleLines / 3));
5394 + ShowScrolltip(textD, valueBuffer, motionEvent->x_root - 50,
5395 + motionEvent->y_root);
5398 setScroll(textD, newValue, textD->horizOffset, False, True);
5400 static void hScrollCB(Widget w, XtPointer clientData, XtPointer callData)
5402 textDisp *textD = (textDisp *)clientData;
5403 @@ -3008,11 +3303,12 @@ static void blankCursorProtrusions(textD
5404 ** Allocate shared graphics contexts used by the widget, which must be
5405 ** re-allocated on a font change.
5407 static void allocateFixedFontGCs(textDisp *textD, XFontStruct *fontStruct,
5408 Pixel bgPixel, Pixel fgPixel, Pixel selectFGPixel, Pixel selectBGPixel,
5409 - Pixel highlightFGPixel, Pixel highlightBGPixel, Pixel lineNumFGPixel)
5410 + Pixel highlightFGPixel, Pixel highlightBGPixel, Pixel lineNumFGPixel,
5411 + Pixel wrapMarginFGPixel, Pixel cursorlineBGPixel)
5413 textD->gc = allocateGC(textD->w, GCFont | GCForeground | GCBackground,
5414 fgPixel, bgPixel, fontStruct->fid, GCClipMask, GCArcMode);
5415 textD->selectGC = allocateGC(textD->w, GCFont | GCForeground | GCBackground,
5416 selectFGPixel, selectBGPixel, fontStruct->fid, GCClipMask,
5417 @@ -3022,13 +3318,20 @@ static void allocateFixedFontGCs(textDis
5418 textD->highlightGC = allocateGC(textD->w, GCFont|GCForeground|GCBackground,
5419 highlightFGPixel, highlightBGPixel, fontStruct->fid, GCClipMask,
5420 GCArcMode);
5421 textD->highlightBGGC = allocateGC(textD->w, GCForeground, highlightBGPixel,
5422 0, fontStruct->fid, GCClipMask, GCArcMode);
5423 + textD->cursorlineGC = allocateGC(textD->w, GCFont|GCForeground|GCBackground,
5424 + fgPixel, cursorlineBGPixel, fontStruct->fid, GCClipMask,
5425 + GCArcMode);
5426 + textD->cursorlineBGGC = allocateGC(textD->w, GCForeground,
5427 + cursorlineBGPixel, 0, fontStruct->fid, GCClipMask, GCArcMode);
5428 textD->lineNumGC = allocateGC(textD->w, GCFont | GCForeground |
5429 GCBackground, lineNumFGPixel, bgPixel, fontStruct->fid,
5430 GCClipMask, GCArcMode);
5431 + textD->wrapMarginGC = allocateGC(textD->w, GCForeground | GCBackground,
5432 + wrapMarginFGPixel, bgPixel, fontStruct->fid, GCClipMask, GCArcMode);
5436 ** X11R4 does not have the XtAllocateGC function for sharing graphics contexts
5437 ** with changeable fields. Unfortunately the R4 call for creating shared
5438 @@ -3097,10 +3400,16 @@ static void resetClipRectangles(textDisp
5439 &clipRect, 1, Unsorted);
5440 XSetClipRectangles(display, textD->highlightBGGC, 0, 0,
5441 &clipRect, 1, Unsorted);
5442 XSetClipRectangles(display, textD->styleGC, 0, 0,
5443 &clipRect, 1, Unsorted);
5444 + XSetClipRectangles(display, textD->cursorlineGC, 0, 0,
5445 + &clipRect, 1, Unsorted);
5446 + XSetClipRectangles(display, textD->cursorlineBGGC, 0, 0,
5447 + &clipRect, 1, Unsorted);
5448 + XSetClipRectangles(display, textD->wrapMarginGC, 0, 0,
5449 + &clipRect, 1, Unsorted);
5453 ** Return the length of a line (number of displayable characters) by examining
5454 ** entries in the line starts array rather than by scanning for newlines
5455 @@ -3800,5 +4109,47 @@ void TextDSetupBGClasses(Widget w, XmStr
5456 return;
5458 memcpy(*pp_bgClass, bgClass, 256);
5459 memcpy(*pp_bgClassPixel, bgClassPixel, class_no * sizeof (Pixel));
5463 +** Draw wrap margin if requested
5465 +static void drawWrapMargin(textDisp *textD)
5467 + int fromX, fromY;
5468 + int fontHeight, lineHeight;
5471 + /* attempt to draw the wrap margin # only if
5472 + - widget has been realized
5473 + - font width is not -1, ie. not using different/proportional width fonts
5474 + - show wrap margins is enabled */
5475 + if (XtWindow(textD->w) != 0
5476 + && textD->fixedFontWidth != -1
5477 + && textD->showWrapMargin)
5479 + fromX = textD->left + (textD->fixedFontWidth * textD->wrapMargin)
5480 + - textD->horizOffset - 1;
5482 + /* compute rest of coordinates if line is to right of left margin */
5483 + if (fromX > textD->left)
5485 + fromY = textD->top;
5486 + fontHeight = textD->ascent + textD->descent;
5487 + lineHeight = textD->nVisibleLines * fontHeight - 1;
5488 + XDrawLine(XtDisplay(textD->w), XtWindow(textD->w),
5489 + textD->wrapMarginGC, fromX, fromY, fromX,
5490 + fromY + lineHeight);
5492 + Handle to move wrap margin around with the mouse.
5493 + XDrawLine(XtDisplay(textD->w), XtWindow(textD->w),
5494 + textD->wrapMarginGC, fromX - 1, fromY, fromX - 1,
5495 + fromY + 3);
5496 + XDrawLine(XtDisplay(textD->w), XtWindow(textD->w),
5497 + textD->wrapMarginGC, fromX + 1, fromY, fromX + 1,
5498 + fromY + 3);
5503 diff --quilt old/source/textDisp.h new/source/textDisp.h
5504 --- old/source/textDisp.h
5505 +++ new/source/textDisp.h
5506 @@ -72,10 +72,11 @@ typedef struct _calltipStruct {
5507 Boolean anchored; /* Is it anchored to a position */
5508 int pos; /* Position tip is anchored to */
5509 int hAlign; /* horizontal alignment */
5510 int vAlign; /* vertical alignment */
5511 int alignMode; /* Strict or sloppy alignment */
5512 + Widget widget; /* calltip's widget */
5513 } calltipStruct;
5515 typedef struct _textDisp {
5516 Widget w;
5517 int top, left, width, height, lineNumLeft, lineNumWidth;
5518 @@ -101,17 +102,21 @@ typedef struct _textDisp {
5519 either to a newline or one character
5520 beyond the end of the buffer) */
5521 int continuousWrap; /* Wrap long lines when displaying */
5522 int wrapMargin; /* Margin in # of char positions for
5523 wrapping in continuousWrap mode */
5524 + int showWrapMargin; /* draw line at wrap margin */
5525 int *lineStarts;
5526 - int topLineNum; /* Line number of top displayed line
5527 - of file (first line of file is 1) */
5528 - int absTopLineNum; /* In continuous wrap mode, the line
5529 - number of the top line if the text
5530 - were not wrapped (note that this is
5531 - only maintained as needed). */
5532 + int topLineNum; /* Almost the line number of top displayed line
5533 + of file (first line of file is 1). Actually
5534 + it's off by one screenful or so most of the
5535 + times. */
5536 + int absTopLineNum; /* In continuous wrap mode, almost the line
5537 + number of the top line if the text were not
5538 + wrapped. Actually it's off by one screenful
5539 + most of the times. (Note that this is only
5540 + maintained as needed). */
5541 int needAbsTopLineNum; /* Externally settable flag to continue
5542 maintaining absTopLineNum even if
5543 it isn't needed for line # display */
5544 int horizOffset; /* Horizontal scroll pos. in pixels */
5545 int visibility; /* Window visibility (see XVisibility event) */
5546 @@ -127,12 +132,15 @@ typedef struct _textDisp {
5547 int ascent, descent; /* Composite ascent and descent for
5548 primary font + all-highlight fonts */
5549 int fixedFontWidth; /* Font width if all current fonts are
5550 fixed and match in width, else -1 */
5551 Widget hScrollBar, vScrollBar;
5552 - GC gc, selectGC, highlightGC; /* GCs for drawing text */
5553 - GC selectBGGC, highlightBGGC; /* GCs for erasing text */
5554 + int oldCursorPos;
5555 + int oldLineStart;
5556 + Pixel cursorlineBGPixel;
5557 + GC gc, selectGC, highlightGC, cursorlineGC; /* GCs for drawing text */
5558 + GC selectBGGC, highlightBGGC, cursorlineBGGC; /* GCs for erasing text */
5559 GC cursorFGGC; /* GC for drawing the cursor */
5560 GC lineNumGC; /* GC for drawing line numbers */
5561 GC styleGC; /* GC with color and font unspecified
5562 for drawing colored/styled text */
5563 Pixel fgPixel, bgPixel; /* Foreground/Background colors */
5564 @@ -143,15 +151,15 @@ typedef struct _textDisp {
5565 Pixel lineNumFGPixel; /* Color for drawing line numbers */
5566 Pixel cursorFGPixel;
5567 Pixel *bgClassPixel; /* table of colors for each BG class */
5568 unsigned char *bgClass; /* obtains index into bgClassPixel[] */
5570 - Widget calltipW; /* The Label widget for the calltip */
5571 - Widget calltipShell; /* The Shell that holds the calltip */
5572 calltipStruct calltip; /* The info for the calltip itself */
5573 Pixel calltipFGPixel;
5574 Pixel calltipBGPixel;
5575 + Pixel wrapMarginFGPixel; /* color for drawing wrap margin */
5576 + GC wrapMarginGC; /* GC for drawing wrap margin */
5577 int suppressResync; /* Suppress resynchronization of line
5578 starts during buffer updates */
5579 int nLinesDeleted; /* Number of lines deleted during
5580 buffer modification (only used
5581 when resynchronization is
5582 @@ -159,28 +167,36 @@ typedef struct _textDisp {
5583 int modifyingTabDist; /* Whether tab distance is being
5584 modified */
5585 Boolean pointerHidden; /* true if the mouse pointer is
5586 hidden */
5587 graphicExposeTranslationEntry *graphicsExposeQueue;
5588 + Boolean showCursorline;
5589 + Boolean showScrolltip;
5590 + Widget scrolltip;
5591 } textDisp;
5593 textDisp *TextDCreate(Widget widget, Widget hScrollBar, Widget vScrollBar,
5594 - Position left, Position top, Position width, Position height,
5595 - Position lineNumLeft, Position lineNumWidth, textBuffer *buffer,
5596 - XFontStruct *fontStruct, Pixel bgPixel, Pixel fgPixel,
5597 - Pixel selectFGPixel, Pixel selectBGPixel, Pixel highlightFGPixel,
5598 - Pixel highlightBGPixel, Pixel cursorFGPixel, Pixel lineNumFGPixel,
5599 - int continuousWrap, int wrapMargin, XmString bgClassString,
5600 - Pixel calltipFGPixel, Pixel calltipBGPixel);
5601 + Position left, Position top, Position width, Position height,
5602 + Position lineNumLeft, Position lineNumWidth,
5603 + textBuffer *buffer,
5604 + XFontStruct *fontStruct,
5605 + Pixel bgPixel, Pixel fgPixel, Pixel selectFGPixel, Pixel selectBGPixel,
5606 + Pixel highlightFGPixel, Pixel highlightBGPixel, Pixel cursorFGPixel,
5607 + Pixel lineNumFGPixel, Pixel wrapMarginFGPixel, Pixel calltipFGPixel,
5608 + Pixel calltipBGPixel, Pixel cursorlineBGPixel,
5609 + int continuousWrap, int wrapMargin, Boolean showWrapMargin,
5610 + XmString bgClassString, Boolean showCursorline, Boolean showScrolltip);
5611 void TextDFree(textDisp *textD);
5612 void TextDSetBuffer(textDisp *textD, textBuffer *buffer);
5613 void TextDAttachHighlightData(textDisp *textD, textBuffer *styleBuffer,
5614 styleTableEntry *styleTable, int nStyles, char unfinishedStyle,
5615 unfinishedStyleCBProc unfinishedHighlightCB, void *cbArg);
5616 void TextDSetColors(textDisp *textD, Pixel textFgP, Pixel textBgP,
5617 Pixel selectFgP, Pixel selectBgP, Pixel hiliteFgP, Pixel hiliteBgP,
5618 - Pixel lineNoFgP, Pixel cursorFgP);
5619 + Pixel lineNoFgP, Pixel cursorFgP, Pixel wrapMarginFgP,
5620 + Pixel cursorlineBgP);
5621 +void TextDSetShowCursorline(textDisp* textD, const Boolean showCursorline);
5622 void TextDSetFont(textDisp *textD, XFontStruct *fontStruct);
5623 int TextDMinFontWidth(textDisp *textD, Boolean considerStyles);
5624 int TextDMaxFontWidth(textDisp *textD, Boolean considerStyles);
5625 void TextDResize(textDisp *textD, int width, int height);
5626 void TextDRedisplayRect(textDisp *textD, int left, int top, int width,
5627 @@ -208,10 +224,11 @@ int TextDMoveUp(textDisp *textD, int abs
5628 int TextDMoveDown(textDisp *textD, int absolute);
5629 void TextDBlankCursor(textDisp *textD);
5630 void TextDUnblankCursor(textDisp *textD);
5631 void TextDSetCursorStyle(textDisp *textD, int style);
5632 void TextDSetWrapMode(textDisp *textD, int wrap, int wrapMargin);
5633 +void TextDSetShowWrapMargin(textDisp *textD, int state);
5634 int TextDEndOfLine(const textDisp* textD, const int pos,
5635 const Boolean startPosIsLineStart);
5636 int TextDStartOfLine(const textDisp* textD, const int pos);
5637 int TextDCountForwardNLines(const textDisp* textD, const int startPos,
5638 const unsigned nLines, const Boolean startPosIsLineStart);
5639 diff --quilt old/source/textP.h new/source/textP.h
5640 --- old/source/textP.h
5641 +++ new/source/textP.h
5642 @@ -57,10 +57,12 @@ extern TextClassRec nTextClassRec;
5644 typedef struct _TextPart {
5645 /* resources */
5646 Pixel selectFGPixel, selectBGPixel, highlightFGPixel, highlightBGPixel;
5647 Pixel cursorFGPixel, lineNumFGPixel, calltipFGPixel, calltipBGPixel;
5648 + Pixel wrapMarginFGPixel;
5649 + Pixel cursorlineBGPixel;
5650 XFontStruct *fontStruct;
5651 Boolean pendingDelete;
5652 Boolean autoShowInsertPos;
5653 Boolean autoWrap;
5654 Boolean autoWrapPastedText;
5655 @@ -69,14 +71,17 @@ typedef struct _TextPart {
5656 Boolean smartIndent;
5657 Boolean overstrike;
5658 Boolean heavyCursor;
5659 Boolean readOnly;
5660 Boolean hidePointer;
5661 + Boolean showCursorline;
5662 + Boolean showScrolltip;
5663 int rows, columns;
5664 int marginWidth, marginHeight;
5665 int cursorBlinkRate;
5666 int wrapMargin;
5667 + Boolean showWrapMargin;
5668 int emulateTabs;
5669 int lineNumCols;
5670 char *delimiters;
5671 Cardinal cursorVPadding;
5672 Widget hScrollBar, vScrollBar;
5673 diff --quilt old/source/window.c new/source/window.c
5674 --- old/source/window.c
5675 +++ new/source/window.c
5676 @@ -6,11 +6,11 @@ static const char CVSID[] = "$Id: window
5677 * Copyright (C) 1999 Mark Edel *
5679 * This is free software; you can redistribute it and/or modify it under the *
5680 * terms of the GNU General Public License as published by the Free Software *
5681 * Foundation; either version 2 of the License, or (at your option) any later *
5682 -* version. In addition, you may distribute version of this program linked to *
5683 +* version. In addition, you may distribute versions of this program linked to *
5684 * Motif or Open Motif. See README for details. *
5686 * This software is distributed in the hope that it will be useful, but WITHOUT *
5687 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
5688 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
5689 @@ -167,10 +167,11 @@ static void showStats(WindowInfo *window
5690 static void showISearch(WindowInfo *window, int state);
5691 static void showStatsForm(WindowInfo *window);
5692 static void addToWindowList(WindowInfo *window);
5693 static void removeFromWindowList(WindowInfo *window);
5694 static void focusCB(Widget w, WindowInfo *window, XtPointer callData);
5695 +static void loosingFocusCB(Widget w, WindowInfo *window, XtPointer callData);
5696 static void modifiedCB(int pos, int nInserted, int nDeleted, int nRestyled,
5697 const char *deletedText, void *cbArg);
5698 static void movedCB(Widget w, WindowInfo *window, XtPointer callData);
5699 static void dragStartCB(Widget w, WindowInfo *window, XtPointer callData);
5700 static void dragEndCB(Widget w, WindowInfo *window, dragEndCBStruct *callData);
5701 @@ -257,19 +258,22 @@ WindowInfo *CreateWindow(const char *nam
5702 window->fileMissing = True;
5703 strcpy(window->filename, name);
5704 window->undo = NULL;
5705 window->redo = NULL;
5706 window->nPanes = 0;
5707 + window->lastFocus = NULL;
5708 window->autoSaveCharCount = 0;
5709 window->autoSaveOpCount = 0;
5710 window->undoOpCount = 0;
5711 window->undoMemUsed = 0;
5712 CLEAR_ALL_LOCKS(window->lockReasons);
5713 + window->transient = False;
5714 window->indentStyle = GetPrefAutoIndent(PLAIN_LANGUAGE_MODE);
5715 window->autoSave = GetPrefAutoSave();
5716 window->saveOldVersion = GetPrefSaveOldVersion();
5717 window->wrapMode = GetPrefWrap(PLAIN_LANGUAGE_MODE);
5718 + window->showWrapMargin = GetPrefShowWrapMargin();
5719 window->overstrike = False;
5720 window->showMatchingStyle = GetPrefShowMatching();
5721 window->matchSyntaxBased = GetPrefMatchSyntaxBased();
5722 window->showStats = GetPrefStatsLine();
5723 window->showISearchLine = GetPrefISearchLine();
5724 @@ -465,11 +469,12 @@ WindowInfo *CreateWindow(const char *nam
5726 window->iSearchRegexToggle = XtVaCreateManagedWidget("iSearchREToggle",
5727 xmToggleButtonWidgetClass, window->iSearchForm,
5728 XmNlabelString, s1=XmStringCreateSimple("RegExp"),
5729 XmNset, GetPrefSearch() == SEARCH_REGEX_NOCASE
5730 - || GetPrefSearch() == SEARCH_REGEX,
5731 + || GetPrefSearch() == SEARCH_REGEX
5732 + || GetPrefSearch() == SEARCH_REGEX_SMARTCASE,
5733 XmNtopAttachment, XmATTACH_FORM,
5734 XmNbottomAttachment, XmATTACH_FORM,
5735 XmNtopOffset, 1, /* see openmotif note above */
5736 XmNrightAttachment, XmATTACH_WIDGET,
5737 XmNrightWidget, window->iSearchCaseToggle,
5738 @@ -695,23 +700,25 @@ WindowInfo *CreateWindow(const char *nam
5739 text = createTextArea(pane, window, rows,cols,
5740 GetPrefEmTabDist(PLAIN_LANGUAGE_MODE), GetPrefDelimiters(),
5741 GetPrefWrapMargin(), window->showLineNumbers?MIN_LINE_NUM_COLS:0);
5742 XtManageChild(text);
5743 window->textArea = text;
5744 - window->lastFocus = text;
5745 + ChangeLastFocus(window, text);
5747 /* Set the initial colors from the globals. */
5748 SetColors(window,
5749 GetPrefColorName(TEXT_FG_COLOR ),
5750 GetPrefColorName(TEXT_BG_COLOR ),
5751 GetPrefColorName(SELECT_FG_COLOR),
5752 GetPrefColorName(SELECT_BG_COLOR),
5753 GetPrefColorName(HILITE_FG_COLOR),
5754 GetPrefColorName(HILITE_BG_COLOR),
5755 GetPrefColorName(LINENO_FG_COLOR),
5756 - GetPrefColorName(CURSOR_FG_COLOR));
5758 + GetPrefColorName(CURSOR_FG_COLOR),
5759 + GetPrefColorName(WRAPMARGIN_FG_COLOR),
5760 + GetPrefColorName(CURSORLINE_BG_COLOR));
5762 /* Create the right button popup menu (note: order is important here,
5763 since the translation for popping up this menu was probably already
5764 added in createTextArea, but CreateBGMenu requires window->textArea
5765 to be set so it can attach the menu to it (because menu shells are
5766 finicky about the kinds of widgets they are attached to)) */
5767 @@ -1214,14 +1221,15 @@ void SplitPane(WindowInfo *window)
5768 newTextD = ((TextWidget)text)->text.textD;
5769 XtVaSetValues(text,
5770 XmNforeground, textD->fgPixel,
5771 XmNbackground, textD->bgPixel,
5772 NULL);
5773 - TextDSetColors( newTextD, textD->fgPixel, textD->bgPixel,
5774 - textD->selectFGPixel, textD->selectBGPixel, textD->highlightFGPixel,
5775 - textD->highlightBGPixel, textD->lineNumFGPixel,
5776 - textD->cursorFGPixel );
5777 + TextDSetColors(newTextD, textD->fgPixel, textD->bgPixel,
5778 + textD->selectFGPixel, textD->selectBGPixel,
5779 + textD->highlightFGPixel, textD->highlightBGPixel,
5780 + textD->lineNumFGPixel, textD->cursorFGPixel,
5781 + textD->wrapMarginFGPixel, textD->cursorlineBGPixel);
5783 /* Set the minimum pane height in the new pane */
5784 UpdateMinPaneHeights(window);
5786 /* adjust the heights, scroll positions, etc., to split the focus pane */
5787 @@ -1292,11 +1300,11 @@ void ClosePane(WindowInfo *window)
5789 short paneHeights[MAX_PANES+1];
5790 int insertPositions[MAX_PANES+1], topLines[MAX_PANES+1];
5791 int horizOffsets[MAX_PANES+1];
5792 int i, focusPane;
5793 - Widget text;
5794 + Widget text = NULL;
5796 /* Don't delete the last pane */
5797 if (window->nPanes <= 0)
5798 return;
5800 @@ -1322,14 +1330,19 @@ void ClosePane(WindowInfo *window)
5801 the remaining panes, simply detroying it didn't seem enough */
5802 window->nPanes--;
5803 XtUnmanageChild(containingPane(window->textPanes[window->nPanes]));
5804 XtDestroyWidget(containingPane(window->textPanes[window->nPanes]));
5806 - if (window->nPanes == 0)
5807 - window->lastFocus = window->textArea;
5808 - else if (focusPane > window->nPanes)
5809 - window->lastFocus = window->textPanes[window->nPanes-1];
5810 + if (window->nPanes == 0) {
5811 + text = window->textArea;
5812 + } else if (focusPane > window->nPanes) {
5813 + text = window->textPanes[window->nPanes - 1];
5814 + } else {
5815 + text = window->textPanes[focusPane - 1];
5818 + ChangeLastFocus(window, text);
5820 /* adjust the heights, scroll positions, etc., to make it look
5821 like the pane with the input focus was closed */
5822 for (i=focusPane; i<=window->nPanes; i++) {
5823 insertPositions[i] = insertPositions[i+1];
5824 @@ -1853,11 +1866,12 @@ void SetFonts(WindowInfo *window, const
5825 UpdateMinPaneHeights(window);
5828 void SetColors(WindowInfo *window, const char *textFg, const char *textBg,
5829 const char *selectFg, const char *selectBg, const char *hiliteFg,
5830 - const char *hiliteBg, const char *lineNoFg, const char *cursorFg)
5831 + const char *hiliteBg, const char *lineNoFg, const char *cursorFg,
5832 + const char* wrapMarginFg, const char* cursorlineBg)
5834 int i, dummy;
5835 Pixel textFgPix = AllocColor( window->textArea, textFg,
5836 &dummy, &dummy, &dummy),
5837 textBgPix = AllocColor( window->textArea, textBg,
5838 @@ -1871,30 +1885,36 @@ void SetColors(WindowInfo *window, const
5839 hiliteBgPix = AllocColor( window->textArea, hiliteBg,
5840 &dummy, &dummy, &dummy),
5841 lineNoFgPix = AllocColor( window->textArea, lineNoFg,
5842 &dummy, &dummy, &dummy),
5843 cursorFgPix = AllocColor( window->textArea, cursorFg,
5844 + &dummy, &dummy, &dummy),
5845 + wrapMarginFgPix = AllocColor( window->textArea, wrapMarginFg,
5846 + &dummy, &dummy, &dummy),
5847 + cursorlineBgPix = AllocColor( window->textArea, cursorlineBg,
5848 &dummy, &dummy, &dummy);
5849 textDisp *textD;
5851 /* Update the main pane */
5852 XtVaSetValues(window->textArea,
5853 XmNforeground, textFgPix,
5854 XmNbackground, textBgPix,
5855 NULL);
5856 textD = ((TextWidget)window->textArea)->text.textD;
5857 TextDSetColors( textD, textFgPix, textBgPix, selectFgPix, selectBgPix,
5858 - hiliteFgPix, hiliteBgPix, lineNoFgPix, cursorFgPix );
5859 + hiliteFgPix, hiliteBgPix, lineNoFgPix, cursorFgPix,
5860 + wrapMarginFgPix, cursorlineBgPix);
5861 /* Update any additional panes */
5862 for (i=0; i<window->nPanes; i++) {
5863 XtVaSetValues(window->textPanes[i],
5864 XmNforeground, textFgPix,
5865 XmNbackground, textBgPix,
5866 NULL);
5867 textD = ((TextWidget)window->textPanes[i])->text.textD;
5868 TextDSetColors( textD, textFgPix, textBgPix, selectFgPix, selectBgPix,
5869 - hiliteFgPix, hiliteBgPix, lineNoFgPix, cursorFgPix );
5870 + hiliteFgPix, hiliteBgPix, lineNoFgPix, cursorFgPix,
5871 + wrapMarginFgPix, cursorlineBgPix);
5874 /* Redo any syntax highlighting */
5875 if (window->highlightData != NULL)
5876 UpdateHighlightStyles(window);
5877 @@ -1926,15 +1946,18 @@ void SetAutoWrap(WindowInfo *window, int
5878 for (i=0; i<window->nPanes; i++)
5879 XtVaSetValues(window->textPanes[i], textNautoWrap, autoWrap,
5880 textNcontinuousWrap, contWrap, NULL);
5881 window->wrapMode = state;
5883 - if (IsTopDocument(window)) {
5884 - XmToggleButtonSetState(window->newlineWrapItem, autoWrap, False);
5885 - XmToggleButtonSetState(window->continuousWrapItem, contWrap, False);
5886 - XmToggleButtonSetState(window->noWrapItem, state == NO_WRAP, False);
5887 + if (IsTopDocument(window))
5889 + XmToggleButtonSetState(window->newlineWrapItem, autoWrap, False);
5890 + XmToggleButtonSetState(window->continuousWrapItem, contWrap, False);
5891 + XmToggleButtonSetState(window->noWrapItem, state == NO_WRAP, False);
5894 + SetShowWrapMargin(window, window->showWrapMargin);
5898 ** Set the auto-scroll margin
5900 @@ -1946,10 +1969,37 @@ void SetAutoScroll(WindowInfo *window, i
5901 for (i=0; i<window->nPanes; i++)
5902 XtVaSetValues(window->textPanes[i], textNcursorVPadding, margin, NULL);
5906 +** Set show-wrap-margin style, one of NEVER, ALWAYS, ON-WRAP
5908 +void SetShowWrapMargin(WindowInfo* window, int state)
5910 + int i;
5911 + int alwaysShowWrapMargin = (SHOW_WRAP_MARGIN_ALWAYS == state);
5912 + int onWrapShowWrapMargin = (SHOW_WRAP_MARGIN_ON_WRAP == state);
5913 + int autoWrap = (NEWLINE_WRAP == window->wrapMode);
5914 + int contWrap = (CONTINUOUS_WRAP == window->wrapMode);
5915 + /* true or false only. not never/always/on-wrap. text widget does need to know
5916 + exact details. it just needs to know that wrap margin should be shown */
5917 + int showWrapMargin = (alwaysShowWrapMargin
5918 + || (onWrapShowWrapMargin && autoWrap)
5919 + || (onWrapShowWrapMargin && contWrap));
5921 + XtVaSetValues(window->textArea, textNshowWrapMargin, showWrapMargin, NULL);
5922 + for (i = 0; i < window->nPanes; i++) {
5923 + XtVaSetValues(window->textPanes[i],
5924 + textNshowWrapMargin, showWrapMargin,
5925 + NULL);
5927 + /* never/always/on-wrap needs to be stored in window settings, for generating
5928 + menu, etc */
5929 + window->showWrapMargin = state;
5933 ** Recover the window pointer from any widget in the window, by searching
5934 ** up the widget hierarcy for the top level container widget where the
5935 ** window pointer is stored in the userData field. In a tabbed window,
5936 ** this is the window pointer of the top (active) document, which is
5937 ** returned if w is 'shell-level' widget - menus, find/replace dialogs, etc.
5938 @@ -2203,10 +2253,19 @@ void MakeSelectionVisible(WindowInfo *wi
5939 static Widget createTextArea(Widget parent, WindowInfo *window, int rows,
5940 int cols, int emTabDist, char *delimiters, int wrapMargin,
5941 int lineNumCols)
5943 Widget text, sw, hScrollBar, vScrollBar, frame;
5944 + int alwaysShowWrapMargin = (window->showWrapMargin == SHOW_WRAP_MARGIN_ALWAYS);
5945 + int onWrapShowWrapMargin = (window->showWrapMargin == SHOW_WRAP_MARGIN_ON_WRAP);
5946 + int autoWrap = (window->wrapMode == NEWLINE_WRAP);
5947 + int contWrap = (window->wrapMode == CONTINUOUS_WRAP);
5948 + /* true or false only. not never/always/on-wrap. text widget does need to know
5949 + exact details. it just needs to know that wrap margin should be shown */
5950 + int showWrapMargin = (alwaysShowWrapMargin ||
5951 + (onWrapShowWrapMargin && autoWrap) ||
5952 + (onWrapShowWrapMargin && contWrap) );
5954 /* Create a text widget inside of a scrolled window widget */
5955 sw = XtVaCreateManagedWidget("scrolledW", xmScrolledWindowWidgetClass,
5956 parent, XmNpaneMaximum, SHRT_MAX,
5957 XmNpaneMinimum, PANE_MIN_HEIGHT, XmNhighlightThickness, 0, NULL);
5958 @@ -2226,24 +2285,29 @@ static Widget createTextArea(Widget pare
5959 textNfont, GetDefaultFontStruct(window->fontList),
5960 textNhScrollBar, hScrollBar, textNvScrollBar, vScrollBar,
5961 textNreadOnly, IS_ANY_LOCKED(window->lockReasons),
5962 textNwordDelimiters, delimiters,
5963 textNwrapMargin, wrapMargin,
5964 + textNshowWrapMargin, showWrapMargin,
5965 textNautoIndent, window->indentStyle == AUTO_INDENT,
5966 textNsmartIndent, window->indentStyle == SMART_INDENT,
5967 textNautoWrap, window->wrapMode == NEWLINE_WRAP,
5968 textNcontinuousWrap, window->wrapMode == CONTINUOUS_WRAP,
5969 textNoverstrike, window->overstrike,
5970 + textNshowCursorline, False,
5971 textNhidePointer, (Boolean) GetPrefTypingHidesPointer(),
5972 textNcursorVPadding, GetVerticalAutoScroll(),
5973 + textNshowScrolltip, GetPrefShowScrolltip(),
5974 NULL);
5976 XtVaSetValues(sw, XmNworkWindow, frame, XmNhorizontalScrollBar,
5977 hScrollBar, XmNverticalScrollBar, vScrollBar, NULL);
5979 /* add focus, drag, cursor tracking, and smart indent callbacks */
5980 XtAddCallback(text, textNfocusCallback, (XtCallbackProc)focusCB, window);
5981 + XtAddCallback(text, textNlosingFocusCallback,
5982 + (XtCallbackProc) loosingFocusCB, window);
5983 XtAddCallback(text, textNcursorMovementCallback, (XtCallbackProc)movedCB,
5984 window);
5985 XtAddCallback(text, textNdragStartCallback, (XtCallbackProc)dragStartCB,
5986 window);
5987 XtAddCallback(text, textNdragEndCallback, (XtCallbackProc)dragEndCB,
5988 @@ -2292,18 +2356,20 @@ static void movedCB(Widget w, WindowInfo
5989 if (0 != textWidget->text.cursorBlinkProcID)
5991 /* Start blinking the caret again. */
5992 ResetCursorBlink(textWidget, False);
5995 + MacroApplyHook(window, "cursor_moved_hook", 0, NULL, NULL);
5998 static void modifiedCB(int pos, int nInserted, int nDeleted, int nRestyled,
5999 const char *deletedText, void *cbArg)
6001 WindowInfo *window = (WindowInfo *)cbArg;
6002 int selected = window->buffer->primary.selected;
6005 /* update the table of bookmarks */
6006 if (!window->ignoreModify) {
6007 UpdateMarkTable(window, pos, nInserted, nDeleted);
6010 @@ -2363,25 +2429,34 @@ static void modifiedCB(int pos, int nIns
6011 /* Update # of bytes, and line and col statistics */
6012 UpdateStatsLine(window);
6014 /* Check if external changes have been made to file and warn user */
6015 CheckForChangesToFile(window);
6017 + MacroApplyHook(window, "modified_hook", 0, NULL, NULL);
6020 static void focusCB(Widget w, WindowInfo *window, XtPointer callData)
6022 /* record which window pane last had the keyboard focus */
6023 - window->lastFocus = w;
6024 + ChangeLastFocus(window, w);
6026 /* update line number statistic to reflect current focus pane */
6027 UpdateStatsLine(window);
6029 /* finish off the current incremental search */
6030 EndISearch(window);
6032 /* Check for changes to read-only status and/or file modifications */
6033 CheckForChangesToFile(window);
6035 + MacroApplyHook(window, "focus_hook", 0, NULL, NULL);
6038 +static void loosingFocusCB(Widget w, WindowInfo *window, XtPointer callData)
6040 + MacroApplyHook(window, "loosing_focus_hook", 0, NULL, NULL);
6043 static void dragStartCB(Widget w, WindowInfo *window, XtPointer callData)
6045 /* don't record all of the intermediate drag steps for undo */
6046 @@ -2519,20 +2594,25 @@ void AttachSessionMgrHandler(Widget appS
6047 ** on the shell window. I think this is the most reliable way to tell,
6048 ** but if someone has a better idea please send me a note).
6050 int IsIconic(WindowInfo *window)
6052 - unsigned long *property = NULL;
6053 + /* We expect back a CARD32 (see ICCCM 4.1.3.1) so we use type long to
6054 + get enough room for it, even if it's casted down later on. */
6055 + unsigned long* property = NULL;
6056 unsigned long nItems;
6057 unsigned long leftover;
6058 static Atom wmStateAtom = 0;
6059 Atom actualType;
6060 int actualFormat;
6061 int result;
6063 - if (wmStateAtom == 0)
6064 - wmStateAtom = XInternAtom(XtDisplay(window->shell), "WM_STATE", False);
6065 + if (0 == wmStateAtom) {
6066 + /* Get Atom for WM_STATE, create if it does not exist. */
6067 + wmStateAtom = XInternAtom(XtDisplay(window->shell), "WM_STATE", False);
6070 if (XGetWindowProperty(XtDisplay(window->shell), XtWindow(window->shell),
6071 wmStateAtom, 0L, 1L, False, wmStateAtom, &actualType, &actualFormat,
6072 &nItems, &leftover, (unsigned char **)&property) != Success ||
6073 nItems != 1 || property == NULL)
6074 return FALSE;
6075 @@ -2699,11 +2779,19 @@ void UpdateStatsLine(WindowInfo *window)
6076 if (!TextPosToLineAndCol(window->lastFocus, pos, &line, &colNum)) {
6077 sprintf(string, "%s%s%s %d bytes", window->path, window->filename,
6078 format, window->buffer->length);
6079 sprintf(slinecol, "L: --- C: ---");
6080 } else {
6081 - sprintf(slinecol, "L: %d C: %d", line, colNum);
6082 + int start, end, isRect, rectStart, rectEnd, bytesSelected = 0;
6083 + if (BufGetSelectionPos(window->buffer, &start, &end, &isRect, &rectStart, &rectEnd)) {
6084 + bytesSelected = isRect ? 0 : end - start;
6086 + if (bytesSelected > 0) {
6087 + sprintf(slinecol, "[%d] L: %d C: %2d", bytesSelected, line, colNum);
6088 + } else {
6089 + sprintf(slinecol, "L: %d C: %2d", line, colNum);
6091 if (window->showLineNumbers)
6092 sprintf(string, "%s%s%s byte %d of %d", window->path,
6093 window->filename, format, pos,
6094 window->buffer->length);
6095 else
6096 @@ -3276,19 +3364,22 @@ WindowInfo* CreateDocument(WindowInfo* s
6097 window->lastModTime = 0;
6098 strcpy(window->filename, name);
6099 window->undo = NULL;
6100 window->redo = NULL;
6101 window->nPanes = 0;
6102 + window->lastFocus = NULL;
6103 window->autoSaveCharCount = 0;
6104 window->autoSaveOpCount = 0;
6105 window->undoOpCount = 0;
6106 window->undoMemUsed = 0;
6107 CLEAR_ALL_LOCKS(window->lockReasons);
6108 + window->transient = False;
6109 window->indentStyle = GetPrefAutoIndent(PLAIN_LANGUAGE_MODE);
6110 window->autoSave = GetPrefAutoSave();
6111 window->saveOldVersion = GetPrefSaveOldVersion();
6112 window->wrapMode = GetPrefWrap(PLAIN_LANGUAGE_MODE);
6113 + window->showWrapMargin = GetPrefShowWrapMargin();
6114 window->overstrike = False;
6115 window->showMatchingStyle = GetPrefShowMatching();
6116 window->matchSyntaxBased = GetPrefMatchSyntaxBased();
6117 window->highlightSyntax = GetPrefHighlightSyntax();
6118 window->backlightCharTypes = NULL;
6119 @@ -3378,23 +3469,25 @@ WindowInfo* CreateDocument(WindowInfo* s
6120 text = createTextArea(pane, window, nRows, nCols,
6121 GetPrefEmTabDist(PLAIN_LANGUAGE_MODE), GetPrefDelimiters(),
6122 GetPrefWrapMargin(), window->showLineNumbers?MIN_LINE_NUM_COLS:0);
6123 XtManageChild(text);
6124 window->textArea = text;
6125 - window->lastFocus = text;
6126 + ChangeLastFocus(window, text);
6128 /* Set the initial colors from the globals. */
6129 SetColors(window,
6130 GetPrefColorName(TEXT_FG_COLOR ),
6131 GetPrefColorName(TEXT_BG_COLOR ),
6132 GetPrefColorName(SELECT_FG_COLOR),
6133 GetPrefColorName(SELECT_BG_COLOR),
6134 GetPrefColorName(HILITE_FG_COLOR),
6135 GetPrefColorName(HILITE_BG_COLOR),
6136 GetPrefColorName(LINENO_FG_COLOR),
6137 - GetPrefColorName(CURSOR_FG_COLOR));
6139 + GetPrefColorName(CURSOR_FG_COLOR),
6140 + GetPrefColorName(WRAPMARGIN_FG_COLOR),
6141 + GetPrefColorName(CURSORLINE_BG_COLOR));
6143 /* Create the right button popup menu (note: order is important here,
6144 since the translation for popping up this menu was probably already
6145 added in createTextArea, but CreateBGMenu requires window->textArea
6146 to be set so it can attach the menu to it (because menu shells are
6147 finicky about the kinds of widgets they are attached to)) */
6148 @@ -3717,10 +3810,11 @@ void RefreshMenuToggleStates(WindowInfo
6149 #endif
6150 XmToggleButtonSetState(window->autoSaveItem, window->autoSave, False);
6151 XmToggleButtonSetState(window->overtypeModeItem, window->overstrike, False);
6152 XmToggleButtonSetState(window->matchSyntaxBasedItem, window->matchSyntaxBased, False);
6153 XmToggleButtonSetState(window->readOnlyItem, IS_USER_LOCKED(window->lockReasons), False);
6154 + XmToggleButtonSetState(window->transientItem, window->transient, False);
6156 XtSetSensitive(window->smartIndentItem,
6157 SmartIndentMacrosAvailable(LanguageModeName(window->languageMode)));
6159 SetAutoIndent(window, window->indentStyle);
6160 @@ -4178,11 +4272,12 @@ static void cloneTextPanes(WindowInfo *w
6161 XtVaSetValues(text, XmNforeground, textD->fgPixel,
6162 XmNbackground, textD->bgPixel, NULL);
6163 TextDSetColors(newTextD, textD->fgPixel, textD->bgPixel,
6164 textD->selectFGPixel, textD->selectBGPixel,
6165 textD->highlightFGPixel,textD->highlightBGPixel,
6166 - textD->lineNumFGPixel, textD->cursorFGPixel);
6167 + textD->lineNumFGPixel, textD->cursorFGPixel,
6168 + textD->wrapMarginFGPixel, textD->cursorlineBGPixel);
6171 /* Set the minimum pane height in the new pane */
6172 UpdateMinPaneHeights(window);
6174 @@ -4211,11 +4306,11 @@ static void cloneTextPanes(WindowInfo *w
6176 /* set the focus pane */
6177 for (i=0; i<=window->nPanes; i++) {
6178 text = i==0 ? window->textArea : window->textPanes[i-1];
6179 if(i == focusPane) {
6180 - window->lastFocus = text;
6181 + ChangeLastFocus(window, text);
6182 XmProcessTraversal(text, XmTRAVERSE_CURRENT);
6183 break;
6187 @@ -4330,10 +4425,11 @@ static void cloneDocument(WindowInfo *wi
6188 window->findLastLiteralCase = orgWin->findLastLiteralCase;
6189 window->device = orgWin->device;
6190 window->inode = orgWin->inode;
6191 window->fileClosedAtom = orgWin->fileClosedAtom;
6192 orgWin->fileClosedAtom = None;
6193 + window->transient = orgWin->transient;
6195 /* copy the text/split panes settings, cursor pos & selection */
6196 cloneTextPanes(window, orgWin);
6198 /* copy undo & redo list */
6199 @@ -4742,5 +4838,24 @@ void CleanUpTabBarExposeQueue(WindowInfo
6200 ev.count = 0;
6201 XSendEvent(TheDisplay, XtWindow(window->tabBar), False,
6202 ExposureMask, (XEvent *)&ev);
6207 +** Track which text pane in this widget is/was last active (with focus).
6208 +** Also perform any tasks relating to changing pane focus.
6210 +void ChangeLastFocus(WindowInfo *window, Widget text)
6212 + Boolean showCursorline = GetPrefShowCursorline();
6214 + if (NULL != window->lastFocus) {
6215 + /* Remove cursorline from last focussed pane. */
6216 + XtVaSetValues(window->lastFocus,
6217 + textNshowCursorline, False,
6218 + NULL);
6220 + XtVaSetValues(text, textNshowCursorline, showCursorline, NULL);
6222 + window->lastFocus = text;
6224 diff --quilt old/source/window.h new/source/window.h
6225 --- old/source/window.h
6226 +++ new/source/window.h
6227 @@ -51,13 +51,16 @@ void SetAutoIndent(WindowInfo *window, i
6228 void SetShowMatching(WindowInfo *window, int state);
6229 void SetFonts(WindowInfo *window, const char *fontName, const char *italicName,
6230 const char *boldName, const char *boldItalicName);
6231 void SetColors(WindowInfo *window, const char *textFg, const char *textBg,
6232 const char *selectFg, const char *selectBg, const char *hiliteFg,
6233 - const char *hiliteBg, const char *lineNoFg, const char *cursorFg);
6234 + const char *hiliteBg, const char *lineNoFg, const char *cursorFg,
6235 + const char* wrapMarginFg, const char* cursorlineBg);
6236 void SetOverstrike(WindowInfo *window, int overstrike);
6237 void SetAutoWrap(WindowInfo *window, int state);
6238 +void SetWrapMargin(WindowInfo *window, int margin);
6239 +void SetShowWrapMargin(WindowInfo *window, int state);
6240 void SetAutoScroll(WindowInfo *window, int margin);
6241 void SplitPane(WindowInfo *window);
6242 Widget GetPaneByIndex(WindowInfo *window, int paneIndex);
6243 int WidgetToPaneIndex(WindowInfo *window, Widget w);
6244 void ClosePane(WindowInfo *window);
6245 @@ -102,6 +105,7 @@ void SortTabBar(WindowInfo *window);
6246 void SetBacklightChars(WindowInfo *window, char *applyBacklightTypes);
6247 void SetToggleButtonState(WindowInfo *window, Widget w, Boolean state,
6248 Boolean notify);
6249 void SetSensitive(WindowInfo *window, Widget w, Boolean sensitive);
6250 void CleanUpTabBarExposeQueue(WindowInfo *window);
6251 +void ChangeLastFocus(WindowInfo *window, Widget text);
6252 #endif /* NEDIT_WINDOW_H_INCLUDED */
6253 diff --quilt old/util/fileUtils.c new/util/fileUtils.c
6254 --- old/util/fileUtils.c
6255 +++ new/util/fileUtils.c
6256 @@ -83,11 +83,11 @@ static void copyThruSlash(char **toStrin
6259 ** Decompose a Unix file name into a file name and a path.
6260 ** Return non-zero value if it fails, zero else.
6261 ** For now we assume that filename and pathname are at
6262 -** least MAXPATHLEN chars long.
6263 +** most MAXPATHLEN chars long.
6264 ** To skip setting filename or pathname pass NULL for that argument.
6267 ParseFilename(const char *fullname, char *filename, char *pathname)
6269 diff --quilt old/util/getfiles.c new/util/getfiles.c
6270 --- old/util/getfiles.c
6271 +++ new/util/getfiles.c
6272 @@ -6,11 +6,11 @@ static const char CVSID[] = "$Id: getfil
6273 * Copyright (C) 1999 Mark Edel *
6275 * This is free software; you can redistribute it and/or modify it under the *
6276 * terms of the GNU General Public License as published by the Free Software *
6277 * Foundation; either version 2 of the License, or (at your option) any later *
6278 -* version. In addition, you may distribute version of this program linked to *
6279 +* version. In addition, you may distribute versions of this program linked to *
6280 * Motif or Open Motif. See README for details. *
6282 * This software is distributed in the hope that it will be useful, but WITHOUT *
6283 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
6284 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
6285 @@ -35,23 +35,19 @@ static const char CVSID[] = "$Id: getfil
6286 * a directory when no filename was specified *
6287 * 6/24/92 by MWE: Made filename list and directory list typeable, *
6288 * set initial focus to filename list *
6289 * 6/25/93 by JMK: Fix memory leaks found by Purify. *
6291 -* Included are two routines written using Motif for accessing files: *
6292 -* *
6293 -* GetExistingFilename presents a FileSelectionBox dialog where users can *
6294 -* choose an existing file to open. *
6295 -* *
6296 *******************************************************************************/
6298 #ifdef HAVE_CONFIG_H
6299 #include "../config.h"
6300 #endif
6302 -#include "getfiles.h"
6303 +#include "DialogF.h"
6304 #include "fileUtils.h"
6305 +#include "getfiles.h"
6306 #include "misc.h"
6308 #include <stdio.h>
6309 #include <stdlib.h>
6310 #include <string.h>
6311 @@ -73,15 +69,19 @@ static const char CVSID[] = "$Id: getfil
6313 #include <X11/keysym.h>
6314 #include <Xm/Xm.h>
6315 #include <Xm/FileSB.h>
6316 #include <Xm/Form.h>
6317 +#include <Xm/Label.h>
6318 #include <Xm/List.h>
6319 #include <Xm/MessageB.h>
6320 +#include <Xm/PushB.h>
6321 #include <Xm/PushBG.h>
6322 -#include <Xm/Text.h>
6323 +#include <Xm/RowColumn.h>
6324 #include <Xm/TextF.h>
6325 +#include <Xm/Text.h>
6326 +#include <Xm/ToggleB.h>
6328 #ifdef HAVE_DEBUG_H
6329 #include "../debug.h"
6330 #endif
6332 @@ -93,26 +93,29 @@ static const char CVSID[] = "$Id: getfil
6333 #define MAX_LIST_KESTROKE_WAIT 2000 /* Allowable delay in milliseconds
6334 between characters typed to a list
6335 before starting over (throwing
6336 out the accumulated characters */
6338 +#define HFSB_OK 1 /* Get Filename OK constant */
6339 +#define HFSB_CANCEL 2 /* Get Filename Cancel constant */
6341 #define SET_ONE_RSRC(widget, name, newValue) \
6343 static Arg tmpargs[1] = {{name, (XtArgVal)0}}; \
6344 tmpargs[0].value = (XtArgVal)newValue; \
6345 XtSetValues(widget, tmpargs, 1); \
6349 enum yesNoValues {ynNone, ynYes, ynNo};
6351 /* Saved default directory and pattern from last successful call */
6352 static XmString DefaultDirectory = NULL;
6353 static XmString DefaultPattern = NULL;
6355 -/* User settable option for leaving the file name text field in
6356 - GetExistingFilename dialogs. Off by default so new users will get
6357 - used to typing in the list rather than in the text field */
6358 +/* User settable option for leaving the file name text field in file
6359 + dialogs. Off by default so new users will get used to typing in the
6360 + list rather than in the text field */
6361 static int RemoveRedundantTextField = True;
6363 /* Text for help button help display */
6364 /* ... needs variant for VMS */
6365 #ifndef SGI_CUSTOM
6366 @@ -131,11 +134,14 @@ If you use the filter field, remember to
6367 either a file name, \"*\" is acceptable, or a trailing \"/\". If \
6368 you don't, the name after the last \"/\" is interpreted as the file name to \
6369 match. When you leave off the file name or trailing \"/\", you won't see \
6370 any files to open in the list \
6371 because the filter specification matched the directory file itself, rather \
6372 -than the files in the directory.";
6373 +than the files in the directory.\n"
6374 +"\n"
6375 +"Hidden files and directories (those whose names begin with a dot) will only "
6376 +"be shown if the 'Show hidden Files' button is activated.";
6378 static const char *HelpNew =
6379 "This dialog allows you to create a new file, or to save the current file \
6380 under a new name. To specify a file \
6381 name in the current directory, complete the name displayed in the \"Save File \
6382 @@ -151,11 +157,14 @@ to move around in the file system hierar
6383 directory names in the list, or selecting them and pressing the \
6384 \"Filter\" button will select that directory. To move upwards \
6385 in the directory tree, double \
6386 click on the directory entry ending in \"..\". You can also move directly \
6387 to a directory by typing the file specification of the path in the \"Filter\" \
6388 -field and pressing the \"Filter\" button.";
6389 +field and pressing the \"Filter\" button."
6390 +"\n"
6391 +"Hidden files and directories (those whose names begins with a dot) will only "
6392 +"be shown if the 'Show hidden Files' button is activated.";
6394 #else /* SGI_CUSTOM */
6395 static const char *HelpExist =
6396 "The \"File to Edit:\" field shows a list of directories and files in the \
6397 current directory.\n\
6398 @@ -175,11 +184,14 @@ will accept icons dragged from the deskt
6399 arrows, to the right, of the field recalls previously selected \
6400 directories.\n\
6402 The \"Filter\" button allows you to narrow down the list of files and \
6403 directories shown in the \"File to Edit:\" field. The default filter of \
6404 -\"*\" allows all files to be listed.";
6405 +\"*\" allows all files to be listed."
6406 +"\n"
6407 +"Hidden files and directories (those whose names begins with a dot) will only "
6408 +"be shown if the 'Show hidden Files' button is activated.";
6410 static const char *HelpNew =
6411 "This dialog allows you to create a new file or to save the current file \
6412 under a new name.\n\
6414 @@ -206,15 +218,20 @@ will accept icons dragged from the deskt
6415 arrows, to the right, of the field recalls previously selected \
6416 directories.\n\
6418 The \"Filter\" button allows you to narrow down the list of files and \
6419 directories shown in the \"Files\" field. The default filter of \
6420 -\"*\" allows all files to be listed.";
6421 -#endif /* SGI_CUSTOM */
6422 +\"*\" allows all files to be listed."
6423 +"\n"
6424 +"Hidden files and directories (those whose names begins with a dot) will only "
6425 +"be shown if the 'Show hidden Files' button is activated.";
6427 -/* Local Callback Routines and variables */
6428 +#endif /* SGI_CUSTOM */
6431 +** Local Callback Routines and variables
6433 static void newFileOKCB(Widget w, Boolean *client_data,
6434 XmFileSelectionBoxCallbackStruct *call_data);
6435 static void newFileCancelCB(Widget w, Boolean *client_data, caddr_t
6436 call_data);
6437 static void newHelpCB(Widget w, Widget helpPanel, caddr_t call_data);
6438 @@ -236,104 +253,441 @@ static void listCharEH(Widget w, XtPoint
6439 Boolean *continueDispatch);
6440 static void replacementDirSearchProc(Widget w, XtPointer searchData);
6441 static void replacementFileSearchProc(Widget w, XtPointer searchData);
6442 static void sortWidgetList(Widget listWidget);
6443 static int compareXmStrings(const void *string1, const void *string2);
6444 +static unsigned removeHiddenFiles(Widget listWidget);
6445 +static Boolean removeDotEntry(Widget listWidget);
6446 +static int isHiddenFile(const char* filename);
6447 +static int handleCustomExistFileSB(Widget existFileSB, char *filename);
6448 +static int handleCustomNewFileSB(Widget newFileSB, char *filename, char *defaultName);
6450 -static int SelectResult = GFN_CANCEL; /* Initialize results as cancel */
6451 +static int SelectResult = HFSB_CANCEL; /* Initialize results as cancel */
6452 static Widget YesNoDialog; /* "Overwrite?" dialog widget */
6453 static int YesNoResult; /* Result of overwrite dialog */
6454 static Widget ErrorDialog; /* Dialog widget for error msgs */
6455 static int ErrorDone; /* Flag to mark dialog completed */
6456 static void (*OrigDirSearchProc)(); /* Built in Motif directory search */
6457 static void (*OrigFileSearchProc)(); /* Built in Motif file search proc */
6458 +static void freeFileList(char** list);
6460 -/*
6461 - * Do the hard work of setting up a file selection dialog
6462 - */
6463 -Widget getFilenameHelper(Widget parent, char *promptString, char *filename,
6464 - int existing)
6466 - int n; /* number of arguments */
6467 - Arg args[MAX_ARGS]; /* arg list */
6468 - Widget fileSB; /* widget file select box */
6469 - XmString titleString; /* compound string for dialog title */
6470 +static Widget addUtilForm(const Widget fsd, const Boolean showHidden,
6471 + const Boolean haveFormatButtons, const Boolean isContWrapped,
6472 + Boolean* addWrap, int* fileFormat);
6473 +static void hiddenFilesCB(Widget widget, XtPointer client_data,
6474 + XtPointer call_data);
6475 +static void showOptionsCB(Widget pushButton, XtPointer client_data,
6476 + XtPointer call_data);
6477 +static void setFormatCB(Widget widget, XtPointer clientData, XtPointer callData);
6478 +static void addWrapCB(Widget w, XtPointer clientData, XtPointer callData);
6481 +** GetFilenameByDialog()
6483 +** Façade for file dialogs.
6485 +** TODO: Refactor the whole module
6486 +** TODO: The original saved/restored a default directory, but I don't see any
6487 +** adverse effects on OM 2.2.3 or Lesstif 0.95 by just skipping that
6488 +** part. Does this depend on the toolkit and/or version used?
6490 +gfbdValue* GetFilenameByDialog(const gfbdParams params)
6492 + /* Values */
6493 + gfbdValue* retValue;
6495 + /* widgets and other GUI stuff */
6496 + Widget fsd;
6497 + XmString titleString;
6499 + /* helpers */
6500 + unsigned n; /* arg list */
6501 + Arg args[MAX_ARGS]; /* arg list */
6502 + int rc; /* return code of handleCustomExistFileSB() */
6504 + /* Can probably be refactored away. */
6505 + fsbUserDataStruct userData;
6507 + /* some initialization */
6508 + retValue = (gfbdValue*) XtMalloc(sizeof(gfbdValue));
6509 + retValue->status = GFDB_ERROR;
6511 n = 0;
6512 - titleString = XmStringCreateSimple(promptString);
6513 + titleString = XmStringCreateLocalized(params.dialogTitle);
6514 XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
6515 XtSetArg(args[n], XmNdialogTitle, titleString); n++;
6516 - fileSB = CreateFileSelectionDialog(parent,"FileSelect",args,n);
6517 + XtSetArg(args[n], XmNresizePolicy, XmRESIZE_GROW); n++;
6518 + fsd = CreateFileSelectionDialog(params.parentShell, "fsd", args, n);
6519 XmStringFree(titleString);
6520 -#ifndef SGI_CUSTOM
6521 - if (existing && RemoveRedundantTextField)
6522 - XtUnmanageChild(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_TEXT));
6523 - XtUnmanageChild(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_SELECTION_LABEL));
6525 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_FILTER_LABEL),
6526 + /* Put mnemonic on labels; this will put the focus in the labeled widget
6527 + if activated. See misc.c:findAndActivateMnemonic() for details. */
6528 + XtVaSetValues(XmFileSelectionBoxGetChild(fsd, XmDIALOG_FILTER_LABEL),
6529 XmNmnemonic, 'l',
6530 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_FILTER_TEXT),
6531 + XmNuserData, XmFileSelectionBoxGetChild(fsd, XmDIALOG_FILTER_TEXT),
6532 NULL);
6533 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST_LABEL),
6534 + XtVaSetValues(XmFileSelectionBoxGetChild(fsd, XmDIALOG_DIR_LIST_LABEL),
6535 XmNmnemonic, 'D',
6536 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST),
6537 + XmNuserData, XmFileSelectionBoxGetChild(fsd, XmDIALOG_DIR_LIST),
6538 + NULL);
6539 + XtVaSetValues(XmFileSelectionBoxGetChild(fsd, XmDIALOG_LIST_LABEL),
6540 + XmNmnemonic, 'F',
6541 + XmNuserData, XmFileSelectionBoxGetChild(fsd, XmDIALOG_LIST),
6542 + NULL);
6543 + /* The last mnemonic originally used strspn() to find the last mnemonic,
6544 + but used the dialog's title instead of the list's label. Since it broke
6545 + user's GUI expectations I replaced it with a plain letter. */
6547 + /* Unmanage text field and label unless a label is given. */
6548 + if (NULL == params.textfieldLabel) {
6549 + XtUnmanageChild(XmFileSelectionBoxGetChild(fsd, XmDIALOG_TEXT));
6550 + XtUnmanageChild(XmFileSelectionBoxGetChild(fsd, XmDIALOG_SELECTION_LABEL));
6551 + } else {
6552 + XmString labelString = XmStringCreateLocalized(params.textfieldLabel);
6554 + XtVaSetValues(XmFileSelectionBoxGetChild(fsd, XmDIALOG_SELECTION_LABEL),
6555 + XmNlabelString, labelString,
6556 + NULL);
6557 + XtVaSetValues(XmFileSelectionBoxGetChild(fsd, XmDIALOG_SELECTION_LABEL),
6558 + XmNmnemonic, params.textfieldLabel[strspn(params.textfieldLabel, "lDF")],
6559 + XmNuserData, XmFileSelectionBoxGetChild(fsd, XmDIALOG_TEXT),
6560 + NULL);
6561 + XmStringFree(labelString);
6564 + retValue->fileFormat = params.fileFormat;
6565 + addUtilForm(fsd, params.showHidden, params.haveFormatButtons,
6566 + params.isContWrapped, &(retValue->addWrap), &(retValue->fileFormat));
6568 + /* Do the mnemonic magic. Wait until all mnemonics are prepared. */
6569 + AddDialogMnemonicHandler(fsd, FALSE);
6571 + /* Fix some ancient hardware/toolkit quirks. */
6572 + RemapDeleteKey(XmFileSelectionBoxGetChild(fsd, XmDIALOG_FILTER_TEXT));
6573 + RemapDeleteKey(XmFileSelectionBoxGetChild(fsd, XmDIALOG_TEXT));
6575 + userData.showHidden = params.showHidden;
6576 + XtVaSetValues(fsd, XmNuserData, &userData, NULL);
6578 + /* Refactor this. */
6579 + if (params.fileExists) {
6580 + rc = handleCustomExistFileSB(fsd, retValue->payload);
6581 + } else {
6582 + rc = handleCustomNewFileSB(fsd, retValue->payload, params.defaultName);
6585 + switch(rc) {
6586 + case HFSB_OK:
6587 + retValue->status = GFDB_OK;
6588 + break;
6589 + case HFSB_CANCEL:
6590 + retValue->status = GFDB_CANCEL;
6591 + break;
6592 + default:
6593 + /* fallback */
6594 + strncpy(retValue->payload, "Something murphied in GetFilenameByDialog, sorry.", MAXPATHLEN);
6595 + retValue->status = GFDB_ERROR;
6596 + break;
6599 + return retValue;
6603 +** Helper for GetFilenameByDialog()
6605 +** Note: Since mnemonics are set here, wait with your call to activate them
6606 +** via AddDialogMnemonicHandler() until this is done.
6608 +** TODO: The reliance on AddDialogMnemonicHandler() (called in the caller
6609 +** after addUtilForm()) breaks low coupling.
6611 +static Widget addUtilForm(const Widget fsd, const Boolean showHidden,
6612 + const Boolean haveFormatButtons, const Boolean isContWrapped,
6613 + Boolean* addWrap, int* fileFormat)
6615 + Widget utilForm; /* form containing utility widgets */
6616 + Widget optionsForm; /* container for option widgets */
6618 + Widget showOptionsCheckBox; /* (un)display additional options */
6619 + Widget showOptionsPushButton; /* (un)display additional options */
6620 + XmString showOptionsLabel; /* PushButton label */
6622 + Widget hiddenFilesCheckBox; /* (un)displaying hidden files */
6623 + Widget hiddenFilesToggleButton; /* (un)displaying hidden files */
6624 + XmString hiddenFilesLabel; /* ToggleButton label */
6626 + Widget formatBtnsRow;
6627 + Widget unixFormatButton, dosFormatButton, macFormatButton;
6628 + Widget wrapToggle;
6629 + Widget topWidget = NULL;
6631 + XmString s1 = NULL;
6633 + /* Creates a Form containing additional widgets */
6634 + utilForm = XtVaCreateManagedWidget("utilForm", xmFormWidgetClass, fsd, NULL);
6636 + /* Creates a RowColumn containing a PushButton to (un)display the
6637 + other options. */
6638 + showOptionsCheckBox = XtVaCreateManagedWidget("showOptionsCheckBox",
6639 + xmRowColumnWidgetClass, utilForm,
6640 + NULL);
6641 + showOptionsLabel = XmStringCreateLocalized("Less...");
6642 + showOptionsPushButton = XtVaCreateManagedWidget("showOptionsPushButton",
6643 + xmPushButtonWidgetClass, showOptionsCheckBox,
6644 + XmNmnemonic, 'M',
6645 + XmNlabelString, showOptionsLabel,
6646 + XmNuserData, 1,
6647 + NULL);
6648 + XmStringFree(showOptionsLabel);
6649 + XtAddCallback(showOptionsPushButton,
6650 + XmNactivateCallback, showOptionsCB,
6651 + (XtPointer) &fsd);
6653 + /* Creates a Form containing all options. */
6654 + optionsForm = XtVaCreateManagedWidget("optionsForm",
6655 + xmFormWidgetClass, utilForm,
6656 + XmNtopAttachment, XmATTACH_WIDGET,
6657 + XmNtopWidget, showOptionsCheckBox,
6658 + XmNbottomAttachment, XmATTACH_FORM,
6659 + XmNleftAttachment, XmATTACH_FORM,
6660 + XmNrightAttachment, XmATTACH_FORM,
6661 + NULL);
6663 + /* Adds format buttons. */
6664 + if (haveFormatButtons) {
6665 + /* Create RowColumn containing a number of push buttons for file format. */
6666 + formatBtnsRow = XtVaCreateManagedWidget("formatBtnsRow",
6667 + xmRowColumnWidgetClass, optionsForm,
6668 + XmNradioBehavior, XmONE_OF_MANY,
6669 + XmNorientation, XmHORIZONTAL,
6670 + XmNpacking, XmPACK_TIGHT,
6671 + XmNtopAttachment, XmATTACH_FORM,
6672 + XmNleftAttachment, XmATTACH_FORM,
6673 + NULL);
6675 + XtVaCreateManagedWidget("formatBtns",
6676 + xmLabelWidgetClass, formatBtnsRow,
6677 + XmNlabelString, s1 = XmStringCreateSimple("Format:"),
6678 + NULL);
6679 + XmStringFree(s1);
6681 + unixFormatButton = XtVaCreateManagedWidget("unixFormat",
6682 + xmToggleButtonWidgetClass, formatBtnsRow,
6683 + XmNlabelString, s1 = XmStringCreateSimple("Unix"),
6684 + XmNset, UNIX_FILE_FORMAT == *fileFormat,
6685 + XmNuserData, (XtPointer) UNIX_FILE_FORMAT,
6686 + XmNmarginHeight, 0,
6687 + XmNalignment, XmALIGNMENT_BEGINNING,
6688 + XmNmnemonic, 'U',
6689 + NULL);
6690 + XmStringFree(s1);
6691 + XtAddCallback(unixFormatButton, XmNvalueChangedCallback, setFormatCB,
6692 + fileFormat);
6694 + dosFormatButton = XtVaCreateManagedWidget("dosFormat",
6695 + xmToggleButtonWidgetClass, formatBtnsRow,
6696 + XmNlabelString, s1 = XmStringCreateSimple("DOS"),
6697 + XmNset, DOS_FILE_FORMAT == *fileFormat,
6698 + XmNuserData, (XtPointer) DOS_FILE_FORMAT,
6699 + XmNmarginHeight, 0,
6700 + XmNalignment, XmALIGNMENT_BEGINNING,
6701 + XmNmnemonic, 'O',
6702 + NULL);
6703 + XmStringFree(s1);
6704 + XtAddCallback(dosFormatButton, XmNvalueChangedCallback, setFormatCB,
6705 + fileFormat);
6707 + macFormatButton = XtVaCreateManagedWidget("macFormat",
6708 + xmToggleButtonWidgetClass, formatBtnsRow,
6709 + XmNlabelString, s1 = XmStringCreateSimple("Macintosh"),
6710 + XmNset, MAC_FILE_FORMAT == *fileFormat,
6711 + XmNuserData, (XtPointer) MAC_FILE_FORMAT,
6712 + XmNmarginHeight, 0,
6713 + XmNalignment, XmALIGNMENT_BEGINNING,
6714 + XmNmnemonic, 'M',
6715 + NULL);
6716 + XmStringFree(s1);
6717 + XtAddCallback(macFormatButton, XmNvalueChangedCallback, setFormatCB,
6718 + fileFormat);
6720 + if (isContWrapped) {
6721 + wrapToggle = XtVaCreateManagedWidget("addWrap",
6722 + xmToggleButtonWidgetClass, optionsForm,
6723 + XmNlabelString,
6724 + s1 = XmStringCreateSimple("Add line breaks where wrapped"),
6725 + XmNalignment, XmALIGNMENT_BEGINNING,
6726 + XmNmnemonic, 'A',
6727 + XmNtopAttachment, XmATTACH_WIDGET,
6728 + XmNtopWidget, formatBtnsRow,
6729 + XmNleftAttachment, XmATTACH_FORM, NULL);
6730 + XtAddCallback(wrapToggle, XmNvalueChangedCallback, addWrapCB, addWrap);
6731 + XmStringFree(s1);
6733 + topWidget = wrapToggle;
6734 + } else {
6735 + topWidget = formatBtnsRow;
6739 + /* Creates a RowColumn containing a ToggleButton to show/hide
6740 + hidden files in the file lists. */
6741 + hiddenFilesCheckBox = XtVaCreateManagedWidget("hiddenFilesCheckBox",
6742 + xmRowColumnWidgetClass,
6743 + optionsForm,
6744 + XmNtopAttachment, XmATTACH_WIDGET,
6745 + XmNtopWidget, topWidget,
6746 + XmNbottomAttachment, XmATTACH_FORM,
6747 + XmNleftAttachment, XmATTACH_FORM,
6748 + XmNrightAttachment, XmATTACH_FORM,
6749 NULL);
6750 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST_LABEL),
6751 - XmNmnemonic, promptString[strspn(promptString, "lD")],
6752 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST),
6753 + hiddenFilesLabel = XmStringCreateLocalized("Show hidden Files");
6754 + hiddenFilesToggleButton = XtVaCreateManagedWidget("hiddenFilesToggleButton",
6755 + xmToggleButtonWidgetClass,
6756 + hiddenFilesCheckBox,
6757 + XmNmnemonic, 'h',
6758 + XmNlabelString, hiddenFilesLabel,
6759 + XmNset, showHidden,
6760 NULL);
6761 - AddDialogMnemonicHandler(fileSB, FALSE);
6762 - RemapDeleteKey(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_FILTER_TEXT));
6763 - RemapDeleteKey(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_TEXT));
6764 + XmStringFree(hiddenFilesLabel);
6765 + XtAddCallback(hiddenFilesToggleButton,
6766 + XmNvalueChangedCallback, hiddenFilesCB,
6767 + (XtPointer) &fsd);
6769 + return optionsForm;
6773 +** Callback for hiddenFilesToggleButton
6774 +** The ToggleButton's state is saved in the FileSelectionBox' XmNuserData
6775 +** field, so that it can be used in the XmN*searchProcs.
6777 +static void hiddenFilesCB(Widget widget,
6778 + XtPointer client_data,
6779 + XtPointer call_data)
6781 + XmToggleButtonCallbackStruct* state =
6782 + (XmToggleButtonCallbackStruct *) call_data;
6783 + Widget* fsbParent = (Widget*) client_data;
6784 + fsbUserDataStruct* userData;
6786 + /* Remember the button's setting for the sort routines */
6787 + XtVaGetValues(*fsbParent, XmNuserData, &userData, NULL);
6788 + userData->showHidden = state->set;
6790 +#if XmVERSION >= 2
6791 + /* This will take care of the the Motif FSB resource fileFilterStyle. It
6792 + is still honored by NEdit by using it to override the compiled-in
6793 + default (see source/preferences.c, initPrefDefaultsFromResources()),
6794 + but the internal resource will override it. */
6796 + int fileFilterStyle =
6797 + (state->set ? XmFILTER_NONE : XmFILTER_HIDDEN_FILES);
6798 + XtVaSetValues(*fsbParent, XmNfileFilterStyle, fileFilterStyle, NULL);
6800 #endif
6801 - return fileSB;
6803 + /* Reinitialize lists */
6804 + XmFileSelectionDoSearch(*fsbParent, NULL);
6808 +** Callback for showOptionsPushButton
6810 +** client_data ist supposed to carry a pointer to the FSB
6812 +static void showOptionsCB(Widget pushButton,
6813 + XtPointer client_data,
6814 + XtPointer call_data)
6816 + Boolean isShown;
6817 + XmString buttonLabel;
6818 + Widget* fsb = (Widget*) client_data;
6819 + Dimension optionFormHeight;
6820 + Widget optionsForm = XtNameToWidget(*fsb, "*optionsForm");
6821 + Dimension fsbHeight;
6823 + XtVaGetValues(pushButton, XmNuserData, &isShown, NULL);
6825 + /* Get initial size of FSB */
6826 + XtVaGetValues(*fsb, XmNheight, &fsbHeight, NULL);
6828 + if (isShown) {
6829 + isShown = False;
6831 + /* We change the size here because the Less/More button should
6832 + stay under the mouse pointer. */
6833 + XtVaGetValues(optionsForm, XmNheight, &optionFormHeight, NULL);
6834 + XtUnmanageChild(optionsForm);
6835 + XtVaSetValues(*fsb, XmNheight, fsbHeight - optionFormHeight, NULL);
6837 + /* FIXME: Is this a leak? Do we have to delete the old string? */
6838 + buttonLabel = XmStringCreateLocalized("More...");
6839 + XtVaSetValues(pushButton, XmNlabelString, buttonLabel, NULL);
6840 + XmStringFree(buttonLabel);
6841 + } else {
6842 + isShown = True;
6844 + /* We change the size here because the Less/More button should
6845 + stay under the mouse pointer. */
6846 + XtManageChild(optionsForm);
6847 + XtVaGetValues(optionsForm, XmNheight, &optionFormHeight, NULL);
6848 + XtVaSetValues(*fsb, XmNheight, fsbHeight + optionFormHeight, NULL);
6850 + /* FIXME: Is this a leak? Do we have to delete the old string? */
6851 + buttonLabel = XmStringCreateLocalized("Less...");
6852 + XtVaSetValues(pushButton, XmNlabelString, buttonLabel, NULL);
6853 + XmStringFree(buttonLabel);
6856 + XtVaSetValues(pushButton, XmNuserData, isShown, NULL);
6859 -/* GetExistingFilename */
6860 -/* */
6861 -/* This routine will popup a file selection box so that the user can */
6862 -/* select an existing file from the scrollable list. The user is */
6863 -/* prevented from entering a new filename because the edittable text */
6864 -/* area of the file selection box widget is unmanaged. After the user */
6865 -/* selects a file, GetExistingFilename returns the selected filename and */
6866 -/* GFN_OK, indicating that the OK button was pressed. If the user */
6867 -/* pressed the cancel button, the return value is GFN_CANCEL, and the */
6868 -/* filename character string supplied in the call is not altered. */
6869 -/* */
6870 -/* Arguments: */
6871 -/* */
6872 -/* Widget parent - parent widget id */
6873 -/* char * promptString - prompt string */
6874 -/* char * filename - a string to receive the selected filename */
6875 -/* (this string will not be altered if the */
6876 -/* user pressed the cancel button) */
6877 -/* */
6878 -/* Returns: GFN_OK - file was selected and OK button pressed */
6879 -/* GFN_CANCEL - Cancel button pressed and no returned file */
6880 -/* */
6881 -int GetExistingFilename(Widget parent, char *promptString, char *filename)
6883 - Widget existFileSB = getFilenameHelper(parent, promptString, filename,
6884 - True);
6885 - return HandleCustomExistFileSB(existFileSB, filename);
6888 -/* GetNewFilename
6890 - * Same as GetExistingFilename but pick a new file instead of an existing one.
6891 - * In this case the text area of the FSB is *not* unmanaged, so the user can
6892 - * enter a new filename.
6893 - */
6894 -int GetNewFilename(Widget parent, char *promptString, char *filename,
6895 - char *defaultName)
6897 +** Callback procedure for toggle button requesting newlines to be inserted
6898 +** to emulate continuous wrapping.
6900 +static void addWrapCB(Widget w, XtPointer clientData, XtPointer callData)
6902 - Widget fileSB = getFilenameHelper(parent, promptString, filename, False);
6903 - return HandleCustomNewFileSB(fileSB, filename, defaultName);
6904 + int resp;
6905 + int *addWrap = (int *)clientData;
6907 + if (XmToggleButtonGetState(w)) {
6908 + resp = DialogF(DF_WARN, w, 2, "Add Wrap",
6909 + "This operation adds permanent line breaks to\n"
6910 + "match the automatic wrapping done by the\n"
6911 + "Continuous Wrap mode Preferences Option.\n\n"
6912 + "*** This Option is Irreversable ***\n\n"
6913 + "Once newlines are inserted, continuous wrapping\n"
6914 + "will no longer work automatically on these lines", "OK",
6915 + "Cancel");
6916 + if (1 == resp) {
6917 + *addWrap = True;
6918 + } else {
6919 + XmToggleButtonSetState(w, False, False);
6920 + *addWrap = False;
6922 + } else {
6923 + *addWrap = False;
6928 -** HandleCustomExistFileSB
6929 +** Callback procedure for File Format toggle buttons. Format is stored
6930 +** in userData field of widget button
6932 +static void setFormatCB(Widget widget, XtPointer clientData, XtPointer callData)
6934 + if (XmToggleButtonGetState(widget)) {
6935 + XtPointer userData;
6936 + XtVaGetValues(widget, XmNuserData, &userData, NULL);
6937 + *((int*) clientData) = (int) userData;
6942 +** handleCustomExistFileSB
6944 ** Manage a customized file selection box for opening existing files.
6945 ** Use this if you want to change the standard file selection dialog
6946 ** from the defaults provided in GetExistingFilename, but still
6947 ** want take advantage of the button processing, help messages, and
6948 @@ -344,23 +698,24 @@ int GetNewFilename(Widget parent, char *
6949 ** Widget existFileSB - your custom file selection box widget id
6950 ** char * filename - a string to receive the selected filename
6951 ** (this string will not be altered if the
6952 ** user pressed the cancel button)
6954 -** Returns: GFN_OK - file was selected and OK button pressed
6955 -** GFN_CANCEL - Cancel button pressed and no returned file
6956 +** Returns: HFSB_OK - file was selected and OK button pressed
6957 +** HFSB_CANCEL - Cancel button pressed and no returned file
6960 -int HandleCustomExistFileSB(Widget existFileSB, char *filename)
6961 +int handleCustomExistFileSB(Widget existFileSB, char *filename)
6963 Boolean done_with_dialog=False; /* ok to destroy dialog flag */
6964 char *fileString; /* C string for file selected */
6965 char *dirString; /* C string for dir of file selected */
6966 XmString cFileString; /* compound string for file selected */
6967 XmString cDir; /* compound directory selected */
6968 XmString cPattern; /* compound filter pattern */
6969 Widget help; /* help window form dialog */
6970 + fsbUserDataStruct* userData;
6971 #if XmVersion < 1002
6972 int i;
6973 #endif
6975 XtAddCallback(existFileSB, XmNokCallback, (XtCallbackProc)existOkCB,
6976 @@ -382,10 +737,17 @@ int HandleCustomExistFileSB(Widget exist
6977 #if XmVersion >= 1002
6978 XtVaSetValues(existFileSB, XmNinitialFocus, XtParent(
6979 XmFileSelectionBoxGetChild(existFileSB, XmDIALOG_LIST)), NULL);
6980 #endif
6981 #endif
6983 + XtVaGetValues(existFileSB, XmNuserData, &userData, NULL);
6984 + /* FIXME: The nice hidden file patch is broken by Nate's non-factoring. */
6985 + userData->cachedDirList = NULL;
6986 + userData->cachedFileList = NULL;
6987 + XtVaSetValues(existFileSB, XmNuserData, userData, NULL);
6989 ManageDialogCenteredOnPointer(existFileSB);
6991 #ifndef SGI_CUSTOM
6992 /* Typing in the directory list is dependent on the list being in the
6993 same form of alphabetical order expected by the character processing
6994 @@ -413,11 +775,11 @@ int HandleCustomExistFileSB(Widget exist
6995 #endif /* SGI_CUSTOM */
6997 while (!done_with_dialog)
6998 XtAppProcessEvent(XtWidgetToApplicationContext(existFileSB), XtIMAll);
7000 - if (SelectResult == GFN_OK) {
7001 + if (SelectResult == HFSB_OK) {
7002 XtVaGetValues(existFileSB, XmNdirSpec, &cFileString, XmNdirectory,
7003 &cDir, XmNpattern, &cPattern, NULL);
7004 /* Undocumented: file selection box widget allocates copies of these
7005 strings on getValues calls. I have risked freeing them to avoid
7006 memory leaks, since I assume other developers have made this same
7007 @@ -457,16 +819,20 @@ int HandleCustomExistFileSB(Widget exist
7008 be necessary as the shell is destroyed automatically when the dialog
7009 is. However, due to a bug in various Lesstif versions, the latter
7010 messes up the grab cascades and leaves new windows without grabs, such
7011 that they appear to be frozen. */
7012 XtDestroyWidget(XtParent(existFileSB));
7014 + freeFileList(userData->cachedDirList);
7015 + freeFileList(userData->cachedFileList);
7017 return SelectResult;
7022 -** HandleCustomNewFileSB
7023 +** handleCustomNewFileSB
7025 ** Manage a customized file selection box for opening new files.
7027 ** Arguments:
7029 @@ -475,23 +841,24 @@ int HandleCustomExistFileSB(Widget exist
7030 ** (this string will not be altered if the
7031 ** user pressed the cancel button)
7032 ** char* defaultName - default name to be pre-entered in filename
7033 ** text field.
7035 -** Returns: GFN_OK - file was selected and OK button pressed
7036 -** GFN_CANCEL - Cancel button pressed and no returned file
7037 +** Returns: HFSB_OK - file was selected and OK button pressed
7038 +** HFSB_CANCEL - Cancel button pressed and no returned file
7041 -int HandleCustomNewFileSB(Widget newFileSB, char *filename, char *defaultName)
7042 +int handleCustomNewFileSB(Widget newFileSB, char *filename, char *defaultName)
7044 Boolean done_with_dialog=False; /* ok to destroy dialog flag */
7045 Widget help; /* help window form dialog */
7046 XmString cFileString; /* compound string for file selected */
7047 XmString cDir; /* compound directory selected */
7048 XmString cPattern; /* compound filter pattern */
7049 char *fileString; /* C string for file selected */
7050 char *dirString; /* C string for dir of file selected */
7051 + fsbUserDataStruct* userData;
7052 #if XmVersion < 1002
7053 int i;
7054 #endif
7056 XtAddCallback(newFileSB, XmNokCallback, (XtCallbackProc)newFileOKCB,
7057 @@ -520,10 +887,16 @@ int HandleCustomNewFileSB(Widget newFile
7058 if ( finder != NULL )
7059 XtVaSetValues(newFileSB, XmNinitialFocus, finder, NULL);
7061 #endif
7062 #endif
7064 + XtVaGetValues(newFileSB, XmNuserData, &userData, NULL);
7065 + userData->cachedDirList = NULL;
7066 + userData->cachedFileList = NULL;
7067 + XtVaSetValues(newFileSB, XmNuserData, userData, NULL);
7069 ManageDialogCenteredOnPointer(newFileSB);
7071 #ifndef SGI_CUSTOM
7072 #if XmVersion < 1002
7073 /* To give filename text initial focus, revoke default button status for
7074 @@ -571,11 +944,11 @@ int HandleCustomNewFileSB(Widget newFile
7077 while (!done_with_dialog)
7078 XtAppProcessEvent (XtWidgetToApplicationContext(newFileSB), XtIMAll);
7080 - if (SelectResult == GFN_OK) {
7081 + if (SelectResult == HFSB_OK) {
7082 /* See note in existing file routines about freeing the values
7083 obtained in the following call */
7084 XtVaGetValues(newFileSB, XmNdirSpec, &cFileString, XmNdirectory,
7085 &cDir, XmNpattern, &cPattern, NULL);
7086 if (DefaultDirectory != NULL) XmStringFree(DefaultDirectory);
7087 @@ -603,10 +976,14 @@ int HandleCustomNewFileSB(Widget newFile
7089 XmStringFree(cFileString);
7090 XtFree(fileString);
7092 XtDestroyWidget(newFileSB);
7094 + freeFileList(userData->cachedDirList);
7095 + freeFileList(userData->cachedFileList);
7097 return SelectResult;
7101 ** Return current default directory used by GetExistingFilename.
7102 @@ -663,11 +1040,11 @@ void SetFileDialogDefaultPattern(char *p
7103 XmStringFree(DefaultPattern);
7104 DefaultPattern = pattern==NULL ? NULL : XmStringCreateSimple(pattern);
7108 -** Turn on or off the text fiend in the GetExistingFilename file selection
7109 +** Turn on or off the text field in the GetExistingFilename file selection
7110 ** box, where users can enter the filename by typing. This is redundant
7111 ** with typing in the list, and leads users who are new to nedit to miss
7112 ** the more powerful feature in favor of changing the focus and typing
7113 ** in the text field.
7115 @@ -791,11 +1168,11 @@ static void newFileOKCB(Widget w, Boolea
7116 int length; /* length of file name */
7117 int response; /* response to dialog */
7118 struct stat buf; /* status from fstat */
7120 XmStringGetLtoR(call_data->value, XmSTRING_DEFAULT_CHARSET, &filename);
7121 - SelectResult = GFN_OK;
7122 + SelectResult = HFSB_OK;
7123 length = strlen(filename);
7124 if (length == 0 || filename[length-1] == '/') {
7125 doErrorDialog("Please supply a name for the file", NULL);
7126 XtFree(filename);
7127 return;
7128 @@ -842,11 +1219,11 @@ static void newFileOKCB(Widget w, Boolea
7132 static void newFileCancelCB(Widget w, Boolean *client_data, caddr_t call_data)
7134 - SelectResult = GFN_CANCEL;
7135 + SelectResult = HFSB_CANCEL;
7136 *client_data = True;
7139 static void newHelpCB(Widget w, Widget helpPanel, caddr_t call_data)
7141 @@ -859,11 +1236,11 @@ static void existOkCB(Widget w, Boolean
7142 char *filename; /* name of chosen file */
7143 int fd; /* file descriptor */
7144 int length; /* length of file name */
7146 XmStringGetLtoR(call_data->value, XmSTRING_DEFAULT_CHARSET, &filename);
7147 - SelectResult = GFN_OK;
7148 + SelectResult = HFSB_OK;
7149 length = strlen(filename);
7150 if (length == 0 || filename[length-1] == '/') {
7151 doErrorDialog("Please select a file to open", NULL);
7152 XtFree(filename);
7153 return;
7154 @@ -879,11 +1256,11 @@ static void existOkCB(Widget w, Boolean
7158 static void existCancelCB(Widget w, Boolean * client_data, caddr_t call_data)
7160 - SelectResult = GFN_CANCEL;
7161 + SelectResult = HFSB_CANCEL;
7162 *client_data = True; /* done with dialog */
7165 static void yesNoOKCB(Widget w, caddr_t client_data, caddr_t call_data)
7167 @@ -1066,40 +1443,115 @@ static void listCharEH(Widget w, XtPoint
7168 ** and should be removed. These routines also leak memory like a seive,
7169 ** because Motif's inconsistent treatment of memory in list widgets does
7170 ** not allow us to free lists that we pass in, and most Motif versions
7171 ** don't clean it up properly.
7173 -static void replacementDirSearchProc(Widget w, XtPointer searchData)
7175 +static int restorePreviousList(Widget list, char** prevList)
7177 - Boolean updated;
7179 + int count = 0, i;
7181 + while (prevList[count]) {
7182 + ++count;
7184 + XmListDeleteAllItems(list);
7186 + for (i = 0; i < count; ++i) {
7187 + XmString s;
7188 + XmListAddItem(list, s = XmStringCreateSimple(prevList[i]), i + 1);
7189 + XtFree(prevList[i]);
7190 + XmStringFree(s);
7192 + XtFree((char*) prevList);
7193 + return count;
7196 +static int saveCurrentList(Widget list, char*** saveList)
7198 + XmString *items;
7199 + int nItems, i;
7201 + XtVaGetValues(list, XmNitems, &items, XmNitemCount, &nItems, NULL);
7202 + *saveList = (char**) XtMalloc(sizeof(char*) * (nItems + 1));
7204 + for (i = 0; i < nItems; ++i) {
7205 + char* s;
7206 + XmStringGetLtoR(items[i], XmSTRING_DEFAULT_CHARSET, &s);
7207 + (*saveList)[i] = s;
7210 + (*saveList)[nItems] = 0;
7211 + return nItems;
7214 +static void replacementDirSearchProc(Widget fileSB, XtPointer searchData)
7216 + int fileCount, newFileCount;
7217 + fsbUserDataStruct* userData;
7219 + XtVaGetValues(fileSB, XmNuserData, &userData, NULL);
7221 + if (userData->cachedDirList) {
7222 + restorePreviousList(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST),
7223 + userData->cachedDirList);
7224 + userData->cachedDirList = NULL;
7227 /* Call the original search procedure to do the actual search */
7228 - (*OrigDirSearchProc)(w, searchData);
7229 - /* Refreshing a list clears the keystroke history, even if no update. */
7230 + (*OrigDirSearchProc)(fileSB, searchData);
7231 nKeystrokes = 0;
7232 - XtVaGetValues(w, XmNlistUpdated, &updated, NULL);
7233 - if (!updated)
7234 - return;
7237 + fileCount = saveCurrentList(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST),
7238 + &userData->cachedDirList);
7240 + if (userData->showHidden)
7242 + /* Remove '.' entry */
7243 + if (removeDotEntry(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST))) {
7244 + newFileCount = fileCount -1;
7245 + } else {
7246 + newFileCount = fileCount;
7249 + } else {
7250 + /* Remove hidden files from list */
7251 + removeHiddenFiles(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST));
7253 + XtVaSetValues(fileSB, XmNlistUpdated, True, NULL);
7255 /* Sort the items in the list */
7256 - sortWidgetList(XmFileSelectionBoxGetChild(w, XmDIALOG_DIR_LIST));
7257 + sortWidgetList(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST));
7260 -static void replacementFileSearchProc(Widget w, XtPointer searchData)
7261 +static void replacementFileSearchProc(Widget fileSB, XtPointer searchData)
7263 - Boolean updated;
7265 + int fileCount;
7266 + fsbUserDataStruct* userData;
7268 + XtVaGetValues(fileSB, XmNuserData, &userData, NULL);
7270 + if (userData->cachedFileList) {
7271 + restorePreviousList(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST),
7272 + userData->cachedFileList);
7273 + userData->cachedFileList = NULL;
7276 /* Call the original search procedure to do the actual search */
7277 - (*OrigFileSearchProc)(w, searchData);
7278 - /* Refreshing a list clears the keystroke history, even if no update. */
7279 + (*OrigFileSearchProc)(fileSB, searchData);
7280 nKeystrokes = 0;
7281 - XtVaGetValues(w, XmNlistUpdated, &updated, NULL);
7282 - if (!updated)
7283 - return;
7286 + fileCount = saveCurrentList(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST),
7287 + &userData->cachedFileList);
7289 + if (!userData->showHidden) {
7290 + /* Remove hidden files from list */
7291 + removeHiddenFiles(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST));
7293 + XtVaSetValues(fileSB, XmNlistUpdated, True, NULL);
7295 /* Sort the items in the list */
7296 - sortWidgetList(XmFileSelectionBoxGetChild(w, XmDIALOG_LIST));
7297 + sortWidgetList(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST));
7301 ** Sort the items in a list widget "listWidget"
7303 @@ -1132,5 +1584,160 @@ static int compareXmStrings(const void *
7304 result = strcmp(s1, s2);
7305 XtFree(s1);
7306 XtFree(s2);
7307 return result;
7311 +** Removes the '.' entry from a listWidget
7313 +** Preconditions:
7314 +** listWidget is an XmList containing filenames
7316 +** Postcondition:
7317 +** first dotEntry in listWidget is removed
7319 +static Boolean removeDotEntry(Widget listWidget)
7321 + /* Items currently in the listWidget */
7322 + XmString* items;
7323 + int nItems;
7325 + int i;
7327 + /* read values in List into array. */
7328 + XtVaGetValues(listWidget,
7329 + XmNitems, &items,
7330 + XmNitemCount, &nItems,
7331 + NULL);
7333 + /* Traverse over items; for every item, check whether it's the dotfile;
7334 + if yes, delete it and return True. */
7335 + for (i = 0; i < nItems; i++) {
7336 + /* C string of current list item */
7337 + char* filename;
7339 + /* basename of current list item */
7340 + char basename[MAXPATHLEN + 1];
7342 + /* Convert Motif compound string to C string */
7343 + XmStringGetLtoR(items[i], XmSTRING_DEFAULT_CHARSET, &filename);
7345 + /* Get basename from list item */
7346 + ParseFilename(filename, basename, NULL);
7348 + /* Free C string, allocated by XmStringGetLtoR(). */
7349 + XtFree(filename);
7351 + /* if this is the dotEntry... */
7352 + if (0 == strcmp(basename, ".")) {
7353 + /* ...delete it and break. */
7354 + XmListDeletePos(listWidget, i + 1);
7355 + return True;
7359 + return False;
7363 +** Removes hidden files from an XmList. Hidden files are all list entries
7364 +** which are recognized as such by isHiddenFile().
7366 +** Preconditions:
7367 +** listWidget is an XmList containing filenames
7368 +** 'int isHiddenFile(const char* fullname)' exists and works.
7370 +** Postcondition:
7371 +** Hidden files in listWidget are removed
7373 +** Returns
7374 +** number of hidden files removed
7376 +static unsigned removeHiddenFiles(Widget listWidget)
7378 + /* Items currently in the listWidget */
7379 + XmString* items;
7380 + int nItems;
7382 + /* Array holding list positions of hidden files. It is allocated based
7383 + on the current number of items in the List. */
7384 + int* hiddenFilePositions;
7386 + /* Number of hidden files found */
7387 + unsigned hiddenFileCount = 0;
7389 + int i;
7391 + /* read values in List into array. */
7392 + XtVaGetValues(listWidget, XmNitems, &items, XmNitemCount, &nItems, NULL);
7394 + /* Allocate array based on number of items in List. */
7395 + hiddenFilePositions = (int*) XtMalloc(sizeof(int*) * nItems);
7397 + /* Traverse over items; for every item, check whether it's a hidden file;
7398 + if yes, put it in hiddenFilePositions[]. */
7399 + for (i = 0; i < nItems; i++) {
7400 + char* filename;
7401 + XmStringGetLtoR(items[i], XmSTRING_DEFAULT_CHARSET, &filename);
7402 + if (isHiddenFile(filename)) {
7403 + /* Add one because XmListDeletePositions expects values > 0. */
7404 + hiddenFilePositions[hiddenFileCount++] = i + 1;
7406 + XtFree(filename);
7409 + /* Do the removal. */
7410 + XmListDeletePositions(listWidget, hiddenFilePositions, hiddenFileCount);
7412 + /* Free array of positions. */
7413 + XtFree((char*) hiddenFilePositions);
7415 + return hiddenFileCount;
7419 +** Checks whether fullname is a dotfile, ie. starts with a '.'
7421 +** Preconditions:
7422 +** fullname < MAXPATHLEN
7423 +** 'void ParseFilename(fullname, filename, NULL)' exists and works
7425 +** Postcondition:
7426 +** Returns False for '..' and non-dotfiles, True for other dotfiles.
7428 +static int isHiddenFile(const char* fullname)
7430 + /* array to hold basename */
7431 + char basename[MAXPATHLEN + 1];
7433 + /* Extract basename from full filename */
7434 + ParseFilename(fullname, basename, NULL);
7436 + if (0 == strcmp(basename, "..")) {
7437 + /* Return False for parent directory */
7438 + return False;
7439 + } else {
7440 + /* Return True for dotfiles, False for other files */
7441 + return (basename[0] == '.');
7445 +static void freeFileList(char** list)
7447 + int count = 0;
7448 + int i;
7450 + if (!list) {
7451 + return;
7454 + while (list[count]) {
7455 + ++count;
7458 + for (i = 0; i < count; i++) {
7459 + XtFree(list[i]);
7462 + XtFree((char*) list);
7464 diff --quilt old/util/getfiles.h new/util/getfiles.h
7465 --- old/util/getfiles.h
7466 +++ new/util/getfiles.h
7467 @@ -26,22 +26,55 @@
7468 *******************************************************************************/
7470 #ifndef NEDIT_GETFILES_H_INCLUDED
7471 #define NEDIT_GETFILES_H_INCLUDED
7473 +#include <sys/param.h>
7475 #include <X11/Intrinsic.h>
7477 -#define GFN_OK 1 /* Get Filename OK constant */
7478 -#define GFN_CANCEL 2 /* Get Filename Cancel constant */
7480 +** The interface got smaller on functions and bigger on parameters. It's still
7481 +** a big too large for my tastes, but that's what you get.
7483 +typedef struct {
7484 + /* GUI customization */
7485 + String dialogTitle;
7486 + Boolean showHidden;
7488 + Boolean fileExists;
7489 + /* Usually only used for potentially unexisting files. */
7490 + String textfieldLabel; /* only set on new file || GetPrefStdOpenDialog() */
7491 + Boolean haveFormatButtons; /* only makes sense for new files */
7492 + String defaultName;
7494 + /* document details */
7495 + int fileFormat;
7496 + Boolean isContWrapped;
7498 + /* GUI handling */
7499 + Widget parentShell;
7500 +} gfbdParams;
7502 +enum gfdbResult {GFDB_OK, GFDB_CANCEL, GFDB_ERROR};
7503 +typedef struct {
7504 + int status;
7505 + char payload[MAXPATHLEN + 1]; /* Usually carries the filename */
7506 + Boolean addWrap;
7507 + int fileFormat;
7508 +} gfbdValue;
7510 -int GetExistingFilename(Widget parent, char *promptString, char *filename);
7511 -int GetNewFilename(Widget parent, char *promptString, char *filename,
7512 - char *defaultName);
7513 -int HandleCustomExistFileSB(Widget existFileSB, char *filename);
7514 -int HandleCustomNewFileSB(Widget newFileSB, char *filename, char *defaultName);
7515 char *GetFileDialogDefaultDirectory(void);
7516 char *GetFileDialogDefaultPattern(void);
7517 void SetFileDialogDefaultDirectory(char *dir);
7518 void SetFileDialogDefaultPattern(char *pattern);
7519 void SetGetEFTextFieldRemoval(int state);
7520 +gfbdValue* GetFilenameByDialog(const gfbdParams params);
7522 +typedef struct
7524 + Bool showHidden;
7525 + char** cachedDirList;
7526 + char** cachedFileList;
7527 +} fsbUserDataStruct;
7529 #endif /* NEDIT_GETFILES_H_INCLUDED */
7530 diff --quilt old/util/prefFile.c new/util/prefFile.c
7531 --- old/util/prefFile.c
7532 +++ new/util/prefFile.c
7533 @@ -6,11 +6,11 @@ static const char CVSID[] = "$Id: prefFi
7534 * Copyright (C) 1999 Mark Edel *
7536 * This is free software; you can redistribute it and/or modify it under the *
7537 * terms of the GNU General Public License as published by the Free Software *
7538 * Foundation; either version 2 of the License, or (at your option) any later *
7539 -* version. In addition, you may distribute version of this program linked to *
7540 +* version. In addition, you may distribute versions of this program linked to *
7541 * Motif or Open Motif. See README for details. *
7543 * This software is distributed in the hope that it will be useful, but WITHOUT *
7544 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
7545 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
7546 @@ -302,11 +302,11 @@ int SavePreferences(Display *display, co
7549 static int stringToPref(const char *string, PrefDescripRec *rsrcDescrip)
7551 int i;
7552 - char *cleanStr, *endPtr, **enumStrings;
7553 + char *cleanStr, *endPtr, **enumStrings, *cleanEnumStr;
7555 switch (rsrcDescrip->dataType) {
7556 case PREF_INT:
7557 cleanStr = removeWhiteSpace(string);
7558 *(int *)rsrcDescrip->valueAddr =
7559 @@ -338,22 +338,25 @@ static int stringToPref(const char *stri
7561 XtFree(cleanStr);
7562 *(int *)rsrcDescrip->valueAddr = False;
7563 return False;
7564 case PREF_ENUM:
7565 - cleanStr = removeWhiteSpace(string);
7566 - enumStrings = (char **)rsrcDescrip->arg;
7567 - for (i=0; enumStrings[i]!=NULL; i++) {
7568 - if (!strcmp(enumStrings[i], cleanStr)) {
7569 - *(int *)rsrcDescrip->valueAddr = i;
7570 - XtFree(cleanStr);
7571 - return True;
7574 - XtFree(cleanStr);
7575 - *(int *)rsrcDescrip->valueAddr = 0;
7576 - return False;
7577 + cleanStr = removeWhiteSpace(string);
7578 + enumStrings = (char **)rsrcDescrip->arg;
7579 + for (i=0; enumStrings[i]!=NULL; i++) {
7580 + cleanEnumStr = removeWhiteSpace(enumStrings[i]);
7581 + if (!strcmp(cleanEnumStr, cleanStr)) {
7582 + *(int *)rsrcDescrip->valueAddr = i;
7583 + XtFree(cleanStr);
7584 + XtFree(cleanEnumStr);
7585 + return True;
7587 + XtFree(cleanEnumStr);
7589 + XtFree(cleanStr);
7590 + *(int *)rsrcDescrip->valueAddr = 0;
7591 + return False;
7592 case PREF_STRING:
7593 if ((int)strlen(string) >= (int)rsrcDescrip->arg)
7594 return False;
7595 strncpy(rsrcDescrip->valueAddr, string, (int)rsrcDescrip->arg);
7596 return True;
7597 diff --quilt old/util/printUtils.c new/util/printUtils.c
7598 --- old/util/printUtils.c
7599 +++ new/util/printUtils.c
7600 @@ -6,11 +6,11 @@ static const char CVSID[] = "$Id: printU
7601 * Copyright (C) 1999 Mark Edel *
7603 * This is free software; you can redistribute it and/or modify it under the *
7604 * terms of the GNU General Public License as published by the Free Software *
7605 * Foundation; either version 2 of the License, or (at your option) any later *
7606 -* version. In addition, you may distribute version of this program linked to *
7607 +* version. In addition, you may distribute versions of this program linked to *
7608 * Motif or Open Motif. See README for details. *
7610 * This software is distributed in the hope that it will be useful, but WITHOUT *
7611 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
7612 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
7613 @@ -324,10 +324,12 @@ static Widget createForm(Widget parent)
7614 argcnt++;
7615 XtSetArg(args[argcnt], XmNdialogTitle, (st0=XmStringCreateLtoR(
7616 "Print", XmSTRING_DEFAULT_CHARSET))); argcnt++;
7617 XtSetArg(args[argcnt], XmNautoUnmanage, False); argcnt++;
7618 form = CreateFormDialog(parent, "printForm", args, argcnt);
7620 + /* Why is this not part of the arg vector? */
7621 XtVaSetValues(form, XmNshadowThickness, 0, NULL);
7623 XmStringFree( st0 );
7625 /*********************** LABEL 1 and TEXT BOX 1 *********************/
7626 diff --quilt /dev/null new/source/backup.c
7627 --- /dev/null
7628 +++ new/source/backup.c
7629 @@ -0,0 +1,313 @@
7630 +/* Copyright (c) 2000, Andy Hood. All rights reserved.
7631 + Copyright (c) 1993,1994, Joseph Arceneaux. All rights reserved.
7633 + This file is subject to the terms of the GNU General Public License as
7634 + published by the Free Software Foundation. A copy of this license is
7635 + included with this software distribution in the file COPYING. If you
7636 + do not have a copy, you may obtain a copy by writing to the Free
7637 + Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
7639 + This software is distributed in the hope that it will be useful,
7640 + but WITHOUT ANY WARRANTY; without even the implied warranty of
7641 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7642 + GNU General Public License for more details. */
7644 +/* GNU/Emacs style backups --
7645 + This behaviour is controlled by two environment variables,
7646 + VERSION_CONTROL and SIMPLE_BACKUP_SUFFIX.
7648 + VERSION_CONTROL determines what kinds of backups are made. If it's
7649 + value is "numbered", then the first modification of some file
7650 + "eraserhead.c" will yield a backup file "eraserhead.c.~1~", the
7651 + second modification will yield "eraserhead.c.~2~", and so on. It
7652 + does not matter if the version numbers are not a sequence; the next
7653 + version will be one greater than the highest in that directory.
7655 + If the value of VERSION_CONTROL is "numbered_existing", then such
7656 + numbered backups will be made if there are already numbered backup
7657 + versions of the file. Otherwise, the backup name will be that of
7658 + the original file with "~" (tilde) appended. E.g., "eraserhead.c~".
7660 + If the value of VERSION_CONTROL is "simple", then the backup name
7661 + will be that of the original file with "~" appended, regardless of
7662 + whether or not there exist numbered versions in the directory.
7664 + For simple backups, the value of SIMPLE_BACKUP_SUFFIX will be used
7665 + rather than "~" if it is set.
7667 + If VERSION_CONTROL is unset, "numbered_existing" is assumed. For
7668 + Emacs lovers, "nil" is equivalent to "numbered_existing" and "t" is
7669 + equivalent to "numbered".
7671 + Finally, if VERSION_CONTROL is "none" or "never", backups are not
7672 + made. I suggest you avoid this behaviour.
7674 + Added, october 1999 (by Chris F.A. Johnson):
7676 + If VERSION_WIDTH is set, then it controls zero padding of a numbered
7677 + suffix. */
7679 +/* Written by jla, based on code from djm (see `patch') */
7681 +#include <ctype.h>
7682 +#include <string.h>
7683 +#ifndef isascii
7684 +#define ISDIGIT(c) (isdigit ((int) (c)))
7685 +#else
7686 +#define ISDIGIT(c) (isascii ((int)c) && isdigit ((int)c))
7687 +#endif
7688 +#include <unistd.h>
7689 +#include <stdio.h>
7690 +#include <stdlib.h>
7691 +#include <dirent.h>
7692 +# define NAMLEN(dirent) strlen((dirent)->d_name)
7693 +#include "backup.h"
7695 +#ifndef NODIR
7696 +#if defined (_POSIX_VERSION) /* Might be defined in unistd.h. */
7697 +/* POSIX does not require that the d_ino field be present, and some
7698 + systems do not provide it. */
7699 +#define REAL_DIR_ENTRY(dp) 1
7700 +#else
7701 +#define REAL_DIR_ENTRY(dp) ((dp)->d_ino != 0)
7702 +#endif
7703 +#else /* NODIR */
7704 +#define generate_backup_filename(v,f) simple_backup_name((f))
7705 +#endif /* NODIR */
7707 +#ifndef BACKUP_SUFFIX_STR
7708 +#define BACKUP_SUFFIX_STR ".bck"
7709 +#endif
7711 +#ifndef BACKUP_SUFFIX_CHAR
7712 +#define BACKUP_SUFFIX_CHAR '~'
7713 +#endif
7715 +#ifndef BACKUP_SUFFIX_FORMAT
7716 +#define BACKUP_SUFFIX_FORMAT "%s.~%0*d~"
7717 +#endif
7719 +/* Default backup file suffix to use */
7720 +static char *simple_backup_suffix = BACKUP_SUFFIX_STR;
7721 +static enum backup_mode version_control = unset;
7722 +int version_width = 1;
7724 +/* Construct a simple backup name for PATHNAME by appending
7725 + the value of `simple_backup_suffix'. */
7727 +static char *
7728 +simple_backup_name (pathname)
7729 + char *pathname;
7731 + char *backup_name;
7733 + backup_name =
7734 + malloc (strlen (pathname) + strlen (simple_backup_suffix) + 2);
7735 + sprintf (backup_name, "%s%s", pathname, simple_backup_suffix);
7736 + return backup_name;
7739 +#ifndef NODIR
7740 +/* If DIRENTRY is a numbered backup version of file BASE, return
7741 + that number. BASE_LENGTH is the string length of BASE. */
7743 +static int
7744 +version_number (base, direntry, base_length)
7745 + char *base;
7746 + char *direntry;
7747 + int base_length;
7749 + int version;
7750 + char *p;
7752 + version = 0;
7753 + if (!strncmp (base, direntry, base_length)
7754 + && ISDIGIT (direntry[base_length + 2]))
7756 + for (p = &direntry[base_length + 2]; ISDIGIT (*p); ++p)
7757 + version = version * 10 + *p - '0';
7758 + if (p[0] != BACKUP_SUFFIX_CHAR || p[1])
7759 + version = 0;
7762 + return version;
7766 +/* Return the highest version of file FILENAME in directory
7767 + DIRNAME. Return 0 if there are no numbered versions. */
7769 +static int
7770 +highest_version (filename, dirname)
7771 + char *filename, *dirname;
7773 + DIR *dirp;
7774 + struct dirent *dp;
7775 + int highest_version;
7776 + int this_version;
7777 + int file_name_length;
7779 + dirp = opendir (dirname);
7780 + if (!dirp)
7781 + return 0;
7783 + highest_version = 0;
7784 + file_name_length = strlen (filename);
7786 + while ((dp = readdir (dirp)) != 0)
7788 + if (!REAL_DIR_ENTRY (dp) || NAMLEN (dp) <= file_name_length + 2)
7789 + continue;
7791 + this_version = version_number (filename, dp->d_name, file_name_length);
7792 + if (this_version > highest_version)
7793 + highest_version = this_version;
7796 + closedir (dirp);
7797 + return highest_version;
7801 +/* Return the highest version number for file PATHNAME. If there
7802 + are no backups, or only a simple backup, return 0. */
7804 +static int
7805 +max_version (pathname)
7806 + char *pathname;
7808 + char *p;
7809 + char *filename;
7810 + int pathlen = strlen (pathname);
7811 + int version;
7813 + p = pathname + pathlen - 1;
7814 + while (p > pathname && *p != '/')
7815 + p--;
7817 + if (*p == '/')
7819 + int dirlen = p - pathname;
7820 + char *dirname;
7822 + filename = p + 1;
7823 + dirname = malloc (dirlen + 1);
7824 + strncpy (dirname, pathname, (dirlen));
7825 + dirname[dirlen] = '\0';
7826 + version = highest_version (filename, dirname);
7827 + free (dirname);
7828 + return version;
7831 + filename = pathname;
7832 + version = highest_version (filename, ".");
7833 + return version;
7837 +/* Generate a backup filename for PATHNAME, dependent on the
7838 + value of VERSION_CONTROL. */
7840 +char *
7841 +generate_backup_filename (version_control, pathname)
7842 + enum backup_mode version_control;
7843 + char *pathname;
7845 + int last_numbered_version;
7846 + char *backup_name;
7848 + if (version_control == none)
7849 + return 0;
7851 + if (version_control == simple)
7852 + return simple_backup_name (pathname);
7854 + last_numbered_version = max_version (pathname);
7855 + if (version_control == numbered_existing && last_numbered_version == 0)
7856 + return simple_backup_name (pathname);
7858 + last_numbered_version++;
7859 + backup_name = malloc (strlen (pathname) + 16);
7860 + if (!backup_name)
7861 + return 0;
7863 + sprintf (backup_name, BACKUP_SUFFIX_FORMAT, pathname, version_width,
7864 + (int) last_numbered_version);
7866 + return backup_name;
7869 +#endif /* !NODIR */
7871 +static struct version_control_values values[] = {
7872 + {none, "never"}, /* Don't make backups. */
7873 + {none, "none"}, /* Ditto */
7874 + {simple, "simple"}, /* Only simple backups */
7875 + {numbered_existing, "existing"}, /* Numbered if they already exist */
7876 + {numbered_existing, "nil"}, /* Ditto */
7877 + {numbered, "numbered"}, /* Numbered backups */
7878 + {numbered, "t"}, /* Ditto */
7879 + {unknown, 0} /* Initial, undefined value. */
7883 +/* Determine the value of `version_control' by looking in the
7884 + environment variable "VERSION_CONTROL". Defaults to
7885 + numbered_existing. */
7887 +enum backup_mode
7888 +version_control_value ()
7890 + char *version;
7891 + struct version_control_values *v;
7893 + version = getenv ("VERSION_CONTROL");
7894 + if (version == 0 || *version == 0)
7895 + return numbered_existing;
7897 + v = &values[0];
7898 + while (v->name)
7900 + if (strcmp (version, v->name) == 0)
7901 + return v->value;
7902 + v++;
7905 + return unknown;
7909 +/* Initialize information used in determining backup filenames. */
7911 +void
7912 +set_version_width(void)
7914 + char *v = getenv ("VERSION_WIDTH");
7915 + if (v && ISDIGIT(*v))
7916 + version_width = atoi(v);
7917 + if (version_width > 16)
7918 + version_width = 16;
7921 +void
7922 +initialize_backups ()
7924 + char *v = getenv ("SIMPLE_BACKUP_SUFFIX");
7926 + if (v && *v)
7927 + simple_backup_suffix = v;
7928 +#ifdef NODIR
7929 + version_control = simple;
7930 +#else /* !NODIR */
7931 + version_control = version_control_value ();
7932 + if (version_control == unknown)
7934 + fprintf (stderr, "nedit: Strange version-control value\n");
7935 + fprintf (stderr, "nedit: Using numbered-existing\n");
7936 + version_control = numbered_existing;
7938 +#endif /* !NODIR */
7939 + set_version_width ();
7943 diff --quilt /dev/null new/source/backup.h
7944 --- /dev/null
7945 +++ new/source/backup.h
7946 @@ -0,0 +1,66 @@
7947 +/* Copyright (c) 2000, Andy Hood. All rights reserved.
7948 + Copyright (c) 1999, Carlo Wood. All rights reserved.
7949 + Copyright (c) 1993,1994, Joseph Arceneaux. All rights reserved.
7951 + This file is subject to the terms of the GNU General Public License as
7952 + published by the Free Software Foundation. A copy of this license is
7953 + included with this software distribution in the file COPYING. If you
7954 + do not have a copy, you may obtain a copy by writing to the Free
7955 + Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
7957 + This software is distributed in the hope that it will be useful,
7958 + but WITHOUT ANY WARRANTY; without even the implied warranty of
7959 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7960 + GNU General Public License for more details. */
7962 +#ifndef NEDIT_BACKUP_H
7963 +#define NEDIT_BACKUP_H
7966 +RCSTAG_H (backup, "$Id: backup.h,v 1.6 1999/08/07 12:54:31 carlo Exp $");
7968 +#include "io.h"
7971 +/* When to make backup files. Analagous to 'version-control' in Emacs. */
7972 +enum backup_mode
7974 + /* Uninitialized */
7975 + unset,
7977 + /* Uninitialized or indeterminate value */
7978 + unknown,
7980 + /* Never make backups. */
7981 + none,
7983 + /* Make simple backups of every file. */
7984 + simple,
7986 + /* Make numbered backups of files that already have numbered backups,
7987 + and simple backups of the others. */
7988 + numbered_existing,
7990 + /* Make numbered backups of every file. */
7991 + numbered
7994 +struct version_control_values
7996 + enum backup_mode value;
7997 + char *name;
8000 +/* Determine the value of `version_control' by looking in the environment
8001 + variable "VERSION_CONTROL". Defaults to numbered_existing. */
8002 +extern enum backup_mode version_control_value(void);
8004 +/* Initialize information used in determining backup filenames. */
8005 +extern void initialize_backups(void);
8007 +/* Make a filename to use for backup. */
8008 +char *
8009 +generate_backup_filename(enum backup_mode version_control, char *pathname);
8010 +#endif /* NEDIT_BACKUP_H */