remove calltip_ignore_arg.patch
[nedit-bw.git] / enhanced-hooks.2008-01-20.1.diff
blob2224d530564acf5af9d7ba75c76f025c4bfbc998
1 ReleaseNotes | 34 +
2 doc/help.etx | 109 +++++
3 source/Makefile.common | 1
4 source/Makefile.dependencies | 3
5 source/calltips.c | 334 ++++++++++++----
6 source/calltips.h | 13
7 source/file.c | 337 ++++++-----------
8 source/file.h | 7
9 source/help.c | 63 ++-
10 source/highlightData.c | 4
11 source/interpret.c | 27 +
12 source/macro.c | 271 +++++++++++--
13 source/macro.h | 3
14 source/menu.c | 254 +++++++++++-
15 source/nedit.c | 16
16 source/nedit.h | 14
17 source/preferences.c | 279 ++++++++++++--
18 source/preferences.h | 8
19 source/search.c | 159 +++++---
20 source/search.h | 10
21 source/selection.c | 49 +-
22 source/server.c | 9
23 source/shell.c | 5
24 source/text.c | 72 ++-
25 source/text.h | 14
26 source/textDisp.c | 461 ++++++++++++++++++++---
27 source/textDisp.h | 53 +-
28 source/textP.h | 5
29 source/window.c | 179 +++++++--
30 source/window.h | 6
31 util/fileUtils.c | 2
32 util/getfiles.c | 847 ++++++++++++++++++++++++++++++++++++-------
33 util/getfiles.h | 47 ++
34 util/prefFile.c | 31 -
35 util/printUtils.c | 4
36 35 files changed, 2951 insertions(+), 779 deletions(-)
38 diff --quilt old/ReleaseNotes new/ReleaseNotes
39 --- old/ReleaseNotes
40 +++ new/ReleaseNotes
41 @@ -13,11 +13,43 @@ If you are upgrading NEdit from a versio
42 the README file which came with the (source or executable) distribution kit,
43 about updating macros and font settings in your .nedit file.
45 New Features in $NEXT_VERSION
47 - - The macro variable $VERSION returns NEdit's version number.
48 + - Hidden files (dotfiles) can now be excluded from the file and directory
49 + lists in the file selection box (SF patch #502840).
51 + - A 'Smart Case' toggles the regex search caseness depending on the occur-
52 + rence of upper case letters in the search expression (SF patch #685618).
54 + - The help window got some small changes to increase usability.
56 + - The resource nedit.prevOpenFilesMask can be set to a regex to exclude
57 + certain files from the Open Previous menu.
59 + - Changes to the macro language:
60 + - The function highlight_calltip_line() can highlight single lines in
61 + a macro-created calltip.
63 + - If the macro routine file_open_hook() exists, it is called when an existing
64 + file is opened.
66 + - A hairline can be displayed at the wrap column (SF patch #701337).
68 + - The current line is now optionally displayed with a colored background
69 + (SF patch #683567).
71 + - Documents can now be flagged 'transient'. This disables the warning
72 + NEdit usually gives when you try to close a document which is not saved.
74 - The new macro function filename_dialog() can be used to query a file
75 name from the user by using the usual file selection dialog.
78 diff --quilt old/doc/help.etx new/doc/help.etx
79 --- old/doc/help.etx
80 +++ new/doc/help.etx
81 @@ -127,10 +127,13 @@ Getting Started
82 If you already have an empty (Untitled) window displayed, just begin typing
83 in the window. To create a new Untitled window, choose New Window or New Tab
84 from the File menu. To give the file a name and save its contents to the
85 disk, choose Save or Save As... from the File menu.
87 + In both Open and Save File Dialogs you can choose whether hidden files and
88 + directories are shown in the lists. Just check/uncheck the toggle button.
90 3>Backup Files
92 NEdit maintains periodic backups of the file you are editing so that you can
93 recover the file in the event of a problem such as a system crash, network
94 failure, or X server crash. These files are saved under the name `~filename`
95 @@ -260,10 +263,15 @@ Finding and Replacing Text
96 button with an icon resembling "|<". Clicking on it empties the search text widget
97 without disturbing selections. A middle click on the clear button copies the
98 content of any existing selection into the search text widget and triggers a new
99 search.
101 + All searches will default to the search mode selected in the preference menu.
102 + (Default Setting -> Searching -> Default Search Style). You can choose a smart
103 + case sensitivity here; this let all searches start insensitive, but changes to
104 + case sensitive as soon as you enter an upper-case letter.
106 3>Searching Backwards
108 Holding down the shift key while choosing any of the search or replace
109 commands from the menu (or using the keyboard shortcut), will search in the
110 reverse direction. Users who have set the search direction using the buttons
111 @@ -1939,13 +1947,13 @@ Macro Language
114 3>Syntax
116 An NEdit macro language program consists of a list of statements, each
117 - terminated by a newline. Groups of statements which are executed together
118 - conditionally, such as the body of a loop, are surrounded by curly braces
119 - "{}".
120 + terminated by a newline or a semicolon (;). Groups of statements which
121 + are executed together conditionally, such as the body of a loop, are
122 + surrounded by curly braces "{}".
124 Blank lines and comments are also allowed. Comments begin with a "#" and end
125 with a newline, and can appear either on a line by themselves, or at the end
126 of a statement line.
128 @@ -2660,11 +2674,11 @@ Macro Subroutines
129 **filename_dialog( [title[, mode[, defaultPath[, filter[, defaultName]]]]] )**
130 Presents a file selection dialog with the given title to the user that
131 prompts for a new or existing file.
133 Options are: ~title~ will be the title of the dialog, defaults to "Choose
134 - file". If ~mode~ is set to "exist" (default), the "New File Name"TextField
135 + file". If ~mode~ is set to "exist" (default), the "New File Name" TextField
136 of the FSB will be unmanaged. If "new", the TextField will be managed.
137 ~defaultPath~ is the default path to use. Default (or "") will use the
138 active document's directory. ~filter~ is the file glob which determines
139 which files to display. Is set to "*" if filter is "" and by default.
140 ~defaultName~ is the default filename that is filled in automatically.
141 @@ -2682,12 +2696,12 @@ Macro Subroutines
142 focused window (the first window being the one returned from calling
143 focus_window("last"). Returns the name of the newly-focused window, or an
144 empty string if the requested window was not found.
146 **get_character( position )**
147 - Returns the single character at the position
148 - indicated by the first argument to the routine from the current window.
149 + Returns the single character at the position indicated by the first argument
150 + to the routine from the current window.
152 **get_range( start, end )**
153 Returns the text between a starting and ending position from the current
154 window.
156 @@ -2697,10 +2711,14 @@ Macro Subroutines
157 the screen (keyword "any").
159 **getenv( name )**
160 Gets the value of an environment variable.
162 +**highlight_calltip_line(calltip_ID, line)**
163 + Highlights a single line in the given calltip. Set line to 0 to remove
164 + any existing highlighting.
166 **kill_calltip( [calltip_ID] )**
167 Kills any calltip that is being displayed in the window in which the macro is
168 running. If there is no displayed calltip this does nothing. If a calltip
169 ID is supplied then the calltip is killed only if its ID is calltip_ID.
171 @@ -2853,10 +2871,19 @@ Macro Subroutines
172 Return an all lower-case version of string.
174 **toupper( string )**
175 Return an all upper-case version of string.
177 +**typeof( value )**
178 + Returns a string indicating the type of a macro value. The value can be
179 + any NEdit macro language value except for the return value of functions
180 + without a return value. Examples:
181 + typeof(2) # -> "INTEGER"
182 + typeof($empty_array) # -> "ARRAY"
183 + typeof(get_range(10, 20)) # -> "STRING"
184 + typeof(myArray["doesnotexist"]) # -> "UNDEFINED"
186 **valid_number( string )**
187 Returns 1 if the string can be converted to a number without error
188 following the same rules that the implicit conversion would. Otherwise 0.
190 **write_file( string, filename )**
191 @@ -3226,11 +3253,11 @@ Action Routines
192 3>Menu Action Routine Arguments
194 Arguments are text strings enclosed in quotes. Below are the menu action
195 routines which take arguments. Optional arguments are enclosed in [].
197 - **new**( ["tab" | "window" | "prefs" | "opposite"] )
198 + **new**( ["tab" | "window" | "prefs" | "opposite"] [, "transient"] )
200 **close**( ["prompt" | "save" | "nosave"] )
202 **execute_command**( shell-command )
204 @@ -3293,10 +3320,19 @@ Action Routines
205 preference
206 "opposite": Opposite of user's tab/window
207 preference
208 Default behaviour is "prefs".
210 + "transient" [EXPERIMENTAL]: Open the new
211 + document in transient mode. This disables the
212 + warning NEdit usually gives when you try to
213 + close a file which is not saved.
215 + WARNING: This is an experimental feature.
216 + Make sure to use this setting only for
217 + documents which can easily be recreated.
219 ~filename~ Path names are relative to the directory from
220 which NEdit was started. Shell interpreted
221 wildcards and `~' are not expanded.
223 ~keep-dialog~ Either "keep" or "nokeep".
224 @@ -3730,10 +3766,35 @@ Action Routines
226 **self_insert()**
227 To be attached to a key-press event, inserts the character
228 equivalent of the key pressed.
231 +Hooks
232 +-----
234 + Hooks are macro routines which are called at specific points in NEdit's
235 + execution. You can use hooks to tie in user-defined functionality at these
236 + points.
238 + No hooks are provided. To use a hook, simply define a macro function with
239 + the name of the hook. The next time the hook will catch, the macro function
240 + is called.
242 + You don't have to provide any hook. If a certain hook does not exist, it is
243 + simply skipped.
245 +**file_open_hook()**
246 + Called when an existing file is opened.
248 +..**file_name_hook(filename)**
249 +.. Called before NEdit opens a file using a certain name. The parameter is
250 +.. the filename NEdit intends to open.
252 +.. Return a string to use instead of the original filename. Return 0 to tell
253 +.. NEdit to use the original filename.
255 ----------------------------------------------------------------------
257 Customizing
258 ===========
260 @@ -3830,10 +3891,18 @@ Preferences
261 **Wrap Margin**
262 Set margin for Auto Newline Wrap, Continuous Wrap, and Fill Paragraph. Lines
263 may, be wrapped at the right margin of the window, or the margin can be set
264 at a specific column.
266 +**Show Wrap Margin**
267 + Visually indicate which column is set as the wrap margin by drawing a vertical
268 + line. Choose between never, always and when wrap is enabled. "Never" turns
269 + this feature off. "Always" will show the wrap margin irrespecitive of the
270 + wrapping style. "When Wrap is Enabled" will show the wrap margin only if
271 + continuous or auto-newline wrap styles are choosen and does not show the wrap
272 + margin if wrapping is turned off.
274 **Tab Stops**
275 Set the tab distance (number of characters between tab stops) for tab
276 characters, and control tab emulation and use of tab characters in padding
277 and emulated tabs.
279 @@ -3873,10 +3942,17 @@ Preferences
280 **Read Only**
281 Lock the file against accidental modification. This temporarily prevents the
282 file from being modified in this NEdit session. Note that this is different
283 from setting the file protection.
285 +**Transient [EXPERIMENTAL]**
286 + Flags the document as transient. This disables the warning NEdit usually
287 + gives when you try to close a file which is not saved.
289 + WARNING: This is an experimental feature. Make sure to use this setting
290 + only for documents which can easily be recreated.
292 3>Preferences -> Default Settings Menu
294 Options in the Preferences -> Default Settings menu have the same meaning as
295 those in the top-level Preferences menu, except that they apply to future
296 NEdit windows and future NEdit sessions if saved with the Save Defaults
297 @@ -3974,10 +4050,16 @@ Preferences
299 **Terminate with Line Break on Save**
300 Some UNIX tools expect that files end with a line feed. If this option is
301 activated, NEdit will append one if required.
303 +**Show Hidden Files**
304 + Show hidden files by default in file selection boxes.
306 **Sort Open Prev. Menu**
307 Option to order the File -> Open Previous menu alphabetically, versus in
308 order of last access.
310 **Popups Under Pointer**
311 @@ -4310,10 +4392,16 @@ X Resources
313 Number of files listed in the Open Previous sub-menu of the File menu.
314 Setting this to zero disables the Open Previous menu item and maintenance of
315 the NEdit file history file.
317 +**nedit.prevOpenFilesMask**: (not defined)
319 + Files not to be listed in the Open Previous sub-menu of the File menu.
320 + Setting this to a regular expression causes files matching the expression to
321 + be omitted from the Open Previous menu item and the .neditdb file.
323 **nedit.printCommand**: (system specific)
325 Command used by the print dialog to print a file, such as, lp, lpr, etc..
326 The command must be capable of accepting input via stdin (standard input).
328 @@ -4349,10 +4437,16 @@ X Resources
329 **nedit.printDefaultHost**: (system specific)
331 The node name of the default print host. Used only to display in the print
332 dialog, and has no effect on printing.
334 +**nedit.showScrolltip**: True
336 + If this resource is set to True, NEdit will show a tooltip displaying the
337 + line number if the user grabs and moves the scroll handle. Set to False to
338 + switch it off.
340 **nedit.visualID**: Best
342 If your screen supports multiple visuals (color mapping models), this
343 resource allows you to manually choose among them. The default value of
344 "Best" chooses the deepest (most colors) visual available. Since NEdit does
345 @@ -5993,10 +6087,11 @@ Problems/Defects
346 .. Menu: Macro Language # macro_lang
347 .. Menu: M_a_cro Subroutines # macro_subrs
348 .. Menu: Rangesets # rangeset
349 .. Menu: Highlighting Information # hiliteInfo
350 .. Menu: Action Routines # actions
351 +.. Menu: H_o_oks # hooks
353 .. Menu: Customizing # customizing
354 .. Menu: Customizing NEdit # customize
355 .. Menu: Preferences # preferences
356 .. Menu: X Resources # resources
357 diff --quilt old/source/Makefile.common new/source/Makefile.common
358 --- old/source/Makefile.common
359 +++ new/source/Makefile.common
360 @@ -6,10 +6,11 @@
361 OBJS = nedit.o file.o menu.o window.o selection.o search.o undo.o shift.o \
362 help.o preferences.o tags.o userCmds.o shell.o regularExp.o macro.o \
363 text.o textSel.o textDisp.o textBuf.o textDrag.o server.o highlight.o \
364 highlightData.o interpret.o parse.o smartIndent.o regexConvert.o \
365 rbTree.o windowTitle.o calltips.o server_common.o rangeset.o
366 +OBJS += backup.o
368 XLTLIB = ../Xlt/libXlt.a
369 XMLLIB = ../Microline/XmL/libXmL.a
371 .c.o:
372 diff --quilt old/source/Makefile.dependencies new/source/Makefile.dependencies
373 --- old/source/Makefile.dependencies
374 +++ new/source/Makefile.dependencies
375 @@ -1,12 +1,13 @@
376 # $Id: Makefile.dependencies,v 1.21 2003/05/02 18:18:41 edg Exp $
377 +backup.o: backup.c backup.h
378 calltips.o: calltips.c text.h textBuf.h textP.h textDisp.h calltips.h \
379 nedit.h ../util/misc.h
380 file.o: file.c file.h nedit.h textBuf.h text.h window.h preferences.h \
381 undo.h menu.h tags.h server.h ../util/misc.h ../util/DialogF.h \
382 ../util/fileUtils.h ../util/getfiles.h ../util/printUtils.h \
383 - ../util/utils.h
384 + ../util/utils.h macro.h
385 help.o: help.c help.h help_topic.h textBuf.h text.h textP.h textDisp.h \
386 textSel.h nedit.h search.h window.h preferences.h help_data.h file.h \
387 highlight.h ../util/misc.h ../util/DialogF.h ../util/system.h
388 highlight.o: highlight.c highlight.h nedit.h textBuf.h textDisp.h text.h \
389 textP.h regularExp.h highlightData.h preferences.h window.h \
390 diff --quilt old/source/calltips.c new/source/calltips.c
391 --- old/source/calltips.c
392 +++ new/source/calltips.c
393 @@ -1,15 +1,15 @@
394 /*******************************************************************************
396 * calltips.c -- Calltip UI functions (calltip *file* functions are in tags.c) *
398 -* Copyright (C) 2002 Nathaniel Gray *
399 +* Copyright (C) 2002, 2004, 2005 The NEdit Developers *
401 * This is free software; you can redistribute it and/or modify it under the *
402 * terms of the GNU General Public License as published by the Free Software *
403 * Foundation; either version 2 of the License, or (at your option) any later *
404 -* version. In addition, you may distribute version of this program linked to *
405 +* version. In addition, you may distribute versions of this program linked to *
406 * Motif or Open Motif. See README for details. *
408 * This software is distributed in the hope that it will be useful, but WITHOUT *
409 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
410 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
411 @@ -28,29 +28,35 @@
413 #ifdef HAVE_CONFIG_H
414 #include "../config.h"
415 #endif
417 +#include "calltips.h"
419 +#include "regularExp.h"
420 #include "text.h"
421 #include "textP.h"
422 -#include "calltips.h"
423 #include "../util/misc.h"
425 #include <stdio.h>
426 #include <stdlib.h>
427 #include <string.h>
428 #include <limits.h>
430 #include <Xm/Xm.h>
431 -#include <Xm/Label.h>
432 #include <X11/Shell.h>
433 +#include <Xm/Text.h>
435 #ifdef HAVE_DEBUG_H
436 #include "../debug.h"
437 #endif
439 -static char *expandAllTabs( char *text, int tab_width );
440 +static char* expandAllTabs(const char *text, const int tab_width);
441 +Boolean getRangeOfLine(const char* textString, const unsigned line,
442 + unsigned* begin, unsigned* end);
443 +Widget createTip(const Widget parent, const Pixel foreground,
444 + const Pixel background, const unsigned char alignment);
447 ** Pop-down a calltip if one exists, else do nothing
449 void KillCalltip(WindowInfo *window, int calltipID) {
450 @@ -60,31 +66,23 @@ void KillCalltip(WindowInfo *window, int
452 void TextDKillCalltip(textDisp *textD, int calltipID) {
453 if( textD->calltip.ID == 0 )
454 return;
455 if( calltipID == 0 || calltipID == textD->calltip.ID ) {
456 - XtPopdown( textD->calltipShell );
457 + XtPopdown(XtParent(textD->calltip.widget));
458 textD->calltip.ID = 0;
463 -** Is a calltip displayed? Returns the calltip ID of the currently displayed
464 -** calltip, or 0 if there is no calltip displayed. If called with
465 -** calltipID != 0, returns 0 unless there is a calltip being
466 -** displayed with that calltipID.
467 +** Returns the calltip ID of the currently displayed calltip, or 0 if
468 +** there is no calltip displayed.
470 -int GetCalltipID(WindowInfo *window, int calltipID) {
471 +int GetCalltipID(const WindowInfo *window) {
472 textDisp *textD = ((TextWidget)window->lastFocus)->text.textD;
473 - if( calltipID == 0 )
474 - return textD->calltip.ID;
475 - else {
476 - if( calltipID == textD->calltip.ID)
477 - return calltipID;
478 - else
479 - return 0;
482 + return textD->calltip.ID;
485 #define CALLTIP_EDGE_GUARD 5
486 static Boolean offscreenV(XWindowAttributes *screenAttr, int top, int height) {
487 return (top < CALLTIP_EDGE_GUARD ||
488 @@ -129,12 +127,15 @@ void TextDRedrawCalltip(textDisp *textD,
489 return;
491 rel_x = textD->calltip.pos;
494 - XtVaGetValues(textD->calltipShell, XmNwidth, &tipWidth, XmNheight,
495 - &tipHeight, XmNborderWidth, &borderWidth, NULL);
496 + XtVaGetValues(XtParent(textD->calltip.widget),
497 + XmNwidth, &tipWidth,
498 + XmNheight, &tipHeight,
499 + XmNborderWidth, &borderWidth,
500 + NULL);
501 rel_x += borderWidth;
502 rel_y += lineHeight/2 + borderWidth;
504 /* Adjust rel_x for horizontal alignment modes */
505 if (textD->calltip.hAlign == TIP_CENTER)
506 @@ -175,119 +176,110 @@ void TextDRedrawCalltip(textDisp *textD,
507 abs_y = screenAttr.height - tipHeight - CALLTIP_EDGE_GUARD;
508 /* If no case applied, just go with the default placement. */
512 - XtVaSetValues( textD->calltipShell, XmNx, abs_x, XmNy, abs_y, NULL );
513 + XtVaSetValues(XtParent(textD->calltip.widget), XmNx, abs_x, XmNy, abs_y, NULL);
517 ** Returns a new string with each \t replaced with tab_width spaces or
518 ** a pointer to text if there were no tabs. Returns NULL on malloc failure.
519 ** Note that this is dumb replacement, not smart tab-like behavior! The goal
520 ** is to prevent tabs from turning into squares in calltips, not to get the
521 ** formatting just right.
523 -static char *expandAllTabs( char *text, int tab_width ) {
524 - int i, nTabs=0;
525 +static char* expandAllTabs(const char* text, const int tab_width)
527 + int i, nTabs = 0;
528 size_t len;
529 - char *c, *cCpy, *textCpy;
530 + const char* c;
531 + char *cCpy, *textCpy;
533 /* First count 'em */
534 - for( c = text; *c; ++c )
535 - if( *c == '\t' )
536 + for (c = (char*) text; *c; ++c) {
537 + if ('\t' == *c)
538 ++nTabs;
539 - if( nTabs == 0 )
540 - return text;
542 + if (0 == nTabs) {
543 + return strdup(text);
546 /* Allocate the new string */
547 - len = strlen( text ) + ( tab_width - 1 )*nTabs;
548 - textCpy = (char*)malloc( len + 1 );
549 - if( !textCpy ) {
550 - fprintf(stderr,
551 - "nedit: Out of heap memory in expandAllTabs!\n");
552 + len = strlen(text) + (tab_width - 1) * nTabs;
553 + textCpy = (char*) malloc(len + 1);
554 + if (!textCpy) {
555 + fprintf(stderr, "nedit: Out of heap memory in expandAllTabs!\n");
556 return NULL;
559 /* Now replace 'em */
560 - for( c = text, cCpy = textCpy; *c; ++c, ++cCpy) {
561 - if( *c == '\t' ) {
562 - for( i = 0; i < tab_width; ++i, ++cCpy )
563 + for (c = text, cCpy = textCpy; *c; ++c, ++cCpy) {
564 + if (*c == '\t') {
565 + for (i = 0; i < tab_width; ++i, ++cCpy) {
566 *cCpy = ' ';
568 --cCpy; /* Will be incremented in outer for loop */
569 - } else
570 + } else {
571 *cCpy = *c;
574 *cCpy = '\0';
575 return textCpy;
579 -** Pop-up a calltip.
580 -** If a calltip is already being displayed it is destroyed and replaced with
581 -** the new calltip. Returns the ID of the calltip or 0 on failure.
582 +** Pop-up a calltip.
584 +** If a calltip is already being displayed it is destroyed and replaced
585 +** with the new calltip.
587 +** Returns the ID of the calltip or 0 on failure.
589 -int ShowCalltip(WindowInfo *window, char *text, Boolean anchored,
590 - int pos, int hAlign, int vAlign, int alignMode) {
591 - static int StaticCalltipID = 1;
592 +int ShowCalltip(const WindowInfo *window, const char *text,
593 + const Boolean anchored, const int pos, const int hAlign,
594 + const int vAlign, const int alignMode)
596 + static unsigned StaticCalltipID = 1;
597 textDisp *textD = ((TextWidget)window->lastFocus)->text.textD;
598 int rel_x, rel_y;
599 - Position txtX, txtY;
600 - char *textCpy;
601 - XmString str;
602 + char* tablessText;
604 /* Destroy any previous calltip */
605 - TextDKillCalltip( textD, 0 );
606 + TextDKillCalltip(textD, 0);
608 /* Make sure the text isn't NULL */
609 if (text == NULL) return 0;
611 - /* Expand any tabs in the calltip and make it an XmString */
612 - textCpy = expandAllTabs( text, BufGetTabDistance(textD->buffer) );
613 - if( textCpy == NULL )
614 + /* Expand any tabs in the calltip */
615 + tablessText = expandAllTabs(text, BufGetTabDistance(textD->buffer));
616 + if (NULL == tablessText) {
617 return 0; /* Out of memory */
618 - str = XmStringCreateLtoR(textCpy, XmFONTLIST_DEFAULT_TAG);
619 - if( textCpy != text )
620 - free( textCpy );
622 - /* Get the location/dimensions of the text area */
623 - XtVaGetValues(textD->w,
624 - XmNx, &txtX,
625 - XmNy, &txtY,
626 - NULL);
630 /* Create the calltip widget on first request */
631 - if (textD->calltipW == NULL) {
632 - Arg args[10];
633 - int argcnt = 0;
634 - XtSetArg(args[argcnt], XmNsaveUnder, True); argcnt++;
635 - XtSetArg(args[argcnt], XmNallowShellResize, True); argcnt++;
637 - textD->calltipShell = CreatePopupShellWithBestVis("calltipshell",
638 - overrideShellWidgetClass, textD->w, args, argcnt);
640 - /* Might want to make this a read-only XmText eventually so that
641 - users can copy from it */
642 - textD->calltipW = XtVaCreateManagedWidget(
643 - "calltip", xmLabelWidgetClass, textD->calltipShell,
644 - XmNborderWidth, 1, /* Thin borders */
645 - XmNhighlightThickness, 0,
646 - XmNalignment, XmALIGNMENT_BEGINNING,
647 - XmNforeground, textD->calltipFGPixel,
648 - XmNbackground, textD->calltipBGPixel,
649 - NULL );
652 - /* Set the text on the label */
653 - XtVaSetValues( textD->calltipW, XmNlabelString, str, NULL );
654 - XmStringFree( str );
655 + if (NULL == textD->calltip.widget) {
656 + textD->calltip.widget = createTip(textD->w, textD->calltipFGPixel,
657 + textD->calltipBGPixel, XmALIGNMENT_BEGINNING);
660 + /* The text widget will keep the size of the largest text it contained
661 + over its lifetime unless we do something about it. So we set it to
662 + minimum size and let the resize functionality do its work to get it
663 + back up again matching the current text. */
664 + XtVaSetValues(textD->calltip.widget,
665 + XmNheight, 10,
666 + XmNwidth, 10,
667 + NULL);
668 + XmTextSetString(textD->calltip.widget, tablessText);
669 + free(tablessText);
671 /* Figure out where to put the tip */
672 if (anchored) {
673 /* Put it at the specified position */
674 /* If position is not displayed, return 0 */
675 - if (pos < textD->firstChar || pos > textD->lastChar ) {
676 + if (pos < textD->firstChar || pos > textD->lastChar) {
677 XBell(TheDisplay, 0);
678 return 0;
680 textD->calltip.pos = pos;
681 } else {
682 @@ -311,15 +303,179 @@ int ShowCalltip(WindowInfo *window, char
683 textD->calltip.vAlign = vAlign;
684 textD->calltip.alignMode = alignMode;
686 /* Increment the static calltip ID. Macro variables can only be int,
687 not unsigned, so have to work to keep it > 0 on overflow */
688 - if(++StaticCalltipID <= 0)
689 + /* Macro variables can only be int, that's why you have to keep the ID
690 + in the unsigned range? */
691 + if (++StaticCalltipID <= 0) {
692 StaticCalltipID = 1;
695 /* Realize the calltip's shell so that its width & height are known */
696 - XtRealizeWidget( textD->calltipShell );
697 + XtRealizeWidget(XtParent(textD->calltip.widget));
699 /* Move the calltip and pop it up */
700 TextDRedrawCalltip(textD, 0);
701 - XtPopup( textD->calltipShell, XtGrabNone );
702 + XtPopup(XtParent(textD->calltip.widget), XtGrabNone);
704 return textD->calltip.ID;
708 +** Highlight a single line in a given calltip, erasing all other highlights.
710 +** Return values for this one need to be a bit more expressive. Some errors
711 +** might just be the result of sloppy parameters, and the caller should
712 +** decide whether to fail hard or not. The following results are possible:
714 +** - The calltip ID given is invalid (CT_INVALID_ID).
715 +** - The user requested to remove all highlightings (CT_OK).
716 +** - The requested line is highlighted (CT_OK).
717 +** - The requested line is not in the provided text (CT_NOLINE).
719 +int HighlightCalltipLine(const WindowInfo* window, const int calltipID,
720 + const unsigned line)
722 + textDisp* textD = ((TextWidget) window->lastFocus)->text.textD;
723 + Boolean result = False;
725 + if (calltipID == textD->calltip.ID) {
726 + Widget textWidget = textD->calltip.widget;
727 + char* textString = XmTextGetString(textWidget);
728 + XmTextPosition textLength = XmTextGetLastPosition(textWidget);
729 + unsigned begin = 0, end = 0;
730 + Boolean lineIsValid = False;
732 + /* First remove all existing highlights. */
733 + XmTextSetHighlight(textWidget, 0, textLength + 1, XmHIGHLIGHT_NORMAL);
735 + if (0 == line) {
736 + /* Just return without highlighting anything. */
737 + result = CT_OK;
738 + } else {
739 + lineIsValid = getRangeOfLine(textString, line, &begin, &end);
740 + if (lineIsValid) {
741 + XmTextSetHighlight(textWidget, (XmTextPosition) begin,
742 + (XmTextPosition) end, XmHIGHLIGHT_SELECTED);
744 + result = CT_OK;
745 + } else {
746 + /* The requested line is not in the provided text. */
747 + result = CT_NOLINE;
751 + XtFree(textString);
752 + } else {
753 + result = CT_INVALID_ID;
756 + return result;
760 +** Sets the parameters to beginning and end of the line. Returns False if
761 +** the line is not in the text, True otherwise.
763 +Boolean getRangeOfLine(const char* textString, const unsigned line,
764 + unsigned* begin, unsigned* end)
766 + int i;
767 + size_t position = 0;
769 + for (i = 0; i < line; i++)
771 + *end = strcspn(textString + position, "\n") + position;
772 + *begin = position;
773 + position = *end + 1;
775 + if (*begin == *end)
777 + /* Break if last line is found. */
778 + break;
782 + return (*begin != *end);
786 +** Pop up a scroll calltip.
788 +Boolean ShowScrolltip(textDisp* textD, const char* text, const int x,
789 + const int y)
791 + if (NULL == textD->scrolltip) {
792 + textD->scrolltip = createTip(textD->w, textD->calltipFGPixel,
793 + textD->calltipBGPixel, XmALIGNMENT_CENTER);
796 + /* Set the text on the tip's label. */
797 + XmTextSetString(textD->scrolltip, (char*) text);
799 + /* Realize the calltip's shell so that its width and height are known */
800 + XtRealizeWidget(XtParent(textD->scrolltip));
802 + /* Move the tip where it belongs and pop it up. */
803 + XtVaSetValues(XtParent(textD->scrolltip), XmNx, x, XmNy, y, NULL);
804 + XtPopup(XtParent(textD->scrolltip), XtGrabNone);
806 + return True;
810 +** Pop down scrolltip if it exists
812 +void KillScrolltip(textDisp* textD)
814 + if (NULL != textD->scrolltip && NULL != XtParent(textD->scrolltip)) {
815 + XtPopdown(XtParent(textD->scrolltip));
820 +** This creates a calltip of class XmText and its parent, a shell of class
821 +** OverrideShell (which in turn will be the child of the grandfather
822 +** parameter). The tip will have minimum size but will resize to match
823 +** the text entered (see XmNallowShellResize).
825 +** Color is picked by the two parameters foreground and background.
827 +** The alignment is on of XmALIGNMENT_BEGINNING, XmALIGNMENT_CENTER or
828 +** XmALIGNMENT_END, taken from the XmLabel class.
830 +** TODO: Some helper functions are still desirable to make this function
831 +** available from other parts of the code. At the moment the caller must
832 +** use calls to Motif/Intrinsics functions to handle it.
835 +Widget createTip(const Widget grandfather, const Pixel foreground,
836 + const Pixel background, const unsigned char alignment)
838 + Widget tip = NULL;
839 + Widget shell = NULL;
840 + Arg args[10];
841 + int argc = 0;
843 + XtSetArg(args[argc], XmNsaveUnder, True); argc++;
844 + XtSetArg(args[argc], XmNallowShellResize, True); argc++;
846 + shell = CreatePopupShellWithBestVis("tipshell", overrideShellWidgetClass,
847 + grandfather, args, argc);
849 + tip = XtVaCreateManagedWidget("tip",
850 + xmTextWidgetClass, shell,
851 + XmNhighlightThickness, 0,
852 + XmNalignment, alignment,
853 + XmNeditable, False,
854 + XmNeditMode, XmMULTI_LINE_EDIT,
855 + XmNcursorPositionVisible, False,
856 + XmNresizeHeight, True,
857 + XmNresizeWidth, True,
858 + XmNforeground, foreground,
859 + XmNbackground, background,
860 + XmNheight, 10, /* will be resized automatically */
861 + XmNwidth, 10, /* will be resized automatically */
862 + NULL);
863 + return tip;
865 diff --quilt old/source/calltips.h new/source/calltips.h
866 --- old/source/calltips.h
867 +++ new/source/calltips.h
868 @@ -36,14 +36,21 @@
871 enum TipHAlignMode {TIP_LEFT, TIP_CENTER, TIP_RIGHT};
872 enum TipVAlignMode {TIP_ABOVE, TIP_BELOW};
873 enum TipAlignStrict {TIP_SLOPPY, TIP_STRICT};
874 +enum TipHighlightError {CT_OK, CT_INVALID_ID, CT_NOLINE};
876 -int ShowCalltip(WindowInfo *window, char *text, Boolean anchored,
877 - int pos, int hAlign, int vAlign, int alignMode);
878 +int ShowCalltip(const WindowInfo *window, const char *text,
879 + const Boolean anchored, const int pos, const int hAlign,
880 + const int vAlign, const int alignMode);
881 void KillCalltip(WindowInfo *window, int calltipID);
882 +Boolean ShowScrolltip(textDisp* textD, const char* text, const int x,
883 + const int y);
884 +void KillScrolltip(textDisp* textD);
885 void TextDKillCalltip(textDisp *textD, int calltipID);
886 -int GetCalltipID(WindowInfo *window, int calltipID);
887 +int GetCalltipID(const WindowInfo *window);
888 void TextDRedrawCalltip(textDisp *textD, int calltipID);
889 +int HighlightCalltipLine(const WindowInfo* window, const int calltipID,
890 + const unsigned line);
892 #endif /* ifndef NEDIT_CALLTIPS_H_INCLUDED */
893 diff --quilt old/source/file.c new/source/file.c
894 --- old/source/file.c
895 +++ new/source/file.c
896 @@ -30,19 +30,22 @@ static const char CVSID[] = "$Id: file.c
897 #ifdef HAVE_CONFIG_H
898 #include "../config.h"
899 #endif
901 #include "file.h"
903 +#include "backup.h"
904 #include "textBuf.h"
905 #include "text.h"
906 #include "window.h"
907 #include "preferences.h"
908 #include "undo.h"
909 #include "menu.h"
910 #include "tags.h"
911 #include "server.h"
912 #include "interpret.h"
913 +#include "macro.h"
914 #include "../util/misc.h"
915 #include "../util/DialogF.h"
916 #include "../util/fileUtils.h"
917 #include "../util/getfiles.h"
918 #include "../util/printUtils.h"
919 @@ -73,10 +76,15 @@ static const char CVSID[] = "$Id: file.c
920 #include <Xm/ToggleB.h>
921 #include <Xm/FileSB.h>
922 #include <Xm/RowColumn.h>
923 #include <Xm/Form.h>
924 #include <Xm/Label.h>
925 +#include <Xm/PushB.h>
927 +/* What kinds of backup files to make -- see
928 + table `version_control_values' in backup.c. */
929 +static enum backup_mode version_control;
931 #ifdef HAVE_DEBUG_H
932 #include "../debug.h"
933 #endif
935 @@ -84,22 +92,22 @@ static const char CVSID[] = "$Id: file.c
936 The periodic check is only performed on buffer modification, and the check
937 interval is only to prevent checking on every keystroke in case of a file
938 system which is slow to process stat requests (which I'm not sure exists) */
939 #define MOD_CHECK_INTERVAL 3000
941 +#define MAX_X_ARGS 20 /* Maximum number of X arguments */
943 static int doSave(WindowInfo *window);
944 static void safeClose(WindowInfo *window);
945 static int doOpen(WindowInfo *window, const char *name, const char *path,
946 int flags);
947 static void backupFileName(WindowInfo *window, char *name, size_t len);
948 static int writeBckVersion(WindowInfo *window);
949 static int bckError(WindowInfo *window, const char *errString, const char *file);
950 static int fileWasModifiedExternally(WindowInfo *window);
951 static const char *errorString(void);
952 static void addWrapNewlines(WindowInfo *window);
953 -static void setFormatCB(Widget w, XtPointer clientData, XtPointer callData);
954 -static void addWrapCB(Widget w, XtPointer clientData, XtPointer callData);
955 static int cmpWinAgainstFile(WindowInfo *window, const char *fileName);
956 static int min(int i1, int i2);
957 static void modifiedWindowDestroyedCB(Widget w, XtPointer clientData,
958 XtPointer callData);
959 static void forceShowLineNumbers(WindowInfo *window);
960 @@ -107,11 +115,11 @@ static void forceShowLineNumbers(WindowI
961 #ifdef VMS
962 void removeVersionNumber(char *fileName);
963 #endif /*VMS*/
965 WindowInfo *EditNewFile(WindowInfo *inWindow, char *geometry, int iconic,
966 - const char *languageMode, const char *defaultPath)
967 + const char* languageMode, const char* defaultPath, Boolean transient)
969 char name[MAXPATHLEN];
970 WindowInfo *window;
972 /*... test for creatability? */
973 @@ -143,11 +151,19 @@ WindowInfo *EditNewFile(WindowInfo *inWi
975 if (iconic && IsIconic(window))
976 RaiseDocument(window);
977 else
978 RaiseDocumentWindow(window);
981 + if (transient) {
982 + /* Set the window to transient mode. */
983 + String apParams[1];
985 + apParams[0] = "1";
986 + XtCallActionProc(window->lastFocus, "set_transient", NULL, apParams, 1);
989 SortTabBar(window);
990 return window;
994 @@ -173,11 +189,11 @@ WindowInfo *EditExistingFile(WindowInfo
995 const char *path, int flags, char *geometry, int iconic,
996 const char *languageMode, int tabbed, int bgOpen)
998 WindowInfo *window;
999 char fullname[MAXPATHLEN];
1002 /* first look to see if file is already displayed in a window */
1003 window = FindWindowWithFile(name, path);
1004 if (window != NULL) {
1005 if (!bgOpen) {
1006 if (iconic)
1007 @@ -248,10 +264,13 @@ WindowInfo *EditExistingFile(WindowInfo
1008 strcat(fullname, name);
1009 if(GetPrefAlwaysCheckRelTagsSpecs())
1010 AddRelTagsFile(GetPrefTagFile(), path, TAG);
1011 AddToPrevOpenMenu(fullname);
1013 + /* file_open_hook() */
1014 + MacroApplyHook(window, "file_open_hook", 0, NULL, NULL);
1016 return window;
1019 void RevertToSaved(WindowInfo *window)
1021 @@ -337,11 +356,11 @@ static int doOpen(WindowInfo *window, co
1022 int fileLen, readLen;
1023 char *fileString, *c;
1024 FILE *fp = NULL;
1025 int fd;
1026 int resp;
1029 /* initialize lock reasons */
1030 CLEAR_ALL_LOCKS(window->lockReasons);
1032 /* Update the window data structure */
1033 strcpy(window->filename, name);
1034 @@ -536,10 +555,14 @@ static int doOpen(WindowInfo *window, co
1037 SET_TMBD_LOCKED(window->lockReasons, TRUE);
1038 for (c = fileString; c < &fileString[readLen]; c++) {
1039 if (*c == '\0') {
1040 + /* Looks like every NUL character is replaced with:
1041 + ISO 8859-1: LATIN SMALL LETTER THORN
1042 + ISO 8859-7: GREEK SMALL LETTER OMEGA WITH TONOS
1043 + UTF-8: <unused> */
1044 *c = (char) 0xfe;
1047 window->buffer->nullSubsChar = (char) 0xfe;
1049 @@ -705,20 +728,21 @@ int CloseFileAndWindow(WindowInfo *windo
1051 /* Make sure that the window is not in iconified state */
1052 if (window->fileChanged)
1053 RaiseDocumentWindow(window);
1055 - /* If the window is a normal & unmodified file or an empty new file,
1056 - or if the user wants to ignore external modifications then
1057 - just close it. Otherwise ask for confirmation first. */
1058 - if (!window->fileChanged &&
1059 - /* Normal File */
1060 - ((!window->fileMissing && window->lastModTime > 0) ||
1061 - /* New File*/
1062 - (window->fileMissing && window->lastModTime == 0) ||
1063 - /* File deleted/modified externally, ignored by user. */
1064 - !GetPrefWarnFileMods()))
1065 + /* If the document is transient, belongs to a normal & unmodified file
1066 + or is empty and unchanged, or if the user wants to ignore external
1067 + modifications then just close it. Otherwise ask for confirmation first. */
1068 + if (window->transient
1069 + || (!window->fileChanged
1070 + /* Normal document, already saved */
1071 + && ((!window->fileMissing && window->lastModTime > 0)
1072 + /* New document, unchanged yet */
1073 + || (window->fileMissing && window->lastModTime == 0)
1074 + /* File deleted/modified externally, ignored by user. */
1075 + || !GetPrefWarnFileMods())))
1077 CloseWindow(window);
1078 /* up-to-date windows don't have outstanding backup files to close */
1079 } else
1081 @@ -908,10 +932,11 @@ static int doSave(WindowInfo *window)
1082 char *fileString = NULL;
1083 char fullname[MAXPATHLEN];
1084 struct stat statbuf;
1085 FILE *fp;
1086 int fileLen, result;
1087 + DataValue* fileNameArg = (DataValue*) XtMalloc(sizeof(DataValue));
1089 /* Get the full name of the file */
1090 strcpy(fullname, window->path);
1091 strcat(fullname, window->filename);
1093 @@ -1045,10 +1070,14 @@ static int doSave(WindowInfo *window)
1094 window->fileMissing = TRUE;
1095 window->device = 0;
1096 window->inode = 0;
1099 + fileNameArg->tag = STRING_TAG;
1100 + AllocNStringNCpy(&fileNameArg->val.str, fullname, MAXPATHLEN);
1101 + MacroApplyHook(window, "post_save_hook", 1, fileNameArg, NULL);
1103 return TRUE;
1107 ** Create a backup file for the current window. The name for the backup file
1108 @@ -1182,38 +1211,52 @@ static void backupFileName(WindowInfo *w
1110 static int writeBckVersion(WindowInfo *window)
1112 #ifndef VMS
1113 char fullname[MAXPATHLEN], bckname[MAXPATHLEN];
1114 + char* backname;
1115 struct stat statbuf;
1116 int in_fd, out_fd;
1117 char *io_buffer;
1118 + off_t fileLen;
1119 #define IO_BUFFER_SIZE ((size_t)(1024*1024))
1121 /* Do only if version backups are turned on */
1122 if (!window->saveOldVersion) {
1123 return False;
1126 + /* First fime numbered backup files are used. */
1127 + if (unset == version_control) {
1128 + initialize_backups();
1131 /* Get the full name of the file */
1132 strcpy(fullname, window->path);
1133 strcat(fullname, window->filename);
1135 + backname = generate_backup_filename(version_control, fullname);
1136 + if ((fileLen = strlen(backname)) < MAXPATHLEN) {
1137 + strncpy(bckname, backname, sizeof(bckname));
1139 + free(backname);
1141 /* Generate name for old version */
1142 - if ((strlen(fullname) + 5) > (size_t) MAXPATHLEN) {
1143 + if (fileLen >= (size_t) MAXPATHLEN) {
1144 return bckError(window, "file name too long", window->filename);
1146 - sprintf(bckname, "%s.bck", fullname);
1148 /* Delete the old backup file */
1149 /* Errors are ignored; we'll notice them later. */
1150 remove(bckname);
1152 /* open the file being edited. If there are problems with the
1153 old file, don't bother the user, just skip the backup */
1154 in_fd = open(fullname, O_RDONLY);
1155 if (in_fd<0) {
1156 + /* This is rather surprising behavior. Let's see more about the error. */
1157 + perror("nedit: Error reading edited file");
1158 return FALSE;
1161 /* Get permissions of the file.
1162 We preserve the normal permissions but not ownership, extended
1163 @@ -1415,162 +1458,98 @@ void PrintString(const char *string, int
1164 #endif /*VMS*/
1165 return;
1169 -** Wrapper for GetExistingFilename which uses the current window's path
1170 -** (if set) as the default directory.
1171 +** Wrapper for GetFilenameByDialog()
1173 +** TODO: I stopped the refactoring here for now, but these two could
1174 +** be combined into some sort of PromptFor.*File().
1176 int PromptForExistingFile(WindowInfo *window, char *prompt, char *fullname)
1178 - char *savedDefaultDir;
1179 - int retVal;
1181 - /* Temporarily set default directory to window->path, prompt for file,
1182 - then, if the call was unsuccessful, restore the original default
1183 - directory */
1184 - savedDefaultDir = GetFileDialogDefaultDirectory();
1185 - if (*window->path != '\0')
1186 - SetFileDialogDefaultDirectory(window->path);
1187 - retVal = GetExistingFilename(window->shell, prompt, fullname);
1188 - if (retVal != GFN_OK)
1189 - SetFileDialogDefaultDirectory(savedDefaultDir);
1191 - XtFree(savedDefaultDir);
1192 + gfbdParams params;
1193 + gfbdValue* gfbdrc;
1194 + int rc = GFN_ERROR;
1196 + params.dialogTitle = prompt;
1197 + params.parentShell = window->shell;
1198 + params.fileExists = True;
1199 + params.textfieldLabel = (GetPrefStdOpenDialog() ? "File Name" : NULL);
1200 + params.defaultName = NULL;
1201 + params.haveFormatButtons = False;
1202 + /* ...so no file format for wrap info necessary. */
1203 + params.showHidden = GetPrefShowHiddenFiles();
1205 + gfbdrc = GetFilenameByDialog(params);
1207 + switch(gfbdrc->status) {
1208 + case GFDB_OK:
1209 + strncpy(fullname, gfbdrc->payload, MAXPATHLEN);
1210 + rc = GFN_OK;
1211 + break;
1212 + case GFDB_CANCEL:
1213 + rc = GFN_CANCEL;
1214 + break;
1215 + case GFDB_ERROR:
1216 + fprintf(stderr, "nedit: Error while calling GetFilenameByDialog(): %s\n", gfbdrc->payload);
1217 + rc = GFN_ERROR;
1218 + break;
1219 + default:
1220 + /* fallback */
1221 + fprintf(stderr, "nedit: Unexpected error in GetFilenameByDialog().\n");
1222 + rc = GFN_ERROR;
1223 + break;
1226 - return retVal;
1227 + return rc;
1231 -** Wrapper for HandleCustomNewFileSB which uses the current window's path
1232 -** (if set) as the default directory, and asks about embedding newlines
1233 -** to make wrapping permanent.
1234 +** Wrapper for GetFilenameByDialog()
1236 int PromptForNewFile(WindowInfo *window, char *prompt, char *fullname,
1237 int *fileFormat, int *addWrap)
1239 - int n, retVal;
1240 - Arg args[20];
1241 - XmString s1, s2;
1242 - Widget fileSB, wrapToggle;
1243 - Widget formatForm, formatBtns, unixFormat, dosFormat, macFormat;
1244 - char *savedDefaultDir;
1246 - *fileFormat = window->fileFormat;
1248 - /* Temporarily set default directory to window->path, prompt for file,
1249 - then, if the call was unsuccessful, restore the original default
1250 - directory */
1251 - savedDefaultDir = GetFileDialogDefaultDirectory();
1252 - if (*window->path != '\0')
1253 - SetFileDialogDefaultDirectory(window->path);
1255 - /* Present a file selection dialog with an added field for requesting
1256 - long line wrapping to become permanent via inserted newlines */
1257 - n = 0;
1258 - XtSetArg(args[n],
1259 - XmNselectionLabelString,
1260 - s1 = XmStringCreateLocalized("New File Name:")); n++;
1261 - XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
1262 - XtSetArg(args[n],
1263 - XmNdialogTitle,
1264 - s2 = XmStringCreateSimple(prompt)); n++;
1265 - fileSB = CreateFileSelectionDialog(window->shell,"FileSelect",args,n);
1266 - XmStringFree(s1);
1267 - XmStringFree(s2);
1268 - formatForm = XtVaCreateManagedWidget("formatForm", xmFormWidgetClass,
1269 - fileSB, NULL);
1270 - formatBtns = XtVaCreateManagedWidget("formatBtns",
1271 - xmRowColumnWidgetClass, formatForm,
1272 - XmNradioBehavior, XmONE_OF_MANY,
1273 - XmNorientation, XmHORIZONTAL,
1274 - XmNpacking, XmPACK_TIGHT,
1275 - XmNtopAttachment, XmATTACH_FORM,
1276 - XmNleftAttachment, XmATTACH_FORM,
1277 - NULL);
1278 - XtVaCreateManagedWidget("formatBtns", xmLabelWidgetClass, formatBtns,
1279 - XmNlabelString, s1=XmStringCreateSimple("Format:"), NULL);
1280 - XmStringFree(s1);
1281 - unixFormat = XtVaCreateManagedWidget("unixFormat",
1282 - xmToggleButtonWidgetClass, formatBtns,
1283 - XmNlabelString, s1 = XmStringCreateSimple("Unix"),
1284 - XmNset, *fileFormat == UNIX_FILE_FORMAT,
1285 - XmNuserData, (XtPointer)UNIX_FILE_FORMAT,
1286 - XmNmarginHeight, 0,
1287 - XmNalignment, XmALIGNMENT_BEGINNING,
1288 - XmNmnemonic, 'U',
1289 - NULL);
1290 - XmStringFree(s1);
1291 - XtAddCallback(unixFormat, XmNvalueChangedCallback, setFormatCB,
1292 - fileFormat);
1293 - dosFormat = XtVaCreateManagedWidget("dosFormat",
1294 - xmToggleButtonWidgetClass, formatBtns,
1295 - XmNlabelString, s1 = XmStringCreateSimple("DOS"),
1296 - XmNset, *fileFormat == DOS_FILE_FORMAT,
1297 - XmNuserData, (XtPointer)DOS_FILE_FORMAT,
1298 - XmNmarginHeight, 0,
1299 - XmNalignment, XmALIGNMENT_BEGINNING,
1300 - XmNmnemonic, 'O',
1301 - NULL);
1302 - XmStringFree(s1);
1303 - XtAddCallback(dosFormat, XmNvalueChangedCallback, setFormatCB,
1304 - fileFormat);
1305 - macFormat = XtVaCreateManagedWidget("macFormat",
1306 - xmToggleButtonWidgetClass, formatBtns,
1307 - XmNlabelString, s1 = XmStringCreateSimple("Macintosh"),
1308 - XmNset, *fileFormat == MAC_FILE_FORMAT,
1309 - XmNuserData, (XtPointer)MAC_FILE_FORMAT,
1310 - XmNmarginHeight, 0,
1311 - XmNalignment, XmALIGNMENT_BEGINNING,
1312 - XmNmnemonic, 'M',
1313 - NULL);
1314 - XmStringFree(s1);
1315 - XtAddCallback(macFormat, XmNvalueChangedCallback, setFormatCB,
1316 - fileFormat);
1317 - if (window->wrapMode == CONTINUOUS_WRAP) {
1318 - wrapToggle = XtVaCreateManagedWidget("addWrap",
1319 - xmToggleButtonWidgetClass, formatForm,
1320 - XmNlabelString, s1 = XmStringCreateSimple("Add line breaks where wrapped"),
1321 - XmNalignment, XmALIGNMENT_BEGINNING,
1322 - XmNmnemonic, 'A',
1323 - XmNtopAttachment, XmATTACH_WIDGET,
1324 - XmNtopWidget, formatBtns,
1325 - XmNleftAttachment, XmATTACH_FORM,
1326 - NULL);
1327 - XtAddCallback(wrapToggle, XmNvalueChangedCallback, addWrapCB,
1328 - addWrap);
1329 - XmStringFree(s1);
1331 - *addWrap = False;
1332 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_FILTER_LABEL),
1333 - XmNmnemonic, 'l',
1334 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_FILTER_TEXT),
1335 - NULL);
1336 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST_LABEL),
1337 - XmNmnemonic, 'D',
1338 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST),
1339 - NULL);
1340 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST_LABEL),
1341 - XmNmnemonic, 'F',
1342 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST),
1343 - NULL);
1344 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_SELECTION_LABEL),
1345 - XmNmnemonic, prompt[strspn(prompt, "lFD")],
1346 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_TEXT),
1347 - NULL);
1348 - AddDialogMnemonicHandler(fileSB, FALSE);
1349 - RemapDeleteKey(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_FILTER_TEXT));
1350 - RemapDeleteKey(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_TEXT));
1351 - retVal = HandleCustomNewFileSB(fileSB, fullname,
1352 - window->filenameSet ? window->filename : NULL);
1353 + gfbdParams params;
1354 + gfbdValue* gfbdrc;
1355 + int rc = GFN_ERROR;
1357 + params.dialogTitle = prompt;
1358 + params.parentShell = window->shell;
1359 + params.fileExists = False;
1360 + params.textfieldLabel = "New File Name";
1361 + params.defaultName = window->filenameSet ? window->filename : NULL;
1362 + params.haveFormatButtons = True;
1363 + params.fileFormat = window->fileFormat;
1364 + params.isContWrapped = (CONTINUOUS_WRAP == window->wrapMode);
1365 + params.showHidden = GetPrefShowHiddenFiles();
1367 - if (retVal != GFN_OK)
1368 - SetFileDialogDefaultDirectory(savedDefaultDir);
1369 + gfbdrc = GetFilenameByDialog(params);
1370 + *addWrap = False;
1372 - XtFree(savedDefaultDir);
1373 + switch(gfbdrc->status) {
1374 + case GFDB_OK:
1375 + strncpy(fullname, gfbdrc->payload, MAXPATHLEN);
1376 + *addWrap = gfbdrc->addWrap;
1377 + rc = GFN_OK;
1378 + break;
1379 + case GFDB_CANCEL:
1380 + rc = GFN_CANCEL;
1381 + break;
1382 + case GFDB_ERROR:
1383 + fprintf(stderr, "nedit: Error while calling GetFilenameByDialog(): %s\n", gfbdrc->payload);
1384 + rc = GFN_ERROR;
1385 + break;
1386 + default:
1387 + /* fallback */
1388 + fprintf(stderr, "nedit: Unexpected error in GetFilenameByDialog().\n");
1389 + rc = GFN_ERROR;
1390 + break;
1393 - return retVal;
1394 + return rc;
1398 ** Find a name for an untitled file, unique in the name space of in the opened
1399 ** files in this session, i.e. Untitled or Untitled_nn, and write it into
1400 @@ -1882,56 +1861,10 @@ void removeVersionNumber(char *fileName)
1401 *versionStart = '\0';
1403 #endif /*VMS*/
1406 -** Callback procedure for File Format toggle buttons. Format is stored
1407 -** in userData field of widget button
1409 -static void setFormatCB(Widget w, XtPointer clientData, XtPointer callData)
1411 - if (XmToggleButtonGetState(w)) {
1412 - XtPointer userData;
1413 - XtVaGetValues(w, XmNuserData, &userData, NULL);
1414 - *(int*) clientData = (int) userData;
1419 -** Callback procedure for toggle button requesting newlines to be inserted
1420 -** to emulate continuous wrapping.
1422 -static void addWrapCB(Widget w, XtPointer clientData, XtPointer callData)
1424 - int resp;
1425 - int *addWrap = (int *)clientData;
1427 - if (XmToggleButtonGetState(w))
1429 - resp = DialogF(DF_WARN, w, 2, "Add Wrap",
1430 - "This operation adds permanent line breaks to\n"
1431 - "match the automatic wrapping done by the\n"
1432 - "Continuous Wrap mode Preferences Option.\n\n"
1433 - "*** This Option is Irreversable ***\n\n"
1434 - "Once newlines are inserted, continuous wrapping\n"
1435 - "will no longer work automatically on these lines", "OK",
1436 - "Cancel");
1437 - if (resp == 2)
1439 - XmToggleButtonSetState(w, False, False);
1440 - *addWrap = False;
1441 - } else
1443 - *addWrap = True;
1445 - } else
1447 - *addWrap = False;
1452 ** Change a window created in NEdit's continuous wrap mode to the more
1453 ** conventional Unix format of embedded newlines. Indicate to the user
1454 ** by turning off Continuous Wrap mode.
1456 static void addWrapNewlines(WindowInfo *window)
1457 diff --quilt old/source/file.h new/source/file.h
1458 --- old/source/file.h
1459 +++ new/source/file.h
1460 @@ -35,16 +35,21 @@
1461 /* flags for EditExistingFile */
1462 #define CREATE 1
1463 #define SUPPRESS_CREATE_WARN 2
1464 #define PREF_READ_ONLY 4
1466 +/* These were once set in util/getfiles.h and used throughout NEdit; they
1467 + were moved here to lower coupling between util/getfiles.c and the rest
1468 + of NEdit. */
1469 +enum gfnResult {GFN_OK, GFN_CANCEL, GFN_ERROR};
1471 #define PROMPT_SBC_DIALOG_RESPONSE 0
1472 #define YES_SBC_DIALOG_RESPONSE 1
1473 #define NO_SBC_DIALOG_RESPONSE 2
1475 WindowInfo *EditNewFile(WindowInfo *inWindow, char *geometry, int iconic,
1476 - const char *languageMode, const char *defaultPath);
1477 + const char *languageMode, const char *defaultPath, Boolean transient);
1478 WindowInfo *EditExistingFile(WindowInfo *inWindow, const char *name,
1479 const char *path, int flags, char *geometry, int iconic,
1480 const char *languageMode, int tabbed, int bgOpen);
1481 void RevertToSaved(WindowInfo *window);
1482 int SaveWindow(WindowInfo *window);
1483 diff --quilt old/source/help.c new/source/help.c
1484 --- old/source/help.c
1485 +++ new/source/help.c
1486 @@ -6,11 +6,11 @@ static const char CVSID[] = "$Id: help.c
1487 * Copyright (C) 1999 Mark Edel *
1489 * This is free software; you can redistribute it and/or modify it under the *
1490 * terms of the GNU General Public License as published by the Free Software *
1491 * Foundation; either version 2 of the License, or (at your option) any later *
1492 -* version. In addition, you may distribute version of this program linked to *
1493 +* version. In addition, you may distribute versions of this program linked to *
1494 * Motif or Open Motif. See README for details. *
1496 * This software is distributed in the hope that it will be useful, but WITHOUT *
1497 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
1498 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
1499 @@ -598,42 +598,48 @@ static Widget createHelpPanel(enum HelpT
1500 form = XtVaCreateManagedWidget("helpForm", xmFormWidgetClass, appShell,
1501 NULL);
1502 XtVaSetValues(form, XmNshadowThickness, 0, NULL);
1504 /* Create the bottom row of buttons */
1505 - btn = XtVaCreateManagedWidget("find", xmPushButtonWidgetClass, form,
1506 + btn = XtVaCreateManagedWidget("find",
1507 + xmPushButtonWidgetClass, form,
1508 XmNlabelString, st1=XmStringCreateSimple("Find..."),
1509 XmNmnemonic, 'F',
1510 XmNbottomAttachment, XmATTACH_FORM,
1511 XmNleftAttachment, XmATTACH_POSITION,
1512 XmNleftPosition, 3,
1513 XmNrightAttachment, XmATTACH_POSITION,
1514 XmNrightPosition, 25,
1515 + XmNtraversalOn, False,
1516 NULL);
1517 XtAddCallback(btn, XmNactivateCallback, searchHelpCB, appShell);
1518 XmStringFree(st1);
1520 - btn = XtVaCreateManagedWidget("findAgain", xmPushButtonWidgetClass, form,
1521 + btn = XtVaCreateManagedWidget("findAgain",
1522 + xmPushButtonWidgetClass, form,
1523 XmNlabelString, st1=XmStringCreateSimple("Find Again"),
1524 XmNmnemonic, 'A',
1525 XmNbottomAttachment, XmATTACH_FORM,
1526 XmNleftAttachment, XmATTACH_POSITION,
1527 XmNleftPosition, 27,
1528 XmNrightAttachment, XmATTACH_POSITION,
1529 XmNrightPosition, 49,
1530 + XmNtraversalOn, False,
1531 NULL);
1532 XtAddCallback(btn, XmNactivateCallback, searchHelpAgainCB, appShell);
1533 XmStringFree(st1);
1535 - btn = XtVaCreateManagedWidget("print", xmPushButtonWidgetClass, form,
1536 + btn = XtVaCreateManagedWidget("print",
1537 + xmPushButtonWidgetClass, form,
1538 XmNlabelString, st1=XmStringCreateSimple("Print..."),
1539 XmNmnemonic, 'P',
1540 XmNbottomAttachment, XmATTACH_FORM,
1541 XmNleftAttachment, XmATTACH_POSITION,
1542 XmNleftPosition, 51,
1543 XmNrightAttachment, XmATTACH_POSITION,
1544 XmNrightPosition, 73,
1545 + XmNtraversalOn, False,
1546 NULL);
1547 XtAddCallback(btn, XmNactivateCallback, printCB, appShell);
1548 XmStringFree(st1);
1550 closeBtn = XtVaCreateManagedWidget("close",
1551 @@ -642,79 +648,89 @@ static Widget createHelpPanel(enum HelpT
1552 XmNbottomAttachment, XmATTACH_FORM,
1553 XmNleftAttachment, XmATTACH_POSITION,
1554 XmNleftPosition, 75,
1555 XmNrightAttachment, XmATTACH_POSITION,
1556 XmNrightPosition, 97,
1557 + XmNtraversalOn, False,
1558 NULL);
1559 XtAddCallback(closeBtn, XmNactivateCallback, closeCB, appShell);
1560 XmStringFree(st1);
1562 /* Create the next row of buttons (for navigation) */
1563 - btn = XtVaCreateManagedWidget("prevTopic", xmPushButtonWidgetClass, form,
1564 + btn = XtVaCreateManagedWidget("prevTopic",
1565 + xmPushButtonWidgetClass, form,
1566 XmNlabelString, st1=XmStringCreateSimple("<< Browse"),
1567 XmNmnemonic, 'o',
1568 XmNbottomAttachment, XmATTACH_WIDGET,
1569 XmNbottomWidget, closeBtn,
1570 XmNleftAttachment, XmATTACH_POSITION,
1571 XmNleftPosition, 51,
1572 XmNrightAttachment, XmATTACH_POSITION,
1573 XmNrightPosition, 73,
1574 + XmNtraversalOn, False,
1575 NULL);
1576 XtAddCallback(btn, XmNactivateCallback, prevTopicCB, appShell);
1577 XmStringFree(st1);
1579 - btn = XtVaCreateManagedWidget("nextTopic", xmPushButtonWidgetClass, form,
1580 + btn = XtVaCreateManagedWidget("nextTopic",
1581 + xmPushButtonWidgetClass, form,
1582 XmNlabelString, st1=XmStringCreateSimple("Browse >>"),
1583 XmNmnemonic, 'e',
1584 XmNbottomAttachment, XmATTACH_WIDGET,
1585 XmNbottomWidget, closeBtn,
1586 XmNleftAttachment, XmATTACH_POSITION,
1587 XmNleftPosition, 75,
1588 XmNrightAttachment, XmATTACH_POSITION,
1589 XmNrightPosition, 97,
1590 + XmNtraversalOn, False,
1591 NULL);
1592 XtAddCallback(btn, XmNactivateCallback, nextTopicCB, appShell);
1593 XmStringFree(st1);
1595 - btn = XtVaCreateManagedWidget("histBack", xmPushButtonWidgetClass, form,
1596 + btn = XtVaCreateManagedWidget("histBack",
1597 + xmPushButtonWidgetClass, form,
1598 XmNlabelString, st1=XmStringCreateSimple("Back"),
1599 XmNmnemonic, 'B',
1600 XmNbottomAttachment, XmATTACH_WIDGET,
1601 XmNbottomWidget, closeBtn,
1602 XmNleftAttachment, XmATTACH_POSITION,
1603 XmNleftPosition, 3,
1604 XmNrightAttachment, XmATTACH_POSITION,
1605 XmNrightPosition, 25,
1606 + XmNtraversalOn, False,
1607 NULL);
1608 XtAddCallback(btn, XmNactivateCallback, bwHistoryCB, appShell);
1609 XmStringFree(st1);
1611 - btnFW = XtVaCreateManagedWidget("histForw", xmPushButtonWidgetClass, form,
1612 + btnFW = XtVaCreateManagedWidget("histForw",
1613 + xmPushButtonWidgetClass, form,
1614 XmNlabelString, st1=XmStringCreateSimple("Forward"),
1615 XmNmnemonic, 'w',
1616 XmNbottomAttachment, XmATTACH_WIDGET,
1617 XmNbottomWidget, closeBtn,
1618 XmNleftAttachment, XmATTACH_POSITION,
1619 XmNleftPosition, 27,
1620 XmNrightAttachment, XmATTACH_POSITION,
1621 XmNrightPosition, 49,
1622 + XmNtraversalOn, False,
1623 NULL);
1624 XtAddCallback(btnFW, XmNactivateCallback, fwHistoryCB, appShell);
1625 XmStringFree(st1);
1627 /* Create a text widget inside of a scrolled window widget */
1628 - sw = XtVaCreateManagedWidget("sw", xmScrolledWindowWidgetClass, form,
1629 + sw = XtVaCreateManagedWidget("sw",
1630 + xmScrolledWindowWidgetClass, form,
1631 XmNshadowThickness, 2,
1632 XmNtopAttachment, XmATTACH_FORM,
1633 XmNleftAttachment, XmATTACH_FORM,
1634 XmNrightAttachment, XmATTACH_FORM,
1635 XmNbottomAttachment, XmATTACH_WIDGET,
1636 XmNbottomWidget, btnFW,
1637 NULL);
1638 hScrollBar = XtVaCreateManagedWidget("hScrollBar",
1639 xmScrollBarWidgetClass, sw,
1640 - XmNorientation, XmHORIZONTAL,
1641 + XmNorientation, XmHORIZONTAL,
1642 XmNrepeatDelay, 10,
1643 NULL);
1644 vScrollBar = XtVaCreateManagedWidget("vScrollBar",
1645 xmScrollBarWidgetClass, sw,
1646 XmNorientation, XmVERTICAL,
1647 @@ -733,15 +749,16 @@ static Widget createHelpPanel(enum HelpT
1648 textNvScrollBar, vScrollBar,
1649 textNreadOnly, True,
1650 textNcontinuousWrap, True,
1651 textNautoShowInsertPos, True,
1652 NULL);
1653 - XtVaSetValues(sw, XmNworkWindow, HelpTextPanes[topic],
1654 + XtVaSetValues(sw,
1655 + XmNworkWindow, HelpTextPanes[topic],
1656 XmNhorizontalScrollBar, hScrollBar,
1657 XmNverticalScrollBar, vScrollBar,
1658 NULL);
1661 /* Initialize help style information, if it hasn't already been init'd */
1662 initHelpStyles (HelpTextPanes[topic]);
1664 /* Put together the text to display and separate it into parallel text
1665 and style data for display by the widget */
1666 @@ -802,11 +819,10 @@ static void changeTopicOrRaise(int exist
1668 RaiseShellWindow(HelpWindows[newTopic], True);
1669 adaptNavigationButtons(existingTopic);
1670 adaptNavigationButtons(newTopic);
1676 ** Callbacks for window controls
1678 @@ -900,12 +916,22 @@ static void searchHelpCB(Widget w, XtPoi
1679 static void searchHelpAgainCB(Widget w, XtPointer clientData,
1680 XtPointer callData)
1682 int topic;
1684 - if ((topic = findTopicFromShellWidget((Widget)clientData)) == -1)
1685 - return; /* shouldn't happen */
1686 + if ((topic = findTopicFromShellWidget((Widget)clientData)) == -1) {
1687 + /* shouldn't happen */
1688 + fprintf(stderr, "nedit: Unexpected location found in help.c\n");
1689 + return;
1692 + if (0 == strcmp(LastSearchString, "")) {
1693 + /* no previous search */
1694 + XBell(TheDisplay, 0);
1695 + return;
1698 searchHelpText(HelpWindows[topic], topic, LastSearchString,
1699 LastSearchWasAllTopics, LastSearchPos, LastSearchTopic);
1702 static void printCB(Widget w, XtPointer clientData, XtPointer callData)
1703 @@ -1005,16 +1031,10 @@ static void followHyperlink(int topic, i
1704 adaptNavigationButtons(topic);
1706 XtFree (link_text);
1709 -static void helpFocusButtonsAP(Widget w, XEvent *event, String *args,
1710 - Cardinal *nArgs)
1712 - XmProcessTraversal(w, XmTRAVERSE_NEXT_TAB_GROUP);
1716 * handler for help-button-action(<button-name>)
1717 * Calls the activate callback for the named button widget of the help text win.
1719 static void helpButtonActionAP(Widget w, XEvent *event, String *args,
1720 @@ -1148,11 +1168,10 @@ static void helpHyperlinkAP(Widget w, XE
1721 void InstallHelpLinkActions(XtAppContext context)
1723 static XtActionsRec Actions[] =
1725 {"help-hyperlink", helpHyperlinkAP},
1726 - {"help-focus-buttons", helpFocusButtonsAP},
1727 {"help-button-action", helpButtonActionAP}
1730 XtAppAddActions(context, Actions, XtNumber(Actions));
1732 diff --quilt old/source/highlightData.c new/source/highlightData.c
1733 --- old/source/highlightData.c
1734 +++ new/source/highlightData.c
1735 @@ -546,14 +546,14 @@ static char *DefaultPatternSets[] = {
1736 Wrong logical ops:\"&&|\\|\\|\":::Plain::\n\
1737 Logical operators:\"~|&|\\|\":::Text Arg2::}",
1738 "NEdit Macro:2:0{\n\
1739 README:\"NEdit Macro syntax highlighting patterns, version 2.6, maintainer Thorsten Haude, nedit at thorstenhau.de\":::Flag::D\n\
1740 Comment:\"#\":\"$\"::Comment::\n\
1741 - 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\
1742 + 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\
1743 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\
1744 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\
1745 - 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\
1746 + 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\
1747 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\
1748 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\
1749 Keyword:\"<(?:break|continue|define|delete|else|for|if|in|return|while)>\":::Keyword::\n\
1750 Braces:\"[{}\\[\\]]\":::Keyword::\n\
1751 Global Variable:\"\\$[A-Za-z0-9_]+\":::Identifier1::\n\
1752 diff --quilt old/source/interpret.c new/source/interpret.c
1753 --- old/source/interpret.c
1754 +++ new/source/interpret.c
1755 @@ -199,11 +199,11 @@ static SparseArrayEntryWrapper *Allocate
1757 /* Message strings used in macros (so they don't get repeated every time
1758 the macros are used */
1759 static const char *StackOverflowMsg = "macro stack overflow";
1760 static const char *StackUnderflowMsg = "macro stack underflow";
1761 -static const char *StringToNumberMsg = "string could not be converted to number";
1762 +static const char* StringToNumberMsg = "string '%s' could not be converted to number";
1764 /* Temporary global data for use while accumulating programs */
1765 static Symbol *LocalSymList = NULL; /* symbols local to the program */
1766 static Inst Prog[PROGRAM_SIZE]; /* the program */
1767 static Inst *ProgP; /* next free spot for code gen. */
1768 @@ -597,10 +597,13 @@ int ContinueMacro(RestartData *continuat
1769 ErrMsg = NULL;
1770 for (;;) {
1772 /* Execute an instruction */
1773 inst = PC++;
1774 +// fprintf(stderr, "inst->sym->name: %s\n", inst->sym->name);
1775 +// fprintf(stderr, "inst->sym->type: %d\n", inst->sym->type);
1776 +// fprintf(stderr, "inst->sym->value.tag: %d\n", inst->sym->value.tag);
1777 status = (inst->func)();
1779 /* If error return was not STAT_OK, return to caller */
1780 if (status != STAT_OK) {
1781 if (status == STAT_PREEMPT) {
1782 @@ -1198,12 +1201,13 @@ static void freeSymbolTable(Symbol *symT
1783 #define POP_INT(number) \
1784 if (StackP == TheStack) \
1785 return execError(StackUnderflowMsg, ""); \
1786 --StackP; \
1787 if (StackP->tag == STRING_TAG) { \
1788 - if (!StringToNum(StackP->val.str.rep, &number)) \
1789 - return execError(StringToNumberMsg, ""); \
1790 + if (!StringToNum(StackP->val.str.rep, &number)) {\
1791 + return execError(StringToNumberMsg, StackP->val.str.rep); \
1792 + } \
1793 } else if (StackP->tag == INT_TAG) \
1794 number = StackP->val.n; \
1795 else \
1796 return(execError("can't convert array to integer", NULL));
1798 @@ -1316,13 +1320,17 @@ static int pushSymVal(void)
1799 return execError(errMsg, s->name);
1801 *StackP = result;
1802 } else
1803 return execError("reading non-variable: %s", s->name);
1805 +/* typeof()
1806 if (StackP->tag == NO_TAG) {
1807 - return execError("variable not set: %s", s->name);
1808 + return execError("variable not set: %s", s->name);
1812 StackP++;
1813 if (StackP >= &TheStack[STACK_SIZE]) {
1814 return execError(StackOverflowMsg, "");
1816 return STAT_OK;
1817 @@ -1423,13 +1431,15 @@ static int pushArraySymVal(void)
1818 if (initEmpty && dataPtr->tag == NO_TAG) {
1819 dataPtr->tag = ARRAY_TAG;
1820 dataPtr->val.arrayPtr = ArrayNew();
1823 +/* typeof()
1824 if (dataPtr->tag == NO_TAG) {
1825 return execError("variable not set: %s", sym->name);
1829 *StackP = *dataPtr;
1830 StackP++;
1832 if (StackP >= &TheStack[STACK_SIZE]) {
1833 @@ -3081,17 +3091,21 @@ static int arrayRef(void)
1836 POP(srcArray)
1837 if (srcArray.tag == ARRAY_TAG) {
1838 if (!ArrayGet(&srcArray, keyString, &valueItem)) {
1839 - return(execError("referenced array value not in array: %s", keyString));
1840 +/*typeof() return(execError("referenced array value not in array: %s", keyString));*/
1841 + valueItem.tag = NO_TAG;
1843 PUSH(valueItem)
1844 return(STAT_OK);
1846 else {
1847 - return(execError("operator [] on non-array", NULL));
1848 +/*typeof() return(execError("operator [] on non-array", NULL));*/
1849 + valueItem.tag = NO_TAG;
1850 + PUSH(valueItem)
1851 + return(STAT_OK);
1854 else {
1855 POP(srcArray)
1856 if (srcArray.tag == ARRAY_TAG) {
1857 @@ -3494,10 +3508,11 @@ static int execError(const char *s1, con
1858 static char msg[MAX_ERR_MSG_LEN];
1859 static char *err = NULL;
1860 static int errlen = 0;
1862 sprintf(msg, s1, s2);
1863 + msg[MAX_ERR_MSG_LEN - 1] = '\0';
1864 ErrMsg = stackDumpStr(FrameP, msg, &err, &errlen);
1865 return STAT_ERROR;
1868 int StringToNum(const char *string, int *number)
1869 diff --quilt old/source/macro.c new/source/macro.c
1870 --- old/source/macro.c
1871 +++ new/source/macro.c
1872 @@ -30,35 +30,35 @@ static const char CVSID[] = "$Id: macro.
1874 #ifdef HAVE_CONFIG_H
1875 #include "../config.h"
1876 #endif
1878 +#include "calltips.h"
1879 +#include "highlightData.h"
1880 +#include "highlight.h"
1881 +#include "interpret.h"
1882 #include "macro.h"
1883 -#include "textBuf.h"
1884 -#include "text.h"
1885 #include "nedit.h"
1886 -#include "window.h"
1887 -#include "preferences.h"
1888 -#include "interpret.h"
1889 #include "parse.h"
1890 +#include "preferences.h"
1891 +#include "rangeset.h"
1892 +#include "rbTree.h"
1893 #include "search.h"
1894 +#include "selection.h"
1895 #include "server.h"
1896 #include "shell.h"
1897 #include "smartIndent.h"
1898 -#include "userCmds.h"
1899 -#include "selection.h"
1900 -#include "rbTree.h"
1901 #include "tags.h"
1902 -#include "calltips.h"
1903 +#include "textBuf.h"
1904 +#include "text.h"
1905 +#include "userCmds.h"
1906 +#include "window.h"
1907 #include "../util/DialogF.h"
1908 -#include "../util/misc.h"
1909 #include "../util/fileUtils.h"
1910 -#include "../util/utils.h"
1911 #include "../util/getfiles.h"
1912 -#include "highlight.h"
1913 -#include "highlightData.h"
1914 -#include "rangeset.h"
1915 +#include "../util/misc.h"
1916 +#include "../util/utils.h"
1918 #include <stdio.h>
1919 #include <stdlib.h>
1920 #include <string.h>
1921 #include <ctype.h>
1922 @@ -75,26 +75,27 @@ static const char CVSID[] = "$Id: macro.
1923 #ifndef __MVS__
1924 #include <sys/param.h>
1925 #endif
1926 #include <fcntl.h>
1927 #endif /*VMS*/
1928 +#include <stdarg.h>
1930 #include <X11/Intrinsic.h>
1931 #include <X11/keysym.h>
1932 #include <Xm/Xm.h>
1933 #include <Xm/CutPaste.h>
1934 +#include <Xm/DialogS.h>
1935 #include <Xm/Form.h>
1936 -#include <Xm/RowColumn.h>
1937 #include <Xm/LabelG.h>
1938 #include <Xm/List.h>
1939 -#include <Xm/ToggleB.h>
1940 -#include <Xm/DialogS.h>
1941 #include <Xm/MessageB.h>
1942 -#include <Xm/SelectioB.h>
1943 #include <Xm/PushB.h>
1944 -#include <Xm/Text.h>
1945 +#include <Xm/RowColumn.h>
1946 +#include <Xm/SelectioB.h>
1947 #include <Xm/Separator.h>
1948 +#include <Xm/Text.h>
1949 +#include <Xm/ToggleB.h>
1951 #ifdef HAVE_DEBUG_H
1952 #include "../debug.h"
1953 #endif
1955 @@ -233,10 +234,12 @@ static void stringDialogCloseCB(Widget w
1956 static void stringDialogEscCB(Widget w, XtPointer clientData, XEvent *event,
1957 Boolean *cont);
1958 #endif /* LESSTIF_VERSION */
1959 static int calltipMS(WindowInfo *window, DataValue *argList, int nArgs,
1960 DataValue *result, char **errMsg);
1961 +static int highlightCTLineMS(WindowInfo* window, DataValue* argList, int nArgs,
1962 + DataValue* result, char** errMsg);
1963 static int killCalltipMS(WindowInfo *window, DataValue *argList, int nArgs,
1964 DataValue *result, char **errMsg);
1965 /* T Balinski */
1966 static int listDialogMS(WindowInfo *window, DataValue *argList, int nArgs,
1967 DataValue *result, char **errMsg);
1968 @@ -350,19 +353,21 @@ static int calltipIDMV(WindowInfo *windo
1969 static int readSearchArgs(DataValue *argList, int nArgs, int*searchDirection,
1970 int *searchType, int *wrap, char **errMsg);
1971 static int wrongNArgsErr(char **errMsg);
1972 static int tooFewArgsErr(char **errMsg);
1973 static int strCaseCmp(char *str1, char *str2);
1974 -static int readIntArg(DataValue dv, int *result, char **errMsg);
1975 +static Boolean readIntArg(DataValue dv, int *result, char **errMsg);
1976 static int readStringArg(DataValue dv, char **result, char *stringStorage,
1977 char **errMsg);
1978 /* DISABLED FOR 5.4
1979 static int backlightStringMV(WindowInfo *window, DataValue *argList,
1980 int nArgs, DataValue *result, char **errMsg);
1982 static int rangesetListMV(WindowInfo *window, DataValue *argList,
1983 int nArgs, DataValue *result, char **errMsg);
1984 static int versionMV(WindowInfo* window, DataValue* argList, int nArgs,
1985 DataValue* result, char** errMsg);
1986 static int rangesetCreateMS(WindowInfo *window, DataValue *argList, int nArgs,
1987 DataValue *result, char **errMsg);
1988 static int rangesetDestroyMS(WindowInfo *window, DataValue *argList, int nArgs,
1989 @@ -405,10 +410,12 @@ static int getStyleAtPosMS(WindowInfo *w
1990 DataValue *result, char **errMsg);
1991 static int filenameDialogMS(WindowInfo* window, DataValue* argList, int nArgs,
1992 DataValue* result, char** errMsg);
1993 static int callMS(WindowInfo *window, DataValue *argList,
1994 int nArgs, DataValue *result, char **errMsg);
1995 +static int typeofMS(WindowInfo* window, DataValue* argList, int nArgs,
1996 + DataValue* result, char** errMsg);
1998 /* Built-in subroutines and variables for the macro language */
1999 static const BuiltInSubrName MacroSubrs[] = {
2000 { "length", lengthMS },
2001 { "get_range", getRangeMS },
2002 @@ -444,10 +451,11 @@ static const BuiltInSubrName MacroSubrs[
2003 { "getenv", getenvMS },
2004 { "string_compare", stringCompareMS },
2005 { "split", splitMS },
2006 { "calltip", calltipMS },
2007 { "kill_calltip", killCalltipMS },
2008 + { "highlight_calltip_line", highlightCTLineMS },
2009 /* DISABLED for 5.4
2010 { "set_backlight_string", setBacklightStringMS },
2012 { "rangeset_create", rangesetCreateMS },
2013 { "rangeset_destroy", rangesetDestroyMS },
2014 @@ -465,10 +473,11 @@ static const BuiltInSubrName MacroSubrs[
2015 { "get_pattern_at_pos", getPatternAtPosMS },
2016 { "get_style_by_name", getStyleByNameMS },
2017 { "get_style_at_pos", getStyleAtPosMS },
2018 { "filename_dialog", filenameDialogMS },
2019 { "call", callMS },
2020 + { "typeof", typeofMS },
2021 { NULL, NULL } /* sentinel */
2024 static const BuiltInSubrName SpecialVars[] = {
2025 { "$cursor", cursorMV },
2026 @@ -3420,10 +3430,61 @@ bad_arg:
2027 *errMsg = "unrecognized argument to %s";
2028 return False;
2032 +** highlight_calltip_line(ctID, line)
2034 +static int highlightCTLineMS(WindowInfo* window, DataValue* argList, int nArgs,
2035 + DataValue* result, char** errMsg)
2037 + int calltipID = 0;
2038 + int line;
2039 + int highlightResult;
2041 + if (2 != nArgs) {
2042 + *errMsg = "%s() called with wrong number of arguments";
2043 + return False;
2046 + if (!readIntArg(argList[0], &calltipID, errMsg)) {
2047 + *errMsg = "%s(): Could not read calltip ID from argument 1";
2048 + return False;
2051 + /* The macro function calltip() uses 0 to report an error. Catch sloppy
2052 + programmers who just feed this value into this function. */
2053 + if (0 == calltipID) {
2054 + *errMsg = "%s(): Invalid calltip ID 0";
2055 + return False;
2058 + if (!readIntArg(argList[1], &line, errMsg) || line < 0) {
2059 + *errMsg = "%s(): Could not read line number from argument 2";
2060 + return False;
2063 + result->tag = NO_TAG;
2065 + highlightResult = HighlightCalltipLine(window, calltipID, (unsigned) line);
2067 + if (CT_INVALID_ID == highlightResult) {
2068 + /* Fail only if the calltip ID given is invalid. */
2069 + *errMsg = "%s(): Invalid calltip ID";
2070 + return False;
2073 + /* In case NEdit ever gets a warning (!= error) mechanism:
2074 + if (CT_NOLINE == highlightResult) {
2075 + *warnMsg = "%s(): Calltip line out of range";
2077 + */
2079 + return True;
2083 ** A subroutine to kill the current calltip
2085 static int killCalltipMS(WindowInfo *window, DataValue *argList, int nArgs,
2086 DataValue *result, char **errMsg)
2088 @@ -3449,11 +3510,11 @@ static int killCalltipMS(WindowInfo *win
2090 static int calltipIDMV(WindowInfo *window, DataValue *argList,
2091 int nArgs, DataValue *result, char **errMsg)
2093 result->tag = INT_TAG;
2094 - result->val.n = GetCalltipID(window, 0);
2095 + result->val.n = GetCalltipID(window);
2096 return True;
2100 ** filename_dialog([title[, mode[, defaultPath[, filter[, defaultName]]]]])
2101 @@ -3478,19 +3539,20 @@ static int calltipIDMV(WindowInfo *windo
2103 static int filenameDialogMS(WindowInfo* window, DataValue* argList, int nArgs,
2104 DataValue* result, char** errMsg)
2106 char stringStorage[5][TYPE_INT_STR_SIZE(int)];
2107 - char filename[MAXPATHLEN + 1];
2108 char* title = "Choose Filename";
2109 char* mode = "exist";
2110 char* defaultPath = "";
2111 char* filter = "";
2112 char* defaultName = "";
2113 char* orgDefaultPath;
2114 char* orgFilter;
2115 - int gfnResult;
2116 + gfbdParams params;
2117 + gfbdValue* gfbdrc;
2118 + int rc = False;
2120 /* Ignore the focused window passed as the function argument and put
2121 the dialog up over the window which is executing the macro */
2122 window = MacroRunWindow();
2124 @@ -3545,37 +3607,56 @@ static int filenameDialogMS(WindowInfo*
2125 orgFilter = GetFileDialogDefaultPattern();
2126 if ('\0' != filter[0]) {
2127 SetFileDialogDefaultPattern(filter);
2130 - /* Fork to one of the worker methods from util/getfiles.c.
2131 - (This should obviously be refactored.) */
2132 - if (0 == strcmp(mode, "exist")) {
2133 - gfnResult = GetExistingFilename(window->shell, title, filename);
2134 - } else {
2135 - gfnResult = GetNewFilename(window->shell, title, filename, defaultName);
2136 - } /* Invalid values are weeded out above. */
2137 + params.dialogTitle = title;
2138 + params.parentShell = window->shell;
2139 + params.fileExists = (0 == strcmp(mode, "exist")) ? True : False;
2140 + params.textfieldLabel = "New File Name";
2141 + params.defaultName = (0 == strcmp("", defaultName)) ? NULL : defaultName;
2142 + params.haveFormatButtons = False;
2143 + /* ...so no file format for wrap info necessary. */
2144 + params.showHidden = GetPrefShowHiddenFiles();
2146 + gfbdrc = GetFilenameByDialog(params);
2148 /* Reset original values and free temps */
2149 SetFileDialogDefaultDirectory(orgDefaultPath);
2150 SetFileDialogDefaultPattern(orgFilter);
2151 XtFree(orgDefaultPath);
2152 XtFree(orgFilter);
2154 result->tag = STRING_TAG;
2155 - if (GFN_OK == gfnResult) {
2156 - /* Got a string, copy it to the result */
2157 - if (!AllocNStringNCpy(&result->val.str, filename, MAXPATHLEN)) {
2158 - M_FAILURE("failed to allocate return value: %s");
2160 - } else {
2161 - /* User cancelled. Return "" */
2162 - result->val.str.rep = PERM_ALLOC_STR("");
2163 - result->val.str.len = 0;
2164 + switch(gfbdrc->status) {
2165 + case GFDB_OK:
2166 + /* Got a filename, copy it to the result */
2167 + if (!AllocNStringNCpy(&result->val.str, gfbdrc->payload, MAXPATHLEN)) {
2168 + M_FAILURE("failed to allocate return value: %s");
2170 + rc = True;
2171 + break;
2172 + case GFDB_CANCEL:
2173 + /* User cancelled. Return "" */
2174 + result->val.str.rep = PERM_ALLOC_STR("");
2175 + result->val.str.len = 0;
2176 + rc = True;
2177 + break;
2178 + case GFDB_ERROR:
2179 + fprintf(stderr, "nedit: Error while calling GetFilenameByDialog(): %s\n", gfbdrc->payload);
2180 + *errMsg = "Error while calling GetFilenameByDialog() in %s";
2181 + rc = False;
2182 + break;
2183 + default:
2184 + /* fallback */
2185 + fprintf(stderr, "nedit: Unexpected error in GetFilenameByDialog().\n");
2186 + *errMsg = "Unexpected error in GetFilenameByDialog() in %s";
2187 + rc = False;
2188 + break;
2191 - return True;
2192 + return rc;
2196 * call(fnname, arg, ...)
2198 @@ -5854,10 +5956,56 @@ static int getPatternAtPosMS(WindowInfo
2199 return fillPatternResult(result, errMsg, window,
2200 HighlightNameOfCode(window, patCode), False, True,
2201 HighlightStyleOfCode(window, patCode), bufferPos);
2205 +** Returns a string containing a flag indicating the arguments type:
2206 +** ARRAY - Argument is an array
2207 +** INTEGER - Argument is an integer or a string that can be cleanly
2208 +** transformed into an integer.
2209 +** STRING - Argument is a string that cannot be cleanly transformed
2210 +** into an integer.
2211 +** UNDEFINED - Argument is undefined. No support for void functions though.
2213 +static int typeofMS(WindowInfo* window, DataValue* argList, int nArgs,
2214 + DataValue* result, char** errMsg)
2216 + int buffer;
2218 + /* Validate number of arguments. */
2219 + if (1 != nArgs) {
2220 + return wrongNArgsErr(errMsg);
2223 + /* Prepare result. */
2224 + result->tag = STRING_TAG;
2226 + switch (argList[0].tag) {
2227 + case STRING_TAG:
2228 + if (readIntArg(argList[0], &buffer, errMsg)) {
2229 + AllocNStringCpy(&result->val.str, "INTEGER");
2230 + } else {
2231 + AllocNStringCpy(&result->val.str, "STRING");
2233 + break;
2234 + case INT_TAG:
2235 + AllocNStringCpy(&result->val.str, "INTEGER");
2236 + break;
2237 + case ARRAY_TAG:
2238 + AllocNStringCpy(&result->val.str, "ARRAY");
2239 + break;
2240 + case NO_TAG:
2241 + AllocNStringCpy(&result->val.str, "UNDEFINED");
2242 + break;
2243 + default:
2244 + fprintf(stderr, "nedit: Internal error: Invalid type in typeofMS().\n");
2247 + return True;
2250 static int wrongNArgsErr(char **errMsg)
2252 *errMsg = "Wrong number of arguments to function %s";
2253 return False;
2255 @@ -5901,11 +6049,11 @@ static int strCaseCmp(char *str1, char *
2257 ** Get an integer value from a tagged DataValue structure. Return True
2258 ** if conversion succeeded, and store result in *result, otherwise
2259 ** return False with an error message in *errMsg.
2261 -static int readIntArg(DataValue dv, int *result, char **errMsg)
2262 +static Boolean readIntArg(DataValue dv, int *result, char **errMsg)
2264 char *c;
2266 if (dv.tag == INT_TAG) {
2267 *result = dv.val.n;
2268 @@ -5944,5 +6092,46 @@ static int readStringArg(DataValue dv, c
2269 return True;
2271 *errMsg = "%s called with unknown object";
2272 return False;
2275 +/* rough hack */
2276 +void MacroApplyHook(const WindowInfo* document, const char* hook, int argc,
2277 + DataValue* argv, DataValue* resultDV)
2279 + Symbol* hookSymbol;
2281 + hookSymbol = LookupSymbol(hook);
2282 + if (NULL != hookSymbol && MACRO_FUNCTION_SYM == hookSymbol->type) {
2283 + Program* hookProg = hookSymbol->value.val.prog;
2284 + RestartData* restartData;
2285 + DataValue dummyResultDV; /* Passed to ExecuteMacro() if no result requested */
2286 + int status;
2287 + char* errMsg;
2288 +// char statusT[1024];
2290 + /* Let 'er rip */
2291 + status = ExecuteMacro((WindowInfo*) document, hookProg, argc, argv,
2292 + (NULL == resultDV) ? &dummyResultDV : resultDV, &restartData,
2293 + &errMsg);
2294 +// switch (status)
2295 +// {
2296 +// case 0: strncpy(statusT, "MACRO_TIME_LIMIT", 1024); break;
2297 +// case 1: strncpy(statusT, "MACRO_PREEMPT", 1024); break;
2298 +// case 2: strncpy(statusT, "MACRO_DONE", 1024); break;
2299 +// case 3: strncpy(statusT, "MACRO_ERROR", 1024); break;
2300 +// default: strncpy(statusT, "UNKNOWN_ERROR", 1024);
2301 +// }
2302 +// fprintf(stderr, "\tstatus: %s\n", statusT);
2303 + while (MACRO_TIME_LIMIT == status) {
2304 + status = ContinueMacro(restartData,
2305 + (NULL == resultDV) ? &dummyResultDV : resultDV, &errMsg);
2308 + if (MACRO_PREEMPT == status || MACRO_ERROR == status) {
2309 + fprintf(stderr, "nedit: \"%s\" error: %s\n", hook, (MACRO_ERROR == status) ? errMsg : "No dialogs");
2310 + } else {
2311 + /* Macro is done here */
2315 diff --quilt old/source/macro.h new/source/macro.h
2316 --- old/source/macro.h
2317 +++ new/source/macro.h
2318 @@ -71,7 +71,10 @@ int ReadMacroString(WindowInfo *window,
2319 int CheckMacroString(Widget dialogParent, char *string, const char *errIn,
2320 char **errPos);
2321 char *GetReplayMacro(void);
2322 void ReadMacroInitFile(WindowInfo *window);
2323 void ReturnShellCommandOutput(WindowInfo *window, const char *outText, int status);
2324 +struct DataValueTag;
2325 +void MacroApplyHook(const WindowInfo* document, const char *hook, int argc,
2326 + struct DataValueTag* argv, struct DataValueTag* resultDV);
2328 #endif /* NEDIT_MACRO_H_INCLUDED */
2329 diff --quilt old/source/menu.c new/source/menu.c
2330 --- old/source/menu.c
2331 +++ new/source/menu.c
2332 @@ -50,10 +50,11 @@ static const char CVSID[] = "$Id: menu.c
2333 #include "highlight.h"
2334 #include "highlightData.h"
2335 #include "interpret.h"
2336 #include "smartIndent.h"
2337 #include "windowTitle.h"
2338 +#include "regularExp.h"
2339 #include "../util/getfiles.h"
2340 #include "../util/DialogF.h"
2341 #include "../util/misc.h"
2342 #include "../util/fileUtils.h"
2343 #include "../util/utils.h"
2344 @@ -177,10 +178,13 @@ static void bgMenuDefCB(Widget w, Window
2345 static void searchDlogsDefCB(Widget w, WindowInfo *window, caddr_t callData);
2346 static void beepOnSearchWrapDefCB(Widget w, WindowInfo *window, caddr_t callData);
2347 static void keepSearchDlogsDefCB(Widget w, WindowInfo *window,
2348 caddr_t callData);
2349 static void searchWrapsDefCB(Widget w, WindowInfo *window, caddr_t callData);
2350 +static void showHiddenFilesCB(Widget w, WindowInfo* window, caddr_t callData);
2351 static void appendLFCB(Widget w, WindowInfo* window, caddr_t callData);
2352 static void sortOpenPrevDefCB(Widget w, WindowInfo *window, caddr_t callData);
2353 static void reposDlogsDefCB(Widget w, WindowInfo *window, caddr_t callData);
2354 static void autoScrollDefCB(Widget w, WindowInfo *window, caddr_t callData);
2355 static void modWarnDefCB(Widget w, WindowInfo *window, caddr_t callData);
2356 @@ -189,10 +193,12 @@ static void exitWarnDefCB(Widget w, Wind
2357 static void searchLiteralCB(Widget w, WindowInfo *window, caddr_t callData);
2358 static void searchCaseSenseCB(Widget w, WindowInfo *window, caddr_t callData);
2359 static void searchLiteralWordCB(Widget w, WindowInfo *window, caddr_t callData);
2360 static void searchCaseSenseWordCB(Widget w, WindowInfo *window, caddr_t callData);
2361 static void searchRegexNoCaseCB(Widget w, WindowInfo *window, caddr_t callData);
2362 +static void searchRegexSmartCaseCB(Widget toggleButton, WindowInfo* windowInfo,
2363 + caddr_t callData);
2364 static void searchRegexCB(Widget w, WindowInfo *window, caddr_t callData);
2365 #ifdef REPLACE_SCOPE
2366 static void replaceScopeWindowCB(Widget w, WindowInfo *window, caddr_t callData);
2367 static void replaceScopeSelectionCB(Widget w, WindowInfo *window, caddr_t callData);
2368 static void replaceScopeSmartCB(Widget w, WindowInfo *window, caddr_t callData);
2369 @@ -392,10 +398,12 @@ static void setAutoIndentAP(Widget w, XE
2370 Cardinal *nArgs);
2371 static void setWrapTextAP(Widget w, XEvent *event, String *args,
2372 Cardinal *nArgs);
2373 static void setWrapMarginAP(Widget w, XEvent *event, String *args,
2374 Cardinal *nArgs);
2375 +static void setShowWrapMarginAP(Widget w, XEvent *event, String *args,
2376 + Cardinal *nArgs);
2377 static void setHighlightSyntaxAP(Widget w, XEvent *event, String *args,
2378 Cardinal *nArgs);
2379 static void setMakeBackupCopyAP(Widget w, XEvent *event, String *args,
2380 Cardinal *nArgs);
2381 static void setIncrementalBackupAP(Widget w, XEvent *event, String *args,
2382 @@ -406,10 +414,12 @@ static void setMatchSyntaxBasedAP(Widget
2383 Cardinal *nArgs);
2384 static void setOvertypeModeAP(Widget w, XEvent *event, String *args,
2385 Cardinal *nArgs);
2386 static void setLockedAP(Widget w, XEvent *event, String *args,
2387 Cardinal *nArgs);
2388 +static void setTransientAP(Widget text, XEvent* event, String* args,
2389 + Cardinal* nArgs);
2390 static void setUseTabsAP(Widget w, XEvent *event, String *args,
2391 Cardinal *nArgs);
2392 static void setEmTabDistAP(Widget w, XEvent *event, String *args,
2393 Cardinal *nArgs);
2394 static void setTabDistAP(Widget w, XEvent *event, String *args,
2395 @@ -566,19 +576,21 @@ static XtActionsRec Actions[] = {
2396 {"set_incremental_search_line", setIncrementalSearchLineAP},
2397 {"set_show_line_numbers", setShowLineNumbersAP},
2398 {"set_auto_indent", setAutoIndentAP},
2399 {"set_wrap_text", setWrapTextAP},
2400 {"set_wrap_margin", setWrapMarginAP},
2401 + {"set_show_wrap_margin", setShowWrapMarginAP},
2402 {"set_highlight_syntax", setHighlightSyntaxAP},
2403 #ifndef VMS
2404 {"set_make_backup_copy", setMakeBackupCopyAP},
2405 #endif
2406 {"set_incremental_backup", setIncrementalBackupAP},
2407 {"set_show_matching", setShowMatchingAP},
2408 {"set_match_syntax_based", setMatchSyntaxBasedAP},
2409 {"set_overtype_mode", setOvertypeModeAP},
2410 {"set_locked", setLockedAP},
2411 + {"set_transient", setTransientAP},
2412 {"set_tab_dist", setTabDistAP},
2413 {"set_em_tab_dist", setEmTabDistAP},
2414 {"set_use_tabs", setUseTabsAP},
2415 {"set_fonts", setFontsAP},
2416 {"set_language_mode", setLanguageModeAP}
2417 @@ -813,10 +825,13 @@ Widget CreateMenuBar(Widget parent, Wind
2418 XtSetSensitive(window->showTipItem, (TagsFileList != NULL ||
2419 TipsFileList != NULL) );
2422 ** Preferences menu, Default Settings sub menu
2423 + **
2424 + ** Mnemonics: L, A, W, C, T, F, u, d, g, H, S, i, N, e, B, M, o, P, r, z
2425 + ** A, B, C, d, e, F, g, H, i, L, M, N, o, P, r, S, T, u, W, z
2427 menuPane = createMenu(menuBar, "preferencesMenu", "Preferences", 0, NULL,
2428 SHORT);
2429 subPane = createMenu(menuPane, "defaultSettings", "Default Settings", 'D',
2430 NULL, FULL);
2431 @@ -926,12 +941,17 @@ Widget CreateMenuBar(Widget parent, Wind
2432 GetPrefSearch() == SEARCH_CASE_SENSE_WORD, FULL);
2433 window->searchRegexDefItem = createMenuToggle(subSubSubPane,
2434 "regularExpression", "Regular Expression", 'R', searchRegexCB,
2435 window, GetPrefSearch() == SEARCH_REGEX, FULL);
2436 window->searchRegexNoCaseDefItem = createMenuToggle(subSubSubPane,
2437 - "regularExpressionNoCase", "Regular Expression, Case Insensitive", 'I', searchRegexNoCaseCB, window,
2438 - GetPrefSearch() == SEARCH_REGEX_NOCASE, FULL);
2439 + "regularExpressionNoCase", "Regular Expression, Case Insensitive",
2440 + 'I', searchRegexNoCaseCB, window,
2441 + GetPrefSearch() == SEARCH_REGEX_NOCASE, FULL);
2442 + window->searchRegexSmartCaseDefItem = createMenuToggle(subSubSubPane,
2443 + "regularExpressionSmartCase", "Regular Expression, Smart Case",
2444 + 'S', searchRegexSmartCaseCB, window,
2445 + GetPrefSearch() == SEARCH_REGEX_SMARTCASE, FULL);
2446 #ifdef REPLACE_SCOPE
2447 subSubSubPane = createMenu(subSubPane, "defaultReplaceScope",
2448 "Default Replace Scope", 'R', NULL, FULL);
2449 XtVaSetValues(subSubSubPane, XmNradioBehavior, True, NULL);
2450 window->replScopeWinDefItem = createMenuToggle(subSubSubPane, "window",
2451 @@ -1015,10 +1035,20 @@ Widget CreateMenuBar(Widget parent, Wind
2452 createMenuSeparator(subSubPane, "sep", SHORT);
2453 window->matchSyntaxBasedDefItem = createMenuToggle(subSubPane,
2454 "matchSyntax", "Syntax Based", 'S', matchSyntaxBasedDefCB, window,
2455 GetPrefMatchSyntaxBased(), SHORT);
2457 + /* Show Hidden Files */
2458 + window->showHiddenFilesItem = createMenuToggle(subPane,
2459 + "showHiddenFilesItem", "Show hidden Files", 'y', showHiddenFilesCB,
2460 + NULL, GetPrefShowHiddenFiles(), FULL);
2462 /* Append LF at end of files on save */
2463 window->appendLFItem = createMenuToggle(subPane, "appendLFItem",
2464 "Terminate with Line Break on Save", 'v', appendLFCB, NULL,
2465 GetPrefAppendLF(), FULL);
2467 @@ -1141,10 +1171,12 @@ Widget CreateMenuBar(Widget parent, Wind
2468 createMenuSeparator(menuPane, "sep2", SHORT);
2469 window->overtypeModeItem = createMenuToggle(menuPane, "overtype", "Overtype", 'O',
2470 doActionCB, "set_overtype_mode", False, SHORT);
2471 window->readOnlyItem = createMenuToggle(menuPane, "readOnly", "Read Only",
2472 'y', doActionCB, "set_locked", IS_USER_LOCKED(window->lockReasons), FULL);
2473 + window->transientItem = createMenuToggle(menuPane, "transient", "Transient",
2474 + 'r', doActionCB, "set_transient", window->transient, FULL);
2475 #endif
2477 #ifndef VMS
2479 ** Create the Shell menu
2480 @@ -2175,10 +2208,41 @@ static void searchWrapsDefCB(Widget w, W
2481 if (IsTopDocument(win))
2482 XmToggleButtonSetState(win->searchWrapsDefItem, state, False);
2486 +static void showHiddenFilesCB(Widget widget, WindowInfo* unused,
2487 + caddr_t callData)
2489 + WindowInfo *window;
2490 + Boolean state = XmToggleButtonGetState(widget);
2492 + SetPrefShowHiddenFiles(state);
2493 + for (window = WindowList; window != NULL; window = window->next) {
2494 + XmToggleButtonSetState(window->showHiddenFilesItem, state, False);
2498 static void appendLFCB(Widget w, WindowInfo* window, caddr_t callData)
2500 WindowInfo *win;
2501 int state = XmToggleButtonGetState(w);
2503 @@ -2537,10 +2601,39 @@ static void searchRegexNoCaseCB(Widget w
2504 XmToggleButtonSetState(win->searchRegexNoCaseDefItem, True, False);
2509 +static void searchRegexSmartCaseCB(Widget toggleButton, WindowInfo* window,
2510 + caddr_t callData)
2512 + WindowInfo* windowInfo;
2514 + /* Set the preference and make the other windows' menus agree */
2515 + if (XmToggleButtonGetState(toggleButton)) {
2516 + SetPrefSearch(SEARCH_REGEX_SMARTCASE);
2517 + for (windowInfo = WindowList;
2518 + windowInfo != NULL;
2519 + windowInfo = windowInfo->next) {
2520 + XmToggleButtonSetState(windowInfo->searchLiteralDefItem,
2521 + False, False);
2522 + XmToggleButtonSetState(windowInfo->searchCaseSenseDefItem,
2523 + False, False);
2524 + XmToggleButtonSetState(windowInfo->searchLiteralWordDefItem,
2525 + False, False);
2526 + XmToggleButtonSetState(windowInfo->searchCaseSenseWordDefItem,
2527 + False, False);
2528 + XmToggleButtonSetState(windowInfo->searchRegexDefItem,
2529 + False, False);
2530 + XmToggleButtonSetState(windowInfo->searchRegexNoCaseDefItem,
2531 + False, False);
2532 + XmToggleButtonSetState(windowInfo->searchRegexSmartCaseDefItem,
2533 + True, False);
2538 #ifdef REPLACE_SCOPE
2539 static void replaceScopeWindowCB(Widget w, WindowInfo *window, caddr_t callData)
2541 WindowInfo *win;
2543 @@ -2714,51 +2807,59 @@ static void unloadTipsFileMenuCB(Widget
2545 static void newAP(Widget w, XEvent *event, String *args, Cardinal *nArgs)
2547 WindowInfo *window = WidgetToWindow(w);
2548 int openInTab = GetPrefOpenInTab();
2549 + Boolean transient = False;
2551 + /* Look for arguments managing the type of window requested and whether
2552 + or not the user wants to have a transient window. */
2553 if (*nArgs > 0) {
2554 - if (strcmp(args[0], "prefs") == 0) {
2555 + if (0 == strcmp(args[0], "prefs")) {
2556 /* accept default */;
2558 - else if (strcmp(args[0], "tab") == 0) {
2559 + } else if (0 == strcmp(args[0], "tab")) {
2560 openInTab = 1;
2562 - else if (strcmp(args[0], "window") == 0) {
2563 + } else if (0 == strcmp(args[0], "window")) {
2564 openInTab = 0;
2566 - else if (strcmp(args[0], "opposite") == 0) {
2567 + } else if (0 == strcmp(args[0], "opposite")) {
2568 openInTab = !openInTab;
2570 - else {
2571 + } else if (0 == strcmp(args[0], "transient")) {
2572 + transient = True;
2573 + } else {
2574 fprintf(stderr, "nedit: Unknown argument to action procedure \"new\": %s\n", args[0]);
2578 - EditNewFile(openInTab? window : NULL, NULL, False, NULL, window->path);
2580 + /* Catch transient if it comes after a window type argument */
2581 + if (2 == *nArgs && (0 == strcmp(args[1], "transient"))) {
2582 + transient = True;
2585 + EditNewFile(openInTab? window : NULL, NULL, False, NULL, window->path,
2586 + transient);
2587 CheckCloseDim();
2591 -** These are just here because our techniques make it hard to bind a menu item
2592 -** to an action procedure that takes arguments. The user doesn't need to know
2593 -** about them -- they can use new( "opposite" ) or new( "tab" ).
2594 +** newOppositeAP() and newTabAP() are just here because our techniques make
2595 +** it hard to bind a menu item to an action procedure that takes arguments.
2596 +** The user doesn't need to know about them -- they can use new("opposite")
2597 +** or new("tab").
2599 static void newOppositeAP(Widget w, XEvent *event, String *args, Cardinal *nArgs)
2601 WindowInfo *window = WidgetToWindow(w);
2603 EditNewFile(GetPrefOpenInTab()? NULL : window, NULL, False, NULL,
2604 - window->path);
2605 + window->path, False);
2606 CheckCloseDim();
2608 static void newTabAP(Widget w, XEvent *event, String *args, Cardinal *nArgs)
2610 WindowInfo *window = WidgetToWindow(w);
2612 - EditNewFile(window, NULL, False, NULL, window->path);
2613 + EditNewFile(window, NULL, False, NULL, window->path, False);
2614 CheckCloseDim();
2617 static void openDialogAP(Widget w, XEvent *event, String *args, Cardinal *nArgs)
2619 @@ -2781,21 +2882,31 @@ static void openDialogAP(Widget w, XEven
2621 static void openAP(Widget w, XEvent *event, String *args, Cardinal *nArgs)
2623 WindowInfo *window = WidgetToWindow(w);
2624 char filename[MAXPATHLEN], pathname[MAXPATHLEN];
2625 + DataValue* fileNameArg = (DataValue*) XtMalloc(sizeof(DataValue));
2626 + DataValue* resultDV = (DataValue*) XtMalloc(sizeof(DataValue));
2628 if (*nArgs == 0) {
2629 fprintf(stderr, "nedit: open action requires file argument\n");
2630 return;
2632 - if (0 != ParseFilename(args[0], filename, pathname)
2634 + fileNameArg->tag = STRING_TAG;
2635 + AllocNStringNCpy(&fileNameArg->val.str, args[0], MAXPATHLEN);
2636 + MacroApplyHook(window, "file_name_hook", 1, fileNameArg, resultDV);
2637 + XtFree((char*) fileNameArg);
2639 + if (0 != ParseFilename(resultDV->val.str.rep, filename, pathname)
2640 || strlen(filename) + strlen(pathname) > MAXPATHLEN - 1) {
2641 fprintf(stderr, "nedit: invalid file name for open action: %s\n",
2642 args[0]);
2643 return;
2645 + XtFree((char*) resultDV);
2647 EditExistingFile(window, filename, pathname, 0, NULL, False,
2648 NULL, GetPrefOpenInTab(), False);
2649 CheckCloseDim();
2652 @@ -4085,10 +4196,23 @@ static void setWrapMarginAP(Widget w, XE
2653 else {
2654 fprintf(stderr, "nedit: set_wrap_margin requires argument\n");
2658 +static void setShowWrapMarginAP(Widget w, XEvent *event, String *args,
2659 + Cardinal *nArgs)
2661 + WindowInfo *window = WidgetToWindow(w);
2662 + int showWrapMargin = 0;
2664 + if (*nArgs > 0) {
2665 + if (sscanf(args[0], "%d", &showWrapMargin) == 1) {
2666 + SetShowWrapMargin(window, showWrapMargin);
2671 static void setHighlightSyntaxAP(Widget w, XEvent *event, String *args,
2672 Cardinal *nArgs)
2674 WindowInfo *window = WidgetToWindow(w);
2675 Boolean newState;
2676 @@ -4209,10 +4333,28 @@ static void setLockedAP(Widget w, XEvent
2677 XmToggleButtonSetState(window->readOnlyItem, IS_ANY_LOCKED(window->lockReasons), False);
2678 UpdateWindowTitle(window);
2679 UpdateWindowReadOnly(window);
2683 +** Action procedure for setting or toggling the transient flag.
2685 +static void setTransientAP(Widget text, XEvent* event, String* args,
2686 + Cardinal* nArgs)
2688 + WindowInfo* window = WidgetToWindow(text);
2689 + Boolean newState;
2691 + ACTION_BOOL_PARAM_OR_TOGGLE(newState, *nArgs, args,
2692 + window->transient, "set_transient");
2694 + window->transient = newState;
2695 + if (IsTopDocument(window)) {
2696 + XmToggleButtonSetState(window->transientItem, window->transient, False);
2700 static void setTabDistAP(Widget w, XEvent *event, String *args,
2701 Cardinal *nArgs)
2703 WindowInfo *window = WidgetToWindow(w);
2705 @@ -4511,17 +4653,40 @@ static void invalidatePrevOpenMenus(void
2707 void AddToPrevOpenMenu(const char *filename)
2709 int i;
2710 char *nameCopy;
2711 + char *fileMask, *compileMsg;
2712 + regexp *compiledRE;
2713 WindowInfo *w;
2715 /* If the Open Previous command is disabled, just return */
2716 if (GetPrefMaxPrevOpenFiles() < 1) {
2717 return;
2720 + /* If the name is to be omitted, return */
2721 + if ((fileMask = GetPrevOpenFilesMask()) && *fileMask)
2723 + compiledRE = CompileRE(fileMask, &compileMsg, REDFLT_STANDARD);
2724 + if (compiledRE == NULL)
2726 + fprintf(stderr, "nedit: %s\n", compileMsg);
2727 + } else
2729 + if (ExecRE(compiledRE, filename, NULL, FALSE, '\0', '\0', NULL,
2730 + NULL, NULL))
2732 + free((char *)compiledRE);
2733 + return;
2734 + } else
2736 + free((char *)compiledRE);
2741 /* Refresh list of previously opened files to avoid Big Race Condition,
2742 where two sessions overwrite each other's changes in NEdit's
2743 history file.
2744 Of course there is still Little Race Condition, which occurs if a
2745 Session A reads the list, then Session B reads the list and writes
2746 @@ -4864,10 +5029,12 @@ static int cmpStrPtr(const void *strA, c
2747 void WriteNEditDB(void)
2749 const char* fullName = GetRCFileName(NEDIT_HISTORY);
2750 FILE *fp;
2751 int i;
2752 + char *fileMask, *compileMsg;
2753 + regexp *compiledRE=NULL;
2754 static char fileHeader[] =
2755 "# File name database for NEdit Open Previous command\n";
2757 if (fullName == NULL) {
2758 /* GetRCFileName() might return NULL if an error occurs during
2759 @@ -4900,23 +5067,48 @@ void WriteNEditDB(void)
2760 #else
2761 return;
2762 #endif
2765 + /* set up removal of any files matching prevOpenFilesMask */
2766 + if ((fileMask = GetPrevOpenFilesMask()) && *fileMask)
2768 + compiledRE = CompileRE(fileMask, &compileMsg, REDFLT_STANDARD);
2769 + if (compiledRE == NULL)
2771 + fprintf(stderr, "%s\n", compileMsg);
2775 /* write the file header text to the file */
2776 fprintf(fp, "%s", fileHeader);
2778 /* Write the list of file names */
2779 - for (i = 0; i < NPrevOpen; ++i) {
2780 - size_t lineLen = strlen(PrevOpen[i]);
2781 + for (i = 0; i < NPrevOpen; i++)
2783 + /* omitting any files matching prevOpenFilesMask */
2784 + if (NULL == compiledRE
2785 + || 0 == ExecRE(compiledRE, PrevOpen[i], NULL, FALSE, '\0', '\0',
2786 + NULL, NULL, NULL))
2788 + size_t lineLen = strlen(PrevOpen[i]);
2790 - if (lineLen > 0 && PrevOpen[i][0] != '#' &&
2791 - strcspn(PrevOpen[i], neditDBBadFilenameChars) == lineLen) {
2792 - fprintf(fp, "%s\n", PrevOpen[i]);
2793 + /* omitting any files with invalid filenames */
2794 + if (lineLen > 0 && '#' != PrevOpen[i][0]
2795 + && strcspn(PrevOpen[i], neditDBBadFilenameChars) == lineLen)
2797 + fprintf(fp, "%s\n", PrevOpen[i]);
2803 + if (compiledRE != NULL) {
2804 + free((char *)compiledRE);
2807 + /* Close the file */
2808 fclose(fp);
2812 ** Read database of file names for 'Open Previous' submenu.
2813 diff --quilt old/source/nedit.c new/source/nedit.c
2814 --- old/source/nedit.c
2815 +++ new/source/nedit.c
2816 @@ -352,15 +352,21 @@ static char *fallbackResources[] = {
2817 "*windowsMenu.splitPane.acceleratorText: Ctrl+2",
2818 "*windowsMenu.closePane.accelerator: Ctrl<Key>1",
2819 "*windowsMenu.closePane.acceleratorText: Ctrl+1",
2820 "*helpMenu.mnemonic: H",
2821 "nedit.help.helpForm.sw.helpText*baseTranslations: #override\
2822 -<Key>Tab:help-focus-buttons()\\n\
2823 +<Key>space: scroll_down(1, \"pages\")\\n\
2824 +~Alt~Shift~Ctrl~Meta<KeyPress>osfUp: scroll_up(1)\\n\
2825 +~Alt~Shift~Ctrl~Meta<KeyPress>osfDown: scroll_down(1)\\n\
2826 +~Alt ~Shift ~Ctrl ~Meta<KeyPress>osfPageUp: scroll_up(1, \"pages\")\\n\
2827 +~Alt ~Shift ~Ctrl ~Meta<KeyPress>osfPageDown: scroll_down(1, \"pages\")\\n\
2828 +~Alt~Shift~Ctrl~Meta<KeyPress>osfLeft: help-button-action(\"prevTopic\")\\n\
2829 +~Alt~Shift~Ctrl~Meta<KeyPress>osfRight: help-button-action(\"nextTopic\")\\n\
2830 <Key>Return:help-button-action(\"close\")\\n\
2831 -Ctrl<Key>F:help-button-action(\"find\")\\n\
2832 -Ctrl<Key>G:help-button-action(\"findAgain\")\\n\
2833 <KeyPress>osfCancel:help-button-action(\"close\")\\n\
2834 +Ctrl<Key>f:help-button-action(\"find\")\\n\
2835 +Ctrl<Key>g:help-button-action(\"findAgain\")\\n\
2836 ~Meta~Ctrl~Shift<Btn1Down>:\
2837 grab-focus() help-hyperlink()\\n\
2838 ~Meta~Ctrl~Shift<Btn1Up>:\
2839 help-hyperlink(\"current\", \"process-cancel\", \"extend-end\")\\n\
2840 ~Meta~Ctrl~Shift<Btn2Down>:\
2841 @@ -489,11 +495,11 @@ int main(int argc, char **argv)
2843 /* Initialize global symbols and subroutines used in the macro language */
2844 InitMacroGlobals();
2845 RegisterMacroSubroutines();
2847 - /* Store preferences from the command line and .nedit file,
2848 + /* Store preferences from the command line and the nedit.rc file,
2849 and set the appropriate preferences */
2850 RestoreNEditPrefs(prefDB, XtDatabase(TheDisplay));
2852 /* Intercept syntactically invalid virtual key bindings BEFORE we
2853 create any shells. */
2854 @@ -775,11 +781,11 @@ int main(int argc, char **argv)
2856 CheckCloseDim();
2858 /* If no file to edit was specified, open a window to edit "Untitled" */
2859 if (!fileSpecified) {
2860 - EditNewFile(NULL, geometry, iconic, langMode, NULL);
2861 + EditNewFile(NULL, geometry, iconic, langMode, NULL, False);
2862 ReadMacroInitFile(WindowList);
2863 CheckCloseDim();
2864 if (toDoCommand != NULL)
2865 DoMacro(WindowList, toDoCommand, "-do macro");
2867 diff --quilt old/source/nedit.h new/source/nedit.h
2868 --- old/source/nedit.h
2869 +++ new/source/nedit.h
2870 @@ -52,13 +52,14 @@
2871 #define NEDIT_DEFAULT_SEL_BG "rgb:cc/cc/cc"
2872 #define NEDIT_DEFAULT_HI_FG "white" /* These are colors for flashing */
2873 #define NEDIT_DEFAULT_HI_BG "red" /* matching parens. */
2874 #define NEDIT_DEFAULT_LINENO_FG "black"
2875 #define NEDIT_DEFAULT_CURSOR_FG "black"
2876 +#define NEDIT_DEFAULT_WRAPMARGIN_FG "black"
2877 #define NEDIT_DEFAULT_HELP_FG "black"
2878 #define NEDIT_DEFAULT_HELP_BG "rgb:cc/cc/cc"
2880 /* Tuning parameters */
2881 #define SEARCHMAX 5119 /* Maximum length of search/replace strings */
2882 #define MAX_SEARCH_HISTORY 100 /* Maximum length of search string history */
2883 #define MAX_PANES 6 /* Max # of ADDITIONAL text editing panes
2884 @@ -103,10 +104,12 @@
2885 enum indentStyle {NO_AUTO_INDENT, AUTO_INDENT, SMART_INDENT};
2886 enum wrapStyle {NO_WRAP, NEWLINE_WRAP, CONTINUOUS_WRAP};
2887 enum showMatchingStyle {NO_FLASH, FLASH_DELIMIT, FLASH_RANGE};
2888 enum virtKeyOverride { VIRT_KEY_OVERRIDE_NEVER, VIRT_KEY_OVERRIDE_AUTO,
2889 VIRT_KEY_OVERRIDE_ALWAYS };
2890 +enum showWrapMarginEnums {SHOW_WRAP_MARGIN_NEVER, SHOW_WRAP_MARGIN_ALWAYS,
2891 + SHOW_WRAP_MARGIN_ON_WRAP};
2893 /* This enum must be kept in parallel to the array TruncSubstitutionModes[]
2894 in preferences.c */
2895 enum truncSubstitution {TRUNCSUBST_SILENT, TRUNCSUBST_FAIL, TRUNCSUBST_WARN, TRUNCSUBST_IGNORE};
2897 @@ -191,10 +194,12 @@ enum colorTypes {
2898 SELECT_BG_COLOR,
2899 HILITE_FG_COLOR,
2900 HILITE_BG_COLOR,
2901 LINENO_FG_COLOR,
2902 CURSOR_FG_COLOR,
2903 + WRAPMARGIN_FG_COLOR,
2904 NUM_COLORS
2907 /* cache user menus: manage mode of user menu list element */
2908 typedef enum {
2909 @@ -325,10 +330,11 @@ typedef struct _WindowInfo {
2910 Widget replaceMultiFileList;
2911 Widget replaceMultiFilePathBtn;
2912 Widget fontDialog; /* NULL, unless font dialog is up */
2913 Widget colorDialog; /* NULL, unless color dialog is up */
2914 Widget readOnlyItem; /* menu bar settable widgets... */
2915 + Widget transientItem;
2916 Widget autoSaveItem;
2917 Widget saveLastItem;
2918 Widget openSelItem;
2919 Widget newOppositeItem;
2920 Widget closeItem;
2921 @@ -393,10 +399,12 @@ typedef struct _WindowInfo {
2922 Widget backlightCharsDefItem;
2923 Widget searchDlogsDefItem;
2924 Widget beepOnSearchWrapDefItem;
2925 Widget keepSearchDlogsDefItem;
2926 Widget searchWrapsDefItem;
2927 + Widget showHiddenFilesItem;
2928 Widget appendLFItem;
2929 Widget sortOpenPrevDefItem;
2930 Widget allTagsDefItem;
2931 Widget smartTagsDefItem;
2932 Widget reposDlogsDefItem;
2933 @@ -417,10 +425,11 @@ typedef struct _WindowInfo {
2934 Widget searchLiteralDefItem;
2935 Widget searchCaseSenseDefItem;
2936 Widget searchLiteralWordDefItem;
2937 Widget searchCaseSenseWordDefItem;
2938 Widget searchRegexNoCaseDefItem;
2939 + Widget searchRegexSmartCaseDefItem;
2940 Widget searchRegexDefItem;
2941 #ifdef REPLACE_SCOPE
2942 Widget replScopeWinDefItem;
2943 Widget replScopeSelDefItem;
2944 Widget replScopeSmartDefItem;
2945 @@ -495,10 +504,12 @@ typedef struct _WindowInfo {
2946 Boolean autoSave; /* is autosave turned on? */
2947 Boolean saveOldVersion; /* keep old version in filename.bck */
2948 char indentStyle; /* whether/how to auto indent */
2949 char wrapMode; /* line wrap style: NO_WRAP,
2950 NEWLINE_WRAP or CONTINUOUS_WRAP */
2951 + int showWrapMargin; /* show wrap margin style: NEVER,
2952 + ALWAYS, ON-WRAP as enums */
2953 Boolean overstrike; /* is overstrike mode turned on ? */
2954 char showMatchingStyle; /* How to show matching parens:
2955 NO_FLASH, FLASH_DELIMIT, or
2956 FLASH_RANGE */
2957 char matchSyntaxBased; /* Use syntax info to show matching */
2958 @@ -555,10 +566,11 @@ typedef struct _WindowInfo {
2959 #endif
2960 UserMenuCache *userMenuCache; /* cache user menus: */
2961 UserBGMenuCache userBGMenuCache; /* shell & macro menu are shared over all
2962 "tabbed" documents, while each document
2963 has its own background menu. */
2964 + Boolean transient;
2965 } WindowInfo;
2967 extern WindowInfo *WindowList;
2968 extern Display *TheDisplay;
2969 extern Widget TheAppShell;
2970 diff --quilt old/source/preferences.c new/source/preferences.c
2971 --- old/source/preferences.c
2972 +++ new/source/preferences.c
2973 @@ -115,13 +115,13 @@ enum fontStatus {GOOD_FONT, BAD_PRIMARY,
2974 ** The order of the elements in this array must be exactly the same
2975 ** as the order of the corresponding integers of the enum SearchType
2976 ** defined in search.h (!!)
2978 static char *SearchMethodStrings[] = {
2979 - "Literal", "CaseSense", "RegExp",
2980 - "LiteralWord", "CaseSenseWord", "RegExpNoCase",
2981 - NULL
2982 + "Literal", "CaseSense", "RegExp",
2983 + "LiteralWord", "CaseSenseWord", "RegExpNoCase", "RegExSmartCase",
2984 + NULL
2987 #ifdef REPLACE_SCOPE
2988 /* enumerated default scope for replace dialog if a selection exists when
2989 ** the dialog is popped up.
2990 @@ -138,10 +138,13 @@ static char *AutoWrapTypes[N_WRAP_STYLES
2991 static char *AutoIndentTypes[N_INDENT_STYLES+3] = {"None", "Auto",
2992 "Smart", "True", "False", NULL};
2993 #define N_VIRTKEY_OVERRIDE_MODES 3
2994 static char *VirtKeyOverrideModes[N_VIRTKEY_OVERRIDE_MODES+1] = { "Never",
2995 "Auto", "Always", NULL};
2996 +#define N_SHOW_WRAP_MARGIN_STYLES 3
2997 +static char *ShowWrapMarginStrings[N_SHOW_WRAP_MARGIN_STYLES+1] = { "Never",
2998 + "Always", "When Wrap is Enabled", NULL};
3000 #define N_SHOW_MATCHING_STYLES 3
3001 /* For backward compatibility, "False" and "True" are still accepted.
3002 They are internally converted to "Off" and "Delimiter" respectively.
3003 NOTE: N_SHOW_MATCHING_STYLES must correspond to the number of
3004 @@ -233,18 +236,23 @@ typedef struct {
3005 Widget hiliteBgErrW;
3006 Widget lineNoFgW;
3007 Widget lineNoFgErrW;
3008 Widget cursorFgW;
3009 Widget cursorFgErrW;
3010 + Widget wrapMarginFgW;
3011 + Widget wrapMarginFgErrW;
3012 WindowInfo *window;
3013 } colorDialog;
3015 /* Repository for simple preferences settings */
3016 static struct prefData {
3017 int openInTab; /* open files in new tabs */
3018 int wrapStyle; /* what kind of wrapping to do */
3019 int wrapMargin; /* 0=wrap at window width, other=wrap margin */
3020 + int showWrapMargin; /* whether to draw line at wrap margin */
3021 int autoIndent; /* style for auto-indent */
3022 int autoSave; /* whether automatic backup feature is on */
3023 int saveOldVersion; /* whether to preserve a copy of last version */
3024 int searchDlogs; /* whether to show explanatory search dialogs */
3025 int searchWrapBeep; /* 1=beep when search restarts at begin/end */
3026 @@ -293,14 +301,17 @@ static struct prefData {
3027 int sortTabs; /* sort tabs alphabetically */
3028 int repositionDialogs; /* w. to reposition dialogs under the pointer */
3029 int autoScroll; /* w. to autoscroll near top/bottom of screen */
3030 int autoScrollVPadding; /* how close to get before autoscrolling */
3031 int sortOpenPrevMenu; /* whether to sort the "Open Previous" menu */
3032 + int showHiddenFiles; /* whether to show hidden files in the FSBs */
3033 int appendLF; /* Whether to append LF at the end of each file */
3034 int mapDelete; /* whether to map delete to backspace */
3035 int stdOpenDialog; /* w. to retain redundant text field in Open */
3036 char tagFile[MAXPATHLEN]; /* name of tags file to look for at startup */
3037 + char prevOpenFilesMask[MAXPATHLEN]; /* regex to omit from Open Previous menu */
3038 int maxPrevOpenFiles; /* limit to size of Open Previous menu */
3039 int typingHidesPointer; /* hide mouse pointer when typing */
3040 char delimiters[MAX_WORD_DELIMITERS]; /* punctuation characters */
3041 char shell[MAXPATHLEN + 1]; /* shell to use for executing commands */
3042 char geometry[MAX_GEOM_STRING_LEN]; /* per-application geometry string,
3043 @@ -319,10 +330,11 @@ static struct prefData {
3044 char helpLinkColor[MAX_COLOR_LEN]; /* Color for hyperlinks in the help system */
3045 char colorNames[NUM_COLORS][MAX_COLOR_LEN];
3046 char tooltipBgColor[MAX_COLOR_LEN];
3047 int undoModifiesSelection;
3048 int focusOnRaise;
3049 + Boolean showScrolltip;
3050 Boolean honorSymlinks;
3051 int truncSubstitution;
3052 Boolean forceOSConversion;
3053 } PrefData;
3055 @@ -845,10 +857,12 @@ static PrefDescripRec PrefDescrip[] = {
3056 "Default", &TempStringPrefs.smartIndentCommon, NULL, True},
3057 {"autoWrap", "AutoWrap", PREF_ENUM, "Continuous",
3058 &PrefData.wrapStyle, AutoWrapTypes, True},
3059 {"wrapMargin", "WrapMargin", PREF_INT, "0",
3060 &PrefData.wrapMargin, NULL, True},
3061 + {"showWrapMargin", "ShowWrapMargin", PREF_ENUM, "Never",
3062 + &PrefData.showWrapMargin, ShowWrapMarginStrings, True},
3063 {"autoIndent", "AutoIndent", PREF_ENUM, "Auto",
3064 &PrefData.autoIndent, AutoIndentTypes, True},
3065 {"autoSave", "AutoSave", PREF_BOOLEAN, "True",
3066 &PrefData.autoSave, NULL, True},
3067 {"openInTab", "OpenInTab", PREF_BOOLEAN, "True",
3068 @@ -882,10 +896,12 @@ static PrefDescripRec PrefDescrip[] = {
3069 &PrefData.repositionDialogs, NULL, True},
3070 #else
3071 {"repositionDialogs", "RepositionDialogs", PREF_BOOLEAN, "True",
3072 &PrefData.repositionDialogs, NULL, True},
3073 #endif
3074 + {"showHiddenFiles", "ShowHiddenFiles", PREF_BOOLEAN, "True",
3075 + &PrefData.showHiddenFiles, NULL, True},
3076 {"autoScroll", "AutoScroll", PREF_BOOLEAN, "False",
3077 &PrefData.autoScroll, NULL, True},
3078 {"autoScrollVPadding", "AutoScrollVPadding", PREF_INT, "4",
3079 &PrefData.autoScrollVPadding, NULL, False},
3080 {"appendLF", "AppendLF", PREF_BOOLEAN, "True",
3081 @@ -1020,13 +1036,20 @@ static PrefDescripRec PrefDescrip[] = {
3082 PrefData.colorNames[LINENO_FG_COLOR],
3083 (void *)sizeof(PrefData.colorNames[LINENO_FG_COLOR]), True},
3084 {"cursorFgColor", "CursorFgColor", PREF_STRING, NEDIT_DEFAULT_CURSOR_FG,
3085 PrefData.colorNames[CURSOR_FG_COLOR],
3086 (void *)sizeof(PrefData.colorNames[CURSOR_FG_COLOR]), True},
3087 {"tooltipBgColor", "TooltipBgColor", PREF_STRING, "LemonChiffon1",
3088 PrefData.tooltipBgColor,
3089 (void *)sizeof(PrefData.tooltipBgColor), False},
3090 + {"wrapMarginForeground", "wrapMarginForeground", PREF_STRING,
3091 + NEDIT_DEFAULT_LINENO_FG, PrefData.colorNames[WRAPMARGIN_FG_COLOR],
3092 + (void *)sizeof(PrefData.colorNames[WRAPMARGIN_FG_COLOR]), True},
3093 {"shell", "Shell", PREF_STRING, "DEFAULT", PrefData.shell,
3094 (void*) sizeof(PrefData.shell), True},
3095 {"geometry", "Geometry", PREF_STRING, "",
3096 PrefData.geometry, (void *)sizeof(PrefData.geometry), False},
3097 {"remapDeleteKey", "RemapDeleteKey", PREF_BOOLEAN, "False",
3098 @@ -1038,10 +1061,13 @@ static PrefDescripRec PrefDescrip[] = {
3099 {"wordDelimiters", "WordDelimiters", PREF_STRING,
3100 ".,/\\`'!|@#%^&*()-=+{}[]\":;<>?",
3101 PrefData.delimiters, (void *)sizeof(PrefData.delimiters), False},
3102 {"serverName", "ServerName", PREF_STRING, "", PrefData.serverName,
3103 (void *)sizeof(PrefData.serverName), False},
3104 + {"prevOpenFilesMask", "PrevOpenFilesMask", PREF_STRING, "",
3105 + PrefData.prevOpenFilesMask,
3106 + (void*) sizeof(PrefData.prevOpenFilesMask), False},
3107 {"maxPrevOpenFiles", "MaxPrevOpenFiles", PREF_INT, "30",
3108 &PrefData.maxPrevOpenFiles, NULL, False},
3109 {"bgMenuButton", "BGMenuButton" , PREF_STRING,
3110 "~Shift~Ctrl~Meta~Alt<Btn3Down>", PrefData.bgMenuBtn,
3111 (void *)sizeof(PrefData.bgMenuBtn), False},
3112 @@ -1069,10 +1095,14 @@ static PrefDescripRec PrefDescrip[] = {
3113 "False", &PrefData.focusOnRaise, NULL, False},
3114 {"forceOSConversion", "ForceOSConversion", PREF_BOOLEAN, "True",
3115 &PrefData.forceOSConversion, NULL, False},
3116 {"truncSubstitution", "TruncSubstitution", PREF_ENUM, "Fail",
3117 &PrefData.truncSubstitution, TruncSubstitutionModes, False},
3118 + {"showScrolltip", "ShowScrolltip", PREF_BOOLEAN, "True",
3119 + &PrefData.showScrolltip, NULL, False},
3120 {"honorSymlinks", "HonorSymlinks", PREF_BOOLEAN, "True",
3121 &PrefData.honorSymlinks, NULL, False}
3124 static XrmOptionDescRec OpTable[] = {
3125 @@ -1124,11 +1154,13 @@ static WindowInfo *TabsDialogForWindow;
3126 static Widget TabDistText, EmTabText, EmTabToggle, UseTabsToggle, EmTabLabel;
3128 /* Module-global variables for Wrap Margin dialog */
3129 static int DoneWithWrapDialog;
3130 static WindowInfo *WrapDialogForWindow;
3131 -static Widget WrapText, WrapTextLabel, WrapWindowToggle;
3132 +static Widget WrapText, WrapTextLabel, WrapWindowToggle, ShowWrapMarginPulldown,
3133 + ShowWrapMarginPulldownItems[N_SHOW_WRAP_MARGIN_STYLES],
3134 + ShowWrapMarginOptMenu, ShowWrapMarginLabel;
3136 /* Module-global variables for shell selection dialog */
3137 static int DoneWithShellSelDialog = False;
3139 static void translatePrefFormats(int convertOld, int fileVer);
3140 @@ -1234,22 +1266,22 @@ static void updatePatternsTo5dot6(void);
3141 static void updateMacroCmdsTo5dot6(void);
3142 static void migrateColorResources(XrmDatabase prefDB, XrmDatabase appDB);
3143 static void spliceString(char **intoString, const char *insertString, const char *atExpr);
3144 static int regexFind(const char *inString, const char *expr);
3145 static int regexReplace(char **inString, const char *expr,
3146 - const char *replaceWith);
3147 + const char *replaceWith);
3148 +static void initPrefDefaultsFromResources(XrmDatabase prefDB, XrmDatabase appDB);
3149 static int caseFind(const char *inString, const char *expr);
3150 static int caseReplace(char **inString, const char *expr,
3151 const char *replaceWith, int replaceLen);
3152 static int stringReplace(char **inString, const char *expr,
3153 const char *replaceWith, int searchType,
3154 int replaceLen);
3155 static int replaceMacroIfUnchanged(const char* oldText, const char* newStart,
3156 const char* newEnd);
3157 static const char* getDefaultShell(void);
3160 #ifdef SGI_CUSTOM
3161 static int shortPrefToDefault(Widget parent, const char *settingName, int *setDefault);
3162 #endif
3164 XrmDatabase CreateNEditPrefDB(int *argcInOut, char **argvInOut)
3165 @@ -1264,10 +1296,14 @@ void RestoreNEditPrefs(XrmDatabase prefD
3166 int major; /* The integral part of version number */
3167 int minor; /* fractional part of version number */
3168 int fileVer = 0; /* Both combined into an integer */
3169 int nparsed;
3171 + /* Default values of certain preferences are derived from Motif resources,
3172 + if these resources are set. */
3173 + initPrefDefaultsFromResources(prefDB, appDB);
3175 /* Load preferences */
3176 RestorePreferences(prefDB, appDB, APP_NAME,
3177 APP_CLASS, PrefDescrip, XtNumber(PrefDescrip));
3179 /* If the preferences file was written by an older version of NEdit,
3180 @@ -1559,10 +1595,20 @@ void SetPrefWrapMargin(int margin)
3181 int GetPrefWrapMargin(void)
3183 return PrefData.wrapMargin;
3186 +void SetPrefShowWrapMargin(int state)
3188 + setIntPref(&PrefData.showWrapMargin, state);
3191 +int GetPrefShowWrapMargin(void)
3193 + return PrefData.showWrapMargin;
3196 void SetPrefSearch(int searchType)
3198 setIntPref(&PrefData.searchMethod, searchType);
3201 @@ -1930,10 +1976,20 @@ void SetPrefRepositionDialogs(int state)
3202 int GetPrefRepositionDialogs(void)
3204 return PrefData.repositionDialogs;
3207 +void SetPrefShowHiddenFiles(int state)
3209 + setIntPref(&PrefData.showHiddenFiles, state);
3212 +int GetPrefShowHiddenFiles(void)
3214 + return PrefData.showHiddenFiles;
3217 void SetPrefAutoScroll(int state)
3219 WindowInfo *w = WindowList;
3220 int margin = state ? PrefData.autoScrollVPadding : 0;
3222 @@ -2118,10 +2174,15 @@ char *GetPrefServerName(void)
3223 char *GetPrefBGMenuBtn(void)
3225 return PrefData.bgMenuBtn;
3228 +char *GetPrevOpenFilesMask(void)
3230 + return PrefData.prevOpenFilesMask;
3233 int GetPrefMaxPrevOpenFiles(void)
3235 return PrefData.maxPrevOpenFiles;
3238 @@ -2186,10 +2247,25 @@ int GetPrefOverrideVirtKeyBindings(void)
3239 int GetPrefTruncSubstitution(void)
3241 return PrefData.truncSubstitution;
3244 +Boolean GetPrefShowScrolltip(void)
3246 + return (Boolean) PrefData.showScrolltip;
3250 ** If preferences don't get saved, ask the user on exit whether to save
3252 void MarkPrefsChanged(void)
3254 @@ -2678,10 +2754,13 @@ void WrapMarginDialog(Widget parent, Win
3256 Widget form, selBox;
3257 Arg selBoxArgs[2];
3258 XmString s1;
3259 int margin;
3260 + int showWrapMargin;
3261 + int i, n;
3262 + Arg args[20];
3264 XtSetArg(selBoxArgs[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
3265 XtSetArg(selBoxArgs[1], XmNautoUnmanage, False);
3266 selBox = CreatePromptDialog(parent, "wrapMargin", selBoxArgs, 2);
3267 XtAddCallback(selBox, XmNokCallback, (XtCallbackProc)wrapOKCB, NULL);
3268 @@ -2720,20 +2799,74 @@ void WrapMarginDialog(Widget parent, Win
3269 XmNrightWidget, WrapText,
3270 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
3271 XmNbottomWidget, WrapText, NULL);
3272 XmStringFree(s1);
3274 + ShowWrapMarginPulldown = CreatePulldownMenu(form, "ShowWrapMarginPulldown",
3275 + NULL, 0);
3276 + for(i=0; i<N_SHOW_WRAP_MARGIN_STYLES; i++) {
3277 + s1 = XmStringCreateSimple(ShowWrapMarginStrings[i]);
3278 + ShowWrapMarginPulldownItems[i] = XtVaCreateManagedWidget(
3279 + "ShowWrapMarginPulldown",
3280 + xmPushButtonWidgetClass, ShowWrapMarginPulldown,
3281 + XmNlabelString, s1,
3282 + XmNmarginHeight, 0,
3283 + XmNuserData, i,
3284 + NULL);
3285 + XmStringFree(s1);
3287 + n = 0;
3288 + XtSetArg(args[n], XmNspacing, 0); n++;
3289 + XtSetArg(args[n], XmNmarginWidth, 0); n++;
3290 + XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
3291 + XtSetArg(args[n], XmNtopWidget, WrapText); n++;
3292 + XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
3293 + XtSetArg(args[n], XmNsubMenuId, ShowWrapMarginPulldown); n++;
3294 + ShowWrapMarginOptMenu = XmCreateOptionMenu(form,
3295 + "ShowWrapMarginOptMenu", args, n);
3296 + XtManageChild(ShowWrapMarginOptMenu);
3298 + ShowWrapMarginLabel = XtVaCreateManagedWidget("ShowWrapMarginLabel",
3299 + xmLabelGadgetClass, form,
3300 + XmNlabelString, s1=XmStringCreateSimple("Show Wrap Margin"),
3301 + XmNmnemonic, 'S',
3302 + XmNuserData, XtParent(ShowWrapMarginOptMenu),
3303 + XmNalignment, XmALIGNMENT_END,
3304 + XmNtopAttachment, XmATTACH_WIDGET,
3305 + XmNtopWidget, WrapText,
3306 + XmNleftAttachment, XmATTACH_FORM,
3307 + XmNrightAttachment, XmATTACH_WIDGET,
3308 + XmNrightWidget, ShowWrapMarginOptMenu,
3309 + XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
3310 + XmNbottomWidget, ShowWrapMarginOptMenu,
3311 + NULL);
3312 + XmStringFree(s1);
3314 /* Set default value */
3315 - if (forWindow == NULL)
3316 + if (forWindow == NULL) {
3317 margin = GetPrefWrapMargin();
3318 - else
3319 + showWrapMargin = GetPrefShowWrapMargin();
3320 + } else {
3321 XtVaGetValues(forWindow->textArea, textNwrapMargin, &margin, NULL);
3322 + showWrapMargin = forWindow->showWrapMargin;
3325 + if (showWrapMargin > N_SHOW_WRAP_MARGIN_STYLES || showWrapMargin < 0)
3327 + fprintf(stderr, "nedit: internal error: illegal value for showWrapMargin: %d\n", showWrapMargin);
3328 + showWrapMargin = SHOW_WRAP_MARGIN_NEVER;
3331 XmToggleButtonSetState(WrapWindowToggle, margin==0, True);
3332 + XtVaSetValues(ShowWrapMarginOptMenu, XmNmenuHistory,
3333 + ShowWrapMarginPulldownItems[showWrapMargin], NULL);
3334 if (margin != 0)
3335 SetIntText(WrapText, margin);
3336 XtSetSensitive(WrapText, margin!=0);
3337 XtSetSensitive(WrapTextLabel, margin!=0);
3338 + XtSetSensitive(ShowWrapMarginOptMenu, margin!=0);
3339 + XtSetSensitive(ShowWrapMarginLabel, margin!=0);
3341 /* Handle mnemonic selection of buttons and focus to dialog */
3342 AddDialogMnemonicHandler(form, FALSE);
3344 /* put up dialog and wait for user to press ok or cancel */
3345 @@ -2752,10 +2885,12 @@ void WrapMarginDialog(Widget parent, Win
3347 static void wrapOKCB(Widget w, XtPointer clientData, XtPointer callData)
3349 int wrapAtWindow, margin, stat;
3350 WindowInfo *window = WrapDialogForWindow;
3351 + int showWrapMargin;
3352 + Widget showWrapMarginSelectedItem;
3354 /* get the values that the user entered and make sure they're ok */
3355 wrapAtWindow = XmToggleButtonGetState(WrapWindowToggle);
3356 if (wrapAtWindow)
3357 margin = 0;
3358 @@ -2771,10 +2906,17 @@ static void wrapOKCB(Widget w, XtPointer
3359 return;
3364 + XtVaGetValues(ShowWrapMarginOptMenu, XmNmenuHistory,
3365 + &showWrapMarginSelectedItem, NULL);
3366 + XtVaGetValues(showWrapMarginSelectedItem, XmNuserData, &showWrapMargin, NULL);
3367 + if (showWrapMargin > N_SHOW_WRAP_MARGIN_STYLES || showWrapMargin < 0) {
3368 + showWrapMargin = SHOW_WRAP_MARGIN_NEVER;
3371 #ifdef SGI_CUSTOM
3372 /* Ask the user about saving as a default preference */
3373 if (WrapDialogForWindow != NULL) {
3374 int setDefault;
3375 if (!shortPrefToDefault(window->shell, "Wrap Margin Settings",
3376 @@ -2782,24 +2924,29 @@ static void wrapOKCB(Widget w, XtPointer
3377 DoneWithWrapDialog = True;
3378 return;
3380 if (setDefault) {
3381 SetPrefWrapMargin(margin);
3382 + SetPrefShowWrapMargin(showWrapMargin);
3383 SaveNEditPrefs(window->shell, GetPrefShortMenus());
3386 #endif
3388 /* Set the value in either the requested window or default preferences */
3389 - if (WrapDialogForWindow == NULL)
3390 + if (WrapDialogForWindow == NULL) {
3391 SetPrefWrapMargin(margin);
3392 - else {
3393 + SetPrefShowWrapMargin(showWrapMargin);
3394 + } else {
3395 char *params[1];
3396 char marginStr[25];
3397 sprintf(marginStr, "%d", margin);
3398 params[0] = marginStr;
3399 XtCallActionProc(window->textArea, "set_wrap_margin", NULL, params, 1);
3400 + sprintf(marginStr, "%d", showWrapMargin);
3401 + params[0] = marginStr;
3402 + XtCallActionProc(window->textArea, "set_show_wrap_margin", NULL, params, 1);
3404 DoneWithWrapDialog = True;
3407 static void wrapCancelCB(Widget w, XtPointer clientData, XtPointer callData)
3408 @@ -2811,10 +2958,12 @@ static void wrapWindowCB(Widget w, XtPoi
3410 int wrapAtWindow = XmToggleButtonGetState(w);
3412 XtSetSensitive(WrapTextLabel, !wrapAtWindow);
3413 XtSetSensitive(WrapText, !wrapAtWindow);
3414 + XtSetSensitive(ShowWrapMarginOptMenu, !wrapAtWindow);
3415 + XtSetSensitive(ShowWrapMarginLabel, !wrapAtWindow);
3419 ** Create and show a dialog for selecting the shell
3421 @@ -6135,10 +6285,24 @@ static void cursorFgModifiedCB(Widget w,
3423 colorDialog *cd = (colorDialog *)clientData;
3424 showColorStatus(cd, cd->cursorFgW, cd->cursorFgErrW);
3427 +static void wrapMarginFgModifiedCB(Widget w, XtPointer clientData,
3428 + XtPointer callData)
3430 + colorDialog *cd = (colorDialog *)clientData;
3431 + showColorStatus(cd, cd->wrapMarginFgW, cd->wrapMarginFgErrW);
3436 * Helper functions for validating colors
3438 static int verifyAllColors(colorDialog *cd)
3439 @@ -6188,35 +6353,41 @@ static void updateColors(colorDialog *cd
3440 *selectFg = XmTextGetString(cd->selectFgW),
3441 *selectBg = XmTextGetString(cd->selectBgW),
3442 *hiliteFg = XmTextGetString(cd->hiliteFgW),
3443 *hiliteBg = XmTextGetString(cd->hiliteBgW),
3444 *lineNoFg = XmTextGetString(cd->lineNoFgW),
3445 - *cursorFg = XmTextGetString(cd->cursorFgW);
3446 + *cursorFg = XmTextGetString(cd->cursorFgW),
3447 + *wrapMarginFg = XmTextGetString(cd->wrapMarginFgW);
3449 for (window = WindowList; window != NULL; window = window->next)
3451 SetColors(window, textFg, textBg, selectFg, selectBg, hiliteFg,
3452 - hiliteBg, lineNoFg, cursorFg);
3453 + hiliteBg, lineNoFg, cursorFg, wrapMarginFg);
3456 SetPrefColorName(TEXT_FG_COLOR , textFg );
3457 SetPrefColorName(TEXT_BG_COLOR , textBg );
3458 SetPrefColorName(SELECT_FG_COLOR, selectFg);
3459 SetPrefColorName(SELECT_BG_COLOR, selectBg);
3460 SetPrefColorName(HILITE_FG_COLOR, hiliteFg);
3461 SetPrefColorName(HILITE_BG_COLOR, hiliteBg);
3462 SetPrefColorName(LINENO_FG_COLOR, lineNoFg);
3463 SetPrefColorName(CURSOR_FG_COLOR, cursorFg);
3464 + SetPrefColorName(WRAPMARGIN_FG_COLOR, wrapMarginFg);
3466 XtFree(textFg);
3467 XtFree(textBg);
3468 XtFree(selectFg);
3469 XtFree(selectBg);
3470 XtFree(hiliteFg);
3471 XtFree(hiliteBg);
3472 XtFree(lineNoFg);
3473 XtFree(cursorFg);
3474 + XtFree(wrapMarginFg);
3479 * Dialog button callbacks
3480 @@ -6382,10 +6553,27 @@ void ChooseColors(WindowInfo *window)
3481 NULL);
3482 XmStringFree(s1);
3484 topW = infoLbl;
3486 + /* The right column (backgrounds) */
3487 + tmpW = addColorGroup( form, "textBg", 'T', "Text Area Background",
3488 + &(cd->textBgW), &(cd->textBgErrW), topW, 51, 99,
3489 + textBgModifiedCB, cd );
3490 + tmpW = addColorGroup( form, "selectBg", 'B', "Selection Background",
3491 + &(cd->selectBgW), &(cd->selectBgErrW), tmpW, 51, 99,
3492 + selectBgModifiedCB, cd );
3493 + tmpW = addColorGroup( form, "hiliteBg", 'h', "Matching (..) Background",
3494 + &(cd->hiliteBgW), &(cd->hiliteBgErrW), tmpW, 51, 99,
3495 + hiliteBgModifiedCB, cd );
3496 + tmpW = addColorGroup( form, "wrapMarginFg", 'w', "Wrap Margin Color",
3497 + &(cd->wrapMarginFgW), &(cd->wrapMarginFgErrW), tmpW, 51, 99,
3498 + wrapMarginFgModifiedCB, cd );
3500 /* The left column (foregrounds) of color entry groups */
3501 tmpW = addColorGroup( form, "textFg", 'P', "Plain Text Foreground",
3502 &(cd->textFgW), &(cd->textFgErrW), topW, 1, 49,
3503 textFgModifiedCB, cd );
3504 tmpW = addColorGroup( form, "selectFg", 'S', "Selection Foreground",
3505 @@ -6395,23 +6583,12 @@ void ChooseColors(WindowInfo *window)
3506 &(cd->hiliteFgW), &(cd->hiliteFgErrW), tmpW, 1, 49,
3507 hiliteFgModifiedCB, cd );
3508 tmpW = addColorGroup( form, "lineNoFg", 'L', "Line Numbers",
3509 &(cd->lineNoFgW), &(cd->lineNoFgErrW), tmpW, 1, 49,
3510 lineNoFgModifiedCB, cd );
3512 - /* The right column (backgrounds) */
3513 - tmpW = addColorGroup( form, "textBg", 'T', "Text Area Background",
3514 - &(cd->textBgW), &(cd->textBgErrW), topW, 51, 99,
3515 - textBgModifiedCB, cd );
3516 - tmpW = addColorGroup( form, "selectBg", 'B', "Selection Background",
3517 - &(cd->selectBgW), &(cd->selectBgErrW), tmpW, 51, 99,
3518 - selectBgModifiedCB, cd );
3519 - tmpW = addColorGroup( form, "hiliteBg", 'h', "Matching (..) Background",
3520 - &(cd->hiliteBgW), &(cd->hiliteBgErrW), tmpW, 51, 99,
3521 - hiliteBgModifiedCB, cd );
3522 tmpW = addColorGroup( form, "cursorFg", 'C', "Cursor Color",
3523 - &(cd->cursorFgW), &(cd->cursorFgErrW), tmpW, 51, 99,
3524 + &(cd->cursorFgW), &(cd->cursorFgErrW), tmpW, 1, 49,
3525 cursorFgModifiedCB, cd );
3527 tmpW = XtVaCreateManagedWidget("infoLbl",
3528 xmLabelGadgetClass, form,
3529 XmNtopAttachment, XmATTACH_WIDGET,
3530 @@ -6490,18 +6667,70 @@ void ChooseColors(WindowInfo *window)
3531 XmTextSetString(cd->selectBgW, GetPrefColorName(SELECT_BG_COLOR));
3532 XmTextSetString(cd->hiliteFgW, GetPrefColorName(HILITE_FG_COLOR));
3533 XmTextSetString(cd->hiliteBgW, GetPrefColorName(HILITE_BG_COLOR));
3534 XmTextSetString(cd->lineNoFgW, GetPrefColorName(LINENO_FG_COLOR));
3535 XmTextSetString(cd->cursorFgW, GetPrefColorName(CURSOR_FG_COLOR));
3536 + XmTextSetString(cd->wrapMarginFgW, GetPrefColorName(WRAPMARGIN_FG_COLOR));
3538 /* Handle mnemonic selection of buttons and focus to dialog */
3539 AddDialogMnemonicHandler(form, FALSE);
3541 /* put up dialog */
3542 ManageDialogCenteredOnPointer(form);
3545 +/* Overrides the defaults for certain preferences with values obtained from
3546 + obsoleted resources. */
3547 +static void initPrefDefaultsFromResources(XrmDatabase prefDB, XrmDatabase appDB)
3549 + char *type, *valueString;
3550 + XrmValue rsrcValue;
3552 + /* XmFileSelectionBox.fileFilterStyle is now obsolete since it is
3553 + overridden by nedit.showHiddenFiles, but this code tries to make
3554 + the transition painless by translating the resource value, if set,
3555 + to a matching default for the preferences */
3556 + const char* showHiddenResName =
3557 + APP_NAME "*XmFileSelectionBox.fileFilterStyle";
3558 + const char* showHiddenClassName =
3559 + APP_CLASS "*XmFileSelectionBox.FileFilterStyle";
3561 + /* Retrieve the value of the resource from the DB */
3562 + if (XrmGetResource(prefDB, showHiddenResName, showHiddenClassName, &type,
3563 + &rsrcValue)) {
3564 + if (strcmp(type, XmRString)) {
3565 + fprintf(stderr, "nedit: Internal Error: Unexpected resource type, %s\n",
3566 + type);
3567 + return;
3569 + valueString = rsrcValue.addr;
3570 + } else if (XrmGetResource(appDB, showHiddenResName, showHiddenClassName,
3571 + &type, &rsrcValue)) {
3572 + if (strcmp(type, XmRString)) {
3573 + fprintf(stderr, "nedit: Internal Error: Unexpected resource type, %s\n",
3574 + type);
3575 + return;
3577 + valueString = rsrcValue.addr;
3578 + } else {
3579 + /* No resources set */
3580 + return;
3583 + /* An X resource is set. If it's non-default, update the prefs default. */
3584 + if (0 == strcmp(valueString, "XmFILTER_HIDDEN_FILES")) {
3585 + unsigned int i;
3586 + for (i = 0; i < XtNumber(PrefDescrip); ++i) {
3587 + if (0 == strcmp(PrefDescrip[i].name, "showHiddenFiles")) {
3588 + PrefDescrip[i].defaultString = "False";
3589 + break;
3596 ** This function passes up a pointer to the static name of the default
3597 ** shell, currently defined as the user's login shell.
3598 ** In case of errors, the fallback of "sh" will be returned.
3600 diff --quilt old/source/preferences.h new/source/preferences.h
3601 --- old/source/preferences.h
3602 +++ new/source/preferences.h
3603 @@ -57,10 +57,12 @@ void MarkPrefsChanged(void);
3604 int CheckPrefsChangesSaved(Widget dialogParent);
3605 void SetPrefWrap(int state);
3606 int GetPrefWrap(int langMode);
3607 void SetPrefWrapMargin(int margin);
3608 int GetPrefWrapMargin(void);
3609 +void SetPrefShowWrapMargin(int state);
3610 +int GetPrefShowWrapMargin(void);
3611 void SetPrefSearchDlogs(int state);
3612 int GetPrefSearchDlogs(void);
3613 void SetPrefKeepSearchDlogs(int state);
3614 int GetPrefKeepSearchDlogs(void);
3615 void SetPrefSearchWraps(int state);
3616 @@ -117,10 +119,12 @@ void SetPrefBacklightChars(int state);
3617 int GetPrefBacklightChars(void);
3618 void SetPrefBacklightCharTypes(char *types);
3619 char *GetPrefBacklightCharTypes(void);
3620 void SetPrefRepositionDialogs(int state);
3621 int GetPrefRepositionDialogs(void);
3622 +void SetPrefShowHiddenFiles(int state);
3623 +int GetPrefShowHiddenFiles(void);
3624 void SetPrefAutoScroll(int state);
3625 int GetPrefAutoScroll(void);
3626 int GetVerticalAutoScroll(void);
3627 void SetPrefAppendLF(int state);
3628 int GetPrefAppendLF(void);
3629 @@ -156,10 +160,11 @@ void RowColumnPrefDialog(Widget parent);
3630 void TabsPrefDialog(Widget parent, WindowInfo *forWindow);
3631 void WrapMarginDialog(Widget parent, WindowInfo *forWindow);
3632 int GetPrefMapDelete(void);
3633 int GetPrefStdOpenDialog(void);
3634 char *GetPrefDelimiters(void);
3635 +char *GetPrevOpenFilesMask(void);
3636 int GetPrefMaxPrevOpenFiles(void);
3637 int GetPrefTypingHidesPointer(void);
3638 #ifdef SGI_CUSTOM
3639 void SetPrefShortMenus(int state);
3640 int GetPrefShortMenus(void);
3641 @@ -209,7 +214,10 @@ void SetPrefOpenInTab(int state);
3642 Boolean GetPrefUndoModifiesSelection(void);
3643 Boolean GetPrefFocusOnRaise(void);
3644 Boolean GetPrefHonorSymlinks(void);
3645 Boolean GetPrefForceOSConversion(void);
3646 void SetPrefFocusOnRaise(Boolean);
3647 +Boolean GetPrefShowScrolltip(void);
3649 #endif /* NEDIT_PREFERENCES_H_INCLUDED */
3650 diff --quilt old/source/search.c new/source/search.c
3651 --- old/source/search.c
3652 +++ new/source/search.c
3653 @@ -241,10 +241,11 @@ static void iSearchCaseToggleCB(Widget w
3654 XtPointer callData);
3655 static void iSearchTryBeepOnWrap(WindowInfo *window, int direction,
3656 int beginPos, int startPos);
3657 static void iSearchRecordLastBeginPos(WindowInfo *window, int direction,
3658 int initPos);
3659 +static void smartCaseToggle(const char* searchString, Widget toggleButton);
3660 static Boolean prefOrUserCancelsSubst(const Widget parent,
3661 const Display* display);
3663 typedef struct _charMatchTable {
3664 char c;
3665 @@ -279,10 +280,11 @@ static char *searchTypeStrings[] = {
3666 "case", /* SEARCH_CASE_SENSE */
3667 "regex", /* SEARCH_REGEX */
3668 "word", /* SEARCH_LITERAL_WORD */
3669 "caseWord", /* SEARCH_CASE_SENSE_WORD */
3670 "regexNoCase", /* SEARCH_REGEX_NOCASE */
3671 + "regexSmartCase", /* SEARCH_REGEX_SMARTCASE */
3672 NULL
3676 ** Window for which a search dialog callback is currently active. That window
3677 @@ -317,70 +319,77 @@ static void initToggleButtons(int search
3678 Bool* lastRegexCase)
3680 /* Set the initial search type and remember the corresponding case
3681 sensitivity states in case sticky case sensitivity is required. */
3682 switch (searchType) {
3683 - case SEARCH_LITERAL:
3684 + case SEARCH_LITERAL:
3685 *lastLiteralCase = False;
3686 *lastRegexCase = True;
3687 XmToggleButtonSetState(regexToggle, False, False);
3688 XmToggleButtonSetState(caseToggle, False, False);
3689 if (wordToggle) {
3690 XmToggleButtonSetState(*wordToggle, False, False);
3691 XtSetSensitive(*wordToggle, True);
3693 - break;
3694 - case SEARCH_CASE_SENSE:
3695 + break;
3697 + case SEARCH_CASE_SENSE:
3698 *lastLiteralCase = True;
3699 *lastRegexCase = True;
3700 XmToggleButtonSetState(regexToggle, False, False);
3701 XmToggleButtonSetState(caseToggle, True, False);
3702 if (wordToggle) {
3703 XmToggleButtonSetState(*wordToggle, False, False);
3704 XtSetSensitive(*wordToggle, True);
3706 - break;
3707 - case SEARCH_LITERAL_WORD:
3708 + break;
3710 + case SEARCH_LITERAL_WORD:
3711 *lastLiteralCase = False;
3712 *lastRegexCase = True;
3713 XmToggleButtonSetState(regexToggle, False, False);
3714 XmToggleButtonSetState(caseToggle, False, False);
3715 if (wordToggle) {
3716 XmToggleButtonSetState(*wordToggle, True, False);
3717 XtSetSensitive(*wordToggle, True);
3719 - break;
3720 - case SEARCH_CASE_SENSE_WORD:
3721 + break;
3723 + case SEARCH_CASE_SENSE_WORD:
3724 *lastLiteralCase = True;
3725 *lastRegexCase = True;
3726 XmToggleButtonSetState(regexToggle, False, False);
3727 XmToggleButtonSetState(caseToggle, True, False);
3728 if (wordToggle) {
3729 XmToggleButtonSetState(*wordToggle, True, False);
3730 XtSetSensitive(*wordToggle, True);
3732 - break;
3733 - case SEARCH_REGEX:
3734 + break;
3736 + case SEARCH_REGEX:
3737 *lastLiteralCase = False;
3738 *lastRegexCase = True;
3739 XmToggleButtonSetState(regexToggle, True, False);
3740 XmToggleButtonSetState(caseToggle, True, False);
3741 if (wordToggle) {
3742 XmToggleButtonSetState(*wordToggle, False, False);
3743 XtSetSensitive(*wordToggle, False);
3745 - break;
3746 - case SEARCH_REGEX_NOCASE:
3747 - *lastLiteralCase = False;
3748 - *lastRegexCase = False;
3749 - XmToggleButtonSetState(regexToggle, True, False);
3750 - XmToggleButtonSetState(caseToggle, False, False);
3751 - if (wordToggle) {
3752 - XmToggleButtonSetState(*wordToggle, False, False);
3753 - XtSetSensitive(*wordToggle, False);
3755 - break;
3756 + break;
3758 + case SEARCH_REGEX_NOCASE:
3759 + case SEARCH_REGEX_SMARTCASE:
3760 + /* Smart case is no case for default setting */
3761 + *lastLiteralCase = False;
3762 + *lastRegexCase = False;
3763 + XmToggleButtonSetState(regexToggle, True, False);
3764 + XmToggleButtonSetState(caseToggle, False, False);
3765 + if (wordToggle) {
3766 + XmToggleButtonSetState(*wordToggle, False, False);
3767 + XtSetSensitive(*wordToggle, False);
3769 + break;
3773 #ifdef REPLACE_SCOPE
3775 @@ -2404,14 +2413,23 @@ static int textFieldNonEmpty(Widget w)
3776 int nonEmpty = (str[0] != '\0');
3777 XtFree(str);
3778 return(nonEmpty);
3781 -static void rFindTextValueChangedCB(Widget w, WindowInfo *window, XKeyEvent *event)
3782 +static void rFindTextValueChangedCB(Widget textWidget, WindowInfo* window,
3783 + XKeyEvent* event)
3785 - window = WidgetToWindow(w);
3786 + char* searchString = XmTextGetString(textWidget);
3788 + window = WidgetToWindow(textWidget);
3789 UpdateReplaceActionButtons(window);
3791 + /* Switch to case-sensitive as soon as the user enters an upper-case
3792 + letter. We have check the whole string each time to catch clipboard
3793 + or selection inserts. */
3794 + smartCaseToggle(searchString, window->replaceCaseToggle);
3795 + XtFree(searchString);
3798 static void rFindArrowKeyCB(Widget w, WindowInfo *window, XKeyEvent *event)
3800 KeySym keysym = XLookupKeysym(event, 0);
3801 @@ -2499,14 +2517,23 @@ static void fUpdateActionButtons(WindowI
3803 int buttonState = textFieldNonEmpty(window->findText);
3804 XtSetSensitive(window->findBtn, buttonState);
3807 -static void findTextValueChangedCB(Widget w, WindowInfo *window, XKeyEvent *event)
3808 +static void findTextValueChangedCB(Widget textWidget, WindowInfo* window,
3809 + XKeyEvent* event)
3811 - window = WidgetToWindow(w);
3812 + char* searchString = XmTextGetString(textWidget);
3814 + window = WidgetToWindow(textWidget);
3815 fUpdateActionButtons(window);
3817 + /* Switch to case-sensitive as soon as the user enters an upper-case
3818 + letter. We have check the whole string each time to catch clipboard
3819 + or selection inserts. */
3820 + smartCaseToggle(searchString, window->findCaseToggle);
3821 + XtFree(searchString);
3824 static void findArrowKeyCB(Widget w, WindowInfo *window, XKeyEvent *event)
3826 KeySym keysym = XLookupKeysym(event, 0);
3827 @@ -2527,11 +2554,10 @@ static void findArrowKeyCB(Widget w, Win
3828 /* if the index is out of range, beep and return */
3829 if (index != 0 && historyIndex(index) == -1) {
3830 XBell(TheDisplay, 0);
3831 return;
3835 /* determine the strings and button settings to use */
3836 if (index == 0) {
3837 searchStr = "";
3838 searchType = GetPrefSearch();
3839 @@ -2874,36 +2900,45 @@ static void selectedSearchCB(Widget w, X
3840 XtFree(value);
3842 /* Use the passed method for searching, unless it is regex, since this
3843 kind of search is by definition a literal search */
3844 searchType = callDataItems->searchType;
3845 - if (searchType == SEARCH_REGEX )
3846 - searchType = SEARCH_CASE_SENSE;
3847 - else if (searchType == SEARCH_REGEX_NOCASE)
3848 - searchType = SEARCH_LITERAL;
3849 + if (searchType == SEARCH_REGEX || searchType == SEARCH_REGEX_SMARTCASE) {
3850 + /* Here smart case must be sensitive, because the user
3851 + cannot modify the string to search for. */
3852 + searchType = SEARCH_CASE_SENSE;
3853 + } else if (searchType == SEARCH_REGEX_NOCASE) {
3854 + searchType = SEARCH_LITERAL;
3857 /* search for it in the window */
3858 SearchAndSelect(window, callDataItems->direction, searchString,
3859 searchType, callDataItems->searchWrap);
3860 XtFree(callData);
3864 ** Pop up and clear the incremental search line and prepare to search.
3866 -void BeginISearch(WindowInfo *window, int direction)
3867 +void BeginISearch(WindowInfo* window, int direction)
3869 window->iSearchStartPos = -1;
3870 XmTextSetString(window->iSearchText, "");
3871 XmToggleButtonSetState(window->iSearchRevToggle,
3872 - direction == SEARCH_BACKWARD, FALSE);
3873 + direction == SEARCH_BACKWARD, FALSE);
3875 /* Note: in contrast to the replace and find dialogs, the regex and
3876 case toggles are not reset to their default state when the incremental
3877 search bar is redisplayed. I'm not sure whether this is the best
3878 choice. If not, an initToggleButtons() call should be inserted
3879 here. But in that case, it might be appropriate to have different
3880 default search modes for i-search and replace/find. */
3882 + /* The 'Case' toggle button must be deactivated for smart cases. */
3883 + if (GetPrefSearch() == SEARCH_REGEX_SMARTCASE) {
3884 + XmToggleButtonSetState(window->iSearchCaseToggle, False, False);
3886 TempShowISearch(window, TRUE);
3887 XmProcessTraversal(window->iSearchText, XmTRAVERSE_CURRENT);
3891 @@ -3181,32 +3216,40 @@ static void iSearchTextActivateCB(Widget
3894 ** Called when user types in the incremental search line. Redoes the
3895 ** search for the new search string.
3897 -static void iSearchTextValueChangedCB(Widget w, WindowInfo *window,
3898 - XmAnyCallbackStruct *callData)
3899 +static void iSearchTextValueChangedCB(Widget widget, WindowInfo *window,
3900 + XmAnyCallbackStruct *callData)
3902 char *params[5];
3903 char *searchString;
3904 int searchType, direction, nParams;
3906 - window = WidgetToWindow(w);
3909 + window = WidgetToWindow(widget);
3911 /* Fetch the string, search type and direction from the incremental
3912 search bar widgets at the top of the window */
3913 searchString = XmTextGetString(window->iSearchText);
3915 + /* Switch to case-sensitive as soon as the user enters an upper-case
3916 + letter. We have check the whole string each time to catch clipboard
3917 + or selection inserts. */
3918 + smartCaseToggle(searchString, window->iSearchCaseToggle);
3920 if(XmToggleButtonGetState(window->iSearchCaseToggle)) {
3921 - if(XmToggleButtonGetState(window->iSearchRegexToggle))
3922 - searchType = SEARCH_REGEX;
3923 - else
3924 - searchType = SEARCH_CASE_SENSE;
3925 + if(XmToggleButtonGetState(window->iSearchRegexToggle)) {
3926 + searchType = SEARCH_REGEX;
3927 + } else {
3928 + searchType = SEARCH_CASE_SENSE;
3930 } else {
3931 - if(XmToggleButtonGetState(window->iSearchRegexToggle))
3932 - searchType = SEARCH_REGEX_NOCASE;
3933 - else
3934 - searchType = SEARCH_LITERAL;
3935 + if(XmToggleButtonGetState(window->iSearchRegexToggle)) {
3936 + searchType = SEARCH_REGEX_NOCASE;
3937 + } else {
3938 + searchType = SEARCH_LITERAL;
3941 direction = XmToggleButtonGetState(window->iSearchRevToggle) ?
3942 SEARCH_BACKWARD : SEARCH_FORWARD;
3944 /* If the search type is a regular expression, test compile it. If it
3945 @@ -4872,11 +4915,13 @@ static char *directionArg(int direction)
3947 ** Checks whether a search mode in one of the regular expression modes.
3949 static int isRegexType(int searchType)
3951 - return searchType == SEARCH_REGEX || searchType == SEARCH_REGEX_NOCASE;
3952 + return searchType == SEARCH_REGEX
3953 + || searchType == SEARCH_REGEX_NOCASE
3954 + || searchType == SEARCH_REGEX_SMARTCASE;
3958 ** Returns the default flags for regular expression matching, given a
3959 ** regular expression search mode.
3960 @@ -5003,17 +5048,35 @@ static void replaceCaseToggleCB(Widget w
3961 window->replaceLastRegexCase = searchCaseSense;
3962 else
3963 window->replaceLastLiteralCase = searchCaseSense;
3966 -static void iSearchCaseToggleCB(Widget w, XtPointer clientData, XtPointer callData)
3967 +static void iSearchCaseToggleCB(Widget toggleButton, XtPointer clientData,
3968 + XtPointer callData)
3970 - WindowInfo * window = WidgetToWindow(w);
3971 - int searchCaseSense = XmToggleButtonGetState(w);
3972 + WindowInfo * window = WidgetToWindow(toggleButton);
3973 + int searchCaseSense = XmToggleButtonGetState(toggleButton);
3975 /* Save the state of the Case Sensitive button
3976 depending on the state of the Regex button*/
3977 if(XmToggleButtonGetState(window->iSearchRegexToggle))
3978 window->iSearchLastRegexCase = searchCaseSense;
3979 else
3980 window->iSearchLastLiteralCase = searchCaseSense;
3984 +** Will search a string for uppercase characters. If there is one,
3985 +** The toggleButton will be set to True.
3987 +static void smartCaseToggle(const char* searchString, Widget toggleButton)
3989 + if (GetPrefSearch() == SEARCH_REGEX_SMARTCASE) {
3990 + int i;
3991 + for (i = 0; i < strlen(searchString); i++) {
3992 + if (isupper(*(searchString + i))) {
3993 + XmToggleButtonSetState(toggleButton, True, False);
3994 + break;
3999 diff --quilt old/source/search.h new/source/search.h
4000 --- old/source/search.h
4001 +++ new/source/search.h
4002 @@ -85,14 +85,16 @@ Boolean WindowCanBeClosed(WindowInfo *wi
4003 ** The order of the integers in this enumeration must be exactly
4004 ** the same as the order of the coressponding strings of the
4005 ** array SearchMethodStrings defined in preferences.c (!!)
4008 -enum SearchType {
4009 - SEARCH_LITERAL, SEARCH_CASE_SENSE, SEARCH_REGEX,
4010 - SEARCH_LITERAL_WORD, SEARCH_CASE_SENSE_WORD, SEARCH_REGEX_NOCASE,
4011 - N_SEARCH_TYPES /* must be last in enum SearchType */ };
4012 +enum SearchType
4014 + SEARCH_LITERAL, SEARCH_CASE_SENSE, SEARCH_REGEX, SEARCH_LITERAL_WORD,
4015 + SEARCH_CASE_SENSE_WORD, SEARCH_REGEX_NOCASE, SEARCH_REGEX_SMARTCASE,
4016 + N_SEARCH_TYPES /* must be last in enum SearchType */
4019 #ifdef REPLACE_SCOPE
4020 /* Scope on which the replace operations apply */
4021 enum ReplaceScope { REPL_SCOPE_WIN, REPL_SCOPE_SEL, REPL_SCOPE_MULTI };
4023 diff --quilt old/source/selection.c new/source/selection.c
4024 --- old/source/selection.c
4025 +++ new/source/selection.c
4026 @@ -27,21 +27,23 @@ static const char CVSID[] = "$Id: select
4028 #ifdef HAVE_CONFIG_H
4029 #include "../config.h"
4030 #endif
4032 -#include "selection.h"
4033 -#include "textBuf.h"
4034 -#include "text.h"
4035 -#include "nedit.h"
4036 #include "file.h"
4037 -#include "window.h"
4038 +#include "interpret.h"
4039 +#include "macro.h"
4040 #include "menu.h"
4041 +#include "nedit.h"
4042 #include "preferences.h"
4043 +#include "selection.h"
4044 #include "server.h"
4045 +#include "textBuf.h"
4046 +#include "text.h"
4047 #include "../util/DialogF.h"
4048 #include "../util/fileUtils.h"
4049 +#include "window.h"
4051 #include <stdlib.h>
4052 #include <stdio.h>
4053 #include <ctype.h>
4054 #include <string.h>
4055 @@ -349,23 +351,34 @@ static void fileCB(Widget widget, Window
4056 XtFree(nameList[i]);
4058 XtFree((char *)nameList);
4060 #else
4061 - { glob_t globbuf;
4062 - int i;
4064 - glob(nameText, GLOB_NOCHECK, NULL, &globbuf);
4065 - for (i=0; i<(int)globbuf.gl_pathc; i++) {
4066 - if (ParseFilename(globbuf.gl_pathv[i], filename, pathname) != 0)
4067 - XBell(TheDisplay, 0);
4068 - else
4069 - EditExistingFile(GetPrefOpenInTab()? window : NULL,
4070 - filename, pathname, 0, NULL, False, NULL,
4071 - GetPrefOpenInTab(), False);
4073 - globfree(&globbuf);
4075 + glob_t globbuf;
4076 + int i;
4078 + glob(nameText, GLOB_NOCHECK, NULL, &globbuf);
4079 + for (i = 0; i < (int) globbuf.gl_pathc; i++) {
4080 + DataValue* fileNameArg = (DataValue*) XtMalloc(sizeof(DataValue));
4081 + DataValue* resultDV = (DataValue*) XtMalloc(sizeof(DataValue));
4083 + fileNameArg->tag = STRING_TAG;
4084 + AllocNStringNCpy(&fileNameArg->val.str, globbuf.gl_pathv[i], MAXPATHLEN);
4085 + MacroApplyHook(window, "file_name_hook", 1, fileNameArg, resultDV);
4086 + XtFree((char*) fileNameArg);
4088 + if (ParseFilename(resultDV->val.str.rep, filename, pathname) != 0) {
4089 + XBell(TheDisplay, 0);
4090 + } else {
4091 + EditExistingFile(GetPrefOpenInTab() ? window : NULL, filename,
4092 + pathname, 0, NULL, False, NULL, GetPrefOpenInTab(),
4093 + False);
4095 + XtFree((char*) resultDV);
4097 + globfree(&globbuf);
4099 #endif
4100 CheckCloseDim();
4103 diff --quilt old/source/server.c new/source/server.c
4104 --- old/source/server.c
4105 +++ new/source/server.c
4106 @@ -242,12 +242,10 @@ static void deleteFileOpenProperty2(cons
4108 Atom atom = findFileOpenProperty(filename, pathname);
4109 deleteProperty(&atom);
4114 /* Try to find existing 'FileClosed' property atom for path. */
4115 static Atom findFileClosedProperty(const char* filename,
4116 const char* pathname)
4118 char path[MAXPATHLEN];
4119 @@ -354,11 +352,11 @@ static void processServerCommandString(c
4120 if (!window->filenameSet && !window->fileChanged &&
4121 isLocatedOnDesktop(window, currentDesktop))
4122 break;
4123 if (window == NULL) {
4124 EditNewFile(findWindowOnDesktop(tabbed, currentDesktop), NULL,
4125 - False, NULL, NULL);
4126 + False, NULL, NULL, False);
4127 CheckCloseDim();
4129 else {
4130 RaiseDocument(window);
4131 XMapRaised(TheDisplay, XtWindow(window->shell));
4132 @@ -417,12 +415,13 @@ static void processServerCommandString(c
4133 isLocatedOnDesktop(window, currentDesktop))
4134 break;
4136 if (*doCommand == '\0') {
4137 if (window == NULL) {
4138 - EditNewFile(findWindowOnDesktop(tabbed, currentDesktop),
4139 - NULL, iconicFlag, lmLen==0?NULL:langMode, NULL);
4140 + EditNewFile(findWindowOnDesktop(tabbed, currentDesktop),
4141 + NULL, iconicFlag, lmLen==0?NULL:langMode, NULL,
4142 + False);
4143 } else {
4144 if (iconicFlag)
4145 RaiseDocument(window);
4146 else
4147 RaiseDocumentWindow(window);
4148 diff --quilt old/source/shell.c new/source/shell.c
4149 --- old/source/shell.c
4150 +++ new/source/shell.c
4151 @@ -387,11 +387,12 @@ void DoShellMenuCmd(WindowInfo *window,
4152 if (output == TO_DIALOG) {
4153 outWidget = NULL;
4154 flags |= OUTPUT_TO_DIALOG;
4155 left = right = 0;
4156 } else if (output == TO_NEW_WINDOW) {
4157 - EditNewFile(GetPrefOpenInTab()?inWindow:NULL, NULL, False, NULL, window->path);
4158 + EditNewFile(GetPrefOpenInTab()?inWindow:NULL, NULL, False, NULL,
4159 + window->path, False);
4160 outWidget = WindowList->textArea;
4161 inWindow = WindowList;
4162 left = right = 0;
4163 CheckCloseDim();
4164 } else { /* TO_SAME_WINDOW */
4165 @@ -478,11 +479,11 @@ void AbortShellCommand(WindowInfo *windo
4167 static void issueCommand(WindowInfo *window, const char *command, char *input,
4168 int inputLen, int flags, Widget textW, int replaceLeft,
4169 int replaceRight, int fromMacro)
4171 - int stdinFD, stdoutFD, stderrFD = 0;
4172 + int stdinFD = 0, stdoutFD = 0, stderrFD = 0;
4173 XtAppContext context = XtWidgetToApplicationContext(window->shell);
4174 shellCmdInfo *cmdData;
4175 pid_t childPid;
4177 /* verify consistency of input parameters */
4178 diff --quilt old/source/text.c new/source/text.c
4179 --- old/source/text.c
4180 +++ new/source/text.c
4181 @@ -629,10 +629,17 @@ static XtResource resources[] = {
4182 XtOffset(TextWidget, text.highlightFGPixel), XmRString,
4183 NEDIT_DEFAULT_HI_FG},
4184 {textNhighlightBackground, textCHighlightBackground, XmRPixel,sizeof(Pixel),
4185 XtOffset(TextWidget, text.highlightBGPixel), XmRString,
4186 NEDIT_DEFAULT_HI_BG},
4187 + {textNshowScrolltip, textCshowScrolltip, XmRBoolean, sizeof(Boolean),
4188 + XtOffset(TextWidget, text.showScrolltip), XmRString, "False"},
4189 {textNlineNumForeground, textCLineNumForeground, XmRPixel,sizeof(Pixel),
4190 XtOffset(TextWidget, text.lineNumFGPixel), XmRString,
4191 NEDIT_DEFAULT_LINENO_FG},
4192 {textNcursorForeground, textCCursorForeground, XmRPixel,sizeof(Pixel),
4193 XtOffset(TextWidget, text.cursorFGPixel), XmRString,
4194 @@ -641,10 +648,13 @@ static XtResource resources[] = {
4195 XtOffset(TextWidget, text.calltipFGPixel), XmRString,
4196 NEDIT_DEFAULT_CALLTIP_FG},
4197 {textNcalltipBackground, textCcalltipBackground, XmRPixel,sizeof(Pixel),
4198 XtOffset(TextWidget, text.calltipBGPixel), XmRString,
4199 NEDIT_DEFAULT_CALLTIP_BG},
4200 + {textNwrapMarginForeground, textCWrapMarginForeground, XmRPixel,sizeof(Pixel),
4201 + XtOffset(TextWidget, text.wrapMarginFGPixel), XmRString,
4202 + NEDIT_DEFAULT_WRAPMARGIN_FG},
4203 {textNbacklightCharTypes,textCBacklightCharTypes,XmRString,sizeof(XmString),
4204 XtOffset(TextWidget, text.backlightCharTypes), XmRString, NULL},
4205 {textNrows, textCRows, XmRInt,sizeof(int),
4206 XtOffset(TextWidget, text.rows), XmRString, "24"},
4207 {textNcolumns, textCColumns, XmRInt, sizeof(int),
4208 @@ -671,10 +681,12 @@ static XtResource resources[] = {
4209 XtOffset(TextWidget, text.readOnly), XmRString, "False"},
4210 {textNhidePointer, textCHidePointer, XmRBoolean, sizeof(Boolean),
4211 XtOffset(TextWidget, text.hidePointer), XmRString, "False"},
4212 {textNwrapMargin, textCWrapMargin, XmRInt, sizeof(int),
4213 XtOffset(TextWidget, text.wrapMargin), XmRString, "0"},
4214 + {textNshowWrapMargin, textCShowWrapMargin, XmRBoolean, sizeof(Boolean),
4215 + XtOffset(TextWidget, text.showWrapMargin), XmRString, "True"},
4216 {textNhScrollBar, textCHScrollBar, XmRWidget, sizeof(Widget),
4217 XtOffset(TextWidget, text.hScrollBar), XmRString, ""},
4218 {textNvScrollBar, textCVScrollBar, XmRWidget, sizeof(Widget),
4219 XtOffset(TextWidget, text.vScrollBar), XmRString, ""},
4220 {textNlineNumCols, textCLineNumCols, XmRInt, sizeof(int),
4221 @@ -810,24 +822,34 @@ static void initialize(TextWidget reques
4222 buf = BufCreate();
4224 /* Create and initialize the text-display part of the widget */
4225 textLeft = new->text.marginWidth +
4226 (lineNumCols == 0 ? 0 : marginWidth + charWidth * lineNumCols);
4227 - new->text.textD = TextDCreate((Widget)new, new->text.hScrollBar,
4228 - new->text.vScrollBar, textLeft, new->text.marginHeight,
4229 - new->core.width - marginWidth - textLeft,
4230 - new->core.height - new->text.marginHeight * 2,
4231 - lineNumCols == 0 ? 0 : marginWidth,
4232 - lineNumCols == 0 ? 0 : lineNumCols * charWidth,
4233 - buf, new->text.fontStruct, new->core.background_pixel,
4234 - new->primitive.foreground, new->text.selectFGPixel,
4235 - new->text.selectBGPixel, new->text.highlightFGPixel,
4236 - new->text.highlightBGPixel, new->text.cursorFGPixel,
4237 - new->text.lineNumFGPixel,
4238 - new->text.continuousWrap, new->text.wrapMargin,
4239 - new->text.backlightCharTypes, new->text.calltipFGPixel,
4240 - new->text.calltipBGPixel);
4241 + new->text.textD = TextDCreate(
4242 + /* Widgets */
4243 + (Widget)new, new->text.hScrollBar, new->text.vScrollBar,
4244 + /* Positions */
4245 + textLeft, new->text.marginHeight,
4246 + new->core.width - marginWidth - textLeft,
4247 + new->core.height - new->text.marginHeight * 2,
4248 + lineNumCols == 0 ? 0 : marginWidth,
4249 + lineNumCols == 0 ? 0 : lineNumCols * charWidth,
4250 + /* buffer */
4251 + buf,
4252 + /* font */
4253 + new->text.fontStruct,
4254 + /* Pixels */
4255 + new->core.background_pixel, new->primitive.foreground,
4256 + new->text.selectFGPixel, new->text.selectBGPixel,
4257 + new->text.highlightFGPixel, new->text.highlightBGPixel,
4258 + new->text.cursorFGPixel, new->text.lineNumFGPixel,
4259 + new->text.wrapMarginFGPixel, new->text.calltipFGPixel,
4260 + new->text.calltipBGPixel,
4261 + /* misc */
4262 + new->text.continuousWrap, new->text.wrapMargin,
4263 + new->text.showWrapMargin, new->text.backlightCharTypes,
4264 + new->text.showScrolltip);
4266 /* Add mandatory delimiters blank, tab, and newline to the list of
4267 delimiters. The memory use scheme here is that new values are
4268 always copied, and can therefore be safely freed on subsequent
4269 set-values calls or destroy */
4270 @@ -1121,10 +1143,25 @@ static Boolean setValues(TextWidget curr
4271 if (new->text.wrapMargin != current->text.wrapMargin ||
4272 new->text.continuousWrap != current->text.continuousWrap)
4273 TextDSetWrapMode(current->text.textD, new->text.continuousWrap,
4274 new->text.wrapMargin);
4276 + if (new->text.showWrapMargin != current->text.showWrapMargin)
4277 + TextDSetShowWrapMargin(current->text.textD, new->text.showWrapMargin);
4279 /* When delimiters are changed, copy the memory, so that the caller
4280 doesn't have to manage it, and add mandatory delimiters blank,
4281 tab, and newline to the list */
4282 if (new->text.delimiters != current->text.delimiters) {
4283 char *delimiters = XtMalloc(strlen(new->text.delimiters) + 4);
4284 @@ -3750,12 +3787,15 @@ static void selectWord(Widget w, int poi
4285 TextWidget tw = (TextWidget)w;
4286 textBuffer *buf = tw->text.textD->buffer;
4287 int x, y, insertPos = TextDGetInsertPosition(tw->text.textD);
4289 TextPosToXY(w, insertPos, &x, &y);
4290 - if (pointerX < x && insertPos > 0 && BufGetCharacter(buf, insertPos-1) != '\n')
4291 - insertPos--;
4292 + if (pointerX < x && insertPos > 0
4293 + && BufGetCharacter(buf, insertPos-1) != '\n')
4295 + insertPos--;
4297 BufSelect(buf, startOfWord(tw, insertPos), endOfWord(tw, insertPos));
4300 static int startOfWord(TextWidget w, int pos)
4302 diff --quilt old/source/text.h new/source/text.h
4303 --- old/source/text.h
4304 +++ new/source/text.h
4305 @@ -51,18 +51,30 @@
4306 #define textCSelectBackground "SelectBackground"
4307 #define textNhighlightForeground "highlightForeground"
4308 #define textCHighlightForeground "HighlightForeground"
4309 #define textNhighlightBackground "highlightBackground"
4310 #define textCHighlightBackground "HighlightBackground"
4311 +#define textNshowScrolltip "showScrolltip"
4312 +#define textCshowScrolltip "ShowScrolltip"
4314 #define textNcursorForeground "cursorForeground"
4315 #define textCCursorForeground "CursorForeground"
4316 #define textNlineNumForeground "lineNumForeground"
4317 #define textCLineNumForeground "LineNumForeground"
4318 #define textNcalltipForeground "calltipForeground"
4319 #define textCcalltipForeground "CalltipForeground"
4320 #define textNcalltipBackground "calltipBackground"
4321 #define textCcalltipBackground "CalltipBackground"
4322 +#define textNwrapMarginForeground "wrapMarginForeground"
4323 +#define textCWrapMarginForeground "WrapMarginForeground"
4324 #define textNpendingDelete "pendingDelete"
4325 #define textCPendingDelete "PendingDelete"
4326 #define textNhScrollBar "hScrollBar"
4327 #define textCHScrollBar "HScrollBar"
4328 #define textNvScrollBar "vScrollBar"
4329 @@ -93,10 +105,12 @@
4330 #define textCAutoWrap "AutoWrap"
4331 #define textNcontinuousWrap "continuousWrap"
4332 #define textCContinuousWrap "ContinuousWrap"
4333 #define textNwrapMargin "wrapMargin"
4334 #define textCWrapMargin "WrapMargin"
4335 +#define textNshowWrapMargin "showWrapMargin"
4336 +#define textCShowWrapMargin "ShowWrapMargin"
4337 #define textNautoIndent "autoIndent"
4338 #define textCAutoIndent "AutoIndent"
4339 #define textNsmartIndent "smartIndent"
4340 #define textCSmartIndent "SmartIndent"
4341 #define textNoverstrike "overstrike"
4342 diff --quilt old/source/textDisp.c new/source/textDisp.c
4343 --- old/source/textDisp.c
4344 +++ new/source/textDisp.c
4345 @@ -147,11 +152,12 @@ static int countLines(const char *string
4346 static int measureVisLine(textDisp *textD, int visLineNum);
4347 static int emptyLinesVisible(textDisp *textD);
4348 static void blankCursorProtrusions(textDisp *textD);
4349 static void allocateFixedFontGCs(textDisp *textD, XFontStruct *fontStruct,
4350 Pixel bgPixel, Pixel fgPixel, Pixel selectFGPixel, Pixel selectBGPixel,
4351 - Pixel highlightFGPixel, Pixel highlightBGPixel, Pixel lineNumFGPixel);
4352 + Pixel highlightFGPixel, Pixel highlightBGPixel, Pixel lineNumFGPixel,
4353 + Pixel wrapMarginFGPixel);
4354 static GC allocateGC(Widget w, unsigned long valueMask,
4355 unsigned long foreground, unsigned long background, Font font,
4356 unsigned long dynamicMask, unsigned long dontCareMask);
4357 static void releaseGC(Widget w, GC gc);
4358 static void resetClipRectangles(textDisp *textD);
4359 @@ -177,19 +183,24 @@ static void resetAbsLineNum(textDisp *te
4360 static int measurePropChar(const textDisp* textD, const char c,
4361 const int colNum, const int pos);
4362 static Pixel allocBGColor(Widget w, char *colorName, int *ok);
4363 static Pixel getRangesetColor(textDisp *textD, int ind, Pixel bground);
4364 static void textDRedisplayRange(textDisp *textD, int start, int end);
4365 +static void drawWrapMargin(textDisp* textD);
4366 +static void redisplayCursor(textDisp* textD);
4368 textDisp *TextDCreate(Widget widget, Widget hScrollBar, Widget vScrollBar,
4369 Position left, Position top, Position width, Position height,
4370 - Position lineNumLeft, Position lineNumWidth, textBuffer *buffer,
4371 - XFontStruct *fontStruct, Pixel bgPixel, Pixel fgPixel,
4372 - Pixel selectFGPixel, Pixel selectBGPixel, Pixel highlightFGPixel,
4373 - Pixel highlightBGPixel, Pixel cursorFGPixel, Pixel lineNumFGPixel,
4374 - int continuousWrap, int wrapMargin, XmString bgClassString,
4375 - Pixel calltipFGPixel, Pixel calltipBGPixel)
4376 + Position lineNumLeft, Position lineNumWidth,
4377 + textBuffer *buffer,
4378 + XFontStruct *fontStruct,
4379 + Pixel bgPixel, Pixel fgPixel, Pixel selectFGPixel, Pixel selectBGPixel,
4380 + Pixel highlightFGPixel, Pixel highlightBGPixel, Pixel cursorFGPixel,
4381 + Pixel lineNumFGPixel, Pixel wrapMarginFGPixel, Pixel calltipFGPixel,
4382 + Pixel calltipBGPixel,
4383 + int continuousWrap, int wrapMargin, Boolean showWrapMargin,
4384 + XmString bgClassString, Boolean showScrolltip)
4386 textDisp *textD;
4387 XGCValues gcValues;
4388 int i;
4390 @@ -230,29 +241,34 @@ textDisp *TextDCreate(Widget widget, Wid
4391 textD->selectFGPixel = selectFGPixel;
4392 textD->highlightFGPixel = highlightFGPixel;
4393 textD->selectBGPixel = selectBGPixel;
4394 textD->highlightBGPixel = highlightBGPixel;
4395 textD->lineNumFGPixel = lineNumFGPixel;
4396 textD->cursorFGPixel = cursorFGPixel;
4397 textD->wrapMargin = wrapMargin;
4398 textD->continuousWrap = continuousWrap;
4399 + textD->showWrapMargin = showWrapMargin;
4400 allocateFixedFontGCs(textD, fontStruct, bgPixel, fgPixel, selectFGPixel,
4401 - selectBGPixel, highlightFGPixel, highlightBGPixel, lineNumFGPixel);
4402 + selectBGPixel, highlightFGPixel, highlightBGPixel, lineNumFGPixel,
4403 + wrapMarginFGPixel);
4404 textD->styleGC = allocateGC(textD->w, 0, 0, 0, fontStruct->fid,
4405 GCClipMask|GCForeground|GCBackground, GCArcMode);
4406 textD->lineNumLeft = lineNumLeft;
4407 textD->lineNumWidth = lineNumWidth;
4408 textD->nVisibleLines = (height - 1) / (textD->ascent + textD->descent) + 1;
4409 gcValues.foreground = cursorFGPixel;
4410 textD->cursorFGGC = XtGetGC(widget, GCForeground, &gcValues);
4411 textD->lineStarts = (int *)XtMalloc(sizeof(int) * textD->nVisibleLines);
4412 textD->lineStarts[0] = 0;
4413 - textD->calltipW = NULL;
4414 - textD->calltipShell = NULL;
4415 + textD->calltip.widget = NULL;
4416 textD->calltip.ID = 0;
4417 textD->calltipFGPixel = calltipFGPixel;
4418 textD->calltipBGPixel = calltipBGPixel;
4419 + textD->showScrolltip = showScrolltip;
4420 + textD->scrolltip = NULL;
4421 for (i=1; i<textD->nVisibleLines; i++)
4422 textD->lineStarts[i] = -1;
4423 textD->bgClassPixel = NULL;
4424 textD->bgClass = NULL;
4425 TextDSetupBGClasses(widget, bgClassString, &textD->bgClassPixel,
4426 @@ -316,13 +335,18 @@ void TextDFree(textDisp *textD)
4427 releaseGC(textD->w, textD->highlightGC);
4428 releaseGC(textD->w, textD->selectBGGC);
4429 releaseGC(textD->w, textD->highlightBGGC);
4430 releaseGC(textD->w, textD->styleGC);
4431 releaseGC(textD->w, textD->lineNumGC);
4432 + releaseGC(textD->w, textD->wrapMarginGC);
4434 XtFree((char *)textD->lineStarts);
4435 while (TextDPopGraphicExposeQueueEntry(textD)) {
4438 XtFree((char *)textD->bgClassPixel);
4439 XtFree((char *)textD->bgClass);
4440 XtFree((char *)textD);
4443 @@ -380,11 +404,12 @@ void TextDAttachHighlightData(textDisp *
4446 /* Change the (non syntax-highlit) colors */
4447 void TextDSetColors(textDisp *textD, Pixel textFgP, Pixel textBgP,
4448 Pixel selectFgP, Pixel selectBgP, Pixel hiliteFgP, Pixel hiliteBgP,
4449 - Pixel lineNoFgP, Pixel cursorFgP)
4450 + Pixel lineNoFgP, Pixel cursorFgP, Pixel wrapMarginFgP)
4452 XGCValues values;
4453 Display *d = XtDisplay(textD->w);
4455 /* Update the stored pixels */
4456 @@ -394,19 +419,24 @@ void TextDSetColors(textDisp *textD, Pix
4457 textD->selectBGPixel = selectBgP;
4458 textD->highlightFGPixel = hiliteFgP;
4459 textD->highlightBGPixel = hiliteBgP;
4460 textD->lineNumFGPixel = lineNoFgP;
4461 textD->cursorFGPixel = cursorFgP;
4462 + textD->wrapMarginFGPixel = wrapMarginFgP;
4464 releaseGC(textD->w, textD->gc);
4465 releaseGC(textD->w, textD->selectGC);
4466 releaseGC(textD->w, textD->selectBGGC);
4467 releaseGC(textD->w, textD->highlightGC);
4468 releaseGC(textD->w, textD->highlightBGGC);
4469 releaseGC(textD->w, textD->lineNumGC);
4470 + releaseGC(textD->w, textD->wrapMarginGC);
4471 allocateFixedFontGCs(textD, textD->fontStruct, textBgP, textFgP, selectFgP,
4472 - selectBgP, hiliteFgP, hiliteBgP, lineNoFgP);
4473 + selectBgP, hiliteFgP, hiliteBgP, lineNoFgP, wrapMarginFgP);
4475 /* Change the cursor GC (the cursor GC is not shared). */
4476 values.foreground = cursorFgP;
4477 XChangeGC( d, textD->cursorFGGC, GCForeground, &values );
4479 @@ -414,20 +444,32 @@ void TextDSetColors(textDisp *textD, Pix
4480 TextDRedisplayRect(textD, textD->left, textD->top, textD->width,
4481 textD->height);
4482 redrawLineNumbers(textD, True);
4486 ** Change the (non highlight) font
4488 void TextDSetFont(textDisp *textD, XFontStruct *fontStruct)
4490 Display *display = XtDisplay(textD->w);
4491 int i, maxAscent = fontStruct->ascent, maxDescent = fontStruct->descent;
4492 int width, height, fontWidth;
4493 Pixel bgPixel, fgPixel, selectFGPixel, selectBGPixel;
4494 Pixel highlightFGPixel, highlightBGPixel, lineNumFGPixel;
4495 + Pixel wrapMarginFGPixel;
4496 XGCValues values;
4497 XFontStruct *styleFont;
4499 /* If font size changes, cursor will be redrawn in a new position */
4500 blankCursorProtrusions(textD);
4501 @@ -475,20 +517,30 @@ void TextDSetFont(textDisp *textD, XFont
4502 selectFGPixel = values.foreground;
4503 selectBGPixel = values.background;
4504 XGetGCValues(display, textD->highlightGC,GCForeground|GCBackground,&values);
4505 highlightFGPixel = values.foreground;
4506 highlightBGPixel = values.background;
4507 XGetGCValues(display, textD->lineNumGC, GCForeground, &values);
4508 lineNumFGPixel = values.foreground;
4509 + XGetGCValues(display, textD->wrapMarginGC, GCForeground, &values);
4510 + wrapMarginFGPixel = values.foreground;
4512 releaseGC(textD->w, textD->gc);
4513 releaseGC(textD->w, textD->selectGC);
4514 releaseGC(textD->w, textD->highlightGC);
4515 releaseGC(textD->w, textD->selectBGGC);
4516 releaseGC(textD->w, textD->highlightBGGC);
4517 releaseGC(textD->w, textD->lineNumGC);
4518 + releaseGC(textD->w, textD->wrapMarginGC);
4519 allocateFixedFontGCs(textD, fontStruct, bgPixel, fgPixel, selectFGPixel,
4520 - selectBGPixel, highlightFGPixel, highlightBGPixel, lineNumFGPixel);
4521 + selectBGPixel, highlightFGPixel, highlightBGPixel, lineNumFGPixel,
4522 + wrapMarginFGPixel);
4523 XSetFont(display, textD->styleGC, fontStruct->fid);
4525 /* Do a full resize to force recalculation of font related parameters */
4526 width = textD->width;
4527 height = textD->height;
4528 @@ -642,10 +694,13 @@ void TextDRedisplayRect(textDisp *textD,
4529 redisplayLine(textD, line, left, left+width, 0, INT_MAX);
4531 /* draw the line numbers if exposed area includes them */
4532 if (textD->lineNumWidth != 0 && left <= textD->lineNumLeft + textD->lineNumWidth)
4533 redrawLineNumbers(textD, False);
4535 + /* draw wrap margin incase it got erased */
4536 + drawWrapMargin(textD);
4540 ** Refresh all of the text between buffer positions "start" and "end"
4541 ** not including the character at the position "end".
4542 @@ -654,11 +709,11 @@ void TextDRedisplayRect(textDisp *textD,
4543 ** any range of characters.
4545 static void textDRedisplayRange(textDisp *textD, int start, int end)
4547 int i, startLine, lastLine, startIndex, endIndex;
4550 /* If the range is outside of the displayed text, just return */
4551 if (end < textD->firstChar || (start > textD->lastChar &&
4552 !emptyLinesVisible(textD)))
4553 return;
4555 @@ -711,23 +766,103 @@ static void textDRedisplayRange(textDisp
4556 resetClipRectangles(textD);
4558 /* If the starting and ending lines are the same, redisplay the single
4559 line between "start" and "end" */
4560 if (startLine == lastLine) {
4561 + /* Add one to endIndex to catch the caret at the end of a range. */
4562 redisplayLine(textD, startLine, 0, INT_MAX, startIndex, endIndex);
4563 - return;
4565 + if (-1 != textD->lineStarts[startLine] ||
4566 + (BufCountDispChars(textD->buffer, textD->lineStarts[startLine],
4567 + start) <= textD->wrapMargin &&
4568 + BufCountDispChars(textD->buffer, textD->lineStarts[startLine],
4569 + end) >= textD->wrapMargin))
4571 + /* redraw wrap margin if it got erased */
4572 + drawWrapMargin(textD);
4574 + } else {
4575 + /* Redisplay the first line from "start" */
4576 + redisplayLine(textD, startLine, 0, INT_MAX, startIndex, INT_MAX);
4578 + /* Redisplay the lines in between at their full width */
4579 + for (i = startLine+1; i < lastLine; i++) {
4580 + redisplayLine(textD, i, 0, INT_MAX, 0, INT_MAX);
4583 + /* Redisplay the last line to "end". Add one to the endIndex to catch
4584 + the caret at the end of a range. */
4585 + redisplayLine(textD, lastLine, 0, INT_MAX, 0, endIndex);
4587 + /* redraw wrap margin */
4588 + drawWrapMargin(textD);
4591 - /* Redisplay the first line from "start" */
4592 - redisplayLine(textD, startLine, 0, INT_MAX, startIndex, INT_MAX);
4594 - /* Redisplay the lines in between at their full width */
4595 - for (i=startLine+1; i<lastLine; i++)
4596 - redisplayLine(textD, i, 0, INT_MAX, 0, INT_MAX);
4599 - /* Redisplay the last line to "end" */
4600 - redisplayLine(textD, lastLine, 0, INT_MAX, 0, endIndex);
4602 +** Custom version of TextDRedisplayRange that only updates the area around
4603 +** the cursor.
4605 +static void redisplayCursor(textDisp* textD)
4607 + int cursorLine, lineStart, start, end, startIndex, endIndex;
4608 + int pos = textD->cursorPos;
4609 + Boolean cursorLineChanged;
4611 + /* If the cursor is outside of the displayed text, just return */
4612 + if (pos + 1 < textD->firstChar || pos - 1 > textD->lastChar) {
4613 + return;
4616 + if (!posToVisibleLineNum(textD, pos, &cursorLine)) {
4617 + /* At first sight, this can only be reached when redisplayCursor()
4618 + is miscalled or when the catch above didn't work. There is at
4619 + least one situation though which makes the catch helpless: If
4620 + your caret is in the last line, column 1 and you move it down,
4621 + textD->cursorPos will be changed *before* this function is
4622 + called, the automatic scroll will be done after. */
4623 + return;
4626 + /* Find the position right before and after the cursor,
4627 + but make sure that we stay on the same line. */
4628 + lineStart = TextDStartOfLine(textD, pos);
4629 + start = max(lineStart, pos - 1);
4630 + end = min(pos + 1, TextDEndOfLine(textD, lineStart, True) + 1);
4632 + /* Get the starting and ending positions within the line. */
4633 + startIndex = start - lineStart;
4634 + endIndex = end - lineStart;
4636 + /* Reset the clipping rectangles for the drawing GCs which are shared
4637 + using XtAllocateGC, and may have changed since the last use */
4638 + resetClipRectangles(textD);
4640 + /* jegub */
4641 + cursorLineChanged = (textD->oldCursorPos != textD->cursorPos
4642 + || textD->oldLineStart != lineStart);
4644 + redisplayLine(textD, cursorLine, 0, INT_MAX, startIndex, endIndex);
4646 + /* jegub */
4647 + if (cursorLineChanged) {
4648 + /* Hairline destroyed in old cursor line! Redraw neccessary. */
4649 + drawWrapMargin(textD);
4650 + return;
4653 + if (BufCountDispChars(textD->buffer, lineStart, end) < textD->wrapMargin) {
4654 + /* hairline is off-screen, most common case */
4655 + return;
4658 + if (BufCountDispChars(textD->buffer, lineStart, start)
4659 + > textD->wrapMargin) {
4660 + return;
4663 + drawWrapMargin(textD);
4667 ** Set the scroll position of the text display vertically by line number and
4668 ** horizontally by pixel offset from the left margin
4669 @@ -769,12 +904,14 @@ void TextDGetScroll(textDisp *textD, int
4670 ** Set the position of the text insertion cursor for text display "textD"
4672 void TextDSetInsertPosition(textDisp *textD, int newPos)
4674 /* make sure new position is ok, do nothing if it hasn't changed */
4675 - if (newPos == textD->cursorPos)
4676 - return;
4677 + if (newPos == textD->cursorPos) {
4678 + return;
4681 if (newPos < 0) newPos = 0;
4682 if (newPos > textD->buffer->length) newPos = textD->buffer->length;
4684 /* cursor movement cancels vertical cursor motion column */
4685 textD->cursorPreferredCol = -1;
4686 @@ -783,37 +920,45 @@ void TextDSetInsertPosition(textDisp *te
4687 TextDBlankCursor(textD);
4689 /* draw it at its new position */
4690 textD->cursorPos = newPos;
4691 textD->cursorOn = True;
4692 - textDRedisplayRange(textD, textD->cursorPos-1, textD->cursorPos + 1);
4694 + redisplayCursor(textD);
4696 + /* We have to force redraw of the hairline here: The hairline will be
4697 + erased if the cursorline changes, but will not be redrawn by
4698 + redisplayCursor() (only works on the area immedietely surrounding
4699 + the cursor). */
4700 + drawWrapMargin(textD);
4703 void TextDBlankCursor(textDisp *textD)
4705 if (!textD->cursorOn)
4706 return;
4708 blankCursorProtrusions(textD);
4709 textD->cursorOn = False;
4710 - textDRedisplayRange(textD, textD->cursorPos-1, textD->cursorPos+1);
4711 + redisplayCursor(textD);
4714 void TextDUnblankCursor(textDisp *textD)
4716 if (!textD->cursorOn) {
4717 textD->cursorOn = True;
4718 - textDRedisplayRange(textD, textD->cursorPos-1, textD->cursorPos+1);
4719 + redisplayCursor(textD);
4723 void TextDSetCursorStyle(textDisp *textD, int style)
4725 textD->cursorStyle = style;
4726 blankCursorProtrusions(textD);
4727 - if (textD->cursorOn) {
4728 - textDRedisplayRange(textD, textD->cursorPos-1, textD->cursorPos + 1);
4729 + if (textD->cursorOn)
4731 + redisplayCursor(textD);
4735 void TextDSetWrapMode(textDisp *textD, int wrap, int wrapMargin)
4737 @@ -845,10 +990,19 @@ void TextDSetWrapMode(textDisp *textD, i
4738 /* Do a full redraw */
4739 TextDRedisplayRect(textD, 0, textD->top, textD->width + textD->left,
4740 textD->height);
4743 +void TextDSetShowWrapMargin(textDisp* textD, int state)
4745 + textD->showWrapMargin = state;
4747 + /* Do a full redraw */
4748 + TextDRedisplayRect(textD, 0, textD->top, textD->width + textD->left,
4749 + textD->height);
4752 int TextDGetInsertPosition(textDisp *textD)
4754 return textD->cursorPos;
4757 @@ -1341,15 +1495,15 @@ int TextDMoveDown(textDisp *textD, int a
4760 column = textD->cursorPreferredCol >= 0
4761 ? textD->cursorPreferredCol
4762 : BufCountDispChars(textD->buffer, lineStartPos, textD->cursorPos);
4764 - if (absolute)
4765 + if (absolute) {
4766 nextLineStartPos = BufCountForwardNLines(textD->buffer, lineStartPos, 1);
4767 - else
4768 + } else {
4769 nextLineStartPos = TextDCountForwardNLines(textD, lineStartPos, 1, True);
4772 newPos = BufCountForwardDispChars(textD->buffer, nextLineStartPos, column);
4774 if (textD->continuousWrap && !absolute) {
4775 newPos = min(newPos, TextDEndOfLine(textD, nextLineStartPos, True));
4776 @@ -2720,12 +2994,13 @@ static void setScroll(textDisp *textD, i
4778 else if (xOffset < 0) {
4779 TextDRedisplayRect(textD, textD->left + textD->width + xOffset,
4780 textD->top, -xOffset, textD->height);
4783 /* Restore protruding parts of the cursor */
4784 - textDRedisplayRange(textD, textD->cursorPos-1, textD->cursorPos+1);
4785 + redisplayCursor(textD);
4788 /* Refresh line number/calltip display if its up and we've scrolled
4789 vertically */
4790 if (lineDelta != 0) {
4791 @@ -2886,14 +3161,34 @@ static void redrawLineNumbers(textDisp *
4793 static void vScrollCB(Widget w, XtPointer clientData, XtPointer callData)
4795 textDisp *textD = (textDisp *)clientData;
4796 int newValue = ((XmScrollBarCallbackStruct *)callData)->value;
4797 + int reason = ((XmScrollBarCallbackStruct*) callData)->reason;
4798 int lineDelta = newValue - textD->topLineNum;
4800 - if (lineDelta == 0)
4802 + if (0 == lineDelta) {
4803 + KillScrolltip(textD);
4804 return;
4807 + /* lineDelta is always != 0 for XmCR_DRAG */
4808 + /* Scrolltip does not work for continuous wrap. The only way to get the
4809 + line number is through textDisp->absTopLineNum, but this value is very
4810 + inaccurate for large files. So no tip. */
4811 + if (XmCR_DRAG == reason && !textD->continuousWrap && textD->showScrolltip) {
4812 + /* Display a scrolltip showing the line number about one third down
4813 + from the top, the position a search jumps to. */
4814 + XEvent* event = ((XmScrollBarCallbackStruct*) callData)->event;
4815 + XMotionEvent* motionEvent = (XMotionEvent*) event;
4816 + char valueBuffer[TYPE_INT_STR_SIZE(int)];
4818 + sprintf(valueBuffer, "%i", newValue + (textD->nVisibleLines / 3));
4819 + ShowScrolltip(textD, valueBuffer, motionEvent->x_root - 50,
4820 + motionEvent->y_root);
4823 setScroll(textD, newValue, textD->horizOffset, False, True);
4825 static void hScrollCB(Widget w, XtPointer clientData, XtPointer callData)
4827 textDisp *textD = (textDisp *)clientData;
4828 @@ -3008,11 +3303,12 @@ static void blankCursorProtrusions(textD
4829 ** Allocate shared graphics contexts used by the widget, which must be
4830 ** re-allocated on a font change.
4832 static void allocateFixedFontGCs(textDisp *textD, XFontStruct *fontStruct,
4833 Pixel bgPixel, Pixel fgPixel, Pixel selectFGPixel, Pixel selectBGPixel,
4834 - Pixel highlightFGPixel, Pixel highlightBGPixel, Pixel lineNumFGPixel)
4835 + Pixel highlightFGPixel, Pixel highlightBGPixel, Pixel lineNumFGPixel,
4836 + Pixel wrapMarginFGPixel)
4838 textD->gc = allocateGC(textD->w, GCFont | GCForeground | GCBackground,
4839 fgPixel, bgPixel, fontStruct->fid, GCClipMask, GCArcMode);
4840 textD->selectGC = allocateGC(textD->w, GCFont | GCForeground | GCBackground,
4841 selectFGPixel, selectBGPixel, fontStruct->fid, GCClipMask,
4842 @@ -3022,13 +3318,20 @@ static void allocateFixedFontGCs(textDis
4843 textD->highlightGC = allocateGC(textD->w, GCFont|GCForeground|GCBackground,
4844 highlightFGPixel, highlightBGPixel, fontStruct->fid, GCClipMask,
4845 GCArcMode);
4846 textD->highlightBGGC = allocateGC(textD->w, GCForeground, highlightBGPixel,
4847 0, fontStruct->fid, GCClipMask, GCArcMode);
4848 textD->lineNumGC = allocateGC(textD->w, GCFont | GCForeground |
4849 GCBackground, lineNumFGPixel, bgPixel, fontStruct->fid,
4850 GCClipMask, GCArcMode);
4851 + textD->wrapMarginGC = allocateGC(textD->w, GCForeground | GCBackground,
4852 + wrapMarginFGPixel, bgPixel, fontStruct->fid, GCClipMask, GCArcMode);
4856 ** X11R4 does not have the XtAllocateGC function for sharing graphics contexts
4857 ** with changeable fields. Unfortunately the R4 call for creating shared
4858 @@ -3097,10 +3400,16 @@ static void resetClipRectangles(textDisp
4859 &clipRect, 1, Unsorted);
4860 XSetClipRectangles(display, textD->highlightBGGC, 0, 0,
4861 &clipRect, 1, Unsorted);
4862 XSetClipRectangles(display, textD->styleGC, 0, 0,
4863 &clipRect, 1, Unsorted);
4864 + XSetClipRectangles(display, textD->wrapMarginGC, 0, 0,
4865 + &clipRect, 1, Unsorted);
4869 ** Return the length of a line (number of displayable characters) by examining
4870 ** entries in the line starts array rather than by scanning for newlines
4871 @@ -3800,5 +4109,47 @@ void TextDSetupBGClasses(Widget w, XmStr
4872 return;
4874 memcpy(*pp_bgClass, bgClass, 256);
4875 memcpy(*pp_bgClassPixel, bgClassPixel, class_no * sizeof (Pixel));
4879 +** Draw wrap margin if requested
4881 +static void drawWrapMargin(textDisp *textD)
4883 + int fromX, fromY;
4884 + int fontHeight, lineHeight;
4887 + /* attempt to draw the wrap margin # only if
4888 + - widget has been realized
4889 + - font width is not -1, ie. not using different/proportional width fonts
4890 + - show wrap margins is enabled */
4891 + if (XtWindow(textD->w) != 0
4892 + && textD->fixedFontWidth != -1
4893 + && textD->showWrapMargin)
4895 + fromX = textD->left + (textD->fixedFontWidth * textD->wrapMargin)
4896 + - textD->horizOffset - 1;
4898 + /* compute rest of coordinates if line is to right of left margin */
4899 + if (fromX > textD->left)
4901 + fromY = textD->top;
4902 + fontHeight = textD->ascent + textD->descent;
4903 + lineHeight = textD->nVisibleLines * fontHeight - 1;
4904 + XDrawLine(XtDisplay(textD->w), XtWindow(textD->w),
4905 + textD->wrapMarginGC, fromX, fromY, fromX,
4906 + fromY + lineHeight);
4908 + Handle to move wrap margin around with the mouse.
4909 + XDrawLine(XtDisplay(textD->w), XtWindow(textD->w),
4910 + textD->wrapMarginGC, fromX - 1, fromY, fromX - 1,
4911 + fromY + 3);
4912 + XDrawLine(XtDisplay(textD->w), XtWindow(textD->w),
4913 + textD->wrapMarginGC, fromX + 1, fromY, fromX + 1,
4914 + fromY + 3);
4919 diff --quilt old/source/textDisp.h new/source/textDisp.h
4920 --- old/source/textDisp.h
4921 +++ new/source/textDisp.h
4922 @@ -72,10 +72,11 @@ typedef struct _calltipStruct {
4923 Boolean anchored; /* Is it anchored to a position */
4924 int pos; /* Position tip is anchored to */
4925 int hAlign; /* horizontal alignment */
4926 int vAlign; /* vertical alignment */
4927 int alignMode; /* Strict or sloppy alignment */
4928 + Widget widget; /* calltip's widget */
4929 } calltipStruct;
4931 typedef struct _textDisp {
4932 Widget w;
4933 int top, left, width, height, lineNumLeft, lineNumWidth;
4934 @@ -101,17 +102,21 @@ typedef struct _textDisp {
4935 either to a newline or one character
4936 beyond the end of the buffer) */
4937 int continuousWrap; /* Wrap long lines when displaying */
4938 int wrapMargin; /* Margin in # of char positions for
4939 wrapping in continuousWrap mode */
4940 + int showWrapMargin; /* draw line at wrap margin */
4941 int *lineStarts;
4942 - int topLineNum; /* Line number of top displayed line
4943 - of file (first line of file is 1) */
4944 - int absTopLineNum; /* In continuous wrap mode, the line
4945 - number of the top line if the text
4946 - were not wrapped (note that this is
4947 - only maintained as needed). */
4948 + int topLineNum; /* Almost the line number of top displayed line
4949 + of file (first line of file is 1). Actually
4950 + it's off by one screenful or so most of the
4951 + times. */
4952 + int absTopLineNum; /* In continuous wrap mode, almost the line
4953 + number of the top line if the text were not
4954 + wrapped. Actually it's off by one screenful
4955 + most of the times. (Note that this is only
4956 + maintained as needed). */
4957 int needAbsTopLineNum; /* Externally settable flag to continue
4958 maintaining absTopLineNum even if
4959 it isn't needed for line # display */
4960 int horizOffset; /* Horizontal scroll pos. in pixels */
4961 int visibility; /* Window visibility (see XVisibility event) */
4962 @@ -127,12 +132,15 @@ typedef struct _textDisp {
4963 int ascent, descent; /* Composite ascent and descent for
4964 primary font + all-highlight fonts */
4965 int fixedFontWidth; /* Font width if all current fonts are
4966 fixed and match in width, else -1 */
4967 Widget hScrollBar, vScrollBar;
4968 GC gc, selectGC, highlightGC; /* GCs for drawing text */
4969 GC selectBGGC, highlightBGGC; /* GCs for erasing text */
4970 GC cursorFGGC; /* GC for drawing the cursor */
4971 GC lineNumGC; /* GC for drawing line numbers */
4972 GC styleGC; /* GC with color and font unspecified
4973 for drawing colored/styled text */
4974 Pixel fgPixel, bgPixel; /* Foreground/Background colors */
4975 @@ -143,15 +151,15 @@ typedef struct _textDisp {
4976 Pixel lineNumFGPixel; /* Color for drawing line numbers */
4977 Pixel cursorFGPixel;
4978 Pixel *bgClassPixel; /* table of colors for each BG class */
4979 unsigned char *bgClass; /* obtains index into bgClassPixel[] */
4981 - Widget calltipW; /* The Label widget for the calltip */
4982 - Widget calltipShell; /* The Shell that holds the calltip */
4983 calltipStruct calltip; /* The info for the calltip itself */
4984 Pixel calltipFGPixel;
4985 Pixel calltipBGPixel;
4986 + Pixel wrapMarginFGPixel; /* color for drawing wrap margin */
4987 + GC wrapMarginGC; /* GC for drawing wrap margin */
4988 int suppressResync; /* Suppress resynchronization of line
4989 starts during buffer updates */
4990 int nLinesDeleted; /* Number of lines deleted during
4991 buffer modification (only used
4992 when resynchronization is
4993 @@ -159,28 +167,36 @@ typedef struct _textDisp {
4994 int modifyingTabDist; /* Whether tab distance is being
4995 modified */
4996 Boolean pointerHidden; /* true if the mouse pointer is
4997 hidden */
4998 graphicExposeTranslationEntry *graphicsExposeQueue;
4999 + Boolean showScrolltip;
5000 + Widget scrolltip;
5001 } textDisp;
5003 textDisp *TextDCreate(Widget widget, Widget hScrollBar, Widget vScrollBar,
5004 - Position left, Position top, Position width, Position height,
5005 - Position lineNumLeft, Position lineNumWidth, textBuffer *buffer,
5006 - XFontStruct *fontStruct, Pixel bgPixel, Pixel fgPixel,
5007 - Pixel selectFGPixel, Pixel selectBGPixel, Pixel highlightFGPixel,
5008 - Pixel highlightBGPixel, Pixel cursorFGPixel, Pixel lineNumFGPixel,
5009 - int continuousWrap, int wrapMargin, XmString bgClassString,
5010 - Pixel calltipFGPixel, Pixel calltipBGPixel);
5011 + Position left, Position top, Position width, Position height,
5012 + Position lineNumLeft, Position lineNumWidth,
5013 + textBuffer *buffer,
5014 + XFontStruct *fontStruct,
5015 + Pixel bgPixel, Pixel fgPixel, Pixel selectFGPixel, Pixel selectBGPixel,
5016 + Pixel highlightFGPixel, Pixel highlightBGPixel, Pixel cursorFGPixel,
5017 + Pixel lineNumFGPixel, Pixel wrapMarginFGPixel, Pixel calltipFGPixel,
5018 + Pixel calltipBGPixel,
5019 + int continuousWrap, int wrapMargin, Boolean showWrapMargin,
5020 + XmString bgClassString, Boolean showScrolltip);
5021 void TextDFree(textDisp *textD);
5022 void TextDSetBuffer(textDisp *textD, textBuffer *buffer);
5023 void TextDAttachHighlightData(textDisp *textD, textBuffer *styleBuffer,
5024 styleTableEntry *styleTable, int nStyles, char unfinishedStyle,
5025 unfinishedStyleCBProc unfinishedHighlightCB, void *cbArg);
5026 void TextDSetColors(textDisp *textD, Pixel textFgP, Pixel textBgP,
5027 Pixel selectFgP, Pixel selectBgP, Pixel hiliteFgP, Pixel hiliteBgP,
5028 - Pixel lineNoFgP, Pixel cursorFgP);
5029 + Pixel lineNoFgP, Pixel cursorFgP, Pixel wrapMarginFgP);
5030 void TextDSetFont(textDisp *textD, XFontStruct *fontStruct);
5031 int TextDMinFontWidth(textDisp *textD, Boolean considerStyles);
5032 int TextDMaxFontWidth(textDisp *textD, Boolean considerStyles);
5033 void TextDResize(textDisp *textD, int width, int height);
5034 void TextDRedisplayRect(textDisp *textD, int left, int top, int width,
5035 @@ -208,10 +224,11 @@ int TextDMoveUp(textDisp *textD, int abs
5036 int TextDMoveDown(textDisp *textD, int absolute);
5037 void TextDBlankCursor(textDisp *textD);
5038 void TextDUnblankCursor(textDisp *textD);
5039 void TextDSetCursorStyle(textDisp *textD, int style);
5040 void TextDSetWrapMode(textDisp *textD, int wrap, int wrapMargin);
5041 +void TextDSetShowWrapMargin(textDisp *textD, int state);
5042 int TextDEndOfLine(const textDisp* textD, const int pos,
5043 const Boolean startPosIsLineStart);
5044 int TextDStartOfLine(const textDisp* textD, const int pos);
5045 int TextDCountForwardNLines(const textDisp* textD, const int startPos,
5046 const unsigned nLines, const Boolean startPosIsLineStart);
5047 diff --quilt old/source/textP.h new/source/textP.h
5048 --- old/source/textP.h
5049 +++ new/source/textP.h
5050 @@ -57,10 +57,12 @@ extern TextClassRec nTextClassRec;
5052 typedef struct _TextPart {
5053 /* resources */
5054 Pixel selectFGPixel, selectBGPixel, highlightFGPixel, highlightBGPixel;
5055 Pixel cursorFGPixel, lineNumFGPixel, calltipFGPixel, calltipBGPixel;
5056 + Pixel wrapMarginFGPixel;
5057 XFontStruct *fontStruct;
5058 Boolean pendingDelete;
5059 Boolean autoShowInsertPos;
5060 Boolean autoWrap;
5061 Boolean autoWrapPastedText;
5062 @@ -69,14 +71,17 @@ typedef struct _TextPart {
5063 Boolean smartIndent;
5064 Boolean overstrike;
5065 Boolean heavyCursor;
5066 Boolean readOnly;
5067 Boolean hidePointer;
5068 + Boolean showScrolltip;
5069 int rows, columns;
5070 int marginWidth, marginHeight;
5071 int cursorBlinkRate;
5072 int wrapMargin;
5073 + Boolean showWrapMargin;
5074 int emulateTabs;
5075 int lineNumCols;
5076 char *delimiters;
5077 Cardinal cursorVPadding;
5078 Widget hScrollBar, vScrollBar;
5079 diff --quilt old/source/window.c new/source/window.c
5080 --- old/source/window.c
5081 +++ new/source/window.c
5082 @@ -6,11 +6,11 @@ static const char CVSID[] = "$Id: window
5083 * Copyright (C) 1999 Mark Edel *
5085 * This is free software; you can redistribute it and/or modify it under the *
5086 * terms of the GNU General Public License as published by the Free Software *
5087 * Foundation; either version 2 of the License, or (at your option) any later *
5088 -* version. In addition, you may distribute version of this program linked to *
5089 +* version. In addition, you may distribute versions of this program linked to *
5090 * Motif or Open Motif. See README for details. *
5092 * This software is distributed in the hope that it will be useful, but WITHOUT *
5093 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
5094 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
5095 @@ -167,10 +167,11 @@ static void showStats(WindowInfo *window
5096 static void showISearch(WindowInfo *window, int state);
5097 static void showStatsForm(WindowInfo *window);
5098 static void addToWindowList(WindowInfo *window);
5099 static void removeFromWindowList(WindowInfo *window);
5100 static void focusCB(Widget w, WindowInfo *window, XtPointer callData);
5101 +static void loosingFocusCB(Widget w, WindowInfo *window, XtPointer callData);
5102 static void modifiedCB(int pos, int nInserted, int nDeleted, int nRestyled,
5103 const char *deletedText, void *cbArg);
5104 static void movedCB(Widget w, WindowInfo *window, XtPointer callData);
5105 static void dragStartCB(Widget w, WindowInfo *window, XtPointer callData);
5106 static void dragEndCB(Widget w, WindowInfo *window, dragEndCBStruct *callData);
5107 @@ -257,19 +258,22 @@ WindowInfo *CreateWindow(const char *nam
5108 window->fileMissing = True;
5109 strcpy(window->filename, name);
5110 window->undo = NULL;
5111 window->redo = NULL;
5112 window->nPanes = 0;
5113 + window->lastFocus = NULL;
5114 window->autoSaveCharCount = 0;
5115 window->autoSaveOpCount = 0;
5116 window->undoOpCount = 0;
5117 window->undoMemUsed = 0;
5118 CLEAR_ALL_LOCKS(window->lockReasons);
5119 + window->transient = False;
5120 window->indentStyle = GetPrefAutoIndent(PLAIN_LANGUAGE_MODE);
5121 window->autoSave = GetPrefAutoSave();
5122 window->saveOldVersion = GetPrefSaveOldVersion();
5123 window->wrapMode = GetPrefWrap(PLAIN_LANGUAGE_MODE);
5124 + window->showWrapMargin = GetPrefShowWrapMargin();
5125 window->overstrike = False;
5126 window->showMatchingStyle = GetPrefShowMatching();
5127 window->matchSyntaxBased = GetPrefMatchSyntaxBased();
5128 window->showStats = GetPrefStatsLine();
5129 window->showISearchLine = GetPrefISearchLine();
5130 @@ -465,11 +469,12 @@ WindowInfo *CreateWindow(const char *nam
5132 window->iSearchRegexToggle = XtVaCreateManagedWidget("iSearchREToggle",
5133 xmToggleButtonWidgetClass, window->iSearchForm,
5134 XmNlabelString, s1=XmStringCreateSimple("RegExp"),
5135 XmNset, GetPrefSearch() == SEARCH_REGEX_NOCASE
5136 - || GetPrefSearch() == SEARCH_REGEX,
5137 + || GetPrefSearch() == SEARCH_REGEX
5138 + || GetPrefSearch() == SEARCH_REGEX_SMARTCASE,
5139 XmNtopAttachment, XmATTACH_FORM,
5140 XmNbottomAttachment, XmATTACH_FORM,
5141 XmNtopOffset, 1, /* see openmotif note above */
5142 XmNrightAttachment, XmATTACH_WIDGET,
5143 XmNrightWidget, window->iSearchCaseToggle,
5144 @@ -695,23 +700,25 @@ WindowInfo *CreateWindow(const char *nam
5145 text = createTextArea(pane, window, rows,cols,
5146 GetPrefEmTabDist(PLAIN_LANGUAGE_MODE), GetPrefDelimiters(),
5147 GetPrefWrapMargin(), window->showLineNumbers?MIN_LINE_NUM_COLS:0);
5148 XtManageChild(text);
5149 window->textArea = text;
5150 window->lastFocus = text;
5152 /* Set the initial colors from the globals. */
5153 SetColors(window,
5154 GetPrefColorName(TEXT_FG_COLOR ),
5155 GetPrefColorName(TEXT_BG_COLOR ),
5156 GetPrefColorName(SELECT_FG_COLOR),
5157 GetPrefColorName(SELECT_BG_COLOR),
5158 GetPrefColorName(HILITE_FG_COLOR),
5159 GetPrefColorName(HILITE_BG_COLOR),
5160 GetPrefColorName(LINENO_FG_COLOR),
5161 - GetPrefColorName(CURSOR_FG_COLOR));
5162 + GetPrefColorName(CURSOR_FG_COLOR),
5163 + GetPrefColorName(WRAPMARGIN_FG_COLOR));
5165 /* Create the right button popup menu (note: order is important here,
5166 since the translation for popping up this menu was probably already
5167 added in createTextArea, but CreateBGMenu requires window->textArea
5168 to be set so it can attach the menu to it (because menu shells are
5169 finicky about the kinds of widgets they are attached to)) */
5170 @@ -1214,14 +1221,15 @@ void SplitPane(WindowInfo *window)
5171 newTextD = ((TextWidget)text)->text.textD;
5172 XtVaSetValues(text,
5173 XmNforeground, textD->fgPixel,
5174 XmNbackground, textD->bgPixel,
5175 NULL);
5176 - TextDSetColors( newTextD, textD->fgPixel, textD->bgPixel,
5177 - textD->selectFGPixel, textD->selectBGPixel, textD->highlightFGPixel,
5178 - textD->highlightBGPixel, textD->lineNumFGPixel,
5179 - textD->cursorFGPixel );
5180 + TextDSetColors(newTextD, textD->fgPixel, textD->bgPixel,
5181 + textD->selectFGPixel, textD->selectBGPixel,
5182 + textD->highlightFGPixel, textD->highlightBGPixel,
5183 + textD->lineNumFGPixel, textD->cursorFGPixel,
5184 + textD->wrapMarginFGPixel);
5186 /* Set the minimum pane height in the new pane */
5187 UpdateMinPaneHeights(window);
5189 /* adjust the heights, scroll positions, etc., to split the focus pane */
5190 @@ -1292,11 +1300,11 @@ void ClosePane(WindowInfo *window)
5192 short paneHeights[MAX_PANES+1];
5193 int insertPositions[MAX_PANES+1], topLines[MAX_PANES+1];
5194 int horizOffsets[MAX_PANES+1];
5195 int i, focusPane;
5196 - Widget text;
5197 + Widget text = NULL;
5199 /* Don't delete the last pane */
5200 if (window->nPanes <= 0)
5201 return;
5203 @@ -1853,11 +1866,12 @@ void SetFonts(WindowInfo *window, const
5204 UpdateMinPaneHeights(window);
5207 void SetColors(WindowInfo *window, const char *textFg, const char *textBg,
5208 const char *selectFg, const char *selectBg, const char *hiliteFg,
5209 - const char *hiliteBg, const char *lineNoFg, const char *cursorFg)
5210 + const char *hiliteBg, const char *lineNoFg, const char *cursorFg,
5211 + const char* wrapMarginFg)
5213 int i, dummy;
5214 Pixel textFgPix = AllocColor( window->textArea, textFg,
5215 &dummy, &dummy, &dummy),
5216 textBgPix = AllocColor( window->textArea, textBg,
5217 @@ -1871,30 +1885,36 @@ void SetColors(WindowInfo *window, const
5218 hiliteBgPix = AllocColor( window->textArea, hiliteBg,
5219 &dummy, &dummy, &dummy),
5220 lineNoFgPix = AllocColor( window->textArea, lineNoFg,
5221 &dummy, &dummy, &dummy),
5222 cursorFgPix = AllocColor( window->textArea, cursorFg,
5223 + &dummy, &dummy, &dummy),
5224 + wrapMarginFgPix = AllocColor( window->textArea, wrapMarginFg,
5225 &dummy, &dummy, &dummy);
5226 textDisp *textD;
5228 /* Update the main pane */
5229 XtVaSetValues(window->textArea,
5230 XmNforeground, textFgPix,
5231 XmNbackground, textBgPix,
5232 NULL);
5233 textD = ((TextWidget)window->textArea)->text.textD;
5234 TextDSetColors( textD, textFgPix, textBgPix, selectFgPix, selectBgPix,
5235 - hiliteFgPix, hiliteBgPix, lineNoFgPix, cursorFgPix );
5236 + hiliteFgPix, hiliteBgPix, lineNoFgPix, cursorFgPix,
5237 + wrapMarginFgPix);
5238 /* Update any additional panes */
5239 for (i=0; i<window->nPanes; i++) {
5240 XtVaSetValues(window->textPanes[i],
5241 XmNforeground, textFgPix,
5242 XmNbackground, textBgPix,
5243 NULL);
5244 textD = ((TextWidget)window->textPanes[i])->text.textD;
5245 TextDSetColors( textD, textFgPix, textBgPix, selectFgPix, selectBgPix,
5246 - hiliteFgPix, hiliteBgPix, lineNoFgPix, cursorFgPix );
5247 + hiliteFgPix, hiliteBgPix, lineNoFgPix, cursorFgPix,
5248 + wrapMarginFgPix);
5251 /* Redo any syntax highlighting */
5252 if (window->highlightData != NULL)
5253 UpdateHighlightStyles(window);
5254 @@ -1926,15 +1946,18 @@ void SetAutoWrap(WindowInfo *window, int
5255 for (i=0; i<window->nPanes; i++)
5256 XtVaSetValues(window->textPanes[i], textNautoWrap, autoWrap,
5257 textNcontinuousWrap, contWrap, NULL);
5258 window->wrapMode = state;
5260 if (IsTopDocument(window)) {
5261 XmToggleButtonSetState(window->newlineWrapItem, autoWrap, False);
5262 XmToggleButtonSetState(window->continuousWrapItem, contWrap, False);
5263 XmToggleButtonSetState(window->noWrapItem, state == NO_WRAP, False);
5266 + SetShowWrapMargin(window, window->showWrapMargin);
5270 ** Set the auto-scroll margin
5272 @@ -1946,10 +1969,37 @@ void SetAutoScroll(WindowInfo *window, i
5273 for (i=0; i<window->nPanes; i++)
5274 XtVaSetValues(window->textPanes[i], textNcursorVPadding, margin, NULL);
5278 +** Set show-wrap-margin style, one of NEVER, ALWAYS, ON-WRAP
5280 +void SetShowWrapMargin(WindowInfo* window, int state)
5282 + int i;
5283 + int alwaysShowWrapMargin = (SHOW_WRAP_MARGIN_ALWAYS == state);
5284 + int onWrapShowWrapMargin = (SHOW_WRAP_MARGIN_ON_WRAP == state);
5285 + int autoWrap = (NEWLINE_WRAP == window->wrapMode);
5286 + int contWrap = (CONTINUOUS_WRAP == window->wrapMode);
5287 + /* true or false only. not never/always/on-wrap. text widget does need to know
5288 + exact details. it just needs to know that wrap margin should be shown */
5289 + int showWrapMargin = (alwaysShowWrapMargin
5290 + || (onWrapShowWrapMargin && autoWrap)
5291 + || (onWrapShowWrapMargin && contWrap));
5293 + XtVaSetValues(window->textArea, textNshowWrapMargin, showWrapMargin, NULL);
5294 + for (i = 0; i < window->nPanes; i++) {
5295 + XtVaSetValues(window->textPanes[i],
5296 + textNshowWrapMargin, showWrapMargin,
5297 + NULL);
5299 + /* never/always/on-wrap needs to be stored in window settings, for generating
5300 + menu, etc */
5301 + window->showWrapMargin = state;
5305 ** Recover the window pointer from any widget in the window, by searching
5306 ** up the widget hierarcy for the top level container widget where the
5307 ** window pointer is stored in the userData field. In a tabbed window,
5308 ** this is the window pointer of the top (active) document, which is
5309 ** returned if w is 'shell-level' widget - menus, find/replace dialogs, etc.
5310 @@ -2203,10 +2253,19 @@ void MakeSelectionVisible(WindowInfo *wi
5311 static Widget createTextArea(Widget parent, WindowInfo *window, int rows,
5312 int cols, int emTabDist, char *delimiters, int wrapMargin,
5313 int lineNumCols)
5315 Widget text, sw, hScrollBar, vScrollBar, frame;
5316 + int alwaysShowWrapMargin = (window->showWrapMargin == SHOW_WRAP_MARGIN_ALWAYS);
5317 + int onWrapShowWrapMargin = (window->showWrapMargin == SHOW_WRAP_MARGIN_ON_WRAP);
5318 + int autoWrap = (window->wrapMode == NEWLINE_WRAP);
5319 + int contWrap = (window->wrapMode == CONTINUOUS_WRAP);
5320 + /* true or false only. not never/always/on-wrap. text widget does need to know
5321 + exact details. it just needs to know that wrap margin should be shown */
5322 + int showWrapMargin = (alwaysShowWrapMargin ||
5323 + (onWrapShowWrapMargin && autoWrap) ||
5324 + (onWrapShowWrapMargin && contWrap) );
5326 /* Create a text widget inside of a scrolled window widget */
5327 sw = XtVaCreateManagedWidget("scrolledW", xmScrolledWindowWidgetClass,
5328 parent, XmNpaneMaximum, SHRT_MAX,
5329 XmNpaneMinimum, PANE_MIN_HEIGHT, XmNhighlightThickness, 0, NULL);
5330 @@ -2226,24 +2285,29 @@ static Widget createTextArea(Widget pare
5331 textNfont, GetDefaultFontStruct(window->fontList),
5332 textNhScrollBar, hScrollBar, textNvScrollBar, vScrollBar,
5333 textNreadOnly, IS_ANY_LOCKED(window->lockReasons),
5334 textNwordDelimiters, delimiters,
5335 textNwrapMargin, wrapMargin,
5336 + textNshowWrapMargin, showWrapMargin,
5337 textNautoIndent, window->indentStyle == AUTO_INDENT,
5338 textNsmartIndent, window->indentStyle == SMART_INDENT,
5339 textNautoWrap, window->wrapMode == NEWLINE_WRAP,
5340 textNcontinuousWrap, window->wrapMode == CONTINUOUS_WRAP,
5341 textNoverstrike, window->overstrike,
5342 textNhidePointer, (Boolean) GetPrefTypingHidesPointer(),
5343 textNcursorVPadding, GetVerticalAutoScroll(),
5344 + textNshowScrolltip, GetPrefShowScrolltip(),
5345 NULL);
5347 XtVaSetValues(sw, XmNworkWindow, frame, XmNhorizontalScrollBar,
5348 hScrollBar, XmNverticalScrollBar, vScrollBar, NULL);
5350 /* add focus, drag, cursor tracking, and smart indent callbacks */
5351 XtAddCallback(text, textNfocusCallback, (XtCallbackProc)focusCB, window);
5352 + XtAddCallback(text, textNlosingFocusCallback,
5353 + (XtCallbackProc) loosingFocusCB, window);
5354 XtAddCallback(text, textNcursorMovementCallback, (XtCallbackProc)movedCB,
5355 window);
5356 XtAddCallback(text, textNdragStartCallback, (XtCallbackProc)dragStartCB,
5357 window);
5358 XtAddCallback(text, textNdragEndCallback, (XtCallbackProc)dragEndCB,
5359 @@ -2292,18 +2356,20 @@ static void movedCB(Widget w, WindowInfo
5360 if (0 != textWidget->text.cursorBlinkProcID)
5362 /* Start blinking the caret again. */
5363 ResetCursorBlink(textWidget, False);
5366 + MacroApplyHook(window, "cursor_moved_hook", 0, NULL, NULL);
5369 static void modifiedCB(int pos, int nInserted, int nDeleted, int nRestyled,
5370 const char *deletedText, void *cbArg)
5372 WindowInfo *window = (WindowInfo *)cbArg;
5373 int selected = window->buffer->primary.selected;
5376 /* update the table of bookmarks */
5377 if (!window->ignoreModify) {
5378 UpdateMarkTable(window, pos, nInserted, nDeleted);
5381 @@ -2363,25 +2429,34 @@ static void modifiedCB(int pos, int nIns
5382 /* Update # of bytes, and line and col statistics */
5383 UpdateStatsLine(window);
5385 /* Check if external changes have been made to file and warn user */
5386 CheckForChangesToFile(window);
5388 + MacroApplyHook(window, "modified_hook", 0, NULL, NULL);
5391 static void focusCB(Widget w, WindowInfo *window, XtPointer callData)
5393 /* record which window pane last had the keyboard focus */
5394 window->lastFocus = w;
5396 /* update line number statistic to reflect current focus pane */
5397 UpdateStatsLine(window);
5399 /* finish off the current incremental search */
5400 EndISearch(window);
5402 /* Check for changes to read-only status and/or file modifications */
5403 CheckForChangesToFile(window);
5405 + MacroApplyHook(window, "focus_hook", 0, NULL, NULL);
5408 +static void loosingFocusCB(Widget w, WindowInfo *window, XtPointer callData)
5410 + MacroApplyHook(window, "loosing_focus_hook", 0, NULL, NULL);
5413 static void dragStartCB(Widget w, WindowInfo *window, XtPointer callData)
5415 /* don't record all of the intermediate drag steps for undo */
5416 @@ -2519,20 +2594,25 @@ void AttachSessionMgrHandler(Widget appS
5417 ** on the shell window. I think this is the most reliable way to tell,
5418 ** but if someone has a better idea please send me a note).
5420 int IsIconic(WindowInfo *window)
5422 - unsigned long *property = NULL;
5423 + /* We expect back a CARD32 (see ICCCM 4.1.3.1) so we use type long to
5424 + get enough room for it, even if it's casted down later on. */
5425 + unsigned long* property = NULL;
5426 unsigned long nItems;
5427 unsigned long leftover;
5428 static Atom wmStateAtom = 0;
5429 Atom actualType;
5430 int actualFormat;
5431 int result;
5433 - if (wmStateAtom == 0)
5434 - wmStateAtom = XInternAtom(XtDisplay(window->shell), "WM_STATE", False);
5435 + if (0 == wmStateAtom) {
5436 + /* Get Atom for WM_STATE, create if it does not exist. */
5437 + wmStateAtom = XInternAtom(XtDisplay(window->shell), "WM_STATE", False);
5440 if (XGetWindowProperty(XtDisplay(window->shell), XtWindow(window->shell),
5441 wmStateAtom, 0L, 1L, False, wmStateAtom, &actualType, &actualFormat,
5442 &nItems, &leftover, (unsigned char **)&property) != Success ||
5443 nItems != 1 || property == NULL)
5444 return FALSE;
5445 @@ -3276,19 +3364,22 @@ WindowInfo* CreateDocument(WindowInfo* s
5446 window->lastModTime = 0;
5447 strcpy(window->filename, name);
5448 window->undo = NULL;
5449 window->redo = NULL;
5450 window->nPanes = 0;
5451 window->autoSaveCharCount = 0;
5452 window->autoSaveOpCount = 0;
5453 window->undoOpCount = 0;
5454 window->undoMemUsed = 0;
5455 CLEAR_ALL_LOCKS(window->lockReasons);
5456 + window->transient = False;
5457 window->indentStyle = GetPrefAutoIndent(PLAIN_LANGUAGE_MODE);
5458 window->autoSave = GetPrefAutoSave();
5459 window->saveOldVersion = GetPrefSaveOldVersion();
5460 window->wrapMode = GetPrefWrap(PLAIN_LANGUAGE_MODE);
5461 + window->showWrapMargin = GetPrefShowWrapMargin();
5462 window->overstrike = False;
5463 window->showMatchingStyle = GetPrefShowMatching();
5464 window->matchSyntaxBased = GetPrefMatchSyntaxBased();
5465 window->highlightSyntax = GetPrefHighlightSyntax();
5466 window->backlightCharTypes = NULL;
5467 @@ -3378,23 +3469,25 @@ WindowInfo* CreateDocument(WindowInfo* s
5468 text = createTextArea(pane, window, nRows, nCols,
5469 GetPrefEmTabDist(PLAIN_LANGUAGE_MODE), GetPrefDelimiters(),
5470 GetPrefWrapMargin(), window->showLineNumbers?MIN_LINE_NUM_COLS:0);
5471 XtManageChild(text);
5472 window->textArea = text;
5473 window->lastFocus = text;
5475 /* Set the initial colors from the globals. */
5476 SetColors(window,
5477 GetPrefColorName(TEXT_FG_COLOR ),
5478 GetPrefColorName(TEXT_BG_COLOR ),
5479 GetPrefColorName(SELECT_FG_COLOR),
5480 GetPrefColorName(SELECT_BG_COLOR),
5481 GetPrefColorName(HILITE_FG_COLOR),
5482 GetPrefColorName(HILITE_BG_COLOR),
5483 GetPrefColorName(LINENO_FG_COLOR),
5484 - GetPrefColorName(CURSOR_FG_COLOR));
5485 + GetPrefColorName(CURSOR_FG_COLOR),
5486 + GetPrefColorName(WRAPMARGIN_FG_COLOR));
5488 /* Create the right button popup menu (note: order is important here,
5489 since the translation for popping up this menu was probably already
5490 added in createTextArea, but CreateBGMenu requires window->textArea
5491 to be set so it can attach the menu to it (because menu shells are
5492 finicky about the kinds of widgets they are attached to)) */
5493 @@ -3717,10 +3810,11 @@ void RefreshMenuToggleStates(WindowInfo
5494 #endif
5495 XmToggleButtonSetState(window->autoSaveItem, window->autoSave, False);
5496 XmToggleButtonSetState(window->overtypeModeItem, window->overstrike, False);
5497 XmToggleButtonSetState(window->matchSyntaxBasedItem, window->matchSyntaxBased, False);
5498 XmToggleButtonSetState(window->readOnlyItem, IS_USER_LOCKED(window->lockReasons), False);
5499 + XmToggleButtonSetState(window->transientItem, window->transient, False);
5501 XtSetSensitive(window->smartIndentItem,
5502 SmartIndentMacrosAvailable(LanguageModeName(window->languageMode)));
5504 SetAutoIndent(window, window->indentStyle);
5505 @@ -4178,11 +4272,12 @@ static void cloneTextPanes(WindowInfo *w
5506 XtVaSetValues(text, XmNforeground, textD->fgPixel,
5507 XmNbackground, textD->bgPixel, NULL);
5508 TextDSetColors(newTextD, textD->fgPixel, textD->bgPixel,
5509 textD->selectFGPixel, textD->selectBGPixel,
5510 textD->highlightFGPixel,textD->highlightBGPixel,
5511 - textD->lineNumFGPixel, textD->cursorFGPixel);
5512 + textD->lineNumFGPixel, textD->cursorFGPixel,
5513 + textD->wrapMarginFGPixel);
5516 /* Set the minimum pane height in the new pane */
5517 UpdateMinPaneHeights(window);
5519 @@ -4330,10 +4425,11 @@ static void cloneDocument(WindowInfo *wi
5520 window->findLastLiteralCase = orgWin->findLastLiteralCase;
5521 window->device = orgWin->device;
5522 window->inode = orgWin->inode;
5523 window->fileClosedAtom = orgWin->fileClosedAtom;
5524 orgWin->fileClosedAtom = None;
5525 + window->transient = orgWin->transient;
5527 /* copy the text/split panes settings, cursor pos & selection */
5528 cloneTextPanes(window, orgWin);
5530 /* copy undo & redo list */
5531 diff --quilt old/source/window.h new/source/window.h
5532 --- old/source/window.h
5533 +++ new/source/window.h
5534 @@ -51,13 +51,16 @@ void SetAutoIndent(WindowInfo *window, i
5535 void SetShowMatching(WindowInfo *window, int state);
5536 void SetFonts(WindowInfo *window, const char *fontName, const char *italicName,
5537 const char *boldName, const char *boldItalicName);
5538 void SetColors(WindowInfo *window, const char *textFg, const char *textBg,
5539 const char *selectFg, const char *selectBg, const char *hiliteFg,
5540 - const char *hiliteBg, const char *lineNoFg, const char *cursorFg);
5541 + const char *hiliteBg, const char *lineNoFg, const char *cursorFg,
5542 + const char* wrapMarginFg);
5543 void SetOverstrike(WindowInfo *window, int overstrike);
5544 void SetAutoWrap(WindowInfo *window, int state);
5545 +void SetWrapMargin(WindowInfo *window, int margin);
5546 +void SetShowWrapMargin(WindowInfo *window, int state);
5547 void SetAutoScroll(WindowInfo *window, int margin);
5548 void SplitPane(WindowInfo *window);
5549 Widget GetPaneByIndex(WindowInfo *window, int paneIndex);
5550 int WidgetToPaneIndex(WindowInfo *window, Widget w);
5551 void ClosePane(WindowInfo *window);
5552 diff --quilt old/util/fileUtils.c new/util/fileUtils.c
5553 --- old/util/fileUtils.c
5554 +++ new/util/fileUtils.c
5555 @@ -83,11 +83,11 @@ static void copyThruSlash(char **toStrin
5558 ** Decompose a Unix file name into a file name and a path.
5559 ** Return non-zero value if it fails, zero else.
5560 ** For now we assume that filename and pathname are at
5561 -** least MAXPATHLEN chars long.
5562 +** most MAXPATHLEN chars long.
5563 ** To skip setting filename or pathname pass NULL for that argument.
5566 ParseFilename(const char *fullname, char *filename, char *pathname)
5568 diff --quilt old/util/getfiles.c new/util/getfiles.c
5569 --- old/util/getfiles.c
5570 +++ new/util/getfiles.c
5571 @@ -6,11 +6,11 @@ static const char CVSID[] = "$Id: getfil
5572 * Copyright (C) 1999 Mark Edel *
5574 * This is free software; you can redistribute it and/or modify it under the *
5575 * terms of the GNU General Public License as published by the Free Software *
5576 * Foundation; either version 2 of the License, or (at your option) any later *
5577 -* version. In addition, you may distribute version of this program linked to *
5578 +* version. In addition, you may distribute versions of this program linked to *
5579 * Motif or Open Motif. See README for details. *
5581 * This software is distributed in the hope that it will be useful, but WITHOUT *
5582 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
5583 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
5584 @@ -35,23 +35,19 @@ static const char CVSID[] = "$Id: getfil
5585 * a directory when no filename was specified *
5586 * 6/24/92 by MWE: Made filename list and directory list typeable, *
5587 * set initial focus to filename list *
5588 * 6/25/93 by JMK: Fix memory leaks found by Purify. *
5590 -* Included are two routines written using Motif for accessing files: *
5591 -* *
5592 -* GetExistingFilename presents a FileSelectionBox dialog where users can *
5593 -* choose an existing file to open. *
5594 -* *
5595 *******************************************************************************/
5597 #ifdef HAVE_CONFIG_H
5598 #include "../config.h"
5599 #endif
5601 -#include "getfiles.h"
5602 +#include "DialogF.h"
5603 #include "fileUtils.h"
5604 +#include "getfiles.h"
5605 #include "misc.h"
5607 #include <stdio.h>
5608 #include <stdlib.h>
5609 #include <string.h>
5610 @@ -73,15 +69,19 @@ static const char CVSID[] = "$Id: getfil
5612 #include <X11/keysym.h>
5613 #include <Xm/Xm.h>
5614 #include <Xm/FileSB.h>
5615 #include <Xm/Form.h>
5616 +#include <Xm/Label.h>
5617 #include <Xm/List.h>
5618 #include <Xm/MessageB.h>
5619 +#include <Xm/PushB.h>
5620 #include <Xm/PushBG.h>
5621 -#include <Xm/Text.h>
5622 +#include <Xm/RowColumn.h>
5623 #include <Xm/TextF.h>
5624 +#include <Xm/Text.h>
5625 +#include <Xm/ToggleB.h>
5627 #ifdef HAVE_DEBUG_H
5628 #include "../debug.h"
5629 #endif
5631 @@ -93,26 +93,29 @@ static const char CVSID[] = "$Id: getfil
5632 #define MAX_LIST_KESTROKE_WAIT 2000 /* Allowable delay in milliseconds
5633 between characters typed to a list
5634 before starting over (throwing
5635 out the accumulated characters */
5637 +#define HFSB_OK 1 /* Get Filename OK constant */
5638 +#define HFSB_CANCEL 2 /* Get Filename Cancel constant */
5640 #define SET_ONE_RSRC(widget, name, newValue) \
5642 static Arg tmpargs[1] = {{name, (XtArgVal)0}}; \
5643 tmpargs[0].value = (XtArgVal)newValue; \
5644 XtSetValues(widget, tmpargs, 1); \
5648 enum yesNoValues {ynNone, ynYes, ynNo};
5650 /* Saved default directory and pattern from last successful call */
5651 static XmString DefaultDirectory = NULL;
5652 static XmString DefaultPattern = NULL;
5654 -/* User settable option for leaving the file name text field in
5655 - GetExistingFilename dialogs. Off by default so new users will get
5656 - used to typing in the list rather than in the text field */
5657 +/* User settable option for leaving the file name text field in file
5658 + dialogs. Off by default so new users will get used to typing in the
5659 + list rather than in the text field */
5660 static int RemoveRedundantTextField = True;
5662 /* Text for help button help display */
5663 /* ... needs variant for VMS */
5664 #ifndef SGI_CUSTOM
5665 @@ -131,11 +134,14 @@ If you use the filter field, remember to
5666 either a file name, \"*\" is acceptable, or a trailing \"/\". If \
5667 you don't, the name after the last \"/\" is interpreted as the file name to \
5668 match. When you leave off the file name or trailing \"/\", you won't see \
5669 any files to open in the list \
5670 because the filter specification matched the directory file itself, rather \
5671 -than the files in the directory.";
5672 +than the files in the directory.\n"
5673 +"\n"
5674 +"Hidden files and directories (those whose names begin with a dot) will only "
5675 +"be shown if the 'Show hidden Files' button is activated.";
5677 static const char *HelpNew =
5678 "This dialog allows you to create a new file, or to save the current file \
5679 under a new name. To specify a file \
5680 name in the current directory, complete the name displayed in the \"Save File \
5681 @@ -151,11 +157,14 @@ to move around in the file system hierar
5682 directory names in the list, or selecting them and pressing the \
5683 \"Filter\" button will select that directory. To move upwards \
5684 in the directory tree, double \
5685 click on the directory entry ending in \"..\". You can also move directly \
5686 to a directory by typing the file specification of the path in the \"Filter\" \
5687 -field and pressing the \"Filter\" button.";
5688 +field and pressing the \"Filter\" button."
5689 +"\n"
5690 +"Hidden files and directories (those whose names begins with a dot) will only "
5691 +"be shown if the 'Show hidden Files' button is activated.";
5693 #else /* SGI_CUSTOM */
5694 static const char *HelpExist =
5695 "The \"File to Edit:\" field shows a list of directories and files in the \
5696 current directory.\n\
5697 @@ -175,11 +184,14 @@ will accept icons dragged from the deskt
5698 arrows, to the right, of the field recalls previously selected \
5699 directories.\n\
5701 The \"Filter\" button allows you to narrow down the list of files and \
5702 directories shown in the \"File to Edit:\" field. The default filter of \
5703 -\"*\" allows all files to be listed.";
5704 +\"*\" allows all files to be listed."
5705 +"\n"
5706 +"Hidden files and directories (those whose names begins with a dot) will only "
5707 +"be shown if the 'Show hidden Files' button is activated.";
5709 static const char *HelpNew =
5710 "This dialog allows you to create a new file or to save the current file \
5711 under a new name.\n\
5713 @@ -206,15 +218,20 @@ will accept icons dragged from the deskt
5714 arrows, to the right, of the field recalls previously selected \
5715 directories.\n\
5717 The \"Filter\" button allows you to narrow down the list of files and \
5718 directories shown in the \"Files\" field. The default filter of \
5719 -\"*\" allows all files to be listed.";
5720 -#endif /* SGI_CUSTOM */
5721 +\"*\" allows all files to be listed."
5722 +"\n"
5723 +"Hidden files and directories (those whose names begins with a dot) will only "
5724 +"be shown if the 'Show hidden Files' button is activated.";
5726 -/* Local Callback Routines and variables */
5727 +#endif /* SGI_CUSTOM */
5730 +** Local Callback Routines and variables
5732 static void newFileOKCB(Widget w, Boolean *client_data,
5733 XmFileSelectionBoxCallbackStruct *call_data);
5734 static void newFileCancelCB(Widget w, Boolean *client_data, caddr_t
5735 call_data);
5736 static void newHelpCB(Widget w, Widget helpPanel, caddr_t call_data);
5737 @@ -236,104 +253,441 @@ static void listCharEH(Widget w, XtPoint
5738 Boolean *continueDispatch);
5739 static void replacementDirSearchProc(Widget w, XtPointer searchData);
5740 static void replacementFileSearchProc(Widget w, XtPointer searchData);
5741 static void sortWidgetList(Widget listWidget);
5742 static int compareXmStrings(const void *string1, const void *string2);
5743 +static unsigned removeHiddenFiles(Widget listWidget);
5744 +static Boolean removeDotEntry(Widget listWidget);
5745 +static int isHiddenFile(const char* filename);
5746 +static int handleCustomExistFileSB(Widget existFileSB, char *filename);
5747 +static int handleCustomNewFileSB(Widget newFileSB, char *filename, char *defaultName);
5749 -static int SelectResult = GFN_CANCEL; /* Initialize results as cancel */
5750 +static int SelectResult = HFSB_CANCEL; /* Initialize results as cancel */
5751 static Widget YesNoDialog; /* "Overwrite?" dialog widget */
5752 static int YesNoResult; /* Result of overwrite dialog */
5753 static Widget ErrorDialog; /* Dialog widget for error msgs */
5754 static int ErrorDone; /* Flag to mark dialog completed */
5755 static void (*OrigDirSearchProc)(); /* Built in Motif directory search */
5756 static void (*OrigFileSearchProc)(); /* Built in Motif file search proc */
5757 +static void freeFileList(char** list);
5759 -/*
5760 - * Do the hard work of setting up a file selection dialog
5761 - */
5762 -Widget getFilenameHelper(Widget parent, char *promptString, char *filename,
5763 - int existing)
5765 - int n; /* number of arguments */
5766 - Arg args[MAX_ARGS]; /* arg list */
5767 - Widget fileSB; /* widget file select box */
5768 - XmString titleString; /* compound string for dialog title */
5769 +static Widget addUtilForm(const Widget fsd, const Boolean showHidden,
5770 + const Boolean haveFormatButtons, const Boolean isContWrapped,
5771 + Boolean* addWrap, int* fileFormat);
5772 +static void hiddenFilesCB(Widget widget, XtPointer client_data,
5773 + XtPointer call_data);
5774 +static void showOptionsCB(Widget pushButton, XtPointer client_data,
5775 + XtPointer call_data);
5776 +static void setFormatCB(Widget widget, XtPointer clientData, XtPointer callData);
5777 +static void addWrapCB(Widget w, XtPointer clientData, XtPointer callData);
5780 +** GetFilenameByDialog()
5782 +** Façade for file dialogs.
5784 +** TODO: Refactor the whole module
5785 +** TODO: The original saved/restored a default directory, but I don't see any
5786 +** adverse effects on OM 2.2.3 or Lesstif 0.95 by just skipping that
5787 +** part. Does this depend on the toolkit and/or version used?
5789 +gfbdValue* GetFilenameByDialog(const gfbdParams params)
5791 + /* Values */
5792 + gfbdValue* retValue;
5794 + /* widgets and other GUI stuff */
5795 + Widget fsd;
5796 + XmString titleString;
5798 + /* helpers */
5799 + unsigned n; /* arg list */
5800 + Arg args[MAX_ARGS]; /* arg list */
5801 + int rc; /* return code of handleCustomExistFileSB() */
5803 + /* Can probably be refactored away. */
5804 + fsbUserDataStruct userData;
5806 + /* some initialization */
5807 + retValue = (gfbdValue*) XtMalloc(sizeof(gfbdValue));
5808 + retValue->status = GFDB_ERROR;
5810 n = 0;
5811 - titleString = XmStringCreateSimple(promptString);
5812 + titleString = XmStringCreateLocalized(params.dialogTitle);
5813 XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
5814 XtSetArg(args[n], XmNdialogTitle, titleString); n++;
5815 - fileSB = CreateFileSelectionDialog(parent,"FileSelect",args,n);
5816 + XtSetArg(args[n], XmNresizePolicy, XmRESIZE_GROW); n++;
5817 + fsd = CreateFileSelectionDialog(params.parentShell, "fsd", args, n);
5818 XmStringFree(titleString);
5819 -#ifndef SGI_CUSTOM
5820 - if (existing && RemoveRedundantTextField)
5821 - XtUnmanageChild(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_TEXT));
5822 - XtUnmanageChild(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_SELECTION_LABEL));
5824 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_FILTER_LABEL),
5825 + /* Put mnemonic on labels; this will put the focus in the labeled widget
5826 + if activated. See misc.c:findAndActivateMnemonic() for details. */
5827 + XtVaSetValues(XmFileSelectionBoxGetChild(fsd, XmDIALOG_FILTER_LABEL),
5828 XmNmnemonic, 'l',
5829 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_FILTER_TEXT),
5830 + XmNuserData, XmFileSelectionBoxGetChild(fsd, XmDIALOG_FILTER_TEXT),
5831 NULL);
5832 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST_LABEL),
5833 + XtVaSetValues(XmFileSelectionBoxGetChild(fsd, XmDIALOG_DIR_LIST_LABEL),
5834 XmNmnemonic, 'D',
5835 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST),
5836 + XmNuserData, XmFileSelectionBoxGetChild(fsd, XmDIALOG_DIR_LIST),
5837 + NULL);
5838 + XtVaSetValues(XmFileSelectionBoxGetChild(fsd, XmDIALOG_LIST_LABEL),
5839 + XmNmnemonic, 'F',
5840 + XmNuserData, XmFileSelectionBoxGetChild(fsd, XmDIALOG_LIST),
5841 + NULL);
5842 + /* The last mnemonic originally used strspn() to find the last mnemonic,
5843 + but used the dialog's title instead of the list's label. Since it broke
5844 + user's GUI expectations I replaced it with a plain letter. */
5846 + /* Unmanage text field and label unless a label is given. */
5847 + if (NULL == params.textfieldLabel) {
5848 + XtUnmanageChild(XmFileSelectionBoxGetChild(fsd, XmDIALOG_TEXT));
5849 + XtUnmanageChild(XmFileSelectionBoxGetChild(fsd, XmDIALOG_SELECTION_LABEL));
5850 + } else {
5851 + XmString labelString = XmStringCreateLocalized(params.textfieldLabel);
5853 + XtVaSetValues(XmFileSelectionBoxGetChild(fsd, XmDIALOG_SELECTION_LABEL),
5854 + XmNlabelString, labelString,
5855 + NULL);
5856 + XtVaSetValues(XmFileSelectionBoxGetChild(fsd, XmDIALOG_SELECTION_LABEL),
5857 + XmNmnemonic, params.textfieldLabel[strspn(params.textfieldLabel, "lDF")],
5858 + XmNuserData, XmFileSelectionBoxGetChild(fsd, XmDIALOG_TEXT),
5859 + NULL);
5860 + XmStringFree(labelString);
5863 + retValue->fileFormat = params.fileFormat;
5864 + addUtilForm(fsd, params.showHidden, params.haveFormatButtons,
5865 + params.isContWrapped, &(retValue->addWrap), &(retValue->fileFormat));
5867 + /* Do the mnemonic magic. Wait until all mnemonics are prepared. */
5868 + AddDialogMnemonicHandler(fsd, FALSE);
5870 + /* Fix some ancient hardware/toolkit quirks. */
5871 + RemapDeleteKey(XmFileSelectionBoxGetChild(fsd, XmDIALOG_FILTER_TEXT));
5872 + RemapDeleteKey(XmFileSelectionBoxGetChild(fsd, XmDIALOG_TEXT));
5874 + userData.showHidden = params.showHidden;
5875 + XtVaSetValues(fsd, XmNuserData, &userData, NULL);
5877 + /* Refactor this. */
5878 + if (params.fileExists) {
5879 + rc = handleCustomExistFileSB(fsd, retValue->payload);
5880 + } else {
5881 + rc = handleCustomNewFileSB(fsd, retValue->payload, params.defaultName);
5884 + switch(rc) {
5885 + case HFSB_OK:
5886 + retValue->status = GFDB_OK;
5887 + break;
5888 + case HFSB_CANCEL:
5889 + retValue->status = GFDB_CANCEL;
5890 + break;
5891 + default:
5892 + /* fallback */
5893 + strncpy(retValue->payload, "Something murphied in GetFilenameByDialog, sorry.", MAXPATHLEN);
5894 + retValue->status = GFDB_ERROR;
5895 + break;
5898 + return retValue;
5902 +** Helper for GetFilenameByDialog()
5904 +** Note: Since mnemonics are set here, wait with your call to activate them
5905 +** via AddDialogMnemonicHandler() until this is done.
5907 +** TODO: The reliance on AddDialogMnemonicHandler() (called in the caller
5908 +** after addUtilForm()) breaks low coupling.
5910 +static Widget addUtilForm(const Widget fsd, const Boolean showHidden,
5911 + const Boolean haveFormatButtons, const Boolean isContWrapped,
5912 + Boolean* addWrap, int* fileFormat)
5914 + Widget utilForm; /* form containing utility widgets */
5915 + Widget optionsForm; /* container for option widgets */
5917 + Widget showOptionsCheckBox; /* (un)display additional options */
5918 + Widget showOptionsPushButton; /* (un)display additional options */
5919 + XmString showOptionsLabel; /* PushButton label */
5921 + Widget hiddenFilesCheckBox; /* (un)displaying hidden files */
5922 + Widget hiddenFilesToggleButton; /* (un)displaying hidden files */
5923 + XmString hiddenFilesLabel; /* ToggleButton label */
5925 + Widget formatBtnsRow;
5926 + Widget unixFormatButton, dosFormatButton, macFormatButton;
5927 + Widget wrapToggle;
5928 + Widget topWidget = NULL;
5930 + XmString s1 = NULL;
5932 + /* Creates a Form containing additional widgets */
5933 + utilForm = XtVaCreateManagedWidget("utilForm", xmFormWidgetClass, fsd, NULL);
5935 + /* Creates a RowColumn containing a PushButton to (un)display the
5936 + other options. */
5937 + showOptionsCheckBox = XtVaCreateManagedWidget("showOptionsCheckBox",
5938 + xmRowColumnWidgetClass, utilForm,
5939 + NULL);
5940 + showOptionsLabel = XmStringCreateLocalized("Less...");
5941 + showOptionsPushButton = XtVaCreateManagedWidget("showOptionsPushButton",
5942 + xmPushButtonWidgetClass, showOptionsCheckBox,
5943 + XmNmnemonic, 'M',
5944 + XmNlabelString, showOptionsLabel,
5945 + XmNuserData, 1,
5946 + NULL);
5947 + XmStringFree(showOptionsLabel);
5948 + XtAddCallback(showOptionsPushButton,
5949 + XmNactivateCallback, showOptionsCB,
5950 + (XtPointer) &fsd);
5952 + /* Creates a Form containing all options. */
5953 + optionsForm = XtVaCreateManagedWidget("optionsForm",
5954 + xmFormWidgetClass, utilForm,
5955 + XmNtopAttachment, XmATTACH_WIDGET,
5956 + XmNtopWidget, showOptionsCheckBox,
5957 + XmNbottomAttachment, XmATTACH_FORM,
5958 + XmNleftAttachment, XmATTACH_FORM,
5959 + XmNrightAttachment, XmATTACH_FORM,
5960 + NULL);
5962 + /* Adds format buttons. */
5963 + if (haveFormatButtons) {
5964 + /* Create RowColumn containing a number of push buttons for file format. */
5965 + formatBtnsRow = XtVaCreateManagedWidget("formatBtnsRow",
5966 + xmRowColumnWidgetClass, optionsForm,
5967 + XmNradioBehavior, XmONE_OF_MANY,
5968 + XmNorientation, XmHORIZONTAL,
5969 + XmNpacking, XmPACK_TIGHT,
5970 + XmNtopAttachment, XmATTACH_FORM,
5971 + XmNleftAttachment, XmATTACH_FORM,
5972 + NULL);
5974 + XtVaCreateManagedWidget("formatBtns",
5975 + xmLabelWidgetClass, formatBtnsRow,
5976 + XmNlabelString, s1 = XmStringCreateSimple("Format:"),
5977 + NULL);
5978 + XmStringFree(s1);
5980 + unixFormatButton = XtVaCreateManagedWidget("unixFormat",
5981 + xmToggleButtonWidgetClass, formatBtnsRow,
5982 + XmNlabelString, s1 = XmStringCreateSimple("Unix"),
5983 + XmNset, UNIX_FILE_FORMAT == *fileFormat,
5984 + XmNuserData, (XtPointer) UNIX_FILE_FORMAT,
5985 + XmNmarginHeight, 0,
5986 + XmNalignment, XmALIGNMENT_BEGINNING,
5987 + XmNmnemonic, 'U',
5988 + NULL);
5989 + XmStringFree(s1);
5990 + XtAddCallback(unixFormatButton, XmNvalueChangedCallback, setFormatCB,
5991 + fileFormat);
5993 + dosFormatButton = XtVaCreateManagedWidget("dosFormat",
5994 + xmToggleButtonWidgetClass, formatBtnsRow,
5995 + XmNlabelString, s1 = XmStringCreateSimple("DOS"),
5996 + XmNset, DOS_FILE_FORMAT == *fileFormat,
5997 + XmNuserData, (XtPointer) DOS_FILE_FORMAT,
5998 + XmNmarginHeight, 0,
5999 + XmNalignment, XmALIGNMENT_BEGINNING,
6000 + XmNmnemonic, 'O',
6001 + NULL);
6002 + XmStringFree(s1);
6003 + XtAddCallback(dosFormatButton, XmNvalueChangedCallback, setFormatCB,
6004 + fileFormat);
6006 + macFormatButton = XtVaCreateManagedWidget("macFormat",
6007 + xmToggleButtonWidgetClass, formatBtnsRow,
6008 + XmNlabelString, s1 = XmStringCreateSimple("Macintosh"),
6009 + XmNset, MAC_FILE_FORMAT == *fileFormat,
6010 + XmNuserData, (XtPointer) MAC_FILE_FORMAT,
6011 + XmNmarginHeight, 0,
6012 + XmNalignment, XmALIGNMENT_BEGINNING,
6013 + XmNmnemonic, 'M',
6014 + NULL);
6015 + XmStringFree(s1);
6016 + XtAddCallback(macFormatButton, XmNvalueChangedCallback, setFormatCB,
6017 + fileFormat);
6019 + if (isContWrapped) {
6020 + wrapToggle = XtVaCreateManagedWidget("addWrap",
6021 + xmToggleButtonWidgetClass, optionsForm,
6022 + XmNlabelString,
6023 + s1 = XmStringCreateSimple("Add line breaks where wrapped"),
6024 + XmNalignment, XmALIGNMENT_BEGINNING,
6025 + XmNmnemonic, 'A',
6026 + XmNtopAttachment, XmATTACH_WIDGET,
6027 + XmNtopWidget, formatBtnsRow,
6028 + XmNleftAttachment, XmATTACH_FORM, NULL);
6029 + XtAddCallback(wrapToggle, XmNvalueChangedCallback, addWrapCB, addWrap);
6030 + XmStringFree(s1);
6032 + topWidget = wrapToggle;
6033 + } else {
6034 + topWidget = formatBtnsRow;
6038 + /* Creates a RowColumn containing a ToggleButton to show/hide
6039 + hidden files in the file lists. */
6040 + hiddenFilesCheckBox = XtVaCreateManagedWidget("hiddenFilesCheckBox",
6041 + xmRowColumnWidgetClass,
6042 + optionsForm,
6043 + XmNtopAttachment, XmATTACH_WIDGET,
6044 + XmNtopWidget, topWidget,
6045 + XmNbottomAttachment, XmATTACH_FORM,
6046 + XmNleftAttachment, XmATTACH_FORM,
6047 + XmNrightAttachment, XmATTACH_FORM,
6048 NULL);
6049 - XtVaSetValues(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST_LABEL),
6050 - XmNmnemonic, promptString[strspn(promptString, "lD")],
6051 - XmNuserData, XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST),
6052 + hiddenFilesLabel = XmStringCreateLocalized("Show hidden Files");
6053 + hiddenFilesToggleButton = XtVaCreateManagedWidget("hiddenFilesToggleButton",
6054 + xmToggleButtonWidgetClass,
6055 + hiddenFilesCheckBox,
6056 + XmNmnemonic, 'h',
6057 + XmNlabelString, hiddenFilesLabel,
6058 + XmNset, showHidden,
6059 NULL);
6060 - AddDialogMnemonicHandler(fileSB, FALSE);
6061 - RemapDeleteKey(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_FILTER_TEXT));
6062 - RemapDeleteKey(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_TEXT));
6063 + XmStringFree(hiddenFilesLabel);
6064 + XtAddCallback(hiddenFilesToggleButton,
6065 + XmNvalueChangedCallback, hiddenFilesCB,
6066 + (XtPointer) &fsd);
6068 + return optionsForm;
6072 +** Callback for hiddenFilesToggleButton
6073 +** The ToggleButton's state is saved in the FileSelectionBox' XmNuserData
6074 +** field, so that it can be used in the XmN*searchProcs.
6076 +static void hiddenFilesCB(Widget widget,
6077 + XtPointer client_data,
6078 + XtPointer call_data)
6080 + XmToggleButtonCallbackStruct* state =
6081 + (XmToggleButtonCallbackStruct *) call_data;
6082 + Widget* fsbParent = (Widget*) client_data;
6083 + fsbUserDataStruct* userData;
6085 + /* Remember the button's setting for the sort routines */
6086 + XtVaGetValues(*fsbParent, XmNuserData, &userData, NULL);
6087 + userData->showHidden = state->set;
6089 +#if XmVERSION >= 2
6090 + /* This will take care of the the Motif FSB resource fileFilterStyle. It
6091 + is still honored by NEdit by using it to override the compiled-in
6092 + default (see source/preferences.c, initPrefDefaultsFromResources()),
6093 + but the internal resource will override it. */
6095 + int fileFilterStyle =
6096 + (state->set ? XmFILTER_NONE : XmFILTER_HIDDEN_FILES);
6097 + XtVaSetValues(*fsbParent, XmNfileFilterStyle, fileFilterStyle, NULL);
6099 #endif
6100 - return fileSB;
6102 + /* Reinitialize lists */
6103 + XmFileSelectionDoSearch(*fsbParent, NULL);
6107 +** Callback for showOptionsPushButton
6109 +** client_data ist supposed to carry a pointer to the FSB
6111 +static void showOptionsCB(Widget pushButton,
6112 + XtPointer client_data,
6113 + XtPointer call_data)
6115 + Boolean isShown;
6116 + XmString buttonLabel;
6117 + Widget* fsb = (Widget*) client_data;
6118 + Dimension optionFormHeight;
6119 + Widget optionsForm = XtNameToWidget(*fsb, "*optionsForm");
6120 + Dimension fsbHeight;
6122 + XtVaGetValues(pushButton, XmNuserData, &isShown, NULL);
6124 + /* Get initial size of FSB */
6125 + XtVaGetValues(*fsb, XmNheight, &fsbHeight, NULL);
6127 + if (isShown) {
6128 + isShown = False;
6130 + /* We change the size here because the Less/More button should
6131 + stay under the mouse pointer. */
6132 + XtVaGetValues(optionsForm, XmNheight, &optionFormHeight, NULL);
6133 + XtUnmanageChild(optionsForm);
6134 + XtVaSetValues(*fsb, XmNheight, fsbHeight - optionFormHeight, NULL);
6136 + /* FIXME: Is this a leak? Do we have to delete the old string? */
6137 + buttonLabel = XmStringCreateLocalized("More...");
6138 + XtVaSetValues(pushButton, XmNlabelString, buttonLabel, NULL);
6139 + XmStringFree(buttonLabel);
6140 + } else {
6141 + isShown = True;
6143 + /* We change the size here because the Less/More button should
6144 + stay under the mouse pointer. */
6145 + XtManageChild(optionsForm);
6146 + XtVaGetValues(optionsForm, XmNheight, &optionFormHeight, NULL);
6147 + XtVaSetValues(*fsb, XmNheight, fsbHeight + optionFormHeight, NULL);
6149 + /* FIXME: Is this a leak? Do we have to delete the old string? */
6150 + buttonLabel = XmStringCreateLocalized("Less...");
6151 + XtVaSetValues(pushButton, XmNlabelString, buttonLabel, NULL);
6152 + XmStringFree(buttonLabel);
6155 + XtVaSetValues(pushButton, XmNuserData, isShown, NULL);
6158 -/* GetExistingFilename */
6159 -/* */
6160 -/* This routine will popup a file selection box so that the user can */
6161 -/* select an existing file from the scrollable list. The user is */
6162 -/* prevented from entering a new filename because the edittable text */
6163 -/* area of the file selection box widget is unmanaged. After the user */
6164 -/* selects a file, GetExistingFilename returns the selected filename and */
6165 -/* GFN_OK, indicating that the OK button was pressed. If the user */
6166 -/* pressed the cancel button, the return value is GFN_CANCEL, and the */
6167 -/* filename character string supplied in the call is not altered. */
6168 -/* */
6169 -/* Arguments: */
6170 -/* */
6171 -/* Widget parent - parent widget id */
6172 -/* char * promptString - prompt string */
6173 -/* char * filename - a string to receive the selected filename */
6174 -/* (this string will not be altered if the */
6175 -/* user pressed the cancel button) */
6176 -/* */
6177 -/* Returns: GFN_OK - file was selected and OK button pressed */
6178 -/* GFN_CANCEL - Cancel button pressed and no returned file */
6179 -/* */
6180 -int GetExistingFilename(Widget parent, char *promptString, char *filename)
6182 - Widget existFileSB = getFilenameHelper(parent, promptString, filename,
6183 - True);
6184 - return HandleCustomExistFileSB(existFileSB, filename);
6187 -/* GetNewFilename
6189 - * Same as GetExistingFilename but pick a new file instead of an existing one.
6190 - * In this case the text area of the FSB is *not* unmanaged, so the user can
6191 - * enter a new filename.
6192 - */
6193 -int GetNewFilename(Widget parent, char *promptString, char *filename,
6194 - char *defaultName)
6196 +** Callback procedure for toggle button requesting newlines to be inserted
6197 +** to emulate continuous wrapping.
6199 +static void addWrapCB(Widget w, XtPointer clientData, XtPointer callData)
6201 - Widget fileSB = getFilenameHelper(parent, promptString, filename, False);
6202 - return HandleCustomNewFileSB(fileSB, filename, defaultName);
6203 + int resp;
6204 + int *addWrap = (int *)clientData;
6206 + if (XmToggleButtonGetState(w)) {
6207 + resp = DialogF(DF_WARN, w, 2, "Add Wrap",
6208 + "This operation adds permanent line breaks to\n"
6209 + "match the automatic wrapping done by the\n"
6210 + "Continuous Wrap mode Preferences Option.\n\n"
6211 + "*** This Option is Irreversable ***\n\n"
6212 + "Once newlines are inserted, continuous wrapping\n"
6213 + "will no longer work automatically on these lines", "OK",
6214 + "Cancel");
6215 + if (1 == resp) {
6216 + *addWrap = True;
6217 + } else {
6218 + XmToggleButtonSetState(w, False, False);
6219 + *addWrap = False;
6221 + } else {
6222 + *addWrap = False;
6227 -** HandleCustomExistFileSB
6228 +** Callback procedure for File Format toggle buttons. Format is stored
6229 +** in userData field of widget button
6231 +static void setFormatCB(Widget widget, XtPointer clientData, XtPointer callData)
6233 + if (XmToggleButtonGetState(widget)) {
6234 + XtPointer userData;
6235 + XtVaGetValues(widget, XmNuserData, &userData, NULL);
6236 + *((int*) clientData) = (int) userData;
6241 +** handleCustomExistFileSB
6243 ** Manage a customized file selection box for opening existing files.
6244 ** Use this if you want to change the standard file selection dialog
6245 ** from the defaults provided in GetExistingFilename, but still
6246 ** want take advantage of the button processing, help messages, and
6247 @@ -344,23 +698,24 @@ int GetNewFilename(Widget parent, char *
6248 ** Widget existFileSB - your custom file selection box widget id
6249 ** char * filename - a string to receive the selected filename
6250 ** (this string will not be altered if the
6251 ** user pressed the cancel button)
6253 -** Returns: GFN_OK - file was selected and OK button pressed
6254 -** GFN_CANCEL - Cancel button pressed and no returned file
6255 +** Returns: HFSB_OK - file was selected and OK button pressed
6256 +** HFSB_CANCEL - Cancel button pressed and no returned file
6259 -int HandleCustomExistFileSB(Widget existFileSB, char *filename)
6260 +int handleCustomExistFileSB(Widget existFileSB, char *filename)
6262 Boolean done_with_dialog=False; /* ok to destroy dialog flag */
6263 char *fileString; /* C string for file selected */
6264 char *dirString; /* C string for dir of file selected */
6265 XmString cFileString; /* compound string for file selected */
6266 XmString cDir; /* compound directory selected */
6267 XmString cPattern; /* compound filter pattern */
6268 Widget help; /* help window form dialog */
6269 + fsbUserDataStruct* userData;
6270 #if XmVersion < 1002
6271 int i;
6272 #endif
6274 XtAddCallback(existFileSB, XmNokCallback, (XtCallbackProc)existOkCB,
6275 @@ -382,10 +737,17 @@ int HandleCustomExistFileSB(Widget exist
6276 #if XmVersion >= 1002
6277 XtVaSetValues(existFileSB, XmNinitialFocus, XtParent(
6278 XmFileSelectionBoxGetChild(existFileSB, XmDIALOG_LIST)), NULL);
6279 #endif
6280 #endif
6282 + XtVaGetValues(existFileSB, XmNuserData, &userData, NULL);
6283 + /* FIXME: The nice hidden file patch is broken by Nate's non-factoring. */
6284 + userData->cachedDirList = NULL;
6285 + userData->cachedFileList = NULL;
6286 + XtVaSetValues(existFileSB, XmNuserData, userData, NULL);
6288 ManageDialogCenteredOnPointer(existFileSB);
6290 #ifndef SGI_CUSTOM
6291 /* Typing in the directory list is dependent on the list being in the
6292 same form of alphabetical order expected by the character processing
6293 @@ -413,11 +775,11 @@ int HandleCustomExistFileSB(Widget exist
6294 #endif /* SGI_CUSTOM */
6296 while (!done_with_dialog)
6297 XtAppProcessEvent(XtWidgetToApplicationContext(existFileSB), XtIMAll);
6299 - if (SelectResult == GFN_OK) {
6300 + if (SelectResult == HFSB_OK) {
6301 XtVaGetValues(existFileSB, XmNdirSpec, &cFileString, XmNdirectory,
6302 &cDir, XmNpattern, &cPattern, NULL);
6303 /* Undocumented: file selection box widget allocates copies of these
6304 strings on getValues calls. I have risked freeing them to avoid
6305 memory leaks, since I assume other developers have made this same
6306 @@ -457,16 +819,20 @@ int HandleCustomExistFileSB(Widget exist
6307 be necessary as the shell is destroyed automatically when the dialog
6308 is. However, due to a bug in various Lesstif versions, the latter
6309 messes up the grab cascades and leaves new windows without grabs, such
6310 that they appear to be frozen. */
6311 XtDestroyWidget(XtParent(existFileSB));
6313 + freeFileList(userData->cachedDirList);
6314 + freeFileList(userData->cachedFileList);
6316 return SelectResult;
6321 -** HandleCustomNewFileSB
6322 +** handleCustomNewFileSB
6324 ** Manage a customized file selection box for opening new files.
6326 ** Arguments:
6328 @@ -475,23 +841,24 @@ int HandleCustomExistFileSB(Widget exist
6329 ** (this string will not be altered if the
6330 ** user pressed the cancel button)
6331 ** char* defaultName - default name to be pre-entered in filename
6332 ** text field.
6334 -** Returns: GFN_OK - file was selected and OK button pressed
6335 -** GFN_CANCEL - Cancel button pressed and no returned file
6336 +** Returns: HFSB_OK - file was selected and OK button pressed
6337 +** HFSB_CANCEL - Cancel button pressed and no returned file
6340 -int HandleCustomNewFileSB(Widget newFileSB, char *filename, char *defaultName)
6341 +int handleCustomNewFileSB(Widget newFileSB, char *filename, char *defaultName)
6343 Boolean done_with_dialog=False; /* ok to destroy dialog flag */
6344 Widget help; /* help window form dialog */
6345 XmString cFileString; /* compound string for file selected */
6346 XmString cDir; /* compound directory selected */
6347 XmString cPattern; /* compound filter pattern */
6348 char *fileString; /* C string for file selected */
6349 char *dirString; /* C string for dir of file selected */
6350 + fsbUserDataStruct* userData;
6351 #if XmVersion < 1002
6352 int i;
6353 #endif
6355 XtAddCallback(newFileSB, XmNokCallback, (XtCallbackProc)newFileOKCB,
6356 @@ -520,10 +887,16 @@ int HandleCustomNewFileSB(Widget newFile
6357 if ( finder != NULL )
6358 XtVaSetValues(newFileSB, XmNinitialFocus, finder, NULL);
6360 #endif
6361 #endif
6363 + XtVaGetValues(newFileSB, XmNuserData, &userData, NULL);
6364 + userData->cachedDirList = NULL;
6365 + userData->cachedFileList = NULL;
6366 + XtVaSetValues(newFileSB, XmNuserData, userData, NULL);
6368 ManageDialogCenteredOnPointer(newFileSB);
6370 #ifndef SGI_CUSTOM
6371 #if XmVersion < 1002
6372 /* To give filename text initial focus, revoke default button status for
6373 @@ -571,11 +944,11 @@ int HandleCustomNewFileSB(Widget newFile
6376 while (!done_with_dialog)
6377 XtAppProcessEvent (XtWidgetToApplicationContext(newFileSB), XtIMAll);
6379 - if (SelectResult == GFN_OK) {
6380 + if (SelectResult == HFSB_OK) {
6381 /* See note in existing file routines about freeing the values
6382 obtained in the following call */
6383 XtVaGetValues(newFileSB, XmNdirSpec, &cFileString, XmNdirectory,
6384 &cDir, XmNpattern, &cPattern, NULL);
6385 if (DefaultDirectory != NULL) XmStringFree(DefaultDirectory);
6386 @@ -603,10 +976,14 @@ int HandleCustomNewFileSB(Widget newFile
6388 XmStringFree(cFileString);
6389 XtFree(fileString);
6391 XtDestroyWidget(newFileSB);
6393 + freeFileList(userData->cachedDirList);
6394 + freeFileList(userData->cachedFileList);
6396 return SelectResult;
6400 ** Return current default directory used by GetExistingFilename.
6401 @@ -663,11 +1040,11 @@ void SetFileDialogDefaultPattern(char *p
6402 XmStringFree(DefaultPattern);
6403 DefaultPattern = pattern==NULL ? NULL : XmStringCreateSimple(pattern);
6407 -** Turn on or off the text fiend in the GetExistingFilename file selection
6408 +** Turn on or off the text field in the GetExistingFilename file selection
6409 ** box, where users can enter the filename by typing. This is redundant
6410 ** with typing in the list, and leads users who are new to nedit to miss
6411 ** the more powerful feature in favor of changing the focus and typing
6412 ** in the text field.
6414 @@ -791,11 +1168,11 @@ static void newFileOKCB(Widget w, Boolea
6415 int length; /* length of file name */
6416 int response; /* response to dialog */
6417 struct stat buf; /* status from fstat */
6419 XmStringGetLtoR(call_data->value, XmSTRING_DEFAULT_CHARSET, &filename);
6420 - SelectResult = GFN_OK;
6421 + SelectResult = HFSB_OK;
6422 length = strlen(filename);
6423 if (length == 0 || filename[length-1] == '/') {
6424 doErrorDialog("Please supply a name for the file", NULL);
6425 XtFree(filename);
6426 return;
6427 @@ -842,11 +1219,11 @@ static void newFileOKCB(Widget w, Boolea
6431 static void newFileCancelCB(Widget w, Boolean *client_data, caddr_t call_data)
6433 - SelectResult = GFN_CANCEL;
6434 + SelectResult = HFSB_CANCEL;
6435 *client_data = True;
6438 static void newHelpCB(Widget w, Widget helpPanel, caddr_t call_data)
6440 @@ -859,11 +1236,11 @@ static void existOkCB(Widget w, Boolean
6441 char *filename; /* name of chosen file */
6442 int fd; /* file descriptor */
6443 int length; /* length of file name */
6445 XmStringGetLtoR(call_data->value, XmSTRING_DEFAULT_CHARSET, &filename);
6446 - SelectResult = GFN_OK;
6447 + SelectResult = HFSB_OK;
6448 length = strlen(filename);
6449 if (length == 0 || filename[length-1] == '/') {
6450 doErrorDialog("Please select a file to open", NULL);
6451 XtFree(filename);
6452 return;
6453 @@ -879,11 +1256,11 @@ static void existOkCB(Widget w, Boolean
6457 static void existCancelCB(Widget w, Boolean * client_data, caddr_t call_data)
6459 - SelectResult = GFN_CANCEL;
6460 + SelectResult = HFSB_CANCEL;
6461 *client_data = True; /* done with dialog */
6464 static void yesNoOKCB(Widget w, caddr_t client_data, caddr_t call_data)
6466 @@ -1066,40 +1443,115 @@ static void listCharEH(Widget w, XtPoint
6467 ** and should be removed. These routines also leak memory like a seive,
6468 ** because Motif's inconsistent treatment of memory in list widgets does
6469 ** not allow us to free lists that we pass in, and most Motif versions
6470 ** don't clean it up properly.
6472 -static void replacementDirSearchProc(Widget w, XtPointer searchData)
6474 +static int restorePreviousList(Widget list, char** prevList)
6476 - Boolean updated;
6478 + int count = 0, i;
6480 + while (prevList[count]) {
6481 + ++count;
6483 + XmListDeleteAllItems(list);
6485 + for (i = 0; i < count; ++i) {
6486 + XmString s;
6487 + XmListAddItem(list, s = XmStringCreateSimple(prevList[i]), i + 1);
6488 + XtFree(prevList[i]);
6489 + XmStringFree(s);
6491 + XtFree((char*) prevList);
6492 + return count;
6495 +static int saveCurrentList(Widget list, char*** saveList)
6497 + XmString *items;
6498 + int nItems, i;
6500 + XtVaGetValues(list, XmNitems, &items, XmNitemCount, &nItems, NULL);
6501 + *saveList = (char**) XtMalloc(sizeof(char*) * (nItems + 1));
6503 + for (i = 0; i < nItems; ++i) {
6504 + char* s;
6505 + XmStringGetLtoR(items[i], XmSTRING_DEFAULT_CHARSET, &s);
6506 + (*saveList)[i] = s;
6509 + (*saveList)[nItems] = 0;
6510 + return nItems;
6513 +static void replacementDirSearchProc(Widget fileSB, XtPointer searchData)
6515 + int fileCount, newFileCount;
6516 + fsbUserDataStruct* userData;
6518 + XtVaGetValues(fileSB, XmNuserData, &userData, NULL);
6520 + if (userData->cachedDirList) {
6521 + restorePreviousList(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST),
6522 + userData->cachedDirList);
6523 + userData->cachedDirList = NULL;
6526 /* Call the original search procedure to do the actual search */
6527 - (*OrigDirSearchProc)(w, searchData);
6528 - /* Refreshing a list clears the keystroke history, even if no update. */
6529 + (*OrigDirSearchProc)(fileSB, searchData);
6530 nKeystrokes = 0;
6531 - XtVaGetValues(w, XmNlistUpdated, &updated, NULL);
6532 - if (!updated)
6533 - return;
6536 + fileCount = saveCurrentList(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST),
6537 + &userData->cachedDirList);
6539 + if (userData->showHidden)
6541 + /* Remove '.' entry */
6542 + if (removeDotEntry(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST))) {
6543 + newFileCount = fileCount -1;
6544 + } else {
6545 + newFileCount = fileCount;
6548 + } else {
6549 + /* Remove hidden files from list */
6550 + removeHiddenFiles(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST));
6552 + XtVaSetValues(fileSB, XmNlistUpdated, True, NULL);
6554 /* Sort the items in the list */
6555 - sortWidgetList(XmFileSelectionBoxGetChild(w, XmDIALOG_DIR_LIST));
6556 + sortWidgetList(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_DIR_LIST));
6559 -static void replacementFileSearchProc(Widget w, XtPointer searchData)
6560 +static void replacementFileSearchProc(Widget fileSB, XtPointer searchData)
6562 - Boolean updated;
6564 + int fileCount;
6565 + fsbUserDataStruct* userData;
6567 + XtVaGetValues(fileSB, XmNuserData, &userData, NULL);
6569 + if (userData->cachedFileList) {
6570 + restorePreviousList(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST),
6571 + userData->cachedFileList);
6572 + userData->cachedFileList = NULL;
6575 /* Call the original search procedure to do the actual search */
6576 - (*OrigFileSearchProc)(w, searchData);
6577 - /* Refreshing a list clears the keystroke history, even if no update. */
6578 + (*OrigFileSearchProc)(fileSB, searchData);
6579 nKeystrokes = 0;
6580 - XtVaGetValues(w, XmNlistUpdated, &updated, NULL);
6581 - if (!updated)
6582 - return;
6585 + fileCount = saveCurrentList(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST),
6586 + &userData->cachedFileList);
6588 + if (!userData->showHidden) {
6589 + /* Remove hidden files from list */
6590 + removeHiddenFiles(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST));
6592 + XtVaSetValues(fileSB, XmNlistUpdated, True, NULL);
6594 /* Sort the items in the list */
6595 - sortWidgetList(XmFileSelectionBoxGetChild(w, XmDIALOG_LIST));
6596 + sortWidgetList(XmFileSelectionBoxGetChild(fileSB, XmDIALOG_LIST));
6600 ** Sort the items in a list widget "listWidget"
6602 @@ -1132,5 +1584,160 @@ static int compareXmStrings(const void *
6603 result = strcmp(s1, s2);
6604 XtFree(s1);
6605 XtFree(s2);
6606 return result;
6610 +** Removes the '.' entry from a listWidget
6612 +** Preconditions:
6613 +** listWidget is an XmList containing filenames
6615 +** Postcondition:
6616 +** first dotEntry in listWidget is removed
6618 +static Boolean removeDotEntry(Widget listWidget)
6620 + /* Items currently in the listWidget */
6621 + XmString* items;
6622 + int nItems;
6624 + int i;
6626 + /* read values in List into array. */
6627 + XtVaGetValues(listWidget,
6628 + XmNitems, &items,
6629 + XmNitemCount, &nItems,
6630 + NULL);
6632 + /* Traverse over items; for every item, check whether it's the dotfile;
6633 + if yes, delete it and return True. */
6634 + for (i = 0; i < nItems; i++) {
6635 + /* C string of current list item */
6636 + char* filename;
6638 + /* basename of current list item */
6639 + char basename[MAXPATHLEN + 1];
6641 + /* Convert Motif compound string to C string */
6642 + XmStringGetLtoR(items[i], XmSTRING_DEFAULT_CHARSET, &filename);
6644 + /* Get basename from list item */
6645 + ParseFilename(filename, basename, NULL);
6647 + /* Free C string, allocated by XmStringGetLtoR(). */
6648 + XtFree(filename);
6650 + /* if this is the dotEntry... */
6651 + if (0 == strcmp(basename, ".")) {
6652 + /* ...delete it and break. */
6653 + XmListDeletePos(listWidget, i + 1);
6654 + return True;
6658 + return False;
6662 +** Removes hidden files from an XmList. Hidden files are all list entries
6663 +** which are recognized as such by isHiddenFile().
6665 +** Preconditions:
6666 +** listWidget is an XmList containing filenames
6667 +** 'int isHiddenFile(const char* fullname)' exists and works.
6669 +** Postcondition:
6670 +** Hidden files in listWidget are removed
6672 +** Returns
6673 +** number of hidden files removed
6675 +static unsigned removeHiddenFiles(Widget listWidget)
6677 + /* Items currently in the listWidget */
6678 + XmString* items;
6679 + int nItems;
6681 + /* Array holding list positions of hidden files. It is allocated based
6682 + on the current number of items in the List. */
6683 + int* hiddenFilePositions;
6685 + /* Number of hidden files found */
6686 + unsigned hiddenFileCount = 0;
6688 + int i;
6690 + /* read values in List into array. */
6691 + XtVaGetValues(listWidget, XmNitems, &items, XmNitemCount, &nItems, NULL);
6693 + /* Allocate array based on number of items in List. */
6694 + hiddenFilePositions = (int*) XtMalloc(sizeof(int*) * nItems);
6696 + /* Traverse over items; for every item, check whether it's a hidden file;
6697 + if yes, put it in hiddenFilePositions[]. */
6698 + for (i = 0; i < nItems; i++) {
6699 + char* filename;
6700 + XmStringGetLtoR(items[i], XmSTRING_DEFAULT_CHARSET, &filename);
6701 + if (isHiddenFile(filename)) {
6702 + /* Add one because XmListDeletePositions expects values > 0. */
6703 + hiddenFilePositions[hiddenFileCount++] = i + 1;
6705 + XtFree(filename);
6708 + /* Do the removal. */
6709 + XmListDeletePositions(listWidget, hiddenFilePositions, hiddenFileCount);
6711 + /* Free array of positions. */
6712 + XtFree((char*) hiddenFilePositions);
6714 + return hiddenFileCount;
6718 +** Checks whether fullname is a dotfile, ie. starts with a '.'
6720 +** Preconditions:
6721 +** fullname < MAXPATHLEN
6722 +** 'void ParseFilename(fullname, filename, NULL)' exists and works
6724 +** Postcondition:
6725 +** Returns False for '..' and non-dotfiles, True for other dotfiles.
6727 +static int isHiddenFile(const char* fullname)
6729 + /* array to hold basename */
6730 + char basename[MAXPATHLEN + 1];
6732 + /* Extract basename from full filename */
6733 + ParseFilename(fullname, basename, NULL);
6735 + if (0 == strcmp(basename, "..")) {
6736 + /* Return False for parent directory */
6737 + return False;
6738 + } else {
6739 + /* Return True for dotfiles, False for other files */
6740 + return (basename[0] == '.');
6744 +static void freeFileList(char** list)
6746 + int count = 0;
6747 + int i;
6749 + if (!list) {
6750 + return;
6753 + while (list[count]) {
6754 + ++count;
6757 + for (i = 0; i < count; i++) {
6758 + XtFree(list[i]);
6761 + XtFree((char*) list);
6763 diff --quilt old/util/getfiles.h new/util/getfiles.h
6764 --- old/util/getfiles.h
6765 +++ new/util/getfiles.h
6766 @@ -26,22 +26,55 @@
6767 *******************************************************************************/
6769 #ifndef NEDIT_GETFILES_H_INCLUDED
6770 #define NEDIT_GETFILES_H_INCLUDED
6772 +#include <sys/param.h>
6774 #include <X11/Intrinsic.h>
6776 -#define GFN_OK 1 /* Get Filename OK constant */
6777 -#define GFN_CANCEL 2 /* Get Filename Cancel constant */
6779 +** The interface got smaller on functions and bigger on parameters. It's still
6780 +** a big too large for my tastes, but that's what you get.
6782 +typedef struct {
6783 + /* GUI customization */
6784 + String dialogTitle;
6785 + Boolean showHidden;
6787 + Boolean fileExists;
6788 + /* Usually only used for potentially unexisting files. */
6789 + String textfieldLabel; /* only set on new file || GetPrefStdOpenDialog() */
6790 + Boolean haveFormatButtons; /* only makes sense for new files */
6791 + String defaultName;
6793 + /* document details */
6794 + int fileFormat;
6795 + Boolean isContWrapped;
6797 + /* GUI handling */
6798 + Widget parentShell;
6799 +} gfbdParams;
6801 +enum gfdbResult {GFDB_OK, GFDB_CANCEL, GFDB_ERROR};
6802 +typedef struct {
6803 + int status;
6804 + char payload[MAXPATHLEN + 1]; /* Usually carries the filename */
6805 + Boolean addWrap;
6806 + int fileFormat;
6807 +} gfbdValue;
6809 -int GetExistingFilename(Widget parent, char *promptString, char *filename);
6810 -int GetNewFilename(Widget parent, char *promptString, char *filename,
6811 - char *defaultName);
6812 -int HandleCustomExistFileSB(Widget existFileSB, char *filename);
6813 -int HandleCustomNewFileSB(Widget newFileSB, char *filename, char *defaultName);
6814 char *GetFileDialogDefaultDirectory(void);
6815 char *GetFileDialogDefaultPattern(void);
6816 void SetFileDialogDefaultDirectory(char *dir);
6817 void SetFileDialogDefaultPattern(char *pattern);
6818 void SetGetEFTextFieldRemoval(int state);
6819 +gfbdValue* GetFilenameByDialog(const gfbdParams params);
6821 +typedef struct
6823 + Bool showHidden;
6824 + char** cachedDirList;
6825 + char** cachedFileList;
6826 +} fsbUserDataStruct;
6828 #endif /* NEDIT_GETFILES_H_INCLUDED */
6829 diff --quilt old/util/prefFile.c new/util/prefFile.c
6830 --- old/util/prefFile.c
6831 +++ new/util/prefFile.c
6832 @@ -6,11 +6,11 @@ static const char CVSID[] = "$Id: prefFi
6833 * Copyright (C) 1999 Mark Edel *
6835 * This is free software; you can redistribute it and/or modify it under the *
6836 * terms of the GNU General Public License as published by the Free Software *
6837 * Foundation; either version 2 of the License, or (at your option) any later *
6838 -* version. In addition, you may distribute version of this program linked to *
6839 +* version. In addition, you may distribute versions of this program linked to *
6840 * Motif or Open Motif. See README for details. *
6842 * This software is distributed in the hope that it will be useful, but WITHOUT *
6843 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
6844 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
6845 @@ -302,11 +302,11 @@ int SavePreferences(Display *display, co
6848 static int stringToPref(const char *string, PrefDescripRec *rsrcDescrip)
6850 int i;
6851 - char *cleanStr, *endPtr, **enumStrings;
6852 + char *cleanStr, *endPtr, **enumStrings, *cleanEnumStr;
6854 switch (rsrcDescrip->dataType) {
6855 case PREF_INT:
6856 cleanStr = removeWhiteSpace(string);
6857 *(int *)rsrcDescrip->valueAddr =
6858 @@ -338,22 +338,25 @@ static int stringToPref(const char *stri
6860 XtFree(cleanStr);
6861 *(int *)rsrcDescrip->valueAddr = False;
6862 return False;
6863 case PREF_ENUM:
6864 - cleanStr = removeWhiteSpace(string);
6865 - enumStrings = (char **)rsrcDescrip->arg;
6866 - for (i=0; enumStrings[i]!=NULL; i++) {
6867 - if (!strcmp(enumStrings[i], cleanStr)) {
6868 - *(int *)rsrcDescrip->valueAddr = i;
6869 - XtFree(cleanStr);
6870 - return True;
6873 - XtFree(cleanStr);
6874 - *(int *)rsrcDescrip->valueAddr = 0;
6875 - return False;
6876 + cleanStr = removeWhiteSpace(string);
6877 + enumStrings = (char **)rsrcDescrip->arg;
6878 + for (i=0; enumStrings[i]!=NULL; i++) {
6879 + cleanEnumStr = removeWhiteSpace(enumStrings[i]);
6880 + if (!strcmp(cleanEnumStr, cleanStr)) {
6881 + *(int *)rsrcDescrip->valueAddr = i;
6882 + XtFree(cleanStr);
6883 + XtFree(cleanEnumStr);
6884 + return True;
6886 + XtFree(cleanEnumStr);
6888 + XtFree(cleanStr);
6889 + *(int *)rsrcDescrip->valueAddr = 0;
6890 + return False;
6891 case PREF_STRING:
6892 if ((int)strlen(string) >= (int)rsrcDescrip->arg)
6893 return False;
6894 strncpy(rsrcDescrip->valueAddr, string, (int)rsrcDescrip->arg);
6895 return True;
6896 diff --quilt old/util/printUtils.c new/util/printUtils.c
6897 --- old/util/printUtils.c
6898 +++ new/util/printUtils.c
6899 @@ -6,11 +6,11 @@ static const char CVSID[] = "$Id: printU
6900 * Copyright (C) 1999 Mark Edel *
6902 * This is free software; you can redistribute it and/or modify it under the *
6903 * terms of the GNU General Public License as published by the Free Software *
6904 * Foundation; either version 2 of the License, or (at your option) any later *
6905 -* version. In addition, you may distribute version of this program linked to *
6906 +* version. In addition, you may distribute versions of this program linked to *
6907 * Motif or Open Motif. See README for details. *
6909 * This software is distributed in the hope that it will be useful, but WITHOUT *
6910 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
6911 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
6912 @@ -324,10 +324,12 @@ static Widget createForm(Widget parent)
6913 argcnt++;
6914 XtSetArg(args[argcnt], XmNdialogTitle, (st0=XmStringCreateLtoR(
6915 "Print", XmSTRING_DEFAULT_CHARSET))); argcnt++;
6916 XtSetArg(args[argcnt], XmNautoUnmanage, False); argcnt++;
6917 form = CreateFormDialog(parent, "printForm", args, argcnt);
6919 + /* Why is this not part of the arg vector? */
6920 XtVaSetValues(form, XmNshadowThickness, 0, NULL);
6922 XmStringFree( st0 );
6924 /*********************** LABEL 1 and TEXT BOX 1 *********************/