/* termios テストプログラム */ /* 入力プロンプト */ #include #include #include #include #include #include #define BUFSIZE 1024 #define HISTSIZE 1000 #define PROMPT printf("\r[prompt(%04d:%02x:%03d/%03d)] %s",\ incnt, inch, histcur, histnew, inbuff) int main() { struct termios save_term; struct termios temp_term; int wretc; int inch; char inbuff[BUFSIZE]; int incnt; char *space; int spaceidx; char history[BUFSIZE][HISTSIZE]; int histold; /* 再古ヒストリエントリ番号 */ int histnew; /* 再新ヒストリエントリ番号 */ int histcur; /* 現在のヒストリエントリ番号 */ int histtmp; /* 一時エントリ番号 */ int overlap; /* オーバラップ判定変数 */ /* 現在の入力設定を取得 */ wretc = tcgetattr(fileno(stdin), &save_term); if (wretc == -1) { perror("tcgetattr ERROR"); exit(1); } /* 現在の入力設定をコピー */ temp_term = save_term; /* 設定を変更 */ temp_term.c_iflag &= IGNCR; /* CR の入力を無視する */ temp_term.c_lflag &= ~ICANON; /* 非カノニカルモードにする */ temp_term.c_lflag &= ~ECHO; /* 入力のエコーを行わないようにする */ temp_term.c_lflag &= ~ISIG; /* シグナルを無視する */ wretc = tcsetattr(fileno(stdin), TCSANOW, &temp_term); if (wretc == -1) { perror("tcsetattr ERROR"); exit(1); } /* 入力を受け付ける */ inch = '\0'; histold = 0; histnew = 0; histcur = 0; overlap = 0; while (1) { incnt = 0; inbuff[0] = '\0'; PROMPT; /* 一行分の入力 */ while (1) { inch = getchar(); if (inch == 0x0d) { /* ENTER が入力された */ inbuff[incnt] = '\0'; if (incnt == 0) { printf("\n"); } else { printf("\ninput = %s\n", inbuff); } break; } else if (inch == 0x04) { /* Ctrl-D が入力された */ if (incnt == 0) { strcpy(inbuff, "exit"); } else { printf("\ninput = %s\n", inbuff); } break; } else if (inch == 0x08) { /* BackSpace/Ctrl-H が入力された */ /* 表示をクリアする */ inbuff[incnt - 1] = ' '; PROMPT; /* カーソルを一つ戻す */ if (incnt > 0) { incnt--; inbuff[incnt] = '\0'; } PROMPT; } else if (inch == 0x15) { /* Ctrl-U が入力された */ /* 表示をクリアする */ memset(inbuff, ' ', incnt); PROMPT; /* バッファをクリアする */ incnt = 0; inbuff[incnt] = '\0'; PROMPT; } else if (inch == 0x17) { /* Ctrl-W キーが入力された */ /* 空白位置を探す */ space = strrchr(inbuff, ' '); if (space == NULL) { /* 空白が入力されていない */ /* 表示をクリアする */ memset(inbuff, ' ', incnt); PROMPT; /* バッファをクリアする */ incnt = 0; } else { /* 空白が見つかった */ spaceidx = space - inbuff; while (spaceidx > 0) { spaceidx--; if (inbuff[spaceidx] != ' ') { spaceidx++; break; } } /* 表示をクリアする*/ memset(&(inbuff[spaceidx]), ' ', incnt - spaceidx); PROMPT; /* 空白以降をクリアする */ incnt = spaceidx; } inbuff[incnt] = '\0'; PROMPT; } else if (inch == 0x10 || inch == 0x41) { /* Ctrl-P/上キーが入力された */ if (histcur == histnew) { /* 現在入力中の文字列を記憶する */ strcpy(history[histcur], inbuff); } if (histcur != histold) { /* 表示をクリアする */ memset(inbuff, ' ', incnt); PROMPT; histcur--; if (histcur == -1) { histcur = HISTSIZE - 1; } strcpy(inbuff, history[histcur]); incnt = strlen(inbuff); PROMPT; } } else if (inch == 0x0e || inch == 0x42) { /* Ctrl-N/下キーが入力された */ if (histcur != histnew) { /* 表示をクリアする */ memset(inbuff, ' ', incnt); PROMPT; histcur++; if (histcur == HISTSIZE) { histcur = 0; } strcpy(inbuff, history[histcur]); incnt = strlen(inbuff); PROMPT; } } else if (inch == 0x5b) { PROMPT; } else { if (incnt < BUFSIZE - 1) { /* 制御文字でない場合にのみ入力バッファに入力する */ if (iscntrl(inch) == 0) { inbuff[incnt] = inch; incnt++; inbuff[incnt] = '\0'; } } /* 入力を受け付ける度に入力行を再表示する */ PROMPT; } } if (strcmp(inbuff, "exit") == 0) { break; } if (strcmp(inbuff, "history") == 0) { histtmp = histold; while (histtmp != histnew) { printf("[%d] %s\n", histtmp, history[histtmp]); histtmp++; if (histtmp == HISTSIZE) { histtmp = 0; } } } if (strlen(inbuff) != 0) { strcpy(history[histnew], inbuff); histnew++; if (histnew == HISTSIZE) { /* ヒストリがオーバラップした */ histnew = 0; overlap = 1; } if (overlap == 1) { histold = histnew + 1; if (histold == HISTSIZE) { histold = 0; } } histcur = histnew; } } /* 設定を元に戻す */ wretc = tcsetattr(fileno(stdin), TCSANOW, &save_term); if (wretc == -1) { perror("tcsetattr ERROR"); exit(1); } }