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 #include <cctype>
20 
21 #include <fxkeys.h>
22 #include <fx.h>
23 
24 #include "compat.h"
25 #include "prefs.h"
26 #include "appname.h"
27 #include "appwin_pub.h"
28 #include "search.h"
29 #include "histbox.h"
30 #include "tooltree.h"
31 #include "menuspec.h"
32 #include "desclistdlg.h"
33 #include "prefdlg_ext.h"
34 #include "prefdlg_sntx.h"
35 #include "prefdlg_tbar.h"
36 #include "theme.h"
37 #include "shady_tabs.h"
38 
39 #include "intl.h"
40 #include "prefdlg.h"
41 
42 
43 #define PACK_UNIFORM   ( PACK_UNIFORM_WIDTH | PACK_UNIFORM_HEIGHT )
44 #define LAYOUT_CENTER  ( LAYOUT_CENTER_Y | LAYOUT_CENTER_X )
45 #define SPIN_OPTS      ( SPIN_NORMAL | FRAME_SUNKEN | FRAME_THICK )
46 #define LIST_BOX_OPTS  ( FRAME_SUNKEN | FRAME_THICK | LISTBOX_NORMAL | LAYOUT_FILL_X )
47 
48 static const char*color_hint = _("Drag a color square to FG/BG, or double-click FG/BG to edit");
49 
50 static const char* hint_list[] = {
51   _("General application settings"),
52   _("Editor specific settings"),
53   color_hint,
54   _("Double-click an item to edit"),
55   _("Edit toolbar buttons"),
56   _("Edit popup menu items"),
57   _("User interface colors and font"),
58   NULL
59 };
60 
61 static FXival whichtab=0;
62 
63 
64 static const char* sntx_hint_list[] = {
65   color_hint,
66   _("Language-specific options"),
67   NULL
68 };
69 
70 static FXival whichsyntab=0;
71 
72 
73 FXDEFMAP(PrefsDialog) PrefsDialogMap[]={
74   FXMAPFUNC(SEL_COMMAND,PrefsDialog::ID_TAB_SWITCHED,PrefsDialog::onTabSwitch),
75   FXMAPFUNC(SEL_DOUBLECLICKED,PrefsDialog::ID_ACCEL_EDIT,PrefsDialog::onAccelEdit),
76   FXMAPFUNC(SEL_KEYPRESS,PrefsDialog::ID_ACCEL_EDIT,PrefsDialog::onAccelEdit),
77   FXMAPFUNC(SEL_COMMAND, PrefsDialog::ID_FILTERS_EDIT,PrefsDialog::onFiltersEdit),
78   FXMAPFUNC(SEL_COMMAND, PrefsDialog::ID_ERRPATS_EDIT,PrefsDialog::onErrPatsEdit),
79   FXMAPFUNC(SEL_COMMAND, PrefsDialog::ID_SYSINCS_EDIT,PrefsDialog::onSysIncsEdit),
80   FXMAPFUNC(SEL_COMMAND, PrefsDialog::ID_CHOOSE_FONT,PrefsDialog::onChooseFont),
81   FXMAPFUNC(SEL_CHANGED, PrefsDialog::ID_CHANGED_TOOLBAR,PrefsDialog::onChangedToolbar),
82 };
83 
84 FXIMPLEMENT(PrefsDialog,FXDialogBox,PrefsDialogMap,ARRAYNUMBER(PrefsDialogMap));
85 
86 
AccelSanity(FXWindow * w,FXHotKey acckey)87 static bool AccelSanity(FXWindow*w, FXHotKey acckey)
88 {
89   FXushort key=FXSELID(acckey);
90   FXushort mod=FXSELTYPE(acckey);
91   if (key==0) {
92     FXMessageBox::error(w, MBOX_OK, _("Invalid keybinding"), _("That keybinding does not end with a valid key name"));
93     return false;
94   }
95   if ((key>=KEY_F1)&&(key<=KEY_F12)) { return true; }
96   if ((mod&CONTROLMASK)||(mod&ALTMASK)||(mod&METAMASK)) { return true; }
97   return (FXMessageBox::question(w, MBOX_YES_NO, _("Weak keybinding"), "%s\n\n%s",
98     _("That key binding doesn't contain any [Ctrl] or [Alt]\n"
99       "modifiers, which might cause you some problems."),
100     _("Are you sure you want to continue?")
101    )==MBOX_CLICKED_YES);
102 }
103 
104 
105 
AccelUnique(FXWindow * w,FXAccelTable * table,FXHotKey acckey,MenuSpec * spec)106 static bool AccelUnique(FXWindow*w, FXAccelTable *table, FXHotKey acckey, MenuSpec*spec)
107 {
108   MenuSpec*killcmd=MenuMgr::LookupMenu(TopWinPub::KillCmdID());
109 
110   if ( (acckey==parseAccel(killcmd->accel)) && (spec!=killcmd)) {
111     FXMessageBox::error(w, MBOX_OK, _("Conflicting keybinding"),
112       _("Keybinding for \"%s\" must not conflict with \"%s\""),spec->pref,killcmd->pref);
113     return false;
114   }
115 
116   if (!table->hasAccel(acckey)) { return true; }
117 
118   if (FXMessageBox::question(w, MBOX_YES_NO, _("Conflicting keybinding"), "%s\n\n%s",
119     _("This keybinding appears to conflict with an existing one."),
120     _("Are you sure you want to continue?")
121   )==MBOX_CLICKED_YES) {
122     table->removeAccel(acckey);
123     return true;
124   } else {
125     return false;
126   }
127 
128 }
129 
130 
131 
AccelDelete(FXWindow * w,FXAccelTable * table,const FXString & acctxt)132 static bool AccelDelete(FXWindow*w, FXAccelTable *table, const FXString &acctxt)
133 {
134   FXHotKey acckey=parseAccel(acctxt);
135   if (!table->hasAccel(acckey)) {
136     return true;
137   } else {
138     if (FXMessageBox::question(w, MBOX_YES_NO, _("Confirm delete"),
139       _("Are you sure you want to remove this keybinding?")
140     )==MBOX_CLICKED_YES) {
141      table->removeAccel(acckey);
142       return true;
143     } else {
144       return false;
145     }
146   }
147 }
148 
149 
150 
EditAccel(FXString & acctxt,FXWindow * w,MenuSpec * spec,FXHotKey & acckey)151 static bool EditAccel(FXString&acctxt, FXWindow*w, MenuSpec*spec, FXHotKey &acckey)
152 {
153   FXInputDialog dlg(w,"","");
154   FXint maxlen=sizeof(spec->accel)-1;
155   dlg.setNumColumns(maxlen);
156   FXString msg;
157   msg.format(
158     "%s:\n"
159     "   Ctrl+Shift+F12\n"
160     "   F3\n"
161     "   Alt+G\n\n"
162     "%s \"%s\"",
163     _("Examples"), _("Keybinding for"), spec->pref);
164   FXString orig=acctxt.text();
165   while (true) {
166     acckey=0;
167     if (dlg.getString(acctxt, w->getShell(), _("Edit keybinding"), msg )) {
168       if (acctxt.empty()) {
169         if (spec->sel==(FXint)TopWinPub::KillCmdID()) {
170           FXMessageBox::error(w->getShell(), MBOX_OK, _("Empty keybinding"), "%s \"%s\"",
171             _("You cannot remove the keybinding for"), spec->pref);
172           acctxt=orig.text();
173           continue;
174         } else {
175           return true;
176         }
177       }
178       acckey=parseAccel(acctxt);
179       if (acckey) {
180         acctxt=unparseAccel(acckey);
181         if ((acctxt.length())<maxlen) {
182           if (AccelSanity(w,acckey)) { return strcmp(spec->accel, acctxt.text())!=0; }
183         } else {
184           FXMessageBox::error(w->getShell(), MBOX_OK,
185             _("Keybinding too long"), _("Text of keybinding specification must not exceed %d bytes\n"), maxlen);
186         }
187       } else {
188         FXMessageBox::error(w->getShell(), MBOX_OK,
189           _("Invalid keybinding"), "%s:\n%s", _("Failed to parse accelerator"), acctxt.text());
190         acctxt=orig.text();
191       }
192     } else {
193       return false;
194     }
195   }
196 }
197 
198 
199 
onAccelEdit(FXObject * o,FXSelector s,void * p)200 long PrefsDialog::onAccelEdit(FXObject*o, FXSelector s, void*p)
201 {
202   if (o!=acclist) { return 0; }
203     switch ( FXSELTYPE(s) ) {
204     case SEL_DOUBLECLICKED: {  break;  }
205     case SEL_KEYPRESS: {
206       FXint code=((FXEvent*)p)->code;
207       switch (code) {
208         case KEY_Return: { break; }
209         case KEY_KP_Enter: { break; }
210         case KEY_F2: { break; }
211         case KEY_space: { break; }
212         default: { return 0; }
213       }
214       break;
215     }
216     default: { return 0; }
217   }
218   MenuSpec*spec=(MenuSpec*)(acclist->getItemData(acclist->getCurrentItem()));
219   FXWindow*own=main_win;
220   FXAccelTable *table=own?own->getAccelTable():NULL;
221   if (spec && own && table) {
222     FXString acctxt=spec->accel;
223     FXHotKey acckey;
224     if ( EditAccel(acctxt,this,spec,acckey) ) {
225       if (acctxt.empty()) {
226         if (AccelDelete(this,table,spec->accel)) {
227           memset(spec->accel,0,sizeof(spec->accel));
228           if (spec->ms_mc) { spec->ms_mc->setAccelText(spec->accel); }
229           FXString txt;
230           txt.format("%s\t",spec->pref);
231           acclist->setItemText(acclist->getCurrentItem(),txt);
232         }
233       } else {
234         if (AccelUnique(this, table, acckey, spec)) {
235           FXHotKey oldkey=parseAccel(spec->accel);
236           memset(spec->accel,0,sizeof(spec->accel));
237           strncpy(spec->accel, acctxt.text(),sizeof(spec->accel)-1);
238           if (oldkey && table->hasAccel(oldkey)) { table->removeAccel(oldkey); }
239           if (spec->sel==(FXint)TopWinPub::KillCmdID()){
240             TopWinPub::SetKillCommandAccelKey(acckey);
241           } else  {
242             if (spec->ms_mc) {
243               spec->ms_mc->setSelector(0);
244               spec->ms_mc->setAccelText(spec->accel);
245               table->addAccel(acckey,spec->ms_mc->getTarget(),FXSEL(SEL_COMMAND,spec->sel));
246             } else {
247               table->addAccel(acckey,own,FXSEL(SEL_COMMAND,spec->sel));
248             }
249           }
250           FXString txt;
251           txt.format("%s\t%s",spec->pref,spec->accel);
252           acclist->setItemText(acclist->getCurrentItem(),txt);
253         }
254       }
255     }
256   } else {
257     FXMessageBox::error(getShell(), MBOX_OK, _("Internal error"), _("Failed to retrieve keybinding information"));
258   }
259   return 1;
260 }
261 
262 
263 
264 #define SetPad(padwin, padsize) \
265 (padwin)->setPadLeft(padsize); \
266 (padwin)->setPadTop(padsize); \
267 (padwin)->setPadRight(padsize); \
268 (padwin)->setPadBottom(padsize);
269 
270 
271 
272 // Subclass FXListItem to show custom tooltip...
273 class TBarListItem: public FXListItem {
274 public:
TBarListItem(const FXString & text,FXIcon * ic=NULL,void * ptr=NULL)275   TBarListItem(const FXString &text, FXIcon *ic=NULL, void *ptr=NULL):FXListItem(text,ic,ptr){ }
getTipText() const276   virtual FXString getTipText() const {
277     FXString tip;
278     MenuSpec*spec=(MenuSpec*)getData();
279     if (spec) { MenuMgr::GetTBarBtnTip(spec,tip); } else { tip=label.text(); }
280     return tip;
281   }
282 };
283 
284 
285 
286 // Subclass FXIconItem to show custom tooltip...
287 class KBindListItem: public FXIconItem {
288 public:
KBindListItem(const FXString & text,FXIcon * bi=NULL,FXIcon * mi=NULL,void * ptr=NULL)289   KBindListItem(const FXString &text, FXIcon*bi=NULL, FXIcon*mi=NULL, void*ptr=NULL):FXIconItem(text,bi,mi,ptr) {}
getTipText() const290   virtual FXString getTipText() const {
291     FXString tip;
292     MenuSpec*spec=(MenuSpec*)getData();
293     if (spec) { MenuMgr::GetTBarBtnTip(spec,tip); } else { tip=label.section('\t',0).text(); }
294     return tip;
295   }
296 };
297 
298 
299 
300 static FXuint changed_toolbar = ToolbarUnchanged;
301 
ChangedToolbar()302 FXuint PrefsDialog::ChangedToolbar()
303 {
304   if (Theme::changed() & ThemeChangedFont) { changed_toolbar |= ToolbarChangedFont; }
305   return changed_toolbar;
306 }
307 
308 
onChangedToolbar(FXObject * o,FXSelector sel,void * p)309 long PrefsDialog::onChangedToolbar(FXObject*o,FXSelector sel,void*p)
310 {
311   changed_toolbar|=(FXuint)((FXival)p);
312   return 1;
313 }
314 
315 
316 
MakeToolbarTab()317 void PrefsDialog::MakeToolbarTab()
318 {
319   new FXTabItem(tabs,_("toolbar"));
320   new ToolbarPrefs(tabs, TopWinPub::UserMenus(), TopWinPub::LastID(), this, ID_CHANGED_TOOLBAR);
321   changed_toolbar=ToolbarUnchanged;
322 }
323 
324 
325 
MakePopupTab()326 void PrefsDialog::MakePopupTab()
327 {
328   new FXTabItem(tabs,_("popup"));
329   new PopupPrefs(tabs, TopWinPub::UserMenus(), TopWinPub::LastID());
330 }
331 
332 
333 
MakeKeybindingsTab()334 void PrefsDialog::MakeKeybindingsTab()
335 {
336   new FXTabItem(tabs,_("keys"));
337   FXHorizontalFrame *frame=new FXHorizontalFrame(tabs,FRAME_RAISED|LAYOUT_FILL);
338   acclist=new FXIconList(frame,
339     this,ID_ACCEL_EDIT,FRAME_SUNKEN|FRAME_THICK|LAYOUT_SIDE_TOP|LAYOUT_FILL_Y|LAYOUT_FIX_WIDTH|ICONLIST_BROWSESELECT);
340 
341   acclist->appendHeader(_("action"));
342   acclist->appendHeader(_("keybinding"));
343   FXString spaces;
344   for (MenuSpec*spec=MenuMgr::MenuSpecs(); spec->sel!=(FXint)TopWinPub::LastID(); spec++) {
345     FXString txt;
346     txt.format("%s\t%s", spec->pref, spec->accel);
347     acclist->appendItem(new KBindListItem(txt, NULL, NULL, (void*)spec));
348   }
349   acclist->selectItem(0);
350 }
351 
352 
353 
MakeSyntaxTab()354 void PrefsDialog::MakeSyntaxTab()
355 {
356   new FXTabItem(tabs,_("syntax"));
357   langs=new LangGUI(tabs,prefs,this,ID_TAB_SWITCHED);
358 
359 }
360 
361 
362 
onFiltersEdit(FXObject * o,FXSelector sel,void * p)363 long PrefsDialog::onFiltersEdit(FXObject*o,FXSelector sel,void*p)
364 {
365   FileFiltersDlg(this).execute();
366 #ifdef WIN32
367   hide();
368   show();
369   ((FXWindow*)o)->setFocus();
370 #endif
371   return 1;
372 }
373 
374 
375 
onErrPatsEdit(FXObject * o,FXSelector sel,void * p)376 long PrefsDialog::onErrPatsEdit(FXObject*o,FXSelector sel,void*p)
377 {
378   ErrPatDlg(this).execute();
379 #ifdef WIN32
380   hide();
381   show();
382   ((FXWindow*)o)->setFocus();
383 #endif
384   return 1;
385 }
386 
387 
388 
onSysIncsEdit(FXObject * o,FXSelector sel,void * p)389 long PrefsDialog::onSysIncsEdit(FXObject*o,FXSelector sel,void*p)
390 {
391   SysIncDlg(this).execute();
392 #ifdef WIN32
393   hide();
394   show();
395   ((FXWindow*)o)->setFocus();
396 #endif
397   return 1;
398 }
399 
400 
401 
MakeGeneralTab()402 void PrefsDialog::MakeGeneralTab()
403 {
404   new FXTabItem(tabs,_("general"));
405   FXHorizontalFrame* hframe;
406   FXVerticalFrame* vframe;
407   FXVerticalFrame* left_column;
408   FXVerticalFrame* right_column;
409   FXCheckButton*chk;
410   ClipTextField *tf;
411   FXSpinner *spin;
412   vframe=new FXVerticalFrame(tabs,FRAME_RAISED|LAYOUT_FILL,0,0,0,0,0,0,0,0,0,0);
413   hframe=new FXHorizontalFrame(vframe,FRAME_NONE|LAYOUT_FILL|PACK_UNIFORM_WIDTH);
414   left_column=new FXVerticalFrame(hframe,FRAME_SUNKEN|LAYOUT_FILL/*|PACK_UNIFORM_HEIGHT*/);
415   right_column=new FXVerticalFrame(hframe,FRAME_SUNKEN|LAYOUT_FILL/*|PACK_UNIFORM_HEIGHT*/);
416 
417   chk=new FXCheckButton(left_column, _("Watch files for external changes."), prefs, Settings::ID_TOGGLE_WATCH_EXTERN);
418   chk->setCheck(prefs->WatchExternChanges, false);
419   chk->setPadBottom(8);
420 
421   hframe=new FXHorizontalFrame(left_column);
422   SetPad(hframe,0);
423   chk=new FXCheckButton(hframe, _("Backup files every "), prefs, Settings::ID_TOGGLE_AUTOSAVE);
424   chk->setCheck(prefs->Autosave, false);
425   chk->setPadBottom(12);
426   spin=new FXSpinner(hframe, 3, prefs, Settings::ID_SET_AUTOSAVE_INT,SPIN_OPTS);
427   spin->setRange(15,900);
428   spin->setValue(prefs->AutosaveInterval);
429 
430   new FXLabel(hframe, _(" seconds."));
431   if (!chk->getCheck()) { spin->disable(); }
432   chk->setUserData(spin);
433 
434   new FXLabel(left_column,  _("Ask before closing multiple files:"));
435   chk=new FXCheckButton(left_column, _("From menu"), prefs, Settings::ID_TOGGLE_ASK_CLOSE_MULTI_MENU);
436   chk->setCheck(prefs->PromptCloseMultiMenu, false);
437   chk->setPadLeft(12);
438   chk=new FXCheckButton(left_column, _("On exit"), prefs, Settings::ID_TOGGLE_ASK_CLOSE_MULTI_EXIT);
439   chk->setCheck(prefs->PromptCloseMultiExit, false);
440   chk->setPadLeft(12);
441   chk->setPadBottom(12);
442 
443   hframe=new FXHorizontalFrame(left_column);
444   hframe->setPadBottom(8);
445   tf=new ClipTextField(hframe, 3, prefs, Settings::ID_SET_MAX_FILES,TEXTFIELD_LIMITED|TEXTFIELD_INTEGER|TEXTFIELD_NORMAL);
446   char maxfiles[8]="\0\0\0\0\0\0\0";
447   snprintf(maxfiles, sizeof(maxfiles)-1, "%d", prefs->MaxFiles);
448   tf->setText(maxfiles);
449   new FXLabel(hframe, _("Maximum number of open files."));
450 
451   (new FXHorizontalSeparator(left_column,LAYOUT_SIDE_TOP|LAYOUT_FILL_X|SEPARATOR_GROOVE))->setPadBottom(12);
452   hframe=new FXHorizontalFrame(left_column);
453   hframe->setPadLeft(12);
454   new FXButton(hframe, _(" File dialog filters... "), NULL, this, ID_FILTERS_EDIT);
455 
456   hframe=new FXHorizontalFrame(left_column, LAYOUT_FILL_X);
457   (new FXLabel(hframe, _("Remember\nlast-used filter :")))->setJustify(JUSTIFY_LEFT);
458   FXListBox* list=new FXListBox(hframe,prefs,Settings::ID_SET_KEEP_FILE_FILTER,LIST_BOX_OPTS|LAYOUT_BOTTOM);
459   list->appendItem(_("never"),NULL,NULL);
460   list->appendItem(_("during session"),NULL,NULL);
461   list->appendItem(_("across sessions"),NULL,NULL);
462   list->setNumVisible(list->getNumItems());
463   list->setCurrentItem(prefs->KeepFileFilter);
464 
465   new FXLabel(right_column,_("Save open files before executing:"));
466   chk=new FXCheckButton(right_column, _("Tools->Filter Selection"), prefs, Settings::ID_SAVE_ON_FILTER_SEL);
467   chk->setCheck(prefs->SaveBeforeFilterSel, false);
468   chk->setPadLeft(12);
469 
470   chk=new FXCheckButton(right_column, _("Tools->Insert Command"), prefs, Settings::ID_SAVE_ON_INS_CMD);
471   chk->setCheck(prefs->SaveBeforeInsCmd, false);
472   chk->setPadLeft(12);
473 
474   chk=new FXCheckButton(right_column, _("Tools->Execute Command"), prefs, Settings::ID_SAVE_ON_EXEC_CMD);
475   chk->setCheck(prefs->SaveBeforeExecCmd, false);
476   chk->setPadLeft(12);
477 
478 #ifndef WIN32
479   hframe=new FXHorizontalFrame(right_column);
480   hframe->setPadTop(16);
481   new FXLabel(hframe, _("Shell command: "));
482   tf=new ClipTextField(hframe,18,prefs,Settings::ID_SET_SHELL_CMD,TEXTFIELD_NORMAL);
483   tf->setText(prefs->ShellCommand);
484 #endif
485 
486   new FXHorizontalSeparator(right_column,LAYOUT_SIDE_TOP|LAYOUT_FILL_X|SEPARATOR_GROOVE);
487 
488   hframe=new FXHorizontalFrame(right_column);
489   hframe->setPadTop(12);
490   spin=new FXSpinner(hframe, 2, prefs, Settings::ID_SET_WHEEL_LINES,SPIN_OPTS);
491   spin->setRange(1,32);
492   spin->setValue(prefs->WheelLines);
493   new FXLabel(hframe, _("Mouse wheel acceleration."));
494 
495   hframe=new FXHorizontalFrame(right_column);
496   hframe->setPadTop(12);
497   spin=new FXSpinner(hframe, 4, prefs, Settings::ID_SET_TAB_TITLE_MAX_WIDTH,SPIN_OPTS);
498   spin->setRange(0,prefs->ScreenWidth);
499   spin->setValue(prefs->TabTitleMaxWidth);
500   new FXLabel(hframe, _("Max width for tab titles.\n( in pixels;  0 = no limit. )"));
501 
502   right_column=new FXVerticalFrame(right_column,FRAME_NONE|PACK_UNIFORM_WIDTH|LAYOUT_CENTER_X|LAYOUT_BOTTOM);
503   right_column->setVSpacing(8);
504   new FXButton(right_column, _("System header locations... "),NULL,this,ID_SYSINCS_EDIT,BUTTON_NORMAL|LAYOUT_CENTER_X);
505   new FXButton(right_column, _("Output pane line matching... "),NULL,this,ID_ERRPATS_EDIT,BUTTON_NORMAL|LAYOUT_CENTER_X);
506 }
507 
508 
509 
onChooseFont(FXObject * o,FXSelector sel,void * p)510 long PrefsDialog::onChooseFont(FXObject*o,FXSelector sel,void*p)
511 {
512   prefs->handle(this, FXSEL(SEL_COMMAND, Settings::ID_CHOOSE_FONT), NULL);
513   langs->handle(langs,FXSEL(SEL_COMMAND,LangGUI::ID_LANG_SWITCH),(void*)((FXival)(-1)));
514   return 1;
515 }
516 
517 
518 
MakeEditorTab()519 void PrefsDialog::MakeEditorTab()
520 {
521   new FXTabItem(tabs,_("editor"));
522   FXHorizontalFrame *frame;
523   FXVerticalFrame *column;
524   FXHorizontalFrame *spinframe;
525   FXCheckButton*chk;
526   FXSpinner *spin;
527   FXListBox*list;
528 
529   frame=new FXHorizontalFrame(tabs,FRAME_RAISED|LAYOUT_FILL);
530   column=new FXVerticalFrame(frame,FRAME_SUNKEN|LAYOUT_FILL);
531 
532   spinframe=new FXHorizontalFrame(column);
533   new FXLabel(spinframe, _("Auto indent:"));
534   list=new FXListBox(spinframe,prefs,Settings::ID_SET_AUTO_INDENT,LIST_BOX_OPTS);
535   list->appendItem(_("off"),NULL,NULL);
536   list->appendItem(_("basic"),NULL,NULL);
537   list->appendItem(_("smart"),NULL,NULL);
538   list->setNumVisible(list->getNumItems());
539   list->setCurrentItem(prefs->AutoIndent);
540 
541   chk=new FXCheckButton(column, _("Smart home key"), prefs, Settings::ID_TOGGLE_SMART_HOME);
542   chk->setCheck(prefs->SmartHome, false);
543 
544   chk=new FXCheckButton(column, _("Smooth scrolling"), prefs, Settings::ID_TOGGLE_SMOOTH_SCROLL);
545   chk->setCheck(prefs->SmoothScroll, false);
546 
547   chk=new FXCheckButton(column, _("Allow caret beyond end of line"), prefs, Settings::ID_TOGGLE_CARET_PAST_EOL);
548   chk->setCheck(prefs->CaretPastEOL, false);
549 
550   chk=new FXCheckButton(column,_("Turn line wrapping on by default"),prefs,Settings::ID_TOGGLE_WORD_WRAP);
551   chk->setCheck(prefs->WordWrap);
552 
553   chk=new FXCheckButton(column, _("Wrap-aware home/end keys"), prefs, Settings::ID_TOGGLE_WRAP_AWARE);
554   chk->setCheck(prefs->WrapAwareHomeEnd, false);
555 
556   spinframe=new FXHorizontalFrame(column);
557   spin=new FXSpinner(spinframe, 2, prefs, Settings::ID_SET_CARET_WIDTH, SPIN_OPTS);
558   spin->setRange(1,3);
559   spin->setValue(prefs->CaretWidth);
560   new FXLabel(spinframe, _("Caret width"));
561 
562 
563   spinframe=new FXHorizontalFrame(column);
564   spin=new FXSpinner(spinframe, 4, prefs, Settings::ID_SET_RIGHT_EDGE, SPIN_OPTS);
565   spin->setRange(1,1024);
566   spin->setValue(prefs->RightEdgeColumn);
567   new FXLabel(spinframe, _("Right Margin Indicator"));
568 
569   spinframe=new FXHorizontalFrame(column);
570   new FXLabel(spinframe, _("Split views:"));
571   list=new FXListBox(spinframe,prefs,Settings::ID_SET_SPLIT_VIEW,LIST_BOX_OPTS);
572   list->appendItem(_("cycle"),NULL,NULL);
573   list->appendItem(_("below"),NULL,NULL);
574   list->appendItem(_("beside"),NULL,NULL);
575   list->setNumVisible(list->getNumItems());
576   list->setCurrentItem(prefs->SplitView);
577 
578   new FXLabel(column, " ");
579   new FXButton(column, _(" Editor font... "), NULL, this, ID_CHOOSE_FONT, BUTTON_NORMAL|LAYOUT_CENTER_X);
580 
581   column=new FXVerticalFrame(frame,FRAME_SUNKEN|LAYOUT_FILL);
582 
583   spinframe=new FXHorizontalFrame(column);
584   new FXLabel(spinframe, _("Highlight matching braces\n(when caret is...)"));
585   list=new FXListBox(spinframe,prefs,Settings::ID_SET_BRACE_MATCHING,LIST_BOX_OPTS|LAYOUT_CENTER_Y);
586   list->appendItem(_("never"),NULL,NULL);
587   list->appendItem(_("inside"),NULL,NULL);
588   list->appendItem(_("outside"),NULL,NULL);
589   list->appendItem(_("on either side"),NULL,NULL);
590   list->appendItem(_("after"),NULL,NULL);
591   list->setNumVisible(list->getNumItems());
592   list->setCurrentItem(prefs->BraceMatch);
593 
594   chk=new FXCheckButton(column, _("Use tabs for indent"), prefs, Settings::ID_TOGGLE_USE_TABS);
595 
596   spinframe=new FXHorizontalFrame(column);
597   spin=new FXSpinner(spinframe, 2, prefs, Settings::ID_SET_TAB_WIDTH, SPIN_OPTS);
598   spin->setRange(1,16);
599   spin->setValue(prefs->TabWidth);
600   (new FXLabel(spinframe, _("Tab width")))->setPadRight(16);
601 
602   spin=new FXSpinner(spinframe, 2, prefs, Settings::ID_SET_INDENT_WIDTH, SPIN_OPTS);
603   spin->setRange(1,16);
604   spin->setValue(prefs->IndentWidth);
605   new FXLabel(spinframe, _("Indent width"));
606 
607   chk->setUserData((void*)spin);
608   chk->setCheck(prefs->UseTabs, true);
609 
610   new FXHorizontalSeparator(column,LAYOUT_SIDE_TOP|LAYOUT_FILL_X|SEPARATOR_GROOVE);
611   new FXLabel(column, _("Default search options:"));
612   srchopts=new SciSearchOptions(column, prefs,Settings::ID_SET_SEARCH_OPTS);
613   srchopts->SetSciFlags(prefs->SearchOptions);
614   chk=new FXCheckButton(column, _("Verbose search messages"), prefs, Settings::ID_TOGGLE_SEARCH_VERBOSE);
615   chk->setCheck(prefs->SearchVerbose, false);
616   chk->setPadLeft(6);
617 
618   spinframe=new FXHorizontalFrame(column);
619 
620   new FXLabel(spinframe, _("Search wrap:"));
621   list=new FXListBox(spinframe,prefs,Settings::ID_SET_SEARCH_WRAP,LIST_BOX_OPTS);
622   list->appendItem(_("never"),NULL,NULL);
623   list->appendItem(_("always"),NULL,NULL);
624   list->appendItem(_("prompt"),NULL,NULL);
625   list->setNumVisible(list->getNumItems());
626   list->setCurrentItem(prefs->SearchWrap);
627 
628   new FXLabel(spinframe, _(" GUI:"));
629   list=new FXListBox(spinframe,prefs,Settings::ID_SET_SEARCH_GUI,LIST_BOX_OPTS);
630   list->appendItem(_("above"),NULL,NULL);
631   list->appendItem(_("below"),NULL,NULL);
632   list->appendItem(_("float"),NULL,NULL);
633   list->setNumVisible(list->getNumItems());
634   list->setCurrentItem(prefs->SearchGui);
635 
636   new FXHorizontalSeparator(column,LAYOUT_SIDE_TOP|LAYOUT_FILL_X|SEPARATOR_GROOVE);
637   chk=new FXCheckButton(column, _("Open 7-bit ASCII files as UTF-8"), prefs, Settings::ID_TOGGLE_ASCII_DEFAULT);
638   chk->setCheck(!prefs->DefaultToAscii, false);
639   chk->setPadBottom(4);
640   chk=new FXCheckButton(column, _("Treat other files as broken UTF-8"), prefs, Settings::ID_TOGGLE_SBCS_DEFAULT);
641   chk->setCheck(!prefs->DefaultToSbcs, false);
642   chk->setPadBottom(8);
643   spinframe=new FXHorizontalFrame(column);
644   new FXLabel(spinframe, _("Default file format:"));
645   list=new FXListBox(spinframe,prefs,Settings::ID_SET_FILE_FORMAT,LIST_BOX_OPTS);
646   list->appendItem(_("DOS  [CRLF]"),NULL,NULL);
647   list->appendItem(_("Mac  [CR]"),NULL,NULL);
648   list->appendItem(_("Unix [LF]"),NULL,NULL);
649   list->setNumVisible(list->getNumItems());
650   list->setCurrentItem(prefs->DefaultFileFormat);
651 
652   chk=new FXCheckButton(column, _("Show line endings with \"View Whitespace\""),
653                           prefs, Settings::ID_TOGGLE_VIEW_WHITESPACE_EOL);
654   chk->setCheck(prefs->WhitespaceShowsEOL, false);
655   chk->setPadLeft(6);
656 }
657 
658 
659 
MakeThemeTab()660 void PrefsDialog::MakeThemeTab()
661 {
662   new FXTabItem(tabs,_("theme"));
663   Theme::MakeThemeGUI(tabs);
664 }
665 
666 
667 
onTabSwitch(FXObject * o,FXSelector sel,void * p)668 long PrefsDialog::onTabSwitch(FXObject*o,FXSelector sel,void*p)
669 {
670 
671   if (o==tabs) {
672     whichtab=(FXival)p;
673     hint_lab->setText(hint_list[whichtab]);
674   } else {
675     whichsyntab=(FXival)p;
676     hint_lab->setText(sntx_hint_list[whichsyntab]);
677   }
678   return 0;
679 }
680 
681 
682 
create()683 void PrefsDialog::create()
684 {
685   FXDialogBox::create();
686   SetupXAtoms(this, "prefs", APP_NAME);
687   show(PLACEMENT_DEFAULT);
688   acclist->setWidth((acclist->getParent()->getWidth()/3)*2);
689   acclist->setHeaderSize(0,(acclist->getWidth()/2)-8);
690   acclist->setHeaderSize(1,(acclist->getWidth()/2)-8);
691 #ifndef FOX_1_6
692   acclist->hide();
693   acclist->show();
694 #endif
695 }
696 
697 
698 
PrefsDialog(FXMainWindow * w,Settings * aprefs)699 PrefsDialog::PrefsDialog(FXMainWindow* w, Settings* aprefs):FXDialogBox(w->getApp(), "Preferences")
700 {
701   prefs=aprefs;
702   main_win=w;
703   setX(w->getX()+16);
704   setY(w->getY()+24);
705   setWidth(620);
706 
707   FXHorizontalFrame* buttons=new FXHorizontalFrame(this,LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X);
708   new FXButton(buttons,_("  &Close  "), NULL,this,ID_ACCEPT,FRAME_RAISED|FRAME_THICK|LAYOUT_CENTER_Y);
709 
710   hint_lab=new FXLabel(buttons, hint_list[0], NULL, LAYOUT_FILL_X);
711 
712   new FXHorizontalSeparator(this,SEPARATOR_GROOVE|LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X);
713   tabs=new ShadyTabs(this, this,ID_TAB_SWITCHED,FRAME_NONE|PACK_UNIFORM|LAYOUT_FILL);
714   MakeGeneralTab();
715   MakeEditorTab();
716   MakeSyntaxTab();
717   MakeKeybindingsTab();
718   MakeToolbarTab();
719   MakePopupTab();
720   MakeThemeTab();
721   tabs->setCurrent(whichtab,true);
722   tabs->childAtIndex(whichtab*2)->setFocus();
723   setIcon(w->getIcon());
724 }
725 
726