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 <SciLexer.h>
22 
23 #include "prefs_base.h"
24 #include "shmenu.h"
25 #include "lang.h"
26 #include "menuspec.h"
27 #include "appwin.h"
28 
29 #include "intl.h"
30 #include "mainmenu.h"
31 
32 #define TEST_SOMETHING 0
33 
34 #define TW TopWindow
35 
36 // Create a new menu command, menu check box, or menu radio item...
37 #define MkMnuCmd(p,s) MenuMgr::MakeMenuCommand(p,tw,TW::s,'m')
38 #define MkMnuChk(p,s,c) ((FXMenuCheck*)MenuMgr::MakeMenuCommand(p,tw,TW::s,'k',c))
39 #define MkMnuRad(p,s) ((FXMenuRadio*)MenuMgr::MakeMenuCommand(p,tw,TW::s,'r'))
40 
41 
42 
43 static const char*usercmdflags[]={
44   "save", _("Save open files first."),
45   NULL
46 };
47 
48 
49 static const char*usersnipflags[]={
50   "read", _("Insert file's contents."),
51   "exec", _("Insert command output."),
52   NULL
53 };
54 
55 
MainMenu(FXComposite * p)56 MainMenu::MainMenu(FXComposite* p):FXMenuBar(p,LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
57 {
58   tw=(TopWindow*)p;
59   prefs=SettingsBase::instance();
60   CreateMenus();
61   new FXHorizontalSeparator(p,LAYOUT_SIDE_TOP|LAYOUT_FILL_X|SEPARATOR_GROOVE);
62 }
63 
64 
65 /*
66   Fox menus don't re-focus the previously active widget after they are dismissed.
67   This sub-class helps to work around that.
68 */
69 class MyMenuPane: public FXMenuPane {
70   FXDECLARE(MyMenuPane)
MyMenuPane()71   MyMenuPane(){}
72 public:
MyMenuPane(FXComposite * o)73   MyMenuPane(FXComposite*o):FXMenuPane(o) {}
onCmdUnpost(FXObject * o,FXSelector sel,void * p)74   long onCmdUnpost(FXObject*o, FXSelector sel, void*p ){
75     long rv=FXMenuPane::onCmdUnpost(o,sel,p);
76     getApp()->addChore(TopWindow::instance(),TopWindow::ID_FOCUS_DOC,NULL);
77     return rv;
78   }
79 };
80 
81 
82 
83 FXDEFMAP(MyMenuPane) MyMenuPaneMap[] = {
84   FXMAPFUNC(SEL_COMMAND,FXWindow::ID_UNPOST,MyMenuPane::onCmdUnpost),
85 };
86 
FXIMPLEMENT(MyMenuPane,FXMenuPane,MyMenuPaneMap,ARRAYNUMBER (MyMenuPaneMap))87 FXIMPLEMENT(MyMenuPane,FXMenuPane,MyMenuPaneMap,ARRAYNUMBER(MyMenuPaneMap))
88 
89 
90 void MainMenu::CreateLanguageMenu()
91 {
92   langmenu=new MyMenuPane(tw);
93   langcasc=new FXMenuCascade(viewmenu,_("&Language"),NULL,langmenu);
94   FXMenuRadio*mr;
95 
96   cpp_langmenu=new MyMenuPane(langmenu);
97   cpp_langcasc=new FXMenuCascade(langmenu,_("C/C++"),NULL,cpp_langmenu);
98 
99   scr_langmenu=new MyMenuPane(langmenu);
100   scr_langcasc=new FXMenuCascade(langmenu,_("Scripting"),NULL,scr_langmenu);
101 
102   cfg_langmenu=new MyMenuPane(langmenu);
103   cfg_langcasc=new FXMenuCascade(langmenu,_("Config"),NULL,cfg_langmenu);
104 
105   html_langmenu=new MyMenuPane(langmenu);
106   html_langcasc=new FXMenuCascade(langmenu,_("Web"),NULL,html_langmenu);
107 
108   inf_langmenu=new MyMenuPane(langmenu);
109   inf_langcasc=new FXMenuCascade(langmenu,_("Info"),NULL,inf_langmenu);
110 
111   lgcy_langmenu=new MyMenuPane(langmenu);
112   lgcy_langcasc=new FXMenuCascade(langmenu,_("Legacy"),NULL,lgcy_langmenu);
113 
114   tex_langmenu=new MyMenuPane(langmenu);
115   tex_langcasc=new FXMenuCascade(langmenu,_("Typeset"),NULL,tex_langmenu);
116 
117   db_langmenu=new MyMenuPane(langmenu);
118   db_langcasc=new FXMenuCascade(langmenu,_("Database"),NULL,db_langmenu);
119 
120   asm_langmenu=new MyMenuPane(langmenu);
121   asm_langcasc=new FXMenuCascade(langmenu,_("Asm/HDL"),NULL,asm_langmenu);
122 
123   misc_langmenu=new MyMenuPane(langmenu);
124   misc_langcasc=new FXMenuCascade(langmenu,_("Other"),NULL,misc_langmenu);
125 
126   mr=new FXMenuRadio(misc_langmenu,_("none"),tw,TW::ID_SET_LANGUAGE);
127   mr->setUserData(NULL);
128 
129   for (LangStyle*ls=languages; ls->name; ls++) {
130     FXMenuPane*mp;
131     switch (ls->id) {
132     case SCLEX_COBOL:
133     case SCLEX_F77:
134     case SCLEX_FORTRAN:
135     case SCLEX_FREEBASIC:
136     case SCLEX_PASCAL:
137     case SCLEX_SMALLTALK:
138     case SCLEX_ERLANG:
139     case SCLEX_LISP:
140     case SCLEX_HASKELL:
141     case SCLEX_MODULA:
142     case SCLEX_ADA: {
143       mp=lgcy_langmenu;
144       break;
145     }
146     case SCLEX_CSS:
147     case SCLEX_HTML:
148     case SCLEX_MARKDOWN:
149     case SCLEX_TXT2TAGS: {
150       mp=(compare(ls->name,"docbook")==0)?tex_langmenu:html_langmenu;
151       break;
152     }
153     case SCLEX_CPP: {
154       mp=(compare(ls->name,"javascript")==0)?html_langmenu:cpp_langmenu;
155       break;
156     }
157     case SCLEX_BASH:
158     case SCLEX_BATCH:
159     case SCLEX_LUA:
160     case SCLEX_PERL:
161     case SCLEX_PYTHON:
162     case SCLEX_RUBY:
163     case SCLEX_R:
164     case SCLEX_TCL: {
165       mp=scr_langmenu;
166       break;
167     }
168     case SCLEX_FLAGSHIP:
169     case SCLEX_SQL: {
170       mp=db_langmenu;
171       break;
172     }
173     case SCLEX_DIFF:
174     case SCLEX_ERRORLIST: {
175       mp=inf_langmenu;
176       break;
177     }
178     case SCLEX_CONF:
179     case SCLEX_CMAKE:
180     case SCLEX_MAKEFILE:
181     case SCLEX_PO:
182     case SCLEX_PROPERTIES:
183     case SCLEX_XML: {
184       mp=cfg_langmenu;
185       break;
186     }
187     case SCLEX_ASM:
188     case SCLEX_VHDL:
189     case SCLEX_VERILOG:
190     case SCLEX_A68K: {
191       mp=asm_langmenu;
192       break;
193     }
194     case SCLEX_LATEX:
195     case SCLEX_TEX:
196     case SCLEX_METAPOST:
197     case SCLEX_PS: {
198       mp=tex_langmenu;
199       break;
200     }
201     default: { mp=misc_langmenu; }
202     }
203     mr=new FXMenuRadio(mp,ls->name,tw,TW::ID_SET_LANGUAGE);
204     mr->setUserData((void*)ls);
205   }
206 }
207 
208 
209 
NewTitle(FXComposite * p,const FXString & text,FXIcon * ic=NULL,FXPopup * pup=NULL,FXuint opts=0)210 static FXMenuTitle*NewTitle(FXComposite*p, const FXString&text, FXIcon*ic=NULL, FXPopup*pup=NULL, FXuint opts=0)
211 {
212   FXMenuTitle*rv=new FXMenuTitle(p, text, ic, pup, opts);
213   if (pup) { pup->setUserData((void*)rv); }
214   return rv;
215 }
216 
217 
218 
NewCascade(FXComposite * p,const FXString & text,FXIcon * ic=NULL,FXPopup * pup=NULL,FXuint opts=0)219 static FXMenuCascade*NewCascade(FXComposite*p, const FXString&text, FXIcon*ic=NULL, FXPopup*pup=NULL, FXuint opts=0)
220 {
221   FXMenuCascade*rv=new FXMenuCascade(p, text, ic, pup, opts);
222   if (pup) { pup->setUserData((void*)rv); }
223   return rv;
224 }
225 
226 
227 
CreateTabsMenu()228 void MainMenu::CreateTabsMenu()
229 {
230   tabmenu=new MyMenuPane(tw);
231   NewCascade(viewmenu,_("&Tabs"),NULL,tabmenu);
232 
233   tabsidemenu=new MyMenuPane(tw);
234   NewCascade(tabmenu,_("&Position"),NULL,tabsidemenu);
235 
236   FXMenuRadio*tT=MkMnuRad(tabsidemenu,ID_TABS_TOP);
237   FXMenuRadio*tB=MkMnuRad(tabsidemenu,ID_TABS_BOTTOM);
238   FXMenuRadio*tL=MkMnuRad(tabsidemenu,ID_TABS_LEFT);
239   FXMenuRadio*tR=MkMnuRad(tabsidemenu,ID_TABS_RIGHT);
240 
241   switch (prefs->DocTabPosition) {
242     case 'B': { tB->setCheck(); break; }
243     case 'L': { tL->setCheck(); break; }
244     case 'R': { tR->setCheck(); break; }
245     default:  { tT->setCheck(); break; }
246   }
247 
248   tabwidthmenu=new MyMenuPane(tw);
249   NewCascade(tabmenu,_("&Width"),NULL,tabwidthmenu);
250 
251   FXMenuRadio*tU=MkMnuRad(tabwidthmenu,ID_TABS_UNIFORM);
252   FXMenuRadio*tP=MkMnuRad(tabwidthmenu,ID_TABS_COMPACT);
253   FXMenuRadio*tA=MkMnuRad(tabwidthmenu,ID_TABS_BY_POS);
254   switch (prefs->DocTabsPacked) {
255     case 'U': { tU->setCheck(); break; }
256     case 'P': { tP->setCheck(); break; }
257     case 'A': { tA->setCheck(); break; }
258   }
259 }
260 
261 
262 
CreateZoomMenu()263 void MainMenu::CreateZoomMenu()
264 {
265   viewzoommenu=new MyMenuPane(tw);
266   NewCascade(viewmenu,_("&Zoom"),NULL,viewzoommenu);
267   MkMnuCmd(viewzoommenu,ID_ZOOM_IN);
268   MkMnuCmd(viewzoommenu,ID_ZOOM_OUT);
269   MkMnuCmd(viewzoommenu,ID_ZOOM_NONE);
270   MkMnuCmd(viewzoommenu,ID_ZOOM_NEAR);
271   MkMnuCmd(viewzoommenu,ID_ZOOM_FAR);
272 }
273 
274 
275 
CreateMenus()276 void MainMenu::CreateMenus()
277 {
278   filemenu=new MyMenuPane(tw);
279   NewTitle(this,_("&File"),NULL,filemenu);
280   MkMnuCmd(filemenu,ID_NEW);
281   MkMnuCmd(filemenu,ID_OPEN_FILES);
282   openselmenu=MkMnuCmd(filemenu,ID_OPEN_SELECTED);
283   recent_files=new HistMenu(filemenu, _("Open pre&vious"), "RecentFiles", tw, TW::ID_OPEN_PREVIOUS);
284 
285   new FXMenuSeparator(filemenu, 0);
286   MkMnuCmd(filemenu,ID_SAVE);
287   MkMnuCmd(filemenu,ID_SAVEAS);
288   MkMnuCmd(filemenu,ID_SAVEALL);
289   MkMnuCmd(filemenu,ID_SAVECOPY);
290 
291   new FXMenuSeparator(filemenu, 0);
292   MkMnuCmd(filemenu,ID_RELOAD);
293 
294   fileexportmenu=new MyMenuPane(tw);
295   NewCascade(filemenu,_("E&xport"),NULL,fileexportmenu);
296   MkMnuCmd(fileexportmenu,ID_EXPORT_PDF);
297   MkMnuCmd(fileexportmenu,ID_EXPORT_HTML);
298 
299   new FXMenuSeparator(filemenu, 0);
300   MkMnuCmd(filemenu,ID_CLOSE);
301   MkMnuCmd(filemenu,ID_CLOSEALL);
302   new FXMenuSeparator(filemenu, 0);
303   MkMnuCmd(filemenu,ID_INSERT_FILE);
304   MkMnuCmd(filemenu,ID_LOAD_TAGS);
305   unloadtagsmenu=new FXMenuCascade(filemenu,_("&Unload tags file"),NULL,(new MyMenuPane(filemenu)));
306   unloadtagsmenu->disable();
307   MkMnuCmd(filemenu,ID_SELECT_DIR);
308   new FXMenuSeparator(filemenu, 0);
309   MkMnuCmd(filemenu,ID_QUIT);
310 
311   editmenu=new MyMenuPane(tw);
312   NewTitle(this,_("&Edit"),NULL,editmenu);
313 
314   MkMnuCmd(editmenu,ID_UNDO);
315   MkMnuCmd(editmenu,ID_REDO);
316   new FXMenuSeparator(editmenu, 0);
317   MkMnuCmd(editmenu,ID_CUT);
318   MkMnuCmd(editmenu,ID_COPY);
319   MkMnuCmd(editmenu,ID_PASTE);
320 
321   editdeletemenu=new MyMenuPane(tw);
322   NewCascade(editmenu,_("&Delete"),NULL,editdeletemenu);
323 
324   MkMnuCmd(editdeletemenu,ID_DEL_WORD_LEFT);
325   MkMnuCmd(editdeletemenu,ID_DEL_WORD_RIGHT);
326   MkMnuCmd(editdeletemenu,ID_DEL_LINE_LEFT);
327   MkMnuCmd(editdeletemenu,ID_DEL_LINE_RIGHT);
328 
329   new FXMenuSeparator(editmenu, 0);
330   MkMnuCmd(editmenu,ID_TOLOWER);
331   MkMnuCmd(editmenu,ID_TOUPPER);
332 
333   editindentmenu=new MyMenuPane(tw);
334   NewCascade(editmenu,_("&Indent"),NULL,editindentmenu);
335 
336   MkMnuCmd(editindentmenu,ID_INDENT_STEP);
337   MkMnuCmd(editindentmenu,ID_UNINDENT_STEP);
338   MkMnuCmd(editindentmenu,ID_INDENT_FULL);
339   MkMnuCmd(editindentmenu,ID_UNINDENT_FULL);
340 
341   new FXMenuSeparator(editmenu, 0);
342   readonly_chk=MkMnuChk(editmenu,ID_READONLY,false);
343   wordwrap_chk=MkMnuChk(editmenu,ID_WORDWRAP,false);
344 
345   fileformatmenu=new MyMenuPane(tw);
346   fileformatcasc=NewCascade(editmenu,_("File &Format"),NULL,fileformatmenu);
347 
348   fmt_dos_mnu=MkMnuRad(fileformatmenu,ID_FMT_DOS);
349   fmt_mac_mnu=MkMnuRad(fileformatmenu,ID_FMT_MAC);
350   fmt_unx_mnu=MkMnuRad(fileformatmenu,ID_FMT_UNIX);
351 
352   MkMnuCmd(editmenu,ID_PREFS_DIALOG);
353 
354   searchmenu=new MyMenuPane(tw);
355   NewTitle(this,_("&Search"),NULL,searchmenu);
356 
357   MkMnuCmd(searchmenu,ID_FIND);
358   MkMnuCmd(searchmenu,ID_FINDNEXT);
359   MkMnuCmd(searchmenu,ID_FINDPREV);
360 
361   searchselectmenu=new MyMenuPane(tw);
362   NewCascade(searchmenu,_("Find &Selected"),NULL,searchselectmenu);
363   MkMnuCmd(searchselectmenu,ID_NEXT_SELECTED);
364   MkMnuCmd(searchselectmenu,ID_PREV_SELECTED);
365   MkMnuCmd(searchmenu,ID_REPLACE_IN_DOC);
366 
367   new FXMenuSeparator(searchmenu, 0);
368   MkMnuCmd(searchmenu,ID_GOTO);
369   MkMnuCmd(searchmenu,ID_GOTO_SELECTED);
370   MkMnuCmd(searchmenu,ID_GOTO_ERROR);
371 
372   searchmarkmenu=new MyMenuPane(tw);
373   NewCascade(searchmenu,_("&Bookmark"),NULL,searchmarkmenu);
374   MkMnuCmd(searchmarkmenu,ID_BOOKMARK_SET);
375   MkMnuCmd(searchmarkmenu,ID_BOOKMARK_RETURN);
376 
377   new FXMenuSeparator(searchmenu, 0);
378 
379   findtagmenu=MkMnuCmd(searchmenu,ID_FIND_TAG);
380   findtagmenu->disable();
381   showtipmenu=MkMnuCmd(searchmenu,ID_SHOW_CALLTIP);
382   showtipmenu->disable();
383   autocompmenu=MkMnuCmd(searchmenu,ID_AUTO_COMPLETE);
384   autocompmenu->disable();
385 
386 
387   viewmenu=new MyMenuPane(tw);
388   NewTitle(this,_("&View"),NULL,viewmenu);
389 
390   CreateLanguageMenu();
391   CreateTabsMenu();
392   CreateZoomMenu();
393 
394   new FXMenuSeparator(viewmenu, 0);
395 
396   status_chk =   MkMnuChk(viewmenu, ID_SHOW_STATUSBAR,  prefs->ShowStatusBar);
397   outpane_chk =  MkMnuChk(viewmenu, ID_SHOW_OUTLIST,    prefs->ShowOutputPane);
398   linenums_chk = MkMnuChk(viewmenu, ID_SHOW_LINENUMS,   prefs->ShowLineNumbers);
399   toolbar_chk =  MkMnuChk(viewmenu, ID_SHOW_TOOLBAR,   prefs->ShowToolbar);
400 
401   new FXMenuSeparator(viewmenu, 0);
402 
403   margin_chk =   MkMnuChk(viewmenu, ID_SHOW_MARGIN,     prefs->ShowRightEdge);
404   guides_chk =   MkMnuChk(viewmenu, ID_SHOW_INDENT,     prefs->ShowIndentGuides);
405   white_chk =    MkMnuChk(viewmenu, ID_SHOW_WHITESPACE, prefs->ShowWhiteSpace);
406   invert_chk =   MkMnuChk(viewmenu, ID_INVERT_COLORS,   prefs->InvertColors);
407   caretline_chk = MkMnuChk(viewmenu, ID_SHOW_CARET_LINE, prefs->ShowCaretLine);
408 
409   new FXMenuSeparator(viewmenu, 0);
410 
411   MkMnuCmd(viewmenu,ID_CYCLE_SPLITTER);
412   MkMnuCmd(viewmenu,ID_CLEAR_OUTPUT);
413 
414   toolsmenu=new MyMenuPane(tw);
415   NewTitle(this,_("&Tools"),NULL,toolsmenu);
416 
417   filterselmenu=MkMnuCmd(toolsmenu,ID_FILTER_SEL);
418   MkMnuCmd(toolsmenu,ID_INSERT_CMD_OUT);
419   MkMnuCmd(toolsmenu,ID_RUN_COMMAND);
420 
421   recordermenu=new MyMenuPane(tw);
422   NewCascade(toolsmenu,_("Macro &recorder"),NULL,recordermenu);
423 
424   recorderstartmenu=MkMnuCmd(recordermenu,ID_MACRO_RECORD);
425   playbackmenu=MkMnuCmd(recordermenu,ID_MACRO_PLAYBACK);
426   playbackmenu->disable();
427   showmacromenu=MkMnuCmd(recordermenu,ID_MACRO_TRANSLATE);
428   showmacromenu->disable();
429   new FXMenuSeparator(toolsmenu, 0);
430 
431   MkMnuCmd(toolsmenu,ID_RESCAN_USER_MENU);
432   MkMnuCmd(toolsmenu,ID_CONFIGURE_TOOLS);
433   new FXMenuSeparator(toolsmenu, 0);
434 
435   FXString scriptdir;
436   scriptdir.format("%s%s", tw->ConfigDir().text(), "tools");
437   FXDir::create(scriptdir);
438 
439   scriptdir.format("%s%s%c%s", tw->ConfigDir().text(), "tools", PATHSEP, "commands");
440   FXDir::create(scriptdir);
441   usercmdmenu=new UserMenu(toolsmenu, _("&Commands"), scriptdir, 'C', tw, TW::ID_USER_COMMAND, usercmdflags);
442   usercmdmenu->helpText(_("Commands: Execute a command and send its output to the output pane."));
443 
444   scriptdir.format("%s%s%c%s", tw->ConfigDir().text(), "tools", PATHSEP, "filters");
445   FXDir::create(scriptdir);
446   userfiltermenu=new UserMenu(toolsmenu, _("&Filters"), scriptdir, 'F', tw, TW::ID_USER_FILTER);
447   userfiltermenu->helpText(_("Filters: Pipe selected text to a command and replace with its output."));
448 
449   scriptdir.format("%s%s%c%s", tw->ConfigDir().text(), "tools", PATHSEP, "snippets");
450   FXDir::create(scriptdir);
451   usersnipmenu=new UserMenu(toolsmenu, _("&Snippets"), scriptdir, 'S', tw, TW::ID_USER_SNIPPET, usersnipflags);
452   usersnipmenu->helpText(_("Snippets: Insert the text of a file or the output of a command."));
453 
454   scriptdir.format("%s%s%c%s", tw->ConfigDir().text(), "tools", PATHSEP, "macros");
455   FXDir::create(scriptdir);
456   usermacromenu=new UserMenu(toolsmenu, _("&Macros"), scriptdir, 'M', tw, TW::ID_USER_MACRO);
457   usermacromenu->helpText(_("Macros: Execute a Lua macro using the built-in interpreter."));
458 
459 #if TEST_SOMETHING
460   new FXMenuCommand(toolsmenu, _("Test something\tF2"), NULL, tw, ID_TEST_SOMETHING);
461 #endif
462 
463   docmenu=new MyMenuPane(tw);
464   NewTitle(this,_("&Documents"),NULL,docmenu);
465 
466   MkMnuCmd(docmenu,ID_TAB_NEXT);
467   MkMnuCmd(docmenu,ID_TAB_PREV);
468 
469   tabordermenu=new MyMenuPane(tw);
470   NewCascade(docmenu,_("&Move"),NULL,tabordermenu);
471 
472   MkMnuCmd(tabordermenu,ID_TAB_TOFIRST);
473   MkMnuCmd(tabordermenu,ID_TAB_TOLAST);
474   MkMnuCmd(tabordermenu,ID_TAB_UP);
475   MkMnuCmd(tabordermenu,ID_TAB_DOWN);
476 
477   FXMenuCommand*tmpcmd=new FXMenuCommand(tabordermenu,"foo",NULL,NULL,0);
478   FXint dh=tmpcmd->getDefaultHeight();
479   delete tmpcmd;
480   getApp()->getRootWindow()->getDefaultHeight();
481   doclistmenu=new FXScrollPane(docmenu,24);
482   doclistmenu->setNumVisible((FXint)((getApp()->getRootWindow()->getDefaultHeight()/dh)*0.75));
483   NewCascade(docmenu, _("&Select"), NULL, doclistmenu);
484 
485   new FXMenuSeparator(docmenu, 0);
486   MkMnuCmd(docmenu,ID_FOCUS_OUTLIST);
487 
488   helpmenu=new MyMenuPane(tw);
489   NewTitle(this,_("&Help"),NULL,helpmenu /*,LAYOUT_RIGHT*/);
490 
491   MkMnuCmd(helpmenu,ID_SHOW_HELP);
492   MkMnuCmd(helpmenu,ID_SHOW_LUA_HELP);
493   new FXMenuSeparator(helpmenu, 0);
494   MkMnuCmd(helpmenu,ID_HELP_ABOUT);
495 }
496 
497 
498 
~MainMenu()499 MainMenu::~MainMenu()
500 {
501   delete usercmdmenu;
502   delete userfiltermenu;
503   delete usersnipmenu;
504   delete usermacromenu;
505   delete tabmenu;
506   delete filemenu;
507   delete doclistmenu;
508   delete docmenu;
509   delete tabordermenu;
510   delete tabsidemenu;
511   delete tabwidthmenu;
512   delete editdeletemenu;
513   delete editindentmenu;
514   delete editmenu;
515   delete searchselectmenu;
516   delete searchmarkmenu;
517   delete searchmenu;
518   delete recordermenu;
519   delete toolsmenu;
520   delete helpmenu;
521   delete fileexportmenu;
522   delete langmenu;
523   delete viewzoommenu;
524   delete viewmenu;
525   delete recent_files;
526 }
527 
528 
529 
RescanUserMenus()530 void MainMenu::RescanUserMenus()
531 {
532   usercmdmenu->rescan();
533   userfiltermenu->rescan();
534   usersnipmenu->rescan();
535   usermacromenu->rescan();
536 }
537 
538 
539 
UserMenus() const540 UserMenu**MainMenu::UserMenus() const
541 {
542   static UserMenu* menus[]={ usercmdmenu, userfiltermenu, usersnipmenu, usermacromenu, NULL };
543   return menus;
544 }
545 
546 
547 
EnableFileFormats()548 void MainMenu::EnableFileFormats()
549 {
550 
551 }
552 
553 
554 
EnableFilterMenu(bool enabled)555 void MainMenu::EnableFilterMenu(bool enabled)
556 {
557   if (enabled) { userfiltermenu->enable(); } else { userfiltermenu->disable(); }
558   SetMenuEnabled(filterselmenu,enabled);
559 }
560 
561 
562 
SetMenuEnabled(FXMenuCommand * mnu,bool enabled)563 void MainMenu::SetMenuEnabled(FXMenuCommand*mnu, bool enabled)
564 {
565   FXLabel*btn=(FXLabel*)(mnu->getUserData());
566   if (enabled) {
567     mnu->enable();
568     if (btn) { btn->enable(); }
569   } else {
570     mnu->disable();
571     if (btn) { btn->disable(); }
572   }
573 }
574 
575 
576 
EnableTagMenus(bool enabled)577 void MainMenu::EnableTagMenus(bool enabled)
578 {
579   if (enabled) { unloadtagsmenu->enable(); } else { unloadtagsmenu->disable(); }
580   SetMenuEnabled(findtagmenu,  enabled);
581   SetMenuEnabled(showtipmenu,  enabled);
582   SetMenuEnabled(autocompmenu, enabled);
583 }
584 
585 
586 
AddFileToTagsList(const FXString & filename)587 void MainMenu::AddFileToTagsList(const FXString &filename)
588 {
589   FXMenuPane*pane=(FXMenuPane*)unloadtagsmenu->getMenu();
590   FXWindow*w;
591   FXString fn=FXPath::simplify(FXPath::absolute(filename));
592   for ( w=pane->getFirst(); w; w=w->getNext() ) {
593     if (strcmp(fn.text(),((FXMenuCaption*)w)->getText().text())==0) {
594       return;
595     }
596   }
597   EnableTagMenus(true);
598   FXMenuCommand*mc=new FXMenuCommand(pane,"",NULL,this,TopWindow::ID_UNLOAD_TAGS);
599   mc->create();
600   mc->setText(fn);
601 }
602 
603 
604 
UnloadTagFile(FXMenuCommand * mc)605 void MainMenu::UnloadTagFile(FXMenuCommand*mc)
606 {
607   mc->hide();
608   mc->destroy();
609   delete mc;
610   if (unloadtagsmenu->getMenu()->numChildren()==0) {
611     EnableTagMenus(false);
612   }
613 }
614 
615 
616 
RemoveFileFromTagsList(const FXString & filename)617 bool MainMenu::RemoveFileFromTagsList(const FXString &filename)
618 {
619   FXMenuPane*pane=(FXMenuPane*)unloadtagsmenu->getMenu();
620   if (filename.empty()) { /* remove all tag files */
621     while (pane->numChildren()>0) { UnloadTagFile((FXMenuCommand*)pane->getFirst()); }
622     return true;
623   } else {
624     FXWindow*w;
625     FXString fn=FXPath::simplify(FXPath::absolute(filename));
626     for ( w=pane->getFirst(); w; w=w->getNext() ) {
627       if (strcmp(fn.text(),((FXMenuCaption*)w)->getText().text())==0) {
628         UnloadTagFile((FXMenuCommand*)w);
629         return true; /* we found it */
630       }
631     }
632     return false; /* we did not find the filename in the menu */
633   }
634 }
635 
636 
637 
TagsMenu() const638 FXMenuCascade*MainMenu::TagsMenu() const
639 {
640   return unloadtagsmenu;
641 }
642 
643 
644 
SetLanguageCheckmark(LangStyle * ls)645 void MainMenu::SetLanguageCheckmark(LangStyle*ls)
646 {
647   for (FXWindow*wmc=langmenu->getFirst(); wmc; wmc=wmc->getNext()) {
648     FXPopup*pu=((FXMenuCascade*)wmc)->getMenu();
649     for (FXWindow*wmr=pu->getFirst(); wmr; wmr=wmr->getNext()) {
650       FXMenuRadio*mr=(FXMenuRadio*)wmr;
651       mr->setCheck(mr->getUserData()==ls);
652     }
653   }
654 }
655 
656 
657 
GetMenuForLanguage(const FXString & name) const658 FXMenuRadio*MainMenu::GetMenuForLanguage(const FXString &name) const
659 {
660   for (FXWindow*grp=langmenu->getFirst(); grp; grp=grp->getNext()) {
661     for (FXWindow*mnu=((FXMenuCascade*)grp)->getMenu()->getFirst(); mnu; mnu=mnu->getNext()) {
662       if (compare(((FXMenuCommand*)mnu)->getText(),name)==0) { return (FXMenuRadio*)mnu; }
663     }
664   }
665   return NULL;
666 }
667 
668 
669 
Recording(bool recording,bool recorded)670 void MainMenu::Recording(bool recording, bool recorded)
671 {
672   FXToggleButton*tbar_rec_btn=dynamic_cast<FXToggleButton*>((FXObject*)recorderstartmenu->getUserData());
673   recorderstartmenu->setText(recording?_("Stop re&cording"):_("Re&cord macro"));
674   SetMenuEnabled(playbackmenu,recorded && !recording);
675   SetMenuEnabled(showmacromenu,recorded && !recording);
676   if (tbar_rec_btn) { tbar_rec_btn->setState(recording); }
677 }
678 
679 
680 
AppendDocList(const FXString & filename,FXTabItem * tab)681 void MainMenu::AppendDocList(const FXString &filename, FXTabItem*tab)
682 {
683   FXMenuCommand* cmd = new FXMenuCommand(  doclistmenu, filename.empty()?tab->getText():filename,
684                                            NULL, tw, TW::ID_TAB_ACTIVATE, 0 );
685   if (shown()) { cmd->create(); }
686   RemoveRecentFile(filename);
687   cmd->setUserData(tab);
688   tab->setUserData(cmd);
689 }
690 
691 
692 
PrependRecentFile(const FXString & filename)693 void MainMenu::PrependRecentFile(const FXString &filename)
694 {
695   recent_files->prepend(filename);
696 }
697 
698 
699 
RemoveRecentFile(const FXString & filename)700 void MainMenu::RemoveRecentFile(const FXString &filename)
701 {
702   recent_files->remove(filename);
703 }
704 
705 
706 
SyncCheck(FXMenuCheck * chk,bool checked)707 static inline void SyncCheck(FXMenuCheck *chk, bool checked)
708 {
709   chk->setCheck(checked);
710   FXToggleButton*btn=dynamic_cast<FXToggleButton*>((FXObject*)chk->getUserData());
711   if (btn) { btn->setState(chk->getCheck()); }
712 }
713 
714 
715 
SyncPrefsCheckmarks()716 void MainMenu::SyncPrefsCheckmarks()
717 {
718 SyncCheck(linenums_chk,  prefs->ShowLineNumbers);
719 SyncCheck(status_chk,    prefs->ShowStatusBar);
720 SyncCheck(outpane_chk,   prefs->ShowOutputPane);
721 SyncCheck(white_chk,     prefs->ShowWhiteSpace);
722 SyncCheck(toolbar_chk,   prefs->ShowToolbar);
723 SyncCheck(margin_chk,    prefs->ShowRightEdge);
724 SyncCheck(guides_chk,    prefs->ShowIndentGuides);
725 SyncCheck(caretline_chk, prefs->ShowCaretLine);
726 SyncCheck(invert_chk,    prefs->InvertColors);
727 }
728 
729 
SetReadOnlyCheckmark(bool rdonly)730 void MainMenu::SetReadOnlyCheckmark(bool rdonly)
731 {
732   SyncCheck(readonly_chk,rdonly);
733   if (rdonly) { fileformatcasc->disable(); } else { fileformatcasc->enable(); }
734   SetMenuEnabled(fmt_dos_mnu,!rdonly);
735   SetMenuEnabled(fmt_mac_mnu,!rdonly);
736   SetMenuEnabled(fmt_unx_mnu,!rdonly);
737 }
738 
739 
740 
SetWordWrapCheckmark(bool wrapped)741 void MainMenu::SetWordWrapCheckmark(bool wrapped)
742 {
743   SyncCheck(wordwrap_chk,wrapped);
744 }
745 
746 
747 
UpdateDocTabSettings()748 void MainMenu::UpdateDocTabSettings()
749 {
750   switch (prefs->DocTabPosition) {
751     case 'T': MenuMgr::RadioUpdate(TW::ID_TABS_TOP,    TW::ID_TABS_TOP, TW::ID_TABS_RIGHT); break;
752     case 'B': MenuMgr::RadioUpdate(TW::ID_TABS_BOTTOM, TW::ID_TABS_TOP, TW::ID_TABS_RIGHT); break;
753     case 'L': MenuMgr::RadioUpdate(TW::ID_TABS_LEFT,   TW::ID_TABS_TOP, TW::ID_TABS_RIGHT); break;
754     case 'R': MenuMgr::RadioUpdate(TW::ID_TABS_RIGHT,  TW::ID_TABS_TOP, TW::ID_TABS_RIGHT); break;
755   }
756   switch (prefs->DocTabsPacked) {
757     case 'U':MenuMgr::RadioUpdate(TW::ID_TABS_UNIFORM,TW::ID_TABS_UNIFORM,TW::ID_TABS_BY_POS); break;
758     case 'P':MenuMgr::RadioUpdate(TW::ID_TABS_COMPACT,TW::ID_TABS_UNIFORM,TW::ID_TABS_BY_POS); break;
759     case 'A':MenuMgr::RadioUpdate(TW::ID_TABS_BY_POS,TW::ID_TABS_UNIFORM,TW::ID_TABS_BY_POS); break;
760   }
761 }
762 
763