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 <fxkeys.h>
22
23 #include "compat.h"
24 #include "scidoc.h"
25 #include "scisrch.h"
26 #include "histbox.h"
27
28 #include "appwin_pub.h"
29
30 #include "intl.h"
31 #include "search.h"
32
33
34
35 #define SetPadLRTB(o,l,r,t,b) \
36 o->setPadLeft(l); \
37 o->setPadRight(r); \
38 o->setPadTop(t); \
39 o->setPadBottom(b);
40
41 #define SetPad(o,p) SetPadLRTB(o,p,p,p,p)
42
43
44
45 FXDEFMAP(SciSearchOptions) SciSearchOptionsMap[]={
46 FXMAPFUNC(SEL_COMMAND,SciSearchOptions::ID_TOGGLE_CHK,SciSearchOptions::onToggleChk),
47 };
48
49 FXIMPLEMENT(SciSearchOptions,FXHorizontalFrame,SciSearchOptionsMap,ARRAYNUMBER(SciSearchOptionsMap))
50
51
52 enum {
53 MODELIST_NORMAL,
54 MODELIST_REGEXP,
55 MODELIST_WHOLEWORD
56 };
57
SetSciFlags(FXuint n)58 void SciSearchOptions::SetSciFlags(FXuint n)
59 {
60 // Favor REGEXP over WHOLEWORD
61 if ( (n&SCFIND_WHOLEWORD) && (n&SCFIND_REGEXP) ) { n&=!SCFIND_WHOLEWORD; }
62 matchcase->setCheck((n & SCFIND_MATCHCASE)?1:0);
63 if (n & SCFIND_WHOLEWORD) {
64 modelist->setCurrentItem(MODELIST_WHOLEWORD);
65 } else if (n & SCFIND_REGEXP) {
66 modelist->setCurrentItem(MODELIST_REGEXP);
67 } else {
68 modelist->setCurrentItem(MODELIST_NORMAL);
69 }
70 }
71
72
73
onToggleChk(FXObject * o,FXSelector sel,void * p)74 long SciSearchOptions::onToggleChk(FXObject*o, FXSelector sel, void*p)
75 {
76 FXuval n=(FXuval)modelist->getItemData(modelist->getCurrentItem());
77 if ((o==modelist) && (modelist->getCurrentItem()==MODELIST_REGEXP)) { matchcase->setCheck(true); }
78 if (matchcase->getCheck()) { n|=SCFIND_MATCHCASE; }
79 if (target) { target->handle(this, FXSEL(SEL_COMMAND,message), (void*)(FXuval)n); }
80 return 1;
81 }
82
83
84
SciSearchOptions(FXComposite * p,FXObject * tgt,FXSelector sel)85 SciSearchOptions::SciSearchOptions(FXComposite *p, FXObject *tgt, FXSelector sel):FXHorizontalFrame(p, 0)
86 {
87 target=tgt;
88 message=sel;
89 new FXLabel(this,_(" M&ode:"));
90 modelist=new FXListBox(this,this,ID_TOGGLE_CHK);
91 modelist->appendItem(FXString::null);
92 modelist->appendItem(FXString::null);
93 modelist->appendItem(FXString::null);
94 modelist->setNumVisible(modelist->getNumItems());
95 modelist->setItem(MODELIST_NORMAL, _("normal"), NULL, (void*)(FXuval)0);
96 modelist->setItem(MODELIST_REGEXP, _("reg. expr."), NULL, (void*)(FXuval)SCFIND_REGEXP);
97 modelist->setItem(MODELIST_WHOLEWORD, _("whole word"), NULL, (void*)(FXuval)SCFIND_WHOLEWORD);
98 matchcase = new FXCheckButton(this, _("&Match case "), this, ID_TOGGLE_CHK);
99 }
100
101
102
103 class SciReplGui: public FXMatrix {
104 FXDECLARE(SciReplGui)
SciReplGui()105 SciReplGui(){}
106 private:
107 FXVerticalFrame *txt_fields;
108 FXVerticalFrame *btn_ctrls;
109 FXLabel*srch_lab;
110 HistoryTextField*srch_hist;
111 FXLabel*repl_lab;
112 HistoryTextField*repl_hist;
113 SciSearchOptions*opts;
114 FXCheckButton* rev_chk;
115 FXuint sciflags;
116 FXHorizontalFrame *btns;
117 FXButton*fwd_btn;
118 FXButton*bwd_btn;
119 FXButton*cncl_btn;
120 FXButton*repall_indoc_btn;
121 FXButton*repall_insel_btn;
122 FXButton*repl_once_btn;
123 FXObject*target;
124 FXSelector message;
125 void EnableSearch();
126 public:
127 SciReplGui(FXComposite*p, FXObject*tgt, FXSelector sel, bool find_only, bool floating);
~SciReplGui()128 ~SciReplGui() { target=NULL; stop(DONE); }
129 void stop(FXuint stopval);
130 long onSciOpts(FXObject*o, FXSelector sel, void*p);
131 long onSrchHist(FXObject*o, FXSelector sel, void*p);
132 long onButton(FXObject*o, FXSelector sel, void*p);
133 long onFakeBtnUp(FXObject*o, FXSelector sel, void*p);
134
135 long onKeyPress(FXObject*o, FXSelector sel, void*p);
136 long onConfigure(FXObject*o, FXSelector sel, void*p);
137 long onFocusIn(FXObject*o, FXSelector sel, void*p);
138
139 void setSearchText(const FXString& text);
140 FXString getSearchText() const;
141 void setReplaceText(const FXString& text);
142 FXString getReplaceText() const;
143 void setHaveSelection(bool have_sel);
getSearchMode()144 FXuint getSearchMode() { return sciflags; }
145 void setSearchMode(FXuint mode);
getSearchReverse()146 FXuint getSearchReverse() { return rev_chk->getCheck(); }
setSearchReverse(bool reverse)147 void setSearchReverse(bool reverse) { rev_chk->setCheck(reverse); }
148 void AppendHist(const FXString& search,const FXString& replace,FXuint mode);
149 void DoExecute();
150 void HandleKeyPress(FXEvent*ev);
151 virtual void create();
152 virtual void destroy();
153 enum {
154 ID_SCI_OPTS=1,
155 ID_SRCH_HIST,
156 ID_REPL_HIST,
157 ID_PREV,
158 ID_NEXT,
159 ID_REPLACE,
160 ID_ALL_INDOC,
161 ID_ALL_INSEL,
162 ID_CANCEL_SRCH,
163 ID_REV_CHK,
164 ID_FAKE_BTN_UP,
165 ID_LAST
166 };
167 enum {
168 DONE = 0, // Cancel search
169 SEARCH = 1, // Search first occurrence
170 SEARCH_NEXT = 2, // Search next occurrence
171 REPL_ALL_INDOC = 3, // Replace all occurrences in document
172 REPL_ALL_INSEL = 4 // Replace all occurrences in selection
173 };
174 };
175
176
177
178 FXDEFMAP(SciReplGui) SciReplGuiMap[]={
179 FXMAPFUNC( SEL_COMMAND, SciReplGui::ID_SCI_OPTS, SciReplGui::onSciOpts),
180 FXMAPFUNCS( SEL_COMMAND, SciReplGui::ID_SRCH_HIST, SciReplGui::ID_REPL_HIST, SciReplGui::onSrchHist),
181 FXMAPFUNC( SEL_CHANGED, SciReplGui::ID_SRCH_HIST, SciReplGui::onSrchHist),
182 FXMAPFUNC( SEL_PICKED, SciReplGui::ID_SRCH_HIST, SciReplGui::onSrchHist),
183 FXMAPFUNCS( SEL_COMMAND, SciReplGui::ID_PREV, SciReplGui::ID_CANCEL_SRCH, SciReplGui::onButton),
184 FXMAPFUNC( SEL_TIMEOUT, SciReplGui::ID_FAKE_BTN_UP, SciReplGui::onFakeBtnUp),
185 FXMAPFUNC( SEL_KEYPRESS, 0, SciReplGui::onKeyPress),
186 FXMAPFUNC( SEL_CONFIGURE, 0, SciReplGui::onConfigure),
187 FXMAPFUNC( SEL_FOCUSIN, 0, SciReplGui::onFocusIn),
188 };
189
190 FXIMPLEMENT(SciReplGui,FXMatrix,SciReplGuiMap,ARRAYNUMBER(SciReplGuiMap))
191
192
193
194 #define ICO_SIZE 8
195
196 static const char close_icon[] =
197 "X_____X_"
198 "_X___X__"
199 "__X_X___"
200 "___X____"
201 "__X_X___"
202 "_X___X__"
203 "X_____X_"
204 "________"
205 ;
206
207
SciReplGui(FXComposite * p,FXObject * tgt,FXSelector sel,bool find_only,bool floating)208 SciReplGui::SciReplGui(FXComposite*p, FXObject*tgt, FXSelector sel, bool find_only, bool floating):FXMatrix(p,2)
209 {
210 sciflags=0;
211 target=tgt;
212 message=sel;
213 setLayoutHints(floating?LAYOUT_FILL:LAYOUT_FILL_X);
214 setMatrixStyle(floating?MATRIX_BY_ROWS:MATRIX_BY_COLUMNS);
215 setFrameStyle(floating?FRAME_NONE:FRAME_GROOVE);
216 FXuint textopts=TEXTFIELD_ENTER_ONLY|FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X;
217 const char*group=find_only?"Search":"Replace";
218
219 txt_fields=new FXVerticalFrame(this,FRAME_NONE|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
220 btn_ctrls=new FXVerticalFrame(this,FRAME_NONE);
221
222 SetPad(txt_fields,0);
223
224 srch_lab=new FXLabel(txt_fields, _("Se&arch for:"));
225 srch_hist=new HistoryTextField(txt_fields,48,group,"SM",this,ID_SRCH_HIST,textopts);
226 if (find_only) {
227 repl_hist=NULL;
228 } else {
229 repl_lab=new FXLabel(txt_fields, _("Replace &with:"));
230 repl_hist=new HistoryTextField(txt_fields,48,group,"R",this,ID_REPL_HIST,textopts);
231 }
232
233 SetPad(btn_ctrls,0);
234
235 opts=new SciSearchOptions(btn_ctrls,this,ID_SCI_OPTS);
236 rev_chk=new FXCheckButton(opts, _("&Backward"),this,ID_REV_CHK);
237 srch_hist->setWatch(&sciflags);
238
239 btns=new FXHorizontalFrame(btn_ctrls,LAYOUT_FILL_X);
240 FXHorizontalFrame*nav_btns=new FXHorizontalFrame(btns);
241 SetPadLRTB(nav_btns,DEFAULT_SPACING,DEFAULT_SPACING*2,0,0);
242 bwd_btn=new FXButton(nav_btns," &< ",NULL,this,ID_PREV);
243 fwd_btn=new FXButton(nav_btns," &> ",NULL,this,ID_NEXT);
244 if (find_only) {
245 repl_once_btn=new FXButton(btns,_("F&ind"),NULL,this,ID_REPLACE);
246 repall_indoc_btn=NULL;
247 repall_insel_btn=NULL;
248 } else {
249 repl_once_btn=new FXButton(btns,_("Rep&lace"),NULL,this,ID_REPLACE);
250 repall_indoc_btn=new FXButton(btns,_("Re&place All"),NULL,this,ID_ALL_INDOC);
251 repall_insel_btn=new FXButton(btns,_("All in Sele&cted"),NULL,this,ID_ALL_INSEL);
252 }
253
254 if (!floating) {
255 FXVerticalFrame*cncl_box=new FXVerticalFrame(btns,LAYOUT_RIGHT|LAYOUT_SIDE_BOTTOM|PACK_UNIFORM_HEIGHT|LAYOUT_FILL_Y);
256 cncl_box->setVSpacing(0);
257 SetPad(cncl_box,0);
258 cncl_btn=new FXButton(cncl_box,FXString::null,NULL,this,ID_CANCEL_SRCH,BUTTON_NORMAL|LAYOUT_BOTTOM);
259 if (!find_only) {
260 new FXVerticalFrame(cncl_box,FRAME_NONE);
261 FXHorizontalFrame*cncl_frm=new FXHorizontalFrame(btn_ctrls,LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_SIDE_BOTTOM);
262 SetPad(cncl_frm,0);
263 cncl_box->reparent(cncl_frm);
264 }
265 cncl_btn->setTipText(_("Close {ESC}"));
266 FXColor ico_buf[ICO_SIZE*ICO_SIZE];
267 FXColor bg=cncl_btn->getBackColor();
268 FXColor fg=cncl_btn->getTextColor();
269 for (FXint i=0; i<ICO_SIZE*ICO_SIZE; i++) { ico_buf[i]=close_icon[i]=='_'?bg:fg; }
270 FXIcon *ico=new FXIcon(cncl_btn->getApp(),ico_buf,0,IMAGE_OPAQUE,ICO_SIZE,ICO_SIZE);
271 ico->create();
272 cncl_btn->setIcon(ico);
273 } else {
274 btn_ctrls->setLayoutHints(LAYOUT_FILL_X);
275 new FXHorizontalFrame(btns,LAYOUT_FILL_X);
276 cncl_btn=new FXButton(btns,_("Close"),NULL,this,ID_CANCEL_SRCH,BUTTON_NORMAL|LAYOUT_BOTTOM);
277 }
278 SetPad(btns,0);
279 if (repl_hist) { srch_hist->enslave(repl_hist); }
280 setSearchText(FXString::null);
281 }
282
283
284
AppendHist(const FXString & search,const FXString & replace,FXuint mode)285 void SciReplGui::AppendHist(const FXString& search,const FXString& replace,FXuint mode)
286 {
287 FXString tmp;
288 FXuint oldmode=sciflags;
289 sciflags=mode;
290 if (!search.empty()) {
291 tmp=getSearchText();
292 setSearchText(search);
293 srch_hist->append();
294 setSearchText(tmp);
295 }
296 if (!replace.empty()) {
297 tmp=getReplaceText();
298 setReplaceText(replace);
299 if (repl_hist) { repl_hist->append(); }
300 setSearchText(tmp);
301 }
302 sciflags=oldmode;
303 }
304
305
306
stop(FXuint stopval)307 void SciReplGui::stop(FXuint stopval)
308 {
309 srch_hist->append();
310 if (repl_hist) { repl_hist->append(); }
311 if (target) { target->handle(this,FXSEL(SEL_COMMAND,message),(void*)(FXuval)stopval); }
312 }
313
314
315
onFakeBtnUp(FXObject * o,FXSelector sel,void * p)316 long SciReplGui::onFakeBtnUp(FXObject*o, FXSelector sel, void*p)
317 {
318 ((FXButton*)p)->setState(STATE_UP);
319 return 0;
320 }
321
322
323
onButton(FXObject * o,FXSelector sel,void * p)324 long SciReplGui::onButton(FXObject*o, FXSelector sel, void*p)
325 {
326 if ( getSearchText().empty() && (FXSELID(sel)!=ID_CANCEL_SRCH) ) { return 0; }
327 FXButton*btn=NULL;
328 switch (FXSELID(sel)) {
329 case ID_PREV:
330 {
331 rev_chk->setCheck(true);
332 btn=bwd_btn;
333 stop(SEARCH_NEXT);
334 break;
335 }
336 case ID_NEXT:
337 {
338 rev_chk->setCheck(false);
339 btn=fwd_btn;
340 stop(SEARCH_NEXT);
341 break;
342 }
343 case ID_REPLACE: {
344 stop(SEARCH);
345 break;
346 }
347 case ID_ALL_INDOC: {
348 stop(REPL_ALL_INDOC);
349 break;
350 }
351 case ID_ALL_INSEL: {
352 stop(REPL_ALL_INSEL);
353 break;
354 }
355 case ID_CANCEL_SRCH: {
356 stop(DONE);
357 break;
358 }
359 default: {return 0; }
360 }
361 if (btn && !o) { // If sender was NULL, fake the appearance of a button press.
362 btn->setFocus();
363 btn->setState(STATE_DOWN);
364 btn->update();
365 btn->getApp()->addTimeout(this,ID_FAKE_BTN_UP,ONE_SECOND/10,(void*)btn);
366 }
367 return 1;
368 }
369
370
371
HandleKeyPress(FXEvent * ev)372 void SciReplGui::HandleKeyPress(FXEvent*ev)
373 {
374 switch (ev->code) {
375 case KEY_less:
376 case KEY_comma: {
377 if (ev->state&ALTMASK) { handle(NULL,FXSEL(SEL_COMMAND,SciReplGui::ID_PREV),NULL); }
378 break;
379 }
380 case KEY_period:
381 case KEY_greater: {
382 if (ev->state&ALTMASK) { handle(NULL,FXSEL(SEL_COMMAND,SciReplGui::ID_NEXT),NULL); }
383 break;
384 }
385 case KEY_Escape: {
386 stop(SciReplGui::DONE);
387 break;
388 }
389 }
390 }
391
392
393
EnableSearch()394 void SciReplGui::EnableSearch()
395 {
396 if (srch_hist->getText().empty()) {
397 bwd_btn->disable();
398 fwd_btn->disable();
399 repl_once_btn->disable();
400 if (repall_indoc_btn) { repall_indoc_btn->disable(); }
401 if (repall_insel_btn) { repall_insel_btn->disable(); }
402 } else {
403 bwd_btn->enable();
404 fwd_btn->enable();
405 repl_once_btn->enable();
406 if (repall_indoc_btn) { repall_indoc_btn->enable(); }
407 if (repall_insel_btn) { repall_insel_btn->enable(); }
408 }
409 }
410
411
412
onSrchHist(FXObject * o,FXSelector sel,void * p)413 long SciReplGui::onSrchHist(FXObject*o, FXSelector sel, void*p)
414 {
415 if (FXSELID(sel)!=ID_SRCH_HIST) { return 0; }
416 switch (FXSELTYPE(sel)) {
417 case SEL_CHANGED: {
418 EnableSearch();
419 return 1;
420 }
421 case SEL_PICKED: {
422 sciflags=(FXuint)((FXival)p);
423 opts->SetSciFlags(sciflags);
424 EnableSearch();
425 return 1;
426 }
427 case SEL_COMMAND: {
428 if (!getSearchText().empty()) {
429 if (repl_hist && repl_hist->isEnabled()) {
430 repl_hist->setFocus();
431 } else {
432 stop(SEARCH);
433 }
434 }
435 return 1;
436 }
437 default: return 0;
438 }
439 }
440
441
442
onSciOpts(FXObject * o,FXSelector sel,void * p)443 long SciReplGui::onSciOpts(FXObject*o, FXSelector sel, void*p)
444 {
445 sciflags=(FXuint)((FXival)p);
446 return 1;
447 }
448
449
450
onConfigure(FXObject * o,FXSelector sel,void * p)451 long SciReplGui::onConfigure(FXObject*o, FXSelector sel, void*p)
452 {
453 setLayoutHints((getDefaultWidth()>getParent()->getWidth())?LAYOUT_FILL_X:0);
454 return FXMatrix::onConfigure(o,sel,p);
455 }
456
457
458
onKeyPress(FXObject * o,FXSelector sel,void * p)459 long SciReplGui::onKeyPress(FXObject*o, FXSelector sel, void*p)
460 {
461 HandleKeyPress(((FXEvent*)p));
462 return FXMatrix::onKeyPress(o,sel,p);
463 }
464
465
466
onFocusIn(FXObject * o,FXSelector sel,void * p)467 long SciReplGui::onFocusIn(FXObject*o, FXSelector sel, void*p)
468 {
469 FXMatrix::onFocusIn(o,sel,p);
470 TopWinPub::ActiveWidget(id());
471 return 1;
472 }
473
474
475
setSearchText(const FXString & text)476 void SciReplGui::setSearchText(const FXString& text)
477 {
478 srch_hist->setText(text);
479 EnableSearch();
480 }
481
482
483
getSearchText() const484 FXString SciReplGui::getSearchText() const
485 {
486 return srch_hist->getText();
487 }
488
489
490
setReplaceText(const FXString & text)491 void SciReplGui::setReplaceText(const FXString& text)
492 {
493 if (repl_hist) { repl_hist->setText(text); }
494 }
495
496
497
getReplaceText() const498 FXString SciReplGui::getReplaceText() const
499 {
500 return repl_hist?repl_hist->getText():FXString::null;
501 }
502
503
504
setHaveSelection(bool have_sel)505 void SciReplGui::setHaveSelection(bool have_sel)
506 {
507 if (repall_insel_btn) {
508 if (have_sel) { repall_insel_btn->enable(); } else { repall_insel_btn->disable(); }
509 }
510 }
511
512
513
setSearchMode(FXuint mode)514 void SciReplGui::setSearchMode(FXuint mode)
515 {
516 sciflags=mode;
517 opts->SetSciFlags(mode);
518 }
519
520
521
create()522 void SciReplGui::create()
523 {
524 FXMatrix::create();
525 srch_hist->setFocus();
526 }
527
528
529
destroy()530 void SciReplGui::destroy()
531 {
532 srch_hist->killSelection();
533 if (repl_hist) repl_hist->killSelection();
534 }
535
536
537
DoExecute()538 void SciReplGui::DoExecute()
539 {
540 if ( (!bwd_btn->hasFocus())&&!fwd_btn->hasFocus() ) { srch_hist->setFocus(); }
541 srch_hist->start();
542 if (repl_hist) { repl_hist->start(); }
543 }
544
545
546
547
548 class MainPanel: public FXHorizontalFrame {
549 FXDECLARE(MainPanel)
MainPanel()550 MainPanel() {}
551 public:
onConfigure(FXObject * o,FXSelector sel,void * p)552 long onConfigure(FXObject*o, FXSelector sel, void*p) {
553 for (FXWindow*w=getFirst(); w; w=w->getNext()) { w->handle(o,sel,p); }
554 return FXHorizontalFrame::onConfigure(o,sel,p);
555 }
MainPanel(FXComposite * p)556 MainPanel(FXComposite *p):FXHorizontalFrame(p,FRAME_NONE|LAYOUT_FILL_X) { setBaseColor(FXRGB(255,0,0)); }
557 };
558
559
560
561 FXDEFMAP(MainPanel) MainPanelMap[]={
562 FXMAPFUNC(SEL_CONFIGURE, 0, MainPanel::onConfigure)
563 };
564
565 FXIMPLEMENT(MainPanel,FXHorizontalFrame,MainPanelMap,ARRAYNUMBER(MainPanelMap));
566
567
568
569 static FXint srch_dlg_box_prev_x=0;
570 static FXint srch_dlg_box_prev_y=0;
571 static bool srch_dlg_box_placed=false;
572
573
574 class SrchDlgBox:public FXDialogBox {
575 public:
SrchDlgBox(FXWindow * o)576 SrchDlgBox(FXWindow*o):FXDialogBox(o,FXString::null) {}
show()577 virtual void show() {
578 if (srch_dlg_box_placed) {
579 position(srch_dlg_box_prev_x,srch_dlg_box_prev_y,getFirst()->getDefaultWidth(),getFirst()->getDefaultHeight());
580 FXDialogBox::show();
581 } else {
582 resize(getFirst()->getDefaultWidth(),getFirst()->getDefaultHeight());
583 FXDialogBox::show(PLACEMENT_OWNER);
584 }
585 srch_dlg_box_placed=true;
586 raise();
587 }
show(FXuint placement)588 virtual void show(FXuint placement) { SrchDlgBox::show(); }
hide()589 virtual void hide() {
590 srch_dlg_box_prev_x=getX();
591 srch_dlg_box_prev_y=getY();
592 FXDialogBox::hide();
593 }
destroy()594 virtual void destroy() {
595 srch_dlg_box_prev_x=getX();
596 srch_dlg_box_prev_y=getY();
597 FXDialogBox::destroy();
598 }
599 };
600
601
602
603 FXDEFMAP(SearchDialogs) SearchDialogsMap[] = {
604 FXMAPFUNC(SEL_COMMAND, SearchDialogs::ID_SEARCH, SearchDialogs::onSearch),
605 FXMAPFUNC(SEL_CHORE, SearchDialogs::ID_SEARCH_DONE, SearchDialogs::onSearchDone),
606 };
607
608 FXIMPLEMENT(SearchDialogs, FXObject, SearchDialogsMap, ARRAYNUMBER(SearchDialogsMap));
609
610
SearchDialogs(FXComposite * p,FXObject * trg,FXSelector sel)611 SearchDialogs::SearchDialogs(FXComposite*p, FXObject*trg, FXSelector sel) {
612 defaultsearchmode=0;
613 searchdirn=SCI_SEARCHNEXT;
614 searchstring=FXString::null;
615 target=trg;
616 message=sel;
617 parent=p;
618 find_initial=true;
619 repl_initial=true;
620 srchdlg=NULL;
621 srchpan=NULL;
622 repl_gui=NULL;
623 find_gui=NULL;
624 }
625
626
627
SetGuiStyle(FXuint style)628 void SearchDialogs::SetGuiStyle(FXuint style)
629 {
630 delete repl_gui;
631 repl_gui=NULL;
632 delete find_gui;
633 find_gui=NULL;
634 gui_style=(SearchDialogStyle)style;
635 if (style==SEARCH_GUI_FLOAT) {
636 if (!srchdlg) { srchdlg=new SrchDlgBox(parent->getShell()); }
637 SetPad(srchdlg,0);
638 container=srchdlg;
639 delete srchpan;
640 srchpan=NULL;
641 } else {
642 if (!srchpan) { srchpan=new MainPanel(parent); }
643 SetPad(srchpan,0);
644 container=srchpan;
645 delete srchdlg;
646 srchdlg=NULL;
647 }
648 }
649
650
651
~SearchDialogs()652 SearchDialogs::~SearchDialogs()
653 {
654 delete repl_gui;
655 repl_gui=NULL;
656 if (hist_queue.no()) {
657 if (!find_gui) {
658 find_gui=new SciReplGui(container, this, ID_SEARCH, true, container==srchdlg);
659 }
660 SaveHistoryQueue();
661 }
662 delete find_gui;
663 find_gui=NULL;
664 }
665
666
667
SetPrefs(FXuint mode,FXuint wrap,bool verbose,FXuint style)668 void SearchDialogs::SetPrefs(FXuint mode, FXuint wrap, bool verbose, FXuint style)
669 {
670 searchmode=mode;
671 defaultsearchmode=mode;
672 searchwrap=(SearchWrapPolicy)wrap;
673 searchverbose=verbose;
674 SetGuiStyle(style);
675 }
676
677
678
SearchFailed(FXWindow * w)679 void SearchDialogs::SearchFailed(FXWindow*w)
680 {
681 FXMessageBox::error(w->getShell(), MBOX_OK, _("Not found"), "%s.", _("Search term not found"));
682 }
683
684
685
SearchFailed()686 bool SearchDialogs::SearchFailed()
687 {
688 if (searchverbose) { SearchFailed(parent); }
689 return false;
690 }
691
692
SearchWrapAsk(FXWindow * w)693 bool SearchDialogs::SearchWrapAsk(FXWindow*w)
694 {
695 return (FXMessageBox::question(w->getShell(), MBOX_YES_NO, _("Wrap search?"), "%s:\n%s",
696 _("Search term not found"),
697 _("Wrap search and try again?"))==MBOX_CLICKED_YES);
698 }
699
700
701
SaveHistoryQueue()702 void SearchDialogs::SaveHistoryQueue()
703 {
704 for (FXint i=0; i<hist_queue.no(); i++) {
705 FXString*s=(FXString*)hist_queue[i];
706 find_gui->AppendHist(*s, FXString::null, defaultsearchmode);
707 delete s;
708 hist_queue[i]=NULL;
709 }
710 hist_queue.clear();
711 }
712
713
714
ShowFindDialog()715 void SearchDialogs::ShowFindDialog()
716 {
717 delete repl_gui;
718 repl_gui=NULL;
719 if (!find_gui) {
720 find_gui=new SciReplGui(container, this, ID_SEARCH, true, container==srchdlg);
721 SaveHistoryQueue();
722 container->create();
723 if (srchdlg) {
724 srchdlg->setTitle(_("Search"));
725 } else {
726 srchpan->reparent(parent,(gui_style==SEARCH_GUI_ABOVE)?parent->getFirst():NULL);
727 }
728 } else {
729 find_gui->setSearchText(FXString::null);
730 }
731 if (srchdlg) {
732 srchdlg->hide();
733 srchdlg->show();
734 }
735 parent->layout();
736 find_gui->setFocus();
737 find_gui->setSearchMode(searchmode);
738 find_gui->DoExecute();
739 }
740
741
742
ShowReplaceDialog()743 void SearchDialogs::ShowReplaceDialog()
744 {
745 delete find_gui;
746 find_gui=NULL;
747 if (!repl_gui) {
748 repl_gui=new SciReplGui(container, this, ID_SEARCH, false, container==srchdlg);
749 container->create();
750 if (srchdlg) {
751 srchdlg->setTitle(_("Replace"));
752 srchdlg->show();
753 } else {
754 srchpan->reparent(parent,(gui_style==SEARCH_GUI_ABOVE)?parent->getFirst():NULL);
755 }
756 }
757 if (srchdlg) {
758 srchdlg->hide();
759 srchdlg->show();
760 }
761 repl_gui->setSearchMode(searchmode);
762 repl_ready=false;
763 repl_gui->setHaveSelection(TopWinPub::FocusedDoc()->GetSelLength()>0);
764 repl_gui->DoExecute();
765 repl_initial=false;
766 }
767
768
769
FindText(bool forward,bool wrap)770 bool SearchDialogs::FindText(bool forward, bool wrap)
771 {
772 SciDoc*sci=TopWinPub::FocusedDoc();
773 if (sci->search->FindText(searchstring,searchmode,forward,wrap)) {
774 if (target) { target->handle(this,FXSEL(SEL_COMMAND,message),NULL); }
775 return true;
776 } else {
777 return false;
778 }
779 }
780
781
782
DoFind(bool forward)783 bool SearchDialogs::DoFind(bool forward)
784 {
785 SciDoc*sci=TopWinPub::FocusedDoc();
786 searchdirn=forward?SCI_SEARCHNEXT:SCI_SEARCHPREV; // <= this is only used for the macro recorder
787 switch (searchwrap) {
788 case SEARCH_WRAP_NEVER: {
789 return FindText(forward,false)?true:SearchFailed();
790 }
791 case SEARCH_WRAP_ALWAYS: {
792 return FindText(forward,true)?true:SearchFailed();
793 }
794 case SEARCH_WRAP_ASK: {
795 if (FindText(forward,false)) { return true; }
796 long pos=sci->sendMessage(SCI_GETCURRENTPOS,0,0);
797 if (forward) {
798 if (pos==0) { return SearchFailed(); }
799 } else {
800 if (pos==sci->sendMessage(SCI_GETLENGTH,0,0)) { return SearchFailed(); }
801 }
802 if (SearchWrapAsk(parent)) { return (FindText(forward,true))?true:SearchFailed(); }
803 }
804 default: { return false; }
805 }
806 }
807
808
809
FindNext()810 void SearchDialogs::FindNext()
811 {
812 searchmode &= ~SEARCH_BACKWARD;
813 if (searchstring.empty()) {
814 ShowFindDialog();
815 } else {
816 DoFind(true);
817 }
818 }
819
820
821
FindPrev()822 void SearchDialogs::FindPrev()
823 {
824 searchmode |= SEARCH_BACKWARD;
825 if (searchstring.empty()) {
826 ShowFindDialog();
827 } else {
828 DoFind(false);
829 }
830 }
831
832
833
FindPhrase(const char * searchfor,FXuint mode,bool forward)834 void SearchDialogs::FindPhrase(const char* searchfor, FXuint mode, bool forward)
835 {
836 searchstring=searchfor;
837 searchmode=mode;
838 if (forward) { FindNext(); } else { FindPrev(); }
839 }
840
841
842
FindAndReplace(const char * searchfor,const char * replacewith,FXuint mode,bool forward)843 void SearchDialogs::FindAndReplace(const char*searchfor, const char*replacewith, FXuint mode, bool forward)
844 {
845 searchstring=searchfor;
846 replacestring=replacewith;
847 searchmode=mode;
848 repl_ready=false;
849 NextReplace(SciReplGui::SEARCH,forward);
850 }
851
852
853
ReplaceAllInSelection(const char * searchfor,const char * replacewith,FXuint mode)854 void SearchDialogs::ReplaceAllInSelection(const char*searchfor, const char*replacewith, FXuint mode)
855 {
856 searchstring=searchfor;
857 replacestring=replacewith;
858 searchmode=mode;
859 NextReplace(SciReplGui::REPL_ALL_INSEL,true);
860 }
861
862
863
ReplaceAllInDocument(const char * searchfor,const char * replacewith,FXuint mode)864 void SearchDialogs::ReplaceAllInDocument(const char*searchfor, const char*replacewith, FXuint mode)
865 {
866 searchstring=searchfor;
867 replacestring=replacewith;
868 searchmode=mode;
869 NextReplace(SciReplGui::REPL_ALL_INDOC,true);
870 }
871
872
873
GetPrimarySelection(SciDoc * sci,FXString & target)874 bool GetPrimarySelection(SciDoc*sci, FXString&target)
875 {
876 return sci->getShell()->getDNDData(FROM_SELECTION,FXWindow::stringType, target);
877 }
878
879
880
FindSelected(bool forward)881 void SearchDialogs::FindSelected(bool forward)
882 {
883 SciDoc*sci=TopWinPub::FocusedDoc();
884 FXString srch=FXString::null;
885 if (!GetPrimarySelection(sci,srch)) {
886 if (sci->GetSelLength()>0) { sci->GetSelText(srch); }
887 }
888 if (!srch.empty()) {
889 searchmode=defaultsearchmode;
890 searchstring=srch;
891 DoFind(forward);
892 if (find_gui) {
893 find_gui->AppendHist(searchstring, FXString::null, defaultsearchmode);
894 find_gui->setSearchText(srch);
895 } else {
896 hist_queue.append((FXObject*)(new FXString(searchstring)));
897 }
898 }
899 }
900
901
902
GoToSelected()903 bool SearchDialogs::GoToSelected()
904 {
905 SciDoc*sci=TopWinPub::FocusedDoc();
906 FXString tmp;
907 if (sci && GetPrimarySelection(sci,tmp)) {
908 tmp.trim();
909 return sci->GoToStringCoords(tmp.text());
910 } else {
911 return false;
912 }
913 }
914
915
916
ShowGoToDialog()917 bool SearchDialogs::ShowGoToDialog()
918 {
919 SciDoc*sci=TopWinPub::FocusedDoc();
920 FXInputDialog dlg(sci->getShell(),_("Go to line"), _("Enter line number\n(or line:column)"));
921 bool rv=dlg.execute(PLACEMENT_OWNER);
922 if (rv) { sci->GoToStringCoords(dlg.getText().text()); }
923 sci->setFocus();
924 return rv;
925 }
926
927
928
NextSearch(FXuint code)929 FXuint SearchDialogs::NextSearch(FXuint code)
930 {
931 searchstring=find_gui->getSearchText();
932 searchmode=find_gui->getSearchMode();
933 if (code!=SciReplGui::DONE) {
934 find_initial=false;
935 switch(code) {
936 case SciReplGui::DONE:{
937 break;
938 }
939 case SciReplGui::SEARCH:
940 case SciReplGui::SEARCH_NEXT: {
941 DoFind(!find_gui->getSearchReverse());
942 break;
943 }
944 }
945 }
946 TopWinPub::FocusedDoc()->update();
947 return code;
948 }
949
950
951
NextReplace(FXuint code,bool forward)952 FXuint SearchDialogs::NextReplace(FXuint code, bool forward)
953 {
954 SciDoc*sci=TopWinPub::FocusedDoc();
955 switch (code) {
956 case SciReplGui::SEARCH:{ // Replace selection
957 if (!repl_ready) { repl_ready=DoFind(forward); }
958 if (repl_ready) {
959 sci->search->ReplaceSelection(replacestring,searchmode);
960 repl_ready=false;
961 }
962 break;
963 }
964 case SciReplGui::SEARCH_NEXT:{ // Find next
965 repl_ready=DoFind(forward);
966 break;
967 }
968 case SciReplGui::REPL_ALL_INDOC:{ // Replace all
969 if (sci->search->ReplaceAllInDoc(searchstring, replacestring, searchmode)==0) {
970 SearchFailed();
971 }
972 break;
973 }
974 case SciReplGui::REPL_ALL_INSEL: { // Replace all in selection
975 if (sci->search->ReplaceAllInSel(searchstring,replacestring,searchmode)==0) {
976 SearchFailed();
977 }
978 break;
979 }
980 default:{ // Cancel
981 break;
982 }
983 }
984 return code;
985 }
986
987
988
onSearchDone(FXObject * o,FXSelector sel,void * p)989 long SearchDialogs::onSearchDone(FXObject*o, FXSelector sel, void *p)
990 {
991 SciReplGui**gui=(SciReplGui**)p;
992 delete *gui;
993 *gui=NULL;
994 TopWinPub::FocusedDoc()->setFocus();
995 return 1;
996 }
997
998
999
onSearch(FXObject * o,FXSelector sel,void * p)1000 long SearchDialogs::onSearch(FXObject*o, FXSelector sel, void *p)
1001 {
1002 FXuint code=(FXuint)(FXuval)p;
1003 if (repl_gui) {
1004 if (code==SciReplGui::DONE) {
1005 container->getApp()->addChore(this,ID_SEARCH_DONE,&repl_gui);
1006 } else {
1007 searchmode=repl_gui->getSearchMode();
1008 searchstring=repl_gui->getSearchText();
1009 replacestring=repl_gui->getReplaceText();
1010 NextReplace(code,!repl_gui->getSearchReverse());
1011 }
1012 } else {
1013 switch (code) {
1014 case SciReplGui::SEARCH:
1015 case SciReplGui::SEARCH_NEXT: {
1016 NextSearch(code);
1017 break;
1018 }
1019 case SciReplGui::DONE: {
1020 container->getApp()->addChore(this,ID_SEARCH_DONE,&find_gui);
1021 break;
1022 }
1023 }
1024 }
1025 if (srchdlg&&(code==SciReplGui::DONE)) { srchdlg->hide(); }
1026 return 1;
1027 }
1028
1029
1030
setHaveSelection(bool have_sel)1031 void SearchDialogs::setHaveSelection(bool have_sel)
1032 {
1033 if (repl_gui) { repl_gui->setHaveSelection(have_sel); }
1034 }
1035
1036
1037
hide()1038 void SearchDialogs::hide()
1039 {
1040 delete repl_gui;
1041 repl_gui=NULL;
1042 delete find_gui;
1043 find_gui=NULL;
1044 if (srchdlg) { srchdlg->hide(); }
1045 }
1046
1047