1 // This is adapted from 'adie', a text editor found
2 // in the FOX library and written by Jeroen van der Zijp.
3 
4 #include "config.h"
5 #include "i18n.h"
6 
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <sys/stat.h>
10 #include <sys/wait.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <signal.h>
14 
15 #include <fx.h>
16 #include <fxkeys.h>
17 #include <FXPNGIcon.h>
18 #include <FX88591Codec.h>
19 #include <FXUTF16Codec.h>
20 
21 #include "xfedefs.h"
22 #include "icons.h"
23 #include "xfeutils.h"
24 #include "startupnotification.h"
25 #include "FileDialog.h"
26 #include "FontDialog.h"
27 #include "MessageBox.h"
28 #include "InputDialog.h"
29 #include "WriteWindow.h"
30 #include "XFileWrite.h"
31 
32 
33 extern FXbool allowPopupScroll;
34 FXbool        save_win_pos;
35 
36 
37 FXIMPLEMENT_ABSTRACT(FXTextCommand, FXCommand, NULL, 0)
38 
39 // Return size of record plus any data kept here
size() const40 FXuint FXTextCommand::size() const
41 {
42     return(sizeof(FXTextCommand)+ndel);
43 }
44 
45 
46 FXIMPLEMENT_ABSTRACT(FXTextInsert, FXTextCommand, NULL, 0)
47 
48 // Insert command
FXTextInsert(FXText * txt,int p,int ni,const char * ins)49 FXTextInsert::FXTextInsert(FXText* txt, int p, int ni, const char* ins) : FXTextCommand(txt, p, 0, ni)
50 {
51     FXMALLOC(&buffer, char, ni);
52     memcpy(buffer, ins, ni);
53 }
54 
55 
56 // Undo an insert removes the inserted text
undo()57 void FXTextInsert::undo()
58 {
59     text->removeText(pos, nins, true);
60     text->setCursorPos(pos);
61     text->makePositionVisible(pos);
62 }
63 
64 
65 // Redo an insert inserts the same old text again
redo()66 void FXTextInsert::redo()
67 {
68     text->insertText(pos, buffer, nins, true);
69     text->setCursorPos(pos+nins);
70     text->makePositionVisible(pos+nins);
71 }
72 
73 
74 FXIMPLEMENT_ABSTRACT(FXTextDelete, FXTextCommand, NULL, 0)
75 
76 // Delete command
FXTextDelete(FXText * txt,int p,int nd,const char * del)77 FXTextDelete::FXTextDelete(FXText* txt, int p, int nd, const char* del) : FXTextCommand(txt, p, nd, 0)
78 {
79     FXMALLOC(&buffer, char, nd);
80     memcpy(buffer, del, nd);
81 }
82 
83 
84 // Undo a delete reinserts the old text
undo()85 void FXTextDelete::undo()
86 {
87     text->insertText(pos, buffer, ndel, true);
88     text->setCursorPos(pos+ndel);
89     text->makePositionVisible(pos+ndel);
90 }
91 
92 
93 // Redo a delete removes it again
redo()94 void FXTextDelete::redo()
95 {
96     text->removeText(pos, ndel, true);
97     text->setCursorPos(pos);
98     text->makePositionVisible(pos);
99 }
100 
101 
102 FXIMPLEMENT_ABSTRACT(FXTextReplace, FXTextCommand, NULL, 0)
103 
104 // Replace command
FXTextReplace(FXText * txt,int p,int nd,int ni,const char * del,const char * ins)105 FXTextReplace::FXTextReplace(FXText* txt, int p, int nd, int ni, const char* del, const char* ins) : FXTextCommand(txt, p, nd, ni)
106 {
107     FXMALLOC(&buffer, char, nd+ni);
108     memcpy(buffer, del, nd);
109     memcpy(buffer+nd, ins, ni);
110 }
111 
112 
113 // Undo a replace reinserts the old text
undo()114 void FXTextReplace::undo()
115 {
116     text->replaceText(pos, nins, buffer, ndel, true);
117     text->setCursorPos(pos+ndel);
118     text->makePositionVisible(pos+ndel);
119 }
120 
121 
122 // Redo a replace reinserts the new text
redo()123 void FXTextReplace::redo()
124 {
125     text->replaceText(pos, ndel, buffer+ndel, nins, true);
126     text->setCursorPos(pos+nins);
127     text->makePositionVisible(pos+nins);
128 }
129 
130 
131 // Preferences class
132 
133 // Map
134 FXDEFMAP(Preferences) PreferencesMap[] =
135 {
136     FXMAPFUNC(SEL_COMMAND, Preferences::ID_ACCEPT, Preferences::onCmdAccept),
137     FXMAPFUNC(SEL_COMMAND, Preferences::ID_CANCEL, Preferences::onCmdCancel),
138     FXMAPFUNC(SEL_COMMAND, Preferences::ID_TEXT_BACK, Preferences::onCmdTextBackColor),
139     FXMAPFUNC(SEL_CHANGED, Preferences::ID_TEXT_BACK, Preferences::onCmdTextBackColor),
140     FXMAPFUNC(SEL_UPDATE, Preferences::ID_TEXT_BACK, Preferences::onUpdTextBackColor),
141     FXMAPFUNC(SEL_COMMAND, Preferences::ID_TEXT_FORE, Preferences::onCmdTextForeColor),
142     FXMAPFUNC(SEL_CHANGED, Preferences::ID_TEXT_FORE, Preferences::onCmdTextForeColor),
143     FXMAPFUNC(SEL_UPDATE, Preferences::ID_TEXT_FORE, Preferences::onUpdTextForeColor),
144     FXMAPFUNC(SEL_COMMAND, Preferences::ID_TEXT_SELBACK, Preferences::onCmdTextSelBackColor),
145     FXMAPFUNC(SEL_CHANGED, Preferences::ID_TEXT_SELBACK, Preferences::onCmdTextSelBackColor),
146     FXMAPFUNC(SEL_UPDATE, Preferences::ID_TEXT_SELBACK, Preferences::onUpdTextSelBackColor),
147     FXMAPFUNC(SEL_COMMAND, Preferences::ID_TEXT_SELFORE, Preferences::onCmdTextSelForeColor),
148     FXMAPFUNC(SEL_CHANGED, Preferences::ID_TEXT_SELFORE, Preferences::onCmdTextSelForeColor),
149     FXMAPFUNC(SEL_UPDATE, Preferences::ID_TEXT_SELFORE, Preferences::onUpdTextSelForeColor),
150     FXMAPFUNC(SEL_COMMAND, Preferences::ID_TEXT_HILITEBACK, Preferences::onCmdTextHiliteBackColor),
151     FXMAPFUNC(SEL_CHANGED, Preferences::ID_TEXT_HILITEBACK, Preferences::onCmdTextHiliteBackColor),
152     FXMAPFUNC(SEL_UPDATE, Preferences::ID_TEXT_HILITEBACK, Preferences::onUpdTextHiliteBackColor),
153     FXMAPFUNC(SEL_COMMAND, Preferences::ID_TEXT_HILITEFORE, Preferences::onCmdTextHiliteForeColor),
154     FXMAPFUNC(SEL_CHANGED, Preferences::ID_TEXT_HILITEFORE, Preferences::onCmdTextHiliteForeColor),
155     FXMAPFUNC(SEL_UPDATE, Preferences::ID_TEXT_HILITEFORE, Preferences::onUpdTextHiliteForeColor),
156     FXMAPFUNC(SEL_COMMAND, Preferences::ID_TEXT_CURSOR, Preferences::onCmdTextCursorColor),
157     FXMAPFUNC(SEL_CHANGED, Preferences::ID_TEXT_CURSOR, Preferences::onCmdTextCursorColor),
158     FXMAPFUNC(SEL_UPDATE, Preferences::ID_TEXT_CURSOR, Preferences::onUpdTextCursorColor),
159     FXMAPFUNC(SEL_COMMAND, Preferences::ID_TEXT_NUMBACK, Preferences::onCmdTextBarColor),
160     FXMAPFUNC(SEL_CHANGED, Preferences::ID_TEXT_NUMBACK, Preferences::onCmdTextBarColor),
161     FXMAPFUNC(SEL_UPDATE, Preferences::ID_TEXT_NUMBACK, Preferences::onUpdTextBarColor),
162     FXMAPFUNC(SEL_COMMAND, Preferences::ID_TEXT_NUMFORE, Preferences::onCmdTextNumberColor),
163     FXMAPFUNC(SEL_CHANGED, Preferences::ID_TEXT_NUMFORE, Preferences::onCmdTextNumberColor),
164     FXMAPFUNC(SEL_UPDATE, Preferences::ID_TEXT_NUMFORE, Preferences::onUpdTextNumberColor),
165 };
166 
167 // Object implementation
FXIMPLEMENT(Preferences,DialogBox,PreferencesMap,ARRAYNUMBER (PreferencesMap))168 FXIMPLEMENT(Preferences, DialogBox, PreferencesMap, ARRAYNUMBER(PreferencesMap))
169 
170 // Construct
171 Preferences::Preferences(WriteWindow* owner) : DialogBox(owner, _("XFileWrite Preferences"), DECOR_TITLE|DECOR_BORDER|DECOR_MAXIMIZE|DECOR_STRETCHABLE|DECOR_CLOSE)
172 {
173     // Get the editor text widget from the owner
174     editwin = owner;
175     editor = owner->getEditor();
176 
177     // Set title
178     setTitle(_("XFileWrite Preferences"));
179 
180     // Buttons
181     FXHorizontalFrame* buttons = new FXHorizontalFrame(this, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X, 0, 0, 0, 0, 10, 10, 5, 5);
182 
183     // Contents
184     FXHorizontalFrame* contents = new FXHorizontalFrame(this, LAYOUT_SIDE_TOP|FRAME_NONE|LAYOUT_FILL_X|LAYOUT_FILL_Y|PACK_UNIFORM_WIDTH);
185 
186     // Accept
187     FXButton* ok = new FXButton(buttons, _("&Accept"), NULL, this, Preferences::ID_ACCEPT, FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT|LAYOUT_CENTER_Y, 0, 0, 0, 0, 20, 20);
188     ok->addHotKey(KEY_Return);
189 
190     // Cancel
191     new FXButton(buttons, _("&Cancel"), NULL, this, Preferences::ID_CANCEL, FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT|LAYOUT_CENTER_Y, 0, 0, 0, 0, 20, 20);
192 
193     // Switcher
194     FXTabBook* tabbook = new FXTabBook(contents, NULL, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_RIGHT);
195 
196     // First tab - Editor
197     new FXTabItem(tabbook, _("&Editor"), NULL);
198     FXVerticalFrame* editor = new FXVerticalFrame(tabbook, FRAME_RAISED);
199     FXGroupBox*      group = new FXGroupBox(editor, _("Text"), GROUPBOX_TITLE_LEFT|FRAME_GROOVE|LAYOUT_FILL_X);
200     FXMatrix*        matrix = new FXMatrix(group, 2, MATRIX_BY_COLUMNS|LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y);
201 
202     new FXLabel(matrix, _("Wrap margin:"), NULL, JUSTIFY_LEFT|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
203     wrapmargin = new FXTextField(matrix, 10, NULL, 0, TEXTFIELD_INTEGER|JUSTIFY_RIGHT|FRAME_SUNKEN|FRAME_THICK|LAYOUT_CENTER_Y|LAYOUT_FILL_X|LAYOUT_FILL_ROW, 0, 0, 0, 0, 2, 2, 1, 1);
204     int wrapcols = getApp()->reg().readIntEntry("OPTIONS", "wrapcols", 80);
205     wrapmargin->setText(FXStringVal(wrapcols));
206 
207     new FXLabel(matrix, _("Tabulation size:"), NULL, JUSTIFY_LEFT|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
208     tabsize = new FXTextField(matrix, 10, NULL, 0, TEXTFIELD_INTEGER|JUSTIFY_RIGHT|FRAME_SUNKEN|FRAME_THICK|LAYOUT_CENTER_Y|LAYOUT_FILL_X|LAYOUT_FILL_ROW, 0, 0, 0, 0, 2, 2, 1, 1);
209     int tabcols = getApp()->reg().readIntEntry("OPTIONS", "tabcols", 8);
210     tabsize->setText(FXStringVal(tabcols));
211 
212     new FXLabel(matrix, _("Strip carriage returns:")+(FXString)"                ", NULL, JUSTIFY_LEFT|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
213     stripcr = new FXCheckButton(matrix, FXString(" "), NULL, 0, LAYOUT_LEFT|LAYOUT_CENTER_Y|LAYOUT_FILL_ROW, 0, 0, 0, 0, 0, 0, 0, 0);
214     int stripreturn = getApp()->reg().readIntEntry("OPTIONS", "stripreturn", false);
215     stripcr->setCheck(stripreturn);
216 
217     // Second tab - Colors
218     new FXTabItem(tabbook, _("&Colors"), NULL);
219     FXVerticalFrame* colors = new FXVerticalFrame(tabbook, FRAME_RAISED);
220     group = new FXGroupBox(colors, _("Text"), GROUPBOX_TITLE_LEFT|FRAME_GROOVE|LAYOUT_FILL_X);
221     FXMatrix* matrix1 = new FXMatrix(group, 2, MATRIX_BY_COLUMNS|LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y);
222     group = new FXGroupBox(colors, _("Lines"), GROUPBOX_TITLE_LEFT|FRAME_GROOVE|LAYOUT_FILL_X);
223     FXMatrix* matrix2 = new FXMatrix(group, 2, MATRIX_BY_COLUMNS|LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y);
224 
225     new FXLabel(matrix1, _("Background:"), NULL, JUSTIFY_LEFT|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
226     new FXColorWell(matrix1, FXRGB(0, 0, 0), this, Preferences::ID_TEXT_BACK, FRAME_SUNKEN|FRAME_THICK|LAYOUT_LEFT|LAYOUT_CENTER_Y|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|LAYOUT_FILL_ROW, 0, 0, 40, 24);
227 
228     new FXLabel(matrix1, _("Text:"), NULL, JUSTIFY_LEFT|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
229     new FXColorWell(matrix1, FXRGB(0, 0, 0), this, Preferences::ID_TEXT_FORE, FRAME_SUNKEN|FRAME_THICK|LAYOUT_LEFT|LAYOUT_CENTER_Y|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|LAYOUT_FILL_ROW, 0, 0, 40, 24);
230 
231     new FXLabel(matrix1, _("Selected text background:"), NULL, JUSTIFY_LEFT|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
232     new FXColorWell(matrix1, FXRGB(0, 0, 0), this, Preferences::ID_TEXT_SELBACK, FRAME_SUNKEN|FRAME_THICK|LAYOUT_LEFT|LAYOUT_CENTER_Y|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|LAYOUT_FILL_ROW, 0, 0, 40, 24);
233 
234     new FXLabel(matrix1, _("Selected text:"), NULL, JUSTIFY_LEFT|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
235     new FXColorWell(matrix1, FXRGB(0, 0, 0), this, Preferences::ID_TEXT_SELFORE, FRAME_SUNKEN|FRAME_THICK|LAYOUT_LEFT|LAYOUT_CENTER_Y|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|LAYOUT_FILL_ROW, 0, 0, 40, 24);
236 
237     new FXLabel(matrix1, _("Highlighted text background:"), NULL, JUSTIFY_LEFT|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
238     new FXColorWell(matrix1, FXRGB(0, 0, 0), this, Preferences::ID_TEXT_HILITEBACK, FRAME_SUNKEN|FRAME_THICK|LAYOUT_LEFT|LAYOUT_CENTER_Y|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|LAYOUT_FILL_ROW, 0, 0, 40, 24);
239 
240     new FXLabel(matrix1, _("Highlighted text:"), NULL, JUSTIFY_LEFT|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
241     new FXColorWell(matrix1, FXRGB(0, 0, 0), this, Preferences::ID_TEXT_HILITEFORE, FRAME_SUNKEN|FRAME_THICK|LAYOUT_LEFT|LAYOUT_CENTER_Y|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|LAYOUT_FILL_ROW, 0, 0, 40, 24);
242 
243     new FXLabel(matrix1, _("Cursor:"), NULL, JUSTIFY_LEFT|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
244     new FXColorWell(matrix1, FXRGB(0, 0, 0), this, Preferences::ID_TEXT_CURSOR, FRAME_SUNKEN|FRAME_THICK|LAYOUT_LEFT|LAYOUT_CENTER_Y|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|LAYOUT_FILL_ROW, 0, 0, 40, 24);
245 
246     new FXLabel(matrix2, _("Line numbers background:"), NULL, JUSTIFY_LEFT|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
247     new FXColorWell(matrix2, FXRGB(0, 0, 0), this, Preferences::ID_TEXT_NUMBACK, FRAME_SUNKEN|FRAME_THICK|LAYOUT_LEFT|LAYOUT_CENTER_Y|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|LAYOUT_FILL_ROW, 0, 0, 40, 24);
248 
249     new FXLabel(matrix2, _("Line numbers foreground:"), NULL, JUSTIFY_LEFT|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW);
250     new FXColorWell(matrix2, FXRGB(0, 0, 0), this, Preferences::ID_TEXT_NUMFORE, FRAME_SUNKEN|FRAME_THICK|LAYOUT_LEFT|LAYOUT_CENTER_Y|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|LAYOUT_FILL_ROW, 0, 0, 40, 24);
251 
252     // Class variable initializations
253     stripcr_prev = false;
254     textcolor_prev = FXRGB(0, 0, 0);
255     backcolor_prev = FXRGB(0, 0, 0);
256     textcolor_prev = FXRGB(0, 0, 0);
257     backcolor_prev = FXRGB(0, 0, 0);
258     seltextcolor_prev = FXRGB(0, 0, 0);
259     selbackcolor_prev = FXRGB(0, 0, 0);
260     hilitetextcolor_prev = FXRGB(0, 0, 0);
261     hilitebackcolor_prev = FXRGB(0, 0, 0);
262     cursorcolor_prev = FXRGB(0, 0, 0);
263     barcolor_prev = FXRGB(0, 0, 0);
264     numbercolor_prev = FXRGB(0, 0, 0);
265 }
266 
267 
onCmdAccept(FXObject * o,FXSelector s,void * p)268 long Preferences::onCmdAccept(FXObject* o, FXSelector s, void* p)
269 {
270     // Update preferences to their new values
271 
272     editor->setWrapColumns(FXIntVal(wrapmargin->getText()));
273     getApp()->reg().writeIntEntry("OPTIONS", "wrapcols", FXIntVal(wrapmargin->getText()));
274 
275     editor->setTabColumns(FXIntVal(tabsize->getText()));
276     getApp()->reg().writeIntEntry("OPTIONS", "tabcols", FXIntVal(tabsize->getText()));
277 
278     editor->setTabColumns(FXIntVal(tabsize->getText()));
279     getApp()->reg().writeIntEntry("OPTIONS", "tabcols", FXIntVal(tabsize->getText()));
280 
281     editwin->setStripcr(stripcr->getCheck());
282     getApp()->reg().writeIntEntry("OPTIONS", "stripreturn", stripcr->getCheck());
283 
284 
285     // Finally, update the registry
286     getApp()->reg().write();
287 
288     DialogBox::onCmdAccept(o, s, p);
289 
290     return(1);
291 }
292 
293 
onCmdCancel(FXObject * o,FXSelector s,void * p)294 long Preferences::onCmdCancel(FXObject* o, FXSelector s, void* p)
295 {
296     // Reset preferences to their previous values
297 
298     // First tab - Editor
299     wrapmargin->setText(wrapmargin_prev);
300     tabsize->setText(tabsize_prev);
301     stripcr->setCheck(stripcr_prev);
302 
303     // Second tab - Colors
304     editor->setTextColor(textcolor_prev);
305     editor->setBackColor(backcolor_prev);
306     editor->setSelTextColor(seltextcolor_prev);
307     editor->setSelBackColor(selbackcolor_prev);
308     editor->setHiliteTextColor(hilitetextcolor_prev);
309     editor->setHiliteBackColor(hilitebackcolor_prev);
310     editor->setCursorColor(cursorcolor_prev);
311     editor->setBarColor(barcolor_prev);
312     editor->setNumberColor(numbercolor_prev);
313 
314     DialogBox::onCmdCancel(o, s, p);
315     return(1);
316 }
317 
318 
319 // Execute dialog box modally
execute(FXuint placement)320 FXuint Preferences::execute(FXuint placement)
321 {
322     // Save current preferences to restore them if cancel is pressed
323 
324     // First tab - Editor
325     wrapmargin_prev = wrapmargin->getText();
326     tabsize_prev = tabsize->getText();
327     stripcr_prev = stripcr->getCheck();
328 
329     // Second tab - Colors
330     textcolor_prev = editor->getTextColor();
331     backcolor_prev = editor->getBackColor();
332     seltextcolor_prev = editor->getSelTextColor();
333     selbackcolor_prev = editor->getSelBackColor();
334     hilitetextcolor_prev = editor->getHiliteTextColor();
335     hilitebackcolor_prev = editor->getHiliteBackColor();
336     cursorcolor_prev = editor->getCursorColor();
337     barcolor_prev = editor->getBarColor();
338     numbercolor_prev = editor->getNumberColor();
339 
340     // Display dialog
341     create();
342     show(placement);
343     getApp()->refresh();
344     return(getApp()->runModalFor(this));
345 }
346 
347 
348 // Change text color
onCmdTextForeColor(FXObject *,FXSelector,void * ptr)349 long Preferences::onCmdTextForeColor(FXObject*, FXSelector, void* ptr)
350 {
351     editor->setTextColor((FXColor)(FXuval)ptr);
352     return(1);
353 }
354 
355 
356 // Update text color
onUpdTextForeColor(FXObject * sender,FXSelector,void *)357 long Preferences::onUpdTextForeColor(FXObject* sender, FXSelector, void*)
358 {
359     FXColor color = editor->getTextColor();
360 
361     sender->handle(this, FXSEL(SEL_COMMAND, ID_SETINTVALUE), (void*)&color);
362     return(1);
363 }
364 
365 
366 // Change text background color
onCmdTextBackColor(FXObject *,FXSelector,void * ptr)367 long Preferences::onCmdTextBackColor(FXObject*, FXSelector, void* ptr)
368 {
369     editor->setBackColor((FXColor)(FXuval)ptr);
370     return(1);
371 }
372 
373 
374 // Update background color
onUpdTextBackColor(FXObject * sender,FXSelector,void *)375 long Preferences::onUpdTextBackColor(FXObject* sender, FXSelector, void*)
376 {
377     FXColor color = editor->getBackColor();
378 
379     sender->handle(this, FXSEL(SEL_COMMAND, ID_SETINTVALUE), (void*)&color);
380     return(1);
381 }
382 
383 
384 // Change selected text foreground color
onCmdTextSelForeColor(FXObject *,FXSelector,void * ptr)385 long Preferences::onCmdTextSelForeColor(FXObject*, FXSelector, void* ptr)
386 {
387     editor->setSelTextColor((FXColor)(FXuval)ptr);
388     return(1);
389 }
390 
391 
392 // Update selected text foregoround color
onUpdTextSelForeColor(FXObject * sender,FXSelector,void *)393 long Preferences::onUpdTextSelForeColor(FXObject* sender, FXSelector, void*)
394 {
395     FXColor color = editor->getSelTextColor();
396 
397     sender->handle(this, FXSEL(SEL_COMMAND, ID_SETINTVALUE), (void*)&color);
398     return(1);
399 }
400 
401 
402 // Change selected text background color
onCmdTextSelBackColor(FXObject *,FXSelector,void * ptr)403 long Preferences::onCmdTextSelBackColor(FXObject*, FXSelector, void* ptr)
404 {
405     editor->setSelBackColor((FXColor)(FXuval)ptr);
406     return(1);
407 }
408 
409 
410 // Update selected text background color
onUpdTextSelBackColor(FXObject * sender,FXSelector,void *)411 long Preferences::onUpdTextSelBackColor(FXObject* sender, FXSelector, void*)
412 {
413     FXColor color = editor->getSelBackColor();
414 
415     sender->handle(this, FXSEL(SEL_COMMAND, ID_SETINTVALUE), (void*)&color);
416     return(1);
417 }
418 
419 
420 // Change hilight text color
onCmdTextHiliteForeColor(FXObject *,FXSelector,void * ptr)421 long Preferences::onCmdTextHiliteForeColor(FXObject*, FXSelector, void* ptr)
422 {
423     editor->setHiliteTextColor((FXColor)(FXuval)ptr);
424     return(1);
425 }
426 
427 
428 // Update hilight text color
onUpdTextHiliteForeColor(FXObject * sender,FXSelector,void *)429 long Preferences::onUpdTextHiliteForeColor(FXObject* sender, FXSelector, void*)
430 {
431     FXColor color = editor->getHiliteTextColor();
432 
433     sender->handle(this, FXSEL(SEL_COMMAND, ID_SETINTVALUE), (void*)&color);
434     return(1);
435 }
436 
437 
438 // Change hilight text background color
onCmdTextHiliteBackColor(FXObject *,FXSelector,void * ptr)439 long Preferences::onCmdTextHiliteBackColor(FXObject*, FXSelector, void* ptr)
440 {
441     editor->setHiliteBackColor((FXColor)(FXuval)ptr);
442     return(1);
443 }
444 
445 
446 // Update hilight text background color
onUpdTextHiliteBackColor(FXObject * sender,FXSelector,void *)447 long Preferences::onUpdTextHiliteBackColor(FXObject* sender, FXSelector, void*)
448 {
449     FXColor color = editor->getHiliteBackColor();
450 
451     sender->handle(this, FXSEL(SEL_COMMAND, ID_SETINTVALUE), (void*)&color);
452     return(1);
453 }
454 
455 
456 // Change cursor color
onCmdTextCursorColor(FXObject *,FXSelector,void * ptr)457 long Preferences::onCmdTextCursorColor(FXObject*, FXSelector, void* ptr)
458 {
459     editor->setCursorColor((FXColor)(FXuval)ptr);
460     return(1);
461 }
462 
463 
464 // Update cursor color
onUpdTextCursorColor(FXObject * sender,FXSelector,void *)465 long Preferences::onUpdTextCursorColor(FXObject* sender, FXSelector, void*)
466 {
467     FXColor color = editor->getCursorColor();
468 
469     sender->handle(sender, FXSEL(SEL_COMMAND, FXWindow::ID_SETINTVALUE), (void*)&color);
470     return(1);
471 }
472 
473 
474 // Change line numbers background color
onCmdTextBarColor(FXObject *,FXSelector,void * ptr)475 long Preferences::onCmdTextBarColor(FXObject*, FXSelector, void* ptr)
476 {
477     editor->setBarColor((FXColor)(FXuval)ptr);
478     return(1);
479 }
480 
481 
482 // Update line numbers background color
onUpdTextBarColor(FXObject * sender,FXSelector,void *)483 long Preferences::onUpdTextBarColor(FXObject* sender, FXSelector, void*)
484 {
485     FXColor color = editor->getBarColor();
486 
487     sender->handle(this, FXSEL(SEL_COMMAND, ID_SETINTVALUE), (void*)&color);
488     return(1);
489 }
490 
491 
492 // Change line numbers color
onCmdTextNumberColor(FXObject *,FXSelector,void * ptr)493 long Preferences::onCmdTextNumberColor(FXObject*, FXSelector, void* ptr)
494 {
495     editor->setNumberColor((FXColor)(FXuval)ptr);
496     return(1);
497 }
498 
499 
500 // Update line numbers color
onUpdTextNumberColor(FXObject * sender,FXSelector,void *)501 long Preferences::onUpdTextNumberColor(FXObject* sender, FXSelector, void*)
502 {
503     FXColor color = editor->getNumberColor();
504 
505     sender->handle(this, FXSEL(SEL_COMMAND, ID_SETINTVALUE), (void*)&color);
506     return(1);
507 }
508 
509 
510 // WriteWindow class
511 
512 
513 // Map
514 FXDEFMAP(WriteWindow) WriteWindowMap[] =
515 {
516     FXMAPFUNC(SEL_UPDATE, 0, WriteWindow::onUpdateTitle),
517     FXMAPFUNC(SEL_FOCUSIN, 0, WriteWindow::onFocusIn),
518     FXMAPFUNC(SEL_COMMAND, WriteWindow::ID_ABOUT, WriteWindow::onCmdAbout),
519     FXMAPFUNC(SEL_SIGNAL, WriteWindow::ID_HARVEST, WriteWindow::onSigHarvest),
520     FXMAPFUNC(SEL_COMMAND, WriteWindow::ID_NEW, WriteWindow::onCmdNew),
521     FXMAPFUNC(SEL_COMMAND, WriteWindow::ID_OPEN, WriteWindow::onCmdOpen),
522     FXMAPFUNC(SEL_COMMAND, WriteWindow::ID_OPEN_RECENT, WriteWindow::onCmdOpenRecent),
523     FXMAPFUNC(SEL_COMMAND, WriteWindow::ID_SAVE, WriteWindow::onCmdSave),
524     FXMAPFUNC(SEL_COMMAND, WriteWindow::ID_SAVEAS, WriteWindow::onCmdSaveAs),
525     FXMAPFUNC(SEL_COMMAND, WriteWindow::ID_FONT, WriteWindow::onCmdFont),
526     FXMAPFUNC(SEL_COMMAND, WriteWindow::ID_PRINT, WriteWindow::onCmdPrint),
527     FXMAPFUNC(SEL_UPDATE, WriteWindow::ID_TOGGLE_WRAP, WriteWindow::onUpdWrap),
528     FXMAPFUNC(SEL_COMMAND, WriteWindow::ID_TOGGLE_WRAP, WriteWindow::onCmdWrap),
529     FXMAPFUNC(SEL_COMMAND, WriteWindow::ID_TOGGLE_LINES_NUM, WriteWindow::onCmdLinesNum),
530     FXMAPFUNC(SEL_UPDATE, WriteWindow::ID_TOGGLE_LINES_NUM, WriteWindow::onUpdLinesNum),
531     FXMAPFUNC(SEL_INSERTED, WriteWindow::ID_TEXT, WriteWindow::onTextInserted),
532     FXMAPFUNC(SEL_REPLACED, WriteWindow::ID_TEXT, WriteWindow::onTextReplaced),
533     FXMAPFUNC(SEL_DELETED, WriteWindow::ID_TEXT, WriteWindow::onTextDeleted),
534     FXMAPFUNC(SEL_RIGHTBUTTONRELEASE, WriteWindow::ID_TEXT, WriteWindow::onTextRightMouse),
535     FXMAPFUNC(SEL_DND_MOTION, WriteWindow::ID_TEXT, WriteWindow::onEditDNDMotion),
536     FXMAPFUNC(SEL_DND_DROP, WriteWindow::ID_TEXT, WriteWindow::onEditDNDDrop),
537     FXMAPFUNC(SEL_UPDATE, WriteWindow::ID_OVERSTRIKE, WriteWindow::onUpdOverstrike),
538     FXMAPFUNC(SEL_UPDATE, WriteWindow::ID_NUM_ROWS, WriteWindow::onUpdNumRows),
539     FXMAPFUNC(SEL_COMMAND, WriteWindow::ID_PREFERENCES, WriteWindow::onCmdMorePrefs),
540     FXMAPFUNC(SEL_COMMAND, WriteWindow::ID_SEARCH, WriteWindow::onCmdSearch),
541     FXMAPFUNC(SEL_COMMAND, WriteWindow::ID_REPLACE, WriteWindow::onCmdReplace),
542     FXMAPFUNC(SEL_COMMAND, WriteWindow::ID_SEARCH_FORW_SEL, WriteWindow::onCmdSearchSel),
543     FXMAPFUNC(SEL_COMMAND, WriteWindow::ID_SEARCH_BACK_SEL, WriteWindow::onCmdSearchSel),
544     FXMAPFUNC(SEL_COMMAND, WriteWindow::ID_GOTO_LINE, WriteWindow::onCmdGotoLine),
545     FXMAPFUNCS(SEL_UPDATE, WriteWindow::ID_WINDOW_1, WriteWindow::ID_WINDOW_50, WriteWindow::onUpdWindow),
546     FXMAPFUNCS(SEL_COMMAND, WriteWindow::ID_WINDOW_1, WriteWindow::ID_WINDOW_50, WriteWindow::onCmdWindow),
547     FXMAPFUNC(SEL_UPDATE, WriteWindow::ID_SAVE, WriteWindow::onUpdSave),
548     FXMAPFUNC(SEL_UPDATE, WriteWindow::ID_SAVEAS, WriteWindow::onUpdReadOnly),
549     FXMAPFUNC(SEL_UPDATE, WriteWindow::ID_REPLACE, WriteWindow::onUpdReadOnly),
550 };
551 
552 
553 // Object implementation
FXIMPLEMENT(WriteWindow,FXMainWindow,WriteWindowMap,ARRAYNUMBER (WriteWindowMap))554 FXIMPLEMENT(WriteWindow, FXMainWindow, WriteWindowMap, ARRAYNUMBER(WriteWindowMap))
555 
556 // Make some windows
557 WriteWindow::WriteWindow(XFileWrite* a, const FXString& file, const FXbool _readonly) : FXMainWindow(a, "XFileWrite", NULL, NULL, DECOR_ALL), mrufiles(a)
558 {
559     FXHotKey hotkey;
560     FXString key;
561 
562     // Add to list of windows
563     getApp()->windowlist.append(this);
564 
565     // Default font
566     font = NULL;
567 
568     // Application icons
569     setIcon(xfwicon);
570 
571     // Status bar
572     statusbar = new FXStatusBar(this, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|STATUSBAR_WITH_DRAGCORNER|FRAME_RAISED);
573 
574     // Make menu bar
575     menubar = new FXMenuBar(this, LAYOUT_DOCK_NEXT|LAYOUT_SIDE_TOP|LAYOUT_FILL_X|FRAME_RAISED);
576 
577     // Sites where to dock
578     FXDockSite* topdock = new FXDockSite(this, LAYOUT_SIDE_TOP|LAYOUT_FILL_X);
579     new FXDockSite(this, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X);
580     new FXDockSite(this, LAYOUT_SIDE_LEFT|LAYOUT_FILL_Y);
581     new FXDockSite(this, LAYOUT_SIDE_RIGHT|LAYOUT_FILL_Y);
582 
583     // Toolbar
584     dragshell = new FXToolBarShell(this, FRAME_RAISED);
585     toolbar = new FXToolBar(topdock, dragshell, LAYOUT_DOCK_NEXT|LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_RAISED);
586     new FXToolBarGrip(toolbar, toolbar, FXToolBar::ID_TOOLBARGRIP, TOOLBARGRIP_DOUBLE);
587 
588     // File menu
589     filemenu = new FXMenuPane(this);
590     new FXMenuTitle(menubar, _("&File"), NULL, filemenu);
591 
592     // Edit Menu
593     editmenu = new FXMenuPane(this);
594     new FXMenuTitle(menubar, _("&Edit"), NULL, editmenu);
595 
596     // View menu
597     viewmenu = new FXMenuPane(this);
598     new FXMenuTitle(menubar, _("&View"), NULL, viewmenu);
599 
600     // Search Menu
601     searchmenu = new FXMenuPane(this);
602     new FXMenuTitle(menubar, _("&Search"), NULL, searchmenu);
603 
604     // Preferences Menu
605     prefsmenu = new FXMenuPane(this);
606     new FXMenuTitle(menubar, _("&Preferences"), NULL, prefsmenu);
607 
608     // Window menu
609     windowmenu = new FXMenuPane(this);
610     new FXMenuTitle(menubar, _("&Window"), NULL, windowmenu);
611 
612     // Help menu
613     helpmenu = new FXMenuPane(this);
614     new FXMenuTitle(menubar, _("&Help"), NULL, helpmenu, LAYOUT_LEFT);
615 
616     // Make editor window
617     FXHorizontalFrame* textbox = new FXHorizontalFrame(this, FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0, 0, 0, 0, 0, 0, 0, 0);
618     editor = new FXText(textbox, this, ID_TEXT, LAYOUT_FILL_X|LAYOUT_FILL_Y|TEXT_SHOWACTIVE);
619     editor->setHiliteMatchTime(2000);
620     editor->setTextStyle(editor->getTextStyle()|TEXT_FIXEDWRAP);
621     editor->setTextStyle(editor->getTextStyle()&~TEXT_NO_TABS);
622     editor->setScrollStyle(editor->getScrollStyle()&~SCROLLERS_DONT_TRACK);
623     editor->setTextStyle(editor->getTextStyle()&~TEXT_SHOWACTIVE);
624     editor->setMarginLeft(10);
625 
626     // Read only
627     readonly = _readonly;
628     if (readonly)
629     {
630         editor->setTextStyle(editor->getTextStyle()|TEXT_READONLY);
631     }
632 
633     // Show insert mode in status bar
634     FXLabel* overstrike = new FXLabel(statusbar, FXString::null, NULL, FRAME_SUNKEN|LAYOUT_RIGHT|LAYOUT_CENTER_Y, 0, 0, 0, 0, 2, 2, 1, 1);
635     overstrike->setTarget(this);
636     overstrike->setSelector(ID_OVERSTRIKE);
637 
638     // Show size of text in status bar
639     FXTextField* numchars = new FXTextField(statusbar, 7, this, ID_NUM_ROWS, TEXTFIELD_READONLY|FRAME_SUNKEN|JUSTIFY_RIGHT|LAYOUT_RIGHT|LAYOUT_CENTER_Y, 0, 0, 0, 0, 2, 2, 1, 1);
640     numchars->setBackColor(statusbar->getBackColor());
641 
642     // Caption before number
643     new FXLabel(statusbar, _("  Lines:"), NULL, LAYOUT_RIGHT|LAYOUT_CENTER_Y);
644 
645     // Show column number in status bar
646     FXTextField* columnno = new FXTextField(statusbar, 7, editor, FXText::ID_CURSOR_COLUMN, FRAME_SUNKEN|JUSTIFY_RIGHT|LAYOUT_RIGHT|LAYOUT_CENTER_Y, 0, 0, 0, 0, 2, 2, 1, 1);
647     columnno->setBackColor(statusbar->getBackColor());
648 
649     // Caption before number
650     new FXLabel(statusbar, _("  Col:"), NULL, LAYOUT_RIGHT|LAYOUT_CENTER_Y);
651 
652     // Show line number in status bar
653     FXTextField* rowno = new FXTextField(statusbar, 7, editor, FXText::ID_CURSOR_ROW, FRAME_SUNKEN|JUSTIFY_RIGHT|LAYOUT_RIGHT|LAYOUT_CENTER_Y, 0, 0, 0, 0, 2, 2, 1, 1);
654     rowno->setBackColor(statusbar->getBackColor());
655 
656     // Caption before number
657     new FXLabel(statusbar, _("  Line:"), NULL, LAYOUT_RIGHT|LAYOUT_CENTER_Y);
658 
659     // Toolbar buttons: File manipulation
660     key = getApp()->reg().readStringEntry("KEYBINDINGS", "new", "Ctrl-N");
661     new FXButton(toolbar, TAB+_("New")+PARS(key)+TAB+_("Create new document.")+PARS(key), newfileicon, this, ID_NEW, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT);
662 
663     key = getApp()->reg().readStringEntry("KEYBINDINGS", "open", "Ctrl-O");
664     new FXButton(toolbar, TAB+_("Open")+PARS(key)+TAB+_("Open document file.")+PARS(key), fileopenicon, this, ID_OPEN, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT);
665 
666     key = getApp()->reg().readStringEntry("KEYBINDINGS", "save", "Ctrl-S");
667     new FXButton(toolbar, TAB+_("Save")+PARS(key)+TAB+_("Save document.")+PARS(key), savefileicon, this, ID_SAVE, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT);
668 
669     key = getApp()->reg().readStringEntry("KEYBINDINGS", "close", "Ctrl-W");
670     new FXButton(toolbar, TAB+_("Close")+PARS(key)+TAB+_("Close document file.")+PARS(key), closefileicon, this, ID_CLOSE, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT);
671 
672     // Spacer
673     new FXSeparator(toolbar, SEPARATOR_GROOVE);
674 
675     // Toolbar buttons: Print and Quit
676     key = getApp()->reg().readStringEntry("KEYBINDINGS", "print", "Ctrl-P");
677     new FXButton(toolbar, TAB+_("Print")+PARS(key)+TAB+_("Print document.")+PARS(key), printicon, this, ID_PRINT, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT);
678 
679     key = getApp()->reg().readStringEntry("KEYBINDINGS", "quit", "Ctrl-Q");
680     new FXButton(toolbar, TAB+_("Quit")+PARS(key)+TAB+_("Quit X File Write.")+PARS(key), quiticon, getApp(), XFileWrite::ID_CLOSEALL, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT);
681 
682     // Spacer
683     new FXSeparator(toolbar, SEPARATOR_GROOVE);
684 
685     // Toolbar buttons: Editing
686     key = getApp()->reg().readStringEntry("KEYBINDINGS", "copy", "Ctrl-C");
687     new FXButton(toolbar, TAB+_("Copy")+PARS(key)+TAB+_("Copy selection to clipboard.")+PARS(key), copy_clpicon, editor, FXText::ID_COPY_SEL, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT);
688 
689     key = getApp()->reg().readStringEntry("KEYBINDINGS", "cut", "Ctrl-X");
690     cut = new FXButton(toolbar, TAB+_("Cut")+PARS(key)+TAB+_("Cut selection to clipboard.")+PARS(key), cut_clpicon, editor, FXText::ID_CUT_SEL, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT);
691 
692     key = getApp()->reg().readStringEntry("KEYBINDINGS", "paste", "Ctrl-V");
693     paste = new FXButton(toolbar, TAB+_("Paste")+PARS(key)+TAB+_("Paste clipboard.")+PARS(key), paste_clpicon, editor, FXText::ID_PASTE_SEL, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT);
694 
695     // Spacer
696     new FXSeparator(toolbar, SEPARATOR_GROOVE);
697 
698     // Goto line
699     key = getApp()->reg().readStringEntry("KEYBINDINGS", "goto_line", "Ctrl-L");
700     new FXButton(toolbar, TAB+_("Goto line")+PARS(key)+TAB+_("Goto line number."), gotolineicon, this, WriteWindow::ID_GOTO_LINE, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT);
701 
702     // Spacer
703     new FXSeparator(toolbar, SEPARATOR_GROOVE);
704 
705     // Undo/redo
706     key = getApp()->reg().readStringEntry("KEYBINDINGS", "undo", "Ctrl-Z");
707     new FXButton(toolbar, TAB+_("Undo")+PARS(key)+TAB+_("Undo last change.")+PARS(key), undoicon, &undolist, FXUndoList::ID_UNDO, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT);
708 
709     key = getApp()->reg().readStringEntry("KEYBINDINGS", "redo", "Ctrl-Y");
710     new FXButton(toolbar, TAB+_("Redo")+PARS(key)+TAB+_("Redo last undo.")+PARS(key), redoicon, &undolist, FXUndoList::ID_REDO, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT);
711 
712     // Spacer
713     new FXSeparator(toolbar, SEPARATOR_GROOVE);
714 
715     // Search
716     key = getApp()->reg().readStringEntry("KEYBINDINGS", "search", "Ctrl-F");
717     new FXButton(toolbar, TAB+_("Search")+PARS(key)+TAB+_("Search text.")+PARS(key), searchicon, this, WriteWindow::ID_SEARCH, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT);
718 
719     key = getApp()->reg().readStringEntry("KEYBINDINGS", "search_prev", "Ctrl-Shift-G");
720     new FXButton(toolbar, TAB+_("Search selection backward")+PARS(key)+TAB+_("Search backward for selected text.")+PARS(key), searchprevicon, this, WriteWindow::ID_SEARCH_BACK_SEL, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT);
721 
722     key = getApp()->reg().readStringEntry("KEYBINDINGS", "search_next", "Ctrl-G");
723     new FXButton(toolbar, TAB+_("Search selection forward")+PARS(key)+TAB+_("Search forward for selected text.")+PARS(key), searchnexticon, this, WriteWindow::ID_SEARCH_FORW_SEL, ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|LAYOUT_CENTER_Y|LAYOUT_LEFT);
724 
725     // Spacer
726     new FXSeparator(toolbar, SEPARATOR_GROOVE);
727 
728     // Preferences
729     key = getApp()->reg().readStringEntry("KEYBINDINGS", "word_wrap", "Ctrl-K");
730     new FXToggleButton(toolbar, TAB+_("Word wrap on")+PARS(key)+TAB+_("Set word wrap on.")+PARS(key), TAB+_("Word wrap off")+PARS(key)+TAB+_("Set word wrap off.")+PARS(key), wrapofficon, wraponicon, this, ID_TOGGLE_WRAP, BUTTON_TOOLBAR|LAYOUT_LEFT|ICON_BEFORE_TEXT);
731 
732     key = getApp()->reg().readStringEntry("KEYBINDINGS", "line_numbers", "Ctrl-T");
733     new FXToggleButton(toolbar, TAB+_("Show line numbers")+PARS(key)+TAB+_("Show line numbers.")+PARS(key), TAB+_("Hide line numbers")+PARS(key)+TAB+_("Hide line numbers.")+PARS(key), hidenumbersicon, shownumbersicon, this, ID_TOGGLE_LINES_NUM, BUTTON_TOOLBAR|LAYOUT_LEFT|ICON_BEFORE_TEXT);
734 
735 
736     // File Menu entries
737     FXMenuCommand* mc = NULL;
738     FXString       text;
739 
740     key = getApp()->reg().readStringEntry("KEYBINDINGS", "new", "Ctrl-N");
741     text = _("&New")+TABS(key)+_("Create new document.")+PARS(key);
742     mc = new FXMenuCommand(filemenu, text, newfileicon, this, ID_NEW);
743     hotkey = _parseAccel(key);
744     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
745 
746     key = getApp()->reg().readStringEntry("KEYBINDINGS", "open", "Ctrl-O");
747     text = _("&Open...")+TABS(key)+_("Open document file.")+PARS(key);
748     mc = new FXMenuCommand(filemenu, text, fileopenicon, this, ID_OPEN);
749     hotkey = _parseAccel(key);
750     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
751 
752     key = getApp()->reg().readStringEntry("KEYBINDINGS", "save", "Ctrl-S");
753     text = _("&Save")+TABS(key)+_("Save changes to file.")+PARS(key);
754     mc = new FXMenuCommand(filemenu, text, savefileicon, this, ID_SAVE);
755     hotkey = _parseAccel(key);
756     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
757 
758     new FXMenuCommand(filemenu, _("Save &As...")+TAB2+_("Save document to another file."), saveasicon, this, ID_SAVEAS);
759 
760     key = getApp()->reg().readStringEntry("KEYBINDINGS", "close", "Ctrl-W");
761     text = _("&Close")+TABS(key)+_("Close document.")+PARS(key);
762     mc = new FXMenuCommand(filemenu, text, closefileicon, this, ID_CLOSE);
763     hotkey = _parseAccel(key);
764     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
765 
766     new FXMenuSeparator(filemenu);
767     key = getApp()->reg().readStringEntry("KEYBINDINGS", "print", "Ctrl-P");
768     text = _("&Print...")+TABS(key)+_("Print document.")+PARS(key);
769     mc = new FXMenuCommand(filemenu, text, printicon, this, ID_PRINT);
770     hotkey = _parseAccel(key);
771     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
772 
773     // Recent file menu; this automatically hides if there are no files
774     FXMenuSeparator* sep1 = new FXMenuSeparator(filemenu);
775     sep1->setTarget(&mrufiles);
776     sep1->setSelector(FXRecentFiles::ID_ANYFILES);
777     new FXMenuCommand(filemenu, FXString::null, NULL, &mrufiles, FXRecentFiles::ID_FILE_1);
778     new FXMenuCommand(filemenu, FXString::null, NULL, &mrufiles, FXRecentFiles::ID_FILE_2);
779     new FXMenuCommand(filemenu, FXString::null, NULL, &mrufiles, FXRecentFiles::ID_FILE_3);
780     new FXMenuCommand(filemenu, FXString::null, NULL, &mrufiles, FXRecentFiles::ID_FILE_4);
781     new FXMenuCommand(filemenu, FXString::null, NULL, &mrufiles, FXRecentFiles::ID_FILE_5);
782     new FXMenuCommand(filemenu, _("&Clear Recent Files"), NULL, &mrufiles, FXRecentFiles::ID_CLEAR);
783     FXMenuSeparator* sep2 = new FXMenuSeparator(filemenu);
784     sep2->setTarget(&mrufiles);
785     sep2->setSelector(FXRecentFiles::ID_ANYFILES);
786 
787     key = getApp()->reg().readStringEntry("KEYBINDINGS", "quit", "Ctrl-Q");
788     text = _("&Quit")+TABS(key)+_("Quit X File Write.")+PARS(key);
789     mc = new FXMenuCommand(filemenu, text, quiticon, getApp(), XFileWrite::ID_CLOSEALL);
790     hotkey = _parseAccel(key);
791     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
792 
793     // Edit Menu entries
794     key = getApp()->reg().readStringEntry("KEYBINDINGS", "undo", "Ctrl-Z");
795     text = _("&Undo")+TABS(key)+_("Undo last change.")+PARS(key);
796     mc = new FXMenuCommand(editmenu, text, undoicon, &undolist, FXUndoList::ID_UNDO);
797     hotkey = _parseAccel(key);
798     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
799 
800     key = getApp()->reg().readStringEntry("KEYBINDINGS", "redo", "Ctrl-Y");
801     text = _("&Redo")+TABS(key)+_("Redo last undo.")+PARS(key);
802     mc = new FXMenuCommand(editmenu, text, redoicon, &undolist, FXUndoList::ID_REDO);
803     hotkey = _parseAccel(key);
804     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
805 
806     new FXMenuCommand(editmenu, _("Revert to &saved")+TAB2+_("Revert to saved document."), reverticon, &undolist, FXUndoList::ID_REVERT);
807 
808     new FXMenuSeparator(editmenu);
809     key = getApp()->reg().readStringEntry("KEYBINDINGS", "copy", "Ctrl-C");
810     text = _("&Copy")+TABS(key)+_("Copy selection to clipboard.")+PARS(key);
811     mc = new FXMenuCommand(editmenu, text, copy_clpicon, editor, FXText::ID_COPY_SEL);
812     hotkey = _parseAccel(key);
813     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
814 
815     key = getApp()->reg().readStringEntry("KEYBINDINGS", "cut", "Ctrl-X");
816     text = _("Cu&t")+TABS(key)+_("Cut selection to clipboard.")+PARS(key);
817     cutmc = new FXMenuCommand(editmenu, text, cut_clpicon, editor, FXText::ID_CUT_SEL);
818     hotkey = _parseAccel(key);
819     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
820 
821     key = getApp()->reg().readStringEntry("KEYBINDINGS", "paste", "Ctrl-V");
822     text = _("&Paste")+TABS(key)+_("Paste from clipboard.")+PARS(key);
823     pastemc = new FXMenuCommand(editmenu, text, paste_clpicon, editor, FXText::ID_PASTE_SEL);
824     hotkey = _parseAccel(key);
825     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
826 
827     new FXMenuSeparator(editmenu);
828     key = getApp()->reg().readStringEntry("KEYBINDINGS", "lower_case", "Ctrl-U");
829     text = _("Lo&wer-case")+TABS(key)+_("Change to lower case.")+PARS(key);
830     mc = new FXMenuCommand(editmenu, text, lowercaseicon, editor, FXText::ID_LOWER_CASE);
831     hotkey = _parseAccel(key);
832     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
833 
834     key = getApp()->reg().readStringEntry("KEYBINDINGS", "upper_case", "Ctrl-Shift-U");
835     text = _("Upp&er-case")+TABS(key)+_("Change to upper case.")+PARS(key);
836     mc = new FXMenuCommand(editmenu, text, uppercaseicon, editor, FXText::ID_UPPER_CASE);
837     hotkey = _parseAccel(key);
838     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
839 
840     key = getApp()->reg().readStringEntry("KEYBINDINGS", "goto_line", "Ctrl-L");
841     text = _("&Goto line...")+TABS(key)+_("Goto line number.")+PARS(key);
842     mc = new FXMenuCommand(editmenu, text, gotolineicon, this, WriteWindow::ID_GOTO_LINE);
843     hotkey = _parseAccel(key);
844     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
845 
846     // Right mouse popup
847     popupmenu = new FXMenuPane(this);
848     new FXMenuCommand(popupmenu, _("&Undo"), undoicon, &undolist, FXUndoList::ID_UNDO);
849     new FXMenuCommand(popupmenu, _("&Redo"), redoicon, &undolist, FXUndoList::ID_REDO);
850     new FXMenuSeparator(popupmenu);
851     new FXMenuCommand(popupmenu, _("&Copy"), copy_clpicon, editor, FXText::ID_COPY_SEL);
852     new FXMenuCommand(popupmenu, _("Cu&t"), cut_clpicon, editor, FXText::ID_CUT_SEL);
853     new FXMenuCommand(popupmenu, _("&Paste"), paste_clpicon, editor, FXText::ID_PASTE_SEL);
854     new FXMenuCommand(popupmenu, _("Select &All"), NULL, editor, FXText::ID_SELECT_ALL);
855     new FXMenuSeparator(popupmenu);
856 
857     // View Menu entries
858     new FXMenuCheck(viewmenu, _("&Toolbar")+TAB2+_("Display toolbar."), toolbar, FXWindow::ID_TOGGLESHOWN);
859     new FXMenuCheck(viewmenu, _("&Status line")+TAB2+_("Display status line."), statusbar, FXWindow::ID_TOGGLESHOWN);
860 
861     // Search Menu entries
862     key = getApp()->reg().readStringEntry("KEYBINDINGS", "search", "Ctrl-F");
863     text = _("&Search...")+TABS(key)+_("Search for a string.")+PARS(key);
864     mc = new FXMenuCommand(searchmenu, text, searchicon, this, WriteWindow::ID_SEARCH);
865     hotkey = _parseAccel(key);
866     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
867 
868     key = getApp()->reg().readStringEntry("KEYBINDINGS", "replace", "Ctrl-R");
869     text = _("&Replace...")+TABS(key)+_("Search for a string and replace with another.")+PARS(key);
870     mc = new FXMenuCommand(searchmenu, text, replaceicon, this, WriteWindow::ID_REPLACE);
871     hotkey = _parseAccel(key);
872     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
873 
874     key = getApp()->reg().readStringEntry("KEYBINDINGS", "search_prev", "Ctrl-Shift-G");
875     text = _("Search sel. &backward")+TABS(key)+_("Search backward for selected text.")+PARS(key);
876     mc = new FXMenuCommand(searchmenu, text, searchprevicon, this, WriteWindow::ID_SEARCH_BACK_SEL);
877     hotkey = _parseAccel(key);
878     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
879 
880     key = getApp()->reg().readStringEntry("KEYBINDINGS", "search_next", "Ctrl-G");
881     text = _("Search sel. &forward")+TABS(key)+_("Search forward for selected text.")+PARS(key);
882     mc = new FXMenuCommand(searchmenu, text, searchnexticon, this, WriteWindow::ID_SEARCH_FORW_SEL);
883     hotkey = _parseAccel(key);
884     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
885 
886 
887     // Preferences menu
888     key = getApp()->reg().readStringEntry("KEYBINDINGS", "word_wrap", "Ctrl-K");
889     text = _("&Word wrap")+TABS(key)+_("Toggle word wrap mode.")+PARS(key);
890     mc = new FXMenuCheck(prefsmenu, text, this, ID_TOGGLE_WRAP);
891     hotkey = _parseAccel(key);
892     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
893 
894     key = getApp()->reg().readStringEntry("KEYBINDINGS", "line_numbers", "Ctrl-T");
895     text = _("&Line numbers")+TABS(key)+_("Toggle line numbers mode.")+PARS(key);
896     mc = new FXMenuCheck(prefsmenu, text, this, ID_TOGGLE_LINES_NUM);
897     hotkey = _parseAccel(key);
898     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
899 
900     new FXMenuCheck(prefsmenu, _("&Overstrike")+TAB2+_("Toggle overstrike mode."), editor, FXText::ID_TOGGLE_OVERSTRIKE);
901     new FXMenuSeparator(prefsmenu);
902     new FXMenuCommand(prefsmenu, _("&Font...")+TAB2+_("Change text font."), fontsicon, this, ID_FONT);
903     new FXMenuCommand(prefsmenu, _("&More preferences...")+TAB2+_("Change other options."), prefsicon, this, ID_PREFERENCES);
904 
905     // Window menu
906     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_1);
907     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_2);
908     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_3);
909     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_4);
910     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_5);
911     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_6);
912     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_7);
913     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_8);
914     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_9);
915     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_10);
916     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_11);
917     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_12);
918     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_13);
919     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_14);
920     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_15);
921     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_16);
922     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_17);
923     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_18);
924     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_19);
925     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_20);
926     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_21);
927     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_22);
928     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_23);
929     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_24);
930     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_25);
931     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_26);
932     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_27);
933     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_28);
934     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_29);
935     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_30);
936     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_31);
937     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_32);
938     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_33);
939     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_34);
940     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_35);
941     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_36);
942     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_37);
943     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_38);
944     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_39);
945     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_40);
946     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_41);
947     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_42);
948     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_43);
949     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_44);
950     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_45);
951     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_46);
952     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_47);
953     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_48);
954     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_49);
955     new FXMenuRadio(windowmenu, FXString::null, this, ID_WINDOW_50);
956 
957     // Help Menu entries
958     key = getApp()->reg().readStringEntry("KEYBINDINGS", "help", "F1");
959     text = _("&About X File Write")+TABS(key)+_("About X File Write.")+PARS(key);
960     mc = new FXMenuCommand(helpmenu, text, NULL, this, ID_ABOUT, 0);
961     hotkey = _parseAccel(key);
962     getAccelTable()->addAccel(hotkey, mc, FXSEL(SEL_COMMAND, FXMenuCommand::ID_ACCEL));
963 
964     // Dialogs
965     printdialog = NULL;
966     prefsdialog = NULL;
967     searchdialog = NULL;
968     replacedialog = NULL;
969 
970     // Recent files
971     mrufiles.setTarget(this);
972     mrufiles.setSelector(ID_OPEN_RECENT);
973 
974     // Initialize file name
975     filename = file;
976     filenameset = false;
977     filetime = 0;
978 
979     // Initialize other stuff
980     stripcr = false;
981     linesnum = false;
982     undolist.mark();
983     undoredoblock = NULL;
984     smoothscroll = true;
985 
986     // Initialize window position and size
987     fromreg = true;
988     ww = 0;
989     hh = 0;
990     xx = 0;
991     yy = 0;
992 }
993 
994 
995 // Create and show window
create()996 void WriteWindow::create()
997 {
998     loadConfig();
999     FXMainWindow::create();
1000     dragshell->create();
1001     filemenu->create();
1002     editmenu->create();
1003     searchmenu->create();
1004     prefsmenu->create();
1005     viewmenu->create();
1006     windowmenu->create();
1007     helpmenu->create();
1008     popupmenu->create();
1009     if (!urilistType)
1010     {
1011         urilistType = getApp()->registerDragType(urilistTypeName);
1012     }
1013     show(PLACEMENT_DEFAULT);
1014     editor->setFocus();
1015 
1016 #ifdef STARTUP_NOTIFICATION
1017     startup_completed();
1018 #endif
1019 }
1020 
1021 
1022 // Detach window
detach()1023 void WriteWindow::detach()
1024 {
1025     FXMainWindow::detach();
1026     dragshell->detach();
1027     urilistType = 0;
1028 }
1029 
1030 
1031 // Clean up
~WriteWindow()1032 WriteWindow::~WriteWindow()
1033 {
1034     getApp()->windowlist.remove(this);
1035     delete font;
1036     delete toolbar;
1037     delete menubar;
1038     delete dragshell;
1039     delete filemenu;
1040     delete editmenu;
1041     delete searchmenu;
1042     delete prefsmenu;
1043     delete viewmenu;
1044     delete windowmenu;
1045     delete helpmenu;
1046     delete popupmenu;
1047     delete editor;
1048     delete printdialog;
1049     delete prefsdialog;
1050     delete searchdialog;
1051     delete replacedialog;
1052 }
1053 
1054 
1055 // Is it modified
isModified() const1056 FXbool WriteWindow::isModified() const
1057 {
1058     return(!undolist.marked());
1059 }
1060 
1061 
1062 // Load file
loadFile(const FXString & file)1063 FXbool WriteWindow::loadFile(const FXString& file)
1064 {
1065     FXFile textfile(file, FXFile::Reading);
1066     int    size, n, i, j, c;
1067     char*  text;
1068 
1069     // Opened file?
1070     if (!textfile.isOpen())
1071     {
1072         MessageBox::error(this, BOX_OK, _("Error Loading File"), _("Unable to open file: %s"), file.text());
1073         return(false);
1074     }
1075 
1076     // Get file size
1077     size = textfile.size();
1078 
1079     // Make buffer to load file
1080     if (!FXMALLOC(&text, char, size))
1081     {
1082         MessageBox::error(this, BOX_OK, _("Error Loading File"), _("File is too big: %s (%d bytes)"), file.text(), size);
1083         return(false);
1084     }
1085 
1086     // Set wait cursor
1087     getApp()->beginWaitCursor();
1088 
1089     // Read the file
1090     n = textfile.readBlock(text, size);
1091     if (n < 0)
1092     {
1093         FXFREE(&text);
1094         MessageBox::error(this, BOX_OK, _("Error Loading File"), _("Unable to read file: %s"), file.text());
1095         getApp()->endWaitCursor();
1096         return(false);
1097     }
1098 
1099     // Strip carriage returns
1100     if (stripcr)
1101     {
1102         for (i = j = 0; j < n; j++)
1103         {
1104             c = text[j];
1105             if (c != '\r')
1106             {
1107                 text[i++] = c;
1108             }
1109         }
1110         n = i;
1111     }
1112 
1113     // Set text
1114     editor->setText(text, n);
1115     FXFREE(&text);
1116 
1117     // Lines numbering
1118     if (linesnum)
1119     {
1120         FXuint size = editor->getNumRows();
1121         FXuint cols = (FXuint)ceil(log10(size));
1122         editor->setBarColumns(cols);
1123     }
1124     else
1125     {
1126         editor->setBarColumns(0);
1127     }
1128 
1129     // Kill wait cursor
1130     getApp()->endWaitCursor();
1131 
1132     mrufiles.appendFile(file);
1133     filetime = FXStat::modified(file);
1134     filenameset = true;
1135     filename = file;
1136 
1137     // Clear undo records
1138     undolist.clear();
1139 
1140     // Mark undo state as clean (saved)
1141     undolist.mark();
1142 
1143     return(true);
1144 }
1145 
1146 
1147 // Save file
saveFile(const FXString & file)1148 FXbool WriteWindow::saveFile(const FXString& file)
1149 {
1150     // Get current file size
1151     int size = editor->getLength();
1152 
1153     // Get available space on current file system
1154     FXlong space = GetAvailableSpace(file);
1155 
1156     // Unknown error
1157     if (space < 0)
1158     {
1159         MessageBox::error(this, BOX_OK, _("Error Saving File"), _("Unable to save file: %s"), file.text());
1160         return(false);
1161     }
1162 
1163     // Not enough space left on file system to save the file
1164     else if (space < size)
1165     {
1166         MessageBox::error(this, BOX_OK, _("Error Saving File"), _("Not enough space left on device, unable to save file: %s\n\n\
1167 => To prevent losing data, you should save this file to another device before exiting!"), file.text());
1168         return(false);
1169     }
1170 
1171     FXFile textfile(file, FXFile::Writing);
1172     char*  text;
1173 
1174     // Opened file?
1175     if (!textfile.isOpen())
1176     {
1177         MessageBox::error(this, BOX_OK, _("Error Saving File"), _("Unable to open file: %s"), file.text());
1178         return(false);
1179     }
1180 
1181     // Alloc buffer
1182     if (!FXMALLOC(&text, char, size+1))
1183     {
1184         MessageBox::error(this, BOX_OK, _("Error Saving File"), _("File is too big: %s"), file.text());
1185         return(false);
1186     }
1187 
1188     // Set wait cursor
1189     getApp()->beginWaitCursor();
1190 
1191     // Get text from editor
1192     editor->getText(text, size);
1193 
1194     // Write the file
1195     int n = textfile.writeBlock(text, size);
1196 
1197     // Ditch buffer
1198     FXFREE(&text);
1199 
1200     // Kill wait cursor
1201     getApp()->endWaitCursor();
1202 
1203     // Were we able to write it all?
1204     if (n != size)
1205     {
1206         MessageBox::error(this, BOX_OK, _("Error Saving File"), _("File: %s truncated."), file.text());
1207         return(false);
1208     }
1209 
1210     mrufiles.appendFile(file);
1211     filetime = FXStat::modified(file);
1212     filenameset = true;
1213     filename = file;
1214     undolist.mark();
1215     return(true);
1216 }
1217 
1218 
1219 // Generate unique name for a new window
unique() const1220 FXString WriteWindow::unique() const
1221 {
1222     FXString name = _("untitled");
1223 
1224     for (int i = 1; i < 2147483647; i++)
1225     {
1226         if (!findWindow(name))
1227         {
1228             break;
1229         }
1230         name.format(_("untitled%d"), i);
1231     }
1232     return(name);
1233 }
1234 
1235 
1236 // Find an as yet untitled, unedited window
findUnused() const1237 WriteWindow* WriteWindow::findUnused() const
1238 {
1239     for (int w = 0; w < getApp()->windowlist.no(); w++)
1240     {
1241         if (!getApp()->windowlist[w]->isFilenameSet() && !getApp()->windowlist[w]->isModified())
1242         {
1243             return(getApp()->windowlist[w]);
1244         }
1245     }
1246     return(NULL);
1247 }
1248 
1249 
1250 // Find window, if any, currently editing the given file
findWindow(const FXString & file) const1251 WriteWindow* WriteWindow::findWindow(const FXString& file) const
1252 {
1253     for (int w = 0; w < getApp()->windowlist.no(); w++)
1254     {
1255         if (getApp()->windowlist[w]->getFilename() == file)
1256         {
1257             return(getApp()->windowlist[w]);
1258         }
1259     }
1260     return(NULL);
1261 }
1262 
1263 
1264 // Visit given line
visitLine(int line)1265 void WriteWindow::visitLine(int line)
1266 {
1267     int pos = editor->nextLine(0, line-1);
1268 
1269     editor->setCursorPos(pos);
1270     editor->setCenterLine(pos);
1271 }
1272 
1273 
1274 // Read configuration from registry
loadConfig()1275 void WriteWindow::loadConfig()
1276 {
1277     FXColor  textback, textfore, textselback, textselfore, textcursor, texthilitefore, texthiliteback;
1278     FXColor  textbar, textnumber;
1279     int      wrapping, wrapcols, tabcols;
1280     int      hidestatus, hidetoolbar, hilitematchtime;
1281     FXString fontspec;
1282 
1283     // Text colors
1284     textback = getApp()->reg().readColorEntry("OPTIONS", "textbackground", editor->getBackColor());
1285     textfore = getApp()->reg().readColorEntry("OPTIONS", "textforeground", editor->getTextColor());
1286     textselback = getApp()->reg().readColorEntry("OPTIONS", "textselbackground", editor->getSelBackColor());
1287     textselfore = getApp()->reg().readColorEntry("OPTIONS", "textselforeground", editor->getSelTextColor());
1288     textcursor = getApp()->reg().readColorEntry("OPTIONS", "textcursor", editor->getCursorColor());
1289     texthiliteback = getApp()->reg().readColorEntry("OPTIONS", "texthilitebackground", editor->getHiliteBackColor());
1290     texthilitefore = getApp()->reg().readColorEntry("OPTIONS", "texthiliteforeground", editor->getHiliteTextColor());
1291     textbar = getApp()->reg().readColorEntry("OPTIONS", "textnumberbackground", editor->getBarColor());
1292     textnumber = getApp()->reg().readColorEntry("OPTIONS", "textnumberforeground", editor->getNumberColor());
1293 
1294     // Font
1295     fontspec = getApp()->reg().readStringEntry("OPTIONS", "textfont", "");
1296     if (!fontspec.empty())
1297     {
1298         font = new FXFont(getApp(), fontspec);
1299         font->create();
1300         editor->setFont(font);
1301     }
1302 
1303     // Read the Xfe registry
1304     FXRegistry* reg_xfe = new FXRegistry(XFEAPPNAME, "");
1305     reg_xfe->read();
1306 
1307     // Get value of the retain window position flag
1308     save_win_pos = reg_xfe->readUnsignedEntry("SETTINGS", "save_win_pos", false);
1309 
1310     delete reg_xfe;
1311 
1312     // Get size and position from registry
1313     if (fromreg)
1314     {
1315         ww = getApp()->reg().readUnsignedEntry("OPTIONS", "width", DEFAULT_WINDOW_WIDTH);
1316         hh = getApp()->reg().readUnsignedEntry("OPTIONS", "height", DEFAULT_WINDOW_HEIGHT);
1317     }
1318 
1319     // Showing the status line?
1320     hidestatus = getApp()->reg().readIntEntry("OPTIONS", "hidestatus", false);
1321 
1322     // Showing the tool bar?
1323     hidetoolbar = getApp()->reg().readIntEntry("OPTIONS", "hidetoolbar", false);
1324 
1325     // Highlight match time
1326     hilitematchtime = getApp()->reg().readIntEntry("OPTIONS", "hilitematchtime", 3000);
1327 
1328     // Word wrapping
1329     wrapping = getApp()->reg().readIntEntry("OPTIONS", "wordwrap", 0);
1330     wrapcols = getApp()->reg().readIntEntry("OPTIONS", "wrapcols", 80);
1331 
1332     // Tab settings
1333     tabcols = getApp()->reg().readIntEntry("OPTIONS", "tabcols", 8);
1334 
1335     // Various flags
1336     stripcr = getApp()->reg().readIntEntry("OPTIONS", "stripreturn", false);
1337     linesnum = getApp()->reg().readIntEntry("OPTIONS", "linesnum", false);
1338 
1339     // Change the colors
1340     editor->setTextColor(textfore);
1341     editor->setBackColor(textback);
1342     editor->setSelBackColor(textselback);
1343     editor->setSelTextColor(textselfore);
1344     editor->setCursorColor(textcursor);
1345     editor->setHiliteBackColor(texthiliteback);
1346     editor->setHiliteTextColor(texthilitefore);
1347     editor->setBarColor(textbar);
1348     editor->setNumberColor(textnumber);
1349 
1350 
1351     // Hide statusline
1352     if (hidestatus)
1353     {
1354         statusbar->hide();
1355     }
1356 
1357     // Hide toolbar
1358     if (hidetoolbar)
1359     {
1360         toolbar->hide();
1361     }
1362 
1363     // Wrap mode
1364     if (wrapping)
1365     {
1366         editor->setTextStyle(editor->getTextStyle()|TEXT_WORDWRAP);
1367     }
1368     else
1369     {
1370         editor->setTextStyle(editor->getTextStyle()&~TEXT_WORDWRAP);
1371     }
1372 
1373     // Wrap and tab columns
1374     editor->setWrapColumns(wrapcols);
1375     editor->setTabColumns(tabcols);
1376 
1377     // Highlight match time
1378     editor->setHiliteMatchTime(hilitematchtime);
1379 
1380     // Get position and position window
1381     if (save_win_pos && fromreg)
1382     {
1383         int xpos = getApp()->reg().readIntEntry("OPTIONS", "xpos", DEFAULT_WINDOW_XPOS);
1384         int ypos = getApp()->reg().readIntEntry("OPTIONS", "ypos", DEFAULT_WINDOW_YPOS);
1385         position(xpos, ypos, ww, hh);
1386     }
1387     else
1388     {
1389         position(getX(), getY(), ww, hh);
1390     }
1391 }
1392 
1393 
1394 // Save configuration to registry
saveConfig()1395 void WriteWindow::saveConfig()
1396 {
1397     FXString fontspec;
1398 
1399     // Colors of text
1400     getApp()->reg().writeColorEntry("OPTIONS", "textbackground", editor->getBackColor());
1401     getApp()->reg().writeColorEntry("OPTIONS", "textforeground", editor->getTextColor());
1402     getApp()->reg().writeColorEntry("OPTIONS", "textselbackground", editor->getSelBackColor());
1403     getApp()->reg().writeColorEntry("OPTIONS", "textselforeground", editor->getSelTextColor());
1404     getApp()->reg().writeColorEntry("OPTIONS", "textcursor", editor->getCursorColor());
1405     getApp()->reg().writeColorEntry("OPTIONS", "texthilitebackground", editor->getHiliteBackColor());
1406     getApp()->reg().writeColorEntry("OPTIONS", "texthiliteforeground", editor->getHiliteTextColor());
1407     getApp()->reg().writeColorEntry("OPTIONS", "textnumberbackground", editor->getBarColor());
1408     getApp()->reg().writeColorEntry("OPTIONS", "textnumberforeground", editor->getNumberColor());
1409 
1410 
1411     // Write new window size back to registry
1412     getApp()->reg().writeUnsignedEntry("OPTIONS", "width", getWidth());
1413     getApp()->reg().writeUnsignedEntry("OPTIONS", "height", getHeight());
1414     if (save_win_pos)
1415     {
1416         // Account for the Window Manager border size
1417         XWindowAttributes xwattr;
1418         if (XGetWindowAttributes((Display*)getApp()->getDisplay(), this->id(), &xwattr))
1419         {
1420             getApp()->reg().writeIntEntry("OPTIONS", "xpos", getX()-xwattr.x);
1421             getApp()->reg().writeIntEntry("OPTIONS", "ypos", getY()-xwattr.y);
1422         }
1423         else
1424         {
1425             getApp()->reg().writeIntEntry("OPTIONS", "xpos", getX());
1426             getApp()->reg().writeIntEntry("OPTIONS", "ypos", getY());
1427         }
1428     }
1429 
1430     // Was status line shown
1431     getApp()->reg().writeIntEntry("OPTIONS", "hidestatus", !statusbar->shown());
1432 
1433     // Was toolbar shown
1434     getApp()->reg().writeIntEntry("OPTIONS", "hidetoolbar", !toolbar->shown());
1435 
1436     // Highlight match time
1437     getApp()->reg().writeIntEntry("OPTIONS", "hilitematchtime", editor->getHiliteMatchTime());
1438 
1439     // Wrap mode
1440     getApp()->reg().writeIntEntry("OPTIONS", "wordwrap", (editor->getTextStyle()&TEXT_WORDWRAP) != 0);
1441     getApp()->reg().writeIntEntry("OPTIONS", "wrapcols", editor->getWrapColumns());
1442 
1443     // Tab settings
1444     getApp()->reg().writeIntEntry("OPTIONS", "tabcols", editor->getTabColumns());
1445 
1446     // Strip returns
1447     getApp()->reg().writeIntEntry("OPTIONS", "stripreturn", stripcr);
1448     getApp()->reg().writeIntEntry("OPTIONS", "linesnum", linesnum);
1449 
1450     // Search path
1451     getApp()->reg().writeStringEntry("OPTIONS", "searchpath", searchpath.text());
1452 
1453     // Font
1454     fontspec = editor->getFont()->getFont();
1455     getApp()->reg().writeStringEntry("OPTIONS", "textfont", fontspec.text());
1456 
1457     // Write registry options
1458     getApp()->reg().write();
1459 }
1460 
1461 
1462 // Harvest the zombies
onSigHarvest(FXObject *,FXSelector,void *)1463 long WriteWindow::onSigHarvest(FXObject*, FXSelector, void*)
1464 {
1465     while (waitpid(-1, NULL, WNOHANG) > 0)
1466     {
1467     }
1468     return(1);
1469 }
1470 
1471 
1472 // About box
onCmdAbout(FXObject *,FXSelector,void *)1473 long WriteWindow::onCmdAbout(FXObject*, FXSelector, void*)
1474 {
1475     FXString msg;
1476 
1477     msg.format(_("X File Write Version %s is a simple text editor.\n\n"), VERSION);
1478     msg += COPYRIGHT;
1479     MessageBox about(this, _("About X File Write"), msg.text(), xfwicon, BOX_OK|DECOR_TITLE|DECOR_BORDER,
1480                      JUSTIFY_CENTER_X|ICON_BEFORE_TEXT|LAYOUT_CENTER_Y|LAYOUT_LEFT|LAYOUT_FILL_X|LAYOUT_FILL_Y);
1481     about.execute(PLACEMENT_OWNER);
1482     return(1);
1483 }
1484 
1485 
1486 // Show preferences dialog
onCmdMorePrefs(FXObject *,FXSelector,void *)1487 long WriteWindow::onCmdMorePrefs(FXObject*, FXSelector, void*)
1488 {
1489     if (prefsdialog == NULL)
1490     {
1491         prefsdialog = new Preferences(this);
1492     }
1493     prefsdialog->execute(PLACEMENT_OWNER);
1494     return(1);
1495 }
1496 
1497 
1498 // Change text font
onCmdFont(FXObject *,FXSelector,void *)1499 long WriteWindow::onCmdFont(FXObject*, FXSelector, void*)
1500 {
1501     FontDialog fontdlg(this, _("Change Font"), DECOR_BORDER|DECOR_TITLE);
1502     FXFontDesc fontdesc;
1503 
1504     editor->getFont()->getFontDesc(fontdesc);
1505     fontdlg.setFontSelection(fontdesc);
1506     if (fontdlg.execute())
1507     {
1508         FXFont* oldfont = font;
1509         fontdlg.getFontSelection(fontdesc);
1510         font = new FXFont(getApp(), fontdesc);
1511         font->create();
1512         editor->setFont(font);
1513         delete oldfont;
1514     }
1515     saveConfig();
1516     return(1);
1517 }
1518 
1519 
1520 // New
onCmdNew(FXObject *,FXSelector,void *)1521 long WriteWindow::onCmdNew(FXObject*, FXSelector, void*)
1522 {
1523     WriteWindow* window = new WriteWindow(getApp(), unique(), readonly);
1524 
1525     // Smooth scrolling
1526     window->setSmoothScroll(smoothscroll);
1527 
1528     window->create();
1529     window->raise();
1530     window->setFocus();
1531     return(1);
1532 }
1533 
1534 
1535 // Open
onCmdOpen(FXObject *,FXSelector,void *)1536 long WriteWindow::onCmdOpen(FXObject*, FXSelector, void*)
1537 {
1538     const char* patterns[] =
1539     {
1540         _("All Files"), "*",
1541         _("Text Files"), "*.txt",
1542         _("C Source Files"), "*.c",
1543         _("C++ Source Files"), "*.cpp",
1544         _("C++ Source Files"), "*.cc",
1545         _("C++ Source Files"), "*.cxx",
1546         _("C/C++ Header Files"), "*.h",
1547         _("HTML Files"), "*.html",
1548         _("HTML Files"), "*.htm",
1549         _("PHP Files"), "*.php", NULL
1550     };
1551 
1552     FileDialog opendialog(this, _("Open Document"));
1553 
1554     opendialog.setSelectMode(SELECTFILE_MULTIPLE);
1555     opendialog.setPatternList(patterns);
1556     opendialog.setDirectory(FXPath::directory(filename));
1557     if (opendialog.execute())
1558     {
1559         FXString* files = opendialog.getFilenames();
1560         FXuint    i = 0;
1561         while (files[i] != FXString::null)
1562         {
1563             WriteWindow* window = findWindow(files[i]);
1564             if (!window)
1565             {
1566                 window = findUnused();
1567                 if (!window)
1568                 {
1569                     // New window
1570                     window = new WriteWindow(getApp(), unique(), readonly);
1571 
1572                     // Smooth scrolling
1573                     window->setSmoothScroll(smoothscroll);
1574 
1575                     // Set the size and position of the new window
1576                     window->fromreg = false;
1577                     window->ww = getWidth();
1578                     window->hh = getHeight();
1579                     window->xx = getX();
1580                     window->yy = getY();
1581 
1582                     // Create window
1583                     window->create();
1584                 }
1585                 window->loadFile(files[i]);
1586             }
1587             window->raise();
1588             window->setFocus();
1589             i++;
1590         }
1591         delete[] files;
1592     }
1593 
1594     return(1);
1595 }
1596 
1597 
1598 // Open recent file
onCmdOpenRecent(FXObject *,FXSelector,void * ptr)1599 long WriteWindow::onCmdOpenRecent(FXObject*, FXSelector, void* ptr)
1600 {
1601     FXString     file = (const char*)ptr;
1602     WriteWindow* window = findWindow(file);
1603 
1604     if (!window)
1605     {
1606         window = findUnused();
1607         if (!window)
1608         {
1609             window = new WriteWindow(getApp(), unique(), readonly);
1610 
1611             // Smooth scrolling
1612             window->setSmoothScroll(smoothscroll);
1613 
1614             window->create();
1615         }
1616         window->loadFile(file);
1617     }
1618     window->raise();
1619     window->setFocus();
1620     return(1);
1621 }
1622 
1623 
1624 // See if we can get it as a filename
onEditDNDDrop(FXObject *,FXSelector,void *)1625 long WriteWindow::onEditDNDDrop(FXObject*, FXSelector, void*)
1626 {
1627     FXuchar*  data;
1628     FXuint len;
1629 
1630     if (getDNDData(FROM_DRAGNDROP, urilistType, data, len))
1631     {
1632         FXString urilist((FXchar*)data, len);
1633         FXString file = FXURL::fileFromURL(urilist.before('\r'));
1634         FXFREE(&data);
1635         if (file.empty())
1636         {
1637             return(1);
1638         }
1639         if (!saveChanges())
1640         {
1641             return(1);
1642         }
1643         loadFile(file);
1644         return(1);
1645     }
1646     return(0);
1647 }
1648 
1649 
1650 // See if a filename is being dragged over the window
onEditDNDMotion(FXObject *,FXSelector,void *)1651 long WriteWindow::onEditDNDMotion(FXObject*, FXSelector, void*)
1652 {
1653     if (offeredDNDType(FROM_DRAGNDROP, urilistType))
1654     {
1655         acceptDrop(DRAG_COPY);
1656         return(1);
1657     }
1658     return(0);
1659 }
1660 
1661 
1662 // Save changes, prompt for new filename
saveChanges()1663 FXbool WriteWindow::saveChanges()
1664 {
1665     FXuint   answer;
1666     FXString file;
1667 
1668     if (isModified())
1669     {
1670         answer = MessageBox::question(this, BOX_YES_NO_CANCEL, _("Unsaved Document"), _("Save %s to file?"), FXPath::name(filename).text());
1671         if (answer == BOX_CLICKED_CANCEL)
1672         {
1673             return(false);
1674         }
1675         if (answer == BOX_CLICKED_YES)
1676         {
1677             file = filename;
1678             if (!filenameset)
1679             {
1680                 FileDialog savedialog(this, _("Save Document"));
1681                 savedialog.setSelectMode(SELECTFILE_ANY);
1682                 savedialog.setFilename(file);
1683                 if (!savedialog.execute())
1684                 {
1685                     return(false);
1686                 }
1687                 file = savedialog.getFilename();
1688                 if (existFile(file))
1689                 {
1690                     if (BOX_CLICKED_NO == MessageBox::question(this, BOX_YES_NO, _("Overwrite Document"), _("Overwrite existing document: %s?"), file.text()))
1691                     {
1692                         return(false);
1693                     }
1694                 }
1695             }
1696             saveFile(file);
1697         }
1698     }
1699     return(true);
1700 }
1701 
1702 
1703 // Save
onCmdSave(FXObject * sender,FXSelector sel,void * ptr)1704 long WriteWindow::onCmdSave(FXObject* sender, FXSelector sel, void* ptr)
1705 {
1706     if (!filenameset)
1707     {
1708         return(onCmdSaveAs(sender, sel, ptr));
1709     }
1710     saveFile(filename);
1711     return(1);
1712 }
1713 
1714 
1715 // Save Update
onUpdSave(FXObject * sender,FXSelector,void *)1716 long WriteWindow::onUpdSave(FXObject* sender, FXSelector, void*)
1717 {
1718     sender->handle(this, isModified() ? FXSEL(SEL_COMMAND, ID_ENABLE) : FXSEL(SEL_COMMAND, ID_DISABLE), NULL);
1719     return(1);
1720 }
1721 
1722 
1723 // Disable menus and buttons when read only
onUpdReadOnly(FXObject * sender,FXSelector,void *)1724 long WriteWindow::onUpdReadOnly(FXObject* sender, FXSelector, void*)
1725 {
1726     sender->handle(this, readonly ? FXSEL(SEL_COMMAND, ID_DISABLE) : FXSEL(SEL_COMMAND, ID_ENABLE), NULL);
1727 
1728     // Disable cut and paste commands
1729     // (note: it seems that the context menu commands can't be disabled)
1730     //paste->disable();
1731     //pastemc->disable();
1732     //cut->disable();
1733     //cutmc->disable();
1734 
1735     return(1);
1736 }
1737 
1738 
1739 // Save As
onCmdSaveAs(FXObject *,FXSelector,void *)1740 long WriteWindow::onCmdSaveAs(FXObject*, FXSelector, void*)
1741 {
1742     FileDialog savedialog(this, _("Save Document"));
1743     FXString   file = filename;
1744 
1745     savedialog.setSelectMode(SELECTFILE_ANY);
1746     savedialog.setFilename(file);
1747     if (savedialog.execute())
1748     {
1749         file = savedialog.getFilename();
1750         if (existFile(file))
1751         {
1752             if (BOX_CLICKED_NO == MessageBox::question(this, BOX_YES_NO, _("Overwrite Document"), _("Overwrite existing document: %s?"), file.text()))
1753             {
1754                 return(1);
1755             }
1756         }
1757         saveFile(file);
1758     }
1759 
1760     return(1);
1761 }
1762 
1763 
1764 // Close window
close(FXbool notify)1765 FXbool WriteWindow::close(FXbool notify)
1766 {
1767     // Prompt to save changes
1768     if (!saveChanges())
1769     {
1770         return(false);
1771     }
1772 
1773     // Save settings
1774     saveConfig();
1775 
1776     // Perform normal close stuff
1777     return(FXMainWindow::close(notify));
1778 }
1779 
1780 
1781 // User clicks on one of the window menus
onCmdWindow(FXObject *,FXSelector sel,void *)1782 long WriteWindow::onCmdWindow(FXObject*, FXSelector sel, void*)
1783 {
1784     int which = FXSELID(sel)-ID_WINDOW_1;
1785 
1786     if (which < getApp()->windowlist.no())
1787     {
1788         getApp()->windowlist[which]->raise();
1789         getApp()->windowlist[which]->setFocus();
1790     }
1791     return(1);
1792 }
1793 
1794 
1795 // Update handler for window menus
onUpdWindow(FXObject * sender,FXSelector sel,void *)1796 long WriteWindow::onUpdWindow(FXObject* sender, FXSelector sel, void*)
1797 {
1798     int which = FXSELID(sel)-ID_WINDOW_1;
1799 
1800     if (which < getApp()->windowlist.no())
1801     {
1802         WriteWindow* window = getApp()->windowlist[which];
1803         FXString     string;
1804         if (which < 49)
1805         {
1806             string.format("&%d %s", which+1, window->getTitle().text());
1807         }
1808         else
1809         {
1810             string.format("5&0 %s", window->getTitle().text());
1811         }
1812 
1813         sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_SETSTRINGVALUE), (void*)&string);
1814 
1815         if (window == getApp()->getActiveWindow())
1816         {
1817             sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_CHECK), NULL);
1818         }
1819 
1820         else
1821         {
1822             sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_UNCHECK), NULL);
1823         }
1824         sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_SHOW), NULL);
1825     }
1826     else
1827     {
1828         sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_HIDE), NULL);
1829     }
1830     return(1);
1831 }
1832 
1833 
1834 // Update title from current filename
onUpdateTitle(FXObject * sender,FXSelector sel,void * ptr)1835 long WriteWindow::onUpdateTitle(FXObject* sender, FXSelector sel, void* ptr)
1836 {
1837     FXMainWindow::onUpdate(sender, sel, ptr);
1838     FXString title = FXPath::name(getFilename());
1839     if (isModified())
1840     {
1841         title += _(" (changed)");
1842     }
1843     FXString directory = FXPath::directory(getFilename());
1844     if (!directory.empty())
1845     {
1846         title += " - " + directory;
1847     }
1848 
1849     if (readonly)
1850     {
1851         title += _(" (read only)");
1852     }
1853 
1854     setTitle(title);
1855     return(1);
1856 }
1857 
1858 
1859 // Print the text
onCmdPrint(FXObject *,FXSelector,void *)1860 long WriteWindow::onCmdPrint(FXObject*, FXSelector, void*)
1861 {
1862     // Read the current print command from the registry
1863     FXString printcommand, command;
1864 
1865     printcommand = getApp()->reg().readStringEntry("OPTIONS", "print_command", "lpr -P printer");
1866 
1867     // Open print dialog filled with the current print command
1868     int rc = 1;
1869     if (printdialog == NULL)
1870     {
1871         printdialog = new InputDialog(this, printcommand, _("Print command: \n(ex: lpr -P <printer>)"), _("Print"), "", printbigicon);
1872     }
1873     printdialog->setText(printcommand);
1874     printdialog->CursorEnd();
1875     rc = printdialog->execute(PLACEMENT_CURSOR);
1876     printcommand = printdialog->getText();
1877 
1878     // If cancel was pressed, exit
1879     if (!rc)
1880     {
1881         return(0);
1882     }
1883 
1884     // Write the new print command to the registry
1885     getApp()->reg().writeStringEntry("OPTIONS", "print_command", printcommand.text());
1886 
1887     // Perform the print command
1888     command = "cat " + filename + " |" + printcommand + " &";
1889     int ret = system(command.text());
1890     if (ret < 0)
1891     {
1892         MessageBox::error(this, BOX_OK, _("Error"), _("Can't execute command %s"), command.text());
1893         return(0);
1894     }
1895 
1896     return(1);
1897 }
1898 
1899 
1900 // Toggle wrap mode
onCmdWrap(FXObject *,FXSelector,void *)1901 long WriteWindow::onCmdWrap(FXObject*, FXSelector, void*)
1902 {
1903     editor->setTextStyle(editor->getTextStyle()^TEXT_WORDWRAP);
1904     return(1);
1905 }
1906 
1907 
1908 // Update toggle wrap mode
onUpdWrap(FXObject * sender,FXSelector,void *)1909 long WriteWindow::onUpdWrap(FXObject* sender, FXSelector, void*)
1910 {
1911     if (editor->getTextStyle()&TEXT_WORDWRAP)
1912     {
1913         sender->handle(this, FXSEL(SEL_COMMAND, ID_CHECK), NULL);
1914     }
1915     else
1916     {
1917         sender->handle(this, FXSEL(SEL_COMMAND, ID_UNCHECK), NULL);
1918     }
1919     return(1);
1920 }
1921 
1922 
1923 // Toggle lines numbering
onCmdLinesNum(FXObject *,FXSelector,void *)1924 long WriteWindow::onCmdLinesNum(FXObject*, FXSelector, void*)
1925 {
1926     linesnum = !linesnum;
1927     if (linesnum)
1928     {
1929         FXuint size = editor->getNumRows();
1930         FXuint cols = (FXuint)ceil(log10(size));
1931         editor->setBarColumns(cols);
1932     }
1933     else
1934     {
1935         editor->setBarColumns(0);
1936     }
1937 
1938     return(1);
1939 }
1940 
1941 
1942 // Update toggle line numbers
onUpdLinesNum(FXObject * sender,FXSelector,void *)1943 long WriteWindow::onUpdLinesNum(FXObject* sender, FXSelector, void*)
1944 {
1945     if (linesnum)
1946     {
1947         sender->handle(this, FXSEL(SEL_COMMAND, ID_CHECK), NULL);
1948     }
1949     else
1950     {
1951         sender->handle(this, FXSEL(SEL_COMMAND, ID_UNCHECK), NULL);
1952     }
1953     return(1);
1954 }
1955 
1956 
1957 // Update box for overstrike mode display
onUpdOverstrike(FXObject * sender,FXSelector,void *)1958 long WriteWindow::onUpdOverstrike(FXObject* sender, FXSelector, void*)
1959 {
1960     if (readonly)
1961     {
1962         FXString mode(_("READ ONLY"));
1963         sender->handle(this, FXSEL(SEL_COMMAND, ID_SETSTRINGVALUE), (void*)&mode);
1964     }
1965     else
1966     {
1967         FXString mode((editor->getTextStyle()&TEXT_OVERSTRIKE) ? _("OVR") : _("INS"));
1968         sender->handle(this, FXSEL(SEL_COMMAND, ID_SETSTRINGVALUE), (void*)&mode);
1969     }
1970 
1971     return(1);
1972 }
1973 
1974 
1975 // Update box for size display
onUpdNumRows(FXObject * sender,FXSelector,void *)1976 long WriteWindow::onUpdNumRows(FXObject* sender, FXSelector, void*)
1977 {
1978     FXuint size = editor->getNumRows();
1979 
1980     sender->handle(this, FXSEL(SEL_COMMAND, ID_SETINTVALUE), (void*)&size);
1981     return(1);
1982 }
1983 
1984 
1985 // Text inserted; callback has [pos nins]
onTextInserted(FXObject *,FXSelector,void * ptr)1986 long WriteWindow::onTextInserted(FXObject*, FXSelector, void* ptr)
1987 {
1988     const FXTextChange* change = (const FXTextChange*)ptr;
1989 
1990     // Log undo record
1991     if (!undolist.busy())
1992     {
1993         undolist.add(new FXTextInsert(editor, change->pos, change->nins, change->ins));
1994         if (undolist.size() > MAXUNDOSIZE)
1995         {
1996             undolist.trimSize(KEEPUNDOSIZE);
1997         }
1998     }
1999 
2000 
2001     return(1);
2002 }
2003 
2004 
2005 // Text deleted; callback has [pos ndel]
onTextDeleted(FXObject *,FXSelector,void * ptr)2006 long WriteWindow::onTextDeleted(FXObject*, FXSelector, void* ptr)
2007 {
2008     const FXTextChange* change = (const FXTextChange*)ptr;
2009 
2010     // Log undo record
2011     if (!undolist.busy())
2012     {
2013         undolist.add(new FXTextDelete(editor, change->pos, change->ndel, change->del));
2014         if (undolist.size() > MAXUNDOSIZE)
2015         {
2016             undolist.trimSize(KEEPUNDOSIZE);
2017         }
2018     }
2019 
2020     return(1);
2021 }
2022 
2023 
2024 // Text replaced; callback has [pos ndel nins]
onTextReplaced(FXObject *,FXSelector,void * ptr)2025 long WriteWindow::onTextReplaced(FXObject*, FXSelector, void* ptr)
2026 {
2027     const FXTextChange* change = (const FXTextChange*)ptr;
2028 
2029     // Log undo record
2030     if (!undolist.busy())
2031     {
2032         undolist.add(new FXTextReplace(editor, change->pos, change->ndel, change->nins, change->del, change->ins));
2033         if (undolist.size() > MAXUNDOSIZE)
2034         {
2035             undolist.trimSize(KEEPUNDOSIZE);
2036         }
2037     }
2038 
2039     return(1);
2040 }
2041 
2042 
2043 // Released right button
onTextRightMouse(FXObject *,FXSelector,void * ptr)2044 long WriteWindow::onTextRightMouse(FXObject*, FXSelector, void* ptr)
2045 {
2046     FXEvent* event = (FXEvent*)ptr;
2047 
2048     if (!event->moved)
2049     {
2050         allowPopupScroll = true; // Allow keyboard scrolling
2051         popupmenu->popup(NULL, event->root_x, event->root_y);
2052         getApp()->runModalWhileShown(popupmenu);
2053         allowPopupScroll = false;
2054     }
2055     return(1);
2056 }
2057 
2058 
2059 // Check file when focus moves in
onFocusIn(FXObject * sender,FXSelector sel,void * ptr)2060 long WriteWindow::onFocusIn(FXObject* sender, FXSelector sel, void* ptr)
2061 {
2062     register FXTime t;
2063 
2064     FXMainWindow::onFocusIn(sender, sel, ptr);
2065     if (filetime != 0)
2066     {
2067         t = FXStat::modified(filename);
2068         if (t && (t != filetime))
2069         {
2070             filetime = t;
2071             if (BOX_CLICKED_OK == MessageBox::warning(this, BOX_OK_CANCEL, _("File Was Changed"), _("%s\nwas changed by another program. Reload this file from disk?"), filename.text()))
2072             {
2073                 int top = editor->getTopLine();
2074                 int pos = editor->getCursorPos();
2075                 loadFile(filename);
2076                 editor->setTopLine(top);
2077                 editor->setCursorPos(pos);
2078             }
2079         }
2080     }
2081     return(1);
2082 }
2083 
2084 
2085 // Search text
onCmdSearch(FXObject *,FXSelector,void *)2086 long WriteWindow::onCmdSearch(FXObject*, FXSelector, void*)
2087 {
2088     if (searchdialog == NULL)
2089     {
2090         searchdialog = new FXSearchDialog(this, _("Search"), searchicon, options|DECOR_CLOSE);
2091     }
2092     searchdialog->setSearchMode(SEARCH_IGNORECASE);
2093 
2094     int      beg[10];
2095     int      end[10];
2096     int      pos;
2097     FXuint   code;
2098     FXString searchstring;
2099     FXuint   searchflags;
2100     do
2101     {
2102         code = searchdialog->execute();
2103         if (code == FXSearchDialog::DONE)
2104         {
2105             return(1);
2106         }
2107         searchstring = searchdialog->getSearchText();
2108         searchflags = searchdialog->getSearchMode();
2109         pos = editor->isPosSelected(editor->getCursorPos()) ? (searchflags&SEARCH_BACKWARD) ? editor->getSelStartPos()-1 : editor->getSelEndPos() : editor->getCursorPos();
2110         if (editor->findText(searchstring, beg, end, pos, searchflags|SEARCH_WRAP, 10))
2111         {
2112             editor->setAnchorPos(beg[0]);
2113             editor->extendSelection(end[0], SELECT_CHARS, true);
2114             editor->setCursorPos(end[0], true);
2115             editor->makePositionVisible(beg[0]);
2116             editor->makePositionVisible(end[0]);
2117         }
2118         else
2119         {
2120             getApp()->beep();
2121         }
2122     } while (code == FXSearchDialog::SEARCH_NEXT);
2123     return(1);
2124 }
2125 
2126 
2127 // Replace text; we assume that findText has called squeezegap()!
onCmdReplace(FXObject *,FXSelector,void *)2128 long WriteWindow::onCmdReplace(FXObject*, FXSelector, void*)
2129 {
2130     if (replacedialog == NULL)
2131     {
2132         replacedialog = new FXReplaceDialog(this, _("Replace"), replaceicon, options|DECOR_CLOSE);
2133     }
2134     replacedialog->setSearchMode(SEARCH_IGNORECASE);
2135 
2136     int      beg[10], end[10], fm, to, len, pos;
2137     FXuint   searchflags, code;
2138     FXString searchstring;
2139     FXString replacestring;
2140     FXString replacevalue;
2141 
2142     // Get text into buffer
2143     char* buffer;
2144     int   length = editor->getLength();
2145     FXMALLOC(&buffer, char, length);
2146     editor->getText(buffer, length);
2147 
2148     do
2149     {
2150         code = replacedialog->execute();
2151         if (code == FXReplaceDialog::DONE)
2152         {
2153             goto ret;
2154         }
2155         searchflags = replacedialog->getSearchMode();
2156         searchstring = replacedialog->getSearchText();
2157         replacestring = replacedialog->getReplaceText();
2158         replacevalue = FXString::null;
2159         fm = -1;
2160         to = -1;
2161         if (code == FXReplaceDialog::REPLACE_ALL)
2162         {
2163             searchflags &= ~SEARCH_BACKWARD;
2164             pos = 0;
2165             while (editor->findText(searchstring, beg, end, pos, searchflags, 10))
2166             {
2167                 if (0 <= fm)
2168                 {
2169                     replacevalue.append(&buffer[pos], beg[0]-pos);
2170                 }
2171                 replacevalue.append(FXRex::substitute(buffer, length, beg, end, replacestring, 10));
2172                 if (fm < 0)
2173                 {
2174                     fm = beg[0];
2175                 }
2176                 to = end[0];
2177                 pos = end[0];
2178                 if (beg[0] == end[0])
2179                 {
2180                     pos++;
2181                 }
2182             }
2183         }
2184         else
2185         {
2186             pos = editor->isPosSelected(editor->getCursorPos()) ? (searchflags&SEARCH_BACKWARD) ? editor->getSelStartPos()-1 : editor->getSelEndPos() : editor->getCursorPos();
2187             if (editor->findText(searchstring, beg, end, pos, searchflags|SEARCH_WRAP, 10))
2188             {
2189                 replacevalue = FXRex::substitute(buffer, length, beg, end, replacestring, 10);
2190                 fm = beg[0];
2191                 to = end[0];
2192             }
2193         }
2194         if (0 <= fm)
2195         {
2196             len = replacevalue.length();
2197             editor->replaceText(fm, to-fm, replacevalue.text(), len, true);
2198             editor->setCursorPos(fm+len, true);
2199             editor->makePositionVisible(editor->getCursorPos());
2200             editor->setModified(true);
2201         }
2202         else
2203         {
2204             getApp()->beep();
2205         }
2206     } while (code == FXReplaceDialog::REPLACE_NEXT);
2207 
2208 ret:
2209     FXFREE(&buffer);
2210     return(1);
2211 }
2212 
2213 
2214 // Search for selected text
onCmdSearchSel(FXObject *,FXSelector sel,void *)2215 long WriteWindow::onCmdSearchSel(FXObject*, FXSelector sel, void*)
2216 {
2217     FXString string;
2218     FXuint   searchflags;
2219     FXString searchstring;
2220     int      pos = editor->getCursorPos();
2221     int      beg, end;
2222 
2223     // First, try UTF-8
2224     if (getDNDData(FROM_SELECTION, utf8Type, string))
2225     {
2226         searchstring = string;
2227     }
2228 
2229     // Next, try UTF-16
2230     else if (getDNDData(FROM_SELECTION, utf16Type, string))
2231     {
2232         FXUTF16LECodec unicode;                 // FIXME maybe other endianness for unix
2233         searchstring = unicode.mb2utf(string);
2234     }
2235 
2236     // Finally, try good old 8859-1
2237     else if (getDNDData(FROM_SELECTION, stringType, string))
2238     {
2239         FX88591Codec ascii;
2240         searchstring = ascii.mb2utf(string);
2241     }
2242 
2243     // No dice!
2244     else
2245     {
2246         goto x;
2247     }
2248 
2249     // Search direction
2250     if (FXSELID(sel) == ID_SEARCH_FORW_SEL)
2251     {
2252         if (editor->isPosSelected(pos))
2253         {
2254             pos = editor->getSelEndPos();
2255         }
2256         searchflags = SEARCH_EXACT|SEARCH_FORWARD;
2257     }
2258     else
2259     {
2260         if (editor->isPosSelected(pos))
2261         {
2262             pos = editor->getSelStartPos()-1;
2263         }
2264         searchflags = SEARCH_EXACT|SEARCH_BACKWARD;
2265     }
2266 
2267     // Perform search
2268     if (editor->findText(searchstring, &beg, &end, pos, searchflags|SEARCH_WRAP))
2269     {
2270         if ((beg != editor->getSelStartPos()) || (end != editor->getSelEndPos()))
2271         {
2272             editor->setAnchorPos(beg);
2273             editor->extendSelection(end, SELECT_CHARS, true);
2274             editor->setCursorPos(end);
2275             editor->makePositionVisible(beg);
2276             editor->makePositionVisible(end);
2277             return(1);
2278         }
2279     }
2280 
2281     // Beep
2282 x:
2283     getApp()->beep();
2284     return(1);
2285 }
2286 
2287 
2288 // Go to line number
onCmdGotoLine(FXObject *,FXSelector,void *)2289 long WriteWindow::onCmdGotoLine(FXObject*, FXSelector, void*)
2290 {
2291     int row = editor->getCursorRow()+1;
2292 
2293     if (FXInputDialog::getInteger(row, this, _("Goto Line"), _("&Goto line number:"), gotobigicon, 1, 2147483647))
2294     {
2295         update();
2296         editor->setCursorRow(row-1, true);
2297         editor->makePositionVisible(editor->getCursorPos());
2298     }
2299     return(1);
2300 }
2301