1 /*
2   FXiTe - The Free eXtensIble Text Editor
3   Copyright (c) 2009-2013 Jeffrey Pohlmeyer <yetanothergeek@gmail.com>
4 
5   This program is free software; you can redistribute it and/or modify it
6   under the terms of the GNU General Public License version 3 as
7   published by the Free Software Foundation.
8 
9   This software is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13 
14   You should have received a copy of the GNU General Public License
15   along with this program; if not, write to the Free Software
16   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18 
19 
20 #include <fx.h>
21 #include <cerrno>
22 
23 #include "appname.h"
24 #include "appmain.h"
25 #include "prefs.h"
26 #include "lang.h"
27 
28 #include "compat.h"
29 #include "scidoc.h"
30 #include "filer.h"
31 #include "toolmgr.h"
32 #include "prefdlg.h"
33 #include "theme.h"
34 #include "tagread.h"
35 #include "recorder.h"
36 #include "macro.h"
37 #include "search.h"
38 #include "backup.h"
39 #include "menuspec.h"
40 #include "mainmenu.h"
41 #include "toolbar.h"
42 #include "doctabs.h"
43 #include "outpane.h"
44 #include "statusbar.h"
45 #include "runcmd.h"
46 #include "cmd_utils.h"
47 #include "scidoc_util.h"
48 #include "foreachtab.h"
49 
50 #include "intl.h"
51 #include "appwin_base.h"
52 
53 
54 #define STALECHECK 5 /* seconds between checks for external changes. */
55 
56 
57 FXDEFMAP(TopWindowBase) TopWindowBaseMap[]={
58   FXMAPFUNC(SEL_TIMEOUT,  TopWindowBase::ID_TIMER,        TopWindowBase::onTimer),
59   FXMAPFUNC(SEL_TIMEOUT,  TopWindowBase::ID_CLOSEWAIT,    TopWindowBase::onCloseWait),
60   FXMAPFUNC(SEL_CHORE,    TopWindowBase::ID_CLOSEWAIT,    TopWindowBase::onCloseWait),
61   FXMAPFUNC(SEL_CHORE,    TopWindowBase::ID_CHECK_STALE,  TopWindowBase::CheckStale),
62   FXMAPFUNC(SEL_CHORE,    TopWindowBase::ID_CHECK_STYLE,  TopWindowBase::CheckStyle),
63   FXMAPFUNC(SEL_CHORE,    TopWindowBase::ID_FOCUS_DOC,    TopWindowBase::onFocusDoc),
64   FXMAPFUNC(SEL_FOCUSIN,  TopWindowBase::ID_SCINTILLA,    TopWindowBase::onFocusSci),
65   FXMAPFUNC(SEL_FOCUSIN,  0,                              TopWindowBase::onFocusIn),
66 };
67 FXIMPLEMENT(TopWindowBase,MainWinWithClipBrd,TopWindowBaseMap,ARRAYNUMBER(TopWindowBaseMap))
68 
69 
70 static bool topwin_closing = false;
71 static TopWindowBase* global_top_window_instance=NULL;
72 
73 
Closing()74 bool TopWindowBase::Closing() { return topwin_closing; }
Closing(bool is_closing)75 void TopWindowBase::Closing(bool is_closing) { topwin_closing=is_closing; }
76 
instance()77 TopWindowBase* TopWindowBase::instance() { return global_top_window_instance; }
78 
ConfigDir()79 const FXString& TopWindowBase::ConfigDir() { return ((AppClass*)(FXApp::instance()))->ConfigDir(); }
80 
Connector()81 const FXString& TopWindowBase::Connector() { return ((AppClass*)(FXApp::instance()))->Connector(); }
82 
SessionFile()83 const FXString& TopWindowBase::SessionFile() { return ((AppClass*)getApp())->SessionFile(); }
84 
85 
Cut()86 void TopWindowBase::Cut()   { SciDocUtils::Cut(FocusedDoc()); }
87 
Copy()88 void TopWindowBase::Copy()  { SciDocUtils::Copy(FocusedDoc()); }
89 
Paste()90 void TopWindowBase::Paste() { SciDocUtils::Paste(FocusedDoc()); }
91 
92 
93 
94 
95 
96 #define PACK_UNIFORM ( PACK_UNIFORM_WIDTH | PACK_UNIFORM_HEIGHT )
97 
TopWindowBase(FXApp * a)98 TopWindowBase::TopWindowBase(FXApp* a):MainWinWithClipBrd(a,EXE_NAME,NULL,NULL,DECOR_ALL,0,0,600,400)
99 {
100   FXASSERT(!global_top_window_instance);
101   global_top_window_instance=this;
102   active_widget=0;
103   recorder=NULL;
104   recording=NULL;
105   need_status=0;
106   stale_ticks=0;
107   save_ticks=0;
108   skipfocus=false;
109   destroying=false;
110   close_all_confirmed=false;
111   kill_commands_confirmed=false;
112   topwin_closing=false;
113   StyleDef*sd=GetStyleFromId(Settings::globalStyle(), STYLE_CALLTIP);
114   tips=new FXToolTip(getApp(),0);
115   RgbToHex(getApp()->getTipbackColor(), sd->bg);
116   RgbToHex(getApp()->getTipforeColor(), sd->fg);
117   prefs=new Settings(this, ConfigDir());
118   SciDoc::DefaultStyles(prefs->Styles());
119   menubar=new MainMenu(this);
120   outerbox=new FXVerticalFrame(this,FRAME_NONE|LAYOUT_FILL,0,0,0,0,0,0,0,0,0,0);
121   innerbox=new FXVerticalFrame(outerbox,FRAME_NONE|LAYOUT_FILL,0,0,0,0,4,4,4,4);
122   toolbar=new ToolBarFrame(innerbox);
123   hsplit=new FXSplitter(innerbox,this, 0, SPLITTER_VERTICAL|SPLITTER_REVERSED|LAYOUT_FILL|SPLITTER_TRACKING);
124   innerbox=new FXVerticalFrame(hsplit,FRAME_NONE|LAYOUT_FILL,0,0,0,0,0,0,0,0);
125   tabbook=new DocTabs(innerbox,this,0,FRAME_NONE|PACK_UNIFORM|LAYOUT_FILL);
126   srchdlgs=new SearchDialogs(innerbox, this, 0);
127   tabbook->setTabStyleByChar(prefs->DocTabPosition);
128   tabbook->setTabsCompact(prefs->DocTabsPacked);
129   tabbook->MaxTabWidth(prefs->TabTitleMaxWidth);
130   outlist=new OutputList(hsplit,NULL,0,LAYOUT_SIDE_TOP|LAYOUT_FILL);
131   statusbar=new StatusBar(outerbox,(void*)CommandUtils::DontFreezeMe());
132   backups=new BackupMgr(this, ConfigDir());
133   completions=new AutoCompleter();
134   srchdlgs->SetPrefs(prefs->SearchOptions,prefs->SearchWrap,prefs->SearchVerbose,prefs->SearchGui);
135   cmdutils=new CommandUtils(this);
136   filedlgs=new FileDialogs(this,0);
137 }
138 
139 
140 
~TopWindowBase()141 TopWindowBase::~TopWindowBase()
142 {
143   destroying=true;
144   delete filedlgs;
145   delete backups;
146   delete cmdutils;
147   delete recorder;
148   delete getIcon();
149   delete getMiniIcon();
150   delete completions;
151   global_top_window_instance=NULL;
152 }
153 
154 
155 
156 const
157 #include "fxite.xpm"
158 
159 
create()160 void TopWindowBase::create()
161 {
162   AppClass* a=(AppClass*)getApp();
163   a->setWheelLines(prefs->WheelLines);
164   position(prefs->Left, prefs->Top,prefs->Width,prefs->Height);
165   MainWinWithClipBrd::create();
166   tips->create();
167   show(prefs->placement);
168   FXIcon*ico=NULL;
169   FXString icon_file=ConfigDir()+"icon.xpm";
170   if (FXStat::isFile(icon_file)) {
171     FXFileStream*icon_strm=new FXFileStream();
172     if (icon_strm->open(icon_file.text(),FXStreamLoad)) {
173       ico=new FXXPMIcon(a,NULL,0,IMAGE_KEEP);
174       if ( ((FXXPMIcon*)ico)->loadPixels(*icon_strm) ) {
175         ico->scale(32,32);
176       } else {
177         delete ico;
178         ico=NULL;
179       }
180       icon_strm->close();
181     }
182     delete icon_strm;
183     if (!ico) { fxwarning(_("NOTE: Failed to load custom icon.\n")); }
184   }
185   if (!ico) { ico=new FXXPMIcon(a,icon32x32_xpm,0,IMAGE_KEEP); }
186   ico->create();
187   setIcon(ico);
188   SetupXAtoms(this, a->ServerName().text(), APP_NAME);
189   if (prefs->Maximize) { maximize(); }
190   FXFont fnt(a, prefs->FontName, prefs->FontSize/10);
191   GetFontDescription(prefs->fontdesc,&fnt);
192   save_hook.format("%s%s%c%s%c%s.lua", ConfigDir().text(), "tools", PATHSEP, "hooks", PATHSEP, "saved");
193   UpdateToolbar();
194   RunHookScript("startup");
195   ParseCommands(a->Commands());
196   a->addTimeout(this,ID_TIMER,ONE_SECOND,NULL);
197 #ifndef FOX_1_6
198   if (!a->migration_errors.empty()) {
199     NewFile(false);
200     SciDoc*sci=ControlDoc();
201     sci->SetText(a->migration_errors.text());
202     a->migration_errors="";
203   }
204 #endif
205 }
206 
207 
208 
209 #define confirm(hdr,fmt,arg) \
210   ( FXMessageBox::question(this,MBOX_OK_CANCEL,hdr,fmt,arg) == MBOX_CLICKED_OK )
211 
212 #define not_confirmed() {\
213  close_all_confirmed=false; \
214  kill_commands_confirmed=false; \
215  Closing(false); \
216 }
217 
218 
close(FXbool notify)219 FXbool TopWindowBase::close(FXbool notify)
220 {
221   if (Closing()) { return false; }
222   if (!getApp()->getActiveWindow()) {
223     hide();
224     getApp()->runWhileEvents();
225     if (Closing()) { return false; }
226     show();
227     getApp()->runWhileEvents();
228     if (Closing()) { return false; }
229   }
230   if ((!tabbook->isEnabled()) && (!kill_commands_confirmed) ) {
231     if (!confirm(_("Command in progress"), "%s", _("External command in progress - exit anyway?"))) {
232       not_confirmed();
233       return false;
234     }
235     kill_commands_confirmed=true;
236     command_timeout=true;
237     getApp()->addChore(this,ID_CLOSEWAIT, NULL);
238     getApp()->runWhileEvents();
239     return false;
240   }
241 
242   if (prefs->PromptCloseMultiExit && (tabbook->Count()>1) && (!close_all_confirmed)) {
243     if (!confirm(_("Multiple files"), _("Editing %d files - \nclose all tabs?"), tabbook->Count() ) ) {
244       not_confirmed();
245       FocusedDoc()->setFocus();
246       return false;
247     }
248     close_all_confirmed=true;
249   }
250 
251   session_data="";
252   if (!RunHookScript("shutdown")) { return false; }
253   prefs->LastFocused=FocusedDoc()->Filename();
254   if (!CloseAll(true)) {
255     not_confirmed();
256     prefs->LastFocused="";
257     FocusedDoc()->setFocus();
258     return false;
259   }
260 
261   if (!session_data.empty()) {
262      FXFile fh(SessionFile(), FXIO::Writing);
263      if (fh.isOpen()) {
264        FXival wrote=0;
265        wrote=fh.writeBlock(session_data.text(),session_data.length());
266        if (!(fh.close() && (wrote==session_data.length()))) {
267          fxwarning(_(EXE_NAME": Could not save %s (%s)"), SessionFile().text(), SystemErrorStr());
268        }
269      } else {
270        fxwarning(_(EXE_NAME": Could not open %s for writing (%s)"), SessionFile().text(), SystemErrorStr());
271      }
272      session_data="";
273   }
274   prefs->Maximize=isMaximized();
275   if (prefs->Maximize) {
276     restore();
277     repaint();
278     getApp()->runWhileEvents();
279   }
280   prefs->Left=getX();
281   prefs->Top=getY();
282   prefs->Width=getWidth();
283   prefs->Height=getHeight();
284 
285   getApp()->runWhileEvents();
286   if (Closing()) { return false; }
287   Closing(true);
288   delete srchdlgs;
289   delete prefs;
290   delete menubar;
291   return FXMainWindow::close(notify);
292 }
293 
294 
295 
296 /*
297   When in split-view mode, ControlDoc() refers to the view at the top (or left) of
298   the split,and FocusedDoc() refers to whichever view has the focus; In single-view
299   mode there is no difference between the ControlDoc and the FocusedDoc.
300 */
ControlDoc()301 SciDoc*TopWindowBase::ControlDoc()
302 {
303   FXWindow *page=tabbook->ActivePage();
304   return page?((SciDoc*)page->getFirst()):NULL;
305 }
306 
307 
308 
FocusedDoc()309 SciDoc*TopWindowBase::FocusedDoc()
310 {
311   return (SciDoc*)tabbook->ActiveView();
312 }
313 
314 
315 
CheckStale(FXObject * o,FXSelector sel,void * p)316 long TopWindowBase::CheckStale(FXObject*o, FXSelector sel, void*p)
317 {
318   static bool CheckingStale=false;
319   SciDoc*sci=ControlDoc();
320   if (!sci) { return 1; }
321   switch (sci->Stale()) {
322     case 0: { break; }
323     case 1: {
324       stale_ticks=0;
325       if ( !CheckingStale ) {
326         if (!IsDesktopCurrent(this)) { return 1; }
327         CheckingStale=true;
328         FXPopup *popup=getApp()->getPopupWindow();
329         if (popup) { popup->popdown(); }
330         if (filedlgs->AskReloadForExternalChanges(sci)) {
331           if (sci->GetReadOnly()) { SetTabLocked(sci,true); }
332         } else {
333           sci->DoStaleTest(false);
334         }
335         CheckingStale=false;
336       }
337       break;
338     }
339     case 2: {
340       stale_ticks=0;
341       if ( !CheckingStale ) {
342         if (!IsDesktopCurrent(this)) { return 1; }
343         CheckingStale=true;
344         FXPopup *popup=getApp()->getPopupWindow();
345         if (popup) { popup->popdown(); }
346         if (filedlgs->AskSaveMissingFile(sci)) {
347           if (!filedlgs->SaveFile(sci,sci->Filename())) { ShowSaveAsDlg(sci); }
348         } else {
349           sci->DoStaleTest(false);
350         }
351         CheckingStale=false;
352       }
353       break;
354     }
355   }
356   return 1;
357 }
358 
359 
360 
361 
362 /*
363   This chore updates a document's settings, and adds a chore to do the same
364   for the next document that needs updating. (See StyleNextDocCB() for more.)
365 */
CheckStyle(FXObject * o,FXSelector sel,void * p)366 long TopWindowBase::CheckStyle(FXObject*o, FXSelector sel, void*p)
367 {
368   SciDoc*sci=(SciDoc*)p;
369   if (sci && sci->NeedStyled()) {
370     SciDocUtils::SetSciDocPrefs(sci, (Settings*)prefs);
371     sci->UpdateStyle();
372     sci->NeedStyled(false);
373   }
374   tabbook->ForEachTab(TabCallbacks::StyleNextDocCB,this,false);
375   return 1;
376 }
377 
378 
379 
onTimer(FXObject * o,FXSelector sel,void * p)380 long TopWindowBase::onTimer(FXObject*o, FXSelector sel, void*p)
381 {
382   if (prefs->WatchExternChanges) {
383     if (stale_ticks < STALECHECK)  {
384       stale_ticks++;
385     } else {
386       if (getApp()->getActiveWindow() && (getApp()->getActiveWindow()->getShell()==this)) {
387         CheckStale(NULL,0,NULL);
388       }
389     }
390   }
391   if (prefs->Autosave) {
392     if (save_ticks < prefs->AutosaveInterval) {
393       save_ticks++;
394     } else {
395       save_ticks=0;
396       tabbook->ForEachTab(TabCallbacks::AutoSaveCB,backups);
397     }
398   }
399   if (prefs->Autosave||prefs->WatchExternChanges) { getApp()->addTimeout(this,ID_TIMER, ONE_SECOND, NULL); }
400   return 1;
401 }
402 
403 
404 
onCloseWait(FXObject * o,FXSelector sel,void * p)405 long TopWindowBase::onCloseWait(FXObject*o, FXSelector sel, void*p)
406 {
407   if (FXSELTYPE(sel)==SEL_CHORE) {
408     static FXint CloseWaitChoreCount=10;
409     if (CloseWaitChoreCount>0) {
410       CloseWaitChoreCount--;
411       getApp()->addChore(this,ID_CLOSEWAIT, NULL);
412     } else {
413       CloseWaitChoreCount=10;
414       getApp()->addTimeout(this,ID_CLOSEWAIT, ONE_SECOND/10, NULL);
415     }
416   } else {
417     close();
418   }
419   return 1;
420 }
421 
422 
423 
onFocusIn(FXObject * o,FXSelector sel,void * p)424 long TopWindowBase::onFocusIn(FXObject*o, FXSelector sel, void*p)
425 {
426   long rv=MainWinWithClipBrd::onFocusIn(o,sel,p);
427   FXWindow*mw=getApp()->getModalWindow();
428   FXWindow*mwo=mw?mw->getOwner():NULL;
429   if (mw&&(mwo!=this)) {
430     if (mwo) {
431       mw->hide();
432       mw->show();
433     }
434     mw->setFocus();
435 #ifdef FOX_1_6
436     FXWindow*dw=FXWindow::findDefault(mw);
437 #else
438     FXWindow*dw=mw->findDefault();
439 #endif
440     if (dw) { dw->setFocus(); }
441   } else {
442     FXWindow*aw=getApp()->findWindowWithId(active_widget);
443     if (aw) {
444       aw->setFocus();
445     } else if (FocusedDoc()) {
446       FocusedDoc()->setFocus();
447     }
448   }
449   return rv;
450 }
451 
452 
453 
onFocusDoc(FXObject * o,FXSelector sel,void * p)454 long TopWindowBase::onFocusDoc(FXObject*o, FXSelector sel, void*p ) {
455   if (skipfocus) {
456     skipfocus=false;
457   } else {
458     if (getApp()->getActiveWindow()==this) {
459       SciDoc*sci=FocusedDoc();
460       if (sci) { sci->setFocus(); }
461     }
462   }
463   return 0;
464 }
465 
466 
467 
onFocusSci(FXObject * o,FXSelector s,void * p)468 long TopWindowBase::onFocusSci(FXObject*o,FXSelector s,void*p)
469 {
470   getApp()->addChore(this, ID_CHECK_STALE);
471   if (((SciDoc*)o)->NeedStyled()) { getApp()->addChore(this, ID_CHECK_STYLE,o); }
472   active_widget=((SciDoc*)o)->id();
473   return 1;
474 }
475 
476 
477 
SetTabDirty(SciDoc * sci,bool dirty)478 void TopWindowBase::SetTabDirty(SciDoc*sci, bool dirty)
479 {
480   DocTab*tab=(DocTab*)sci->getParent()->getPrev();
481   tab->SetIcon(dirty?DOCTAB_DIRTY:DOCTAB_CLEAN);
482   sci->Dirty(dirty);
483 }
484 
485 
486 
SetTabLocked(SciDoc * sci,bool locked)487 void TopWindowBase::SetTabLocked(SciDoc*sci, bool locked)
488 {
489   DocTab*tab=(DocTab*)sci->getParent()->getPrev();
490   tab->SetIcon(locked?DOCTAB_LOCKED:DOCTAB_CLEAN);
491   sci->sendMessage(SCI_SETREADONLY,locked?1:0,0);
492 }
493 
494 
495 
ShowSaveAsDlg(SciDoc * sci)496 bool TopWindowBase::ShowSaveAsDlg(SciDoc*sci)
497 {
498   FXString orig=sci->Filename();
499   if (filedlgs->SaveFileAs(sci)) {
500     if (!orig.empty()) { menubar->PrependRecentFile(orig); }
501     menubar->RemoveRecentFile(sci->Filename());
502     return true;
503   }
504   return false;
505 }
506 
507 
508 
ShowInsertFileDlg()509 void TopWindowBase::ShowInsertFileDlg()
510 {
511   FXString* filename=NULL;
512   SciDoc*sci=FocusedDoc();
513   if (!sci->GetReadOnly()) {
514     if (filedlgs->GetOpenFilenames(sci,filename,false)&&!filename->empty()) {
515       SciDocUtils::InsertFile(sci,*filename);
516       delete[] filename;
517     }
518   }
519   sci->setFocus();
520 }
521 
522 
ToggleRecorder()523 void TopWindowBase::ToggleRecorder()
524 {
525   if (recording) {
526     recording=NULL;
527   } else {
528     if (!recorder) {recorder=new MacroRecorder(); }
529     recorder->clear();
530     recording=ControlDoc();
531   }
532   ControlDoc()->EnableRecorder(recording);
533   statusbar->Recording(recording);
534   menubar->Recording(recording,recorder);
535   ControlDoc()->setFocus();
536 }
537 
538 
539 
IsMacroCancelled()540 bool TopWindowBase::IsMacroCancelled()
541 {
542   return cmdutils->IsMacroCancelled(command_timeout);
543 }
544 
545 
546 
547 class MyCmdIO: public CmdIO {
IsCancelled()548   virtual bool IsCancelled() { return ((TopWindowBase*)win)->IsMacroCancelled(); }
549 public:
MyCmdIO(FXMainWindow * window,const char * shellcmd="/bin/sh -c")550   MyCmdIO(FXMainWindow *window, const char*shellcmd="/bin/sh -c"):CmdIO(window,shellcmd){}
551 };
552 
553 
554 
FilterSelection(SciDoc * sci,const FXString & cmd,const FXString & input)555 bool TopWindowBase::FilterSelection(SciDoc *sci, const FXString &cmd, const FXString &input)
556 {
557   if (!cmdutils->IsCommandReady()) { return false; }
558   cmdutils->CommandBusy(true);
559   cmdutils->SetShellEnv(sci->Filename().text(),sci->GetLineNumber());
560   bool success=false;
561   if (!cmd.empty()) {
562     MyCmdIO cmdio(this, prefs->ShellCommand.text());
563     FXString output=FXString::null;
564     command_timeout=false;
565     getApp()->beginWaitCursor();
566     statusbar->Running(_("command"));
567     cmdutils->DisableUI(true);
568     success=cmdio.filter(cmdutils->FixUpCmdLineEnv(cmd).text(), input, output);
569     if (success) {
570       sci->sendString(SCI_REPLACESEL, 0, output.text());
571       sci->ScrollWrappedInsert();
572     }
573     cmdutils->DisableUI(false);
574     statusbar->Normal();
575     getApp()->endWaitCursor();
576   }
577   sci->setFocus();
578   need_status=1;
579   cmdutils->CommandBusy(false);
580   return success;
581 }
582 
583 
584 
RunCommand(SciDoc * sci,const FXString & cmd)585 bool TopWindowBase::RunCommand(SciDoc *sci, const FXString &cmd)
586 {
587   if (!cmdutils->IsCommandReady()) { return false; }
588   cmdutils->CommandBusy(true);
589   cmdutils->SetShellEnv(sci->Filename().text(),sci->GetLineNumber());
590   bool success=false;
591   if (!cmd.empty()) {
592     MyCmdIO cmdio(this, prefs->ShellCommand.text());
593     command_timeout=false;
594     outlist->clearItems(true);
595     update();
596     repaint();
597     if (!prefs->ShowOutputPane) { ShowOutputPane(true); }
598     statusbar->Running(_("command"));
599     success=cmdio.lines(cmdutils->FixUpCmdLineEnv(cmd).text(), outlist, outlist->ID_CMDIO, true);
600     statusbar->Normal();
601     if (success) {
602       outlist->appendItem(_("Command succeeded."));
603     } else {
604       if (command_timeout) {
605         outlist->appendItem(_("Command cancelled."));
606       } else {
607         outlist->appendItem(_("Command failed."));
608         outlist->SelectFirstError();
609       }
610     }
611   }
612   if (FocusedDoc() && (GetNetActiveWindow()==id())) { FocusedDoc()->setFocus(); }
613   need_status=1;
614   cmdutils->CommandBusy(false);
615   return success;
616 }
617 
618 
619 
RunMacro(const FXString & script,bool isfilename)620 bool TopWindowBase::RunMacro(const FXString &script, bool isfilename)
621 {
622   if (!cmdutils->IsCommandReady()) { return false; }
623   cmdutils->CommandBusy(true);
624   MacroRunner macros;
625   command_timeout=false;
626   statusbar->Running(_("macro"));
627   update();
628   statusbar->layout();
629   getApp()->runWhileEvents();
630   bool rv=isfilename?macros.DoFile(script):macros.DoString(script);
631   getApp()->runWhileEvents();
632   if (!destroying) {
633     tabbook->ForEachTab(TabCallbacks::ResetUndoLevelCB,NULL);
634     statusbar->Normal();
635     if (FocusedDoc() && (GetNetActiveWindow()==id())) { FocusedDoc()->setFocus(); }
636     need_status=1;
637   }
638   cmdutils->CommandBusy(false);
639   return rv;
640 }
641 
642 
643 
RunHookScript(const char * hookname)644 bool TopWindowBase::RunHookScript(const char*hookname)
645 {
646   static bool running_hook_script=false;
647   FXString hook;
648   if (running_hook_script) { return false; }
649   hook.format("%s%s%c%s%c%s.lua", ConfigDir().text(), "tools", PATHSEP, "hooks", PATHSEP, hookname);
650   if (FXStat::isFile(hook)) {
651    bool rv;
652    running_hook_script=true;
653    rv=RunMacro(hook, true);
654    running_hook_script=false;
655    return rv;
656   } else {
657     return true;
658   }
659 }
660 
661 
662 
FileSaved(SciDoc * saved)663 void TopWindowBase::FileSaved(SciDoc* saved)
664 {
665   SciDoc *active=ControlDoc();
666   FXStat st;
667   if ( FXStat::stat(save_hook,st) && (st.size()>0) && st.isFile() ) {
668     if (active!=saved) {
669       tabbook->ActivateTab((DocTab*)(saved->getParent()->getPrev()));
670     }
671     RunHookScript("saved");
672     if ( TabCallbacks::IsDocValid(active,tabbook) && (active!=saved) ) {
673       tabbook->ActivateTab((DocTab*)(active->getParent()->getPrev()));
674     }
675   }
676 }
677 
678 
679 
AskReload()680 void TopWindowBase::AskReload()
681 {
682   SciDoc*sci=ControlDoc();
683   if (sci->Filename().empty()) {
684     FXMessageBox::error(this,MBOX_OK,_("Unamed file"), _("File has no name, can't reload."));
685     return;
686   }
687   if (!sci->Dirty()) {
688     if ( FXMessageBox::question(this, MBOX_YES_NO, _("Reload file"),
689            _("Reload current document?") ) != MBOX_CLICKED_YES ) { return; }
690   }
691   filedlgs->AskReload(sci);
692 }
693 
694 
695 
AddFileToTagsMenu(const FXString & filename)696 void TopWindowBase::AddFileToTagsMenu(const FXString &filename)
697 {
698   menubar->AddFileToTagsList(filename);
699 }
700 
701 
702 
RemoveFileFromTagsMenu(const FXString & filename)703 bool TopWindowBase::RemoveFileFromTagsMenu(const FXString &filename)
704 {
705   return menubar->RemoveFileFromTagsList(filename);
706 }
707 
708 
709 
SetLanguage(FXMenuRadio * mnu)710 bool TopWindowBase::SetLanguage(FXMenuRadio *mnu)
711 {
712   if (mnu) {
713     LangStyle*ls=(LangStyle*) mnu->getUserData();
714     SciDoc*sci=ControlDoc();
715     sci->setLanguage(ls);
716     menubar->SetLanguageCheckmark(ls);
717     return true;
718   } else { return false; }
719 }
720 
721 
722 
SetLanguage(const FXString & name)723 bool TopWindowBase::SetLanguage(const FXString &name)
724 {
725   return SetLanguage(menubar->GetMenuForLanguage(name));
726 }
727 
728 
729 
AddOutput(const FXString & line)730 void TopWindowBase::AddOutput(const FXString&line)
731 {
732   outlist->appendItem(line.text());
733 }
734 
735 
736 
ClearOutput()737 void TopWindowBase::ClearOutput()
738 {
739   outlist->clearItems();
740 }
741 
742 
743 
TagFiles()744 FXMenuCaption*TopWindowBase::TagFiles() {
745   return (FXMenuCaption*)(menubar->TagsMenu()->getMenu()->getFirst());
746 }
747 
748 
749 
SetKillCommandAccelKey(FXHotKey acckey)750 void TopWindowBase::SetKillCommandAccelKey(FXHotKey acckey)
751 {
752   cmdutils->SetKillCommandAccelKey(acckey);
753 }
754 
755 
756 
SaveAll(bool break_on_fail)757 bool TopWindowBase::SaveAll(bool break_on_fail)
758 {
759   DocTab*curr=tabbook->ActiveTab();
760   FXWindow*tab,*page;
761   bool success=true;
762   for (tab=tabbook->getFirst(); tab && (page=tab->getNext()); tab=page->getNext()) {
763     SciDoc*sci=(SciDoc*)page->getFirst();
764     if (sci->Dirty()) {
765       if (sci->Filename().empty() ) {
766         tabbook->ActivateTab((DocTab*)tab);
767       }
768       if (!filedlgs->SaveFile(sci,sci->Filename())) {
769         if (break_on_fail) { return false; } else { success=false; }
770       }
771     }
772   }
773   if (curr!=tabbook->ActiveTab()) { tabbook->ActivateTab((curr)); }
774   return success;
775 }
776 
777 
778 
779 // Tell the window manager we want the focus back after dialogs close...
ClosedDialog()780 void TopWindowBase::ClosedDialog()
781 {
782   setFocus();
783   FocusedDoc()->setFocus();
784 }
785 
786 
787 
AvoidMultiLineCommand(TopWindowBase * w,const FXString & cmd)788 static bool AvoidMultiLineCommand(TopWindowBase*w, const FXString &cmd)
789 {
790   if (cmd.contains('\n')) {
791     FXMessageBox::error(w, MBOX_OK, _("Command Error"),
792       _("Multiline commands are not supported."));
793     return false;
794   } else {
795     return true;
796   }
797 }
798 
799 
800 
ShowFilterDialog(bool is_filter)801 void TopWindowBase::ShowFilterDialog(bool is_filter)
802 {
803   SciDoc *sci=FocusedDoc();
804   HistBox *dlg;
805   bool save_first;
806   if(is_filter) {
807     dlg=new HistBox(this, _("Filter selection"), _("Command:"), "Filters");
808     save_first=prefs->SaveBeforeFilterSel;
809   } else {
810     dlg=new HistBox(this, _("Insert output of command"), _("Command:"), "InsertOutput");
811     save_first=prefs->SaveBeforeInsCmd;
812   }
813   dlg->setNumColumns(48);
814   if ( dlg->execute(PLACEMENT_OWNER) ) {
815     FXString cmd=dlg->getText();
816     if (AvoidMultiLineCommand(this, cmd)) {
817       if ( (!save_first) || SaveAll(true) ) {
818         FXString input="";
819         if (is_filter) { sci->GetSelText(input); }
820         FilterSelection(sci, cmd, input);
821       }
822     }
823   }
824   delete dlg;
825   ClosedDialog();
826 }
827 
828 
829 
ShowCommandDialog()830 void TopWindowBase::ShowCommandDialog()
831 {
832   SciDoc *sci=FocusedDoc();
833   HistBox dlg(this, _("Run command"), _("Command:"), "Commands");
834   dlg.setNumColumns(48);
835   if ( dlg.execute(PLACEMENT_OWNER) ) {
836     FXString cmd=dlg.getText();
837     if (AvoidMultiLineCommand(this,cmd)) {
838       if ( (!prefs->SaveBeforeExecCmd) || SaveAll(true) ) {
839         ClosedDialog();
840         RunCommand(sci,cmd);
841       }
842     }
843   } else {
844     ClosedDialog();
845   }
846 }
847 
848 
849 
850 
SetBookmark()851 void TopWindowBase::SetBookmark()
852 {
853   SciDoc*sci=ControlDoc();
854   bookmarked_file=sci->Filename();
855   bookmarked_tab=tabbook->ActiveTab();
856   bookmarked_pos=sci->GetCaretPos();
857 }
858 
859 
SetReadOnly(SciDoc * sci,bool rdonly)860 bool TopWindowBase::SetReadOnly(SciDoc*sci, bool rdonly)
861 {
862   if (!sci) { return false; }
863   if (rdonly && sci->Dirty()) {
864     FXMessageBox::error(this, MBOX_OK, _("Unsaved changes"),
865       _("Cannot mark a modified document as read-only.\n"
866         "You should save or undo your changes first.")
867     );
868     return false;
869   }
870   SetTabLocked(sci,rdonly);
871   menubar->SetReadOnlyCheckmark(rdonly);
872   need_status=32;
873   return true;
874 }
875 
876 
EnableUserFilters(bool enabled)877 void TopWindowBase::EnableUserFilters(bool enabled)
878 {
879   toolbar->EnableFilterBtn(enabled);
880   menubar->EnableFilterMenu(enabled);
881   srchdlgs->setHaveSelection(enabled);
882 }
883 
884 
885 
RemoveTBarBtnData(void * p)886 void TopWindowBase::RemoveTBarBtnData(void*p)
887 {
888   toolbar->NullifyButtonData(p);
889 }
890 
891 
892 // Exposes "userland" search behavior to scripting engine.
FindText(const char * searchfor,FXuint searchmode,bool forward)893 void TopWindowBase::FindText(const char*searchfor, FXuint searchmode, bool forward)
894 {
895   srchdlgs->FindPhrase(searchfor,searchmode,forward);
896 }
897 
898 
899 
FindAndReplace(const char * searchfor,const char * replacewith,FXuint searchmode,bool forward)900 void TopWindowBase::FindAndReplace(const char*searchfor, const char*replacewith, FXuint searchmode, bool forward)
901 {
902   srchdlgs->FindAndReplace(searchfor, replacewith, searchmode, forward);
903 }
904 
905 
906 
ReplaceAllInSelection(const char * searchfor,const char * replacewith,FXuint searchmode)907 void TopWindowBase::ReplaceAllInSelection(const char*searchfor, const char*replacewith, FXuint searchmode)
908 {
909   srchdlgs->ReplaceAllInSelection(searchfor, replacewith, searchmode);
910 }
911 
912 
913 
ReplaceAllInDocument(const char * searchfor,const char * replacewith,FXuint searchmode)914 void TopWindowBase::ReplaceAllInDocument(const char*searchfor, const char*replacewith, FXuint searchmode)
915 {
916   srchdlgs->ReplaceAllInDocument(searchfor, replacewith, searchmode);
917 }
918 
919 
920 
UserMenus() const921 UserMenu**TopWindowBase::UserMenus() const
922 {
923   return menubar->UserMenus();
924 }
925 
926 
927 
AdjustIndent(SciDoc * sci,char ch)928 void TopWindowBase::AdjustIndent(SciDoc*sci, char ch)
929 {
930   SciDocUtils::AdjustIndent(sci, ch, (Settings*)prefs, recording);
931 }
932 
933 
934 
OpenSelected()935 void TopWindowBase::OpenSelected()
936 {
937   SciDocUtils::OpenSelected(this, FocusedDoc());
938 }
939 
940 
941 
942 // Create a new tab and editor panel
OpenFile(const char * filename,const char * rowcol,bool readonly,bool hooked)943 bool TopWindowBase::OpenFile(const char*filename, const char*rowcol, bool readonly, bool hooked)
944 {
945   if (Closing()) return false;
946   FXString fn="";
947   SciDoc*sci=NULL;
948   if ( tabbook->Count() >= prefs->MaxFiles ) { return false; }
949   if (filename) {
950     fn=FXPath::simplify(FXPath::absolute(filename));
951 #ifdef WIN32
952      FileDialogs::ReadShortcut(this,fn);
953 #endif
954     if (IsFileOpen(fn,true)) {
955       if (rowcol && *rowcol) { ControlDoc()->GoToStringCoords(rowcol); }
956       if (hooked) { RunHookScript("opened"); }
957       return true;
958     }
959   }
960   if (!FileDialogs::FileExistsOrConfirmCreate(this,fn)) { return false; }
961   DocTab*tab=tabbook->NewTab(fn.empty()?_("Untitled"):FXPath::name(fn));
962   sci=SciDocUtils::NewSci((FXComposite*)tab->getNext(),this,(Settings*)prefs);
963   if (!fn.empty()) {
964     if (!sci->LoadFromFile(fn.text())) {
965       if (!sci->GetLastError().contains(SciDoc::BinaryFileMessage())) {
966          FXMessageBox::error(this, MBOX_OK, _("Error opening file"), "%s:\n%s\n%s",
967              _("Could not open file"),  fn.text(),  sci->GetLastError().text());
968       }
969       SciDocUtils::DoneSci(sci,recording);
970       return false;
971     }
972     if (!sci->SetLanguageForHeader(fn)) {
973       if (!sci->setLanguageFromFileName(FXPath::name(fn).text())) {
974         sci->setLanguageFromContent();
975       }
976     }
977   } else {
978     sci->SetUTF8(!prefs->DefaultToAscii);
979     sci->UpdateStyle();
980   }
981   SetTabLocked(sci,readonly);
982   tabbook->ActivateTab(tabbook->Count()-1);
983   menubar->AppendDocList(sci->Filename(), tab);
984   if (shown()) {
985     sci->create();
986     if (rowcol && *rowcol) { sci->GoToStringCoords(rowcol); }
987   }
988 
989   //  If the only thing we had open prior to this file was a single,
990   //  empty, untitled, unmodified document, then close it...
991   if ((tabbook->Count()==2) && (!sci->Filename().empty())) {
992     SciDoc*sc0=(SciDoc*)(tabbook->PageAt(0)->getFirst());
993     if ( sc0->Filename().empty() && (sc0->GetTextLength()==0) && (sc0->Dirty()==false)  ) {
994       tabbook->ActivateTab(0);
995       CloseFile(false,false);
996     }
997   }
998   sci->setFocus();
999   sci->NeedStyled(true);
1000   getApp()->addChore(this, ID_CHECK_STYLE, sci);
1001   if (hooked) { RunHookScript("opened"); }
1002   return true;
1003 }
1004 
1005 
1006 
NewFile(bool hooked)1007 bool TopWindowBase::NewFile(bool hooked)
1008 {
1009   return OpenFile(NULL,NULL,false,hooked);
1010 }
1011 
1012 
1013 
CloseFile(bool close_last,bool hooked)1014 bool TopWindowBase::CloseFile(bool close_last, bool hooked)
1015 {
1016   FXint i=tabbook->getCurrent();
1017   DocTab*tab=tabbook->ActiveTab();
1018   SciDoc*sci=ControlDoc();
1019   if (!filedlgs->TryClose(sci,tab->getText().text())) { return false; }
1020   menubar->PrependRecentFile(sci->Filename());
1021   if (hooked) { RunHookScript("closing"); }
1022   if (close_last) {
1023     if (!sci->Filename().empty()) {
1024       FXString line;
1025       line.format("-%c\n+%ld,%ld\n%s\n", sci->GetReadOnly()?'r':'w',
1026         sci->GetLineNumber()+1, sci->GetColumnNumber(), sci->Filename().text());
1027       session_data.append(line);
1028     }
1029   }
1030   backups->RemoveBackup(sci);
1031   if (tabbook->numChildren()==2) {
1032     if (!close_last) { NewFile(false); }
1033     SciDocUtils::DoneSci(sci,recording);
1034   } else {
1035     SciDocUtils::DoneSci(sci,recording);
1036     tabbook->ActivateTab( tabbook->childAtIndex(i*2) ? i : i-1 );
1037   }
1038   need_status=1;
1039   return true;
1040 }
1041 
1042 
1043 
CloseAll(bool close_last)1044 bool TopWindowBase::CloseAll(bool close_last)
1045 {
1046   bool rv;
1047   do {
1048     tabbook->ActivateTab(0);
1049   } while ((tabbook->numChildren()>0) && CloseFile(true,true));
1050   rv=tabbook->numChildren()==0;
1051   if (!close_last) { NewFile(false); }
1052   return rv;
1053 }
1054 
1055 
1056 
ChangeCase(bool to_upper)1057 void TopWindowBase::ChangeCase(bool to_upper)
1058 {
1059   SciDoc*sci=FocusedDoc();
1060   if (sci->GetSelLength()==0) { return; }
1061   if (to_upper) { sci->SelectionToUpper(); } else { sci->SelectionToLower(); }
1062   if (recording==sci) { recorder->record(to_upper?SCI_UPPERCASE:SCI_LOWERCASE,0,0); }
1063 }
1064 
1065 
1066 
FindTag()1067 void TopWindowBase::FindTag()
1068 {
1069   FXString filename;
1070   FXString locn;
1071   FXString pattern;
1072   if ( !TagHandler::FindTag(FocusedDoc(), TagFiles(), filename, locn, pattern) ) { return; }
1073   if ( filename.empty()) { return; }
1074   if (OpenFile(filename.text(), locn.text(),false,true)) {
1075     if (locn.empty()) { TagHandler::GoToTag(ControlDoc(),pattern); }
1076   }
1077 }
1078 
1079 
1080 
GoToBookmark()1081 void TopWindowBase::GoToBookmark()
1082 {
1083   if (!bookmarked_file.empty()) {
1084     if (OpenFile(bookmarked_file.text(),NULL,false,false)) {
1085       FocusedDoc()->GoToPos(bookmarked_pos);
1086     }
1087   } else {
1088     tabbook->ForEachTab(TabCallbacks::BookmarkCB,this);
1089   }
1090 }
1091 
1092 
1093 
FoundBookmarkedTab(DocTab * tab)1094 bool TopWindowBase::FoundBookmarkedTab(DocTab*tab)
1095 {
1096   if (bookmarked_tab == tab) {
1097     tabbook->ActivateTab(tab);
1098     FocusedDoc()->GoToPos(bookmarked_pos);
1099     return true;
1100   }
1101   return false;
1102 }
1103 
1104 
1105 
UpdateToolbar()1106 void TopWindowBase::UpdateToolbar()
1107 {
1108   toolbar->CreateButtons((TopWindow*)this);
1109   menubar->UpdateDocTabSettings();
1110   menubar->Recording(recording,recorder);
1111   toolbar->EnableFilterBtn(FocusedDoc()&&(FocusedDoc()->GetSelLength()>0));
1112 }
1113 
1114 
1115 
ShowPrefsDialog()1116 void TopWindowBase::ShowPrefsDialog()
1117 {
1118   PrefsDialog*prefdlg=new PrefsDialog(this, (Settings*)prefs);
1119   prefdlg->execute(PLACEMENT_DEFAULT);
1120   delete prefdlg;
1121   ClosedDialog();
1122   srchdlgs->SetPrefs(prefs->SearchOptions,prefs->SearchWrap,prefs->SearchVerbose,prefs->SearchGui);
1123   tabbook->MaxTabWidth(prefs->TabTitleMaxWidth);
1124   tabbook->ForEachTab(TabCallbacks::PrefsCB, NULL);
1125   CheckStyle(NULL,0,ControlDoc());
1126   if ((prefs->WatchExternChanges||prefs->Autosave) && !getApp()->hasTimeout(this,ID_TIMER)) {
1127     getApp()->addTimeout(this,ID_TIMER, ONE_SECOND, NULL);
1128   }
1129   getApp()->setWheelLines(prefs->WheelLines);
1130   if ( PrefsDialog::ChangedToolbar() & ToolbarChangedLayout ) {
1131     UpdateToolbar();
1132   }
1133   if ( PrefsDialog::ChangedToolbar() & ToolbarChangedWrap ) {
1134     toolbar->handle(toolbar,FXSEL(SEL_CONFIGURE,0),NULL);
1135   }
1136   if ( PrefsDialog::ChangedToolbar() & ToolbarChangedFont ) {
1137     toolbar->SetTBarFont();
1138   }
1139   if (Theme::changed() & ThemeChangedColors) {
1140     Theme::apply(this);
1141     Theme::apply(srchdlgs->FindDialog());
1142     tips->setBackColor(getApp()->getTipbackColor());
1143     tips->setTextColor(getApp()->getTipforeColor());
1144     statusbar->Colorize();
1145   }
1146   tabbook->ActivateTab(tabbook->ActiveTab());
1147   toolbar->SetToolbarColors();
1148   EnableUserFilters(FocusedDoc()->GetSelLength());
1149 }
1150 
1151 
1152 
1153 
ShowToolManagerDialog()1154 void TopWindowBase::ShowToolManagerDialog()
1155 {
1156   ToolsDialog tooldlg(this,UserMenus());
1157   tooldlg.execute(PLACEMENT_SCREEN);
1158   RescanUserMenu();
1159   ClosedDialog();
1160 }
1161 
1162 
1163 
RescanUserMenu()1164 void TopWindowBase::RescanUserMenu()
1165 {
1166   menubar->RescanUserMenus();
1167   MenuMgr::PurgeTBarCmds();
1168   UpdateToolbar();
1169 }
1170 
1171 
1172 
ParseCommands(FXString & commands)1173 void TopWindowBase::ParseCommands(FXString &commands)
1174 {
1175   FXString sect="";
1176   FXString rowcol="";
1177   FXRex rx_rowcol(":\\d+$",REX_CAPTURE);
1178   FXchar rw='w';
1179   bool tagopt=false;
1180   bool macopt=false;
1181   bool session_restored=false;
1182   bool quiet=((compare(commands,"-q\n",2)==0) || (commands.contains("\n-q\n")));
1183   int i=0;
1184   while (1) {
1185     sect=commands.section('\n',i++);
1186     if (sect.empty()) { break; }
1187     switch (sect.text()[0]) {
1188       case '+': {
1189         rowcol=sect.text();
1190         break;
1191       }
1192       case '-': {
1193         switch (sect.text()[1]) {
1194           case 'r':
1195           case 'w': {
1196             rw=sect.text()[1];
1197             break;
1198           }
1199           case 't': {
1200             tagopt=true;
1201             break;
1202           }
1203           case 'e': {
1204             macopt=true;
1205             break;
1206           }
1207           case 'p' : {
1208             if (!session_restored) {
1209               session_restored=true;
1210               FXString sessionname;
1211               FXFile fh(SessionFile(), FXIO::Reading);
1212               if (fh.isOpen()) {
1213                 session_data.length(fh.size());
1214                 fh.readBlock((void*)(session_data.text()),fh.size());
1215                 fh.close();
1216                 ParseCommands(session_data);
1217                 if (!prefs->LastFocused.empty()) {
1218                   if (FXStat::isFile(prefs->LastFocused)) {
1219                     IsFileOpen(prefs->LastFocused,true);
1220                   }
1221                 }
1222               }
1223             }
1224             break;
1225           }
1226           case 'q' : {
1227             break; // "quiet" option is invalid for a new instance, so just ignore it.
1228           }
1229           default: fprintf(stderr, _("Warning: unrecognized option: %s\n"), sect.text());
1230         }
1231         break;
1232       }
1233       default: {
1234         if (tagopt) {
1235           AddFileToTagsMenu(sect);
1236           tagopt=false;
1237         } else {
1238           if (macopt) {
1239             macopt=false;
1240             if (tabbook->numChildren()==0) { /* Be sure we have a document before running a macro */
1241               NewFile(false);
1242               RunMacro(sect,false);
1243               if (tabbook->numChildren()==2) {
1244                 SciDoc*sci=ControlDoc();
1245                 if ( (sci->Filename().empty()) && (sci->GetTextLength()==0) && (!sci->Dirty()) ) {
1246                   CloseFile(true,false); /* Forget this document if it wasn't changed */
1247                 }
1248               }
1249             } else {
1250               RunMacro(sect,false);
1251             }
1252           } else {
1253             FXString filename=sect.text();
1254             if (rowcol.empty()) {
1255               FXint beg,end;
1256 #ifdef FOX_1_7_50_OR_NEWER
1257               if (rx_rowcol.search(filename,0,filename.length(),Normal,&beg,&end,1)>=0)
1258 #else
1259               if (rx_rowcol.match(filename,&beg,&end))
1260 #endif
1261               {
1262                 if (!FXStat::isFile(filename)) {
1263                   rowcol=filename.mid(beg,end-beg).text();
1264                   filename=filename.left(beg).text();
1265                   if (!FXStat::isFile(filename)) {
1266                     rowcol="";
1267                     filename=sect.text();
1268                   }
1269                 }
1270               }
1271             }
1272             OpenFile(filename.text(), rowcol.empty()?NULL:(rowcol.text())+1, rw=='r',true);
1273             rowcol="";
1274           }
1275         }
1276       }
1277     }
1278   }
1279   commands=FXString::null;
1280   if (tabbook->numChildren()==0) { NewFile(false); }
1281   if (!quiet) { WaitForWindowFocus(this); }
1282 }
1283 
1284 
1285 
UpdateTitle(long line,long col)1286 void TopWindowBase::UpdateTitle(long line, long col)
1287 {
1288   SciDoc*sci=ControlDoc();
1289   if (sci) {
1290     DocTab *tab=tabbook->ActiveTab();
1291     FXString s;
1292     s.format("%s%s  %s - %s", sci->Dirty()?"*":"", tab->getText().text(), FXPath::directory(sci->Filename()).text(), EXE_NAME);
1293     setTitle(s);
1294     menubar->SetLanguageCheckmark(sci->getLanguage());
1295     menubar->SetReadOnlyCheckmark(sci->sendMessage(SCI_GETREADONLY,0,0));
1296     menubar->SetWordWrapCheckmark(sci->GetWordWrap());
1297     statusbar->FileInfo(sci->Filename(),sci->GetEncoding(),line,col);
1298     MenuMgr::UpdateEolMenu(sci);
1299   } else {
1300     setTitle(EXE_NAME);
1301     statusbar->Clear();
1302   }
1303 }
1304 
1305 
1306 
ShowLineNumbers(bool showit)1307 void TopWindowBase::ShowLineNumbers(bool showit)
1308 {
1309   prefs->ShowLineNumbers=showit;
1310   tabbook->ForEachTab(TabCallbacks::LineNumsCB, (void*)(FXival)showit);
1311   menubar->SyncPrefsCheckmarks();
1312 }
1313 
1314 
1315 
ShowStatusBar(bool showit)1316 void TopWindowBase::ShowStatusBar(bool showit)
1317 {
1318   prefs->ShowStatusBar=showit;
1319   statusbar->Show(showit);
1320   menubar->SyncPrefsCheckmarks();
1321 }
1322 
1323 
1324 
ShowOutputPane(bool showit)1325 void TopWindowBase::ShowOutputPane(bool showit)
1326 {
1327   prefs->ShowOutputPane=showit;
1328   if (showit) {
1329     if (prefs->OutputPaneHeight<16) { prefs->OutputPaneHeight=16; }
1330     hsplit->setSplit(1, prefs->OutputPaneHeight);
1331     outlist->show();
1332   } else {
1333     outlist->hide();
1334     hsplit->setSplit(1,0);
1335   }
1336   menubar->SyncPrefsCheckmarks();
1337 }
1338 
1339 
1340 
ShowWhiteSpace(bool showit)1341 void TopWindowBase::ShowWhiteSpace(bool showit)
1342 {
1343   prefs->ShowWhiteSpace=showit;
1344   tabbook->ForEachTab(TabCallbacks::WhiteSpaceCB, (void*)(FXival)showit);
1345   menubar->SyncPrefsCheckmarks();
1346 }
1347 
1348 
1349 
ShowToolbar(bool showit)1350 void TopWindowBase::ShowToolbar(bool showit)
1351 {
1352   prefs->ShowToolbar=showit;
1353   if (showit) { toolbar->show(); } else { toolbar->hide(); }
1354   menubar->SyncPrefsCheckmarks();
1355 }
1356 
1357 
1358 
ShowMargin(bool showit)1359 void TopWindowBase::ShowMargin(bool showit)
1360 {
1361   prefs->ShowRightEdge = showit;
1362   tabbook->ForEachTab(TabCallbacks::ShowMarginCB, (void*)(FXival)showit);
1363   menubar->SyncPrefsCheckmarks();
1364 }
1365 
1366 
1367 
ShowIndent(bool showit)1368 void TopWindowBase::ShowIndent(bool showit)
1369 {
1370   prefs->ShowIndentGuides = showit;
1371   tabbook->ForEachTab(TabCallbacks::ShowIndentCB, (void*)(FXival)showit);
1372   menubar->SyncPrefsCheckmarks();
1373 }
1374 
1375 
1376 
ShowCaretLine(bool showit)1377 void TopWindowBase::ShowCaretLine(bool showit)
1378 {
1379   prefs->ShowCaretLine = showit;
1380   tabbook->ForEachTab(TabCallbacks::ShowCaretLineCB, (void*)prefs);
1381   menubar->SyncPrefsCheckmarks();
1382 }
1383 
1384 
1385 
SetWordWrap(SciDoc * sci,bool wrapped)1386 void TopWindowBase::SetWordWrap(SciDoc*sci, bool wrapped)
1387 {
1388   sci->SetWordWrap(wrapped);
1389   menubar->SetWordWrapCheckmark(wrapped);
1390 }
1391 
1392 
1393 
InvertColors(bool inverted)1394 void TopWindowBase::InvertColors(bool inverted)
1395 {
1396   prefs->InvertColors=inverted;
1397   toolbar->SetToolbarColors();
1398   tabbook->ForEachTab(TabCallbacks::PrefsCB,NULL);
1399   CheckStyle(NULL,0,ControlDoc());
1400   menubar->SyncPrefsCheckmarks();
1401 }
1402 
1403 
1404 
1405 // Returns: 0=File not open; 1=File open and clean; 2=File open and dirty;
IsFileOpen(const FXString & filename,bool activate)1406 int TopWindowBase::IsFileOpen(const FXString &filename, bool activate)
1407 {
1408   void*userdata[3]={(void*)&filename,&activate,NULL};
1409   tabbook->ForEachTab(TabCallbacks::FileAlreadyOpenCB,userdata);
1410   SciDoc*sci=(SciDoc*)userdata[2];
1411   return sci?sci->Dirty()?2:1:0;
1412 }
1413 
1414 
1415 
1416 // Caller should delete[] result when done!
NamedFiles() const1417 FXString* TopWindowBase::NamedFiles() const
1418 {
1419   FXint n=tabbook->Count();
1420   FXString *list=new FXString[n+1];
1421   for (FXint i=0; i<=n; i++) { list[i]=FXString::null; }
1422   tabbook->ForEachTab(TabCallbacks::NamedFilesCB,list);
1423   return list;
1424 }
1425 
1426 
1427 
1428