1 /********************************************************************************
2 *                                                                               *
3 *                     T h e   A d i e   T e x t   E d i t o r                   *
4 *                                                                               *
5 *********************************************************************************
6 * Copyright (C) 1998,2021 by Jeroen van der Zijp.   All Rights Reserved.        *
7 *********************************************************************************
8 * This program is free software: you can redistribute it and/or modify          *
9 * it under the terms of the GNU General Public License as published by          *
10 * the Free Software Foundation, either version 3 of the License, or             *
11 * (at your option) any later version.                                           *
12 *                                                                               *
13 * This program is distributed in the hope that it will be useful,               *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of                *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                 *
16 * GNU General Public License for more details.                                  *
17 *                                                                               *
18 * You should have received a copy of the GNU General Public License             *
19 * along with this program.  If not, see <http://www.gnu.org/licenses/>.         *
20 ********************************************************************************/
21 #include "fx.h"
22 #include "fxkeys.h"
23 #include "FX88591Codec.h"
24 #include "FXCP1252Codec.h"
25 #include "FXUTF16Codec.h"
26 #include "HelpWindow.h"
27 #include "Preferences.h"
28 #include "Commands.h"
29 #include "Modeline.h"
30 #include "Syntax.h"
31 #include "TextWindow.h"
32 #include "Adie.h"
33 #include "FindInFiles.h"
34 #include "ShellCommand.h"
35 #include "icons.h"
36 
37 
38 /*
39   Note:
40   - Block select (and block operations).
41   - C tags support.
42   - Each style has optional parent; colors with value FXRGBA(0,0,0,0) are
43     inherited from the parent; this way, sub-styles are possible.
44   - If there is text selected, ctrl-H goes to the next occurrence.  If there
45     is nothing selected, ctrl-H would go to the previous search pattern, similar
46     to the way ctrl-G works in nedit.
47   - Have an option to beep when the search wraps back to the top of the file.
48   - When entire lines are highlighted through triple click and then dragged, a
49     drop at the start of the destination line would seem more natural.
50   - A more serious problem occurs when you undo a drag and drop.  If you undo,
51     (using ctrl-Z for example), the paste is reversed, but not the cut.  You have
52     to hit undo again to reverse the cut.  It would be far more natural to have
53     the "combination" type operations, such as a move, (cut then paste), be
54     somehow recorded as a single operation in the undo system.
55   - Ctrl-B does not seem to be used for anything now.  Could we use this for the
56     block select.  The shift-alt-{ does not flow from my fingers easily.  Just a
57     preference...
58   - The C++ comment/uncomment of selected lines would be very useful.  I didn't
59     realize how much I used it until it wasn't there.
60   - Would be nice if we could remember not only bookmarks, but also window
61     size/position based on file name (see idea about sessions below).
62   - Close last window just saves text, then starts new document in last window;
63     in other words, only quit will terminate app.
64   - Maybe FXText should have its own accelerator table so that key bindings
65     may be changed.
66   - Would be nice to save as HTML.
67   - Sessions. When reloading session, restore all windows (& positions)
68     that were open last time when in that session.
69     Info of sessions is in registry
70   - Command line option --sesssion <name> to open session instead of single
71     file.
72   - Master syntax rule should be explicitly created.  Simplifies parser.
73   - Master syntax rule NOT style index 0.  So you can set normal colors
74     on a per-language basis...
75   - Need option for tabbed interface.
76   - Ability to open multiple files at once in open-panel.
77   - Need default set of styles built-in to code, we can now parse this
78     due to new SyntaxParser being able to parse everything from a big
79     string!
80   - Some way to inherit style attributes, and a way to edit them.
81   - Perhaps change registry representation of style colors.
82   - We can (temporarily) colorize result of find/replace search pattern,
83     simply by writing the style buffer with some value.  This would
84     require a small tweak: add one extra style entry at the end for
85     this purpose, use only temporarily (save old style buffer temporarily).
86   - For this, we should really remove search stuff from FXText widget
87     proper.
88   - Option to read/write BOM at start when load/save from disk.
89   - Comment/uncomment regex in Syntax object.  This would make this
90     language-independent. (1) snap selection, (2) execute regex, (3)
91     replace selection with result.
92   - When making new window (i.e. no file), initialize directory part
93     of the untitled file to that of the current text window.
94 */
95 
96 #define CLOCKTIMER      1000000000      // Blink rate for corner clock
97 #define RESTYLEJUMP     80              // Restyling back-off
98 #define MAXFILESIZE     1000000000      // Limit files to this when loading
99 
100 /*******************************************************************************/
101 
102 // Section key
103 const FXchar sectionKey[]="ISearch";
104 
105 // String keys
106 static const FXchar skey[20][3]={
107   "SA","SB","SC","SD","SE","SF","SG","SH","SI","SJ",
108   "SK","SL","SM","SN","SO","SP","SQ","SR","SS","ST"
109   };
110 
111 // Mode keys
112 static const FXchar mkey[20][3]={
113   "MA","MB","MC","MD","ME","MF","MG","MH","MI","MJ",
114   "MK","ML","MM","MN","MO","MP","MQ","MR","MS","MT"
115   };
116 
117 // Map
118 FXDEFMAP(TextWindow) TextWindowMap[]={
119   FXMAPFUNC(SEL_UPDATE,0,TextWindow::onUpdate),
120   FXMAPFUNC(SEL_FOCUSIN,0,TextWindow::onFocusIn),
121   FXMAPFUNC(SEL_TIMEOUT,TextWindow::ID_CLOCKTIME,TextWindow::onClock),
122   FXMAPFUNC(SEL_FOCUSIN,TextWindow::ID_TEXT,TextWindow::onTextFocus),
123   FXMAPFUNC(SEL_INSERTED,TextWindow::ID_TEXT,TextWindow::onTextInserted),
124   FXMAPFUNC(SEL_REPLACED,TextWindow::ID_TEXT,TextWindow::onTextReplaced),
125   FXMAPFUNC(SEL_DELETED,TextWindow::ID_TEXT,TextWindow::onTextDeleted),
126   FXMAPFUNC(SEL_DND_DROP,TextWindow::ID_TEXT,TextWindow::onTextDNDDrop),
127   FXMAPFUNC(SEL_DND_MOTION,TextWindow::ID_TEXT,TextWindow::onTextDNDMotion),
128   FXMAPFUNC(SEL_QUERY_TIP,TextWindow::ID_TEXT,TextWindow::onQueryTextTip),
129   FXMAPFUNC(SEL_RIGHTBUTTONRELEASE,TextWindow::ID_TEXT,TextWindow::onTextRightMouse),
130 
131   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_ABOUT,TextWindow::onCmdAbout),
132   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_HELP,TextWindow::onCmdHelp),
133   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_NEW,TextWindow::onCmdNew),
134   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_OPEN,TextWindow::onCmdOpen),
135   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_OPEN_SELECTED,TextWindow::onCmdOpenSelected),
136   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_OPEN_TREE,TextWindow::onCmdOpenTree),
137   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_OPEN_RECENT,TextWindow::onCmdOpenRecent),
138   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SWITCH,TextWindow::onCmdSwitch),
139   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_REOPEN,TextWindow::onCmdReopen),
140   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_REOPEN,TextWindow::onUpdReopen),
141   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SAVE,TextWindow::onCmdSave),
142   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_SAVE,TextWindow::onUpdSave),
143   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SAVEAS,TextWindow::onCmdSaveAs),
144   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SAVETO,TextWindow::onCmdSaveTo),
145   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_REPLACE_FILE,TextWindow::onUpdIsEditable),
146   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_REPLACE_FILE,TextWindow::onCmdReplaceFile),
147   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_EXTRACT_FILE,TextWindow::onUpdHasSelection),
148   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_EXTRACT_FILE,TextWindow::onCmdExtractFile),
149 
150   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_FONT,TextWindow::onCmdFont),
151   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_PRINT,TextWindow::onCmdPrint),
152 
153   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_TEXT_BACK,TextWindow::onCmdTextBackColor),
154   FXMAPFUNC(SEL_CHANGED,TextWindow::ID_TEXT_BACK,TextWindow::onCmdTextBackColor),
155   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_TEXT_BACK,TextWindow::onUpdTextBackColor),
156   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_TEXT_FORE,TextWindow::onCmdTextForeColor),
157   FXMAPFUNC(SEL_CHANGED,TextWindow::ID_TEXT_FORE,TextWindow::onCmdTextForeColor),
158   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_TEXT_FORE,TextWindow::onUpdTextForeColor),
159   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_TEXT_SELBACK,TextWindow::onCmdTextSelBackColor),
160   FXMAPFUNC(SEL_CHANGED,TextWindow::ID_TEXT_SELBACK,TextWindow::onCmdTextSelBackColor),
161   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_TEXT_SELBACK,TextWindow::onUpdTextSelBackColor),
162   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_TEXT_SELFORE,TextWindow::onCmdTextSelForeColor),
163   FXMAPFUNC(SEL_CHANGED,TextWindow::ID_TEXT_SELFORE,TextWindow::onCmdTextSelForeColor),
164   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_TEXT_SELFORE,TextWindow::onUpdTextSelForeColor),
165   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_TEXT_HILITEBACK,TextWindow::onCmdTextHiliteBackColor),
166   FXMAPFUNC(SEL_CHANGED,TextWindow::ID_TEXT_HILITEBACK,TextWindow::onCmdTextHiliteBackColor),
167   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_TEXT_HILITEBACK,TextWindow::onUpdTextHiliteBackColor),
168   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_TEXT_HILITEFORE,TextWindow::onCmdTextHiliteForeColor),
169   FXMAPFUNC(SEL_CHANGED,TextWindow::ID_TEXT_HILITEFORE,TextWindow::onCmdTextHiliteForeColor),
170   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_TEXT_HILITEFORE,TextWindow::onUpdTextHiliteForeColor),
171   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_TEXT_CURSOR,TextWindow::onCmdTextCursorColor),
172   FXMAPFUNC(SEL_CHANGED,TextWindow::ID_TEXT_CURSOR,TextWindow::onCmdTextCursorColor),
173   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_TEXT_CURSOR,TextWindow::onUpdTextCursorColor),
174   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_TEXT_ACTIVEBACK,TextWindow::onCmdTextActBackColor),
175   FXMAPFUNC(SEL_CHANGED,TextWindow::ID_TEXT_ACTIVEBACK,TextWindow::onCmdTextActBackColor),
176   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_TEXT_ACTIVEBACK,TextWindow::onUpdTextActBackColor),
177   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_TEXT_NUMBACK,TextWindow::onCmdTextBarColor),
178   FXMAPFUNC(SEL_CHANGED,TextWindow::ID_TEXT_NUMBACK,TextWindow::onCmdTextBarColor),
179   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_TEXT_NUMBACK,TextWindow::onUpdTextBarColor),
180   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_TEXT_NUMFORE,TextWindow::onCmdTextNumberColor),
181   FXMAPFUNC(SEL_CHANGED,TextWindow::ID_TEXT_NUMFORE,TextWindow::onCmdTextNumberColor),
182   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_TEXT_NUMFORE,TextWindow::onUpdTextNumberColor),
183 
184   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_DIR_BACK,TextWindow::onCmdDirBackColor),
185   FXMAPFUNC(SEL_CHANGED,TextWindow::ID_DIR_BACK,TextWindow::onCmdDirBackColor),
186   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_DIR_BACK,TextWindow::onUpdDirBackColor),
187   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_DIR_FORE,TextWindow::onCmdDirForeColor),
188   FXMAPFUNC(SEL_CHANGED,TextWindow::ID_DIR_FORE,TextWindow::onCmdDirForeColor),
189   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_DIR_FORE,TextWindow::onUpdDirForeColor),
190   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_DIR_SELBACK,TextWindow::onCmdDirSelBackColor),
191   FXMAPFUNC(SEL_CHANGED,TextWindow::ID_DIR_SELBACK,TextWindow::onCmdDirSelBackColor),
192   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_DIR_SELBACK,TextWindow::onUpdDirSelBackColor),
193   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_DIR_SELFORE,TextWindow::onCmdDirSelForeColor),
194   FXMAPFUNC(SEL_CHANGED,TextWindow::ID_DIR_SELFORE,TextWindow::onCmdDirSelForeColor),
195   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_DIR_SELFORE,TextWindow::onUpdDirSelForeColor),
196   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_DIR_LINES,TextWindow::onCmdDirLineColor),
197   FXMAPFUNC(SEL_CHANGED,TextWindow::ID_DIR_LINES,TextWindow::onCmdDirLineColor),
198   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_DIR_LINES,TextWindow::onUpdDirLineColor),
199 
200   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_TOGGLE_WRAP,TextWindow::onUpdWrap),
201   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_TOGGLE_WRAP,TextWindow::onCmdWrap),
202   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_FIXED_WRAP,TextWindow::onUpdWrapFixed),
203   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_FIXED_WRAP,TextWindow::onCmdWrapFixed),
204   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_STRIP_CR,TextWindow::onUpdStripReturns),
205   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_STRIP_CR,TextWindow::onCmdStripReturns),
206   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_STRIP_SP,TextWindow::onUpdStripSpaces),
207   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_STRIP_SP,TextWindow::onCmdStripSpaces),
208   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_APPEND_CR,TextWindow::onUpdAppendCarriageReturn),
209   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_APPEND_CR,TextWindow::onCmdAppendCarriageReturn),
210   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_APPEND_NL,TextWindow::onUpdAppendNewline),
211   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_APPEND_NL,TextWindow::onCmdAppendNewline),
212   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_FILEFILTER,TextWindow::onCmdFilter),
213   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_OVERSTRIKE,TextWindow::onUpdOverstrike),
214   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_READONLY,TextWindow::onUpdReadOnly),
215   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_TABMODE,TextWindow::onUpdTabMode),
216   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_NUM_ROWS,TextWindow::onUpdNumRows),
217   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_PREFERENCES,TextWindow::onCmdPreferences),
218   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_TABCOLUMNS,TextWindow::onCmdTabColumns),
219   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_TABCOLUMNS,TextWindow::onUpdTabColumns),
220   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_DELIMITERS,TextWindow::onCmdDelimiters),
221   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_DELIMITERS,TextWindow::onUpdDelimiters),
222   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_WRAPCOLUMNS,TextWindow::onCmdWrapColumns),
223   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_WRAPCOLUMNS,TextWindow::onUpdWrapColumns),
224   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_MODELINE,TextWindow::onCmdModeline),
225   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_MODELINE,TextWindow::onUpdModeline),
226   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_AUTOINDENT,TextWindow::onCmdAutoIndent),
227   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_AUTOINDENT,TextWindow::onUpdAutoIndent),
228   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_INSERTTABS,TextWindow::onCmdInsertTabs),
229   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_INSERTTABS,TextWindow::onUpdInsertTabs),
230   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_BRACEMATCH,TextWindow::onCmdBraceMatch),
231   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_BRACEMATCH,TextWindow::onUpdBraceMatch),
232   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_BRACEMATCHTIME,TextWindow::onCmdBraceMatchTime),
233   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_BRACEMATCHTIME,TextWindow::onUpdBraceMatchTime),
234   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_BRACEMATCHSTAY,TextWindow::onCmdBraceMatchStay),
235   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_BRACEMATCHSTAY,TextWindow::onUpdBraceMatchStay),
236   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_WHEELADJUST,TextWindow::onUpdWheelAdjust),
237   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_WHEELADJUST,TextWindow::onCmdWheelAdjust),
238   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_SAVEVIEWS,TextWindow::onUpdSaveViews),
239   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SAVEVIEWS,TextWindow::onCmdSaveViews),
240   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_SHOWACTIVE,TextWindow::onUpdShowActive),
241   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SHOWACTIVE,TextWindow::onCmdShowActive),
242   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_TEXT_LINENUMS,TextWindow::onUpdLineNumbers),
243   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_TEXT_LINENUMS,TextWindow::onCmdLineNumbers),
244   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_WARNCHANGED,TextWindow::onUpdWarnChanged),
245   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_WARNCHANGED,TextWindow::onCmdWarnChanged),
246   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_TOGGLE_BROWSER,TextWindow::onCmdToggleBrowser),
247   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_TOGGLE_BROWSER,TextWindow::onUpdToggleBrowser),
248   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_TOGGLE_DOTFILES,TextWindow::onCmdToggleHidden),
249   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_TOGGLE_DOTFILES,TextWindow::onUpdToggleHidden),
250   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SEARCHPATHS,TextWindow::onCmdSearchPaths),
251   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_SEARCHPATHS,TextWindow::onUpdSearchPaths),
252   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SAVE_SETTINGS,TextWindow::onCmdSaveSettings),
253   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_FINDFILES,TextWindow::onCmdFindInFiles),
254 
255   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_SET_MARK,TextWindow::onUpdSetMark),
256   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SET_MARK,TextWindow::onCmdSetMark),
257   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_NEXT_MARK,TextWindow::onUpdNextMark),
258   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_NEXT_MARK,TextWindow::onCmdNextMark),
259   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_PREV_MARK,TextWindow::onUpdPrevMark),
260   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_PREV_MARK,TextWindow::onCmdPrevMark),
261   FXMAPFUNCS(SEL_UPDATE,TextWindow::ID_MARK_0,TextWindow::ID_MARK_9,TextWindow::onUpdGotoMark),
262   FXMAPFUNCS(SEL_COMMAND,TextWindow::ID_MARK_0,TextWindow::ID_MARK_9,TextWindow::onCmdGotoMark),
263   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_DEL_MARK,TextWindow::onUpdDelMark),
264   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_DEL_MARK,TextWindow::onCmdDelMark),
265   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_CLEAR_MARKS,TextWindow::onUpdClearMarks),
266   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_CLEAR_MARKS,TextWindow::onCmdClearMarks),
267   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_SAVEMARKS,TextWindow::onUpdSaveMarks),
268   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SAVEMARKS,TextWindow::onCmdSaveMarks),
269 
270   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SHELL_DIALOG,TextWindow::onCmdShellDialog),
271   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_SHELL_DIALOG,TextWindow::onUpdShellDialog),
272   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SHELL_FILTER,TextWindow::onCmdShellFilter),
273   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_SHELL_FILTER,TextWindow::onUpdShellFilter),
274   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SHELL_CANCEL,TextWindow::onCmdShellCancel),
275   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_SHELL_CANCEL,TextWindow::onUpdShellCancel),
276   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SHELL_OUTPUT,TextWindow::onCmdShellOutput),
277   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SHELL_ERROR,TextWindow::onCmdShellError),
278   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SHELL_DONE,TextWindow::onCmdShellDone),
279 
280   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_EXPRESSION,TextWindow::onCmdExpression),
281   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_EXPRESSION,TextWindow::onUpdExpression),
282 
283   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_URL_ENCODE,TextWindow::onCmdURLEncode),
284   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_URL_ENCODE,TextWindow::onUpdURLCoding),
285   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_URL_DECODE,TextWindow::onCmdURLDecode),
286   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_URL_DECODE,TextWindow::onUpdURLCoding),
287 
288   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_GOTO_LINE,TextWindow::onCmdGotoLine),
289   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_GOTO_SELECTED,TextWindow::onCmdGotoSelected),
290 
291   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SEARCH,TextWindow::onCmdSearch),
292   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_REPLACE,TextWindow::onCmdReplace),
293   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_REPLACE,TextWindow::onUpdIsEditable),
294   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SEARCH_SEL_FORW,TextWindow::onCmdSearchSel),
295   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SEARCH_SEL_BACK,TextWindow::onCmdSearchSel),
296   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SEARCH_NXT_FORW,TextWindow::onCmdSearchNext),
297   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SEARCH_NXT_BACK,TextWindow::onCmdSearchNext),
298 
299   FXMAPFUNC(SEL_CHANGED,TextWindow::ID_ISEARCH_TEXT,TextWindow::onChgISearchText),
300   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_ISEARCH_TEXT,TextWindow::onCmdISearchText),
301   FXMAPFUNC(SEL_KEYPRESS,TextWindow::ID_ISEARCH_TEXT,TextWindow::onKeyISearchText),
302   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_ISEARCH_PREV,TextWindow::onCmdISearchPrev),
303   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_ISEARCH_NEXT,TextWindow::onCmdISearchNext),
304   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_ISEARCH_START,TextWindow::onCmdISearchStart),
305   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_ISEARCH_FINISH,TextWindow::onCmdISearchFinish),
306   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_ISEARCH_HIST_UP,TextWindow::onCmdISearchHistUp),
307   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_ISEARCH_HIST_DN,TextWindow::onCmdISearchHistDn),
308 
309   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_ISEARCH_IGNCASE,TextWindow::onUpdISearchCase),
310   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_ISEARCH_IGNCASE,TextWindow::onCmdISearchCase),
311   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_ISEARCH_REVERSE,TextWindow::onUpdISearchDir),
312   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_ISEARCH_REVERSE,TextWindow::onCmdISearchDir),
313   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_ISEARCH_REGEX,TextWindow::onUpdISearchRegex),
314   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_ISEARCH_REGEX,TextWindow::onCmdISearchRegex),
315 
316   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_USE_INITIAL_SIZE,TextWindow::onUpdUseInitialSize),
317   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_USE_INITIAL_SIZE,TextWindow::onCmdUseInitialSize),
318   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SET_INITIAL_SIZE,TextWindow::onCmdSetInitialSize),
319 
320   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_SYNTAX,TextWindow::onUpdSyntax),
321   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_SYNTAX,TextWindow::onCmdSyntax),
322   FXMAPFUNC(SEL_UPDATE,TextWindow::ID_RESTYLE,TextWindow::onUpdRestyle),
323   FXMAPFUNC(SEL_COMMAND,TextWindow::ID_RESTYLE,TextWindow::onCmdRestyle),
324   FXMAPFUNCS(SEL_UPDATE,TextWindow::ID_WINDOW_1,TextWindow::ID_WINDOW_10,TextWindow::onUpdWindow),
325   FXMAPFUNCS(SEL_COMMAND,TextWindow::ID_WINDOW_1,TextWindow::ID_WINDOW_10,TextWindow::onCmdWindow),
326   FXMAPFUNCS(SEL_UPDATE,TextWindow::ID_SYNTAX_FIRST,TextWindow::ID_SYNTAX_LAST,TextWindow::onUpdSyntaxSwitch),
327   FXMAPFUNCS(SEL_COMMAND,TextWindow::ID_SYNTAX_FIRST,TextWindow::ID_SYNTAX_LAST,TextWindow::onCmdSyntaxSwitch),
328 
329   FXMAPFUNCS(SEL_UPDATE,TextWindow::ID_TABSELECT_0,TextWindow::ID_TABSELECT_8,TextWindow::onUpdTabSelect),
330   FXMAPFUNCS(SEL_COMMAND,TextWindow::ID_TABSELECT_0,TextWindow::ID_TABSELECT_8,TextWindow::onCmdTabSelect),
331 
332   FXMAPFUNCS(SEL_COMMAND,TextWindow::ID_STYLE_NORMAL_FG_FIRST,TextWindow::ID_STYLE_NORMAL_FG_LAST,TextWindow::onCmdStyleNormalFG),
333   FXMAPFUNCS(SEL_CHANGED,TextWindow::ID_STYLE_NORMAL_FG_FIRST,TextWindow::ID_STYLE_NORMAL_FG_LAST,TextWindow::onCmdStyleNormalFG),
334   FXMAPFUNCS(SEL_UPDATE,TextWindow::ID_STYLE_NORMAL_FG_FIRST,TextWindow::ID_STYLE_NORMAL_FG_LAST,TextWindow::onUpdStyleNormalFG),
335   FXMAPFUNCS(SEL_COMMAND,TextWindow::ID_STYLE_NORMAL_BG_FIRST,TextWindow::ID_STYLE_NORMAL_BG_LAST,TextWindow::onCmdStyleNormalBG),
336   FXMAPFUNCS(SEL_CHANGED,TextWindow::ID_STYLE_NORMAL_BG_FIRST,TextWindow::ID_STYLE_NORMAL_BG_LAST,TextWindow::onCmdStyleNormalBG),
337   FXMAPFUNCS(SEL_UPDATE,TextWindow::ID_STYLE_NORMAL_BG_FIRST,TextWindow::ID_STYLE_NORMAL_BG_LAST,TextWindow::onUpdStyleNormalBG),
338   FXMAPFUNCS(SEL_COMMAND,TextWindow::ID_STYLE_SELECT_FG_FIRST,TextWindow::ID_STYLE_SELECT_FG_LAST,TextWindow::onCmdStyleSelectFG),
339   FXMAPFUNCS(SEL_CHANGED,TextWindow::ID_STYLE_SELECT_FG_FIRST,TextWindow::ID_STYLE_SELECT_FG_LAST,TextWindow::onCmdStyleSelectFG),
340   FXMAPFUNCS(SEL_UPDATE,TextWindow::ID_STYLE_SELECT_FG_FIRST,TextWindow::ID_STYLE_SELECT_FG_LAST,TextWindow::onUpdStyleSelectFG),
341   FXMAPFUNCS(SEL_COMMAND,TextWindow::ID_STYLE_SELECT_BG_FIRST,TextWindow::ID_STYLE_SELECT_BG_LAST,TextWindow::onCmdStyleSelectBG),
342   FXMAPFUNCS(SEL_CHANGED,TextWindow::ID_STYLE_SELECT_BG_FIRST,TextWindow::ID_STYLE_SELECT_BG_LAST,TextWindow::onCmdStyleSelectBG),
343   FXMAPFUNCS(SEL_UPDATE,TextWindow::ID_STYLE_SELECT_BG_FIRST,TextWindow::ID_STYLE_SELECT_BG_LAST,TextWindow::onUpdStyleSelectBG),
344   FXMAPFUNCS(SEL_COMMAND,TextWindow::ID_STYLE_HILITE_FG_FIRST,TextWindow::ID_STYLE_HILITE_FG_LAST,TextWindow::onCmdStyleHiliteFG),
345   FXMAPFUNCS(SEL_CHANGED,TextWindow::ID_STYLE_HILITE_FG_FIRST,TextWindow::ID_STYLE_HILITE_FG_LAST,TextWindow::onCmdStyleHiliteFG),
346   FXMAPFUNCS(SEL_UPDATE,TextWindow::ID_STYLE_HILITE_FG_FIRST,TextWindow::ID_STYLE_HILITE_FG_LAST,TextWindow::onUpdStyleHiliteFG),
347   FXMAPFUNCS(SEL_COMMAND,TextWindow::ID_STYLE_HILITE_BG_FIRST,TextWindow::ID_STYLE_HILITE_BG_LAST,TextWindow::onCmdStyleHiliteBG),
348   FXMAPFUNCS(SEL_CHANGED,TextWindow::ID_STYLE_HILITE_BG_FIRST,TextWindow::ID_STYLE_HILITE_BG_LAST,TextWindow::onCmdStyleHiliteBG),
349   FXMAPFUNCS(SEL_UPDATE,TextWindow::ID_STYLE_HILITE_BG_FIRST,TextWindow::ID_STYLE_HILITE_BG_LAST,TextWindow::onUpdStyleHiliteBG),
350   FXMAPFUNCS(SEL_COMMAND,TextWindow::ID_STYLE_ACTIVE_BG_FIRST,TextWindow::ID_STYLE_ACTIVE_BG_LAST,TextWindow::onCmdStyleActiveBG),
351   FXMAPFUNCS(SEL_CHANGED,TextWindow::ID_STYLE_ACTIVE_BG_FIRST,TextWindow::ID_STYLE_ACTIVE_BG_LAST,TextWindow::onCmdStyleActiveBG),
352   FXMAPFUNCS(SEL_UPDATE,TextWindow::ID_STYLE_ACTIVE_BG_FIRST,TextWindow::ID_STYLE_ACTIVE_BG_LAST,TextWindow::onUpdStyleActiveBG),
353 
354   FXMAPFUNCS(SEL_COMMAND,TextWindow::ID_STYLE_UNDERLINE_FIRST,TextWindow::ID_STYLE_UNDERLINE_LAST,TextWindow::onCmdStyleUnderline),
355   FXMAPFUNCS(SEL_UPDATE,TextWindow::ID_STYLE_UNDERLINE_FIRST,TextWindow::ID_STYLE_UNDERLINE_LAST,TextWindow::onUpdStyleUnderline),
356   FXMAPFUNCS(SEL_COMMAND,TextWindow::ID_STYLE_STRIKEOUT_FIRST,TextWindow::ID_STYLE_STRIKEOUT_LAST,TextWindow::onCmdStyleStrikeout),
357   FXMAPFUNCS(SEL_UPDATE,TextWindow::ID_STYLE_STRIKEOUT_FIRST,TextWindow::ID_STYLE_STRIKEOUT_LAST,TextWindow::onUpdStyleStrikeout),
358   FXMAPFUNCS(SEL_COMMAND,TextWindow::ID_STYLE_BOLD_FIRST,TextWindow::ID_STYLE_BOLD_LAST,TextWindow::onCmdStyleBold),
359   FXMAPFUNCS(SEL_UPDATE,TextWindow::ID_STYLE_BOLD_FIRST,TextWindow::ID_STYLE_BOLD_LAST,TextWindow::onUpdStyleBold),
360   };
361 
362 
363 // Object implementation
FXIMPLEMENT(TextWindow,FXMainWindow,TextWindowMap,ARRAYNUMBER (TextWindowMap))364 FXIMPLEMENT(TextWindow,FXMainWindow,TextWindowMap,ARRAYNUMBER(TextWindowMap))
365 
366 /*******************************************************************************/
367 
368 // Make some windows
369 TextWindow::TextWindow(Adie* a):FXMainWindow(a,"Adie",NULL,NULL,DECOR_ALL,0,0,850,600,0,0),mrufiles(a){
370 
371   // Add to list of windows
372   getApp()->windowlist.append(this);
373 
374   // Default font
375   font=NULL;
376 
377   // Application icons
378   setIcon(getApp()->bigicon);
379   setMiniIcon(getApp()->smallicon);
380 
381   // Status bar
382   statusbar=new FXStatusBar(this,LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|STATUSBAR_WITH_DRAGCORNER|FRAME_RAISED);
383 
384   // Sites where to dock
385   topdock=new FXDockSite(this,LAYOUT_SIDE_TOP|LAYOUT_FILL_X);
386   bottomdock=new FXDockSite(this,LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X);
387   leftdock=new FXDockSite(this,LAYOUT_SIDE_LEFT|LAYOUT_FILL_Y);
388   rightdock=new FXDockSite(this,LAYOUT_SIDE_RIGHT|LAYOUT_FILL_Y);
389 
390   // Make menu bar
391   dragshell1=new FXToolBarShell(this,FRAME_RAISED);
392   menubar=new FXMenuBar(topdock,dragshell1,LAYOUT_DOCK_NEXT|LAYOUT_SIDE_TOP|LAYOUT_FILL_X|FRAME_RAISED);
393   new FXToolBarGrip(menubar,menubar,FXMenuBar::ID_TOOLBARGRIP,TOOLBARGRIP_DOUBLE);
394 
395   // Tool bar
396   dragshell2=new FXToolBarShell(this,FRAME_RAISED);
397   toolbar=new FXToolBar(topdock,dragshell2,LAYOUT_DOCK_NEXT|LAYOUT_SIDE_TOP|LAYOUT_FILL_X|FRAME_RAISED);
398   new FXToolBarGrip(toolbar,toolbar,FXToolBar::ID_TOOLBARGRIP,TOOLBARGRIP_DOUBLE);
399 
400   // Search bar
401   dragshell3=new FXToolBarShell(this,FRAME_RAISED);
402   searchbar=new FXToolBar(bottomdock,dragshell3,LAYOUT_DOCK_NEXT|LAYOUT_SIDE_TOP|LAYOUT_FILL_X|FRAME_RAISED);
403   searchbar->allowedSides(FXDockBar::ALLOW_HORIZONTAL);
404   new FXToolBarGrip(searchbar,searchbar,FXToolBar::ID_TOOLBARGRIP,TOOLBARGRIP_DOUBLE);
405 
406   // Splitter
407   FXSplitter* splitter=new FXSplitter(this,LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y|SPLITTER_TRACKING);
408 
409   // Sunken border for tree
410   treebox=new FXVerticalFrame(splitter,LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 0,0,0,0);
411 
412   // Make tree
413   FXHorizontalFrame* treeframe=new FXHorizontalFrame(treebox,FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 0,0,0,0);
414   dirlist=new FXDirList(treeframe,this,ID_OPEN_TREE,DIRLIST_SHOWFILES|DIRLIST_NO_OWN_ASSOC|TREELIST_BROWSESELECT|TREELIST_SHOWS_LINES|TREELIST_SHOWS_BOXES|LAYOUT_FILL_X|LAYOUT_FILL_Y);
415   dirlist->setAssociations(getApp()->associations,false);
416   dirlist->setDraggableFiles(false);
417   FXHorizontalFrame* filterframe=new FXHorizontalFrame(treebox,LAYOUT_FILL_X,0,0,0,0, 4,0,0,4);
418   new FXLabel(filterframe,tr("Filter:"),NULL,LAYOUT_CENTER_Y);
419   filter=new FXComboBox(filterframe,25,this,ID_FILEFILTER,COMBOBOX_STATIC|LAYOUT_FILL_X|FRAME_SUNKEN|FRAME_THICK);
420   filter->setNumVisible(4);
421   new FXToggleButton(filterframe,tr("\tShow hidden files\tShow hidden files and directories."),tr("\tHide Hidden Files\tHide hidden files and directories."),getApp()->hiddenicon,getApp()->shownicon,this,ID_TOGGLE_DOTFILES,TOGGLEBUTTON_TOOLBAR|FRAME_RAISED,0,0,0,0, 3,3,3,3);
422 
423   FXSplitter* subsplitter=new FXSplitter(splitter,LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|LAYOUT_FILL_Y|SPLITTER_VERTICAL|SPLITTER_REVERSED|SPLITTER_TRACKING);
424 
425   // Editor frame and text widgets
426   editorframe=new FXHorizontalFrame(subsplitter,FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 0,0,0,0);
427   editor=new FXText(editorframe,this,ID_TEXT,LAYOUT_FILL_X|LAYOUT_FILL_Y);
428   editor->setHiliteMatchTime(2000000000);
429   editor->setBarColumns(6);
430 
431   // Logger frame and logger widget
432   loggerframe=new FXHorizontalFrame(subsplitter,LAYOUT_SIDE_BOTTOM|FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X,0,0,0,0, 0,0,0,0);
433   logger=new FXText(loggerframe,this,ID_LOGGER,LAYOUT_FILL_X|LAYOUT_FILL_Y|TEXT_READONLY);
434   logger->setVisibleRows(6);
435 
436   // Create status bar
437   createStatusbar();
438 
439   // Create menu bar
440   createMenubar();
441 
442   // Create tool bar
443   createToolbar();
444 
445   // Create search bar
446   createSearchbar();
447 
448   // Initialize bookmarks
449   clearBookmarks();
450 
451   // Set status
452   setStatusMessage(tr("Ready."));
453 
454   // Initial setting
455   syntax=NULL;
456 
457   // Recent files
458   mrufiles.setTarget(this);
459   mrufiles.setSelector(ID_OPEN_RECENT);
460 
461   // Initialize file name
462   filename="untitled";
463   filenameset=false;
464   filetime=0;
465 
466   // Initialize other stuff
467   searchpaths="/usr/include";
468   setPatternList("All Files (*)");
469   setCurrentPattern(0);
470   shellCommand=NULL;
471   replaceStart=0;
472   replaceEnd=0;
473   initialwidth=640;
474   initialheight=480;
475   isearchReplace=false;
476   isearchIndex=-1;
477   isearchpos=-1;
478   searchflags=SEARCH_FORWARD|SEARCH_EXACT;
479   searching=false;
480   showsearchbar=false;
481   showlogger=false;
482   initialsize=true;
483   colorize=false;
484   stripcr=true;
485   stripsp=false;
486   appendcr=false;
487   appendnl=true;
488   saveviews=false;
489   savemarks=false;
490   warnchanged=false;
491   modeline=false;
492   undolist.mark();
493   }
494 
495 
496 // Create main menu bar
createMenubar()497 void TextWindow::createMenubar(){
498 
499   // File menu
500   filemenu=new FXMenuPane(this);
501   new FXMenuTitle(menubar,tr("&File"),NULL,filemenu);
502 
503   // File Menu entries
504   new FXMenuCommand(filemenu,tr("&New...\tCtl-N\tCreate new document."),getApp()->newicon,this,ID_NEW);
505   new FXMenuCommand(filemenu,tr("&Open...\tCtl-O\tOpen document file."),getApp()->openicon,this,ID_OPEN);
506   new FXMenuCommand(filemenu,tr("Open Selected...  \tCtl-Y\tOpen highlighted document file."),NULL,this,ID_OPEN_SELECTED);
507   new FXMenuCommand(filemenu,tr("Switch...\t\tSwitch to other file."),NULL,this,ID_SWITCH);
508   new FXMenuCommand(filemenu,tr("&Reopen...\t\tReopen file."),getApp()->reloadicon,this,ID_REOPEN);
509   new FXMenuCommand(filemenu,tr("&Save\tCtl-S\tSave changes to file."),getApp()->saveicon,this,ID_SAVE);
510   new FXMenuCommand(filemenu,tr("Save &As...\tShift-Ctl-S\tSave document under a different file name."),getApp()->saveasicon,this,ID_SAVEAS);
511   new FXMenuCommand(filemenu,tr("Save &To...\tShift-Ctl-T\tSave copy of document to file name."),getApp()->savetoicon,this,ID_SAVETO);
512   new FXMenuCommand(filemenu,tr("&Close\tCtl-W\tClose document."),NULL,this,ID_CLOSE);
513   new FXMenuSeparator(filemenu);
514   new FXMenuCommand(filemenu,tr("Replace by file...\t\tReplace by text from file."),NULL,this,ID_REPLACE_FILE);
515   new FXMenuCommand(filemenu,tr("Extract to file...\t\tExtract text to file."),NULL,this,ID_EXTRACT_FILE);
516   new FXMenuCommand(filemenu,tr("&Print...\tCtl-P\tPrint document."),getApp()->printicon,this,ID_PRINT);
517   new FXMenuCheck(filemenu,tr("&Editable\t\tDocument editable."),editor,FXText::ID_TOGGLE_EDITABLE);
518 
519   // Recent file menu; this automatically hides if there are no files
520   new FXMenuSeparator(filemenu,&mrufiles,FXRecentFiles::ID_ANYFILES);
521   new FXMenuCommand(filemenu,FXString::null,NULL,&mrufiles,FXRecentFiles::ID_FILE_1);
522   new FXMenuCommand(filemenu,FXString::null,NULL,&mrufiles,FXRecentFiles::ID_FILE_2);
523   new FXMenuCommand(filemenu,FXString::null,NULL,&mrufiles,FXRecentFiles::ID_FILE_3);
524   new FXMenuCommand(filemenu,FXString::null,NULL,&mrufiles,FXRecentFiles::ID_FILE_4);
525   new FXMenuCommand(filemenu,FXString::null,NULL,&mrufiles,FXRecentFiles::ID_FILE_5);
526   new FXMenuCommand(filemenu,FXString::null,NULL,&mrufiles,FXRecentFiles::ID_FILE_6);
527   new FXMenuCommand(filemenu,FXString::null,NULL,&mrufiles,FXRecentFiles::ID_FILE_7);
528   new FXMenuCommand(filemenu,FXString::null,NULL,&mrufiles,FXRecentFiles::ID_FILE_8);
529   new FXMenuCommand(filemenu,FXString::null,NULL,&mrufiles,FXRecentFiles::ID_FILE_9);
530   new FXMenuCommand(filemenu,FXString::null,NULL,&mrufiles,FXRecentFiles::ID_FILE_10);
531   new FXMenuCommand(filemenu,tr("&Clear Recent Files"),NULL,&mrufiles,FXRecentFiles::ID_CLEAR);
532   new FXMenuSeparator(filemenu,&mrufiles,FXRecentFiles::ID_ANYFILES);
533   new FXMenuCommand(filemenu,tr("&Quit\tCtl-Q\tQuit program."),getApp()->quiticon,getApp(),Adie::ID_CLOSEALL);
534 
535   // Edit Menu
536   editmenu=new FXMenuPane(this);
537   new FXMenuTitle(menubar,tr("&Edit"),NULL,editmenu);
538 
539   // Edit Menu entries
540   new FXMenuCommand(editmenu,tr("&Undo\tCtl-Z\tUndo last change."),getApp()->undoicon,&undolist,FXUndoList::ID_UNDO);
541   new FXMenuCommand(editmenu,tr("&Redo\tCtl-Shift-Z\tRedo last undo."),getApp()->redoicon,&undolist,FXUndoList::ID_REDO);
542   new FXMenuCommand(editmenu,tr("Undo all\t\tUndo all."),NULL,&undolist,FXUndoList::ID_UNDO_ALL);
543   new FXMenuCommand(editmenu,tr("Redo all\t\tRedo all."),NULL,&undolist,FXUndoList::ID_REDO_ALL);
544   new FXMenuCommand(editmenu,tr("Revert to saved\t\tRevert to saved."),NULL,&undolist,FXUndoList::ID_REVERT);
545   new FXMenuSeparator(editmenu);
546   new FXMenuCommand(editmenu,tr("&Copy\tCtl-C\tCopy selection to clipboard."),getApp()->copyicon,editor,FXText::ID_COPY_SEL);
547   new FXMenuCommand(editmenu,tr("Cu&t\tCtl-X\tCut selection to clipboard."),getApp()->cuticon,editor,FXText::ID_CUT_SEL);
548   new FXMenuCommand(editmenu,tr("&Paste\tCtl-V\tPaste from clipboard."),getApp()->pasteicon,editor,FXText::ID_PASTE_SEL);
549   new FXMenuCommand(editmenu,tr("&Delete\t\tDelete selection."),getApp()->deleteicon,editor,FXText::ID_DELETE_SEL);
550   new FXMenuSeparator(editmenu);
551   new FXMenuCommand(editmenu,tr("Expression\t\tEvaluate selected expression."),NULL,this,ID_EXPRESSION);
552   new FXMenuCommand(editmenu,tr("URL Encode\t\tEncode url special characters."),NULL,this,ID_URL_ENCODE);
553   new FXMenuCommand(editmenu,tr("URL Decode\t\tDecode url special characters."),NULL,this,ID_URL_DECODE);
554   new FXMenuCommand(editmenu,tr("Duplicate Line\tCtl-D\tDuplicate current line."),NULL,editor,FXText::ID_COPY_LINE);
555   new FXMenuCommand(editmenu,tr("Move line up\tCtl-Shift-<\tMove current line up."),NULL,editor,FXText::ID_MOVE_LINE_UP);
556   new FXMenuCommand(editmenu,tr("Move line down\tCtl-Shift->\tMove current line down."),NULL,editor,FXText::ID_MOVE_LINE_DOWN);
557   new FXMenuCommand(editmenu,tr("Lo&wer-case\tCtl-U\tChange to lower case."),getApp()->lowercaseicon,editor,FXText::ID_LOWER_CASE);
558   new FXMenuCommand(editmenu,tr("Upp&er-case\tCtl-Shift-U\tChange to upper case."),getApp()->uppercaseicon,editor,FXText::ID_UPPER_CASE);
559   new FXMenuCommand(editmenu,tr("Clean indent\t\tClean indentation to either all tabs or all spaces."),NULL,editor,FXText::ID_CLEAN_INDENT);
560   new FXMenuCommand(editmenu,tr("Shift left\tCtl-[\tShift text left."),getApp()->shiftlefticon,editor,FXText::ID_SHIFT_LEFT);
561   new FXMenuCommand(editmenu,tr("Shift right\tCtl-]\tShift text right."),getApp()->shiftrighticon,editor,FXText::ID_SHIFT_RIGHT);
562   new FXMenuCommand(editmenu,tr("Shift tab left\tAlt-[\tShift text left one tab position."),getApp()->shiftlefticon,editor,FXText::ID_SHIFT_TABLEFT);
563   new FXMenuCommand(editmenu,tr("Shift tab right\tAlt-]\tShift text right one tab position."),getApp()->shiftrighticon,editor,FXText::ID_SHIFT_TABRIGHT);
564 
565   // These were the old bindings; keeping them for now...
566   getAccelTable()->addAccel("Ctl-9",editor,FXSEL(SEL_COMMAND,FXText::ID_SHIFT_LEFT));
567   getAccelTable()->addAccel("Ctl-0",editor,FXSEL(SEL_COMMAND,FXText::ID_SHIFT_RIGHT));
568 
569   // Goto Menu
570   gotomenu=new FXMenuPane(this);
571   new FXMenuTitle(menubar,tr("&Goto"),NULL,gotomenu);
572 
573   // Goto Menu entries
574   new FXMenuCommand(gotomenu,tr("&Goto...\tCtl-L\tGoto line number."),NULL,this,ID_GOTO_LINE);
575   new FXMenuCommand(gotomenu,tr("Goto selected...\tCtl-E\tGoto selected line number."),NULL,this,ID_GOTO_SELECTED);
576   new FXMenuSeparator(gotomenu);
577   new FXMenuCommand(gotomenu,tr("Goto {..\tShift-Ctl-{\tGoto start of enclosing block."),NULL,editor,FXText::ID_LEFT_BRACE);
578   new FXMenuCommand(gotomenu,tr("Goto ..}\tShift-Ctl-}\tGoto end of enclosing block."),NULL,editor,FXText::ID_RIGHT_BRACE);
579   new FXMenuCommand(gotomenu,tr("Goto (..\tShift-Ctl-(\tGoto start of enclosing expression."),NULL,editor,FXText::ID_LEFT_PAREN);
580   new FXMenuCommand(gotomenu,tr("Goto ..)\tShift-Ctl-)\tGoto end of enclosing expression."),NULL,editor,FXText::ID_RIGHT_PAREN);
581   new FXMenuSeparator(gotomenu);
582   new FXMenuCommand(gotomenu,tr("Goto matching (..)\tCtl-M\tGoto matching brace or parenthesis."),NULL,editor,FXText::ID_GOTO_MATCHING);
583   new FXMenuSeparator(gotomenu);
584   new FXMenuCommand(gotomenu,tr("&Set bookmark\tAlt-B\tSet bookmark at cursor location."),getApp()->bookseticon,this,ID_SET_MARK);
585   new FXMenuCommand(gotomenu,tr("&Next bookmark\tAlt-N\tMove cursor to next bookmark."),getApp()->booknexticon,this,ID_NEXT_MARK);
586   new FXMenuCommand(gotomenu,tr("&Previous bookmark\tAlt-P\tMove cursor to previous bookmark."),getApp()->bookprevicon,this,ID_PREV_MARK);
587   new FXMenuCommand(gotomenu,tr("&Delete bookmark\tAlt-D\tDelete bookmark at cursor."),getApp()->bookdelicon,this,ID_DEL_MARK);
588   new FXMenuCommand(gotomenu,tr("&Clear all bookmarks\tAlt-C\tClear all bookmarks."),getApp()->bookdelicon,this,ID_CLEAR_MARKS);
589 
590   // Search Menu
591   searchmenu=new FXMenuPane(this);
592   new FXMenuTitle(menubar,tr("&Search"),NULL,searchmenu);
593 
594   // Search Menu entries
595   new FXMenuCommand(searchmenu,tr("Select matching (..)\tShift-Ctl-M\tSelect matching brace or parenthesis."),NULL,editor,FXText::ID_SELECT_MATCHING);
596   new FXMenuCommand(searchmenu,tr("Select block {..}\tShift-Alt-{\tSelect enclosing block."),NULL,editor,FXText::ID_SELECT_BRACE);
597   new FXMenuCommand(searchmenu,tr("Select block {..}\tShift-Alt-}\tSelect enclosing block."),NULL,editor,FXText::ID_SELECT_BRACE);
598   new FXMenuCommand(searchmenu,tr("Select expression (..)\tShift-Alt-(\tSelect enclosing parentheses."),NULL,editor,FXText::ID_SELECT_PAREN);
599   new FXMenuCommand(searchmenu,tr("Select expression (..)\tShift-Alt-)\tSelect enclosing parentheses."),NULL,editor,FXText::ID_SELECT_PAREN);
600   new FXMenuSeparator(searchmenu);
601   new FXMenuCommand(searchmenu,tr("Incremental search\tCtl-I\tSearch for a string."),NULL,this,ID_ISEARCH_START);
602   new FXMenuCommand(searchmenu,tr("Search &Files\tShift-Ctl-F\tSearch files for a string."),NULL,this,ID_FINDFILES);
603   new FXMenuCommand(searchmenu,tr("Find Backward\tShift-Ctl-G\tSearch backward for another occurrence."),getApp()->searchprevicon,this,ID_SEARCH_NXT_BACK);
604   new FXMenuCommand(searchmenu,tr("Find Forward\tCtl-G\tSearch forward for another occurrence."),getApp()->searchnexticon,this,ID_SEARCH_NXT_FORW);
605   new FXMenuCommand(searchmenu,tr("Find Backward Selected\tShift-Ctl-H\tSearch backward for selected text."),getApp()->searchprevicon,this,ID_SEARCH_SEL_BACK);
606   new FXMenuCommand(searchmenu,tr("Find Forward Selected\tCtl-H\tSearch forward for selected text."),getApp()->searchnexticon,this,ID_SEARCH_SEL_FORW);
607 
608   new FXMenuCommand(searchmenu,tr("&Search...\tCtl-F\tSearch with a string pattern."),getApp()->searchicon,this,ID_SEARCH);
609   new FXMenuCommand(searchmenu,tr("R&eplace...\tCtl-R\tSearch and replace with a string pattern."),getApp()->replaceicon,this,ID_REPLACE);
610 
611   // Accelerators for search
612   getAccelTable()->addAccel("F3",this,FXSEL(SEL_COMMAND,ID_SEARCH_NXT_FORW));
613   getAccelTable()->addAccel("Shift-F3",this,FXSEL(SEL_COMMAND,ID_SEARCH_NXT_BACK));
614 
615   // Syntax menu; it scrolls if we get too many
616   syntaxmenu=new FXScrollPane(this,25);
617   new FXMenuRadio(syntaxmenu,tr("Plain\t\tNo syntax for this file."),this,ID_SYNTAX_FIRST);
618   for(int syn=0; syn<getApp()->syntaxes.no() && syn<100; syn++){
619     new FXMenuRadio(syntaxmenu,getApp()->syntaxes[syn]->getName(),this,ID_SYNTAX_FIRST+1+syn);
620     }
621 
622   // Tabs menu
623   tabsmenu=new FXMenuPane(this);
624   new FXMenuRadio(tabsmenu,"1",this,ID_TABSELECT_1);
625   new FXMenuRadio(tabsmenu,"2",this,ID_TABSELECT_2);
626   new FXMenuRadio(tabsmenu,"3",this,ID_TABSELECT_3);
627   new FXMenuRadio(tabsmenu,"4",this,ID_TABSELECT_4);
628   new FXMenuRadio(tabsmenu,"5",this,ID_TABSELECT_5);
629   new FXMenuRadio(tabsmenu,"6",this,ID_TABSELECT_6);
630   new FXMenuRadio(tabsmenu,"7",this,ID_TABSELECT_7);
631   new FXMenuRadio(tabsmenu,"8",this,ID_TABSELECT_8);
632 
633 
634   // Shell Menu
635   shellmenu=new FXMenuPane(this);
636   new FXMenuTitle(menubar,tr("&Command"),NULL,shellmenu);
637 
638   // Options menu
639   new FXMenuCommand(shellmenu,tr("Execute &Command...\t\tExecute a shell command."),NULL,this,ID_SHELL_DIALOG);
640   new FXMenuCommand(shellmenu,tr("&Filter Selection...\t\tFilter selection through shell command."),NULL,this,ID_SHELL_FILTER);
641   new FXMenuCommand(shellmenu,tr("C&ancel Command\t\tCancel shell command."),NULL,this,ID_SHELL_CANCEL);
642 
643   // Options Menu
644   optionmenu=new FXMenuPane(this);
645   new FXMenuTitle(menubar,tr("&Options"),NULL,optionmenu);
646 
647   // Options menu
648   new FXMenuCommand(optionmenu,tr("Preferences...\t\tChange preferences."),getApp()->configicon,this,ID_PREFERENCES);
649   new FXMenuCommand(optionmenu,tr("Font...\t\tChange text font."),getApp()->fontsicon,this,ID_FONT);
650   new FXMenuCheck(optionmenu,tr("Insert &tabs\t\tToggle insert tabs."),this,ID_INSERTTABS);
651   new FXMenuCheck(optionmenu,tr("&Word wrap\t\tToggle word wrap mode."),this,ID_TOGGLE_WRAP);
652   new FXMenuCheck(optionmenu,tr("&Overstrike\t\tToggle overstrike mode."),editor,FXText::ID_TOGGLE_OVERSTRIKE);
653   new FXMenuCheck(optionmenu,tr("&Syntax coloring\t\tToggle syntax coloring."),this,ID_SYNTAX);
654   new FXMenuCheck(optionmenu,tr("Use initial size\t\tToggle initial window size mode."),this,ID_USE_INITIAL_SIZE);
655   new FXMenuCommand(optionmenu,tr("Set initial size\t\tSet current window size as the initial window size."),NULL,this,ID_SET_INITIAL_SIZE);
656   new FXMenuCommand(optionmenu,tr("&Restyle\t\tToggle syntax coloring."),NULL,this,ID_RESTYLE);
657   new FXMenuCascade(optionmenu,tr("Tab stops"),NULL,tabsmenu);
658   new FXMenuCascade(optionmenu,tr("Syntax patterns\t\tSelect syntax for this file."),NULL,syntaxmenu);
659   new FXMenuSeparator(optionmenu);
660   new FXMenuCommand(optionmenu,tr("Save Settings\t\tSave settings now."),NULL,this,ID_SAVE_SETTINGS);
661 
662   // View menu
663   viewmenu=new FXMenuPane(this);
664   new FXMenuTitle(menubar,tr("&View"),NULL,viewmenu);
665 
666   // View Menu entries
667   new FXMenuCheck(viewmenu,tr("File Browser\t\tDisplay file list."),this,ID_TOGGLE_BROWSER);
668   new FXMenuCheck(viewmenu,tr("Error Logger\t\tDisplay error logger."),loggerframe,FXWindow::ID_TOGGLESHOWN);
669   new FXMenuCheck(viewmenu,tr("Toolbar\t\tDisplay toolbar."),toolbar,FXWindow::ID_TOGGLESHOWN);
670   new FXMenuCheck(viewmenu,tr("Searchbar\t\tDisplay search bar."),searchbar,FXWindow::ID_TOGGLESHOWN);
671   new FXMenuCheck(viewmenu,tr("Status line\t\tDisplay status line."),statusbar,FXWindow::ID_TOGGLESHOWN);
672   new FXMenuCheck(viewmenu,tr("Undo Counters\t\tShow undo/redo counters on status line."),undoredoblock,FXWindow::ID_TOGGLESHOWN);
673   new FXMenuCheck(viewmenu,tr("Clock\t\tShow clock on status line."),clock,FXWindow::ID_TOGGLESHOWN);
674 
675   // Window menu
676   windowmenu=new FXMenuPane(this);
677   new FXMenuTitle(menubar,tr("&Window"),NULL,windowmenu);
678 
679   // Window menu
680   new FXMenuRadio(windowmenu,FXString::null,this,ID_WINDOW_1);
681   new FXMenuRadio(windowmenu,FXString::null,this,ID_WINDOW_2);
682   new FXMenuRadio(windowmenu,FXString::null,this,ID_WINDOW_3);
683   new FXMenuRadio(windowmenu,FXString::null,this,ID_WINDOW_4);
684   new FXMenuRadio(windowmenu,FXString::null,this,ID_WINDOW_5);
685   new FXMenuRadio(windowmenu,FXString::null,this,ID_WINDOW_6);
686   new FXMenuRadio(windowmenu,FXString::null,this,ID_WINDOW_7);
687   new FXMenuRadio(windowmenu,FXString::null,this,ID_WINDOW_8);
688   new FXMenuRadio(windowmenu,FXString::null,this,ID_WINDOW_9);
689   new FXMenuRadio(windowmenu,FXString::null,this,ID_WINDOW_10);
690 
691   // Help menu
692   helpmenu=new FXMenuPane(this);
693   new FXMenuTitle(menubar,tr("&Help"),NULL,helpmenu);
694 
695   // Help Menu entries
696   new FXMenuCommand(helpmenu,tr("&Help...\t\tDisplay help information."),getApp()->helpicon,this,ID_HELP,0);
697   new FXMenuSeparator(helpmenu);
698   new FXMenuCommand(helpmenu,tr("&About Adie...\t\tDisplay about panel."),getApp()->smallicon,this,ID_ABOUT,0);
699   }
700 
701 
702 // Create tool bar
createToolbar()703 void TextWindow::createToolbar(){
704 
705   // Toobar buttons: File manipulation
706   new FXButton(toolbar,tr("\tNew\tCreate new document."),getApp()->newicon,this,ID_NEW,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
707   new FXButton(toolbar,tr("\tOpen\tOpen document file."),getApp()->openicon,this,ID_OPEN,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
708   new FXButton(toolbar,tr("\tSave\tSave document."),getApp()->saveicon,this,ID_SAVE,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
709   new FXButton(toolbar,tr("\tSave As\tSave document under a different file name."),getApp()->saveasicon,this,ID_SAVEAS,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
710   new FXButton(toolbar,tr("\tSave To\tSave copy of document to file name."),getApp()->savetoicon,this,ID_SAVETO,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
711 
712   // Spacer
713   new FXSeparator(toolbar,SEPARATOR_GROOVE);
714 
715   // Toobar buttons: Print
716   new FXButton(toolbar,"\tPrint\tPrint document.",getApp()->printicon,this,ID_PRINT,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
717 
718   // Spacer
719   new FXSeparator(toolbar,SEPARATOR_GROOVE);
720 
721   // Toobar buttons: Editing
722   new FXButton(toolbar,tr("\tCut\tCut selection to clipboard."),getApp()->cuticon,editor,FXText::ID_CUT_SEL,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
723   new FXButton(toolbar,tr("\tCopy\tCopy selection to clipboard."),getApp()->copyicon,editor,FXText::ID_COPY_SEL,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
724   new FXButton(toolbar,tr("\tPaste\tPaste clipboard."),getApp()->pasteicon,editor,FXText::ID_PASTE_SEL,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
725   new FXButton(toolbar,tr("\tDelete\t\tDelete selection."),getApp()->deleteicon,editor,FXText::ID_DELETE_SEL,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
726 
727   // Spacer
728   new FXSeparator(toolbar,SEPARATOR_GROOVE);
729 
730   // Undo/redo
731   new FXButton(toolbar,tr("\tUndo\tUndo last change."),getApp()->undoicon,&undolist,FXUndoList::ID_UNDO,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
732   new FXButton(toolbar,tr("\tRedo\tRedo last undo."),getApp()->redoicon,&undolist,FXUndoList::ID_REDO,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
733 
734   // Spacer
735   new FXSeparator(toolbar,SEPARATOR_GROOVE);
736 
737   // Search
738   new FXButton(toolbar,tr("\tSearch...\tSearch with a string pattern."),getApp()->searchicon,this,ID_SEARCH,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
739   new FXButton(toolbar,tr("\tReplace...\tSearch and replace with a string pattern."),getApp()->replaceicon,this,ID_REPLACE,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
740   new FXButton(toolbar,tr("\tFind previous selected\tSearch previous occurrence of selected text."),getApp()->searchprevicon,this,ID_SEARCH_SEL_BACK,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
741   new FXButton(toolbar,tr("\tFind next selected\tSearch next occurrence of selected text."),getApp()->searchnexticon,this,ID_SEARCH_SEL_FORW,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
742 
743   // Spacer
744   new FXSeparator(toolbar,SEPARATOR_GROOVE);
745 
746   // Bookmarks
747   new FXButton(toolbar,tr("\tSet bookmark\tSet bookmark at cursor location."),getApp()->bookseticon,this,ID_SET_MARK,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
748   new FXButton(toolbar,tr("\tPrevious Bookmark\tMove cursor to previous bookmark."),getApp()->bookprevicon,this,ID_PREV_MARK,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
749   new FXButton(toolbar,tr("\tNext Bookmark\tMove cursor to next bookmark."),getApp()->booknexticon,this,ID_NEXT_MARK,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
750   new FXButton(toolbar,tr("\tClear Bookmarks\tClear all bookmarks."),getApp()->bookdelicon,this,ID_CLEAR_MARKS,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
751 
752   // Spacer
753   new FXSeparator(toolbar,SEPARATOR_GROOVE);
754 
755   new FXButton(toolbar,tr("\tShift left\tShift text left by one."),getApp()->shiftlefticon,editor,FXText::ID_SHIFT_LEFT,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
756   new FXButton(toolbar,tr("\tShift right\tShift text right by one."),getApp()->shiftrighticon,editor,FXText::ID_SHIFT_RIGHT,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
757 
758   // Spacer
759   new FXSeparator(toolbar,SEPARATOR_GROOVE);
760   new FXToggleButton(toolbar,tr("\tShow Browser\t\tShow file browser."),tr("\tHide Browser\t\tHide file browser."),getApp()->nobrowsericon,getApp()->browsericon,this,ID_TOGGLE_BROWSER,ICON_ABOVE_TEXT|TOGGLEBUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
761   new FXToggleButton(toolbar,tr("\tShow Logger\t\tShow error logger."),tr("\tHide Logger\t\tHide error logger."),getApp()->nologgericon,getApp()->loggericon,loggerframe,FXWindow::ID_TOGGLESHOWN,ICON_ABOVE_TEXT|TOGGLEBUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
762   new FXButton(toolbar,tr("\tPreferences\tDisplay preferences dialog."),getApp()->configicon,this,ID_PREFERENCES,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
763   new FXButton(toolbar,tr("\tFonts\tDisplay font dialog."),getApp()->fontsicon,this,ID_FONT,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
764 
765   // Help
766   new FXButton(toolbar,tr("\tDisplay help\tDisplay online help information."),getApp()->helpicon,this,ID_HELP,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_RIGHT);
767   }
768 
769 
770 // Create search bar
createSearchbar()771 void TextWindow::createSearchbar(){
772   new FXLabel(searchbar,tr("Search:"),NULL,LAYOUT_CENTER_Y);
773   FXHorizontalFrame* searchbox=new FXHorizontalFrame(searchbar,FRAME_LINE|LAYOUT_FILL_X|LAYOUT_CENTER_Y,0,0,0,0, 0,0,0,0, 0,0);
774   searchtext=new FXTextField(searchbox,50,this,ID_ISEARCH_TEXT,TEXTFIELD_ENTER_ONLY|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 4,4,1,1);
775   searchtext->setTipText(tr("Incremental Search (Ctl-I)"));
776   searchtext->setHelpText(tr("Incremental search for a string."));
777   FXVerticalFrame* searcharrows=new FXVerticalFrame(searchbox,LAYOUT_RIGHT|LAYOUT_FILL_Y,0,0,0,0, 0,0,0,0, 0,0);
778   FXArrowButton* ar1=new FXArrowButton(searcharrows,this,ID_ISEARCH_HIST_UP,ARROW_UP|ARROW_REPEAT|LAYOUT_FILL_Y|LAYOUT_FIX_WIDTH, 0,0,16,0, 3,3,2,2);
779   FXArrowButton* ar2=new FXArrowButton(searcharrows,this,ID_ISEARCH_HIST_DN,ARROW_DOWN|ARROW_REPEAT|LAYOUT_FILL_Y|LAYOUT_FIX_WIDTH, 0,0,16,0, 3,3,2,2);
780   ar1->setArrowSize(3);
781   ar2->setArrowSize(3);
782   ar1->setBackColor(searchtext->getBackColor());
783   ar2->setBackColor(searchtext->getBackColor());
784   new FXButton(searchbar,tr("\tSearch Previous (Page Up)\tSearch previous occurrence."),getApp()->backwardicon,this,ID_ISEARCH_PREV,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
785   new FXButton(searchbar,tr("\tSearch Next (Page Down)\tSearch next occurrence."),getApp()->forwardicon,this,ID_ISEARCH_NEXT,ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT);
786   new FXFrame(searchbar,FRAME_NONE|LAYOUT_CENTER_Y|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT,0,0,4,4);
787   new FXCheckButton(searchbar,tr("Rex:\tRegular Expression (Ctl-E)\tRegular expression search."),this,ID_ISEARCH_REGEX,ICON_AFTER_TEXT|JUSTIFY_CENTER_Y|LAYOUT_CENTER_Y,0,0,0,0, 1,1,1,1);
788   new FXFrame(searchbar,FRAME_NONE|LAYOUT_CENTER_Y|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT,0,0,4,4);
789   new FXCheckButton(searchbar,tr("Case:\tCase Insensitive (Ctl-I)\tCase insensitive search."),this,ID_ISEARCH_IGNCASE,ICON_AFTER_TEXT|JUSTIFY_CENTER_Y|LAYOUT_CENTER_Y,0,0,0,0, 1,1,1,1);
790   new FXFrame(searchbar,FRAME_NONE|LAYOUT_CENTER_Y|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT,0,0,4,4);
791   new FXCheckButton(searchbar,tr("Rev:\tReverse Direction (Ctl-D)\tBackward search direction."),this,ID_ISEARCH_REVERSE,ICON_AFTER_TEXT|JUSTIFY_CENTER_Y|LAYOUT_CENTER_Y,0,0,0,0, 1,1,1,1);
792   new FXFrame(searchbar,FRAME_NONE|LAYOUT_CENTER_Y|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT,0,0,4,4);
793   }
794 
795 
796 // Create status bar
createStatusbar()797 void TextWindow::createStatusbar(){
798 
799   // Info about the editor
800   new FXButton(statusbar,tr("\tAbout Adie\tAbout the Adie text editor."),getApp()->smallicon,this,ID_ABOUT,LAYOUT_FILL_Y|LAYOUT_RIGHT);
801 
802   // Show clock on status bar
803   clock=new FXTextField(statusbar,8,NULL,0,FRAME_SUNKEN|JUSTIFY_RIGHT|LAYOUT_RIGHT|LAYOUT_CENTER_Y|TEXTFIELD_READONLY,0,0,0,0,2,2,1,1);
804   clock->setBackColor(statusbar->getBackColor());
805 
806   // Undo/redo block
807   undoredoblock=new FXHorizontalFrame(statusbar,LAYOUT_RIGHT|LAYOUT_CENTER_Y,0,0,0,0, 0,0,0,0);
808   new FXLabel(undoredoblock,tr("  Undo:"),NULL,LAYOUT_CENTER_Y);
809   FXTextField* undocount=new FXTextField(undoredoblock,5,&undolist,FXUndoList::ID_UNDO_COUNT,TEXTFIELD_READONLY|FRAME_SUNKEN|JUSTIFY_RIGHT|LAYOUT_CENTER_Y,0,0,0,0,2,2,1,1);
810   undocount->setBackColor(statusbar->getBackColor());
811   new FXLabel(undoredoblock,tr("  Redo:"),NULL,LAYOUT_CENTER_Y);
812   FXTextField* redocount=new FXTextField(undoredoblock,5,&undolist,FXUndoList::ID_REDO_COUNT,TEXTFIELD_READONLY|FRAME_SUNKEN|JUSTIFY_RIGHT|LAYOUT_CENTER_Y,0,0,0,0,2,2,1,1);
813   redocount->setBackColor(statusbar->getBackColor());
814 
815   // Show readonly state in status bar
816   FXLabel* readonly=new FXLabel(statusbar,FXString::null,NULL,FRAME_SUNKEN|JUSTIFY_RIGHT|LAYOUT_RIGHT|LAYOUT_CENTER_Y,0,0,0,0,2,2,1,1);
817   readonly->setTarget(this);
818   readonly->setSelector(ID_READONLY);
819   readonly->setTipText(tr("Editable"));
820 
821   // Show insert mode in status bar
822   FXLabel* overstrike=new FXLabel(statusbar,FXString::null,NULL,FRAME_SUNKEN|LAYOUT_RIGHT|LAYOUT_CENTER_Y,0,0,0,0,2,2,1,1);
823   overstrike->setTarget(this);
824   overstrike->setSelector(ID_OVERSTRIKE);
825   overstrike->setTipText(tr("Overstrike mode"));
826 
827   // Show tab mode in status bar
828   FXLabel* tabmode=new FXLabel(statusbar,FXString::null,NULL,FRAME_SUNKEN|LAYOUT_RIGHT|LAYOUT_CENTER_Y,0,0,0,0,2,2,1,1);
829   tabmode->setTarget(this);
830   tabmode->setSelector(ID_TABMODE);
831   tabmode->setTipText(tr("Tab mode"));
832 
833   // Show size of text in status bar
834   FXTextField* numchars=new FXTextField(statusbar,2,this,ID_TABCOLUMNS,FRAME_SUNKEN|JUSTIFY_RIGHT|LAYOUT_RIGHT|LAYOUT_CENTER_Y,0,0,0,0,2,2,1,1);
835   numchars->setBackColor(statusbar->getBackColor());
836   numchars->setTipText(tr("Tab setting"));
837 
838   // Caption before tab columns
839   new FXLabel(statusbar,tr("  Tab:"),NULL,LAYOUT_RIGHT|LAYOUT_CENTER_Y);
840 
841   // Show column number in status bar
842   FXTextField* columnno=new FXTextField(statusbar,6,editor,FXText::ID_CURSOR_COLUMN,FRAME_SUNKEN|JUSTIFY_RIGHT|LAYOUT_RIGHT|LAYOUT_CENTER_Y,0,0,0,0,2,2,1,1);
843   columnno->setBackColor(statusbar->getBackColor());
844   columnno->setTipText(tr("Current column"));
845 
846   // Caption before number
847   new FXLabel(statusbar,tr("  Col:"),NULL,LAYOUT_RIGHT|LAYOUT_CENTER_Y);
848 
849   // Show line number in status bar
850   FXTextField* rowno=new FXTextField(statusbar,6,editor,FXText::ID_CURSOR_ROW,FRAME_SUNKEN|JUSTIFY_RIGHT|LAYOUT_RIGHT|LAYOUT_CENTER_Y,0,0,0,0,2,2,1,1);
851   rowno->setBackColor(statusbar->getBackColor());
852   rowno->setTipText(tr("Current line"));
853 
854   // Caption before number
855   new FXLabel(statusbar,tr("  Line:"),NULL,LAYOUT_RIGHT|LAYOUT_CENTER_Y);
856   }
857 
858 
859 // Create and show window
create()860 void TextWindow::create(){
861   readRegistry();
862   FXMainWindow::create();
863   dragshell1->create();
864   dragshell2->create();
865   dragshell3->create();
866   filemenu->create();
867   editmenu->create();
868   gotomenu->create();
869   searchmenu->create();
870   optionmenu->create();
871   viewmenu->create();
872   windowmenu->create();
873   helpmenu->create();
874   if(!urilistType){urilistType=getApp()->registerDragType(urilistTypeName);}
875   getApp()->addTimeout(this,ID_CLOCKTIME,CLOCKTIMER);
876   editor->setFocus();
877   show(PLACEMENT_DEFAULT);
878   }
879 
880 
881 // Detach window
detach()882 void TextWindow::detach(){
883   FXMainWindow::detach();
884   dragshell1->detach();
885   dragshell2->detach();
886   urilistType=0;
887   }
888 
889 
890 // Clean up the mess
~TextWindow()891 TextWindow::~TextWindow(){
892   getApp()->windowlist.remove(this);
893   getApp()->removeTimeout(this,ID_CLOCKTIME);
894   delete shellCommand;
895   delete font;
896   delete dragshell1;
897   delete dragshell2;
898   delete dragshell3;
899   delete filemenu;
900   delete editmenu;
901   delete gotomenu;
902   delete searchmenu;
903   delete shellmenu;
904   delete optionmenu;
905   delete viewmenu;
906   delete windowmenu;
907   delete helpmenu;
908   delete syntaxmenu;
909   delete tabsmenu;
910   }
911 
912 
913 /*******************************************************************************/
914 
915 // Set current file of directory browser
setBrowserCurrentFile(const FXString & file)916 void TextWindow::setBrowserCurrentFile(const FXString& file){
917   dirlist->setCurrentFile(file);
918   }
919 
920 
921 // Get current file of directory browser
getBrowserCurrentFile() const922 FXString TextWindow::getBrowserCurrentFile() const {
923   return dirlist->getCurrentFile();
924   }
925 
926 
927 // Is it modified
isModified() const928 FXbool TextWindow::isModified() const {
929   return !undolist.marked();
930   }
931 
932 
933 // Set editable flag
setEditable(FXbool edit)934 void TextWindow::setEditable(FXbool edit){
935   editor->setEditable(edit);
936   }
937 
938 
939 // Is it editable
isEditable() const940 FXbool TextWindow::isEditable() const {
941   return editor->isEditable();
942   }
943 
944 /*******************************************************************************/
945 
946 enum {
947   CRLF = 1,     // CRLF versus LF
948   LINE = 2,     // Append end of line
949   TRIM = 4      // trim trailing space
950   };
951 
952 // Load file into buffer
loadBuffer(const FXString & file,FXString & buffer,FXuint bits)953 FXbool TextWindow::loadBuffer(const FXString& file,FXString& buffer,FXuint bits){
954   FXFile textfile(file,FXFile::Reading);
955   if(textfile.isOpen()){
956     FXlong size=textfile.size();
957     if(size<=MAXFILESIZE){
958       if(buffer.length(size)){
959         if(textfile.readBlock(buffer.text(),buffer.length())==buffer.length()){
960           if(bits&TRIM){
961             FXint i=0,j=0,k=0,c;
962             while(j<buffer.length()){
963               buffer[i]=c=buffer[j];
964               if(c=='\n'){
965                 while(k<i && Ascii::isSpace(buffer[i-1])){
966                   i--;
967                   }
968                 buffer[i]='\n';
969                 k=i+1;
970                 }
971               i++;
972               j++;
973               }
974             buffer.trunc(i);
975             }
976           if(bits&LINE){
977             if(buffer.tail()!='\n'){
978               buffer.append('\n');
979               }
980             }
981           if(bits&CRLF){
982             dosToUnix(buffer);
983             }
984           return true;
985           }
986         }
987       }
988     }
989   return false;
990   }
991 
992 
993 // Save file from buffer
saveBuffer(const FXString & file,FXString & buffer,FXuint bits)994 FXbool TextWindow::saveBuffer(const FXString& file,FXString& buffer,FXuint bits){
995   FXFile textfile(file,FXFile::Writing);
996   if(textfile.isOpen()){
997     if(bits&TRIM){
998       FXint i=0,j=0,k=0,c;
999       while(j<buffer.length()){
1000         buffer[i]=c=buffer[j];
1001         if(c=='\n'){
1002           while(k<i && Ascii::isSpace(buffer[i-1])){
1003             i--;
1004             }
1005           buffer[i]='\n';
1006           k=i+1;
1007           }
1008         i++;
1009         j++;
1010         }
1011       buffer.trunc(i);
1012       }
1013     if(bits&LINE){
1014       if(buffer.tail()!='\n'){
1015         buffer.append('\n');
1016         }
1017       }
1018     if(bits&CRLF){
1019       unixToDos(buffer);
1020       }
1021     if(textfile.writeBlock(buffer.text(),buffer.length())==buffer.length()){
1022       return true;
1023       }
1024     }
1025   return false;
1026   }
1027 
1028 /*******************************************************************************/
1029 
1030 // Load file
loadFile(const FXString & file)1031 FXbool TextWindow::loadFile(const FXString& file){
1032   FXString buffer;
1033   FXbool loaded=false;
1034   FXuint bits=0;
1035 
1036   // Load flags
1037   if(stripsp) bits|=TRIM;
1038   if(stripcr) bits|=CRLF;
1039 
1040   // Set wait cursor
1041   getApp()->beginWaitCursor();
1042 
1043   // Try load buffer
1044   if(TextWindow::loadBuffer(file,buffer,bits)){
1045 
1046     // Set text
1047     editor->setText(buffer);
1048 
1049     // Set stuff
1050     setEditable(FXStat::isAccessible(file,FXIO::ReadOnly|FXIO::WriteOnly));
1051     setBrowserCurrentFile(file);
1052     mrufiles.appendFile(file);
1053     setFiletime(FXStat::modified(file));
1054     setFilename(file);
1055     setFilenameSet(true);
1056 
1057     // Clear undo records
1058     undolist.clear();
1059 
1060     // Mark undo state as clean (saved)
1061     undolist.mark();
1062 
1063     // Success
1064     loaded=true;
1065     }
1066 
1067   // Kill wait cursor
1068   getApp()->endWaitCursor();
1069   return loaded;
1070   }
1071 
1072 
1073 // Save file
saveFile(const FXString & file)1074 FXbool TextWindow::saveFile(const FXString& file){
1075   FXString buffer;
1076   FXbool saved=false;
1077   FXuint bits=0;
1078 
1079   // Load flags
1080   if(stripsp) bits|=TRIM;
1081   if(appendcr) bits|=CRLF;
1082   if(appendnl) bits|=LINE;
1083 
1084   // Set wait cursor
1085   getApp()->beginWaitCursor();
1086 
1087   // Get text from editor
1088   editor->getText(buffer);
1089 
1090   // Try save buffer
1091   if(TextWindow::saveBuffer(file,buffer,bits)){
1092 
1093     // Set stuff
1094     setEditable(true);
1095     setBrowserCurrentFile(file);
1096     mrufiles.appendFile(file);
1097     setFiletime(FXStat::modified(file));
1098     setFilename(file);
1099     setFilenameSet(true);
1100 
1101     // Mark undo state as clean (saved)
1102     undolist.mark();
1103 
1104     // Success
1105     saved=true;
1106     }
1107 
1108   // Kill wait cursor
1109   getApp()->endWaitCursor();
1110   return saved;
1111   }
1112 
1113 
1114 // Save to file; don't switch to it as current document
saveToFile(const FXString & file)1115 FXbool TextWindow::saveToFile(const FXString& file){
1116   FXString buffer;
1117   FXbool saved=false;
1118   FXuint bits=0;
1119 
1120   // Load flags
1121   if(stripsp) bits|=TRIM;
1122   if(appendcr) bits|=CRLF;
1123   if(appendnl) bits|=LINE;
1124 
1125   // Set wait cursor
1126   getApp()->beginWaitCursor();
1127 
1128   // Get text from editor
1129   editor->getText(buffer);
1130 
1131   // Try save buffer
1132   if(TextWindow::saveBuffer(file,buffer,bits)){
1133     saved=true;
1134     }
1135 
1136   // Kill wait cursor
1137   getApp()->endWaitCursor();
1138   return saved;
1139   }
1140 
1141 /*******************************************************************************/
1142 
1143 // Replace by file
replaceByFile(const FXString & file,FXint startpos,FXint endpos,FXint startcol,FXint endcol)1144 FXbool TextWindow::replaceByFile(const FXString& file,FXint startpos,FXint endpos,FXint startcol,FXint endcol){
1145   FXString buffer;
1146   FXbool loaded=false;
1147   FXuint bits=0;
1148 
1149   // Load flags
1150   if(stripsp) bits|=TRIM;
1151   if(stripcr) bits|=CRLF;
1152 
1153   // Set wait cursor
1154   getApp()->beginWaitCursor();
1155 
1156   // Try load buffer
1157   if(TextWindow::loadBuffer(file,buffer,bits)){
1158 
1159     // Replace selection
1160     if(startpos<=endpos){
1161       if(startcol<endcol){
1162         editor->replaceTextBlock(startpos,endpos,startcol,endcol,buffer,true);
1163         }
1164       else if(startpos<endpos){
1165         editor->replaceText(startpos,endpos-startpos,buffer,true);
1166         }
1167       }
1168 
1169     // Or insert at cursor
1170     else{
1171       editor->insertText(editor->getCursorPos(),buffer,true);
1172       }
1173 
1174     // Success
1175     loaded=true;
1176     }
1177 
1178   // Kill wait cursor
1179   getApp()->endWaitCursor();
1180   return loaded;
1181   }
1182 
1183 
1184 // Extract file
extractToFile(const FXString & file,FXint startpos,FXint endpos,FXint startcol,FXint endcol)1185 FXbool TextWindow::extractToFile(const FXString& file,FXint startpos,FXint endpos,FXint startcol,FXint endcol){
1186   FXString buffer;
1187   FXbool saved=false;
1188   FXuint bits=0;
1189 
1190   // Load flags
1191   if(stripsp) bits|=TRIM;
1192   if(appendcr) bits|=CRLF;
1193   if(appendnl) bits|=LINE;
1194 
1195   // Set wait cursor
1196   getApp()->beginWaitCursor();
1197 
1198   // Replace selection
1199   if(startpos<=endpos){
1200     if(startcol<endcol){
1201       editor->extractTextBlock(buffer,startpos,endpos,startcol,endcol);
1202       }
1203     else if(startpos<endpos){
1204       editor->extractText(buffer,startpos,endpos-startpos);
1205       }
1206     }
1207 
1208   // Don't bother if no text
1209   if(buffer.length()){
1210 
1211     // Try save buffer
1212     if(TextWindow::saveBuffer(file,buffer,bits)){
1213       saved=true;
1214       }
1215     }
1216 
1217   // Kill wait cursor
1218   getApp()->endWaitCursor();
1219   return saved;
1220   }
1221 
1222 /*******************************************************************************/
1223 
1224 // Visit given line
visitLine(FXint line,FXint column)1225 void TextWindow::visitLine(FXint line,FXint column){
1226   editor->setCursorRowColumn(line-1,column);
1227   editor->setCenterLine(editor->getCursorPos());
1228   editor->makePositionVisible(editor->getCursorPos());
1229   }
1230 
1231 
1232 // Change patterns, each pattern separated by newline
setPatternList(const FXString & patterns)1233 void TextWindow::setPatternList(const FXString& patterns){
1234   FXint current=getCurrentPattern();
1235   filter->clearItems();
1236   filter->fillItems(patterns);
1237   if(!filter->getNumItems()) filter->appendItem("All Files (*)");
1238   setCurrentPattern(FXCLAMP(0,current,filter->getNumItems()-1));
1239   }
1240 
1241 
1242 // Return list of patterns
getPatternList() const1243 FXString TextWindow::getPatternList() const {
1244   FXString pat; FXint i;
1245   for(i=0; i<filter->getNumItems(); i++){
1246     if(!pat.empty()) pat+='\n';
1247     pat+=filter->getItemText(i);
1248     }
1249   return pat;
1250   }
1251 
1252 
1253 // Change search paths
setSearchPaths(const FXString & paths)1254 void TextWindow::setSearchPaths(const FXString& paths){
1255   searchpaths=paths;
1256   }
1257 
1258 
getSearchPaths() const1259 FXString TextWindow::getSearchPaths() const {
1260   return searchpaths;
1261   }
1262 
1263 
1264 // Set current pattern
setCurrentPattern(FXint n)1265 void TextWindow::setCurrentPattern(FXint n){
1266   filter->setCurrentItem(FXCLAMP(0,n,filter->getNumItems()-1),true);
1267   }
1268 
1269 
1270 // Return current pattern
getCurrentPattern() const1271 FXint TextWindow::getCurrentPattern() const {
1272   return filter->getCurrentItem();
1273   }
1274 
1275 
1276 // Set status message
setStatusMessage(const FXString & msg)1277 void TextWindow::setStatusMessage(const FXString& msg){
1278   statusbar->getStatusLine()->setNormalText(msg);
1279   }
1280 
1281 /*******************************************************************************/
1282 
1283 // Read settings from registry
readRegistry()1284 void TextWindow::readRegistry(){
1285   FXColor textback,textfore,textselback,textselfore,textcursor,texthilitefore,texthiliteback,textactiveback,textbar,textnumber;
1286   FXColor dirback,dirfore,dirselback,dirselfore,dirlines;
1287   FXbool hiddenfiles,showactive,showmatch,hidetree;
1288   FXbool hideclock,hidestatus,hideundo,hidetoolbar;
1289   FXint ww,hh,xx,yy,modebits,treewidth,loggerheight;
1290   FXString fontspec;
1291 
1292   // Text colors
1293   textback=getApp()->reg().readColorEntry("SETTINGS","textbackground",editor->getBackColor());
1294   textfore=getApp()->reg().readColorEntry("SETTINGS","textforeground",editor->getTextColor());
1295   textselback=getApp()->reg().readColorEntry("SETTINGS","textselbackground",editor->getSelBackColor());
1296   textselfore=getApp()->reg().readColorEntry("SETTINGS","textselforeground",editor->getSelTextColor());
1297   textcursor=getApp()->reg().readColorEntry("SETTINGS","textcursor",editor->getCursorColor());
1298   texthilitefore=getApp()->reg().readColorEntry("SETTINGS","texthiliteforeground",editor->getHiliteTextColor());
1299   texthiliteback=getApp()->reg().readColorEntry("SETTINGS","texthilitebackground",editor->getHiliteBackColor());
1300   textactiveback=getApp()->reg().readColorEntry("SETTINGS","textactivebackground",editor->getActiveBackColor());
1301   textbar=getApp()->reg().readColorEntry("SETTINGS","textnumberbackground",editor->getBarColor());
1302   textnumber=getApp()->reg().readColorEntry("SETTINGS","textnumberforeground",editor->getNumberColor());
1303 
1304   // Directory colors
1305   dirback=getApp()->reg().readColorEntry("SETTINGS","browserbackground",dirlist->getBackColor());
1306   dirfore=getApp()->reg().readColorEntry("SETTINGS","browserforeground",dirlist->getTextColor());
1307   dirselback=getApp()->reg().readColorEntry("SETTINGS","browserselbackground",dirlist->getSelBackColor());
1308   dirselfore=getApp()->reg().readColorEntry("SETTINGS","browserselforeground",dirlist->getSelTextColor());
1309   dirlines=getApp()->reg().readColorEntry("SETTINGS","browserlines",dirlist->getLineColor());
1310 
1311   // Delimiters
1312   delimiters=getApp()->reg().readStringEntry("SETTINGS","delimiters","~.,/\\`'!@#$%^&*()-=+{}|[]\":;<>?");
1313 
1314   // Font
1315   fontspec=getApp()->reg().readStringEntry("SETTINGS","textfont","");
1316   if(!fontspec.empty()){
1317     font=new FXFont(getApp(),fontspec);
1318     editor->setFont(font);
1319     logger->setFont(font);
1320     }
1321 
1322   // Get size
1323   xx=getApp()->reg().readIntEntry("SETTINGS","x",5);
1324   yy=getApp()->reg().readIntEntry("SETTINGS","y",5);
1325   ww=getApp()->reg().readIntEntry("SETTINGS","width",600);
1326   hh=getApp()->reg().readIntEntry("SETTINGS","height",400);
1327 
1328   // Initial rows and columns
1329   initialwidth=getApp()->reg().readIntEntry("SETTINGS","initialwidth",640);
1330   initialheight=getApp()->reg().readIntEntry("SETTINGS","initialheight",480);
1331   initialsize=getApp()->reg().readBoolEntry("SETTINGS","initialsize",false);
1332 
1333   // Use this instead of size from last time
1334   if(initialsize){
1335     ww=initialwidth;
1336     hh=initialheight;
1337     }
1338 
1339   // Hidden files shown
1340   hiddenfiles=getApp()->reg().readBoolEntry("SETTINGS","showhiddenfiles",false);
1341   dirlist->showHiddenFiles(hiddenfiles);
1342 
1343   // Showing undo counters?
1344   hideundo=getApp()->reg().readBoolEntry("SETTINGS","hideundo",true);
1345 
1346   // Showing the tree?
1347   hidetree=getApp()->reg().readBoolEntry("SETTINGS","hidetree",true);
1348   treewidth=getApp()->reg().readIntEntry("SETTINGS","treewidth",100);
1349   if(!hidetree) ww+=treewidth;
1350   treebox->setWidth(treewidth);
1351 
1352   // Showing the clock?
1353   hideclock=getApp()->reg().readBoolEntry("SETTINGS","hideclock",false);
1354 
1355   // Showing the status line?
1356   hidestatus=getApp()->reg().readBoolEntry("SETTINGS","hidestatus",false);
1357 
1358   // Showing the tool bar?
1359   hidetoolbar=getApp()->reg().readBoolEntry("SETTINGS","hidetoolbar",false);
1360 
1361   // Showing the search bar?
1362   showsearchbar=getApp()->reg().readBoolEntry("SETTINGS","showsearchbar",false);
1363 
1364   // Showing the errors display?
1365   showlogger=getApp()->reg().readBoolEntry("SETTINGS","showlogger",false);
1366   loggerheight=getApp()->reg().readIntEntry("SETTINGS","loggerheight",32);
1367   loggerframe->setHeight(loggerheight);
1368 
1369   // Highlight match time
1370   editor->setHiliteMatchTime(getApp()->reg().readLongEntry("SETTINGS","bracematchpause",2000000000));
1371   showmatch=getApp()->reg().readBoolEntry("SETTINGS","bracematch",true);
1372 
1373   // Active Background
1374   showactive=getApp()->reg().readBoolEntry("SETTINGS","showactive",false);
1375 
1376   // Modeline support
1377   modeline=getApp()->reg().readBoolEntry("SETTINGS","modeline",false);
1378 
1379   // Autoindent
1380   autoindent=getApp()->reg().readBoolEntry("SETTINGS","autoindent",false);
1381 
1382   // Word wrapping
1383   wrapcols=getApp()->reg().readIntEntry("SETTINGS","wrapcols",80);
1384   wrapping=getApp()->reg().readBoolEntry("SETTINGS","wordwrap",false);
1385   fixedwrap=getApp()->reg().readBoolEntry("SETTINGS","fixedwrap",true);
1386 
1387   // Tab settings
1388   tabcols=getApp()->reg().readIntEntry("SETTINGS","tabcols",8);
1389   hardtabs=getApp()->reg().readBoolEntry("SETTINGS","hardtabs",true);
1390 
1391   // Space for line numbers
1392   barcols=getApp()->reg().readIntEntry("SETTINGS","barcols",0);
1393 
1394   // Various flags
1395   stripcr=getApp()->reg().readBoolEntry("SETTINGS","stripreturn",true);
1396   appendcr=getApp()->reg().readBoolEntry("SETTINGS","appendreturn",false);
1397   stripsp=getApp()->reg().readBoolEntry("SETTINGS","stripspaces",false);
1398   appendnl=getApp()->reg().readBoolEntry("SETTINGS","appendnewline",true);
1399   saveviews=getApp()->reg().readBoolEntry("SETTINGS","saveviews",false);
1400   savemarks=getApp()->reg().readBoolEntry("SETTINGS","savebookmarks",false);
1401   warnchanged=getApp()->reg().readBoolEntry("SETTINGS","warnchanged",true);
1402   colorize=getApp()->reg().readBoolEntry("SETTINGS","colorize",false);
1403   searchflags=getApp()->reg().readUIntEntry("SETTINGS","searchflags",SEARCH_FORWARD|SEARCH_EXACT);
1404 
1405   // File patterns
1406   setPatternList(getApp()->reg().readStringEntry("SETTINGS","filepatterns","All Files (*)"));
1407   setCurrentPattern(getApp()->reg().readIntEntry("SETTINGS","filepatternno",0));
1408 
1409   // Search path
1410   searchpaths=getApp()->reg().readStringEntry("SETTINGS","searchpaths","/usr/include");
1411 
1412   // Change the colors
1413   editor->setTextColor(textfore);
1414   editor->setBackColor(textback);
1415   editor->setSelBackColor(textselback);
1416   editor->setSelTextColor(textselfore);
1417   editor->setCursorColor(textcursor);
1418   editor->setHiliteBackColor(texthiliteback);
1419   editor->setHiliteTextColor(texthilitefore);
1420   editor->setActiveBackColor(textactiveback);
1421   editor->setBarColor(textbar);
1422   editor->setNumberColor(textnumber);
1423 
1424   dirlist->setTextColor(dirfore);
1425   dirlist->setBackColor(dirback);
1426   dirlist->setSelBackColor(dirselback);
1427   dirlist->setSelTextColor(dirselfore);
1428   dirlist->setLineColor(dirlines);
1429 
1430   // Change delimiters
1431   editor->setDelimiters(delimiters.text());
1432 
1433   // Hide tree if asked for
1434   if(hidetree) treebox->hide();
1435 
1436   // Hide clock
1437   if(hideclock) clock->hide();
1438 
1439   // Hide statusline
1440   if(hidestatus) statusbar->hide();
1441 
1442   // Hide toolbar
1443   if(hidetoolbar) toolbar->hide();
1444 
1445   // Hide search bar
1446   if(!showsearchbar) searchbar->hide();
1447 
1448   // Hide errors
1449   if(!showlogger) loggerframe->hide();
1450 
1451   // Hide undo counters
1452   if(hideundo) undoredoblock->hide();
1453 
1454   // Set editor modes
1455   modebits=0;
1456   if(!hardtabs) modebits|=TEXT_NO_TABS;
1457   if(wrapping) modebits|=TEXT_WORDWRAP;
1458   if(showactive) modebits|=TEXT_SHOWACTIVE;
1459   if(fixedwrap) modebits|=TEXT_FIXEDWRAP;
1460   if(autoindent) modebits|=TEXT_AUTOINDENT;
1461   if(showmatch) modebits|=TEXT_SHOWMATCH;
1462   editor->setTextStyle(modebits);
1463 
1464   // Wrap and tab columns
1465   editor->setWrapColumns(wrapcols);
1466   editor->setTabColumns(tabcols);
1467   editor->setBarColumns(barcols);
1468 
1469   // Search history
1470   loadSearchHistory();
1471 
1472   // Reposition window
1473   position(xx,yy,ww,hh);
1474   }
1475 
1476 /*******************************************************************************/
1477 
1478 // Save settings to registry
writeRegistry()1479 void TextWindow::writeRegistry(){
1480   FXString fontspec;
1481 
1482   // Colors of text
1483   getApp()->reg().writeColorEntry("SETTINGS","textbackground",editor->getBackColor());
1484   getApp()->reg().writeColorEntry("SETTINGS","textforeground",editor->getTextColor());
1485   getApp()->reg().writeColorEntry("SETTINGS","textselbackground",editor->getSelBackColor());
1486   getApp()->reg().writeColorEntry("SETTINGS","textselforeground",editor->getSelTextColor());
1487   getApp()->reg().writeColorEntry("SETTINGS","textcursor",editor->getCursorColor());
1488   getApp()->reg().writeColorEntry("SETTINGS","texthilitebackground",editor->getHiliteBackColor());
1489   getApp()->reg().writeColorEntry("SETTINGS","texthiliteforeground",editor->getHiliteTextColor());
1490   getApp()->reg().writeColorEntry("SETTINGS","textactivebackground",editor->getActiveBackColor());
1491   getApp()->reg().writeColorEntry("SETTINGS","textnumberbackground",editor->getBarColor());
1492   getApp()->reg().writeColorEntry("SETTINGS","textnumberforeground",editor->getNumberColor());
1493 
1494   // Colors of directory
1495   getApp()->reg().writeColorEntry("SETTINGS","browserbackground",dirlist->getBackColor());
1496   getApp()->reg().writeColorEntry("SETTINGS","browserforeground",dirlist->getTextColor());
1497   getApp()->reg().writeColorEntry("SETTINGS","browserselbackground",dirlist->getSelBackColor());
1498   getApp()->reg().writeColorEntry("SETTINGS","browserselforeground",dirlist->getSelTextColor());
1499   getApp()->reg().writeColorEntry("SETTINGS","browserlines",dirlist->getLineColor());
1500 
1501   // Delimiters
1502   getApp()->reg().writeStringEntry("SETTINGS","delimiters",delimiters.text());
1503 
1504   // Write new window size back to registry
1505   getApp()->reg().writeIntEntry("SETTINGS","x",getX());
1506   getApp()->reg().writeIntEntry("SETTINGS","y",getY());
1507   getApp()->reg().writeIntEntry("SETTINGS","width",treebox->shown() ? getWidth()-treebox->getWidth() : getWidth());
1508   getApp()->reg().writeIntEntry("SETTINGS","height",getHeight());
1509 
1510   // Initial size setting
1511   getApp()->reg().writeIntEntry("SETTINGS","initialwidth",initialwidth);
1512   getApp()->reg().writeIntEntry("SETTINGS","initialheight",initialheight);
1513   getApp()->reg().writeBoolEntry("SETTINGS","initialsize",initialsize);
1514 
1515   // Were showing hidden files
1516   getApp()->reg().writeBoolEntry("SETTINGS","showhiddenfiles",dirlist->showHiddenFiles());
1517 
1518   // Was tree shown
1519   getApp()->reg().writeBoolEntry("SETTINGS","hidetree",!treebox->shown());
1520   getApp()->reg().writeIntEntry("SETTINGS","treewidth",treebox->getWidth());
1521 
1522   // Was status line shown
1523   getApp()->reg().writeBoolEntry("SETTINGS","hidestatus",!statusbar->shown());
1524 
1525   // Was clock shown
1526   getApp()->reg().writeBoolEntry("SETTINGS","hideclock",!clock->shown());
1527 
1528   // Was toolbar shown
1529   getApp()->reg().writeBoolEntry("SETTINGS","hidetoolbar",!toolbar->shown());
1530 
1531   // Was search bar shown
1532   getApp()->reg().writeBoolEntry("SETTINGS","showsearchbar",searchbar->shown());
1533 
1534   // Was logger display shown
1535   getApp()->reg().writeBoolEntry("SETTINGS","showlogger",loggerframe->shown());
1536   getApp()->reg().writeIntEntry("SETTINGS","loggerheight",loggerframe->getHeight());
1537 
1538   // Were undo counters shown
1539   getApp()->reg().writeBoolEntry("SETTINGS","hideundo",!undoredoblock->shown());
1540 
1541   // Highlight match time
1542   getApp()->reg().writeLongEntry("SETTINGS","bracematchpause",editor->getHiliteMatchTime());
1543   getApp()->reg().writeBoolEntry("SETTINGS","bracematch",(editor->getTextStyle()&TEXT_SHOWMATCH)!=0);
1544 
1545   // Active background
1546   getApp()->reg().writeBoolEntry("SETTINGS","showactive",(editor->getTextStyle()&TEXT_SHOWACTIVE)!=0);
1547 
1548   // Modeline support
1549   getApp()->reg().writeBoolEntry("SETTINGS","modeline",modeline);
1550 
1551   // Autoindent mode
1552   getApp()->reg().writeBoolEntry("SETTINGS","autoindent",autoindent);
1553 
1554   // Wrap mode
1555   getApp()->reg().writeIntEntry("SETTINGS","wrapcols",wrapcols);
1556   getApp()->reg().writeBoolEntry("SETTINGS","wordwrap",wrapping);
1557   getApp()->reg().writeBoolEntry("SETTINGS","fixedwrap",fixedwrap);
1558 
1559   // Tab settings
1560   getApp()->reg().writeIntEntry("SETTINGS","tabcols",tabcols);
1561   getApp()->reg().writeBoolEntry("SETTINGS","hardtabs",hardtabs);
1562 
1563   // Bar columns
1564   getApp()->reg().writeIntEntry("SETTINGS","barcols",editor->getBarColumns());
1565 
1566   // Strip returns
1567   getApp()->reg().writeBoolEntry("SETTINGS","stripreturn",stripcr);
1568   getApp()->reg().writeBoolEntry("SETTINGS","appendreturn",appendcr);
1569   getApp()->reg().writeBoolEntry("SETTINGS","stripspaces",stripsp);
1570   getApp()->reg().writeBoolEntry("SETTINGS","appendnewline",appendnl);
1571   getApp()->reg().writeBoolEntry("SETTINGS","saveviews",saveviews);
1572   getApp()->reg().writeBoolEntry("SETTINGS","savebookmarks",savemarks);
1573   getApp()->reg().writeBoolEntry("SETTINGS","warnchanged",warnchanged);
1574   getApp()->reg().writeBoolEntry("SETTINGS","colorize",colorize);
1575   getApp()->reg().writeUIntEntry("SETTINGS","searchflags",searchflags);
1576 
1577   // File patterns
1578   getApp()->reg().writeIntEntry("SETTINGS","filepatternno",getCurrentPattern());
1579   getApp()->reg().writeStringEntry("SETTINGS","filepatterns",getPatternList().text());
1580 
1581   // Search path
1582   getApp()->reg().writeStringEntry("SETTINGS","searchpaths",searchpaths.text());
1583 
1584   // Font
1585   fontspec=editor->getFont()->getFont();
1586   getApp()->reg().writeStringEntry("SETTINGS","textfont",fontspec.text());
1587 
1588   // Search history
1589   saveSearchHistory();
1590   }
1591 
1592 /*******************************************************************************/
1593 
1594 // About box
onCmdAbout(FXObject *,FXSelector,void *)1595 long TextWindow::onCmdAbout(FXObject*,FXSelector,void*){
1596   FXDialogBox about(this,tr("About Adie"),DECOR_TITLE|DECOR_BORDER,0,0,0,0, 0,0,0,0, 0,0);
1597   FXGIFIcon picture(getApp(),adie_gif);
1598   new FXLabel(&about,FXString::null,&picture,FRAME_GROOVE|LAYOUT_SIDE_LEFT|LAYOUT_CENTER_Y|JUSTIFY_CENTER_X|JUSTIFY_CENTER_Y,0,0,0,0, 0,0,0,0);
1599   FXVerticalFrame* side=new FXVerticalFrame(&about,LAYOUT_SIDE_RIGHT|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 10,10,10,10, 0,0);
1600   new FXLabel(side,"A . d . i . e",NULL,JUSTIFY_LEFT|ICON_BEFORE_TEXT|LAYOUT_FILL_X);
1601   new FXHorizontalSeparator(side,SEPARATOR_LINE|LAYOUT_FILL_X);
1602   new FXLabel(side,FXString::value(tr("\nThe Adie ADvanced Interactive Editor, version %d.%d.%d (%s).\n\nAdie is a fast and convenient programming text editor and file\nviewer with an integrated directory browser.\nUsing The FOX Toolkit (www.fox-toolkit.org), version %d.%d.%d.\nCopyright (C) 2000,2020 Jeroen van der Zijp (jeroen@fox-toolkit.com).\n "),VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH,__DATE__,FOX_MAJOR,FOX_MINOR,FOX_LEVEL),NULL,JUSTIFY_LEFT|LAYOUT_FILL_X|LAYOUT_FILL_Y);
1603   FXButton *button=new FXButton(side,tr("&OK"),NULL,&about,FXDialogBox::ID_ACCEPT,BUTTON_INITIAL|BUTTON_DEFAULT|FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT,0,0,0,0,32,32,2,2);
1604   button->setFocus();
1605   about.execute(PLACEMENT_OWNER);
1606   return 1;
1607   }
1608 
1609 
1610 // Show help window, create it on-the-fly
onCmdHelp(FXObject *,FXSelector,void *)1611 long TextWindow::onCmdHelp(FXObject*,FXSelector,void*){
1612   HelpWindow *helpwindow=new HelpWindow(getApp());
1613   helpwindow->create();
1614   helpwindow->show(PLACEMENT_CURSOR);
1615   return 1;
1616   }
1617 
1618 
1619 // Show preferences dialog
onCmdPreferences(FXObject *,FXSelector,void *)1620 long TextWindow::onCmdPreferences(FXObject*,FXSelector,void*){
1621   Preferences preferences(this);
1622   preferences.setPatternList(getPatternList());
1623   preferences.setSyntax(getSyntax());
1624   if(preferences.execute()){
1625     setPatternList(preferences.getPatternList());
1626     }
1627   return 1;
1628   }
1629 
1630 
1631 // Change font
onCmdFont(FXObject *,FXSelector,void *)1632 long TextWindow::onCmdFont(FXObject*,FXSelector,void*){
1633   FXFontDialog fontdlg(this,tr("Change Font"),DECOR_BORDER|DECOR_TITLE);
1634   FXFontDesc fontdesc=editor->getFont()->getFontDesc();
1635   fontdlg.setFontDesc(fontdesc);
1636   if(fontdlg.execute()){
1637     FXFont *oldfont=font;
1638     fontdesc=fontdlg.getFontDesc();
1639     font=new FXFont(getApp(),fontdesc);
1640     font->create();
1641     editor->setFont(font);
1642     logger->setFont(font);
1643     delete oldfont;
1644     }
1645   return 1;
1646   }
1647 
1648 /*******************************************************************************/
1649 
1650 // Sensitize if editable
onUpdIsEditable(FXObject * sender,FXSelector,void *)1651 long TextWindow::onUpdIsEditable(FXObject* sender,FXSelector,void*){
1652   sender->handle(this,editor->isEditable()?FXSEL(SEL_COMMAND,ID_ENABLE):FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
1653   return 1;
1654   }
1655 
1656 
1657 // Sensitize if selection
onUpdHasSelection(FXObject * sender,FXSelector,void *)1658 long TextWindow::onUpdHasSelection(FXObject* sender,FXSelector,void*){
1659   sender->handle(this,editor->hasSelection()?FXSEL(SEL_COMMAND,ID_ENABLE):FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
1660   return 1;
1661   }
1662 
1663 
1664 // Reopen file
onCmdReopen(FXObject *,FXSelector,void *)1665 long TextWindow::onCmdReopen(FXObject*,FXSelector,void*){
1666   if(isModified()){
1667     if(FXMessageBox::question(this,MBOX_YES_NO,tr("Document was changed"),tr("Discard changes to this document?"))==MBOX_CLICKED_NO) return 1;
1668     }
1669   if(loadFile(getFilename())){
1670     readBookmarks(getFilename());
1671     readView(getFilename());
1672     determineSyntax();
1673     parseModeline();
1674     }
1675   else{
1676     getApp()->beep();
1677     FXMessageBox::error(this,MBOX_OK,tr("Error Loading File"),tr("Unable to load file: %s"),getFilename().text());
1678     }
1679   return 1;
1680   }
1681 
1682 
1683 // Update reopen file
onUpdReopen(FXObject * sender,FXSelector,void * ptr)1684 long TextWindow::onUpdReopen(FXObject* sender,FXSelector,void* ptr){
1685   sender->handle(this,isFilenameSet()?FXSEL(SEL_COMMAND,ID_ENABLE):FXSEL(SEL_COMMAND,ID_DISABLE),ptr);
1686   return 1;
1687   }
1688 
1689 
1690 // New
onCmdNew(FXObject *,FXSelector,void *)1691 long TextWindow::onCmdNew(FXObject*,FXSelector,void*){
1692   TextWindow *window=new TextWindow(getApp());
1693   FXString file=getApp()->unique(FXPath::directory(filename));
1694   window->setFilename(file);
1695   window->setBrowserCurrentFile(file);
1696   window->create();
1697   window->raise();
1698   window->setFocus();
1699   return 1;
1700   }
1701 
1702 
1703 // Open
onCmdOpen(FXObject *,FXSelector,void *)1704 long TextWindow::onCmdOpen(FXObject*,FXSelector,void*){
1705   FXFileDialog opendialog(this,tr("Open Document"));
1706   FXString file=getFilename();
1707   opendialog.setSelectMode(SELECTFILE_EXISTING);
1708   opendialog.setAssociations(getApp()->associations,false);
1709   opendialog.setPatternList(getPatternList());
1710   opendialog.setCurrentPattern(getCurrentPattern());
1711   opendialog.setFilename(file);
1712   if(opendialog.execute()){
1713     setCurrentPattern(opendialog.getCurrentPattern());
1714     file=opendialog.getFilename();
1715     TextWindow *window=getApp()->findWindow(file);
1716     if(!window){
1717       window=getApp()->findUnused();
1718       if(!window){
1719         window=new TextWindow(getApp());
1720         window->create();
1721         }
1722       if(window->loadFile(file)){
1723         window->readBookmarks(file);
1724         window->readView(file);
1725         window->determineSyntax();
1726         window->parseModeline();
1727         }
1728       else{
1729         FXMessageBox::error(window,MBOX_OK,tr("Error Loading File"),tr("Unable to load file: %s"),file.text());
1730         }
1731       }
1732     window->raise();
1733     window->setFocus();
1734     }
1735   return 1;
1736   }
1737 
1738 
1739 // Search for file from a list of possible directory paths;
1740 // the list of paths may contain expandable items relative to base
searchRelativePaths(const FXString & base,const FXString & paths,const FXString & file)1741 static FXString searchRelativePaths(const FXString& base,const FXString& paths,const FXString& file){
1742   if(!file.empty()){
1743     if(FXPath::isAbsolute(file)){
1744       if(FXStat::exists(file)) return file;
1745       }
1746     else{
1747       FXString path=FXPath::absolute(base,file);
1748       if(FXStat::exists(path)) return path;
1749       for(FXint beg=0,end=0; paths[beg]; beg=end){
1750         while(paths[beg]==PATHLISTSEP) beg++;
1751         end=beg;
1752         while(paths[end] && paths[end]!=PATHLISTSEP) end++;
1753         if(beg==end) break;
1754         path=FXPath::absolute(FXPath::absolute(base,FXPath::expand(paths.mid(beg,end-beg))),file);
1755         if(FXStat::exists(path)) return path;
1756         }
1757       }
1758     }
1759   return FXString::null;
1760   }
1761 
1762 
1763 // Open Selected
onCmdOpenSelected(FXObject *,FXSelector,void *)1764 long TextWindow::onCmdOpenSelected(FXObject*,FXSelector,void*){
1765   FXString string;
1766 
1767   // Get selection
1768   if(getDNDData(FROM_SELECTION,stringType,string)){
1769 
1770     // Its too big, most likely not a file name
1771     if(string.length()<1024){
1772 
1773       // Strip leading/trailing space
1774       string.trim();
1775 
1776       FXString file=string;
1777       FXint lineno=0;
1778       FXint column=0;
1779 
1780       // Maybe the string is the filename
1781       if(!FXStat::exists(file)){
1782 
1783         // If no directory part, use current directory
1784         FXString base=FXPath::directory(getFilename());
1785         if(base.empty()){
1786           base=FXSystem::getCurrentDirectory();
1787           }
1788 
1789         // Try if we can find it relative to base
1790         file=FXPath::absolute(base,string);
1791         if(!FXStat::exists(file)){
1792           FXchar   name[1024];
1793 
1794           // Extract name from #include "file.h" syntax
1795           if(string.scan("#%*[ \t]include \"%1023[^\"]\"",name)==1){
1796             file=searchRelativePaths(base,searchpaths,name);
1797             }
1798 
1799           // Extract name from #include <file.h> syntax
1800           else if(string.scan("#%*[ \t]include <%1023[^>]>",name)==1){
1801             file=searchRelativePaths(base,searchpaths,name);
1802             }
1803 
1804           // Compiler output in the form <filename>:<number>:<number>: Error message
1805           else if(string.scan("%1023[^:]:%d:%d",name,&lineno,&column)==3){
1806             file=searchRelativePaths(base,searchpaths,name);
1807             }
1808 
1809           // Compiler output in the form <filename>:<number>: Error message
1810           else if(string.scan("%1023[^:]:%d",name,&lineno)==2){
1811             file=searchRelativePaths(base,searchpaths,name);
1812             }
1813 
1814           // Compiler output in the form <filename>(<number>) : Error message
1815           else if(string.scan("%1023[^(](%d)",name,&lineno)==2){
1816             file=searchRelativePaths(base,searchpaths,name);
1817             }
1818 
1819           // Compiler output in the form "<filename>", line <number>: Error message
1820           else if(string.scan("\"%1023[^\"]\", line %d",name,&lineno)==2){
1821             file=searchRelativePaths(base,searchpaths,name);
1822             }
1823 
1824           // Compiler output in the form ... File = <filename>, Line = <number>
1825           else if(string.scan("%*[^:]: %*s File = %1023[^,], Line = %d",name,&lineno)==2){
1826             file=searchRelativePaths(base,searchpaths,name);
1827             }
1828 
1829           // Compiler output in the form filename: Other stuff
1830           else if(string.scan("%1023[^:]:",name)==1){
1831             file=searchRelativePaths(base,searchpaths,name);
1832             }
1833 
1834           // Last straw, maybe dequote it?
1835           if(file.empty()){
1836             file=FXPath::dequote(string);
1837             }
1838           }
1839         }
1840 
1841       // If exists, try load it!
1842       if(FXStat::exists(file)){
1843 
1844         // File loaded already?
1845         TextWindow *window=getApp()->findWindow(file);
1846         if(!window){
1847           window=getApp()->findUnused();
1848           if(!window){
1849             window=new TextWindow(getApp());
1850             window->create();
1851             }
1852           if(window->loadFile(file)){
1853             window->readBookmarks(file);
1854             window->readView(file);
1855             window->determineSyntax();
1856             window->parseModeline();
1857             }
1858           else{
1859             getApp()->beep();
1860             FXMessageBox::error(this,MBOX_OK,tr("Error Loading File"),tr("Unable to load file: %s"),file.text());
1861             }
1862           }
1863 
1864         // Switch line number only
1865         if(lineno){
1866           window->visitLine(lineno,column);
1867           }
1868 
1869         // Bring up the window
1870         window->raise();
1871         window->setFocus();
1872         return 1;
1873         }
1874       }
1875     getApp()->beep();
1876     }
1877   return 1;
1878   }
1879 
1880 
1881 // Open recent file
onCmdOpenRecent(FXObject *,FXSelector,void * ptr)1882 long TextWindow::onCmdOpenRecent(FXObject*,FXSelector,void* ptr){
1883   FXString file=(const char*)ptr;
1884   TextWindow *window=getApp()->findWindow(file);
1885   if(!window){
1886     window=getApp()->findUnused();
1887     if(!window){
1888       window=new TextWindow(getApp());
1889       window->create();
1890       }
1891     if(window->loadFile(file)){
1892       window->readBookmarks(file);
1893       window->readView(file);
1894       window->determineSyntax();
1895       window->parseModeline();
1896       }
1897     else{
1898       mrufiles.removeFile(file);
1899       getApp()->beep();
1900       FXMessageBox::error(this,MBOX_OK,tr("Error Loading File"),tr("Unable to load file: %s"),file.text());
1901       }
1902     }
1903   window->raise();
1904   window->setFocus();
1905   return 1;
1906   }
1907 
1908 
1909 // Command from the tree list
onCmdOpenTree(FXObject *,FXSelector,void * ptr)1910 long TextWindow::onCmdOpenTree(FXObject*,FXSelector,void* ptr){
1911   FXTreeItem *item=(FXTreeItem*)ptr;
1912   if(item && dirlist->isItemFile(item)){
1913     if(!saveChanges()) return 1;
1914     FXString file=dirlist->getItemPathname(item);
1915     if(loadFile(file)){
1916       readBookmarks(file);
1917       readView(file);
1918       determineSyntax();
1919       parseModeline();
1920       }
1921     else{
1922       getApp()->beep();
1923       FXMessageBox::error(this,MBOX_OK,tr("Error Loading File"),tr("Unable to load file: %s"),file.text());
1924       }
1925     }
1926   return 1;
1927   }
1928 
1929 
1930 // Switch files
onCmdSwitch(FXObject *,FXSelector,void *)1931 long TextWindow::onCmdSwitch(FXObject*,FXSelector,void*){
1932   if(saveChanges()){
1933     FXFileDialog opendialog(this,tr("Switch Document"));
1934     FXString file=getFilename();
1935     opendialog.setSelectMode(SELECTFILE_EXISTING);
1936     opendialog.setAssociations(getApp()->associations,false);
1937     opendialog.setPatternList(getPatternList());
1938     opendialog.setCurrentPattern(getCurrentPattern());
1939     opendialog.setFilename(file);
1940     if(opendialog.execute()){
1941       setCurrentPattern(opendialog.getCurrentPattern());
1942       file=opendialog.getFilename();
1943       if(loadFile(file)){
1944         readBookmarks(file);
1945         readView(file);
1946         determineSyntax();
1947         parseModeline();
1948         }
1949       else{
1950         getApp()->beep();
1951         FXMessageBox::error(this,MBOX_OK,tr("Error Switching Files"),tr("Unable to switch to file: %s"),file.text());
1952         }
1953       }
1954     }
1955   return 1;
1956   }
1957 
1958 
1959 // See if we can get it as a filename
onTextDNDDrop(FXObject *,FXSelector,void *)1960 long TextWindow::onTextDNDDrop(FXObject*,FXSelector,void*){
1961   FXString string,file;
1962   if(getDNDData(FROM_DRAGNDROP,urilistType,string)){
1963     file=FXURL::fileFromURL(string.before('\r'));
1964     if(file.empty()) return 1;
1965     if(!saveChanges()) return 1;
1966     if(loadFile(file)){
1967       readBookmarks(file);
1968       readView(file);
1969       determineSyntax();
1970       parseModeline();
1971       }
1972     else{
1973       getApp()->beep();
1974       FXMessageBox::error(this,MBOX_OK,tr("Error Loading File"),tr("Unable to load file: %s"),file.text());
1975       }
1976     return 1;
1977     }
1978   return 0;
1979   }
1980 
1981 
1982 // See if a filename is being dragged over the window
onTextDNDMotion(FXObject *,FXSelector,void *)1983 long TextWindow::onTextDNDMotion(FXObject*,FXSelector,void*){
1984   if(offeredDNDType(FROM_DRAGNDROP,urilistType)){
1985     acceptDrop(DRAG_COPY);
1986     return 1;
1987     }
1988   return 0;
1989   }
1990 
1991 
1992 // Replace by text from file
onCmdReplaceFile(FXObject *,FXSelector,void *)1993 long TextWindow::onCmdReplaceFile(FXObject*,FXSelector,void*){
1994   FXFileDialog opendialog(this,tr("Load Text"));
1995   FXint sp=editor->getSelStartPos();
1996   FXint ep=editor->getSelEndPos();
1997   FXint sc=editor->getSelStartColumn();
1998   FXint ec=editor->getSelEndColumn();
1999   FXString file;
2000   opendialog.setSelectMode(SELECTFILE_EXISTING);
2001   opendialog.setAssociations(getApp()->associations,false);
2002   opendialog.setPatternList(getPatternList());
2003   opendialog.setCurrentPattern(getCurrentPattern());
2004   opendialog.setDirectory(FXPath::directory(getFilename()));
2005   if(opendialog.execute()){
2006     setCurrentPattern(opendialog.getCurrentPattern());
2007     file=opendialog.getFilename();
2008     if(!replaceByFile(file,sp,ep,sc,ec)){
2009       FXMessageBox::error(this,MBOX_OK,tr("Error Replacing From File"),tr("Unable to replace text from file: %s."),file.text());
2010       }
2011     }
2012   return 1;
2013   }
2014 
2015 
2016 // Extract selection to file
onCmdExtractFile(FXObject *,FXSelector,void *)2017 long TextWindow::onCmdExtractFile(FXObject*,FXSelector,void*){
2018   FXFileDialog savedialog(this,tr("Save Text"));
2019   FXint sp=editor->getSelStartPos();
2020   FXint ep=editor->getSelEndPos();
2021   FXint sc=editor->getSelStartColumn();
2022   FXint ec=editor->getSelEndColumn();
2023   FXString file=FXPath::stripExtension(getFilename())+".extract";
2024   savedialog.setSelectMode(SELECTFILE_ANY);
2025   savedialog.setAssociations(getApp()->associations,false);
2026   savedialog.setPatternList(getPatternList());
2027   savedialog.setCurrentPattern(getCurrentPattern());
2028   savedialog.setDirectory(FXPath::directory(getFilename()));
2029   savedialog.setFilename(file);
2030   if(savedialog.execute()){
2031     setCurrentPattern(savedialog.getCurrentPattern());
2032     file=savedialog.getFilename();
2033     if(FXStat::exists(file)){
2034       if(MBOX_CLICKED_NO==FXMessageBox::question(this,MBOX_YES_NO,tr("Overwrite Document"),tr("Overwrite existing document: %s?"),file.text())) return 1;
2035       }
2036     if(!extractToFile(file,sp,ep,sc,ec)){
2037       FXMessageBox::error(this,MBOX_OK,tr("Error Extracting To File"),tr("Unable to extract to file: %s."),file.text());
2038       }
2039     }
2040   return 1;
2041   }
2042 
2043 
2044 // Save changes, prompt for new filename
saveChanges()2045 FXbool TextWindow::saveChanges(){
2046   if(isModified()){
2047     FXuint answer=FXMessageBox::question(this,MBOX_YES_NO_CANCEL,tr("Unsaved Document"),tr("Save %s to file?"),getFilename().text());
2048     if(answer==MBOX_CLICKED_CANCEL) return false;
2049     if(answer==MBOX_CLICKED_YES){
2050       FXString file=getFilename();
2051       if(!isFilenameSet()){
2052         FXFileDialog savedialog(this,tr("Save Document"));
2053         savedialog.setSelectMode(SELECTFILE_ANY);
2054         savedialog.setAssociations(getApp()->associations,false);
2055         savedialog.setPatternList(getPatternList());
2056         savedialog.setCurrentPattern(getCurrentPattern());
2057         savedialog.setFilename(file);
2058         if(!savedialog.execute()) return false;
2059         setCurrentPattern(savedialog.getCurrentPattern());
2060         file=savedialog.getFilename();
2061         if(FXStat::exists(file)){
2062           if(MBOX_CLICKED_NO==FXMessageBox::question(this,MBOX_YES_NO,tr("Overwrite Document"),tr("Overwrite existing document: %s?"),file.text())) return false;
2063           }
2064         }
2065       if(!saveFile(file)){
2066         getApp()->beep();
2067         FXMessageBox::error(this,MBOX_OK,tr("Error Saving File"),tr("Unable to save file: %s"),file.text());
2068         }
2069       }
2070     }
2071   writeBookmarks(getFilename());
2072   writeView(getFilename());
2073   return true;
2074   }
2075 
2076 
2077 // Save
onCmdSave(FXObject * sender,FXSelector sel,void * ptr)2078 long TextWindow::onCmdSave(FXObject* sender,FXSelector sel,void* ptr){
2079   if(!isFilenameSet()) return onCmdSaveAs(sender,sel,ptr);
2080   if(!saveFile(getFilename())){
2081     getApp()->beep();
2082     FXMessageBox::error(this,MBOX_OK,tr("Error Saving File"),tr("Unable to save file: %s"),getFilename().text());
2083     }
2084   return 1;
2085   }
2086 
2087 
2088 // Save Update
onUpdSave(FXObject * sender,FXSelector,void *)2089 long TextWindow::onUpdSave(FXObject* sender,FXSelector,void*){
2090   sender->handle(this,isModified()?FXSEL(SEL_COMMAND,ID_ENABLE):FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
2091   return 1;
2092   }
2093 
2094 
2095 // Save As
onCmdSaveAs(FXObject *,FXSelector,void *)2096 long TextWindow::onCmdSaveAs(FXObject*,FXSelector,void*){
2097   FXFileDialog savedialog(this,tr("Save As"));
2098   FXString file=getFilename();
2099   savedialog.setSelectMode(SELECTFILE_ANY);
2100   savedialog.setAssociations(getApp()->associations,false);
2101   savedialog.setPatternList(getPatternList());
2102   savedialog.setCurrentPattern(getCurrentPattern());
2103   savedialog.setFilename(file);
2104   if(savedialog.execute()){
2105     setCurrentPattern(savedialog.getCurrentPattern());
2106     file=savedialog.getFilename();
2107     if(FXStat::exists(file)){
2108       if(MBOX_CLICKED_NO==FXMessageBox::question(this,MBOX_YES_NO,tr("Overwrite Document"),tr("Overwrite existing document: %s?"),file.text())) return 1;
2109       }
2110     if(!saveFile(file)){
2111       getApp()->beep();
2112       FXMessageBox::error(this,MBOX_OK,tr("Error Saving File"),tr("Unable to save file: %s"),file.text());
2113       }
2114     determineSyntax();
2115     }
2116   return 1;
2117   }
2118 
2119 
2120 // Save To
onCmdSaveTo(FXObject *,FXSelector,void *)2121 long TextWindow::onCmdSaveTo(FXObject*,FXSelector,void*){
2122   FXFileDialog savedialog(this,tr("Save To"));
2123   FXString file=getFilename();
2124   savedialog.setSelectMode(SELECTFILE_ANY);
2125   savedialog.setAssociations(getApp()->associations,false);
2126   savedialog.setPatternList(getPatternList());
2127   savedialog.setCurrentPattern(getCurrentPattern());
2128   savedialog.setFilename(file);
2129   if(savedialog.execute()){
2130     file=savedialog.getFilename();
2131     if(FXStat::exists(file)){
2132       if(MBOX_CLICKED_NO==FXMessageBox::question(this,MBOX_YES_NO,tr("Overwrite Document"),tr("Overwrite existing document: %s?"),file.text())) return 1;
2133       }
2134     if(!saveToFile(file)){
2135       getApp()->beep();
2136       FXMessageBox::error(this,MBOX_OK,tr("Error Saving To File"),tr("Unable to save to file: %s"),file.text());
2137       }
2138     }
2139   return 1;
2140   }
2141 
2142 
2143 // Close window
close(FXbool notify)2144 FXbool TextWindow::close(FXbool notify){
2145 
2146   // Prompt to save changes
2147   if(!saveChanges()) return false;
2148 
2149   // Save settings
2150   writeRegistry();
2151 
2152 /*
2153   // Reset as empty text window
2154   setFilename(getApp()->unique(FXPath::directory(filename)));
2155   setFilenameSet(false);
2156   editor->setText(FXString::null);
2157   undolist.clear();
2158   undolist.mark();
2159   clearBookmarks();
2160   setSyntax(NULL);
2161 */
2162 
2163   // Perform normal close stuff
2164   return FXMainWindow::close(notify);
2165   }
2166 
2167 
2168 // User clicks on one of the window menus
onCmdWindow(FXObject *,FXSelector sel,void *)2169 long TextWindow::onCmdWindow(FXObject*,FXSelector sel,void*){
2170   FXint which=FXSELID(sel)-ID_WINDOW_1;
2171   if(which<getApp()->windowlist.no()){
2172     getApp()->windowlist[which]->raise();
2173     getApp()->windowlist[which]->setFocus();
2174     }
2175   return 1;
2176   }
2177 
2178 
2179 // Update handler for window menus
onUpdWindow(FXObject * sender,FXSelector sel,void *)2180 long TextWindow::onUpdWindow(FXObject *sender,FXSelector sel,void*){
2181   FXint which=FXSELID(sel)-ID_WINDOW_1;
2182   if(which<getApp()->windowlist.no()){
2183     TextWindow *window=getApp()->windowlist[which];
2184     FXString string;
2185     if(which<9)
2186       string.format("&%d %s",which+1,window->getTitle().text());
2187     else
2188       string.format("1&0 %s",window->getTitle().text());
2189     sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_SETSTRINGVALUE),(void*)&string);
2190     if(window==getApp()->getActiveWindow())
2191       sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_CHECK),NULL);
2192     else
2193       sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_UNCHECK),NULL);
2194     sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_SHOW),NULL);
2195     }
2196   else{
2197     sender->handle(this,FXSEL(SEL_COMMAND,FXWindow::ID_HIDE),NULL);
2198     }
2199   return 1;
2200   }
2201 
2202 
2203 // Update title from current filename
onUpdate(FXObject * sender,FXSelector sel,void * ptr)2204 long TextWindow::onUpdate(FXObject* sender,FXSelector sel,void* ptr){
2205   FXMainWindow::onUpdate(sender,sel,ptr);
2206   FXString ttl=FXPath::name(getFilename());
2207   if(isModified()) ttl.append(tr(" (changed)"));
2208   FXString directory=FXPath::directory(getFilename());
2209   if(!directory.empty()) ttl.append(" - " + directory);
2210   setTitle(ttl);
2211   return 1;
2212   }
2213 
2214 
2215 // Print the text
onCmdPrint(FXObject *,FXSelector,void *)2216 long TextWindow::onCmdPrint(FXObject*,FXSelector,void*){
2217   FXPrintDialog dlg(this,tr("Print File"));
2218   FXPrinter printer;
2219   if(dlg.execute()){
2220     dlg.getPrinter(printer);
2221     FXTRACE((100,"Printer = %s\n",printer.name.text()));
2222     }
2223   return 1;
2224   }
2225 
2226 
2227 // Toggle file browser
onCmdToggleBrowser(FXObject *,FXSelector,void *)2228 long TextWindow::onCmdToggleBrowser(FXObject*,FXSelector,void*){
2229   if(treebox->shown()){
2230     treebox->hide();
2231     position(getX(),getY(),getWidth()-treebox->getWidth(),getHeight());
2232     }
2233   else{
2234     treebox->show();
2235     position(getX(),getY(),getWidth()+treebox->getWidth(),getHeight());
2236     }
2237   return 1;
2238   }
2239 
2240 
2241 // Toggle file browser
onUpdToggleBrowser(FXObject * sender,FXSelector,void *)2242 long TextWindow::onUpdToggleBrowser(FXObject* sender,FXSelector,void*){
2243   sender->handle(this,treebox->shown() ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
2244   return 1;
2245   }
2246 
2247 
2248 // Toggle hidden files display
onCmdToggleHidden(FXObject *,FXSelector,void *)2249 long TextWindow::onCmdToggleHidden(FXObject*,FXSelector,void*){
2250   dirlist->showHiddenFiles(!dirlist->showHiddenFiles());
2251   if(dirlist->getCurrentItem()){
2252     dirlist->makeItemVisible(dirlist->getCurrentItem());
2253     }
2254   return 1;
2255   }
2256 
2257 
2258 // Update toggle hidden files widget
onUpdToggleHidden(FXObject * sender,FXSelector,void *)2259 long TextWindow::onUpdToggleHidden(FXObject* sender,FXSelector,void*){
2260   sender->handle(this,dirlist->showHiddenFiles()?FXSEL(SEL_COMMAND,ID_CHECK):FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
2261   return 1;
2262   }
2263 
2264 /*******************************************************************************/
2265 
2266 // Save settings
onCmdSaveSettings(FXObject *,FXSelector,void *)2267 long TextWindow::onCmdSaveSettings(FXObject*,FXSelector,void*){
2268   writeRegistry();
2269   getApp()->reg().write();
2270   return 1;
2271   }
2272 
2273 
2274 // Toggle mode line parsing
onCmdModeline(FXObject *,FXSelector,void *)2275 long TextWindow::onCmdModeline(FXObject*,FXSelector,void*){
2276   modeline=!modeline;
2277   return 1;
2278   }
2279 
2280 
2281 // Update mode line parsing
onUpdModeline(FXObject * sender,FXSelector,void *)2282 long TextWindow::onUpdModeline(FXObject* sender,FXSelector,void*){
2283   sender->handle(this,modeline ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
2284   return 1;
2285   }
2286 
2287 
2288 // Toggle autoindent; we remember this value as the default
onCmdAutoIndent(FXObject *,FXSelector,void *)2289 long TextWindow::onCmdAutoIndent(FXObject*,FXSelector,void*){
2290   FXuint modebits=editor->getTextStyle()^TEXT_AUTOINDENT;
2291   editor->setTextStyle(modebits);
2292   autoindent=((modebits&TEXT_AUTOINDENT)!=0);
2293   return 1;
2294   }
2295 
2296 
2297 // Update autoindent; show indeterminate if default is different from current
onUpdAutoIndent(FXObject * sender,FXSelector,void *)2298 long TextWindow::onUpdAutoIndent(FXObject* sender,FXSelector,void*){
2299   FXbool ai=(editor->getTextStyle()&TEXT_AUTOINDENT)!=0;
2300   sender->handle(this,(autoindent!=ai) ? FXSEL(SEL_COMMAND,ID_UNKNOWN) : ai ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
2301   return 1;
2302   }
2303 
2304 
2305 // Change wrap columns; we remember this value as the default
onCmdWrapColumns(FXObject * sender,FXSelector,void *)2306 long TextWindow::onCmdWrapColumns(FXObject* sender,FXSelector,void*){
2307   sender->handle(this,FXSEL(SEL_COMMAND,ID_GETINTVALUE),(void*)&wrapcols);
2308   editor->setWrapColumns(wrapcols);
2309   return 1;
2310   }
2311 
2312 
2313 // Update wrap columns
onUpdWrapColumns(FXObject * sender,FXSelector,void *)2314 long TextWindow::onUpdWrapColumns(FXObject* sender,FXSelector,void*){
2315   FXint wrap=editor->getWrapColumns();
2316   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&wrap);
2317   return 1;
2318   }
2319 
2320 
2321 // Toggle wrap mode; we remember this value as the default
onCmdWrap(FXObject *,FXSelector,void *)2322 long TextWindow::onCmdWrap(FXObject*,FXSelector,void*){
2323   FXuint modebits=editor->getTextStyle()^TEXT_WORDWRAP;
2324   editor->setTextStyle(modebits);
2325   wrapping=((modebits&TEXT_WORDWRAP)!=0);
2326   return 1;
2327   }
2328 
2329 
2330 // Update toggle wrap mode
onUpdWrap(FXObject * sender,FXSelector,void *)2331 long TextWindow::onUpdWrap(FXObject* sender,FXSelector,void*){
2332   FXbool wr=(editor->getTextStyle()&TEXT_WORDWRAP)!=0;
2333   sender->handle(this,(wrapping!=wr) ? FXSEL(SEL_COMMAND,ID_UNKNOWN) : wr ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
2334   return 1;
2335   }
2336 
2337 
2338 // Toggle fixed wrap mode; we remember this value as the default
onCmdWrapFixed(FXObject *,FXSelector,void *)2339 long TextWindow::onCmdWrapFixed(FXObject*,FXSelector,void*){
2340   FXuint modebits=editor->getTextStyle()^TEXT_FIXEDWRAP;
2341   editor->setTextStyle(modebits);
2342   fixedwrap=((modebits&TEXT_FIXEDWRAP)!=0);
2343   return 1;
2344   }
2345 
2346 
2347 // Update toggle fixed wrap mode; show indeterminate if default is different from current
onUpdWrapFixed(FXObject * sender,FXSelector,void *)2348 long TextWindow::onUpdWrapFixed(FXObject* sender,FXSelector,void*){
2349   FXbool fw=(editor->getTextStyle()&TEXT_FIXEDWRAP)!=0;
2350   sender->handle(this,(fixedwrap!=fw) ? FXSEL(SEL_COMMAND,ID_UNKNOWN) : fw ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
2351   return 1;
2352   }
2353 
2354 
2355 // Change tab columns; we remember this value as the default
onCmdTabColumns(FXObject * sender,FXSelector,void *)2356 long TextWindow::onCmdTabColumns(FXObject* sender,FXSelector,void*){
2357   sender->handle(this,FXSEL(SEL_COMMAND,ID_GETINTVALUE),(void*)&tabcols);
2358   editor->setTabColumns(tabcols);
2359   return 1;
2360   }
2361 
2362 
2363 // Update tab columns
onUpdTabColumns(FXObject * sender,FXSelector,void *)2364 long TextWindow::onUpdTabColumns(FXObject* sender,FXSelector,void*){
2365   FXint tabs=editor->getTabColumns();
2366   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&tabs);
2367   return 1;
2368   }
2369 
2370 
2371 // Select tab columns; we remember this value as the default
onCmdTabSelect(FXObject *,FXSelector sel,void *)2372 long TextWindow::onCmdTabSelect(FXObject*,FXSelector sel,void*){
2373   tabcols=FXSELID(sel)-ID_TABSELECT_0;
2374   editor->setTabColumns(tabcols);
2375   return 1;
2376   }
2377 
2378 
2379 // Update select tab columns
onUpdTabSelect(FXObject * sender,FXSelector sel,void *)2380 long TextWindow::onUpdTabSelect(FXObject* sender,FXSelector sel,void*){
2381   FXint tabs=FXSELID(sel)-ID_TABSELECT_0;
2382   sender->handle(this,editor->getTabColumns()==tabs?FXSEL(SEL_COMMAND,ID_CHECK):FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
2383   return 1;
2384   }
2385 
2386 
2387 // Toggle insertion of tabs; we remember this value as the default
onCmdInsertTabs(FXObject *,FXSelector,void *)2388 long TextWindow::onCmdInsertTabs(FXObject*,FXSelector,void*){
2389   FXuint modebits=editor->getTextStyle()^TEXT_NO_TABS;
2390   editor->setTextStyle(modebits);
2391   hardtabs=((modebits&TEXT_NO_TABS)==0);
2392   return 1;
2393   }
2394 
2395 
2396 // Update insertion of tabs; show indeterminate if default is different from current
onUpdInsertTabs(FXObject * sender,FXSelector,void *)2397 long TextWindow::onUpdInsertTabs(FXObject* sender,FXSelector,void*){
2398   FXbool ht=(editor->getTextStyle()&TEXT_NO_TABS)==0;
2399   sender->handle(this,(hardtabs!=ht) ? FXSEL(SEL_COMMAND,ID_UNKNOWN) : ht ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
2400   return 1;
2401   }
2402 
2403 
2404 // Toggle show active background mode
onCmdShowActive(FXObject *,FXSelector,void *)2405 long TextWindow::onCmdShowActive(FXObject*,FXSelector,void*){
2406   editor->setTextStyle(editor->getTextStyle()^TEXT_SHOWACTIVE);
2407   return 1;
2408   }
2409 
2410 
2411 // Update show active background mode
onUpdShowActive(FXObject * sender,FXSelector,void *)2412 long TextWindow::onUpdShowActive(FXObject* sender,FXSelector,void*){
2413   sender->handle(this,(editor->getTextStyle()&TEXT_SHOWACTIVE) ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
2414   return 1;
2415   }
2416 
2417 
2418 // Toggle strip returns mode
onCmdStripReturns(FXObject *,FXSelector,void * ptr)2419 long TextWindow::onCmdStripReturns(FXObject*,FXSelector,void* ptr){
2420   stripcr=(FXbool)(FXuval)ptr;
2421   return 1;
2422   }
2423 
2424 
2425 // Update toggle strip returns mode
onUpdStripReturns(FXObject * sender,FXSelector,void *)2426 long TextWindow::onUpdStripReturns(FXObject* sender,FXSelector,void*){
2427   sender->handle(this,stripcr ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
2428   return 1;
2429   }
2430 
2431 
2432 // Enable warning if file changed externally
onCmdWarnChanged(FXObject *,FXSelector,void * ptr)2433 long TextWindow::onCmdWarnChanged(FXObject*,FXSelector,void* ptr){
2434   warnchanged=(FXbool)(FXuval)ptr;
2435   return 1;
2436   }
2437 
2438 
2439 // Update check button for warning
onUpdWarnChanged(FXObject * sender,FXSelector,void *)2440 long TextWindow::onUpdWarnChanged(FXObject* sender,FXSelector,void*){
2441   sender->handle(this,warnchanged ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
2442   return 1;
2443   }
2444 
2445 
2446 // Set initial size flag
onCmdUseInitialSize(FXObject *,FXSelector,void * ptr)2447 long TextWindow::onCmdUseInitialSize(FXObject*,FXSelector,void* ptr){
2448   initialsize=(FXbool)(FXuval)ptr;
2449   return 1;
2450   }
2451 
2452 
2453 // Update initial size flag
onUpdUseInitialSize(FXObject * sender,FXSelector,void *)2454 long TextWindow::onUpdUseInitialSize(FXObject* sender,FXSelector,void*){
2455   sender->handle(this,initialsize ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
2456   return 1;
2457   }
2458 
2459 
2460 // Remember this as the initial size
onCmdSetInitialSize(FXObject *,FXSelector,void *)2461 long TextWindow::onCmdSetInitialSize(FXObject*,FXSelector,void*){
2462   initialwidth=getWidth();
2463   initialheight=getHeight();
2464   return 1;
2465   }
2466 
2467 
2468 // Toggle strip spaces mode
onCmdStripSpaces(FXObject *,FXSelector,void * ptr)2469 long TextWindow::onCmdStripSpaces(FXObject*,FXSelector,void* ptr){
2470   stripsp=(FXbool)(FXuval)ptr;
2471   return 1;
2472   }
2473 
2474 
2475 // Update toggle strip spaces mode
onUpdStripSpaces(FXObject * sender,FXSelector,void *)2476 long TextWindow::onUpdStripSpaces(FXObject* sender,FXSelector,void*){
2477   sender->handle(this,stripsp ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
2478   return 1;
2479   }
2480 
2481 
2482 // Toggle append newline mode
onCmdAppendNewline(FXObject *,FXSelector,void * ptr)2483 long TextWindow::onCmdAppendNewline(FXObject*,FXSelector,void* ptr){
2484   appendnl=(FXbool)(FXuval)ptr;
2485   return 1;
2486   }
2487 
2488 
2489 // Update toggle append newline mode
onUpdAppendNewline(FXObject * sender,FXSelector,void *)2490 long TextWindow::onUpdAppendNewline(FXObject* sender,FXSelector,void*){
2491   sender->handle(this,appendnl ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
2492   return 1;
2493   }
2494 
2495 
2496 
2497 // Toggle append carriage return mode
onCmdAppendCarriageReturn(FXObject *,FXSelector,void * ptr)2498 long TextWindow::onCmdAppendCarriageReturn(FXObject*,FXSelector,void* ptr){
2499   appendcr=(FXbool)(FXuval)ptr;
2500   return 1;
2501   }
2502 
2503 
2504 // Update toggle append carriage return mode
onUpdAppendCarriageReturn(FXObject * sender,FXSelector,void *)2505 long TextWindow::onUpdAppendCarriageReturn(FXObject* sender,FXSelector,void*){
2506   sender->handle(this,appendcr ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
2507   return 1;
2508   }
2509 
2510 
2511 // Change line number column
onCmdLineNumbers(FXObject * sender,FXSelector,void *)2512 long TextWindow::onCmdLineNumbers(FXObject* sender,FXSelector,void*){
2513   FXint cols;
2514   sender->handle(this,FXSEL(SEL_COMMAND,ID_GETINTVALUE),(void*)&cols);
2515   editor->setBarColumns(cols);
2516   return 1;
2517   }
2518 
2519 
2520 // Update line number column
onUpdLineNumbers(FXObject * sender,FXSelector,void *)2521 long TextWindow::onUpdLineNumbers(FXObject* sender,FXSelector,void*){
2522   FXint cols=editor->getBarColumns();
2523   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&cols);
2524   return 1;
2525   }
2526 
2527 
2528 // Set brace matching
onCmdBraceMatch(FXObject *,FXSelector,void *)2529 long TextWindow::onCmdBraceMatch(FXObject*,FXSelector,void*){
2530   editor->setTextStyle(editor->getTextStyle()^TEXT_SHOWMATCH);
2531   return 1;
2532   }
2533 
2534 
2535 // Update brace matching
onUpdBraceMatch(FXObject * sender,FXSelector,void *)2536 long TextWindow::onUpdBraceMatch(FXObject* sender,FXSelector,void*){
2537   sender->handle(this,(editor->getTextStyle()&TEXT_SHOWMATCH) ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
2538   return 1;
2539   }
2540 
2541 
2542 // Set brace match time
onCmdBraceMatchTime(FXObject * sender,FXSelector,void *)2543 long TextWindow::onCmdBraceMatchTime(FXObject* sender,FXSelector,void*){
2544   FXTime value;
2545   sender->handle(this,FXSEL(SEL_COMMAND,ID_GETLONGVALUE),(void*)&value);
2546   editor->setHiliteMatchTime(value*1000000);
2547   return 1;
2548   }
2549 
2550 
2551 // Update brace match time
onUpdBraceMatchTime(FXObject * sender,FXSelector,void *)2552 long TextWindow::onUpdBraceMatchTime(FXObject* sender,FXSelector,void*){
2553   FXTime value=editor->getHiliteMatchTime();
2554   if(value<forever){
2555     value/=1000000;
2556     sender->handle(this,FXSEL(SEL_COMMAND,ID_SETLONGVALUE),(void*)&value);
2557     }
2558   else{
2559     sender->handle(this,FXSEL(SEL_COMMAND,ID_SETVALUE),(void*)"forever");
2560     }
2561   return 1;
2562   }
2563 
2564 
2565 // Set brace match to remain highlighted forever
onCmdBraceMatchStay(FXObject *,FXSelector,void *)2566 long TextWindow::onCmdBraceMatchStay(FXObject*,FXSelector,void*){
2567   FXTime value=editor->getHiliteMatchTime();
2568   value=(value<forever) ? forever : 2000000000;
2569   editor->setHiliteMatchTime(value);
2570   return 1;
2571   }
2572 
2573 
2574 // Update brace match remain highlighted forever
onUpdBraceMatchStay(FXObject * sender,FXSelector,void *)2575 long TextWindow::onUpdBraceMatchStay(FXObject* sender,FXSelector,void*){
2576   FXTime value=editor->getHiliteMatchTime();
2577   sender->handle(this,(value==forever) ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
2578   return 1;
2579   }
2580 
2581 
2582 // Change word delimiters
onCmdDelimiters(FXObject * sender,FXSelector,void *)2583 long TextWindow::onCmdDelimiters(FXObject* sender,FXSelector,void*){
2584   sender->handle(this,FXSEL(SEL_COMMAND,ID_GETSTRINGVALUE),(void*)&delimiters);
2585   editor->setDelimiters(delimiters.text());
2586   return 1;
2587   }
2588 
2589 
2590 // Update word delimiters
onUpdDelimiters(FXObject * sender,FXSelector,void *)2591 long TextWindow::onUpdDelimiters(FXObject* sender,FXSelector,void*){
2592   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&delimiters);
2593   return 1;
2594   }
2595 
2596 
2597 // Update box for overstrike mode display
onUpdOverstrike(FXObject * sender,FXSelector,void *)2598 long TextWindow::onUpdOverstrike(FXObject* sender,FXSelector,void*){
2599   FXString mode((editor->getTextStyle()&TEXT_OVERSTRIKE)?"OVR":"INS");
2600   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&mode);
2601   return 1;
2602   }
2603 
2604 
2605 // Update box for readonly display
onUpdReadOnly(FXObject * sender,FXSelector,void *)2606 long TextWindow::onUpdReadOnly(FXObject* sender,FXSelector,void*){
2607   FXString rw((editor->getTextStyle()&TEXT_READONLY)?"RO":"RW");
2608   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&rw);
2609   return 1;
2610   }
2611 
2612 
2613 // Update box for tabmode display
onUpdTabMode(FXObject * sender,FXSelector,void *)2614 long TextWindow::onUpdTabMode(FXObject* sender,FXSelector,void*){
2615   FXString tab((editor->getTextStyle()&TEXT_NO_TABS)?"EMT":"TAB");
2616   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&tab);
2617   return 1;
2618   }
2619 
2620 
2621 // Update box for size display
onUpdNumRows(FXObject * sender,FXSelector,void *)2622 long TextWindow::onUpdNumRows(FXObject* sender,FXSelector,void*){
2623   FXuint size=editor->getNumRows();
2624   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&size);
2625   return 1;
2626   }
2627 
2628 
2629 // Set scroll wheel lines (Mathew Robertson <mathew@optushome.com.au>)
onCmdWheelAdjust(FXObject * sender,FXSelector,void *)2630 long TextWindow::onCmdWheelAdjust(FXObject* sender,FXSelector,void*){
2631   FXuint value;
2632   sender->handle(this,FXSEL(SEL_COMMAND,ID_GETINTVALUE),(void*)&value);
2633   getApp()->setWheelLines(value);
2634   return 1;
2635   }
2636 
2637 
2638 // Update scroll wheel lines
onUpdWheelAdjust(FXObject * sender,FXSelector,void *)2639 long TextWindow::onUpdWheelAdjust(FXObject* sender,FXSelector,void*){
2640   FXuint value=getApp()->getWheelLines();
2641   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&value);
2642   return 1;
2643   }
2644 
2645 
2646 /*******************************************************************************/
2647 
2648 
2649 // Change text color
onCmdTextForeColor(FXObject *,FXSelector,void * ptr)2650 long TextWindow::onCmdTextForeColor(FXObject*,FXSelector,void* ptr){
2651   editor->setTextColor((FXColor)(FXuval)ptr);
2652   return 1;
2653   }
2654 
2655 // Update text color
onUpdTextForeColor(FXObject * sender,FXSelector,void *)2656 long TextWindow::onUpdTextForeColor(FXObject* sender,FXSelector,void*){
2657   FXColor color=editor->getTextColor();
2658   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&color);
2659   return 1;
2660   }
2661 
2662 
2663 // Change text background color
onCmdTextBackColor(FXObject *,FXSelector,void * ptr)2664 long TextWindow::onCmdTextBackColor(FXObject*,FXSelector,void* ptr){
2665   editor->setBackColor((FXColor)(FXuval)ptr);
2666   return 1;
2667   }
2668 
2669 // Update background color
onUpdTextBackColor(FXObject * sender,FXSelector,void *)2670 long TextWindow::onUpdTextBackColor(FXObject* sender,FXSelector,void*){
2671   FXColor color=editor->getBackColor();
2672   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&color);
2673   return 1;
2674   }
2675 
2676 
2677 // Change selected text foreground color
onCmdTextSelForeColor(FXObject *,FXSelector,void * ptr)2678 long TextWindow::onCmdTextSelForeColor(FXObject*,FXSelector,void* ptr){
2679   editor->setSelTextColor((FXColor)(FXuval)ptr);
2680   return 1;
2681   }
2682 
2683 
2684 // Update selected text foregoround color
onUpdTextSelForeColor(FXObject * sender,FXSelector,void *)2685 long TextWindow::onUpdTextSelForeColor(FXObject* sender,FXSelector,void*){
2686   FXColor color=editor->getSelTextColor();
2687   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&color);
2688   return 1;
2689   }
2690 
2691 
2692 // Change selected text background color
onCmdTextSelBackColor(FXObject *,FXSelector,void * ptr)2693 long TextWindow::onCmdTextSelBackColor(FXObject*,FXSelector,void* ptr){
2694   editor->setSelBackColor((FXColor)(FXuval)ptr);
2695   return 1;
2696   }
2697 
2698 // Update selected text background color
onUpdTextSelBackColor(FXObject * sender,FXSelector,void *)2699 long TextWindow::onUpdTextSelBackColor(FXObject* sender,FXSelector,void*){
2700   FXColor color=editor->getSelBackColor();
2701   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&color);
2702   return 1;
2703   }
2704 
2705 
2706 // Change hilight text color
onCmdTextHiliteForeColor(FXObject *,FXSelector,void * ptr)2707 long TextWindow::onCmdTextHiliteForeColor(FXObject*,FXSelector,void* ptr){
2708   editor->setHiliteTextColor((FXColor)(FXuval)ptr);
2709   return 1;
2710   }
2711 
2712 // Update hilight text color
onUpdTextHiliteForeColor(FXObject * sender,FXSelector,void *)2713 long TextWindow::onUpdTextHiliteForeColor(FXObject* sender,FXSelector,void*){
2714   FXColor color=editor->getHiliteTextColor();
2715   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&color);
2716   return 1;
2717   }
2718 
2719 
2720 // Change hilight text background color
onCmdTextHiliteBackColor(FXObject *,FXSelector,void * ptr)2721 long TextWindow::onCmdTextHiliteBackColor(FXObject*,FXSelector,void* ptr){
2722   editor->setHiliteBackColor((FXColor)(FXuval)ptr);
2723   return 1;
2724   }
2725 
2726 // Update hilight text background color
onUpdTextHiliteBackColor(FXObject * sender,FXSelector,void *)2727 long TextWindow::onUpdTextHiliteBackColor(FXObject* sender,FXSelector,void*){
2728   FXColor color=editor->getHiliteBackColor();
2729   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&color);
2730   return 1;
2731   }
2732 
2733 
2734 // Change active text background color
onCmdTextActBackColor(FXObject *,FXSelector,void * ptr)2735 long TextWindow::onCmdTextActBackColor(FXObject*,FXSelector,void* ptr){
2736   editor->setActiveBackColor((FXColor)(FXuval)ptr);
2737   return 1;
2738   }
2739 
2740 // Update active text background color
onUpdTextActBackColor(FXObject * sender,FXSelector,void *)2741 long TextWindow::onUpdTextActBackColor(FXObject* sender,FXSelector,void*){
2742   FXColor color=editor->getActiveBackColor();
2743   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&color);
2744   return 1;
2745   }
2746 
2747 
2748 // Change cursor color
onCmdTextCursorColor(FXObject *,FXSelector,void * ptr)2749 long TextWindow::onCmdTextCursorColor(FXObject*,FXSelector,void* ptr){
2750   editor->setCursorColor((FXColor)(FXuval)ptr);
2751   return 1;
2752   }
2753 
2754 // Update cursor color
onUpdTextCursorColor(FXObject * sender,FXSelector,void *)2755 long TextWindow::onUpdTextCursorColor(FXObject* sender,FXSelector,void*){
2756   FXColor color=editor->getCursorColor();
2757   sender->handle(sender,FXSEL(SEL_COMMAND,FXWindow::ID_SETINTVALUE),(void*)&color);
2758   return 1;
2759   }
2760 
2761 
2762 // Change line numbers background color
onCmdTextBarColor(FXObject *,FXSelector,void * ptr)2763 long TextWindow::onCmdTextBarColor(FXObject*,FXSelector,void* ptr){
2764   editor->setBarColor((FXColor)(FXuval)ptr);
2765   return 1;
2766   }
2767 
2768 
2769 // Update line numbers background color
onUpdTextBarColor(FXObject * sender,FXSelector,void *)2770 long TextWindow::onUpdTextBarColor(FXObject* sender,FXSelector,void*){
2771   FXColor color=editor->getBarColor();
2772   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&color);
2773   return 1;
2774   }
2775 
2776 // Change line numbers color
onCmdTextNumberColor(FXObject *,FXSelector,void * ptr)2777 long TextWindow::onCmdTextNumberColor(FXObject*,FXSelector,void* ptr){
2778   editor->setNumberColor((FXColor)(FXuval)ptr);
2779   return 1;
2780   }
2781 
2782 
2783 // Update line numbers color
onUpdTextNumberColor(FXObject * sender,FXSelector,void *)2784 long TextWindow::onUpdTextNumberColor(FXObject* sender,FXSelector,void*){
2785   FXColor color=editor->getNumberColor();
2786   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&color);
2787   return 1;
2788   }
2789 
2790 
2791 // Change both tree background color
onCmdDirBackColor(FXObject *,FXSelector,void * ptr)2792 long TextWindow::onCmdDirBackColor(FXObject*,FXSelector,void* ptr){
2793   dirlist->setBackColor((FXColor)(FXuval)ptr);
2794   return 1;
2795   }
2796 
2797 
2798 // Update background color
onUpdDirBackColor(FXObject * sender,FXSelector,void *)2799 long TextWindow::onUpdDirBackColor(FXObject* sender,FXSelector,void*){
2800   FXColor color=dirlist->getBackColor();
2801   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&color);
2802   return 1;
2803   }
2804 
2805 
2806 // Change both text and tree selected background color
onCmdDirSelBackColor(FXObject *,FXSelector,void * ptr)2807 long TextWindow::onCmdDirSelBackColor(FXObject*,FXSelector,void* ptr){
2808   dirlist->setSelBackColor((FXColor)(FXuval)ptr);
2809   return 1;
2810   }
2811 
2812 // Update selected background color
onUpdDirSelBackColor(FXObject * sender,FXSelector,void *)2813 long TextWindow::onUpdDirSelBackColor(FXObject* sender,FXSelector,void*){
2814   FXColor color=dirlist->getSelBackColor();
2815   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&color);
2816   return 1;
2817   }
2818 
2819 
2820 // Change both text and tree text color
onCmdDirForeColor(FXObject *,FXSelector,void * ptr)2821 long TextWindow::onCmdDirForeColor(FXObject*,FXSelector,void* ptr){
2822   dirlist->setTextColor((FXColor)(FXuval)ptr);
2823   return 1;
2824   }
2825 
2826 // Forward GUI update to text widget
onUpdDirForeColor(FXObject * sender,FXSelector,void *)2827 long TextWindow::onUpdDirForeColor(FXObject* sender,FXSelector,void*){
2828   FXColor color=dirlist->getTextColor();
2829   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&color);
2830   return 1;
2831   }
2832 
2833 
2834 // Change both text and tree
onCmdDirSelForeColor(FXObject *,FXSelector,void * ptr)2835 long TextWindow::onCmdDirSelForeColor(FXObject*,FXSelector,void* ptr){
2836   dirlist->setSelTextColor((FXColor)(FXuval)ptr);
2837   return 1;
2838   }
2839 
2840 
2841 // Forward GUI update to text widget
onUpdDirSelForeColor(FXObject * sender,FXSelector,void *)2842 long TextWindow::onUpdDirSelForeColor(FXObject* sender,FXSelector,void*){
2843   FXColor color=dirlist->getSelTextColor();
2844   sender->handle(sender,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&color);
2845   return 1;
2846   }
2847 
2848 
2849 // Change both text and tree
onCmdDirLineColor(FXObject *,FXSelector,void * ptr)2850 long TextWindow::onCmdDirLineColor(FXObject*,FXSelector,void* ptr){
2851   dirlist->setLineColor((FXColor)(FXuval)ptr);
2852   return 1;
2853   }
2854 
2855 
2856 // Forward GUI update to text widget
onUpdDirLineColor(FXObject * sender,FXSelector,void *)2857 long TextWindow::onUpdDirLineColor(FXObject* sender,FXSelector,void*){
2858   FXColor color=dirlist->getLineColor();
2859   sender->handle(sender,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&color);
2860   return 1;
2861   }
2862 
2863 
2864 // Change the pattern
onCmdFilter(FXObject *,FXSelector,void * ptr)2865 long TextWindow::onCmdFilter(FXObject*,FXSelector,void* ptr){
2866   dirlist->setPattern(FXFileSelector::patternFromText((FXchar*)ptr));
2867   dirlist->makeItemVisible(dirlist->getCurrentItem());
2868   return 1;
2869   }
2870 
2871 
2872 // Change search paths
onCmdSearchPaths(FXObject * sender,FXSelector,void *)2873 long TextWindow::onCmdSearchPaths(FXObject* sender,FXSelector,void*){
2874   sender->handle(this,FXSEL(SEL_COMMAND,ID_GETSTRINGVALUE),(void*)&searchpaths);
2875   return 1;
2876   }
2877 
2878 
2879 // Update search paths
onUpdSearchPaths(FXObject * sender,FXSelector,void *)2880 long TextWindow::onUpdSearchPaths(FXObject* sender,FXSelector,void*){
2881   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&searchpaths);
2882   return 1;
2883   }
2884 
2885 
2886 // Find in files
onCmdFindInFiles(FXObject *,FXSelector,void *)2887 long TextWindow::onCmdFindInFiles(FXObject*,FXSelector,void*){
2888   FindInFiles *findwindow=new FindInFiles(getApp());
2889   findwindow->setPatternList(getPatternList());
2890   findwindow->setDirectory(FXPath::directory(getFilename()));
2891   findwindow->setSearchText(searchstring);
2892   findwindow->create();
2893   findwindow->show(PLACEMENT_CURSOR);
2894   return 1;
2895   }
2896 
2897 
2898 /*******************************************************************************/
2899 
2900 // Evaluate expression
onCmdExpression(FXObject *,FXSelector,void *)2901 long TextWindow::onCmdExpression(FXObject*,FXSelector,void*){
2902   FXString string(editor->getSelectedText());
2903   FXExpression expression;
2904   if(expression.parse(string)==FXExpression::ErrOK){
2905     FXString result(FXString::value(expression.evaluate(),15,2));
2906     editor->replaceSelection(result,true);
2907     return 1;
2908     }
2909   getApp()->beep();
2910   return 1;
2911   }
2912 
2913 
2914 // Update evaluate expression; ensure that no more than one line is selected
onUpdExpression(FXObject * sender,FXSelector,void *)2915 long TextWindow::onUpdExpression(FXObject* sender,FXSelector,void*){
2916   if(editor->getSelStartPos()<editor->getSelEndPos() && editor->getSelEndPos()<=editor->lineEnd(editor->getSelStartPos())){
2917     FXString string(editor->getSelectedText());
2918     FXExpression expression;
2919     if(expression.parse(string)==FXExpression::ErrOK){
2920       sender->handle(this,FXSEL(SEL_COMMAND,ID_ENABLE),NULL);
2921       return 1;
2922       }
2923     }
2924   sender->handle(this,FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
2925   return 1;
2926   }
2927 
2928 /*******************************************************************************/
2929 
2930 // Encode URL characters
onCmdURLEncode(FXObject *,FXSelector,void *)2931 long TextWindow::onCmdURLEncode(FXObject*,FXSelector,void*){
2932   FXString string(editor->getSelectedText());
2933   editor->replaceSelection(FXURL::encode(string,"<>#%{}|^~[]`\"\\?$&'*,;= "),true);
2934   return 1;
2935   }
2936 
2937 // Decode URL characters
onCmdURLDecode(FXObject *,FXSelector,void *)2938 long TextWindow::onCmdURLDecode(FXObject*,FXSelector,void*){
2939   FXString string(editor->getSelectedText());
2940   editor->replaceSelection(FXURL::decode(string),true);
2941   return 1;
2942   }
2943 
2944 
2945 // Enable url decode/encode if single line
onUpdURLCoding(FXObject * sender,FXSelector,void *)2946 long TextWindow::onUpdURLCoding(FXObject* sender,FXSelector,void*){
2947   FXbool onelineselected=editor->getSelStartPos()<editor->getSelEndPos() && editor->getSelEndPos()<=editor->lineEnd(editor->getSelStartPos());
2948   sender->handle(this,onelineselected?FXSEL(SEL_COMMAND,ID_ENABLE):FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
2949   return 1;
2950   }
2951 
2952 /*******************************************************************************/
2953 
2954 // Start shell command
startCommand(const FXString & command,const FXString & input)2955 FXbool TextWindow::startCommand(const FXString& command,const FXString& input){
2956   if(!shellCommand){
2957     shellCommand=new ShellCommand(getApp(),this,FXSEL(SEL_COMMAND,ID_SHELL_OUTPUT),FXSEL(SEL_COMMAND,ID_SHELL_ERROR),FXSEL(SEL_COMMAND,ID_SHELL_DONE));
2958     shellCommand->setInput(input);
2959     if(!shellCommand->start(command)){
2960       FXMessageBox::error(this,MBOX_OK,tr("Command Error"),tr("Unable to execute command: %s"),command.text());
2961       delete shellCommand;
2962       shellCommand=NULL;
2963       return false;
2964       }
2965     undolist.begin(new FXCommandGroup);
2966     getApp()->beginWaitCursor();
2967     logger->clearText();
2968     return true;
2969     }
2970   return false;
2971   }
2972 
2973 
2974 // Stop shell command
stopCommand()2975 FXbool TextWindow::stopCommand(){
2976   if(shellCommand){
2977     undolist.end();
2978     getApp()->endWaitCursor();
2979     if(!showlogger){
2980       loggerframe->hide();
2981       loggerframe->recalc();
2982       }
2983     shellCommand->cancel();
2984     delete shellCommand;
2985     shellCommand=NULL;
2986     return true;
2987     }
2988   return false;
2989   }
2990 
2991 
2992 // Done with command
doneCommand()2993 FXbool TextWindow::doneCommand(){
2994   if(shellCommand){
2995     undolist.end();
2996     getApp()->endWaitCursor();
2997     delete shellCommand;
2998     shellCommand=NULL;
2999     return true;
3000     }
3001   return false;
3002   }
3003 
3004 
3005 // Shell command dialog
onCmdShellDialog(FXObject *,FXSelector,void *)3006 long TextWindow::onCmdShellDialog(FXObject*,FXSelector,void*){
3007   if(!shellCommand){
3008     FXInputDialog dialog(this,tr("Execute Command"),tr("&Execute shell command:"),NULL,INPUTDIALOG_STRING,0,0,400,0);
3009     if(dialog.execute(PLACEMENT_OWNER)){
3010 
3011       // Get command
3012       FXString command=dialog.getText();
3013 
3014       // Output goes to insertion point
3015       replaceStart=replaceEnd=editor->getCursorPos();
3016 
3017       // Start
3018       startCommand(command);
3019       }
3020     }
3021   return 1;
3022   }
3023 
3024 
3025 // Update command dialog
onUpdShellDialog(FXObject * sender,FXSelector,void *)3026 long TextWindow::onUpdShellDialog(FXObject* sender,FXSelector,void*){
3027   sender->handle(this,!shellCommand?FXSEL(SEL_COMMAND,ID_ENABLE):FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
3028   return 1;
3029   }
3030 
3031 
3032 // Filter selection through shell command
onCmdShellFilter(FXObject *,FXSelector,void *)3033 long TextWindow::onCmdShellFilter(FXObject*,FXSelector,void*){
3034   if(!shellCommand){
3035     FXInputDialog dialog(this,tr("Filter Selection"),tr("&Filter selection with shell command:"),NULL,INPUTDIALOG_STRING,0,0,400,0);
3036     if(dialog.execute(PLACEMENT_OWNER)){
3037 
3038       // Get command
3039       FXString command=dialog.getText();
3040       FXString selection;
3041 
3042       // Get selection
3043       replaceStart=editor->getSelStartPos();
3044       replaceEnd=editor->getSelEndPos();
3045       editor->extractText(selection,replaceStart,replaceEnd-replaceStart);
3046 
3047       // Start
3048       startCommand(command,selection);
3049       }
3050     }
3051   return 1;
3052   }
3053 
3054 
3055 // Update filter selection
onUpdShellFilter(FXObject * sender,FXSelector,void *)3056 long TextWindow::onUpdShellFilter(FXObject* sender,FXSelector,void*){
3057   sender->handle(this,!shellCommand && editor->hasSelection()?FXSEL(SEL_COMMAND,ID_ENABLE):FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
3058   return 1;
3059   }
3060 
3061 
3062 // Cancel shell command
onCmdShellCancel(FXObject *,FXSelector,void *)3063 long TextWindow::onCmdShellCancel(FXObject*,FXSelector,void*){
3064   stopCommand();
3065   return 1;
3066   }
3067 
3068 
3069 // Update shell command
onUpdShellCancel(FXObject * sender,FXSelector,void *)3070 long TextWindow::onUpdShellCancel(FXObject* sender,FXSelector,void*){
3071   sender->handle(this,shellCommand?FXSEL(SEL_COMMAND,ID_ENABLE):FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
3072   return 1;
3073   }
3074 
3075 
3076 // Output from shell
onCmdShellOutput(FXObject *,FXSelector,void * ptr)3077 long TextWindow::onCmdShellOutput(FXObject*,FXSelector,void* ptr){
3078   FXTRACE((100,"TextWindow::onCmdShellOutput\n"));
3079   const FXchar* string=(const FXchar*)ptr;
3080   FXint len=strlen(string);
3081   if(replaceStart>editor->getLength()) replaceStart=editor->getLength();
3082   if(replaceEnd>editor->getLength()) replaceEnd=editor->getLength();
3083   editor->replaceText(replaceStart,replaceEnd-replaceStart,string,len,true);
3084   replaceStart=replaceStart+len;
3085   replaceEnd=replaceStart;
3086   editor->setCursorPos(replaceEnd);
3087   editor->makePositionVisible(replaceEnd);
3088   return 1;
3089   }
3090 
3091 
3092 // Shell command has error
onCmdShellError(FXObject *,FXSelector,void * ptr)3093 long TextWindow::onCmdShellError(FXObject*,FXSelector,void* ptr){
3094   FXTRACE((100,"TextWindow::onCmdShellError\n"));
3095   const FXchar* string=(const FXchar*)ptr;
3096   FXint len=strlen(string);
3097   showlogger=loggerframe->shown();
3098   if(!showlogger){
3099     loggerframe->show();
3100     loggerframe->recalc();
3101     }
3102   logger->appendText(string,len,true);
3103   logger->setCursorPos(logger->getLength());
3104   logger->makePositionVisible(logger->getLength());
3105   return 1;
3106   }
3107 
3108 
3109 // Shell command is done
onCmdShellDone(FXObject *,FXSelector,void *)3110 long TextWindow::onCmdShellDone(FXObject*,FXSelector,void*){
3111   FXTRACE((100,"TextWindow::onCmdShellDone\n"));
3112   doneCommand();
3113   return 1;
3114   }
3115 
3116 /*******************************************************************************/
3117 
3118 // Goto line number
onCmdGotoLine(FXObject *,FXSelector,void *)3119 long TextWindow::onCmdGotoLine(FXObject*,FXSelector,void*){
3120   FXGIFIcon dialogicon(getApp(),goto_gif);
3121   FXint row=editor->getCursorRow()+1;
3122   if(FXInputDialog::getInteger(row,this,tr("Goto Line"),tr("&Goto line number:"),&dialogicon,1,2147483647)){
3123     editor->setCursorRow(row-1,true);
3124     editor->makePositionVisible(editor->getCursorPos());
3125     }
3126   return 1;
3127   }
3128 
3129 
3130 // Goto selected line number
onCmdGotoSelected(FXObject *,FXSelector,void *)3131 long TextWindow::onCmdGotoSelected(FXObject*,FXSelector,void*){
3132   FXString string;
3133   if(getDNDData(FROM_SELECTION,stringType,string)){
3134     FXint row=0,s;
3135     if((s=string.find_first_of("0123456789"))>=0){
3136       while(Ascii::isDigit(string[s])){
3137         row=row*10+Ascii::digitValue(string[s]);
3138         s++;
3139         }
3140       if(1<=row){
3141         editor->setCursorRow(row-1,true);
3142         editor->makePositionVisible(editor->getCursorPos());
3143         return 1;
3144         }
3145       }
3146     }
3147   getApp()->beep();
3148   return 1;
3149   }
3150 
3151 /*******************************************************************************/
3152 
3153 // Check if the selection (if any) matches the pattern
matchesSelection(const FXString & string,FXint * beg,FXint * end,FXuint flgs,FXint npar) const3154 FXbool TextWindow::matchesSelection(const FXString& string,FXint* beg,FXint* end,FXuint flgs,FXint npar) const {
3155   FXint selstart=editor->getSelStartPos();
3156   FXint selend=editor->getSelEndPos();
3157   if((selstart<selend) && (0<npar)){
3158     if(editor->findText(string,beg,end,selstart,flgs&~(SEARCH_FORWARD|SEARCH_BACKWARD),npar)){
3159       return (beg[0]==selstart) && (end[0]==selend);
3160       }
3161     }
3162   return false;
3163   }
3164 
3165 
3166 // Search text
onCmdSearch(FXObject *,FXSelector,void *)3167 long TextWindow::onCmdSearch(FXObject*,FXSelector,void*){
3168   FXTRACE((100,"TextWindow::onCmdSearch()\n"));
3169   FXGIFIcon dialogicon(getApp(),searchicon_gif);
3170   FXSearchDialog searchdialog(this,tr("Search"),&dialogicon);
3171   FXint    beg[10],end[10],pos,code;
3172   FXuint   placement=PLACEMENT_OWNER;
3173   FXString findstring;
3174   FXuint   findflags;
3175 
3176   // Start the search
3177   setStatusMessage(tr("Search for a string in the file."));
3178 
3179   // Start with same flags as last time
3180 //  searchdialog.setSearchMode(searchflags);
3181 //  searchdialog.setSearchText(searchstring);
3182 
3183   // First time, throw dialog over window
3184   while((code=searchdialog.execute(placement))!=FXSearchDialog::DONE){
3185 
3186     // User may have moved the panel
3187     placement=PLACEMENT_DEFAULT;
3188 
3189     // Grab the search parameters
3190 //    searchstring=searchdialog.getSearchText();
3191 //    searchflags=searchdialog.getSearchMode();
3192     findstring=searchdialog.getSearchText();
3193     findflags=searchdialog.getSearchMode();
3194 
3195     // If search string matches the selection, start from the end (or begin
3196     // when seaching backwards) of the selection.  Otherwise proceed from the
3197     // cursor position.
3198     pos=editor->getCursorPos();
3199     if(matchesSelection(findstring,beg,end,findflags,10)){
3200       pos=(findflags&SEARCH_BACKWARD) ? beg[0]-1 : end[0];
3201       }
3202 
3203     // Search the text
3204     if(editor->findText(findstring,beg,end,pos,findflags,10)){
3205 
3206       // Feed back success, search box turns green
3207       setStatusMessage(tr("String found!"));
3208       searchdialog.setSearchTextColor(FXRGB(128,255,128));
3209 
3210       // Flag a wraparound the text
3211       if(findflags&SEARCH_BACKWARD){
3212         if(pos<=beg[0]){ setStatusMessage(tr("Search wrapped around.")); }
3213         }
3214       else{
3215         if(beg[0]<pos){ setStatusMessage(tr("Search wrapped around.")); }
3216         }
3217 
3218       // Beep if same location in buffer
3219       if((beg[0]==editor->getSelStartPos()) && (end[0]==editor->getSelEndPos())){
3220         getApp()->beep();
3221         }
3222 
3223       // Select new text
3224       editor->setAnchorPos(beg[0]);
3225       editor->moveCursorAndSelect(end[0],FXText::SelectChars,true);
3226       }
3227     else{
3228 
3229       // Feedback failure, search box turns red
3230       setStatusMessage(tr("String not found!"));
3231       searchdialog.setSearchTextColor(FXRGB(255,128,128));
3232       getApp()->beep();
3233       }
3234     }
3235 
3236   // Restore normal message
3237   setStatusMessage(tr("Ready."));
3238   return 1;
3239   }
3240 
3241 
3242 // Substitute algorithm
substitute(const FXString & original,const FXString & replace,FXint * beg,FXint * end,FXint npar)3243 static FXString substitute(const FXString& original,const FXString& replace,FXint* beg,FXint* end,FXint npar){
3244   FXint adjbeg[10],adjend[10],i;
3245   for(i=0; i<npar; ++i){
3246     adjbeg[i]=beg[i]-beg[0];
3247     adjend[i]=end[i]-beg[0];
3248     }
3249   return FXRex::substitute(original,adjbeg,adjend,replace,npar);
3250   }
3251 
3252 
3253 // Replace text
onCmdReplace(FXObject *,FXSelector,void *)3254 long TextWindow::onCmdReplace(FXObject*,FXSelector,void*){
3255   FXTRACE((100,"TextWindow::onCmdReplace()\n"));
3256   FXGIFIcon dialogicon(getApp(),searchicon_gif);
3257   FXReplaceDialog replacedialog(this,tr("Replace"),&dialogicon);
3258   FXint    beg[10],end[10],pos,finish,fm,to,code;
3259   FXuint   placement=PLACEMENT_OWNER;
3260   FXString originalvalue;
3261   FXString findstring;
3262   FXString replacestring;
3263   FXString replacevalue;
3264   FXuint   findflags;
3265   FXbool   found;
3266 
3267   // Start the search/replace
3268   setStatusMessage(tr("Search and replace strings in the file."));
3269 
3270   // Start with same flags as last time
3271 //  replacedialog.setSearchMode(searchflags);
3272 //  replacedialog.setSearchText(searchstring);
3273 //  replacedialog.setReplaceText(searchstring);
3274 
3275   // First time, throw dialog over window
3276   while((code=replacedialog.execute(placement))!=FXReplaceDialog::DONE){
3277 
3278     // User may have moved the panel
3279     placement=PLACEMENT_DEFAULT;
3280 
3281     // Grab the search parameters
3282 //    searchstring=replacedialog.getSearchText();
3283 //    replacestring=replacedialog.getReplaceText();
3284 //    searchflags=replacedialog.getSearchMode();
3285 //    replacevalue=FXString::null;
3286 
3287     findstring=replacedialog.getSearchText();
3288     findflags=replacedialog.getSearchMode();
3289     replacestring=replacedialog.getReplaceText();
3290     replacevalue=FXString::null;
3291 
3292     // Search or replace one instance
3293     if((code==FXReplaceDialog::SEARCH) || (code==FXReplaceDialog::REPLACE)){
3294 
3295       // If search string matches the selection, start from the end (or begin
3296       // when seaching backwards) of the selection.  Otherwise proceed from the
3297       // cursor position.
3298       pos=editor->getCursorPos();
3299       found=matchesSelection(findstring,beg,end,findflags,10);
3300       if(found){
3301         pos=(findflags&SEARCH_BACKWARD) ? beg[0]-1 : end[0];
3302         }
3303 
3304       // Perform a search if no match yet, or we're just searching
3305       if(!found || (code==FXReplaceDialog::SEARCH)){
3306         found=editor->findText(findstring,beg,end,pos,findflags|SEARCH_WRAP,10);
3307         }
3308 
3309       // Found a match; if just searching, select the match, otherwise, select
3310       // the replaced text to what the match was replaced with.
3311       if(found){
3312         setStatusMessage(tr("String found!"));
3313         replacedialog.setSearchTextColor(FXRGB(128,255,128));
3314         replacedialog.setReplaceTextColor(FXRGB(128,255,128));
3315 
3316         // Flag a wraparound the text
3317         if(findflags&SEARCH_BACKWARD){
3318           if(pos<=beg[0]){ setStatusMessage(tr("Search wrapped around.")); }
3319           }
3320         else{
3321           if(beg[0]<pos){ setStatusMessage(tr("Search wrapped around.")); }
3322           }
3323 
3324         // Replace the string
3325         if(code==FXReplaceDialog::REPLACE){
3326           if(findflags&SEARCH_REGEX){
3327             editor->extractText(originalvalue,beg[0],end[0]-beg[0]);
3328             replacevalue=substitute(originalvalue,replacestring,beg,end,10);
3329             }
3330           else{
3331             replacevalue=replacestring;
3332             }
3333           editor->replaceText(beg[0],end[0]-beg[0],replacevalue,true);
3334 
3335           // Highlight last changed
3336           editor->setAnchorPos(beg[0]);
3337           editor->moveCursorAndSelect(beg[0]+replacevalue.length(),FXText::SelectChars,true);
3338           }
3339 
3340         // Just highlight it
3341         else{
3342           editor->setAnchorPos(beg[0]);
3343           editor->moveCursorAndSelect(end[0],FXText::SelectChars,true);
3344           }
3345         }
3346 
3347       // Not found
3348       else{
3349         setStatusMessage(tr("String not found!"));
3350         replacedialog.setSearchTextColor(FXRGB(255,128,128));
3351         replacedialog.setReplaceTextColor(FXRGB(255,128,128));
3352         getApp()->beep();
3353         }
3354       }
3355 
3356     // Replace multiple instances
3357     else{
3358       fm=-1;
3359       to=-1;
3360 
3361       // Replace range
3362       if(code==FXReplaceDialog::REPLACE_ALL){
3363         pos=0;
3364         finish=editor->getLength();
3365         }
3366       else{
3367         pos=editor->getSelStartPos();
3368         finish=editor->getSelEndPos();
3369         }
3370 
3371       // Scan through text buffer
3372       while(editor->findText(findstring,beg,end,pos,((findflags&~(SEARCH_WRAP|SEARCH_BACKWARD|SEARCH_FORWARD))|SEARCH_FORWARD),10) && end[0]<=finish){
3373 
3374         // Start buffer mutation at first occurrence
3375         if(fm<0){ fm=to=beg[0]; }
3376 
3377         // Unchanged piece is just copied over
3378         if(to<beg[0]){
3379           editor->extractText(originalvalue,to,beg[0]-to);
3380           replacevalue.append(originalvalue);
3381           }
3382 
3383         // For changed piece, use substitution pattern
3384         if(findflags&SEARCH_REGEX){
3385           editor->extractText(originalvalue,beg[0],end[0]-beg[0]);
3386           replacevalue.append(substitute(originalvalue,replacestring,beg,end,10));
3387           }
3388         else{
3389           replacevalue.append(replacestring);
3390           }
3391 
3392         // End of buffer mutation at end of last occurrence
3393         to=end[0];
3394 
3395         // Advance at least one character
3396         pos=to;
3397         if(beg[0]==end[0]) pos++;
3398         }
3399 
3400       // Got anything at all?
3401       if(0<=fm && 0<=to){
3402         setStatusMessage(tr("Strings replaced!"));
3403         replacedialog.setSearchTextColor(FXRGB(128,255,128));
3404         replacedialog.setReplaceTextColor(FXRGB(128,255,128));
3405 
3406         // Replace the text
3407         editor->replaceText(fm,to-fm,replacevalue,true);
3408         editor->moveCursor(fm+replacevalue.length(),true);
3409         }
3410       else{
3411         setStatusMessage(tr("String not found!"));
3412         replacedialog.setSearchTextColor(FXRGB(255,128,128));
3413         replacedialog.setReplaceTextColor(FXRGB(255,128,128));
3414         getApp()->beep();
3415         }
3416       }
3417     }
3418 
3419   // Restore normal message
3420   setStatusMessage(tr("Ready."));
3421   return 1;
3422   }
3423 
3424 
3425 // Search seleced
onCmdSearchSel(FXObject *,FXSelector sel,void *)3426 long TextWindow::onCmdSearchSel(FXObject*,FXSelector sel,void*){
3427   FXTRACE((100,"TextWindow::onCmdSearchSel()\n"));
3428   FXString string;
3429   if(getDNDData(FROM_SELECTION,utf8Type,string)){               // UTF8 string
3430     searchstring=string;
3431     searchflags=SEARCH_EXACT;
3432     }
3433   else if(getDNDData(FROM_SELECTION,utf16Type,string)){         // UTF16 string
3434     FXUTF16LECodec unicode;
3435     searchstring=unicode.mb2utf(string);
3436     searchflags=SEARCH_EXACT;
3437     }
3438   else if(getDNDData(FROM_SELECTION,stringType,string)){        // ASCII string
3439     FX88591Codec ascii;
3440     searchstring=ascii.mb2utf(string);
3441     searchflags=SEARCH_EXACT;
3442     }
3443   if(!searchstring.empty()){
3444     FXint selstart=editor->getSelStartPos();
3445     FXint selend=editor->getSelEndPos();
3446     FXint pos=editor->getCursorPos();
3447     FXint beg[10],end[10];
3448     if(FXSELID(sel)==ID_SEARCH_SEL_FORW){
3449       if(editor->isPosSelected(pos)) pos=selend;                // Start from selection end if position is selected
3450       searchflags=(searchflags&~SEARCH_BACKWARD)|SEARCH_FORWARD;
3451       }
3452     else{
3453       if(editor->isPosSelected(pos)) pos=selstart-1;            // Start from selection start-1 if position is selected
3454       searchflags=(searchflags&~SEARCH_FORWARD)|SEARCH_BACKWARD;
3455       }
3456     FXTRACE((100,"searchstring=\n\"\"\"\n%s\n\"\"\"\n",searchstring.text()));
3457     if(editor->findText(searchstring,beg,end,pos,searchflags|SEARCH_WRAP,10)){
3458       if(beg[0]!=selstart || end[0]!=selend){
3459         editor->setAnchorPos(beg[0]);
3460         editor->moveCursorAndSelect(end[0],FXText::SelectChars,true);
3461         return 1;
3462         }
3463       }
3464     }
3465   getApp()->beep();
3466   return 1;
3467   }
3468 
3469 
3470 // Search for next occurence
onCmdSearchNext(FXObject *,FXSelector sel,void *)3471 long TextWindow::onCmdSearchNext(FXObject*,FXSelector sel,void*){
3472   FXTRACE((100,"TextWindow::onCmdSearchNext()\n"));
3473   if(!searchstring.empty()){
3474     FXint selstart=editor->getSelStartPos();
3475     FXint selend=editor->getSelEndPos();
3476     FXint pos=editor->getCursorPos();
3477     FXint beg[10];
3478     FXint end[10];
3479     if(FXSELID(sel)==ID_SEARCH_NXT_FORW){
3480       if(editor->isPosSelected(pos)) pos=selend;                // Start from selection end if position is selected
3481       searchflags=(searchflags&~SEARCH_BACKWARD)|SEARCH_FORWARD;
3482       }
3483     else{
3484       if(editor->isPosSelected(pos)) pos=selstart-1;            // Start from selection start-1 if position is selected
3485       searchflags=(searchflags&~SEARCH_FORWARD)|SEARCH_BACKWARD;
3486       }
3487     if(editor->findText(searchstring,beg,end,pos,searchflags|SEARCH_WRAP,10)){
3488       if(beg[0]!=selstart || end[0]!=selend){
3489         editor->setAnchorPos(beg[0]);
3490         editor->moveCursorAndSelect(end[0],FXText::SelectChars,true);
3491         return 1;
3492         }
3493       }
3494     }
3495   getApp()->beep();
3496   return 1;
3497   }
3498 
3499 /*******************************************************************************/
3500 
3501 // Start incremental search; show search bar if not permanently visible
startISearch()3502 void TextWindow::startISearch(){
3503   if(!searching){
3504     showsearchbar=searchbar->shown();
3505     if(!showsearchbar){
3506       searchbar->show();
3507       searchbar->recalc();
3508       }
3509     searchtext->setBackColor(getApp()->getBackColor());
3510     searchtext->setText(FXString::null);
3511     searchtext->setFocus();
3512     searchstring=FXString::null;
3513     searchflags=(searchflags&~SEARCH_BACKWARD)|SEARCH_FORWARD;
3514     isearchReplace=false;
3515     isearchpos=-1;
3516     searching=true;
3517     }
3518   }
3519 
3520 
3521 // Finish incremental search; hide search bar if not permanently visible
finishISearch()3522 void TextWindow::finishISearch(){
3523   if(searching){
3524     if(!showsearchbar){
3525       searchbar->hide();
3526       searchbar->recalc();
3527       }
3528     searchtext->setBackColor(getApp()->getBackColor());
3529     searchtext->setText(FXString::null);
3530     editor->setFocus();
3531     isearchReplace=false;
3532     isearchpos=-1;
3533     searching=false;
3534     }
3535   }
3536 
3537 
3538 // Search next incremental text
performISearch(const FXString & text,FXuint opts,FXbool advance,FXbool notify)3539 FXbool TextWindow::performISearch(const FXString& text,FXuint opts,FXbool advance,FXbool notify){
3540   FXint beg[10],end[10],start,mode;
3541   FXRex rex;
3542 
3543   // Figure start of search
3544   start=editor->getCursorPos();
3545   if(isearchpos==-1) isearchpos=start;
3546   if(advance){
3547     if(editor->isPosSelected(start)){
3548       if((opts&SEARCH_BACKWARD)){
3549         start=editor->getSelStartPos();
3550         }
3551       else{
3552         start=editor->getSelEndPos();
3553         }
3554       }
3555     }
3556   else{
3557     start=isearchpos;
3558     }
3559 
3560   // Back off a bit for a backward search
3561   if((opts&SEARCH_BACKWARD) && start>0) start--;
3562 
3563   // Restore normal color
3564   searchtext->setBackColor(getApp()->getBackColor());
3565 
3566   // If entry is empty, clear selection and jump back to start
3567   if(text.empty()){
3568     editor->killSelection(notify);
3569     editor->makePositionVisible(isearchpos);
3570     editor->setCursorPos(isearchpos,notify);
3571     getApp()->beep();
3572     return true;
3573     }
3574 
3575   // Check syntax of regex; ignore if input not yet complete
3576   mode=FXRex::Syntax;
3577   if(!(opts&SEARCH_REGEX)) mode|=FXRex::Verbatim;
3578   if(opts&SEARCH_IGNORECASE) mode|=FXRex::IgnoreCase;
3579   if(rex.parse(text,mode)==FXRex::ErrOK){
3580 
3581     // Search text, beep if not found
3582     if(!editor->findText(text,beg,end,start,opts,10)){
3583       searchtext->setBackColor(FXRGB(255,128,128));
3584       getApp()->beep();
3585       return false;
3586       }
3587 
3588     // Matching zero-length assertion at start position; advance to next one
3589     if(!(opts&SEARCH_BACKWARD) && start==beg[0] && beg[0]==end[0]){
3590       if(!editor->findText(text,beg,end,start+1,opts,10)){
3591         searchtext->setBackColor(FXRGB(255,128,128));
3592         getApp()->beep();
3593         return false;
3594         }
3595       }
3596 
3597     // Select matching text
3598     if(opts&SEARCH_BACKWARD){
3599       editor->setAnchorPos(end[0]);
3600       editor->extendSelection(beg[0],FXText::SelectChars,notify);
3601       editor->makePositionVisible(beg[0]);
3602       editor->setCursorPos(beg[0],notify);
3603       }
3604     else{
3605       editor->setAnchorPos(beg[0]);
3606       editor->extendSelection(end[0],FXText::SelectChars,notify);
3607       editor->makePositionVisible(end[0]);
3608       editor->setCursorPos(end[0],notify);
3609       }
3610     }
3611   return true;
3612   }
3613 
3614 
3615 // Incremental search text changed
onChgISearchText(FXObject *,FXSelector,void *)3616 long TextWindow::onChgISearchText(FXObject*,FXSelector,void*){
3617   searchstring=searchtext->getText();
3618   performISearch(searchstring,searchflags,false,true);
3619   addSearchHistory(searchstring,searchflags,isearchReplace);
3620   isearchReplace=true;
3621   return 1;
3622   }
3623 
3624 
3625 // Incremental search text command
onCmdISearchText(FXObject *,FXSelector,void *)3626 long TextWindow::onCmdISearchText(FXObject*,FXSelector,void*){
3627   searchstring=searchtext->getText();
3628   performISearch(searchstring,searchflags,true,true);
3629   isearchReplace=false;
3630   return 1;
3631   }
3632 
3633 
3634 // Incremental search text command
onKeyISearchText(FXObject *,FXSelector,void * ptr)3635 long TextWindow::onKeyISearchText(FXObject*,FXSelector,void* ptr){
3636   switch(((FXEvent*)ptr)->code){
3637     case KEY_Escape:
3638       finishISearch();
3639       return 1;
3640     case KEY_Page_Down:
3641       return onCmdISearchNext(this,FXSEL(SEL_COMMAND,ID_ISEARCH_NEXT),NULL);
3642     case KEY_Page_Up:
3643       return onCmdISearchPrev(this,FXSEL(SEL_COMMAND,ID_ISEARCH_PREV),NULL);
3644     case KEY_Down:
3645       return onCmdISearchHistDn(this,FXSEL(SEL_COMMAND,ID_ISEARCH_HIST_DN),NULL);
3646     case KEY_Up:
3647       return onCmdISearchHistUp(this,FXSEL(SEL_COMMAND,ID_ISEARCH_HIST_UP),NULL);
3648     case KEY_i:
3649       if(!(((FXEvent*)ptr)->state&CONTROLMASK)) return 0;
3650       return onCmdISearchCase(this,FXSEL(SEL_COMMAND,ID_ISEARCH_IGNCASE),NULL);
3651     case KEY_e:
3652       if(!(((FXEvent*)ptr)->state&CONTROLMASK)) return 0;
3653       return onCmdISearchRegex(this,FXSEL(SEL_COMMAND,ID_ISEARCH_REGEX),NULL);
3654     case KEY_d:
3655       if(!(((FXEvent*)ptr)->state&CONTROLMASK)) return 0;
3656       return onCmdISearchDir(this,FXSEL(SEL_COMMAND,ID_ISEARCH_REVERSE),NULL);
3657     }
3658   return 0;
3659   }
3660 
3661 
3662 // Append entry
addSearchHistory(const FXString & pat,FXuint opt,FXbool rep)3663 void TextWindow::addSearchHistory(const FXString& pat,FXuint opt,FXbool rep){
3664   if(!pat.empty()){
3665     if(!rep && isearchString[0]!=pat){
3666       for(FXint i=19; i>0; --i){
3667         swap(isearchString[i],isearchString[i-1]);
3668         swap(isearchOption[i],isearchOption[i-1]);
3669         }
3670       }
3671     isearchString[0]=pat;
3672     isearchOption[0]=opt;
3673     isearchIndex=-1;
3674     }
3675   }
3676 
3677 
3678 // Load incremental search history
loadSearchHistory()3679 void TextWindow::loadSearchHistory(){
3680   for(FXint i=0; i<20; ++i){
3681     isearchString[i]=getApp()->reg().readStringEntry(sectionKey,skey[i],FXString::null);
3682     if(isearchString[i].empty()) break;
3683     isearchOption[i]=getApp()->reg().readUIntEntry(sectionKey,mkey[i],SEARCH_EXACT|SEARCH_FORWARD|SEARCH_WRAP);
3684     }
3685   isearchIndex=-1;
3686   }
3687 
3688 
3689 // Save incremental search history
saveSearchHistory()3690 void TextWindow::saveSearchHistory(){
3691   for(FXint i=0; i<20; ++i){
3692     if(!isearchString[i].empty()){
3693       getApp()->reg().writeStringEntry(sectionKey,skey[i],isearchString[i].text());
3694       getApp()->reg().writeUIntEntry(sectionKey,mkey[i],isearchOption[i]);
3695       }
3696     else{
3697       getApp()->reg().deleteEntry(sectionKey,skey[i]);
3698       getApp()->reg().deleteEntry(sectionKey,mkey[i]);
3699       }
3700     }
3701   }
3702 
3703 
3704 // Scroll back in incremental search history
onCmdISearchHistUp(FXObject *,FXSelector,void *)3705 long TextWindow::onCmdISearchHistUp(FXObject*,FXSelector,void*){
3706   if(isearchIndex+1<20 && !isearchString[isearchIndex+1].empty()){
3707     isearchIndex++;
3708     FXASSERT(0<=isearchIndex && isearchIndex<20);
3709     searchstring=isearchString[isearchIndex];
3710     searchtext->setText(searchstring);
3711     performISearch(searchstring,searchflags,false,true);
3712     }
3713   else{
3714     getApp()->beep();
3715     }
3716   return 1;
3717   }
3718 
3719 
3720 // Scroll forward in incremental search history
onCmdISearchHistDn(FXObject *,FXSelector,void *)3721 long TextWindow::onCmdISearchHistDn(FXObject*,FXSelector,void*){
3722   if(0<isearchIndex){
3723     isearchIndex--;
3724     FXASSERT(0<=isearchIndex && isearchIndex<20);
3725     searchstring=isearchString[isearchIndex];
3726     searchtext->setText(searchstring);
3727     performISearch(searchstring,searchflags,false,true);
3728     }
3729   else{
3730     isearchIndex=-1;
3731     searchstring=FXString::null;
3732     searchtext->setText(FXString::null,true);
3733     }
3734   return 1;
3735   }
3736 
3737 
3738 // Search incremental backward for next occurrence
onCmdISearchPrev(FXObject *,FXSelector,void *)3739 long TextWindow::onCmdISearchPrev(FXObject*,FXSelector,void*){
3740   searchflags=(searchflags&~SEARCH_FORWARD)|SEARCH_BACKWARD;
3741   performISearch(searchstring,searchflags,true,true);
3742   return 1;
3743   }
3744 
3745 
3746 // Search incremental forward for next occurrence
onCmdISearchNext(FXObject *,FXSelector,void *)3747 long TextWindow::onCmdISearchNext(FXObject*,FXSelector,void*){
3748   searchflags=(searchflags&~SEARCH_BACKWARD)|SEARCH_FORWARD;
3749   performISearch(searchstring,searchflags,true,true);
3750   return 1;
3751   }
3752 
3753 
3754 // Start incremental search
onCmdISearchStart(FXObject *,FXSelector,void *)3755 long TextWindow::onCmdISearchStart(FXObject*,FXSelector,void*){
3756   startISearch();
3757   return 1;
3758   }
3759 
3760 
3761 // End incremental search
onCmdISearchFinish(FXObject *,FXSelector,void *)3762 long TextWindow::onCmdISearchFinish(FXObject*,FXSelector,void*){
3763   finishISearch();
3764   return 1;
3765   }
3766 
3767 
3768 // Update case sensitive mode
onUpdISearchCase(FXObject * sender,FXSelector,void *)3769 long TextWindow::onUpdISearchCase(FXObject* sender,FXSelector,void*){
3770   sender->handle(this,(searchflags&SEARCH_IGNORECASE)?FXSEL(SEL_COMMAND,ID_CHECK):FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
3771   return 1;
3772   }
3773 
3774 
3775 // Change case sensitive mode
onCmdISearchCase(FXObject *,FXSelector,void *)3776 long TextWindow::onCmdISearchCase(FXObject*,FXSelector,void*){
3777   searchflags^=SEARCH_IGNORECASE;
3778   performISearch(searchstring,searchflags,false,true);
3779   return 1;
3780   }
3781 
3782 
3783 // Update search direction
onUpdISearchDir(FXObject * sender,FXSelector,void *)3784 long TextWindow::onUpdISearchDir(FXObject* sender,FXSelector,void*){
3785   sender->handle(this,(searchflags&SEARCH_BACKWARD)?FXSEL(SEL_COMMAND,ID_CHECK):FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
3786   return 1;
3787   }
3788 
3789 
3790 // Change search direction
onCmdISearchDir(FXObject *,FXSelector,void *)3791 long TextWindow::onCmdISearchDir(FXObject*,FXSelector,void*){
3792   searchflags^=(SEARCH_FORWARD|SEARCH_BACKWARD);
3793   performISearch(searchstring,searchflags,false,true);
3794   return 1;
3795   }
3796 
3797 
3798 // Update search mode
onUpdISearchRegex(FXObject * sender,FXSelector,void *)3799 long TextWindow::onUpdISearchRegex(FXObject* sender,FXSelector,void*){
3800   sender->handle(this,(searchflags&SEARCH_REGEX)?FXSEL(SEL_COMMAND,ID_CHECK):FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
3801   return 1;
3802   }
3803 
3804 
3805 // Change search mode
onCmdISearchRegex(FXObject *,FXSelector,void *)3806 long TextWindow::onCmdISearchRegex(FXObject*,FXSelector,void*){
3807   searchflags^=SEARCH_REGEX;
3808   performISearch(searchstring,searchflags,false,true);
3809   return 1;
3810   }
3811 
3812 /*******************************************************************************/
3813 
3814 // Text window got focus; terminate incremental search
onTextFocus(FXObject *,FXSelector,void *)3815 long TextWindow::onTextFocus(FXObject*,FXSelector,void*){
3816   finishISearch();
3817   return 1;
3818   }
3819 
3820 
3821 // Text inserted; callback has [pos nins]
onTextInserted(FXObject *,FXSelector,void * ptr)3822 long TextWindow::onTextInserted(FXObject*,FXSelector,void* ptr){
3823   const FXTextChange *change=(const FXTextChange*)ptr;
3824 
3825   FXTRACE((140,"Inserted: pos=%d ndel=%d nins=%d\n",change->pos,change->ndel,change->nins));
3826 
3827   // Log undo record
3828   if(!undolist.busy()){
3829     undolist.add(new FXTextInsert(editor,change->pos,change->nins,change->ins));
3830     if(undolist.size()>MAXUNDOSIZE) undolist.trimSize(KEEPUNDOSIZE);
3831     }
3832 
3833   // Update bookmark locations
3834   updateBookmarks(change->pos,change->ndel,change->nins);
3835 
3836   // Restyle text
3837   restyleText(change->pos,change->ndel,change->nins);
3838 
3839   return 1;
3840   }
3841 
3842 
3843 // Text replaced; callback has [pos ndel nins]
onTextReplaced(FXObject *,FXSelector,void * ptr)3844 long TextWindow::onTextReplaced(FXObject*,FXSelector,void* ptr){
3845   const FXTextChange *change=(const FXTextChange*)ptr;
3846 
3847   FXTRACE((140,"Replaced: pos=%d ndel=%d nins=%d\n",change->pos,change->ndel,change->nins));
3848 
3849   // Log undo record
3850   if(!undolist.busy()){
3851     undolist.add(new FXTextReplace(editor,change->pos,change->ndel,change->nins,change->del,change->ins));
3852     if(undolist.size()>MAXUNDOSIZE) undolist.trimSize(KEEPUNDOSIZE);
3853     }
3854 
3855   // Update bookmark locations
3856   updateBookmarks(change->pos,change->ndel,change->nins);
3857 
3858   // Restyle text
3859   restyleText(change->pos,change->ndel,change->nins);
3860 
3861   return 1;
3862   }
3863 
3864 
3865 // Text deleted; callback has [pos ndel]
onTextDeleted(FXObject *,FXSelector,void * ptr)3866 long TextWindow::onTextDeleted(FXObject*,FXSelector,void* ptr){
3867   const FXTextChange *change=(const FXTextChange*)ptr;
3868 
3869   FXTRACE((140,"Deleted: pos=%d ndel=%d nins=%d\n",change->pos,change->ndel,change->nins));
3870 
3871   // Log undo record
3872   if(!undolist.busy()){
3873     undolist.add(new FXTextDelete(editor,change->pos,change->ndel,change->del));
3874     if(undolist.size()>MAXUNDOSIZE) undolist.trimSize(KEEPUNDOSIZE);
3875     }
3876 
3877   // Update bookmark locations
3878   updateBookmarks(change->pos,change->ndel,change->nins);
3879 
3880   // Restyle text
3881   restyleText(change->pos,change->ndel,change->nins);
3882 
3883   return 1;
3884   }
3885 
3886 
3887 // Released right button
onTextRightMouse(FXObject *,FXSelector,void * ptr)3888 long TextWindow::onTextRightMouse(FXObject*,FXSelector,void* ptr){
3889   FXEvent* event=(FXEvent*)ptr;
3890   if(!event->moved){
3891     FXMenuPane popupmenu(this,POPUP_SHRINKWRAP);
3892     new FXMenuCommand(&popupmenu,tr("Undo"),getApp()->undoicon,&undolist,FXUndoList::ID_UNDO);
3893     new FXMenuCommand(&popupmenu,tr("Redo"),getApp()->redoicon,&undolist,FXUndoList::ID_REDO);
3894     new FXMenuSeparator(&popupmenu);
3895     new FXMenuCommand(&popupmenu,tr("Find Backward\t\tSearch backward for another occurrence."),getApp()->searchprevicon,this,ID_SEARCH_NXT_BACK);
3896     new FXMenuCommand(&popupmenu,tr("Find Forward\t\tSearch forward for another occurrence."),getApp()->searchnexticon,this,ID_SEARCH_NXT_FORW);
3897     new FXMenuCommand(&popupmenu,tr("Find Backward Selected\t\tSearch backward for selected text."),getApp()->searchprevicon,this,ID_SEARCH_SEL_BACK);
3898     new FXMenuCommand(&popupmenu,tr("Find Forward Selected\t\tSearch forward for selected text."),getApp()->searchnexticon,this,ID_SEARCH_SEL_FORW);
3899     new FXMenuSeparator(&popupmenu);
3900     new FXMenuCommand(&popupmenu,tr("Cut"),getApp()->cuticon,editor,FXText::ID_CUT_SEL);
3901     new FXMenuCommand(&popupmenu,tr("Copy"),getApp()->copyicon,editor,FXText::ID_COPY_SEL);
3902     new FXMenuCommand(&popupmenu,tr("Paste"),getApp()->pasteicon,editor,FXText::ID_PASTE_SEL);
3903     new FXMenuCommand(&popupmenu,tr("Select All"),NULL,editor,FXText::ID_SELECT_ALL);
3904     new FXMenuSeparator(&popupmenu);
3905     new FXMenuCommand(&popupmenu,tr("Set bookmark\t\tSet bookmark at cursor location."),getApp()->bookseticon,this,ID_SET_MARK);
3906     new FXMenuCheck(&popupmenu,FXString::null,this,ID_MARK_0);
3907     new FXMenuCheck(&popupmenu,FXString::null,this,ID_MARK_1);
3908     new FXMenuCheck(&popupmenu,FXString::null,this,ID_MARK_2);
3909     new FXMenuCheck(&popupmenu,FXString::null,this,ID_MARK_3);
3910     new FXMenuCheck(&popupmenu,FXString::null,this,ID_MARK_4);
3911     new FXMenuCheck(&popupmenu,FXString::null,this,ID_MARK_5);
3912     new FXMenuCheck(&popupmenu,FXString::null,this,ID_MARK_6);
3913     new FXMenuCheck(&popupmenu,FXString::null,this,ID_MARK_7);
3914     new FXMenuCheck(&popupmenu,FXString::null,this,ID_MARK_8);
3915     new FXMenuCheck(&popupmenu,FXString::null,this,ID_MARK_9);
3916     new FXMenuCommand(&popupmenu,tr("Delete bookmark\t\tDelete bookmark at cursor."),getApp()->bookdelicon,this,ID_DEL_MARK);
3917     new FXMenuCommand(&popupmenu,tr("Clear all bookmarks\t\tClear all bookmarks."),getApp()->bookdelicon,this,ID_CLEAR_MARKS);
3918     popupmenu.forceRefresh();
3919     popupmenu.create();
3920     popupmenu.popup(NULL,event->root_x,event->root_y);
3921     getApp()->runModalWhileShown(&popupmenu);
3922     }
3923   return 1;
3924   }
3925 
3926 
3927 /*******************************************************************************/
3928 
3929 
3930 // Check file when focus moves in
onFocusIn(FXObject * sender,FXSelector sel,void * ptr)3931 long TextWindow::onFocusIn(FXObject* sender,FXSelector sel,void* ptr){
3932   FXMainWindow::onFocusIn(sender,sel,ptr);
3933   if(warnchanged && getFiletime()!=0){
3934     FXTime t=FXStat::modified(getFilename());
3935     if(t && t!=getFiletime()){
3936       warnchanged=false;
3937       setFiletime(t);
3938       if(MBOX_CLICKED_OK==FXMessageBox::warning(this,MBOX_OK_CANCEL,tr("File Was Changed"),tr("%s\nwas changed by another program. Reload this file from disk?"),getFilename().text())){
3939         FXint top=editor->getTopLine();
3940         FXint pos=editor->getCursorPos();
3941         if(loadFile(getFilename())){
3942           editor->setTopLine(top);
3943           editor->setCursorPos(pos);
3944           determineSyntax();
3945           parseModeline();
3946           }
3947         }
3948       warnchanged=true;
3949       }
3950     }
3951   return 1;
3952   }
3953 
3954 
3955 // Update clock
onClock(FXObject *,FXSelector,void *)3956 long TextWindow::onClock(FXObject*,FXSelector,void*){
3957   FXTime current=FXThread::time();
3958   clock->setText(FXSystem::localTime(current,tr("%H:%M:%S")));
3959   clock->setTipText(FXSystem::localTime(current,tr("%A %B %d %Y")));
3960   getApp()->addTimeout(this,ID_CLOCKTIME,CLOCKTIMER);
3961   return 0;
3962   }
3963 
3964 
3965 /*******************************************************************************/
3966 
3967 
3968 // Next bookmarked place
onCmdNextMark(FXObject *,FXSelector,void *)3969 long TextWindow::onCmdNextMark(FXObject*,FXSelector,void*){
3970   if(bookmark[0]){
3971     FXint pos=editor->getCursorPos();
3972     for(FXuint b=0; b<ARRAYNUMBER(bookmark); b++){
3973       if(bookmark[b]==0) break;
3974       if(bookmark[b]>pos){ gotoPosition(bookmark[b]); break; }
3975       }
3976     }
3977   return 1;
3978   }
3979 
3980 
3981 // Sensitize if bookmark beyond cursor pos
onUpdNextMark(FXObject * sender,FXSelector,void *)3982 long TextWindow::onUpdNextMark(FXObject* sender,FXSelector,void*){
3983   if(bookmark[0]){
3984     FXint pos=editor->getCursorPos();
3985     for(FXuint b=0; b<ARRAYNUMBER(bookmark); b++){
3986       if(bookmark[b]==0) break;
3987       if(bookmark[b] && bookmark[b]>pos){ sender->handle(this,FXSEL(SEL_COMMAND,ID_ENABLE),NULL); return 1; }
3988       }
3989     }
3990   sender->handle(this,FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
3991   return 1;
3992   }
3993 
3994 
3995 // Previous bookmarked place
onCmdPrevMark(FXObject *,FXSelector,void *)3996 long TextWindow::onCmdPrevMark(FXObject*,FXSelector,void*){
3997   if(bookmark[0]){
3998     FXint pos=editor->getCursorPos();
3999     for(FXuint b=ARRAYNUMBER(bookmark); b>0; b--){
4000       if(bookmark[b-1]==0) continue;
4001       if(bookmark[b-1]<pos){ gotoPosition(bookmark[b-1]); break; }
4002       }
4003     }
4004   return 1;
4005   }
4006 
4007 
4008 // Sensitize if bookmark before cursor pos
onUpdPrevMark(FXObject * sender,FXSelector,void *)4009 long TextWindow::onUpdPrevMark(FXObject* sender,FXSelector,void*){
4010   if(bookmark[0]){
4011     FXint pos=editor->getCursorPos();
4012     for(FXuint b=ARRAYNUMBER(bookmark); b>0; b--){
4013       if(bookmark[b-1]==0) continue;
4014       if(bookmark[b-1]<pos){ sender->handle(this,FXSEL(SEL_COMMAND,ID_ENABLE),NULL); return 1; }
4015       }
4016     }
4017   sender->handle(this,FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
4018   return 1;
4019   }
4020 
4021 
4022 // Set bookmark, but don't set more than one per line
onCmdSetMark(FXObject *,FXSelector,void *)4023 long TextWindow::onCmdSetMark(FXObject*,FXSelector,void*){
4024   setBookmark(editor->getCursorPos());
4025   return 1;
4026   }
4027 
4028 
4029 // Update set bookmark
onUpdSetMark(FXObject * sender,FXSelector,void *)4030 long TextWindow::onUpdSetMark(FXObject* sender,FXSelector,void*){
4031   sender->handle(this,(bookmark[ARRAYNUMBER(bookmark)-1]==0)?FXSEL(SEL_COMMAND,ID_ENABLE):FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
4032   return 1;
4033   }
4034 
4035 
4036 // Goto bookmark i
onCmdGotoMark(FXObject *,FXSelector sel,void *)4037 long TextWindow::onCmdGotoMark(FXObject*,FXSelector sel,void*){
4038   FXint pos=bookmark[FXSELID(sel)-ID_MARK_0];
4039   if(pos){
4040     gotoPosition(pos);
4041     }
4042   return 1;
4043   }
4044 
4045 
4046 // Update bookmark i
onUpdGotoMark(FXObject * sender,FXSelector sel,void *)4047 long TextWindow::onUpdGotoMark(FXObject* sender,FXSelector sel,void*){
4048   FXint pos=bookmark[FXSELID(sel)-ID_MARK_0];
4049   if(0<pos && pos<=editor->getLength()){
4050     FXint b=editor->lineStart(pos);     // Extent of bookmarked line
4051     FXint e=editor->lineEnd(pos);
4052     FXint p=editor->getCursorPos();
4053     FXint c=(b<=p&&p<=e);               // Cursor inside bookmarked line
4054     FXString string;
4055     FXASSERT(0<=b && e<=editor->getLength());
4056     if(b==e){                           // Empty line: just show line number
4057       string.format("<<%d>>",pos);
4058       }
4059     else{                               // Show squeezed text of line as label
4060       string=editor->extractText(b,e-b);
4061       string.simplify();
4062       if(50<=string.length()){          // If too long after squeeze, suffix "..."
4063         string.replace(50,string.length()-50,"...");
4064         }
4065       string.substitute("&","&&",true); // Don't want to introduce accelerator key
4066       }
4067     sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&string);
4068     sender->handle(this,FXSEL(SEL_COMMAND,ID_SETVALUE),(void*)(FXuval)c);
4069     sender->handle(this,FXSEL(SEL_COMMAND,ID_SHOW),NULL);
4070     return 1;
4071     }
4072   sender->handle(this,FXSEL(SEL_COMMAND,ID_HIDE),NULL);
4073   return 1;
4074   }
4075 
4076 
4077 // Highlight if cursor on bookmarked line
onUpdDelMark(FXObject * sender,FXSelector,void *)4078 long TextWindow::onUpdDelMark(FXObject* sender,FXSelector,void*){
4079   FXint pos=editor->getCursorPos();
4080   for(FXuint i=0; bookmark[i] && i<ARRAYNUMBER(bookmark); i++){
4081     if(bookmark[i]==pos){
4082       sender->handle(this,FXSEL(SEL_COMMAND,ID_ENABLE),NULL);
4083       return 1;
4084       }
4085     }
4086   sender->handle(this,FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
4087   return 1;
4088   }
4089 
4090 
4091 // Clear bookmark at cursor
onCmdDelMark(FXObject *,FXSelector,void *)4092 long TextWindow::onCmdDelMark(FXObject*,FXSelector,void*){
4093   clearBookmark(editor->getCursorPos());
4094   return 1;
4095   }
4096 
4097 
4098 
4099 // Highlight if cursor on bookmarked line
onUpdClearMarks(FXObject * sender,FXSelector,void *)4100 long TextWindow::onUpdClearMarks(FXObject* sender,FXSelector,void*){
4101   sender->handle(this,bookmark[0]?FXSEL(SEL_COMMAND,ID_ENABLE):FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
4102   return 1;
4103   }
4104 
4105 
4106 // Clear bookmarks
onCmdClearMarks(FXObject *,FXSelector,void *)4107 long TextWindow::onCmdClearMarks(FXObject*,FXSelector,void*){
4108   clearBookmarks();
4109   return 1;
4110   }
4111 
4112 
4113 // Goto position
gotoPosition(FXint pos)4114 void TextWindow::gotoPosition(FXint pos){
4115   if(!editor->isPosVisible(pos)){
4116     editor->setCenterLine(pos);
4117     }
4118   editor->setCursorPos(pos);
4119   editor->makePositionVisible(editor->getCursorPos());
4120   }
4121 
4122 
4123 // Add bookmark at current cursor position; we force the cursor
4124 // position to be somewhere in the currently visible text.
setBookmark(FXint pos)4125 void TextWindow::setBookmark(FXint pos){
4126   if(!bookmark[ARRAYNUMBER(bookmark)-1] && pos){
4127     FXuint i;
4128     for(i=0; i<ARRAYNUMBER(bookmark); i++){
4129       if(bookmark[i]==pos) return;
4130       }
4131     for(i=ARRAYNUMBER(bookmark)-1; i>0 && (bookmark[i-1]==0 || pos<bookmark[i-1]); i--){
4132       bookmark[i]=bookmark[i-1];
4133       }
4134     FXASSERT(i<ARRAYNUMBER(bookmark));
4135     bookmark[i]=pos;
4136     }
4137   }
4138 
4139 
4140 // Remove bookmark at given position pos
clearBookmark(FXint pos)4141 void TextWindow::clearBookmark(FXint pos){
4142   if(bookmark[0] && pos){
4143     FXuint i,j;
4144     for(i=j=0; j<ARRAYNUMBER(bookmark); j++){
4145       if(bookmark[j]==pos) continue;
4146       bookmark[i++]=bookmark[j];
4147       }
4148     if(i<ARRAYNUMBER(bookmark)) bookmark[i]=0;
4149     }
4150   }
4151 
4152 
4153 // Update bookmarks upon a text mutation, deleting the bookmark
4154 // if it was inside the deleted text and moving its position otherwise
updateBookmarks(FXint pos,FXint nd,FXint ni)4155 void TextWindow::updateBookmarks(FXint pos,FXint nd,FXint ni){
4156   if(bookmark[0]){
4157     FXuint i,j;
4158     for(i=j=0; j<ARRAYNUMBER(bookmark); j++){
4159       if(bookmark[j]<=pos){
4160         bookmark[i++]=bookmark[j];
4161         }
4162       else if(pos+nd<=bookmark[j]){
4163         bookmark[i++]=bookmark[j]-nd+ni;
4164         }
4165       else{
4166         bookmark[j]=0;
4167         }
4168       }
4169     }
4170   }
4171 
4172 
4173 // Clear bookmarks
clearBookmarks()4174 void TextWindow::clearBookmarks(){
4175   bookmark[0]=bookmark[1]=bookmark[2]=bookmark[3]=bookmark[4]=bookmark[5]=bookmark[6]=bookmark[7]=bookmark[8]=bookmark[9]=0;
4176   }
4177 
4178 
4179 // Read bookmarks associated with file
readBookmarks(const FXString & file)4180 void TextWindow::readBookmarks(const FXString& file){
4181   clearBookmarks();
4182   getApp()->reg().readFormatEntry("BOOKMARKS",FXPath::name(file),"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",&bookmark[0],&bookmark[1],&bookmark[2],&bookmark[3],&bookmark[4],&bookmark[5],&bookmark[6],&bookmark[7],&bookmark[8],&bookmark[9]);
4183   }
4184 
4185 
4186 // Write bookmarks associated with file, if any were set
writeBookmarks(const FXString & file)4187 void TextWindow::writeBookmarks(const FXString& file){
4188   if(savemarks && (bookmark[0] || bookmark[1] || bookmark[2] || bookmark[3] || bookmark[4] || bookmark[5] || bookmark[6] || bookmark[7] || bookmark[8] || bookmark[9])){
4189     getApp()->reg().writeFormatEntry("BOOKMARKS",FXPath::name(file).text(),"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",bookmark[0],bookmark[1],bookmark[2],bookmark[3],bookmark[4],bookmark[5],bookmark[6],bookmark[7],bookmark[8],bookmark[9]);
4190     }
4191   else{
4192     getApp()->reg().deleteEntry("BOOKMARKS",FXPath::name(file));
4193     }
4194   }
4195 
4196 
4197 // Toggle saving of bookmarks
onCmdSaveMarks(FXObject *,FXSelector,void *)4198 long TextWindow::onCmdSaveMarks(FXObject*,FXSelector,void*){
4199   savemarks=!savemarks;
4200   if(!savemarks) getApp()->reg().deleteSection("BOOKMARKS");
4201   return 1;
4202   }
4203 
4204 
4205 // Update saving bookmarks
onUpdSaveMarks(FXObject * sender,FXSelector,void *)4206 long TextWindow::onUpdSaveMarks(FXObject* sender,FXSelector,void*){
4207   sender->handle(this,savemarks?FXSEL(SEL_COMMAND,ID_CHECK):FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
4208   return 1;
4209   }
4210 
4211 
4212 // Toggle saving of views
onCmdSaveViews(FXObject *,FXSelector,void *)4213 long TextWindow::onCmdSaveViews(FXObject*,FXSelector,void*){
4214   saveviews=!saveviews;
4215   if(!saveviews) getApp()->reg().deleteSection("VIEW");
4216   return 1;
4217   }
4218 
4219 
4220 // Update saving views
onUpdSaveViews(FXObject * sender,FXSelector,void *)4221 long TextWindow::onUpdSaveViews(FXObject* sender,FXSelector,void*){
4222   sender->handle(this,saveviews?FXSEL(SEL_COMMAND,ID_CHECK):FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
4223   return 1;
4224   }
4225 
4226 
4227 // Read view of the file
readView(const FXString & file)4228 void TextWindow::readView(const FXString& file){
4229   editor->setTopLine(getApp()->reg().readIntEntry("VIEW",FXPath::name(file),0));
4230   }
4231 
4232 
4233 // Write current view of the file
writeView(const FXString & file)4234 void TextWindow::writeView(const FXString& file){
4235   if(saveviews && editor->getTopLine()){
4236     getApp()->reg().writeIntEntry("VIEW",FXPath::name(file),editor->getTopLine());
4237     }
4238   else{
4239     getApp()->reg().deleteEntry("VIEW",FXPath::name(file));
4240     }
4241   }
4242 
4243 
4244 /*******************************************************************************/
4245 
4246 // Parse modeline from the text buffer
parseModeline()4247 void TextWindow::parseModeline(){
4248   if(modeline){
4249     Modeline modes;
4250     FXString lines;
4251     FXString language;
4252 
4253     // Buffer chunk
4254     FXint len=editor->getLength();
4255     FXint pos=editor->nextLine(0,30);
4256 
4257     // Extract top few lines and check for modeline
4258     editor->extractText(lines,0,pos);
4259     if(!modes.parseModeline(lines)){
4260       if(pos>=len) return;
4261       pos=editor->prevLine(len,10);
4262 
4263       // Extract bottom few lines and check for modeline
4264       editor->extractText(lines,pos,len-pos);
4265       if(!modes.parseModeline(lines)) return;
4266       }
4267 
4268     // See if a new langauge is called for
4269     language=modes.getLanguage();
4270     if(!language.empty()){
4271       Syntax* stx=getApp()->getSyntaxByName(language);
4272       if(stx){ setSyntax(stx); }
4273       }
4274 
4275     // Get original parameters
4276     FXuint modebits=editor->getTextStyle();
4277     FXint  tabwidth=editor->getTabColumns();
4278     FXint  wrapwidth=editor->getWrapColumns();
4279 
4280     // Modes from the mode line
4281     if(modes.getAutoIndent()==0) modebits&=~TEXT_AUTOINDENT;
4282     if(modes.getAutoIndent()==1) modebits|=TEXT_AUTOINDENT;
4283     if(modes.getWrapMode()==0) modebits&=~(TEXT_WORDWRAP|TEXT_FIXEDWRAP);
4284     if(modes.getWrapMode()==1) modebits|=(TEXT_WORDWRAP|TEXT_FIXEDWRAP);
4285     if(modes.getTabMode()==0) modebits&=~TEXT_NO_TABS;
4286     if(modes.getTabMode()==1) modebits|=TEXT_NO_TABS;
4287 
4288     // Tab and wrap widths
4289     if(modes.getTabWidth()>0) tabwidth=modes.getTabWidth();
4290     if(modes.getWrapWidth()>0) wrapwidth=modes.getWrapWidth();
4291 
4292     // Put back (modified) parameters
4293     editor->setTextStyle(modebits);
4294     editor->setTabColumns(tabwidth);
4295     editor->setWrapColumns(wrapwidth);
4296     }
4297   }
4298 
4299 /*******************************************************************************/
4300 
4301 // Determine language
4302 // If modeline support is turned on, parse chunk of the file to get the modeline-
4303 // settable parameters.  If modeline is turned on and syntax mapping not forced by
4304 // user, use the one provided by the modeline.  Override editor settings with those
4305 // from modeline regardless of how language-mode was resolved.
determineSyntax()4306 void TextWindow::determineSyntax(){
4307   FXString file(FXPath::name(getFilename()));
4308 
4309   // This filename was to be directly associated with a particular syntax
4310   // Ignore syntax settings in the modeline, user has explicitly set it
4311   Syntax* stx=getApp()->getSyntaxByRegistry(file);
4312   if(!stx){
4313 
4314     // Use the syntax whose wildcards match the given filename
4315     stx=getApp()->getSyntaxByPattern(file);
4316     if(!stx){
4317       FXString lines;
4318 
4319       // Grab up to here
4320       FXint pos=editor->nextLine(0,30);
4321 
4322       // Grab some lines of the top of the file and see if it contains
4323       // anything one of the syntaxes would match against
4324       editor->extractText(lines,0,pos);
4325 
4326       // Use the syntax matching some regex patterns inside the file
4327       stx=getApp()->getSyntaxByContents(lines);
4328       }
4329     }
4330 
4331   // Change the syntax coloring scheme
4332   setSyntax(stx);
4333   }
4334 
4335 
4336 // Switch syntax
onCmdSyntaxSwitch(FXObject *,FXSelector sel,void *)4337 long TextWindow::onCmdSyntaxSwitch(FXObject*,FXSelector sel,void*){
4338   FXint syn=FXSELID(sel)-ID_SYNTAX_FIRST;
4339   FXString file=FXPath::name(getFilename());
4340   if(0<syn){
4341     getApp()->reg().writeStringEntry("SYNTAX",file,getApp()->syntaxes[syn-1]->getName().text());
4342     setSyntax(getApp()->syntaxes[syn-1]);
4343     }
4344   else{
4345     getApp()->reg().deleteEntry("SYNTAX",file);
4346     setSyntax(NULL);
4347     }
4348   return 1;
4349   }
4350 
4351 
4352 // Switch syntax
onUpdSyntaxSwitch(FXObject * sender,FXSelector sel,void *)4353 long TextWindow::onUpdSyntaxSwitch(FXObject* sender,FXSelector sel,void*){
4354   FXint syn=FXSELID(sel)-ID_SYNTAX_FIRST;
4355   FXASSERT(0<=syn && syn<=getApp()->syntaxes.no());
4356   Syntax *sntx=syn?getApp()->syntaxes[syn-1]:NULL;
4357   sender->handle(this,(sntx==syntax)?FXSEL(SEL_COMMAND,ID_CHECK):FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
4358   return 1;
4359   }
4360 
4361 /*******************************************************************************/
4362 
4363 // Change normal foreground color
onCmdStyleNormalFG(FXObject * sender,FXSelector sel,void *)4364 long TextWindow::onCmdStyleNormalFG(FXObject* sender,FXSelector sel,void*){
4365   FXint index=FXSELID(sel)-ID_STYLE_NORMAL_FG_FIRST;
4366   sender->handle(this,FXSEL(SEL_COMMAND,ID_GETINTVALUE),(void*)&styles[index].normalForeColor);
4367   writeStyleForRule(syntax->getGroup(),syntax->getRule(index+1)->getName(),styles[index]);
4368   editor->update();
4369   return 1;
4370   }
4371 
4372 // Update normal foreground color
onUpdStyleNormalFG(FXObject * sender,FXSelector sel,void *)4373 long TextWindow::onUpdStyleNormalFG(FXObject* sender,FXSelector sel,void*){
4374   FXint index=FXSELID(sel)-ID_STYLE_NORMAL_FG_FIRST;
4375   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&styles[index].normalForeColor);
4376   return 1;
4377   }
4378 
4379 
4380 // Change normal background color
onCmdStyleNormalBG(FXObject * sender,FXSelector sel,void *)4381 long TextWindow::onCmdStyleNormalBG(FXObject* sender,FXSelector sel,void*){
4382   FXint index=FXSELID(sel)-ID_STYLE_NORMAL_BG_FIRST;
4383   sender->handle(this,FXSEL(SEL_COMMAND,ID_GETINTVALUE),(void*)&styles[index].normalBackColor);
4384   writeStyleForRule(syntax->getGroup(),syntax->getRule(index+1)->getName(),styles[index]);
4385   editor->update();
4386   return 1;
4387   }
4388 
4389 // Update normal background color
onUpdStyleNormalBG(FXObject * sender,FXSelector sel,void *)4390 long TextWindow::onUpdStyleNormalBG(FXObject* sender,FXSelector sel,void*){
4391   FXint index=FXSELID(sel)-ID_STYLE_NORMAL_BG_FIRST;
4392   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&styles[index].normalBackColor);
4393   return 1;
4394   }
4395 
4396 
4397 // Change selected foreground color
onCmdStyleSelectFG(FXObject * sender,FXSelector sel,void *)4398 long TextWindow::onCmdStyleSelectFG(FXObject* sender,FXSelector sel,void*){
4399   FXint index=FXSELID(sel)-ID_STYLE_SELECT_FG_FIRST;
4400   sender->handle(this,FXSEL(SEL_COMMAND,ID_GETINTVALUE),(void*)&styles[index].selectForeColor);
4401   writeStyleForRule(syntax->getGroup(),syntax->getRule(index+1)->getName(),styles[index]);
4402   editor->update();
4403   return 1;
4404   }
4405 
4406 // Update selected foreground color
onUpdStyleSelectFG(FXObject * sender,FXSelector sel,void *)4407 long TextWindow::onUpdStyleSelectFG(FXObject* sender,FXSelector sel,void*){
4408   FXint index=FXSELID(sel)-ID_STYLE_SELECT_FG_FIRST;
4409   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&styles[index].selectForeColor);
4410   return 1;
4411   }
4412 
4413 
4414 // Change selected background color
onCmdStyleSelectBG(FXObject * sender,FXSelector sel,void *)4415 long TextWindow::onCmdStyleSelectBG(FXObject* sender,FXSelector sel,void*){
4416   FXint index=FXSELID(sel)-ID_STYLE_SELECT_BG_FIRST;
4417   sender->handle(this,FXSEL(SEL_COMMAND,ID_GETINTVALUE),(void*)&styles[index].selectBackColor);
4418   writeStyleForRule(syntax->getGroup(),syntax->getRule(index+1)->getName(),styles[index]);
4419   editor->update();
4420   return 1;
4421   }
4422 
4423 // Update selected background color
onUpdStyleSelectBG(FXObject * sender,FXSelector sel,void *)4424 long TextWindow::onUpdStyleSelectBG(FXObject* sender,FXSelector sel,void*){
4425   FXint index=FXSELID(sel)-ID_STYLE_SELECT_BG_FIRST;
4426   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&styles[index].selectBackColor);
4427   return 1;
4428   }
4429 
4430 
4431 // Change highlight foreground color
onCmdStyleHiliteFG(FXObject * sender,FXSelector sel,void *)4432 long TextWindow::onCmdStyleHiliteFG(FXObject* sender,FXSelector sel,void*){
4433   FXint index=FXSELID(sel)-ID_STYLE_HILITE_FG_FIRST;
4434   sender->handle(this,FXSEL(SEL_COMMAND,ID_GETINTVALUE),(void*)&styles[index].hiliteForeColor);
4435   writeStyleForRule(syntax->getGroup(),syntax->getRule(index+1)->getName(),styles[index]);
4436   editor->update();
4437   return 1;
4438   }
4439 
4440 // Update highlight foreground color
onUpdStyleHiliteFG(FXObject * sender,FXSelector sel,void *)4441 long TextWindow::onUpdStyleHiliteFG(FXObject* sender,FXSelector sel,void*){
4442   FXint index=FXSELID(sel)-ID_STYLE_HILITE_FG_FIRST;
4443   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&styles[index].hiliteForeColor);
4444   return 1;
4445   }
4446 
4447 
4448 // Change highlight background color
onCmdStyleHiliteBG(FXObject * sender,FXSelector sel,void *)4449 long TextWindow::onCmdStyleHiliteBG(FXObject* sender,FXSelector sel,void*){
4450   FXint index=FXSELID(sel)-ID_STYLE_HILITE_BG_FIRST;
4451   sender->handle(this,FXSEL(SEL_COMMAND,ID_GETINTVALUE),(void*)&styles[index].hiliteBackColor);
4452   writeStyleForRule(syntax->getGroup(),syntax->getRule(index+1)->getName(),styles[index]);
4453   editor->update();
4454   return 1;
4455   }
4456 
4457 // Update highlight background color
onUpdStyleHiliteBG(FXObject * sender,FXSelector sel,void *)4458 long TextWindow::onUpdStyleHiliteBG(FXObject* sender,FXSelector sel,void*){
4459   FXint index=FXSELID(sel)-ID_STYLE_HILITE_BG_FIRST;
4460   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&styles[index].hiliteBackColor);
4461   return 1;
4462   }
4463 
4464 
4465 // Change active background color
onCmdStyleActiveBG(FXObject * sender,FXSelector sel,void *)4466 long TextWindow::onCmdStyleActiveBG(FXObject* sender,FXSelector sel,void*){
4467   FXint index=FXSELID(sel)-ID_STYLE_ACTIVE_BG_FIRST;
4468   sender->handle(this,FXSEL(SEL_COMMAND,ID_GETINTVALUE),(void*)&styles[index].activeBackColor);
4469   writeStyleForRule(syntax->getGroup(),syntax->getRule(index+1)->getName(),styles[index]);
4470   editor->update();
4471   return 1;
4472   }
4473 
4474 // Update active background color
onUpdStyleActiveBG(FXObject * sender,FXSelector sel,void *)4475 long TextWindow::onUpdStyleActiveBG(FXObject* sender,FXSelector sel,void*){
4476   FXint index=FXSELID(sel)-ID_STYLE_ACTIVE_BG_FIRST;
4477   sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&styles[index].activeBackColor);
4478   return 1;
4479   }
4480 
4481 
4482 // Change underline style
onCmdStyleUnderline(FXObject *,FXSelector sel,void *)4483 long TextWindow::onCmdStyleUnderline(FXObject*,FXSelector sel,void*){
4484   FXint index=FXSELID(sel)-ID_STYLE_UNDERLINE_FIRST;
4485   styles[index].style^=FXText::STYLE_UNDERLINE;
4486   writeStyleForRule(syntax->getGroup(),syntax->getRule(index+1)->getName(),styles[index]);
4487   editor->update();
4488   return 1;
4489   }
4490 
4491 // Update underline style
onUpdStyleUnderline(FXObject * sender,FXSelector sel,void *)4492 long TextWindow::onUpdStyleUnderline(FXObject* sender,FXSelector sel,void*){
4493   FXint index=FXSELID(sel)-ID_STYLE_UNDERLINE_FIRST;
4494   sender->handle(this,(styles[index].style&FXText::STYLE_UNDERLINE)?FXSEL(SEL_COMMAND,ID_CHECK):FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
4495   return 1;
4496   }
4497 
4498 
4499 // Change strikeout style
onCmdStyleStrikeout(FXObject *,FXSelector sel,void *)4500 long TextWindow::onCmdStyleStrikeout(FXObject*,FXSelector sel,void*){
4501   FXint index=FXSELID(sel)-ID_STYLE_STRIKEOUT_FIRST;
4502   styles[index].style^=FXText::STYLE_STRIKEOUT;
4503   writeStyleForRule(syntax->getGroup(),syntax->getRule(index+1)->getName(),styles[index]);
4504   editor->update();
4505   return 1;
4506   }
4507 
4508 // Update strikeout style
onUpdStyleStrikeout(FXObject * sender,FXSelector sel,void *)4509 long TextWindow::onUpdStyleStrikeout(FXObject* sender,FXSelector sel,void*){
4510   FXint index=FXSELID(sel)-ID_STYLE_STRIKEOUT_FIRST;
4511   sender->handle(this,(styles[index].style&FXText::STYLE_STRIKEOUT)?FXSEL(SEL_COMMAND,ID_CHECK):FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
4512   return 1;
4513   }
4514 
4515 
4516 // Change bold style
onCmdStyleBold(FXObject *,FXSelector sel,void *)4517 long TextWindow::onCmdStyleBold(FXObject*,FXSelector sel,void*){
4518   FXint index=FXSELID(sel)-ID_STYLE_BOLD_FIRST;
4519   styles[index].style^=FXText::STYLE_BOLD;
4520   writeStyleForRule(syntax->getGroup(),syntax->getRule(index+1)->getName(),styles[index]);
4521   editor->update();
4522   return 1;
4523   }
4524 
4525 // Update bold style
onUpdStyleBold(FXObject * sender,FXSelector sel,void *)4526 long TextWindow::onUpdStyleBold(FXObject* sender,FXSelector sel,void*){
4527   FXint index=FXSELID(sel)-ID_STYLE_BOLD_FIRST;
4528   sender->handle(this,(styles[index].style&FXText::STYLE_BOLD)?FXSEL(SEL_COMMAND,ID_CHECK):FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
4529   return 1;
4530   }
4531 
4532 /*******************************************************************************/
4533 
4534 // Set language
setSyntax(Syntax * syn)4535 void TextWindow::setSyntax(Syntax* syn){
4536   syntax=syn;
4537 
4538   // Set editor attributes to syntax mode
4539   if(syntax){
4540 
4541     // Get original parameters
4542     FXuint modebits=editor->getTextStyle();
4543     FXint  tabwidth=editor->getTabColumns();
4544     FXint  wrapwidth=editor->getWrapColumns();
4545 
4546     // Set number of syntax styles
4547     styles.no(syntax->getNumRules()-1);
4548 
4549     // Read attributes for each style
4550     for(FXint rule=1; rule<syntax->getNumRules(); rule++){
4551       styles[rule-1]=readStyleForRule(syntax->getGroup(),syntax->getRule(rule)->getName(),syntax->getRule(rule)->getStyle());
4552       }
4553 
4554     // Set styles
4555     editor->setHiliteStyles(styles.data());
4556     editor->setStyled(colorize);
4557 
4558     // Other syntax-determined stuff
4559     editor->setDelimiters(syntax->getDelimiters().text());
4560 
4561     // Modes from the syntax
4562     if(syntax->getAutoIndent()==0) modebits&=~TEXT_AUTOINDENT;
4563     if(syntax->getAutoIndent()==1) modebits|=TEXT_AUTOINDENT;
4564     if(syntax->getWrapMode()==0) modebits&=~(TEXT_WORDWRAP|TEXT_FIXEDWRAP);
4565     if(syntax->getWrapMode()==1) modebits|=(TEXT_WORDWRAP|TEXT_FIXEDWRAP);
4566     if(syntax->getTabMode()==0) modebits&=~TEXT_NO_TABS;
4567     if(syntax->getTabMode()==1) modebits|=TEXT_NO_TABS;
4568 
4569     // Tab and wrap widths
4570     if(syntax->getTabWidth()>0) tabwidth=syntax->getTabWidth();
4571     if(syntax->getWrapWidth()>0) wrapwidth=syntax->getWrapWidth();
4572 
4573     // Put back (modified) parameters
4574     editor->setTextStyle(modebits);
4575     editor->setTabColumns(tabwidth);
4576     editor->setWrapColumns(wrapwidth);
4577 
4578     // Full recolorization is called for
4579     restyleText();
4580     }
4581 
4582   // Reset editor attributes to defaults
4583   else{
4584     FXuint modebits=editor->getTextStyle();
4585     editor->setHiliteStyles(NULL);
4586     editor->setStyled(false);
4587     editor->setDelimiters(delimiters.text());
4588     if(autoindent) modebits|=TEXT_AUTOINDENT; else modebits&=~TEXT_AUTOINDENT;
4589     if(wrapping) modebits|=TEXT_WORDWRAP; else modebits&=~TEXT_WORDWRAP;
4590     if(fixedwrap) modebits|=TEXT_FIXEDWRAP; else modebits&=~TEXT_FIXEDWRAP;
4591     if(hardtabs) modebits&=~TEXT_NO_TABS; else modebits|=TEXT_NO_TABS;
4592     editor->setTextStyle(modebits);
4593     editor->setTabColumns(tabcols);
4594     editor->setWrapColumns(wrapcols);
4595     }
4596   }
4597 
4598 
4599 // Read style
readStyleForRule(const FXString & group,const FXString & name,const FXString & style)4600 FXHiliteStyle TextWindow::readStyleForRule(const FXString& group,const FXString& name,const FXString& style){
4601   FXchar nfg[100],nbg[100],sfg[100],sbg[100],hfg[100],hbg[100],abg[100]; FXint sty;
4602   FXHiliteStyle result={0,0,0,0,0,0,0,0};
4603   result.normalForeColor=colorFromName(style);  // Fallback color
4604   if(getApp()->reg().readFormatEntry(group,name,"%99[^,],%99[^,],%99[^,],%99[^,],%99[^,],%99[^,],%99[^,],%d",nfg,nbg,sfg,sbg,hfg,hbg,abg,&sty)==8){
4605     result.normalForeColor=colorFromName(nfg);
4606     result.normalBackColor=colorFromName(nbg);
4607     result.selectForeColor=colorFromName(sfg);
4608     result.selectBackColor=colorFromName(sbg);
4609     result.hiliteForeColor=colorFromName(hfg);
4610     result.hiliteBackColor=colorFromName(hbg);
4611     result.activeBackColor=colorFromName(abg);
4612     result.style=sty;
4613     }
4614   return result;
4615   }
4616 
4617 
4618 // Write style
writeStyleForRule(const FXString & group,const FXString & name,const FXHiliteStyle & style)4619 void TextWindow::writeStyleForRule(const FXString& group,const FXString& name,const FXHiliteStyle& style){
4620   FXchar nfg[100],nbg[100],sfg[100],sbg[100],hfg[100],hbg[100],abg[100];
4621   nameFromColor(nfg,style.normalForeColor);
4622   nameFromColor(nbg,style.normalBackColor);
4623   nameFromColor(sfg,style.selectForeColor);
4624   nameFromColor(sbg,style.selectBackColor);
4625   nameFromColor(hfg,style.hiliteForeColor);
4626   nameFromColor(hbg,style.hiliteBackColor);
4627   nameFromColor(abg,style.activeBackColor);
4628   getApp()->reg().writeFormatEntry(group,name,"%s,%s,%s,%s,%s,%s,%s,%d",nfg,nbg,sfg,sbg,hfg,hbg,abg,style.style);
4629   }
4630 
4631 
4632 // Restyle entire text
restyleText()4633 void TextWindow::restyleText(){
4634   if(colorize && syntax){
4635     FXint head,tail,len;
4636     FXchar *text;
4637     FXchar *style;
4638     len=editor->getLength();
4639     if(allocElms(text,len+len)){
4640       style=text+len;
4641       editor->extractText(text,0,len);
4642       syntax->getRule(0)->stylize(text,style,0,len,head,tail);
4643       editor->changeStyle(0,style,len);
4644       freeElms(text);
4645       }
4646     }
4647   }
4648 
4649 
4650 // Scan backward by context amount
backwardByContext(FXint pos) const4651 FXint TextWindow::backwardByContext(FXint pos) const {
4652   FXint nlines=syntax->getContextLines();
4653   FXint nchars=syntax->getContextChars();
4654   FXint r1=pos;
4655   FXint r2=pos;
4656   if(0<nchars){
4657     r1=editor->validPos(pos-nchars);
4658     }
4659   if(0<nlines){
4660     r2=editor->prevLine(pos,nlines);
4661     }
4662   return FXMAX(0,FXMIN(r1,r2));
4663   }
4664 
4665 
4666 // Scan forward by context amount
forwardByContext(FXint pos) const4667 FXint TextWindow::forwardByContext(FXint pos) const {
4668   FXint nlines=syntax->getContextLines();
4669   FXint nchars=syntax->getContextChars();
4670   FXint r1=pos;
4671   FXint r2=pos;
4672   if(0<nchars){
4673     r1=editor->validPos(pos+nchars);
4674     }
4675   if(0<nlines){
4676     r2=editor->nextLine(pos,nlines);
4677     }
4678   return FXMIN(editor->getLength(),FXMAX(r1,r2));
4679   }
4680 
4681 
4682 // Find restyle point
findRestylePoint(FXint pos,FXint & style) const4683 FXint TextWindow::findRestylePoint(FXint pos,FXint& style) const {
4684   FXint probepos,safepos,beforesafepos,runstyle,s;
4685 
4686   // Return 0 for style unless we found something else
4687   style=0;
4688 
4689   // Scan back by a certain amount of match context
4690   probepos=backwardByContext(pos);
4691 
4692   // At begin of buffer, so restyle from begin
4693   if(probepos==0) return 0;
4694 
4695   // Get style here
4696   runstyle=editor->getStyle(probepos);
4697 
4698   // Outside of colorized part, so restyle from here
4699   if(runstyle==0) return probepos;
4700 
4701   // Scan back one more context
4702   safepos=backwardByContext(probepos);
4703 
4704   // And one before that
4705   beforesafepos=backwardByContext(safepos);
4706 
4707   // Scan back for style change
4708   while(0<probepos){
4709 
4710     // Style prior to probe position
4711     s=editor->getStyle(probepos-1);
4712 
4713     // Style change?
4714     if(runstyle!=s){
4715 
4716       // At beginning of child-pattern, return parent style
4717       if(syntax->isAncestor(s,runstyle)){
4718         style=s;
4719         return probepos;
4720         }
4721 
4722       // Before end of child-pattern, return running style
4723       if(syntax->isAncestor(runstyle,s)){
4724         style=runstyle;
4725         return probepos;
4726         }
4727 
4728       // Set common ancestor style
4729       style=syntax->commonAncestor(runstyle,s);
4730       return probepos;
4731       }
4732 
4733     // Scan back
4734     --probepos;
4735 
4736     // Further back
4737     if(probepos<beforesafepos){
4738       style=runstyle;
4739       return safepos;
4740       }
4741     }
4742   return 0;
4743   }
4744 
4745 
4746 // Restyle range; returns affected style end, i.e. one beyond
4747 // the last position where the style changed from the original style
restyleRange(FXint beg,FXint end,FXint & head,FXint & tail,FXint rule)4748 FXint TextWindow::restyleRange(FXint beg,FXint end,FXint& head,FXint& tail,FXint rule){
4749   FXchar *text,*newstyle,*oldstyle;
4750   FXint len=end-beg;
4751   FXint delta=0;
4752   head=0;
4753   tail=0;
4754   FXASSERT(0<=rule && rule<syntax->getNumRules());
4755   FXASSERT(0<=beg && beg<=end && end<=editor->getLength());
4756   if(allocElms(text,len+len+len)){
4757     newstyle=text+len;
4758     oldstyle=text+len+len;
4759     editor->extractText(text,beg,len);
4760     editor->extractStyle(oldstyle,beg,len);
4761     syntax->getRule(rule)->stylizeBody(text,newstyle,0,len,head,tail);
4762     FXASSERT(0<=head && head<=tail && tail<=len);
4763     editor->changeStyle(beg,newstyle,tail);
4764     for(delta=tail; 0<delta && oldstyle[delta-1]==newstyle[delta-1]; --delta){ }
4765     freeElms(text);
4766     }
4767   head+=beg;
4768   tail+=beg;
4769   delta+=beg;
4770   return delta;
4771   }
4772 
4773 
4774 // Restyle text after change in buffer
restyleText(FXint pos,FXint del,FXint ins)4775 void TextWindow::restyleText(FXint pos,FXint del,FXint ins){
4776   FXint head,tail,changed,affected,beg,end,len,rule,restylejump;
4777   FXTRACE((100,"restyleText(pos=%d,del=%d,ins=%d)\n",pos,del,ins));
4778   if(colorize && syntax){
4779 
4780     // Length of text
4781     len=editor->getLength();
4782 
4783     // End of buffer modification
4784     changed=pos+ins;
4785 
4786     // Scan back to a place where the style changed, return
4787     // the style rule in effect at that location
4788     beg=findRestylePoint(pos,rule);
4789 
4790     // Scan forward by one context
4791     end=forwardByContext(changed);
4792 
4793     FXTRACE((110,"pos=%d del=%d ins=%d beg=%d end=%d len=%d rule=%d (%s)\n",pos,del,ins,beg,end,len,rule,syntax->getRule(rule)->getName().text()));
4794 
4795     FXASSERT(0<=rule && rule<syntax->getNumRules());
4796 
4797     // Restyle until we fully enclose the style change
4798     restylejump=RESTYLEJUMP;
4799     while(1){
4800 
4801       // Restyle [beg,end> using rule, return matched range in [head,tail>
4802       affected=restyleRange(beg,end,head,tail,rule);
4803       FXTRACE((110,"affected=%d beg=%d end=%d head=%d tail=%d, rule=%d (%s) \n",affected,beg,end,head,tail,rule,syntax->getRule(rule)->getName().text()));
4804 
4805       // Not all colored yet, continue coloring with parent rule from
4806       if(tail<end){
4807         beg=tail;
4808         end=forwardByContext(FXMAX(affected,changed));
4809         if(rule==0){ fxwarning("Top level patterns did not color everything.\n"); return; }
4810         rule=syntax->getRule(rule)->getParent();
4811         continue;
4812         }
4813 
4814       // Style changed in unchanged text
4815       if(affected>changed){
4816         restylejump<<=1;
4817 	changed=affected;
4818     	end=changed+restylejump;
4819     	if(end>len) end=len;
4820         continue;
4821         }
4822 
4823       // Everything was recolored and style didn't change anymore
4824       return;
4825       }
4826     }
4827   }
4828 
4829 
4830 // Toggle syntax coloring
onCmdSyntax(FXObject *,FXSelector,void * ptr)4831 long TextWindow::onCmdSyntax(FXObject*,FXSelector,void* ptr){
4832   colorize=(FXbool)(FXuval)ptr;
4833   if(syntax && colorize){
4834     editor->setStyled(true);
4835     restyleText();
4836     }
4837   else{
4838     editor->setStyled(false);
4839     }
4840   return 1;
4841   }
4842 
4843 
4844 // Update syntax coloring
onUpdSyntax(FXObject * sender,FXSelector,void *)4845 long TextWindow::onUpdSyntax(FXObject* sender,FXSelector,void*){
4846   sender->handle(this,colorize?FXSEL(SEL_COMMAND,ID_CHECK):FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
4847   return 1;
4848   }
4849 
4850 
4851 // Restyle text
onCmdRestyle(FXObject *,FXSelector,void *)4852 long TextWindow::onCmdRestyle(FXObject*,FXSelector,void*){
4853   restyleText();
4854   return 1;
4855   }
4856 
4857 
4858 // Update restyle text
onUpdRestyle(FXObject * sender,FXSelector,void *)4859 long TextWindow::onUpdRestyle(FXObject* sender,FXSelector,void*){
4860   sender->handle(this,editor->isStyled()?FXSEL(SEL_COMMAND,ID_ENABLE):FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
4861   return 1;
4862   }
4863 
4864 
4865 // Show syntax in tooltip
4866 // FIXME for now, we show the syntax rule; but in the future,
4867 // we will show more interesting stuff than that.
onQueryTextTip(FXObject * sender,FXSelector,void *)4868 long TextWindow::onQueryTextTip(FXObject* sender,FXSelector,void*){
4869   if(getSyntax() && editor->isStyled()){
4870     FXint vx=editor->getVisibleX();
4871     FXint vy=editor->getVisibleY();
4872     FXint vw=editor->getVisibleWidth();
4873     FXint vh=editor->getVisibleHeight();
4874     FXint pos,x,y,s;
4875     FXuint btns;
4876     if(editor->getCursorPosition(x,y,btns)){
4877       if(vx<=x && vy<=y && x<vx+vw && y<vy+vh){
4878         pos=editor->getPosAt(x,y);
4879         s=editor->getStyle(pos);
4880         if(0<s && s<getSyntax()->getNumRules()){
4881           FXString tipstring=getSyntax()->getRule(s)->getName();
4882           sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&tipstring);
4883           return 1;
4884           }
4885         }
4886       }
4887     }
4888   return 0;
4889   }
4890