📄 int_streams.c
字号:
/* * Same as printf but on stderr and then generate an error */ void C_Errorf(char **argv){ char result[PrintfStrLength+1]; _CPrintf(argv,result); SetErrorf("%s",result); InitResult(); Errorf1("");}/* * The sprintf command */ void C_SPrintf(char **argv){ char result[PrintfStrLength+1]; char *var; argv = ParseArgv(argv,tVNAME,&var,-1); _CPrintf(argv,result); SetStrVariable(var,result); SetResultStr(result);}/*************************************************************** * * Functions for terminal line edition * ***************************************************************/ static void DeleteSelection(){ int i; if (toplevelCur->termSelSize != 0) { for (i = 0; toplevelCur->termCursor+i+toplevelCur->termSelSize <= strlen(toplevelCur->termLine);i++) toplevelCur->termLine[toplevelCur->termCursor+i] = toplevelCur->termLine[toplevelCur->termCursor+i+toplevelCur->termSelSize]; toplevelCur->termSelSize = 0; }}/* * Inserting a string in the terminal line at the cursor position. * If there is a new line then we print the new line at the end of the terminal line and stop. * * WARNING : the string might change ! * */void TermInsertStr(char *str){ int flagNewLine; int l,i,ls; char *str1,*str2; DeleteSelection(); flagNewLine = NO; /* Looking for the end of 'str' or for the first new line */ str1 = str; while (*str1 != '\0' && *str1 != '\n' && *str1 != '\r') str1++; if (*str1 != '\0') { flagNewLine = YES; *str1 = '\0'; } ls = strlen(str); l = strlen(toplevelCur->termLine); /* Too many characters already ! */ if (l + ls + flagNewLine> MaxLengthTermLine) {TerminalBeep();return;} /* Case the 'str' is not empty or just equal to "\n" */ if (ls != 0) { /* In case the cursor is at the end of the line we just need to append... */ if (toplevelCur->termLine[toplevelCur->termCursor] == '\0') { str1 = str; while (*str1 != '\0') { XXTerminalInsertChar(*str1,""); str1++; } } /* Otherwise we insert it */ else { for (i = l+ls; i > toplevelCur->termCursor+ls-1;i--) toplevelCur->termLine[i] = toplevelCur->termLine[i-ls]; str1 = str; while (*(str1+1) != '\0') { XXTerminalInsertChar(*str1,""); str1++; } XXTerminalInsertChar(*str1,toplevelCur->termLine+i+ls); } /* We copy the string and update the cursor */ str1 = str; str2 = toplevelCur->termLine + toplevelCur->termCursor; while (*str1 != '\0') { *str2 = *str1; str2++; str1++; } toplevelCur->termCursor += ls; toplevelCur->termLine[l+ls] = '\0'; } /* Manage the new line if any */ if (flagNewLine) { if (toplevelCur->termCursor != l) XXTerminalCursorGoForward(l-toplevelCur->termCursor); toplevelCur->termCursor = l; toplevelCur->termLine[l+ls] = '\n'; toplevelCur->termLine[l+ls+1] = '\0'; XXTerminalPrintChar('\n'); } /* And flush ! */// XXTerminalFlush();} /* * Delete n characters just before the cursor */void TermDeleteNChars(int n,char flagBeep) { int l,i; if (n <= 0) return; if (toplevelCur->termSelSize != 0) { DeleteSelection(); XXTerminalInsertChar(' ',(char *) (toplevelCur->termLine+toplevelCur->termCursor)); XXTerminalDeleteInsertChar(1,toplevelCur->termLine+toplevelCur->termCursor); n--; if (n <= 0) return; } l = strlen(toplevelCur->termLine); if (toplevelCur->termCursor < n) { if (flagBeep) {TerminalBeep(); return;} else n = toplevelCur->termCursor; } /* In case the cursor is at the end of the line we just need to erase the last N chars */ if (toplevelCur->termLine[toplevelCur->termCursor] == '\0') { toplevelCur->termLine[l-n] = '\0'; XXTerminalDeleteInsertChar(n,""); } /* Otherwise we must shift left what's on the right of the cursor */ else { for (i = toplevelCur->termCursor-n; i+n <= l;i++) toplevelCur->termLine[i] = toplevelCur->termLine[i+n]; XXTerminalDeleteInsertChar(n,toplevelCur->termLine+toplevelCur->termCursor-n); } toplevelCur->termCursor -= n; XXTerminalFlush();}/* * Move the cursor */static void TermMoveCursor(int n,char flagBeep){ if (n == 0) return; toplevelCur->termSelSize = 0; /* Backward */ if (n < 0) { if (-n > toplevelCur->termCursor) { if (flagBeep) {TerminalBeep(); return;} n = -toplevelCur->termCursor; } if (n != 0) { toplevelCur->termCursor += n; XXTerminalCursorGoBackward(-n); } } /* Forward */ else { if (n > strlen(toplevelCur->termLine) - toplevelCur->termCursor) { if (flagBeep) {TerminalBeep(); return;} n = strlen(toplevelCur->termLine) - toplevelCur->termCursor; } if (n != 0) { toplevelCur->termCursor += n; XXTerminalCursorGoForward(n); } }}/*************************************************************** * * The main command for terminal line edition * ***************************************************************/void C_Terminal(char **argv){ char *action,*str; int n; int x,y,w,h; LWPROC proc; char *c; LISTV lv; FONT font; argv = ParseArgv(argv,tWORD,&action,-1); /* Erase line action */ if (!strcmp(action,"eraseline")) { NoMoreArgs(argv); TermMoveCursor(MaxLengthTermLine,NO); TermDeleteNChars(MaxLengthTermLine,NO); } /* Erase chars action */ else if (!strcmp(action,"erasechars")) { argv = ParseArgv(argv,tINT_,1,&n,0); TermDeleteNChars(n,YES); } /* Clear action */ else if (!strcmp(action,"clear")) { argv = ParseArgv(argv,0); XXClear(); } /* Set font action */ else if (!strcmp(action,"setfont")) { argv = ParseArgv(argv,tFONT,&font,0); XXSetFont(NULL,font); } /* movecursor action */ else if (!strcmp(action,"movecursor")) { argv = ParseArgv(argv,tINT,&n,0); TermMoveCursor(n,NO); } /* getsize action */ else if (!strcmp(action,"getsize")) { NoMoreArgs(argv); XXTerminalGetsizeWindow(&w,&h); lv = TNewListv(); AppendInt2Listv(lv,w); AppendInt2Listv(lv,h); SetResultValue((VALUE) lv); } /* cursor action */ else if (!strcmp(action,"cursor")) { if (*argv == NULL) SetResultInt(toplevelCur->termCursor); else { argv = ParseArgv(argv,tINT,&n,0); TermMoveCursor(n-toplevelCur->termCursor,NO); } } /* prompt action */ else if (!strcmp(action,"prompt")) { if (*argv == NULL) { GetPrompt(&str); SetResultStr(str); } else { argv = ParseArgv(argv,tPROC,&proc,0); if (proc->flagSP == NO) Errorf("Sorry, the prompt procedure must be a script procedure"); if (toplevelCur->promptProc != NULL) DeleteProc(toplevelCur->promptProc); toplevelCur->promptProc = proc; proc->nRef++; } } /* beep action */ else if (!strcmp(action,"beep")) { NoMoreArgs(argv); TerminalBeep(); } /* Insert action */ else if (!strcmp(action,"insert")) { argv = ParseArgv(argv,tSTR,&str,0); while (*str != '\0') { TermBufferPushKey(*str); str++; } } /* line action */ else if (!strcmp(action,"line")) { argv = ParseArgv(argv,tSTR_,NULL,&str,0); if (str == NULL) SetResultStr(toplevelCur->termLine); else { TermMoveCursor(MaxLengthTermLine,NO); TermDeleteNChars(MaxLengthTermLine,NO); /* ????? */ if ((c = strchr(str,'\n')) || (c = strchr(str,'\r'))) *c = '\0'; TermInsertStr(str);/* while (*str != '\0') { TermBufferPushKey(*str); str++; } */ } } /* eof action */ else if (!strcmp(action,"eof")) { argv = ParseArgv(argv,0); TermBufferPushKey(EofKC); } /* state action */ else if (!strcmp(action,"mode")) { NoMoreArgs(argv); if (toplevelCur->termMode == ScanTMode) SetResultStr("scanline"); else if (toplevelCur->termMode == GetcharTMode) SetResultStr("getchar"); else if (toplevelCur->termMode == CommandTMode) SetResultStr("command"); else SetResultStr("unknown"); } /* movewindow action */ else if (!strcmp(action,"movewindow")) { argv = ParseArgv(argv,tINT,&x,tINT,&y,0); if (x <= 0 || y <=0) Errorf("No negative values allowed for window position"); XXTerminalMoveWindow(x,y); } /* resizewindow action */ else if (!strcmp(action,"resizewindow")) { argv = ParseArgv(argv,tINT,&x,tINT,&y,0); if (x <= 0 || y <=0) Errorf("No negative values allowed for window size"); XXTerminalResizeWindow(x,y); } /* change the way the result will be printed */ else if (!strcmp(action,"result")) { argv = ParseArgv(argv,tSTR,&str); if (!strcmp(str,"normal")) toplevelCur->termResultMode = TermResultNormalMode; else if (!strcmp(str,"hack")) toplevelCur->termResultMode = TermResultHackMode; else Errorf("Bad mode '%s'",str); } /* Erase chars action */ else if (!strcmp(action,"flush")) { NoMoreArgs(argv); Flush(); } /* Unknown action */ else Errorf("Unknown action '%s'",action); }/*************************************************************** * * Basic functions for terminal key event management * ***************************************************************//* * Initialization of the current terminal line */void InitTerminalInput(void){ toplevelCur->termLine[0] = '\0'; toplevelCur->termCursor = 0; toplevelCur->termSelSize = 0;} /* * Push a key code in the terminal buffer (called by ProcessNextEvent) */void TermBufferPushKey(unsigned long c){ PushBuffer(_StdinStream->buffer,c);}/* * Wait for the next terminal keyPress and returns the corresponding key code * if delay is non negative then wait only for delay seconds */static unsigned long WaitForTerminalKeyPress(LWFLOAT delay){ unsigned long key = 0; LWFLOAT t; if (delay <0) t = MyTime(); else t = MyTime()+delay; while((key = PullBuffer(_StdinStream->buffer)) == 0 && (delay < 0 || MyTime() < t)) { Flush(); } return(key);} /* * Pull terminal line characters up to 'pos' (excluded) and copy them in out (if out != NULL) */static void PullTermLine(char *pos,char *out){ char *line = toplevelCur->termLine; char *line1; if (pos == line) { if (out == NULL) return; out[0] = '\0'; } if (out != NULL) { line1 = line; while(line1 != pos) *(out++) = *(line1++); *out = '\0'; } while (*pos != '\0') *(line++) = *(pos++); *line = '\0'; toplevelCur->termCursor = line-toplevelCur->termLine;} /* * Function to call for allowing the user to write a whole line on the terminal * Basically it loops until a newline or an eof is typed */ char DoLineTerm(void){ unsigned long c; char *str; /* Otherwise we have to wait */ while (1) { /* Get the next char and echo it */ c = WaitForTerminalKeyPress(-1); if (c == DeleteKC) TermDeleteNChars(1,YES); else if (c != EofKC) { str = KeyCode2Str(c,YES); TermInsertStr(str); } /* Stops if EOF or \n or \r */ if (c == EofKC || c == NewlineKC) break; } } /************************************************************** * * Functions and commands for getting a key from any stream * *************************************************************//* * Getting a char from any stream and returns it (or returns EOF) * * if delay is non negative, waiyts only for delay seconds */long FGetChar(STREAM stream, LWFLOAT delay){ unsigned long c; if (stream->mode != StreamRead) Errorf("FGetChar() : stream '%d' not readable",stream->id); /* Case the stdin is the terminal */ if (stream == _StdinStream) { toplevelCur->oldTermMode = toplevelCur->termMode; toplevelCur->termMode = GetcharTMode; c = WaitForTerminalKeyPress(delay); toplevelCur->termMode = toplevelCur->oldTermMode; if (c == EofKC) c = EOF; } /* Case the stdin is a string stream */ else if (stream->buffer != NULL) { c = PullBuffer(stream->buffer); if (c == EofKC) c = EOF; } /* Case the stdin is a file */ else { c = fgetc(stream->stream); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -