2 #include "motormanager.h"
3 #include "motordebugger.h"
4 #include "motorconfiguration.h"
10 #include "uiwatcher.h"
11 #include "uiregexper.h"
23 #define LOOKER_HEIGHT (LINES-2)
24 #define OUTLINES_LIMIT 512
25 #define NULL_CONST_STR ((const char *) 0)
27 #define getcolor(c) uiconf.getcolor(c)
29 ncursesui::ncursesui(): terminate(false), outopen(false) {
32 ncursesui::~ncursesui() {
35 for(INT i
= 0; i
< LINES
; i
++) cout
<< endl
;
39 void ncursesui::sighandler(int signum
) {
42 while(wait3(0, WNOHANG
, 0) > 0);
46 signal(SIGCHLD
, &sighandler
);
47 signal(SIGINT
, &sighandler
);
50 void ncursesui::execute(INT argc
, char **argv
) {
59 commandline(argc
, argv
);
60 outwindow
= textwindow(0, 1, COLS
, LOOKER_HEIGHT
, normalcolor(0), TW_SPACEBORDER
);
65 if(project
.empty()) pload();
67 if(!project
.empty()) {
72 terminate
= project
.close();
79 void ncursesui::pload(const projectname pname
) {
80 projectname nname
= pname
;
84 for(fin
= false; !fin
; ) {
86 nname
= selectproject(selectorcreate
);
89 if(!(fin
= nname
.empty())) {
90 np
= motorproject(nname
);
94 project
= motorproject(static_cast<projectname
> (np
));
100 nname
= projectname();
103 terminate
= project
.empty();
106 motorui::askresult
ncursesui::ask(const string
&answersallowed
, const string
&text
) {
107 INT line
= /*watcher.visible() ? LINES-uiconf.getwatchlines()-2 :*/ LINES
-2;
108 screenarea
sarea(0, line
, COLS
, line
);
110 string::const_iterator c
;
113 attrset(getcolor(cp_input
));
114 mvhline(line
, 0, ' ', COLS
);
117 for(c
= answersallowed
.begin(); c
!= answersallowed
.end(); c
++) {
118 msg
+= c
!= answersallowed
.begin() ? tolower(*c
) : toupper(*c
);
119 if(c
!= answersallowed
.end()-1) msg
+= '/';
123 kwriteat(0, line
, msg
.c_str(), getcolor(cp_input
));
126 key
= toupper(getch());
127 if(key
== '\r') key
= toupper(*answersallowed
.begin());
128 if(answersallowed
.find(key
) != -1) break;
134 case 'Y': return motorui::yes
;
135 case 'C': return motorui::cancel
;
136 case 'A': return motorui::all
;
137 case 'N': return motorui::no
;
143 void ncursesui::log(const string
&text
) {
145 string::const_iterator i
;
147 attrset(getcolor(cp_bottom
));
148 mvhline(LINES
-1, 0, ' ', COLS
);
149 mvprintw(LINES
-1, 0, "");
151 for(i
= text
.begin(); i
!= text
.end(); i
++) {
153 if(text
.substr(i
-text
.begin(), 2) != "~~") {
155 attrset(getcolor(cp_bottomhl
));
157 attrset(getcolor(cp_bottom
));
171 void ncursesui::loadeditfile(const motorui::editfile ef
, INT options
) {
177 vector
<motorfolder
>::iterator ifold
, icfold
;
178 vector
<motorfile
>::iterator ifile
, icfile
;
181 if(ef
.fname
.empty()) return;
183 if((fname
= ef
.fname
).substr(0, 1) != "/") {
184 fname
= (string
) getcwd(buf
, 512) + "/" + fname
;
187 if(access(fname
.c_str(), F_OK
)) {
188 fname
= justfname(fname
);
190 for(ifold
= project
.foldbegin(), found
= false; !found
&& ifold
!= project
.foldend(); ifold
++)
191 for(ifile
= ifold
->begin(); !found
&& ifile
!= ifold
->end(); ifile
++)
192 switch(ifold
->getcontentkind()) {
193 case motorfile::source
:
194 if(found
= (justfname(ifile
->getfname()) == fname
))
195 fname
= project
.transformfname(projectpaths::absolute
, ifile
->getfname());
198 case motorfile::project
:
199 pf
= motorproject(ifile
->getfname());
201 for(icfold
= pf
.foldbegin(); !found
&& icfold
!= pf
.foldend(); icfold
++) {
202 if(icfold
->getcontentkind() == motorfile::source
) {
203 for(icfile
= icfold
->begin(); !found
&& icfile
!= icfold
->end(); icfile
++) {
204 if(found
= (justfname(icfile
->getfname()) == fname
))
205 fname
= pf
.transformfname(projectpaths::absolute
,
214 for(i
= 0, found
= false; i
< ed
.getfcount() && !found
; i
++) {
215 found
= samefile(ed
.getfid(i
), fname
);
221 if((options
& LF_CREATE_IF_NOTFOUND
) && access(fname
.c_str(), F_OK
)) {
224 f
.open(fname
.c_str());
227 ed
.markbreakpoints();
233 if(ef
.x
!= -1 && ef
.y
!= -1)
234 ed
.setpos(ef
.x
, ef
.y
-1);
239 void ncursesui::commandline(INT argc
, char **argv
) {
243 for(r
= 1; argv
[r
]; r
++) {
246 if(slong
== "--ascii" || slong
== "-a") {
249 } else if((slong
== "--debugtty" || slong
== "-t") && argv
[++r
]) {
250 debugger
.forceusetty(argv
[r
]);
252 } else if(slong
== "--help" || slong
.substr(0, 1) == "-") {
256 } else if(project
.empty()) {
257 project
= motorproject(projectname(slong
));
264 void ncursesui::usage() {
266 cout
<< "usage: motor [options] [project name]" << endl
<<
267 "options are as follows:" << endl
<<
268 "\t-a, --ascii\tuse ascii characters to draw lines" << endl
<<
269 "\t-t, --debugtty\tuse the specified tty for debugging" << endl
<<
270 "\t-h, --help\tdisplay this help screen" << endl
;
273 bool ncursesui::regproject() {
275 string fname
, pname
, lfname
, postfix
= ".motor";
278 if(input(motorui::file
, fname
, _("add project to the registry: ")) == motorui::yes
) {
279 if(!access(fname
.c_str(), R_OK
)) {
280 pname
= justfname(fname
);
282 if(pname
.size() > postfix
.size())
283 if(pname
.substr(pname
.size()-postfix
.size()) == postfix
)
284 pname
.erase(pname
.size()-postfix
.size());
286 if(pname
!= justfname(fname
)) {
287 bool updname
= false;
289 while(!pname
.empty() && !projectname(pname
).empty()) {
291 sprintf(buf
, _("Already registered! Rename %s (%s) to: "),
292 pname
.c_str(), justfname(fname
).c_str());
293 if(input(text
, pname
, buf
) != motorui::yes
)
299 string nfname
= justpathname(fname
) + "/" + pname
+ postfix
;
300 rename(fname
.c_str(), nfname
.c_str());
304 lfname
= conf
.getprojectdir() + pname
;
305 symlink(fname
.c_str(), lfname
.c_str());
307 motorproject
np(pname
);
310 logf(_("~%s~ is not a motor project"), justfname(fname
).c_str());
311 unlink(lfname
.c_str());
315 logf(_("~%s~ is an invalid name for a motor project file"));
319 logf(_("Cannot access ~%s~"), justfname(fname
).c_str());
326 const projectname
ncursesui::selectproject(mgrmode amode
, vector
<string
> templs
) {
327 vector
<projectname
>::iterator i
;
328 vector
<projectname
> pnames
;
329 vector
<string
>::iterator is
;
330 vector
< pair
<string
, INT
> >::iterator itnode
;
331 vector
< pair
<string
, INT
> > tnodes
;
334 INT j
, baritem
, menuitem
, cid
, lpid
;
335 string templatelast
, head
;
338 bool iterfirst
= true;
340 if(amode
== selectorcreate
) {
341 db
.setbar(new horizontalbar(getcolor(cp_menu
), getcolor(cp_menusel
),
342 _("Create/Import.."), _("Add"), _("Remove"), _("Open"), NULL_CONST_STR
));
344 db
.addkey(KEY_IC
, 1);
345 db
.addkey(KEY_DC
, 2);
347 db
.getbar()->item
= 3;
349 db
.setwindow(new textwindow(0, 0, (INT
) (DIALOG_WIDTH
*0.8),
350 DIALOG_HEIGHT
, getcolor(cp_menufr
), TW_CENTERED
,
351 getcolor(cp_menuhl
), _(" Projects registry ")));
354 db
.setwindow(new textwindow(0, 0, DIALOG_WIDTH
, DIALOG_HEIGHT
,
355 getcolor(cp_menufr
), TW_CENTERED
, getcolor(cp_menuhl
),
356 _(" Add a project ")));
359 db
.settree(new treeview(getcolor(cp_menu
), getcolor(cp_menusel
),
360 getcolor(cp_menu
), getcolor(cp_menu
)));
362 treeview
&tree
= *db
.gettree();
364 while(pname
.empty()) {
368 pnames
= manager
.getprojectlist();
370 for(i
= pnames
.begin(); i
!= pnames
.end(); i
++) {
371 for(itnode
= tnodes
.begin(); itnode
!= tnodes
.end(); itnode
++)
372 if(itnode
->first
== i
->gettemplatename()) break;
375 if(find(templs
.begin(), templs
.end(), i
->gettemplatename()) == templs
.end())
378 if(itnode
== tnodes
.end()) {
379 j
= tree
.addnode(0, getcolor(cp_menuhl
), NULL
, " " + i
->gettemplatename() + " ");
380 tnodes
.push_back(pair
<string
, INT
>(i
->gettemplatename(), j
));
381 itnode
= tnodes
.end()-1;
384 cid
= tree
.addleaf(itnode
->second
, 0,
385 i
-pnames
.begin()+1, " " + i
->getname() + " ");
388 if((project
.empty() && (i
->getname() == uiconf
.getlastproject()))
389 || (i
->getname() == project
.getname())) {
394 if(iterfirst
) tree
.setcur(lpid
);
397 /* if(tree.empty() && (amode == selectorcreate)) {
398 if(iterfirst) baritem = 0; else break;
400 if(!db
.open(menuitem
, baritem
, (void **) &j
)) break;
405 if((amode
== selectonly
) && j
) {
410 if(createproject()) {
411 pname
= static_cast<projectname
> (project
);
420 mp
= motorproject(pnames
[j
-1], LP_NOCHECK
);
425 iterfirst
= pnames
.size() == 1;
441 string
ncursesui::selecttemplate(const string
&def
, const string
&title
) const {
444 INT n
, b
, nnode
, citem
, id
, cpid
= -1;
445 vector
<string
> tlist
;
446 vector
<string
>::iterator it
;
447 vector
< pair
<string
, INT
> > nodes
;
448 vector
< pair
<string
, INT
> >::iterator in
;
450 tlist
= manager
.gettemplatelist();
452 db
.setwindow(new textwindow(0, 0, DIALOG_WIDTH
, DIALOG_HEIGHT
,
453 getcolor(cp_menufr
), TW_CENTERED
, getcolor(cp_menuhl
), title
.c_str()));
454 db
.settree(new treeview(getcolor(cp_menu
), getcolor(cp_menusel
),
455 getcolor(cp_menu
), getcolor(cp_menu
)));
457 for(it
= tlist
.begin(); it
!= tlist
.end(); it
++) {
458 lw
= getrword(buf
= *it
, "/");
460 for(in
= nodes
.begin(), nnode
= 0; !nnode
&& (in
!= nodes
.end()); in
++)
461 if(in
->first
== buf
) nnode
= in
->second
;
464 nnode
= db
.gettree()->addnode(0, getcolor(cp_menuhl
), NULL
, " " + buf
+ " ");
465 nodes
.push_back(pair
<string
, INT
>(buf
, nnode
));
468 id
= db
.gettree()->addleaf(nnode
, 0, it
-tlist
.begin()+1, " " + lw
+ " ");
469 if(*it
== def
) cpid
= id
;
472 db
.gettree()->setcur(cpid
);
475 if(db
.open(n
, b
, (void **) &citem
)) {
477 ret
= tlist
[citem
-1];
491 void ncursesui::mainloop() {
503 void ncursesui::redraw() {
507 void ncursesui::initmenubar() {
509 menubar
= horizontalmenu(1, 0, getcolor(cp_menu
), getcolor(cp_menusel
), getcolor(cp_menufr
));
511 menubar
.otherkeys
= &horizontalmenukeys
;
513 menubar
.additem(_(" File "));
514 menubar
.additem(_(" Edit "));
515 menubar
.additem(_(" Project "));
516 menubar
.additem(_(" VCS "));
517 menubar
.additem(_(" Debug "));
518 menubar
.additem(_(" Window "));
520 m
= menubar
.pulldown(0);
521 m
->additem(_(" Load.. ^O"));
522 m
->additem(_(" Save F2"));
523 m
->additem(_(" Save as.."));
524 m
->additem(_(" Save all"));
525 m
->additem(_(" Close ^D"));
526 m
->additem(_(" Generate.."));
528 m
->additem(_(" Motor settings"));
529 m
->additem(_(" External keys"));
530 m
->additem(_(" Regexper A-R"));
532 m
->additem(_(" Quit ^X"));
534 m
= menubar
.pulldown(1);
535 m
->additem(_(" Toggle mark F3"));
536 m
->additem(_(" Cut A-X"));
537 m
->additem(_(" Copy A-C"));
538 m
->additem(_(" Paste A-V"));
540 m
->additem(_(" Toggle ins/overw Ins"));
542 m
->additem(_(" Find ^F"));
543 m
->additem(_(" Find again ^G"));
544 m
->additem(_(" Replace ^R"));
545 m
->additem(_(" Go to line.. A-L"));
547 m
->additem(_(" Shft block fwd A-Tab"));
548 m
->additem(_(" Shft block back A-Bsp"));
550 m
->additem(_(" Undo ^U"));
552 m
= menubar
.pulldown(2);
553 m
->additem(_(" Projects registry"));
555 m
->additem(_(" Files.. F11"));
556 m
->additem(_(" Directories.. ^F11"));
557 m
->additem(_(" Project settings S-F11"));
559 m
->additem(_(" Build F9"));
560 m
->additem(_(" Clean S-F9"));
561 m
->additem(_(" Make a target.. A-T"));
562 m
->additem(_(" Regen. build stuff"));
563 m
->additem(_(" Make a dist package"));
565 m
->additem(_(" Find a symbol.. A-?"));
566 m
->additem(_(" External output.."));
568 m
= menubar
.pulldown(3);
569 m
->additem(_(" Check in/out"));
570 m
->additem(_(" Import"));
571 m
->additem(_(" Tag a release"));
574 m->additem(_(" Browse revisions.."));
576 m->additem(_(" Fork a branch"));
577 m->additem(_(" Merge branches.."));
579 m
= menubar
.pulldown(4);
580 m
->additem(_(" Run program F12"));
581 m
->additem(_(" Load core dump.."));
582 m
->additem(_(" Arguments.. S-F12"));
583 m
->additem(_(" Reset program ^F12"));
584 m
->additem(_(" Call stack.. A-S"));
586 m
->additem(_(" Set/Clear breakpoint ^B"));
587 m
->additem(_(" Breakpoints A-B"));
589 m
->additem(_(" Add watch ^W"));
590 m
->additem(_(" Watches A-W"));
591 m
->additem(_(" Evaluate/Modify A-E"));
593 m
->additem(_(" Trace into F7"));
594 m
->additem(_(" Step over F8"));
595 m
->additem(_(" Go to cursor F4"));
597 m
= menubar
.pulldown(5);
598 m
->additem(_(" Next ^N"));
599 m
->additem(_(" Previous ^P"));
601 m
->additem(_(" Window list F5"));
602 m
->additem(_(" Last build messages F6"));
605 void ncursesui::execmenubar() {
609 if(menubar
.open(&h
, &p
))
613 case 1: hotkey(CTRL('o')); break;
614 case 2: ed
.fsave(uieditor::savecurrent
); break;
615 case 3: ed
.fsave(uieditor::saveas
); break;
616 case 4: ed
.fsave(uieditor::saveall
); break;
617 case 5: ed
.closecurrentfile(); break;
618 case 6: generate(); break;
619 case 8: settings(); break;
620 case 9: extkeylist(); break;
621 case 10: regexper
.exec(); break;
622 case 12: terminate
= true; break;
627 case 1: ed
.switchmark(); break;
628 case 2: ed
.clipboard(uieditor::cut
); break;
629 case 3: ed
.clipboard(uieditor::copy
); break;
630 case 4: ed
.clipboard(uieditor::paste
); break;
631 case 6: ed
.insertmode
= !ed
.insertmode
; break;
632 case 8: hotkey(CTRL('f')); break;
633 case 9: hotkey(CTRL('g')); break;
634 case 10: hotkey(CTRL('r')); break;
663 projectedit(psettings
);
675 project
.regenerate();
713 if(debugger
.running()) {
759 case 1: ed
.switchwindow(+1); break;
760 case 2: ed
.switchwindow(-1); break;
761 case 4: ed
.windowlist(); break;
762 case 5: hotkey(KEY_F(6)); break;
768 bool ncursesui::horizontalmenukeys(horizontalmenu
&hm
, INT k
) {
769 bool r
= thisui
.hotkey(k
);
770 return thisui
.terminate
|| r
;
773 void ncursesui::workareaupdate() {
780 for(i
= 1; i
< LINES
-1; i
++)
781 mvhline(i
, 0, ' ', COLS
);
788 void ncursesui::statusupdate() {
793 pname
= (string
) _("PROJECT: ") + project
.getname();
796 fname
= (string
) _("FILE: ") + justfname(ed
.getfid()) + " ";
800 attrset(getcolor(cp_bottom
));
801 mvhline(0, 0, ' ', COLS
);
802 mvprintw(0, 0, " MOTOR %s %s%s", VERSION
, fname
.c_str(), pname
.c_str());
805 mvprintw(0, COLS
-18, "[%c%c%c] %5d:%5d",
806 ed
.insertmode
? '-' : 'O',
807 ed
.ismark() ? 'B' : '-',
808 ed
.modified
? 'M' : '-',
814 bool ncursesui::hotkey(INT k
) {
815 INT modifiers
= getctrlkeys(), line
;
816 vector
<motorconfiguration::extkey
>::const_iterator ek
;
828 debugger
.tocursor(ed
.getfid(), line
+1);
850 if(executor
.begin() != executor
.end()) showmessages();
858 if(modifiers
& SHIFT_PRESSED
) projectedit(psettings
); else
859 if(modifiers
& CONTROL_PRESSED
) projectedit(pdirs
, true); else
864 if(modifiers
& SHIFT_PRESSED
) {
866 } else if(modifiers
& CONTROL_PRESSED
) {
869 if(debugger
.running()) {
896 breakpoint
bp(ed
.getfid(), line
+1);
898 if(debugger
.isbreakpoint(bp
)) {
899 debugger
.removebreakpoint(bp
);
901 debugger
.addbreakpoint(bp
);
904 ed
.markbreakpoints();
961 if(r
= ((ek
= find(conf
.extkeybegin(), conf
.extkeyend(), k
))
962 != conf
.extkeyend())) {
971 bool ncursesui::isterminated() {
975 void ncursesui::textboxf(const string
&title
, const char *fmt
, ...) {
979 vsprintf(buf
, fmt
, ap
);
984 void ncursesui::textbox(const string
&text
, const string
&title
) {
987 db
.setwindow(new textwindow(0, 0, DIALOG_WIDTH
, DIALOG_HEIGHT
,
988 getcolor(cp_menufr
), TW_CENTERED
));
990 db
.setbrowser(new textbrowser(getcolor(cp_menu
)));
992 db
.setbar(new horizontalbar(getcolor(cp_menu
),
993 getcolor(cp_menusel
), _("Ok"), NULL_CONST_STR
));
995 db
.getwindow()->set_title(getcolor(cp_menuhl
), title
);
996 db
.getbrowser()->setbuf(text
);
1002 INT
ncursesui::texteditboxkeys(texteditor
&ed
, INT k
) {
1005 thisui
.texteditok
= true;
1013 bool ncursesui::texteditbox(const string
&title
, string
&text
) {
1017 textwindow
w(0, 0, DIALOG_WIDTH
, DIALOG_HEIGHT
, getcolor(cp_menufr
),
1018 TW_CENTERED
, getcolor(cp_menuhl
), "%s", title
.c_str());
1022 w
.separatey(w
.y2
-w
.y1
-2);
1023 w
.write(w
.x2
-w
.x1
-20, w
.y2
-w
.y1
-1, getcolor(cp_menufr
), "^X save ESC cancel");
1024 w
.write(w
.x2
-w
.x1
-20, w
.y2
-w
.y1
-1, getcolor(cp_menuhl
), "^X");
1025 w
.write(w
.x2
-w
.x1
-11, w
.y2
-w
.y1
-1, getcolor(cp_menuhl
), "ESC");
1027 ed
.setcoords(w
.x1
+1, w
.y1
+1, w
.x2
-1, w
.y2
-2);
1028 ed
.addscheme(cp_menufr
, cp_menufr
, 0, 0);
1030 ed
.otherkeys
= &texteditboxkeys
;
1038 text
= sp
= ed
.save("\r\n");
1046 void ncursesui::help() {
1049 helptext
+= _("F1 Display this help screen\n");
1050 helptext
+= _("F10 Activate menu\n");
1051 helptext
+= _("^X Quit motor\n\n");
1052 helptext
+= _("F2 Save current file\n");
1053 helptext
+= _("^O Load file\n");
1054 helptext
+= _("^D Close current editor window\n");
1055 helptext
+= _("F5 Editor files..\n");
1056 helptext
+= _("^N Next editor window\n");
1057 helptext
+= _("^P Previous editor window\n\n");
1058 helptext
+= _("Ins Toggle insert/overwrite mode\n");
1059 helptext
+= _("F3 Toggle block marking mode\n");
1060 helptext
+= _("Alt-X, ^Del Cut selected text\n");
1061 helptext
+= _("Alt-C, ^Ins Copy selected text\n");
1062 helptext
+= _("Alt-V, ^Ins Paste previously copied text\n");
1063 helptext
+= _("Alt-Tab Shift selected block forward\n");
1064 helptext
+= _("Alt-Backsp Shift selected block backward\n\n");
1065 helptext
+= _("^U Undo previous editor operation\n");
1066 helptext
+= _("^F Find text in current file\n");
1067 helptext
+= _("^G Find again\n");
1068 helptext
+= _("^R Search and replace\n");
1069 helptext
+= _("Alt-L Goto line..\n\n");
1070 helptext
+= _("Shift-F11 Project settings..\n");
1071 helptext
+= _("F11 Project files..\n");
1072 helptext
+= _("^F11 Project directories..\n\n");
1073 helptext
+= _("F9 Build a project\n");
1074 helptext
+= _("Shift-F9 Clean\n");
1075 helptext
+= _("Alt-T Make a specific target..\n");
1076 helptext
+= _("F12 Run program\n");
1077 helptext
+= _("Shift-F12 Specify program arguments\n");
1078 helptext
+= _("Alt-? Find a symbol definition in the source\n\n");
1079 helptext
+= _("F4 Go to cursor\n");
1080 helptext
+= _("F7 Debug mode: trace into\n");
1081 helptext
+= _("F8 Step over\n\n");
1082 helptext
+= _("^B Set breakpoint at current line\n");
1083 helptext
+= _("Alt-B Breakpoints..\n");
1084 helptext
+= _("^W Add watch\n");
1085 helptext
+= _("Alt-W Watches..\n");
1086 helptext
+= _("Alt-E Evaluate/modify..\n\n");
1087 helptext
+= _("Alt-R Invoke the regexper tool\n\n");
1088 helptext
+= _("Note: If your terminal doesn't allow using Alt-keys or\n");
1089 helptext
+= _(" Fx keys, you can use ESC 'letter or number' instead.\n");
1090 helptext
+= _(" '^' char means the key should be pressed with Ctrl.");
1092 textbox(helptext
, _(" Help "));
1095 vector
<motorui::editfile
> ncursesui::geteditfiles() {
1097 vector
<motorui::editfile
> v
;
1099 saven
= ed
.getfnum();
1100 for(i
= 0; i
< ed
.getfcount(); i
++) {
1103 v
.push_back(motorui::editfile(ed
.getfid(i
), x
, y
+1));
1106 if(ed
.getfcount() > 1) {
1107 v
.push_back(v
[saven
]);
1108 v
.erase(v
.begin()+saven
);
1115 vector
<string
> ncursesui::geteditfile(const string
&fname
) {
1121 for(i
= 0; i
< ed
.getfcount(); i
++) {
1122 if(samefile(fname
, ed
.getfid(i
))) {
1123 saven
= ed
.getfnum();
1125 buf
= ed
.save("\n");
1132 breakintolines(buf
, r
);
1137 string
ncursesui::inputskel(const string
&initval
, const string
&text
, bool selmode
) {
1139 INT mright
= COLS
-text
.size();
1140 screenarea
sarea(0, line
, COLS
, line
);
1142 attrset(getcolor(cp_input
));
1143 mvhline(line
, 0, ' ', COLS
);
1144 kwriteatf(0, line
, getcolor(cp_input
), "%s", text
.c_str());
1148 kwriteatf(COLS
-8, line
, getcolor(cp_input
), "[Ctrl-T]");
1149 inp
.connectselector(selector
);
1151 inp
.removeselector();
1154 inp
.setvalue(initval
);
1155 inp
.setcoords(text
.size(), line
, mright
);
1159 return inp
.getvalue();
1162 void ncursesui::initelements() {
1163 inp
.setcolor(getcolor(cp_input
), getcolor(cp_menufr
));
1165 selwindow
= textwindow(0, 0, (INT
) (DIALOG_WIDTH
*0.8),
1166 DIALOG_HEIGHT
, getcolor(cp_menufr
), TW_CENTERED
);
1168 selector
.setcolor(getcolor(cp_menu
), getcolor(cp_menuhl
),
1169 getcolor(cp_menusel
), getcolor(cp_menu
));
1172 bool ncursesui::editcloseall() {
1175 if(ret
= ed
.fsave(uieditor::saveallask
))
1176 while(ed
.getfcount()) ed
.close();
1181 bool ncursesui::changetemplate() {
1182 string nt
= selecttemplate(project
.gettemplatename());
1184 if(!nt
.empty() && nt
!= project
.gettemplatename())
1185 if(ask("NY", _("Warning: changing template will rearrange files in project. Proceed?")) == motorui::yes
) {
1186 project
.settemplate(nt
);
1193 void ncursesui::populatesettingstree(treeview
&tree
) {
1194 string cflags
, lflags
;
1197 project
.getflags(cflags
, lflags
);
1199 INT nmain
= tree
.addnode(0, getcolor(cp_menuhl
), NULL
, _(" Main "));
1200 INT nvcs
= tree
.addnode(0, getcolor(cp_menuhl
), NULL
, _(" Version control "));
1201 INT nmake
= tree
.addnode(0, getcolor(cp_menuhl
), NULL
, _(" Make "));
1203 tree
.addleaff(nmain
, 0, 10, _(" Version : %s "), project
.getversion().c_str());
1204 tree
.addleaff(nmain
, 0, 11, _(" Template : %s "), project
.gettemplatename().c_str());
1205 tree
.addleaff(nmain
, 0, 12, _(" Root directory : %s "), project
.getrootdir().c_str());
1206 tree
.addleaff(nmain
, 0, 13, _(" Use GNU gettext for internationalization : %s "), BOOL_TO_STR(project
.isgettextized()));
1209 tree
.addleaff(nvcs
, 0, 14, _(" %s: %s in %s "),
1210 project
.getvcs().c_str(), project
.getvcsmodulename().c_str(),
1211 project
.getvcsroot().c_str());
1213 tree
.addleaf(nvcs
, 0, 14, _(" Not under version control "));
1216 tree
.addleaff(nmake
, 0, 16, _(" Makefile mode : %s "), MAKEMODE_TO_STR(project
.getmakemode()));
1217 tree
.addleaff(nmake
, 0, 17, _(" Compiler options : %s "), cflags
.c_str());
1218 tree
.addleaff(nmake
, 0, 18, _(" Linker options : %s "), lflags
.c_str());
1220 tree
.addnode(0, getcolor(cp_menuhl
), 30, _(" Files.. "));
1221 tree
.addnode(0, getcolor(cp_menuhl
), 31, _(" Directories.. "));
1224 bool ncursesui::projectsettings() {
1228 string cflags
, lflags
, buf
;
1229 bool rc
= false, trc
;
1231 project
.getflags(cflags
, lflags
);
1233 db
.setwindow(new textwindow(0, 0, DIALOG_WIDTH
, DIALOG_HEIGHT
,
1234 getcolor(cp_menufr
), TW_CENTERED
, getcolor(cp_menuhl
),
1235 _(" Project settings ")));
1236 db
.settree(new treeview(getcolor(cp_menu
), getcolor(cp_menusel
),
1237 getcolor(cp_menu
), getcolor(cp_menu
)));
1238 db
.setbar(new horizontalbar(getcolor(cp_menu
), getcolor(cp_menusel
),
1239 _("Change"), NULL_CONST_STR
));
1241 nfiles
= ed
.getfcount();
1242 for(bool fin
= false; nfiles
== ed
.getfcount() && !fin
; ) {
1243 populatesettingstree(*db
.gettree());
1244 if(fin
= !db
.open(n
, b
, &p
)) break;
1248 if(input(motorui::text
, buf
= project
.getversion(),
1249 _("version: ")) == motorui::yes
) {
1250 project
.setversion(buf
);
1255 if(changetemplate())
1260 log(_("Cannot modify the root directory. Please move the files manually"));
1264 project
.setgettextized(!project
.isgettextized());
1269 if(ask("NY", _("Do you want to disable version control for the project?")) == motorui::yes
) {
1270 project
.setvcsmodule("");
1271 project
.setvcsroot("");
1279 project
.setmakemode(
1280 project
.getmakemode() == motorproject::automake
?
1281 motorproject::manual
:
1282 motorproject::automake
);
1286 if(input(motorui::text
, cflags
, _("additional compiler command line options: "))
1287 != motorui::cancel
) {
1288 project
.setflags(cflags
, lflags
);
1293 if(input(motorui::text
, lflags
, _("additional linker command line options: "))
1294 != motorui::cancel
) {
1295 project
.setflags(cflags
, lflags
);
1300 if(projectcontents(pfiles
, false))
1304 if(projectcontents(pdirs
, false))
1314 motorui::askresult
ncursesui::input(motorui::inputkind kind
, string
&result
,
1315 const string
&prompt
) {
1318 INT fseloptions
= 0;
1320 selwindow
.set_title(getcolor(cp_menuhl
), _(" <Ins> select; <Space> confirm; <Esc> cancel "));
1323 case motorui::filechroot
:
1324 fseloptions
|= FSEL_CHROOT
;
1325 fseloptions
|= FSEL_MULTI
;
1330 case motorui::directorychroot
:
1331 fseloptions
|= FSEL_CHROOT
;
1332 case motorui::directory
:
1334 fseloptions
|= FSEL_DIRSELECT
;
1335 selector
.setstartpoint(result
);
1343 selector
.setwindow(selwindow
);
1344 selector
.setoptions(fseloptions
);
1346 text
= inputskel(result
, prompt
, fselmode
);
1348 if(inp
.getlastkey() == KEY_ESC
) {
1349 return motorui::cancel
;
1353 return result
.empty() ? motorui::no
: motorui::yes
;
1356 typedef pair
<motorfile
*, motorfolder
*> shitpair
;
1357 vector
<shitpair
> treeshit
;
1359 void ncursesui::populatecontentstree(treeview
&tree
, motorproject
&mp
, projeditaction pea
, bool setcurrent
) {
1360 INT foldid
, id
, cfid
= -1, i
, sid
;
1361 vector
<motorfolder
>::iterator ifold
;
1362 vector
<motorfile
>::iterator ifile
;
1363 static vector
<string
> cnodes
;
1368 for(i
= 0; i
< tree
.menu
.getcount(); i
++) {
1372 if(sid
= (INT
) tree
.getref(id
))
1373 if(!tree
.isnodeopen(id
))
1374 cnodes
.push_back(treeshit
[sid
-1].second
->gettagname());
1381 for(ifold
= mp
.foldbegin(); ifold
!= mp
.foldend(); ifold
++)
1382 if((pea
== pfiles
&& ifold
->getcontentkind() != motorfile::directory
)
1383 || (pea
== pdirs
&& ifold
->getcontentkind() == motorfile::directory
)) {
1385 treeshit
.push_back(shitpair(0, &(*ifold
)));
1386 foldid
= tree
.addnode(0, getcolor(cp_menuhl
), treeshit
.size(), " " + ifold
->getname() + " ");
1388 if(find(cnodes
.begin(), cnodes
.end(), ifold
->gettagname()) != cnodes
.end()) {
1389 tree
.closenode(foldid
);
1391 tree
.opennode(foldid
);
1394 for(ifile
= ifold
->begin(); ifile
!= ifold
->end(); ifile
++) {
1395 treeshit
.push_back(shitpair(&(*ifile
), &(*ifold
)));
1396 id
= tree
.addleaf(foldid
, 0, treeshit
.size(), " " + ifile
->getfname() + " ");
1399 if(ifold
->getcontentkind() == motorfile::source
)
1400 if(ifile
->getfname() == mp
.transformfname(motorproject::relative
, ed
.getfid()))
1408 bool ncursesui::projectcontents(projeditaction pea
, bool setcurrent
) {
1409 INT n
, b
, citem
, id
;
1411 string buf
, head
, fname
;
1414 motorui::askresult ar
;
1415 vector
<string
> templnames
;
1419 bool fpass
= true, tregen
, rc
= false;
1423 head
= _(" Project files ");
1424 db
.setbar(new horizontalbar(getcolor(cp_menu
),
1425 getcolor(cp_menusel
), _("Add"), _("Remove"), _("Edit"), NULL_CONST_STR
));
1426 db
.getbar()->item
= 2;
1429 head
= _(" Project directories ");
1430 db
.setbar(new horizontalbar(getcolor(cp_menu
),
1431 getcolor(cp_menusel
), _("Add"), _("Remove"), NULL_CONST_STR
));
1435 db
.setwindow(new textwindow(0, 0, DIALOG_WIDTH
, DIALOG_HEIGHT
,
1436 getcolor(cp_menufr
), TW_CENTERED
, getcolor(cp_menuhl
), head
.c_str()));
1438 db
.settree(new treeview(getcolor(cp_menu
), getcolor(cp_menusel
),
1439 getcolor(cp_menu
), getcolor(cp_menu
)));
1441 treeview
&tree
= *db
.gettree();
1443 tree
.collapsable
= true;
1444 db
.addkey(KEY_IC
, 0);
1445 db
.addkey(KEY_DC
, 1);
1447 for(bool fin
= false; !fin
; ) {
1448 if(tree
.empty() || tregen
) {
1449 populatecontentstree(tree
, project
, pea
, setcurrent
&& ed
.getfid() && fpass
);
1453 log(_("No folders of this kind are defined in the template"));
1459 if(fin
= !db
.open(n
, b
, (void **) &citem
)) break;
1462 file
= treeshit
[citem
-1].first
;
1463 fold
= treeshit
[citem
-1].second
;
1467 ar
= motorui::cancel
;
1470 switch(fold
->getcontentkind()) {
1471 case motorfile::source
:
1472 ar
= input(motorui::filechroot
, buf
, _("add file: "));
1474 case motorfile::directory
:
1475 ar
= input(motorui::directory
, buf
, _("add directory: "));
1477 case motorfile::symbol
:
1478 ar
= input(motorui::text
, buf
, _("add symbol: "));
1480 case motorfile::project
:
1481 pname
= selectproject(selectonly
, fold
->gettempltotakefrom());
1482 if(!pname
.empty()) {
1483 buf
= pname
.getname();
1489 if(ar
== motorui::yes
) {
1490 while(!buf
.empty()) {
1491 fname
= getword(buf
, "\"");
1492 if(!fname
.empty()) {
1493 fname
= project
.transformfname(projectpaths::relative
, fname
);
1495 if(find(fold
->begin(), fold
->end(), fname
) == fold
->end()) {
1496 if(fold
->addfile(motorfile(fname
), AF_VCS
| AF_CHECKDIR
| AF_TAKE
)) {
1499 logf(_("Cannot add ~%s~ to the ~%s~ folder"),
1500 fname
.c_str(), fold
->getname().c_str());
1506 if(tregen
) db
.redraw();
1511 fold
->removefile(*file
);
1518 switch(fold
->getcontentkind()) {
1519 case motorfile::source
:
1520 ui
.loadeditfile(editfile(file
->getfname(), -1, 0),
1521 LF_CREATE_IF_NOTFOUND
);
1525 case motorfile::symbol
:
1528 case motorfile::project
:
1529 m
= verticalmenu(getcolor(cp_menufr
), getcolor(cp_menusel
));
1531 textwindow(db
.getwindow()->x2
-17,
1532 db
.getwindow()->y2
-3, db
.getwindow()->x2
+3,
1533 0, getcolor(cp_menufr
)
1536 m
.additem(_(" Files.."));
1537 m
.additem(_(" Open the project"));
1539 if(project.getmakemode() == motorproject::automake)
1540 m.additem(_(" Build options.."));
1548 buf
= selectprojectfile(projectname(file
->getfname()));
1549 if(fin
= !buf
.empty()) {
1550 ui
.loadeditfile(editfile(buf
, -1, 0), LF_CREATE_IF_NOTFOUND
);
1554 pload(file
->getfname());
1559 if(editbuildoptions(*file
))
1565 } else if(fold
&& !file
) {
1566 id
= tree
.getid((void *) citem
);
1568 if(tree
.isnodeopen(id
)) {
1582 return project
.modified() || rc
;
1585 string
ncursesui::selectprojectfile(motorproject mp
) {
1591 vector
<shitpair
> savetreeshit
= treeshit
;
1595 db
.setwindow(new textwindow(0, 0, DIALOG_WIDTH
, DIALOG_HEIGHT
,
1596 getcolor(cp_menufr
), TW_CENTERED
, getcolor(cp_menuhl
),
1597 _(" Project %s "), mp
.getname().c_str()));
1599 db
.settree(new treeview(getcolor(cp_menu
), getcolor(cp_menusel
),
1600 getcolor(cp_menu
), getcolor(cp_menu
)));
1602 db
.setbar(new horizontalbar(getcolor(cp_menu
),
1603 getcolor(cp_menusel
), _("Open"), NULL_CONST_STR
));
1605 treeview
&tree
= *db
.gettree();
1606 populatecontentstree(tree
, mp
, pfiles
, false);
1609 success
= db
.open(n
, b
, (void **) &citem
);
1610 file
= treeshit
[citem
-1].first
;
1611 fold
= treeshit
[citem
-1].second
;
1612 if(!success
|| file
) break;
1615 if(success
&& file
) {
1616 if(fold
->getcontentkind() == motorfile::source
) {
1617 rc
= file
->getfname();
1624 treeshit
= savetreeshit
;
1628 bool ncursesui::autosave() {
1629 ed
.fsave(uieditor::saveall
);
1633 void ncursesui::writeoutput(const string
&text
) {
1634 vector
<string
>::iterator il
;
1635 INT pos
, len
= COLS
-2, ln
;
1639 outlines
.push_back("");
1641 for(pos
= 0; pos
< text
.size(); pos
+= len
) {
1642 line
= text
.substr(pos
, len
);
1643 outlines
.push_back(line
);
1647 while(outlines
.size() > OUTLINES_LIMIT
)
1648 outlines
.erase(outlines
.begin());
1650 if(!outputblocked
) {
1656 ln
= outlines
.size() >= LOOKER_HEIGHT
? 1 : LOOKER_HEIGHT
-outlines
.size();
1657 il
= ln
== 1 ? outlines
.end()-LOOKER_HEIGHT
+1 : outlines
.begin();
1659 for(; il
!= outlines
.end(); il
++, ln
++) {
1660 mvhline(ln
, 0, ' ', COLS
);
1662 if(il
->substr(0, 1) == "\001") {
1663 kwriteat(0, ln
, il
->c_str()+1, boldcolor(0));
1665 kwriteat(0, ln
, il
->c_str(), normalcolor(0));
1669 mvhline(ln
, 0, ' ', COLS
);
1670 kwriteat(0, ln
, "", normalcolor(0));
1674 void ncursesui::doneoutput() {
1681 void ncursesui::showoutput() {
1682 textbrowser
b(0, 1, COLS
, LOOKER_HEIGHT
+1, normalcolor(0));
1683 vector
<string
>::iterator i
;
1686 if(outlines
.size() < LOOKER_HEIGHT
)
1687 text
.assign(LOOKER_HEIGHT
-outlines
.size()+1, '\n');
1689 for(i
= outlines
.begin(); i
!= outlines
.end(); i
++) {
1690 if(!text
.empty()) text
+= "\n";
1692 // text += (i->substr(0, 1) == "\001" ? i->substr(1) : *i);
1695 log(_("External output viewer, ~ESC~ to close"));
1696 b
.setbuf(text
.c_str());
1703 void ncursesui::pointmessage() {
1708 if(!currentmsg
->fname
.empty())
1709 loadeditfile(editfile(currentmsg
->fname
, 0, currentmsg
->line
));
1712 lmsg
= currentmsg
->description
;
1715 while((i
= find(i
, lmsg
.end(), '~')) != lmsg
.end()) {
1716 lmsg
.insert(i
-lmsg
.begin()+k
, "~");
1724 void ncursesui::showmessages() {
1727 vector
<motorexecutor::message
>::const_iterator i
;
1728 bool curfound
= false, start
= false;
1730 if(executor
.begin() != executor
.end()) {
1731 rm
= verticalmenu(getcolor(cp_menufr
), getcolor(cp_menusel
));
1733 for(i
= executor
.begin(); i
!= executor
.end(); i
++) {
1734 if(!i
->fname
.empty()) rm
.additem(" " + justfname(i
->fname
) + ":" + i
->description
+ " ");
1735 else rm
.additem(" " + i
->description
);
1736 if(i
== currentmsg
) {
1737 rm
.setpos(i
-executor
.begin());
1742 if(!curfound
) currentmsg
= executor
.begin();
1743 if((h
= rm
.getcount()) > LINES
-3) h
= LINES
-3;
1744 rm
.setwindow(textwindow(0, LINES
-3-h
, COLS
-1, LINES
-2, getcolor(cp_menufr
)));
1746 if(start
= (pos
= rm
.open())) {
1747 currentmsg
= executor
.begin()+pos
-1;
1756 ui
.log(_("No build messages"));
1760 void ncursesui::nextmessage() {
1761 if(executor
.begin() != executor
.end()) {
1762 if(++currentmsg
!= executor
.end()) {
1766 log(_("At the end of the messages"));
1771 bool ncursesui::createproject() {
1773 INT nopt
, nproj
, citem
, n
, b
;
1774 bool ret
= false, gnudoc
, gettextized
, gensource
;
1775 enum {cmscratch
, cmfiles
, cmvcs
} mode
= cmscratch
;
1776 string templname
, pname
, rootdir
, vcsroot
, vcsmodule
, vcsrevision
, buf
, savename
;
1777 motorproject::makemodekind makemode
= motorproject::automake
;
1779 motorproject oldproject
;
1781 vector
<string
> vcses
;
1782 vector
<string
>::iterator ivcs
;
1784 gnudoc
= gensource
= true;
1785 gettextized
= false;
1787 vcses
= manager
.getvcslist();
1788 ivcs
= vcses
.begin();
1790 db
.setwindow(new textwindow(0, 0, DIALOG_WIDTH
, DIALOG_HEIGHT
,
1791 getcolor(cp_menufr
), TW_CENTERED
, getcolor(cp_menuhl
),
1792 _(" Create a new project ")));
1794 db
.setbar(new horizontalbar(getcolor(cp_menu
), getcolor(cp_menusel
),
1795 _("Change"), _("Create"), NULL_CONST_STR
));
1797 db
.settree(new treeview(getcolor(cp_menu
), getcolor(cp_menusel
),
1798 getcolor(cp_menu
), getcolor(cp_menu
)));
1800 treeview
&tree
= *db
.gettree();
1802 for(bool fin
= false; !fin
; ) {
1805 nproj
= tree
.addnode(0, getcolor(cp_menuhl
), NULL
, _(" Project "));
1807 tree
.addleaff(nproj
, 0, 10, _(" Creation mode : %s "),
1808 mode
== cmscratch
? _("from scratch") :
1809 mode
== cmfiles
? _("from files") : _("from VCS"));
1811 tree
.addleaff(nproj
, 0, 11, _(" Template : %s "), templname
.empty() ? _("none") : templname
.c_str());
1812 tree
.addleaff(nproj
, 0, 12, _(" New project name : %s "), pname
.c_str());
1813 tree
.addleaff(nproj
, 0, 13, _(" Root directory : %s "), rootdir
.c_str());
1814 tree
.addleaff(nproj
, 0, 14, _(" Makefile mode : %s "), MAKEMODE_TO_STR(makemode
));
1815 tree
.addleaff(nproj
, 0, 15, _(" GNU standard documentation : %s "), BOOL_TO_STR(gnudoc
));
1816 tree
.addleaff(nproj
, 0, 19, _(" Use GNU gettext for internationalization : %s "), BOOL_TO_STR(gettextized
));
1818 if(mode
!= cmfiles
) {
1819 nopt
= tree
.addnode(0, getcolor(cp_menuhl
), NULL
, _(" Creation "));
1821 if(mode
== cmscratch
) {
1822 tree
.addleaff(nopt
, 0, 16, _(" Generate inital source: %s "), BOOL_TO_STR(gensource
));
1823 } else if(mode
== cmvcs
) {
1824 tree
.addleaff(nopt
, 0, 20, _(" VCS name : %s "), ivcs
->c_str());
1825 tree
.addleaff(nopt
, 0, 17, _(" Repository : %s "), vcsroot
.c_str());
1826 tree
.addleaff(nopt
, 0, 18, _(" Module name : %s "), vcsmodule
.c_str());
1827 tree
.addleaff(nopt
, 0, 21, _(" Revision : %s "), vcsrevision
.c_str());
1831 if(!db
.open(n
, b
, (void **) &citem
)) {
1841 mode
= mode
== cmscratch
? cmfiles
:
1842 mode
== cmfiles
? cmvcs
:
1846 makemode
= motorproject::manual
;
1848 if((mode
== cmvcs
) && vcses
.empty()) {
1849 log(_("No version control systems defined"));
1856 templname
= selecttemplate(templname
);
1860 if(input(motorui::text
, pname
, _("project name: ")) == motorui::yes
) {
1861 buf
= rootdir
.substr(0, conf
.getdefaultprojectsdir().size());
1862 if(vcsmodule
.empty()) vcsmodule
= pname
;
1863 if(rootdir
.empty() || (buf
== conf
.getdefaultprojectsdir())) {
1864 rootdir
= trailcut(conf
.getdefaultprojectsdir(), "/") + "/" + pname
;
1870 input(motorui::directory
, rootdir
, _("root directory: "));
1871 if(pname
.empty()) pname
= justfname(rootdir
);
1876 makemode
== motorproject::manual
?
1877 motorproject::automake
:
1878 motorproject::manual
;
1881 case 15: gnudoc
= !gnudoc
; break;
1882 case 16: gensource
= !gensource
; break;
1885 input(motorui::text
, vcsroot
, _("VCS repository to check out from: "));
1889 input(motorui::text
, vcsmodule
, _("VCS module name: "));
1892 case 19: gettextized
= !gettextized
; break;
1895 if(++ivcs
== vcses
.end())
1896 ivcs
= vcses
.begin();
1900 input(motorui::text
, vcsrevision
, _("VCS revision: "));
1911 if(rootdir
.empty()) {
1912 log(_("Project root directory must be set"));
1918 log(_("Project name must be set"));
1923 if(templname
.empty()) {
1924 log(_("Template must be set"));
1929 if(!(mp
= projectname(pname
)).empty()) {
1930 logf(_("Project named %s already exists"), pname
.c_str());
1935 if(pname
.substr(0, 1).find_first_of("0123456789") != -1) {
1936 log(_("Project name cannot start with a number"));
1942 if(vcsroot
.empty() || vcsmodule
.empty()) {
1943 log(_("VCS name, repository and module name must be specified"));
1949 if(access(rootdir
.c_str(), F_OK
))
1950 if(ret
= (ask("YNC", _("root directory you specified does not exist. create?")) == motorui::yes
)) {
1955 if(access(rootdir
.c_str(), R_OK
| W_OK
| X_OK
)) {
1956 log(_("Access denied for the directory specified"));
1964 savename
= project
.getname();
1967 if(project
.close()) {
1968 project
= motorproject();
1970 project
.setname(pname
);
1971 project
.setversion("0.1");
1972 project
.settemplate(templname
);
1973 project
.setrootdir(rootdir
);
1974 project
.setgettextized(gettextized
);
1975 project
.setmakemode(makemode
);
1978 if(gnudoc
) n
|= CR_GNU_DOC
;
1982 if(gensource
) n
|= CR_GENERATE_SOURCE
;
1985 project
.setvcs(*ivcs
);
1986 project
.setvcsroot(vcsroot
);
1987 project
.setvcsmodule(vcsmodule
, vcsrevision
);
1991 if(!(ret
= project
.create(n
))) {
1992 if(!savename
.empty()) {
1993 project
= motorproject(projectname(savename
));
1997 vector
<motordist
>::const_iterator di
;
1998 vector
<motordist::distparam
>::const_iterator pi
;
2000 for(di
= project
.distbegin(); di
!= project
.distend(); ++di
)
2001 for(pi
= di
->parambegin(); pi
!= di
->paramend(); ++pi
)
2002 distparams
[pi
->name
] = pi
->defval
;
2010 void ncursesui::dist() {
2011 INT maxl
, i
, b
, fid
;
2015 vector
<motordist
>::const_iterator di
;
2016 vector
<motordist::distparam
>::const_iterator pi
;
2018 verticalmenu
mdist(getcolor(cp_menu
), getcolor(cp_menusel
));
2020 if(project
.distbegin() == project
.distend()) {
2021 logf(_("No distribution methods defined in template %s"),
2022 project
.gettemplatename().c_str());
2027 distdir
= project
.getrootdir();
2029 for(maxl
= 0, di
= project
.distbegin(); di
!= project
.distend(); di
++) {
2030 if(maxl
< di
->getname().size()) maxl
= di
->getname().size();
2031 mdist
.additem(" " + di
->getname());
2034 db
.setwindow(wdist
= new textwindow(0, 0, DIALOG_WIDTH
, DIALOG_HEIGHT
, getcolor(cp_menufr
),
2035 TW_CENTERED
, getcolor(cp_menuhl
), _(" Distribution package generation ")));
2037 mdist
.setwindow(textwindow(wdist
->x1
+6, wdist
->y1
+1, wdist
->x1
+9+maxl
,
2038 wdist
->y1
+2+mdist
.getcount(), getcolor(cp_menufr
)));
2040 db
.settree(new treeview(getcolor(cp_menu
), getcolor(cp_menusel
),
2041 getcolor(cp_menu
), getcolor(cp_menu
)));
2043 db
.setbar(new horizontalbar(getcolor(cp_menu
),
2044 getcolor(cp_menusel
), _("Change"), _("Go!"), NULL_CONST_STR
));
2046 di
= project
.distbegin();
2047 treeview
&tree
= *db
.gettree();
2049 for(fin
= r
= false, first
= true; !fin
&& !r
; ) {
2052 i
= tree
.addnode(0, getcolor(cp_menuhl
), NULL
, _(" Format "));
2053 fid
= tree
.addleaf(i
, 0, NULL
, " " + di
->getname() + " ");
2055 i
= tree
.addnode(0, getcolor(cp_menuhl
), NULL
, _(" Out directory "));
2056 tree
.addleaf(i
, 0, NULL
, " " + distdir
+ " ");
2058 for(pi
= di
->parambegin(); pi
!= di
->paramend(); ++pi
) {
2059 if(pi
== di
->parambegin())
2060 i
= tree
.addnode(0, getcolor(cp_menuhl
), NULL
, _(" Parameters "));
2062 tree
.addleaff(i
, 0, NULL
, " %s : %s ", pi
->title
.c_str(), distparams
[pi
->name
].c_str());
2072 if(!db
.open(i
, b
)) break;
2075 if(!(r
= (b
== 1))) {
2077 if(mdist
.getcount() == 1) {
2078 di
= project
.distbegin();
2080 if(i
= mdist
.open()) {
2081 di
= project
.distbegin()+i
-1;
2086 input(motorui::directory
, distdir
, _("directory to put a dist to: "));
2088 pi
= di
->parambegin()+i
-6;
2089 input(motorui::directory
, distparams
[pi
->name
], pi
->title
+ ": ");
2096 for(map
<string
, string
>::const_iterator mi
= distparams
.begin(); mi
!= distparams
.end(); ++mi
)
2097 executor
.setvar(mi
->first
, mi
->second
);
2103 void ncursesui::executordone(const string
&target
, INT nerr
, INT nwarn
, INT ninfo
) {
2104 if(nerr
|| nwarn
|| ninfo
) {
2105 logf(_("Finished ~%s~: ~%lu~ errors, ~%lu~ warnings, ~%lu~ infos. ~F6~ to see the list"),
2106 target
.c_str(), nerr
, nwarn
, ninfo
);
2108 logf(_("~%s~ finished sucessfully"), target
.c_str());
2112 void ncursesui::projectedit(projeditaction pea
, bool setcurrent
) {
2113 bool modified
= false;
2116 case psettings
: modified
= projectsettings(); break;
2117 case pfiles
: modified
= projectcontents(pea
, setcurrent
); break;
2118 case pdirs
: modified
= projectcontents(pea
); break;
2121 if(project
.modified() || modified
) {
2122 log(_("The project has been modified. Regenerating the build stuff.."));
2123 project
.regenerate();
2128 void ncursesui::maketarget() {
2130 static vector
<string
> targets
;
2133 vector
<string
>::iterator is
;
2136 db
.setwindow(new textwindow(0, 0, DIALOG_WIDTH
, DIALOG_HEIGHT
,
2137 getcolor(cp_menufr
), TW_CENTERED
, getcolor(cp_menuhl
),
2138 _(" Make a target.. ")));
2139 db
.setmenu(new verticalmenu(getcolor(cp_menu
), getcolor(cp_menusel
)));
2140 db
.setbar(new horizontalbar(getcolor(cp_menu
), getcolor(cp_menusel
),
2141 _("Add"), _("Remove"), _("Make"), NULL_CONST_STR
));
2143 db
.addkey(KEY_IC
, 0);
2144 db
.addkey(KEY_DC
, 1);
2145 db
.getbar()->item
= 2;
2147 for(bool fin
= false; !fin
; ) {
2148 db
.getmenu()->clear();
2149 for(is
= targets
.begin(); is
!= targets
.end(); is
++)
2150 db
.getmenu()->additem(" " + *is
);
2151 db
.getmenu()->setpos(pos
);
2153 if(!(fin
= !db
.open(i
, b
))) {
2154 pos
= db
.getmenu()->getpos();
2158 if(input(motorui::text
, buf
= "", _("make a target: ")) == motorui::yes
) {
2159 targets
.push_back(buf
);
2163 if(fin
= !targets
.empty()) {
2164 tomake
= targets
[i
-1];
2168 if(!targets
.empty())
2169 targets
.erase(targets
.begin()+i
);
2177 if(!tomake
.empty()) {
2178 project
.runtarget(tomake
);
2182 void ncursesui::setdebugcurrentline(const editfile ef
) {
2183 static INT prevfn
, prevline
;
2184 static string prevfname
;
2185 vector
<breakpoint
> bps
;
2186 vector
<breakpoint
>::iterator ibp
;
2188 if((prevfname
!= ef
.fname
) || (prevline
!= ef
.y
)) {
2189 ed
.unlight(prevfn
, prevline
);
2191 if(ed
.getfid(prevfn
)) {
2192 bps
= debugger
.getbreakpoints();
2194 if((ibp
= find(bps
.begin(), bps
.end(), pair
<string
, INT
>(ed
.getfid(prevfn
), prevline
))) != bps
.end())
2195 if(ibp
->permanent())
2196 ed
.highlight(prevfn
, ibp
->getline(), cp_debug_breakpoint
);
2199 if(!ef
.fname
.empty()) {
2201 ed
.highlight(ed
.getfnum(), ef
.y
, cp_debug_current
);
2204 prevfname
= ef
.fname
;
2205 prevfn
= ed
.getfnum();
2212 void ncursesui::evaluate(const string
&e
) {
2218 db
.setwindow(new textwindow(0, 0, DIALOG_WIDTH
, (INT
) (DIALOG_HEIGHT
*0.45),
2219 getcolor(cp_menufr
), TW_CENTERED
,
2220 getcolor(cp_menuhl
), _(" Evaluate/Modify ")));
2222 db
.settree(new treeview(getcolor(cp_menu
), getcolor(cp_menusel
),
2223 getcolor(cp_menu
), getcolor(cp_menu
)));
2225 db
.setbar(new horizontalbar(getcolor(cp_menu
),
2226 getcolor(cp_menusel
), _("Change"), NULL_CONST_STR
));
2228 if(!e
.empty()) re
= e
;
2230 treeview
&tree
= *db
.gettree();
2232 for(bool fin
= false; !fin
; ) {
2234 val
= debugger
.getvar(re
);
2239 i
= tree
.addnode(0, getcolor(cp_menuhl
), NULL
, _(" Expression "));
2240 nexp
= tree
.addleaf(i
, 0, NULL
, " " + re
+ " ");
2242 i
= tree
.addnode(0, getcolor(cp_menuhl
), NULL
, _(" Value "));
2243 tree
.addleaf(i
, 0, NULL
, " " + (val
.empty() ? _("not available") : val
) + " ");
2249 if(!db
.open(i
, b
)) break;
2254 fin
= input(motorui::text
, re
, _("expression: ")) != motorui::yes
;
2257 watcher
.modify(re
, val
);
2265 void ncursesui::settings() {
2268 bool fdispvcs
, fdispmake
, fdispcomp
, fdebugstd
, fchecktty
, fmcedclip
, fsmarttab
;
2271 db
.setwindow(new textwindow(0, 0, DIALOG_WIDTH
, DIALOG_HEIGHT
,
2272 getcolor(cp_menufr
), TW_CENTERED
, getcolor(cp_menuhl
),
2273 _(" Motor settings ")));
2275 db
.setbar(new horizontalbar(getcolor(cp_menu
),
2276 getcolor(cp_menusel
), _("Change"), _("Done"), NULL_CONST_STR
));
2278 db
.settree(new treeview(getcolor(cp_menu
), getcolor(cp_menusel
),
2279 getcolor(cp_menu
), getcolor(cp_menu
)));
2281 treeview
&tree
= *db
.gettree();
2283 fdebugstd
= conf
.getdebugstd();
2284 fdefprojdir
= conf
.getdefaultprojectsdir();
2285 fchecktty
= conf
.getchecktty();
2286 fmcedclip
= uiconf
.getmcedclip();
2287 fsmarttab
= uiconf
.getsmarttab();
2289 conf
.getdisplay(fdispmake
, fdispcomp
, fdispvcs
);
2291 for(bool fin
= false; !fin
; ) {
2294 n
= tree
.addnode(0, getcolor(cp_menuhl
), NULL
, _(" Show the run-time output "));
2295 tree
.addleaff(n
, 0, 1, _(" show compiler output : %s "), BOOL_TO_STR(fdispcomp
));
2296 tree
.addleaff(n
, 0, 2, _(" show VCS output : %s "), BOOL_TO_STR(fdispvcs
));
2297 tree
.addleaff(n
, 0, 3, _(" show make output : %s "), BOOL_TO_STR(fdispmake
));
2299 n
= tree
.addnode(0, getcolor(cp_menuhl
), NULL
, _(" Debugger "));
2300 tree
.addleaff(n
, 0, 5, _(" debug standard headers : %s "), BOOL_TO_STR(fdebugstd
));
2301 tree
.addleaff(n
, 0, 7, _(" disable free tty check : %s "), BOOL_TO_STR(!fchecktty
));
2303 n
= tree
.addnode(0, getcolor(cp_menuhl
), NULL
, _(" Editor "));
2304 tree
.addleaff(n
, 0, 9, _(" enable \"smart tabs\" feature : %s "), BOOL_TO_STR(fsmarttab
));
2305 tree
.addleaff(n
, 0, 8, _(" enable mcedit clipboard integration : %s "), BOOL_TO_STR(fmcedclip
));
2307 n
= tree
.addnode(0, getcolor(cp_menuhl
), NULL
, _(" Directories and paths "));
2308 tree
.addleaff(n
, 0, 6, _(" default directory for projects : %s "), fdefprojdir
.c_str());
2310 if(!db
.open(n
, b
, (void **) &citem
)) break;
2314 case 1: fdispcomp
= !fdispcomp
; break;
2315 case 2: fdispvcs
= !fdispvcs
; break;
2316 case 3: fdispmake
= !fdispmake
; break;
2317 case 5: fdebugstd
= !fdebugstd
; break;
2319 input(motorui::directory
, fdefprojdir
, _("default directory for projects: "));
2321 case 7: fchecktty
= !fchecktty
; break;
2322 case 8: fmcedclip
= !fmcedclip
; break;
2323 case 9: fsmarttab
= !fsmarttab
; break;
2325 conf
.setdefaultprojectsdir(fdefprojdir
);
2326 conf
.setdisplay(fdispmake
, fdispcomp
, fdispvcs
);
2327 conf
.setdebugstd(fdebugstd
);
2328 conf
.setchecktty(fchecktty
);
2329 uiconf
.setmcedclip(fmcedclip
);
2331 uiconf
.setsmarttab(fsmarttab
);
2332 ed
.smarttab
= fsmarttab
;
2342 void ncursesui::extkeylist() {
2344 vector
<motorconfiguration::extkey
>::const_iterator ik
;
2345 verticalmenu
m(getcolor(cp_menufr
), getcolor(cp_menusel
));
2347 if(count
= conf
.extkeyend()-conf
.extkeybegin()) {
2348 for(ik
= conf
.extkeybegin(); ik
!= conf
.extkeyend(); ik
++) {
2349 m
.additem(" " + ik
->description());
2352 m
.setwindow(textwindow(1, 1, (INT
) (COLS
*0.8), count
> LINES
-4 ? LINES
-4 : count
+2,
2353 getcolor(cp_menufr
), 0, getcolor(cp_menuhl
), _(" External programs ")));
2358 if(i
) (conf
.extkeybegin()+i
-1)->exec();
2360 log(_("No external keys defined"));
2364 void ncursesui::reloadeditfiles() {
2365 vector
<motorui::editfile
> openfiles
;
2366 vector
<motorui::editfile
>::iterator iof
;
2368 openfiles
= geteditfiles();
2373 for(iof
= openfiles
.begin(); iof
!= openfiles
.end(); iof
++) {
2379 void ncursesui::externalexec(INT options
, const string
&cmd
) {
2384 attrset(normalcolor(0));
2386 for(i
= 0; i
<= LINES
; i
++) cout
<< endl
;
2389 system(cmd
.c_str());
2391 if(options
& EE_PAUSE
) {
2392 cout
<< _("Press Enter to continue..") << flush
;
2401 void ncursesui::showbreakpoints() {
2404 vector
<breakpoint
> bps
;
2405 vector
<breakpoint
>::iterator ib
;
2408 db
.setwindow(new textwindow(0, 0, DIALOG_WIDTH
, DIALOG_HEIGHT
,
2409 getcolor(cp_menufr
), TW_CENTERED
,
2410 getcolor(cp_menuhl
), _(" Breakpoints ")));
2412 db
.settree(new treeview(getcolor(cp_menu
), getcolor(cp_menusel
),
2413 getcolor(cp_menu
), getcolor(cp_menu
)));
2415 db
.setbar(new horizontalbar(getcolor(cp_menu
),
2416 getcolor(cp_menusel
), _("Remove"), _("Goto"), NULL_CONST_STR
));
2418 db
.addkey(KEY_DC
, 0);
2419 db
.getbar()->item
= 1;
2421 treeview
&tree
= *db
.gettree();
2423 for(bool fin
= false; !fin
; ) {
2429 ef
= editfile(ed
.getfid(), x
, y
+1);
2432 for(bps
= debugger
.getbreakpoints(), ib
= bps
.begin(); ib
!= bps
.end(); ib
++) {
2433 i
= tree
.addleaff(0, 0, (ib
-bps
.begin()+1), " %s:%lu ",
2434 ib
->getfname().c_str(), ib
->getline());
2436 if((ib
->getfname() == ef
.fname
) && (ib
->getline() == ef
.y
))
2441 if(!db
.open(n
, b
, (void **) &i
)) break;
2446 ib
= bps
.begin()+i
-1;
2447 debugger
.removebreakpoint(*ib
);
2451 ib
= bps
.begin()+i
-1;
2452 ef
= editfile(ib
->getfname(), 0, ib
->getline());
2459 if(!ef
.fname
.empty()) {
2463 ed
.markbreakpoints();
2466 void ncursesui::generate() {
2469 vector
<sourcetemplate
> tg
;
2470 vector
<sourcetemplate
>::const_iterator it
;
2471 vector
<sourcetemplate
>::iterator itg
;
2474 db
.setwindow(new textwindow(0, 0, DIALOG_WIDTH
, DIALOG_HEIGHT
,
2475 getcolor(cp_menufr
), TW_CENTERED
, getcolor(cp_menuhl
),
2476 _(" Files to generate ")));
2478 db
.setmenu(new verticalmenu(getcolor(cp_menu
), getcolor(cp_menusel
)));
2480 db
.setbar(new horizontalbar(getcolor(cp_menu
), getcolor(cp_menusel
),
2481 _("Mark"), _("Generate"), NULL_CONST_STR
));
2484 verticalmenu
&menu
= *db
.getmenu();
2486 for(bool fin
= false; !fin
; ) {
2489 for(it
= project
.templbegin(); it
!= project
.templend(); it
++) {
2490 menu
.additemf(" [%c] %s ",
2491 find(tg
.begin(), tg
.end(), it
->getfname()) != tg
.end() ? 'x' : ' ',
2492 it
->getfname().c_str());
2495 if(!db
.open(n
, b
)) break;
2498 it
= project
.templbegin()+n
-1;
2500 if((itg
= find(tg
.begin(), tg
.end(), it
->getfname())) != tg
.end()) {
2513 for(it
= tg
.begin(); it
!= tg
.end(); it
++) {
2519 void ncursesui::arguments() {
2522 if(input(motorui::text
, buf
= project
.getarguments(),
2523 _("arguments: ")) != motorui::cancel
) {
2524 project
.setarguments(buf
);
2528 void ncursesui::loadcore() {
2530 string corefname
, r
;
2533 if(input(motorui::file
, corefname
= project
.getrootdir() + "/core",
2534 _("Core dump to explore: ")) == motorui::yes
) {
2535 if(!(r
= debugger
.loadcore(corefname
)).empty()) {
2538 db
.setwindow(new textwindow(0, 0, DIALOG_WIDTH
, DIALOG_HEIGHT
,
2539 getcolor(cp_menufr
), TW_CENTERED
, getcolor(cp_menuhl
),
2540 _(" Core dump load results ")));
2542 db
.setbar(new horizontalbar(getcolor(cp_menu
),
2543 getcolor(cp_menusel
), _("Inspect stack"), _("Close"), NULL_CONST_STR
));
2545 db
.setbrowser(new textbrowser(getcolor(cp_menu
)));
2546 db
.getbrowser()->setbuf(r
);
2548 for(bool fin
= false; !fin
; ) {
2549 fin
= !db
.open(n
, b
) || b
;
2550 if(!fin
) fin
= showstack();
2558 bool ncursesui::showstack() {
2561 vector
<stackitem
> stack
;
2562 vector
<stackitem
>::iterator i
;
2563 static INT savecount
= 0, citem
;
2569 if(!(stack
= debugger
.getstack()).empty()) {
2570 db
.setwindow(new textwindow(0, 0, DIALOG_WIDTH
, DIALOG_HEIGHT
,
2571 getcolor(cp_menufr
), TW_CENTERED
,
2572 getcolor(cp_menuhl
), _(" Call stack ")));
2574 db
.setmenu(new verticalmenu(getcolor(cp_menu
), getcolor(cp_menusel
)));
2575 db
.setbar(new horizontalbar(getcolor(cp_menu
), getcolor(cp_menusel
),
2576 _("Info"), _("Go to"), NULL_CONST_STR
));
2578 db
.getbar()->item
= 1;
2580 for(i
= stack
.begin(); i
!= stack
.end(); i
++) {
2581 db
.getmenu()->additemf(" %s() ", i
->getname().c_str());
2584 if(savecount
!= stack
.size()) {
2585 savecount
= stack
.size();
2588 db
.getmenu()->setpos(citem
);
2591 for(bool fin
= false; !fin
; ) {
2592 if(!(fin
= !db
.open(n
, b
))) {
2593 i
= stack
.begin()+n
-1;
2597 desc
= _("Function:");
2598 desc
+= "\n " + i
->getname() + "\n\n";
2599 desc
+= _("Location:");
2602 if(i
->getlocation().fname
.empty()) desc
+= "unknown";
2603 else desc
+= i
->getlocation().fname
+ ":" + i2str(i
->getlocation().y
);
2606 desc
+= _("Arguments:");
2607 desc
+= "\n " + i
->getarguments();
2609 textbox(desc
, _(" Stack item details "));
2622 loadeditfile(i
->getlocation());
2629 void ncursesui::setdesktop(const vector
< pair
<string
, string
> > &asettings
) {
2630 string afilter
, param
, buf
;
2631 vector
< pair
<string
, string
> >::const_iterator i
;
2632 vector
< pair
<char, string
> >::const_iterator ik
;
2637 for(ik
= project
.tagnamebegin(); ik
!= project
.tagnameend(); ++ik
)
2638 afilter
+= ik
->first
;
2640 uitb
.setfilter(afilter
);
2642 for(i
= asettings
.begin(); i
!= asettings
.end(); i
++) {
2643 if(i
->first
== "ncurses_watchactive") {
2644 if(i
->second
== "1") watcher
.activate();
2646 } else if(i
->first
== "distdir") {
2647 distdir
= i
->second
;
2649 } else if(i
->first
.substr(0, 9) == "distparam") {
2651 param
= getword(buf
);
2652 distparams
[param
] = buf
;
2654 } else if(i
->first
== "tagbrowser_scope") {
2655 tagbrowser
.setscope((motortagbrowser::viewscope
)
2656 strtoul(i
->second
.c_str(), 0, 0));
2658 } else if(i
->first
== "tagbrowser_filter") {
2659 uitb
.setfilter(i
->second
);
2665 vector
< pair
<string
, string
> > ncursesui::getdesktop() const {
2667 vector
< pair
<string
, string
> > r
;
2669 r
.push_back(pair
<string
, string
>("ncurses_watchactive",
2670 watcher
.visible() ? "1" : "0"));
2672 r
.push_back(pair
<string
, string
>("distdir", distdir
));
2673 r
.push_back(pair
<string
, string
>("tagbrowser_scope", i2str((INT
) tagbrowser
.getscope())));
2674 r
.push_back(pair
<string
, string
>("tagbrowser_filter", uitb
.getfilter()));
2677 for(map
<string
, string
>::const_iterator ip
= distparams
.begin(); ip
!= distparams
.end(); ++ip
, pn
++)
2678 r
.push_back(make_pair(string("distparam") + i2str(pn
), ip
->first
+ " " + ip
->second
));
2683 void ncursesui::updatewatches() {
2687 bool ncursesui::editmodified() const {
2688 return ed
.anymodified();
2691 void ncursesui::onprojectload() {
2693 project
.debugload();
2694 ed
.markbreakpoints();
2695 selector
.setstartpoint(project
.getrootdir());
2696 logf(_("Project %s has been loaded"), project
.getname().c_str());
2699 motorui::askresult
ncursesui::notemplate(string
&templname
) const {
2701 sprintf(buf
, _("%s not found, please select template"), templname
.c_str());
2702 string nt
= selecttemplate("", buf
);
2704 if(!nt
.empty()) templname
= nt
; else
2710 bool ncursesui::editbuildoptions(motorfile
&f
) const {
2713 bool enabled
, start
;
2714 motorfile::build bd
= f
.getbuild();
2716 db
.setwindow(new textwindow(0, 0, (INT
) (DIALOG_WIDTH
*0.9), (INT
) (DIALOG_HEIGHT
*0.6),
2717 getcolor(cp_menufr
), TW_CENTERED
,
2718 getcolor(cp_menuhl
), _(" %s build options "),
2719 f
.getfname().c_str()));
2721 db
.settree(new treeview(getcolor(cp_menu
), getcolor(cp_menusel
),
2722 getcolor(cp_menu
), getcolor(cp_menu
)));
2724 db
.setbar(new horizontalbar(getcolor(cp_menu
),
2725 getcolor(cp_menusel
), _("Change"), _("Done"), NULL_CONST_STR
));
2727 treeview
&tree
= *db
.gettree();
2730 enabled
= !bd
.param
.empty();
2732 for(bool fin
= false; !fin
; ) {
2735 i
= tree
.addnode(0, getcolor(cp_menuhl
), NULL
, _(" General "));
2736 tree
.addleaff(i
, 0, 1, _(" Enable optional build : %s "), BOOL_TO_STR(enabled
));
2739 i
= tree
.addnode(0, getcolor(cp_menuhl
), NULL
, _(" Build "));
2740 tree
.addleaff(i
, 0, 2, _(" Parameter name (--enable-xxx) : %s "), bd
.param
.c_str());
2741 tree
.addleaff(i
, 0, 3, _(" Parameter help text : %s "), bd
.help
.c_str());
2742 tree
.addleaff(i
, 0, 4, _(" Enabled by default : %s "), BOOL_TO_STR(bd
.def
));
2745 if(!db
.open(n
, b
, (void **) &citem
)) break;
2749 case 1: enabled
= !enabled
; break;
2750 case 2: ui
.input(motorui::text
, bd
.param
, _("configure parameter name (--enable-xxx): ")); break;
2751 case 3: ui
.input(motorui::text
, bd
.help
, _("help text: ")); break;
2752 case 4: bd
.def
= !bd
.def
; break;