/* Copyright (c) 2002 * Marko Boomstra (m.boomstra@chello.nl). All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include "mudix.h" //#define CSI_DEBUG /* * Defines */ #define MAX_HISTORY 100 /* * Locals */ int check_esc(char *pBuf, int *attrib); char history [MAX_HISTORY][LINE_MAXIM]; char *pHistory [MAX_HISTORY]; char **pCurHist = pHistory; char **pGetHist = pHistory; bool fCharacterMode = FALSE; void init_history(void) { int index; for (index = 0; index < MAX_HISTORY; index++) { pHistory[index] = &history[index][0]; history[index][0] = '\0'; } return; } void read_input(void) { static int input[LINE_MAXIM]; int *in = input, i = 0, value = 0; while((*in = fgetc(stdin)) != EOF) { #if KEY_DEBUG wprintw(wInput, "", *in); #endif in++; if ((in-input) >= INPUT_MAX) break; } #if KEY_DEBUG wprintw(wInput, "<%d-%d>", *in, in-input); #endif if (in == input) return; if (input[0] == ESC) while (i < (in-input)) value += input[i++]; #if KEY_DEBUG wprintw(wInput, "", value); #endif switch (value) { case 0: { int length = in-input; in = input; while (length-- > 0) { if (isprint(*in)) { if (pEndIn >= (inbuf+INPUT_MAX)) { beep(); break; } if (fCharacterMode) { char k[2]; k[0] = (char)*in; k[1] = '\0'; process_input(k, NULL, FALSE); break; } pCursor++; if (fEchoIn) { waddch(wInput, *in); } else { waddch(wInput, '*'); } } switch (*in) { case TAB: check_tab(inbuf, pEndIn); break; case BS: case BACKSPACE: if (pCursor == pEndIn) { if (pEndIn > inbuf) { pEndIn--; pCursor--; } else break; if (pCursor >= (LINE_LENGTH + inbuf)) print_cmd_line(); else backspace(); } else { char *pTemp; if (pCursor > inbuf) { pCursor--; move_cursor(wInput, LEFT, 1); } else break; pTemp = pCursor; while (pTemp != pEndIn) { *pTemp = *(pTemp+1); pTemp++; } pEndIn--; print_cmd_line(); if (pCursor < (LINE_LENGTH + inbuf)) wmove(wInput, 0, pCursor-inbuf); } break; case CR: *pEndIn++ = '\n'; *pEndIn = '\0'; /* put command in history */ if (pEndIn - inbuf >= 4 && fEchoIn) { char *pTempHis = *pCurHist; char *pTempBuf = inbuf; while(*pTempBuf != '\n') *pTempHis++ = *pTempBuf++; *pTempHis = '\0'; if (pCurHist == &pHistory[MAX_HISTORY-1]) pCurHist = pGetHist = &pHistory[0]; else pGetHist = ++pCurHist; } process_input(inbuf, NULL, FALSE); werase(wInput); pEndIn = inbuf; pCursor = inbuf; break; default: *pEndIn++ = *in; if (pCursor == pEndIn) { if (pCursor >= (LINE_LENGTH + inbuf)) print_cmd_line(); } else { char *pTemp; pCursor--; pTemp = pEndIn-1; while (pTemp != pCursor) { *pTemp = *(pTemp-1); pTemp--; } *pCursor++ = *in; print_cmd_line(); if (pCursor < (LINE_LENGTH + inbuf)) wmove(wInput, 0, pCursor-inbuf); } break; } in++; } break; } case ESC: if (panel_hidden(pMsg) == PANEL_VISIBLE) hide_panel(pMsg); else if (panel_hidden(pScroll) == PANEL_VISIBLE) hide_panel(pScroll); else if (panel_hidden(pStatus) == PANEL_VISIBLE) hide_panel(pStatus); break; case F1: case F2: case F3: case F4: case F5: case F6: case F7: case F8: case F9: case F10: case F11: case F12: process_alias(value); break; case HOME: if (fKeypadWalk) process_input("u", NULL, TRUE); else { pCursor = inbuf; print_cmd_line(); wmove(wInput, 0, 0); } break; case END: if (fKeypadWalk) process_input("d", NULL, TRUE); else { pCursor = pEndIn; print_cmd_line(); } break; case PGUP: show_scroll(UP, SCROLL_SIZE); break; case PGDWN: show_scroll(DOWN, SCROLL_SIZE); break; case L_ALT('1'): show_triggers(); break; case L_ALT('2'): show_aliases(); break; case L_ALT('3'): show_paths(); break; case L_ALT('4'): show_tabs(); break; case L_ALT('5'): show_vars(); break; case L_ALT('m'): fCharacterMode ^= TRUE; if (fCharacterMode) { do_status("Character mode turned ON.", 3); hide_panel(pBanner); hide_panel(pInput); wresize(wMain, LEN_ROW, LEN_COL); } else { do_status("Character mode turned OFF.", 3); show_panel(pBanner); show_panel(pInput); wresize(wMain, LEN_ROW-2, LEN_COL); } break; case L_ALT('h'): do_help(); break; case L_ALT('q'): dialog("Are you sure you want to quit? (Y/N)"); settings->state = STATE_QUIT; break; case L_ALT('r'): fReconnect = TRUE; do_status("Reconnect requested.", 3); break; case L_ALT('t'): dialog("Toggle which trigger? (#)"); settings->state = STATE_TTOGGLE; break; case L_ALT('s'): show_settings(); break; case L_ALT('c'): dialog("What text should initiate the login procedure?"); settings->state = STATE_CREATE_1; break; case L_ALT('i'): fEchoIn ^= TRUE; if (fEchoIn) do_status("Input echo turned ON.", 3); else do_status("Input echo turned OFF.", 3); break; case L_ALT('o'): fEchoOut ^= TRUE; if (fEchoOut) do_status("Command echo turned ON.", 3); else do_status("Command echo turned OFF.", 3); break; case L_ALT('p'): fPrintTime ^= TRUE; if (fPrintTime) do_status("Time displayed.", 3); else do_status("Time display disabled.", 3); break; case L_ALT('k'): fKeypadWalk ^= TRUE; if (fKeypadWalk) do_status("Keypad walking enabled.", 3); else do_status("Keypad walking disabled.", 3); break; case L_ALT('a'): if (!fStatusReport) { fStatusReport = TRUE; do_status("Status reports enabled.", 3); } else { do_status("Status reports disabled.", 3); fStatusReport = FALSE; } break; case ARROW_U: case XARROW_U: if (fKeypadWalk) { process_input("n", NULL, TRUE); break; } if (panel_hidden(pScroll) == PANEL_VISIBLE) { show_scroll(UP, 1); break; } if (pGetHist == &pHistory[0]) pGetHist = &pHistory[MAX_HISTORY-1]; else pGetHist--; werase(wInput); if (**pGetHist != '\0') { char *pTemp = inbuf; char *pHtmp = *pGetHist; while(*pHtmp != '\0') *pTemp++ = *pHtmp++; *pTemp = '\0'; pEndIn = pCursor = pTemp; if (pCursor >= (LINE_LENGTH + inbuf)) print_cmd_line(); else { waddnstr(wInput, inbuf, pTemp - inbuf); } } else pEndIn = pCursor = inbuf; break; case ARROW_D: case XARROW_D: if (fKeypadWalk) { process_input("s", NULL, TRUE); break; } if (panel_hidden(pScroll) == PANEL_VISIBLE) { show_scroll(DOWN, 1); break; } if (pGetHist == &pHistory[MAX_HISTORY-1]) pGetHist = &pHistory[0]; else pGetHist++; werase(wInput); if (**pGetHist != '\0') { char *pTemp = inbuf; char *pHtmp = *pGetHist; while(*pHtmp != '\0') *pTemp++ = *pHtmp++; *pTemp = '\0'; pEndIn = pCursor = pTemp; if (pCursor >= (LINE_LENGTH + inbuf)) print_cmd_line(); else { waddnstr(wInput, inbuf, pTemp - inbuf); } } else pEndIn = pCursor = inbuf; break; case ARROW_R: case XARROW_R: if (fKeypadWalk) { process_input("e", NULL, TRUE); break; } if (pCursor < pEndIn) { pCursor++; if (pCursor >= (LINE_LENGTH + inbuf)) print_cmd_line(); else move_cursor(wInput, RIGHT, 1); } break; case ARROW_L: case XARROW_L: if (fKeypadWalk) { process_input("w", NULL, TRUE); break; } if (pCursor > inbuf) { pCursor--; if (pCursor >= (LINE_LENGTH + inbuf)) print_cmd_line(); else move_cursor(wInput, LEFT, 1); } break; default: break; } return; } void process_input(char *input, char *args, bool fReturn) { char cmd[MAX_STRING]; while (*input != '\0') { input = parse_input(input, args, cmd, fReturn); if (cmd[0] == '#') { /* it's a MUDix command */ do_command(&cmd[1]); /* do not pass the '#' */ continue; } if (process_naming(cmd)) continue; if (!settings->state) { if (fEchoOut) { wattrset(wMain, COLOR_PAIR(COL_GREEN)|A_NORMAL); waddstr(wMain, cmd); put_in_scroll(cmd, NULL, COLOR_PAIR(COL_GREEN)|A_NORMAL); wattrset(wMain, COLOR_PAIR(0)|A_NORMAL); } strcat(send_buffer, cmd); } else set_settings(cmd); } return; } int fill_param(int *npar, char *pBuf, int *params) { char local[24]; char *pLoc = local; if (*npar >= CSIPARAMS) return 0; while (pBuf < pOut) { if (*pBuf == ';' || (*pBuf != ' ' && !isdigit(*pBuf))) { *pLoc = '\0'; params[(*npar)++] = local[0]? atoi(local): 0; #ifdef CSI_DEBUG { FILE *fp = fopen("log", "a+"); fprintf(fp, "<%d-%s-%c>\n", *npar, local, *pBuf); fclose(fp); } #endif return pLoc-local; } *pLoc++ = *pBuf++; } return 0; } bool iscsiseq(char c) { if ((c>='A' && c<='J') || (c>='K' && c<='M') || (c>='c' && c<='h') || (c>='l' && c<='n') || (c>='q' && c<='s') || c=='P' || c=='X' || c=='a' || c=='u' || c=='`') return TRUE; return FALSE; } int check_esc(char *pBuf, int *attrib) { char *pBegin = pBuf; int params[CSIPARAMS], npar, i; if (*pBuf++ != ESC || pBuf >= pOut) /* push character back */ return 0; if (*pBuf++ != '[') /* only accept "ESC [" */ return 1; npar = 0; while (pBuf < pOut) { if (isdigit(*pBuf)) pBuf += fill_param(&npar, pBuf, params); if (iscsiseq(*pBuf)) { static int x_cur, y_cur; /* cursor position for store/restore */ int x, y; switch (*pBuf++) { case '@': for (i=0; i