1 ////////////////////////////////////////////////////////////////////////////////
2 static K8Term
*oldTerm
;
4 static K8Term
*newTerm
;
6 static int newTermSwitch
;
9 #define CMDLD(_t) (K8T_DATA(_t)->cmdline)
12 typedef void (*CmdHandlerFn
) (const char *cmdname
, char *argstr
);
20 static void cmdPastePrimary (const char *cmdname
, char *argstr
) {
21 selpaste(curterm
, XA_PRIMARY
);
25 static void cmdPasteSecondary (const char *cmdname
, char *argstr
) {
26 selpaste(curterm
, XA_SECONDARY
);
30 static void cmdPasteClipboard (const char *cmdname
, char *argstr
) {
31 selpaste(curterm
, XA_CLIPBOARD
);
35 static void cmdExec (const char *cmdname
, char *argstr
) {
36 if (curterm
!= NULL
) {
37 if (K8T_DATA(curterm
)->execcmd
!= NULL
) free(K8T_DATA(curterm
)->execcmd
);
38 K8T_DATA(curterm
)->execcmd
= (argstr
[0] ? strdup(argstr
) : NULL
);
43 static int parseTabArgs (char *argstr
, int *noswitch
, int nowrap
, int idx
) {
47 while (*argstr
&& isspace(*argstr
)) ++argstr
;
48 if (!argstr
[0]) break;
49 if (iniParseArguments(argstr
, "s-R-", &arg
, &argstr
) != NULL
) break;
51 if (strcasecmp(arg
, "noswitch") == 0) *noswitch
= 1;
52 else if (strcasecmp(arg
, "switch") == 0) *noswitch
= 0;
53 else if (strcasecmp(arg
, "nowrap") == 0) nowrap
= 1;
54 else if (strcasecmp(arg
, "wrap") == 0) nowrap
= 0;
55 else if (strcasecmp(arg
, "first") == 0) idx
= 0;
56 else if (strcasecmp(arg
, "last") == 0) idx
= term_count
-1;
57 else if (strcasecmp(arg
, "prev") == 0) idx
= -1;
58 else if (strcasecmp(arg
, "next") == 0) idx
= -2;
63 n
= strtol(arg
, &eptr
, 0);
64 if (!eptr
[0] && n
>= 0 && n
< term_count
) idx
= n
;
69 if ((idx
= termidx
-1) < 0) idx
= nowrap
? 0 : term_count
-1;
72 if ((idx
= termidx
+1) >= term_count
) idx
= nowrap
? term_count
-1 : 0;
79 static void flushNewTerm (void) {
80 if (newTerm
!= NULL
) {
81 if (newTermSwitch
&& curterm
!= NULL
) curterm
->lastActiveTime
= mclock_ticks();
83 //termidx = newTermIdx;
84 k8t_tmInitialize(newTerm
, term_array
[0]->col
, term_array
[0]->row
, opt_maxhistory
);
85 termCreateXPixmap(newTerm
);
87 if (k8t_ttyNew(newTerm
) != 0) {
93 k8t_ttyResize(newTerm
);
97 switchToTerm(newTermIdx
, 1);
102 termidx
= oldTermIdx
;
110 static void cmdNewTab (const char *cmdname
, char *argstr
) {
111 int noswitch
= 0, idx
;
113 if (opt_disabletabs
) return;
115 if ((newTerm
= k8t_termalloc()) == NULL
) return;
116 /*idx =*/ parseTabArgs(argstr
, &noswitch
, 0, termidx
);
119 if (curterm
!= NULL
) curterm
->lastActiveTime
= mclock_ticks();
122 newTermIdx
= termidx
= idx
;
124 newTermSwitch
= !noswitch
;
128 static void cmdCloseTab (const char *cmdname
, char *argstr
) {
130 if (curterm
!= NULL
&& !curterm
->dead
) kill(K8T_DATA(curterm
)->pid
, SIGTERM
);
134 static void cmdKillTab (const char *cmdname
, char *argstr
) {
136 if (!curterm
->dead
) kill(K8T_DATA(curterm
)->pid
, SIGKILL
);
140 static void cmdSwitchToTab (const char *cmdname
, char *argstr
) {
141 int noswitch
= 0, idx
;
144 idx
= parseTabArgs(argstr
, &noswitch
, 0, -666);
146 switchToTerm(idx
, 1);
148 oldTermIdx
= termidx
;
153 static void cmdMoveTabTo (const char *cmdname
, char *argstr
) {
154 int noswitch
= 0, idx
;
157 idx
= parseTabArgs(argstr
, &noswitch
, 0, termidx
);
158 if (idx
!= termidx
&& idx
>= 0 && idx
< term_count
) {
159 K8Term
*t
= term_array
[termidx
];
161 // remove current term
162 for (int f
= termidx
+1; f
< term_count
; ++f
) term_array
[f
-1] = term_array
[f
];
164 for (int f
= term_count
-2; f
>= idx
; --f
) term_array
[f
+1] = term_array
[f
];
175 static void cmdDefaultFG (const char *cmdname
, char *argstr
) {
179 if (iniParseArguments(argstr
, "i{0,511}|s-", &c
, &s
) == NULL
) {
180 if (s
!= NULL
&& tolower(s
[0]) == 'g') defaultFG
= c
; else curterm
->deffg
= c
;
185 static void cmdDefaultBG (const char *cmdname
, char *argstr
) {
189 if (iniParseArguments(argstr
, "i{0,511}|s-", &c
) == NULL
) {
190 if (s
!= NULL
&& tolower(s
[0]) == 'g') {
194 XSetWindowBackground(xw
.dpy
, xw
.win
, getColor(curterm
->defbg
));
195 if (newTerm
== NULL
) {
196 k8t_tmFullDirty(curterm
);
197 k8t_drawTerm(curterm
, 1);
205 static void scrollHistory (K8Term
*term
, int delta
) {
206 if (term
== NULL
|| term
->maxhistory
< 1) return; // no history
207 term
->topline
+= delta
;
208 if (term
->topline
> term
->maxhistory
) term
->topline
= term
->maxhistory
;
209 if (term
->topline
< 0) term
->topline
= 0;
210 k8t_tmFullDirty(term
);
211 k8t_drawTerm(term
, 1);
215 static void cmdScrollHistoryLineUp (const char *cmdname
, char *argstr
) {
216 scrollHistory(curterm
, 1);
220 static void cmdScrollHistoryPageUp (const char *cmdname
, char *argstr
) {
221 scrollHistory(curterm
, curterm
->row
);
225 static void cmdScrollHistoryLineDown (const char *cmdname
, char *argstr
) {
226 scrollHistory(curterm
, -1);
230 static void cmdScrollHistoryPageDown (const char *cmdname
, char *argstr
) {
231 scrollHistory(curterm
, -curterm
->row
);
235 static void cmdScrollHistoryTop (const char *cmdname
, char *argstr
) {
236 scrollHistory(curterm
, curterm
->linecount
);
240 static void cmdScrollHistoryBottom (const char *cmdname
, char *argstr
) {
241 scrollHistory(curterm
, -curterm
->linecount
);
245 static void cmdCommandMode (const char *cmdname
, char *argstr
) {
246 if (curterm
!= NULL
) {
247 if (CMDLD(curterm
).cmdMode
== K8T_CMDMODE_NONE
) tcmdlineinit(curterm
, &CMDLD(curterm
)); else tcmdlinehide(curterm
, &CMDLD(curterm
));
253 static void cmdCursor (const char *cmdname
, char *argstr
) {
254 if (curterm
!= NULL
) {
257 if (iniParseArguments(argstr
, "s!-", &s
) != NULL
) {
258 tcmdlinemsgf(curterm
, &CMDLD(curterm
), "cursor is %s", ((curterm
->c
.state
&K8T_CURSOR_HIDE
) ? "hidden" : "visible"));
260 if (strcasecmp(s
, "show") == 0) curterm
->c
.state
&= ~K8T_CURSOR_HIDE
;
261 else if (strcasecmp(s
, "hide") == 0) curterm
->c
.state
|= K8T_CURSOR_HIDE
;
262 k8t_tmWantRedraw(curterm
, 0);
268 static void cmdReset (const char *cmdname
, char *argstr
) {
271 if (curterm
!= NULL
) {
272 if (iniParseArguments(argstr
, "|s-", &s
) == NULL
) {
274 switch (tolower(s
[0])) {
276 k8t_tmResetMode(curterm
);
279 k8t_tmResetAttrs(curterm
);
281 case 'g': // graphics
282 curterm
->mode
&= ~(K8T_MODE_GFX0
|K8T_MODE_GFX1
);
283 curterm
->charset
= K8T_MODE_GFX0
;
286 curterm
->csaved
.state
= curterm
->c
.state
= K8T_CURSOR_DEFAULT
;
291 tcmdlinemsgf(curterm
, &CMDLD(curterm
), "Reset (a)ll | (c)olor | (g)raphics | c(u)rsor");
297 static void cmdScreen (const char *cmdname
, char *argstr
) {
298 if (curterm
!= NULL
) {
301 if (iniParseArguments(argstr
, "s!-", &s
) != NULL
) {
302 tcmdlinemsgf(curterm
, &CMDLD(curterm
), "screen: %s", (K8T_ISSET(curterm
, K8T_MODE_ALTSCREEN
) ? "alt" : "norm"));
304 if (strcasecmp(s
, "norm") == 0) {
305 if (K8T_ISSET(curterm
, K8T_MODE_ALTSCREEN
)) k8t_tmSwapScreen(curterm
);
306 } else if (strcasecmp(s
, "alt") == 0) {
307 if (!K8T_ISSET(curterm
, K8T_MODE_ALTSCREEN
)) k8t_tmSwapScreen(curterm
);
315 static void cmdMouseReports (const char *cmdname
, char *argstr
) {
316 if (curterm
!= NULL
) {
319 if (iniParseArguments(argstr
, "b", &b
) != NULL
) {
320 tcmdlinemsgf(curterm
, &CMDLD(curterm
), "mouse reports are o%s", (K8T_ISSET(curterm
, K8T_MODE_MOUSE
) ? "n" : "ff"));
322 if (b
) curterm
->mode
|= K8T_MODE_MOUSEBTN
; else curterm
->mode
&= ~K8T_MODE_MOUSEBTN
;
328 static int cmd_parseIntArg (const char *fmt
, char *argstr
, int *b
, int *global
, int *toggle
) {
332 if (iniParseArguments(argstr
, "R-", &argstr
) != NULL
) break;
333 if (!argstr
[0]) break;
335 if (iniParseArguments(argstr
, "s!-R-", &s
, &argstr
) != NULL
) break;
336 if (global
&& tolower(s
[0]) == 'g') {
338 } else if (toggle
&& tolower(s
[0]) == 't') {
341 if (!b
|| iniParseArguments(s
, fmt
, b
) != NULL
) return -1;
348 static void cmdUTF8Locale (const char *cmdname
, char *argstr
) {
349 int b
= -1, toggle
= 0;
351 if (cmd_parseIntArg("b", argstr
, &b
, NULL
, &toggle
) != 0) return;
353 tcmdlinemsgf(curterm
, &CMDLD(curterm
), "UTF8Locale: %s", ((needConversion
? !curterm
->needConv
: 1) ? "yes" : "no"));
355 if (!needConversion
) b
= 1;
356 if (curterm
!= NULL
) curterm
->needConv
= !b
;
361 static void cmdAudibleBell (const char *cmdname
, char *argstr
) {
362 int b
= -1, toggle
= 0, global
= 0;
364 if (curterm
== NULL
) return;
365 if (cmd_parseIntArg("b", argstr
, &b
, &global
, &toggle
) != 0) return;
368 tcmdlinemsgf(curterm
, &CMDLD(curterm
), "AudibleBell: %s", (global
? opt_audiblebell
: (curterm
->belltype
&K8T_BELL_AUDIO
)) ? "yes" : "no");
371 if (global
) opt_audiblebell
= !opt_audiblebell
; else curterm
->belltype
^= K8T_BELL_AUDIO
;
373 if (global
) opt_audiblebell
= b
; else curterm
->belltype
= (curterm
->belltype
&~K8T_BELL_AUDIO
)|(b
!=0?K8T_BELL_AUDIO
:0);
379 static void cmdUrgentBell (const char *cmdname
, char *argstr
) {
380 int b
= -1, toggle
= 0, global
= 0;
382 if (curterm
== NULL
) return;
383 if (cmd_parseIntArg("b", argstr
, &b
, &global
, &toggle
) != 0) return;
386 tcmdlinemsgf(curterm
, &CMDLD(curterm
), "UrgentBell: %s", (global
? opt_urgentbell
: (curterm
->belltype
&K8T_BELL_URGENT
)) ? "yes" : "no");
389 if (global
) opt_urgentbell
= !opt_urgentbell
; else curterm
->belltype
^= K8T_BELL_URGENT
;
391 if (global
) opt_urgentbell
= b
; else curterm
->belltype
= (curterm
->belltype
&~K8T_BELL_URGENT
)|(b
!=0?K8T_BELL_URGENT
:0);
397 static void cmdMonochrome (const char *cmdname
, char *argstr
) {
398 int b
= -1, global
= 0;
400 if (curterm
== NULL
) return;
401 if (cmd_parseIntArg("i{0,3}", argstr
, &b
, &global
, NULL
) != 0) return;
404 b
= (global
? globalBW
: curterm
->blackandwhite
);
405 tcmdlinemsgf(curterm
, &CMDLD(curterm
), "Monochrome: %d", b
);
408 if (b
== 3) tcmdlinemsg(curterm
, &CMDLD(curterm
), "Monochrome-global can't be '3'!");
411 curterm
->blackandwhite
= b
;
414 k8t_tmFullDirty(curterm
);
419 static void cmdCursorBlink (const char *cmdname
, char *argstr
) {
420 int b
= -1, global
= 0;
422 if (curterm
== NULL
) return;
423 if (cmd_parseIntArg("i{0,10000}", argstr
, &b
, &global
, NULL
) != 0) return;
426 b
= (global
? opt_cursorBlink
: curterm
->curblink
);
427 tcmdlinemsgf(curterm
, &CMDLD(curterm
), "CursorBlink: %d", b
);
432 curterm
->curblink
= b
;
433 curterm
->curbhidden
= 0;
436 k8t_tmFullDirty(curterm
);
441 static void cmdCursorBlinkInactive (const char *cmdname
, char *argstr
) {
442 int b
= -1, global
= 0, toggle
= 0, *iptr
;
444 if (curterm
== NULL
) return;
445 if (cmd_parseIntArg("b", argstr
, &b
, &global
, &toggle
) != 0) return;
447 iptr
= (global
? &opt_cursorBlinkInactive
: &curterm
->curblinkinactive
);
449 if (toggle
) *iptr
= !(*iptr
); else *iptr
= b
;
450 k8t_drawTerm(curterm
, 0);
455 static void cmdIgnoreClose (const char *cmdname
, char *argstr
) {
458 if (curterm
== NULL
) return;
459 if (cmd_parseIntArg("i{-1,1}", argstr
, &b
, NULL
, NULL
) != 0) return;
462 tcmdlinemsgf(curterm
, &CMDLD(curterm
), "IgnoreClose: %d", opt_ignoreclose
);
469 static void cmdMaxHistory (const char *cmdname
, char *argstr
) {
470 int b
= -1, global
= 0;
472 if (curterm
== NULL
) return;
473 if (cmd_parseIntArg("i{0,65535}", argstr
, &b
, &global
, NULL
) != 0) return;
476 tcmdlinemsgf(curterm
, &CMDLD(curterm
), "MaxHistory: %d", (global
?opt_maxhistory
:curterm
->maxhistory
));
478 if (!global
) k8t_tmAdjMaxHistory(curterm
, b
); else opt_maxhistory
= b
;
483 static void cmdMaxDrawTimeout (const char *cmdname
, char *argstr
) {
486 if (curterm
== NULL
) return;
487 if (cmd_parseIntArg("i{100,60000}", argstr
, &b
, NULL
, NULL
) != 0) return;
490 tcmdlinemsgf(curterm
, &CMDLD(curterm
), "MaxDrawTimeout: %d", opt_maxdrawtimeout
);
492 opt_maxdrawtimeout
= b
;
497 static void cmdSwapDrawTimeout (const char *cmdname
, char *argstr
) {
500 if (curterm
== NULL
) return;
501 if (cmd_parseIntArg("i{10,60000}", argstr
, &b
, NULL
, NULL
) != 0) return;
504 tcmdlinemsgf(curterm
, &CMDLD(curterm
), "SwapDrawTimeout: %d", opt_swapdrawtimeout
);
506 opt_swapdrawtimeout
= b
;
511 static void cmdTabPosition (const char *cmdname
, char *argstr
) {
517 if (iniParseArguments(argstr
, "R-", &argstr
) != NULL
) break;
518 if (!argstr
[0]) break;
520 if (iniParseArguments(argstr
, "s!-R-", &s
, &argstr
) != NULL
) break;
521 if (tolower(s
[0]) == 't') newpos
= 1;
522 else if (tolower(s
[0]) == 'b') newpos
= 0;
523 else if (iniParseArguments(s
, "i{0,1}", &newpos
) != NULL
) return;
527 tcmdlinemsgf(curterm
, &CMDLD(curterm
), "TabPostion: %s", (opt_tabposition
== 0 ? "bottom" : "top"));
528 } else if (opt_tabposition
!= newpos
) {
529 opt_tabposition
= newpos
;
531 k8t_tmFullDirty(curterm
);
532 k8t_drawTerm(curterm
, 1);
539 static void cmdTabCount (const char *cmdname
, char *argstr
) {
542 if (curterm
== NULL
) return;
543 if (cmd_parseIntArg("i{1,128}", argstr
, &b
, NULL
, NULL
) != 0) return;
546 tcmdlinemsgf(curterm
, &CMDLD(curterm
), "TabCount: %d", opt_tabcount
);
547 } else if (opt_tabcount
!= b
) {
556 static void cmdDoFullRedraw (const char *cmdname
, char *argstr
) {
558 k8t_tmFullDirty(curterm
);
560 k8t_drawTerm(curterm
, 1);
565 static void cmdTitle (const char *cmdname
, char *argstr
) {
566 if (curterm
!= NULL
) {
569 if (iniParseArguments(argstr
, "s-", &s
) != NULL
|| s
== NULL
) return;
570 memset(curterm
->title
, 0, sizeof(curterm
->title
));
571 while (strlen(s
) > K8T_ESC_TITLE_SIZ
) k8t_UTF8ChopLast(s
);
572 fprintf(stderr
, "[%s]\n", s
);
573 strncpy(curterm
->title
, s
, K8T_ESC_TITLE_SIZ
);
574 fixWindowTitle(curterm
);
581 static void cmdFastRedraw (const char *cmdname
, char *argstr
) {
582 int b
= -1, global
= 0, toggle
= 0, *iptr
;
584 if (curterm
== NULL
) return;
585 if (cmd_parseIntArg("b", argstr
, &b
, &global
, &toggle
) != 0) return;
587 iptr
= (global
? &opt_fastredraw
: &curterm
->fastredraw
);
589 if (toggle
) *iptr
= !(*iptr
); else *iptr
= b
;
590 k8t_drawTerm(curterm
, 0);
592 tcmdlinemsgf(curterm
, &CMDLD(curterm
), "FastRedraw: %s", (*iptr
? "yes" : "no"));
597 static void cmdAbout (const char *cmdname
, char *argstr
) {
598 if (curterm
!= NULL
) {
599 tcmdlinemsgf(curterm
, &CMDLD(curterm
), "k8sterm " VERSION
);
604 static void cmdDebugDump (const char *cmdname
, char *argstr
) {
605 if (curterm
!= NULL
) {
608 if (iniParseArguments(argstr
, "s-", &s
) == NULL
) {
610 switch (tolower(s
[0])) {
613 curterm
->dumpescapes
= 0;
614 curterm
->dumpeskeys
= 0;
617 curterm
->dumpescapes
= 1;
618 curterm
->dumpeskeys
= 1;
621 curterm
->dumpescapes
= !curterm
->dumpescapes
;
624 curterm
->dumpeskeys
= !curterm
->dumpeskeys
;
629 tcmdlinemsgf(curterm
, &CMDLD(curterm
), "DbgDump (n)one | (a)ll | toggle (e)scapes | toggle extended (k)eys");
638 static void cmdTabEllipsis (const char *cmdname
, char *argstr
) {
641 if (curterm
== NULL
) return;
642 if (cmd_parseIntArg("i{0,3}", argstr
, &b
, NULL
, NULL
) != 0) return;
645 if (opt_tabellipsis
!= b
) {
651 tcmdlinemsgf(curterm
, &CMDLD(curterm
), "TabEllipsis: %d", opt_tabellipsis
);
656 static const Command commandList
[] = {
657 {"PastePrimary", cmdPastePrimary
},
658 {"PasteSecondary", cmdPasteSecondary
},
659 {"PasteClipboard", cmdPasteClipboard
},
661 {"NewTab", cmdNewTab
}, // 'noswitch' 'next' 'prev' 'first' 'last'
662 {"CloseTab", cmdCloseTab
},
663 {"KillTab", cmdKillTab
},
664 {"SwitchToTab", cmdSwitchToTab
}, // 'next' 'prev' 'first' 'last' 'nowrap' 'wrap'
665 {"MoveTabTo", cmdMoveTabTo
}, // 'next' 'prev' 'first' 'last' 'nowrap' 'wrap'
666 {"DefaultFG", cmdDefaultFG
},
667 {"DefaultBG", cmdDefaultBG
},
668 {"ScrollHistoryLineUp", cmdScrollHistoryLineUp
},
669 {"ScrollHistoryPageUp", cmdScrollHistoryPageUp
},
670 {"ScrollHistoryLineDown", cmdScrollHistoryLineDown
},
671 {"ScrollHistoryPageDown", cmdScrollHistoryPageDown
},
672 {"ScrollHistoryTop", cmdScrollHistoryTop
},
673 {"ScrollHistoryBottom", cmdScrollHistoryBottom
},
674 {"UTF8Locale", cmdUTF8Locale
}, // 'on', 'off'
675 {"AudibleBell", cmdAudibleBell
},
676 {"UrgentBell", cmdUrgentBell
},
677 {"CommandMode", cmdCommandMode
},
678 {"Cursor", cmdCursor
},
680 {"Screen", cmdScreen
},
681 {"MouseReports", cmdMouseReports
},
682 {"Monochrome", cmdMonochrome
},
683 {"Mono", cmdMonochrome
},
684 {"CursorBlink", cmdCursorBlink
},
685 {"CursorBlinkInactive", cmdCursorBlinkInactive
},
686 {"IgnoreClose", cmdIgnoreClose
},
687 {"MaxHistory", cmdMaxHistory
},
688 {"MaxDrawTimeout", cmdMaxDrawTimeout
},
689 {"SwapDrawTimeout", cmdSwapDrawTimeout
},
690 {"TabPosition", cmdTabPosition
},
691 {"TabCount", cmdTabCount
},
692 {"DoFullRedraw", cmdDoFullRedraw
},
694 {"FastRedraw", cmdFastRedraw
},
695 {"TabEllipsis", cmdTabEllipsis
},
702 {"DbgDump", cmdDebugDump
},
706 {"term", cmdTermName},
707 {"title", cmdWinTitle},
708 {"tabsize", cmdTabSize},
709 {"defaultcursorfg", cmdDefaultCursorFG},
710 {"defaultcursorbg", cmdDefaultCursorBG},
711 {"defaultinactivecursorfg", cmdDefaultInactiveCursorFG},
712 {"defaultinactivecursorbg", cmdDefaultInactiveCursorBG},
713 {"defaultboldfg", cmdDefaultBoldFG},
714 {"defaultunderlinefg", cmdDefaultUnderlineFG},
720 static const char *findCommandCompletion (const char *str
, int slen
, const char *prev
) {
721 const char *res
= NULL
;
724 if (slen
< 1) return NULL
;
725 for (int f
= 0; commandList
[f
].name
!= NULL
; ++f
) {
726 if (strlen(commandList
[f
].name
) >= slen
&& strncasecmp(commandList
[f
].name
, str
, slen
) == 0) {
727 if (prev
== NULL
|| phit
) return commandList
[f
].name
;
728 if (strcasecmp(commandList
[f
].name
, prev
) == 0) phit
= 1;
729 if (res
== NULL
) res
= commandList
[f
].name
;
736 // !0: NewTab command
737 static int executeCommand (const char *str
, int slen
) {
742 if (str
== NULL
) return 0;
743 if (slen
< 0) slen
= strlen(str
);
745 for (int f
= 0; f
< slen
; ++f
) if (!str
[f
]) { slen
= f
; break; }
747 while (slen
> 0 && isspace(*str
)) { ++str
; --slen
; }
748 if (slen
< 1 || !str
[0]) return 0;
750 for (e
= str
; slen
> 0 && !isspace(*e
); ++e
, --slen
) ;
752 if (e
-str
> 127) return 0;
753 cmdname
= alloca(e
-str
+8);
754 if (cmdname
== NULL
) return 0;
755 memcpy(cmdname
, str
, e
-str
);
757 if (opt_disabletabs
&& strcasecmp(cmdname
, "NewTab") == 0) return 1;
759 while (slen
> 0 && isspace(*e
)) { ++e
; --slen
; }
760 //FIXME: ugly copypaste!
762 for (int f
= 0; commandList
[f
].name
!= NULL
; ++f
) {
763 if (strcasecmp(commandList
[f
].name
, cmdname
) == 0 && commandList
[f
].fn
!= NULL
) {
764 char *left
= calloc(slen
+2, 1);
767 if (slen
> 0) memcpy(left
, e
, slen
);
768 //fprintf(stderr, "command: [%s]; args: [%s]\n", cmdname, left);
769 commandList
[f
].fn(cmdname
, left
);
778 char *left
= calloc(slen
+2, 1);
781 if (slen
> 0) memcpy(left
, e
, slen
);
782 processMiscCmds(cmdname
, left
);
792 static const char *cmdpSkipStr (const char *str) {
793 while (*str && isspace(*str)) ++str;
794 if (str[0] && str[0] != ';') {
798 if (*str == ';' && qch == ' ') break;
799 if (qch != ' ' && *str == qch) { qch = ' '; ++str; continue; }
800 if (*str == '"' || *str == '\'') {
801 if (qch == ' ') qch = *str;
805 if (*str++ == '\\' && *str) ++str;
813 static void executeCommands (const char *str
) {
815 oldTermIdx
= termidx
;
818 if (str
== NULL
) return;
823 while (*str
&& isspace(*str
)) ++str
;
825 if (*str
== ';') { ++str
; continue; }
830 if (*ce
== ';' && qch
== ' ') break;
831 if (qch
!= ' ' && *ce
== qch
) { qch
= ' '; ++ce
; continue; }
832 if (*ce
== '"' || *ce
== '\'') {
833 if (qch
== ' ') qch
= *ce
;
837 if (*ce
++ == '\\' && *ce
) ++ce
;
840 if (executeCommand(str
, ce
-str
)) break;
841 if (*ce
) str
= ce
+1; else break;
844 switchToTerm(oldTermIdx
, 1);