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