コマンド履歴、スクロール機能追加
@@ -16,6 +16,7 @@ | ||
16 | 16 | #include <bitnos/timer.h> |
17 | 17 | #include <bitnos/specialtask.h> |
18 | 18 | #include <bitnos/pit.h> |
19 | +#include <bitnos/scancode.h> | |
19 | 20 | |
20 | 21 | namespace TaskConsole |
21 | 22 | { |
@@ -108,6 +109,14 @@ | ||
108 | 109 | /* end of class ScreenBuffer */ |
109 | 110 | |
110 | 111 | |
112 | +// 定数 | |
113 | +const uint32_t TIMERDATA_CURSOR = 1; | |
114 | +const uint32_t TIMERDATA_BEEP = 2; | |
115 | + | |
116 | +const int COMMAND_MAXLENGTH = 127; // コマンド最大文字数 | |
117 | +const int COMMAND_HISTORYSIZE = 32; // 履歴を記憶する最大数 | |
118 | + | |
119 | + | |
111 | 120 | struct Valiables |
112 | 121 | { |
113 | 122 | Console cons; |
@@ -114,7 +123,7 @@ | ||
114 | 123 | Image* img; |
115 | 124 | Sheet* sht; |
116 | 125 | |
117 | - char cmdline[128]; | |
126 | + char cmdline[COMMAND_MAXLENGTH + 1]; | |
118 | 127 | int cmdlineBegin; |
119 | 128 | |
120 | 129 | Timer* tim; |
@@ -134,7 +143,7 @@ | ||
134 | 143 | |
135 | 144 | void PutString0(Valiables* o, const char* str, int len); |
136 | 145 | |
137 | -void ConsoleRefreshScreen(Valiables* o, int begin); | |
146 | +void ConsoleRefreshScreen(Valiables* o, int begin, int printBegin = -1); | |
138 | 147 | |
139 | 148 | void RunCommand(Valiables* o); |
140 | 149 |
@@ -143,6 +152,14 @@ | ||
143 | 152 | |
144 | 153 | void ConsoleMakeBorderLine(Image* img); |
145 | 154 | |
155 | +void PrintHistoryUp(Valiables* o); | |
156 | +void PrintHistoryDown(Valiables* o); | |
157 | + | |
158 | +void ClearInputString(Valiables* o); | |
159 | + | |
160 | +void ScrollUp(Valiables* o, int lines); | |
161 | +void ScrollDown(Valiables* o, int lines); | |
162 | + | |
146 | 163 | /* |
147 | 164 | * コンソールコマンド関数 |
148 | 165 | */ |
@@ -157,9 +174,6 @@ | ||
157 | 174 | static void cat(Valiables* o, const char* arg); |
158 | 175 | }; |
159 | 176 | |
160 | -const uint32_t TIMERDATA_CURSOR = 1; | |
161 | -const uint32_t TIMERDATA_BEEP = 2; | |
162 | - | |
163 | 177 | void Init(void* obj) |
164 | 178 | { |
165 | 179 | static int initialPosX = 110, initialPosY = 50; |
@@ -185,7 +199,7 @@ | ||
185 | 199 | o->active = SpecialTask::Get(SpecialTask::Active) == task; |
186 | 200 | |
187 | 201 | // 文字列バッファの準備 |
188 | - o->cons.sbuf.Init(o->cons.width, 20); | |
202 | + o->cons.sbuf.Init(o->cons.width, 50); | |
189 | 203 | |
190 | 204 | // バッファ内の書き込み位置 |
191 | 205 | o->cons.wPos = Point(0, 0); |
@@ -193,6 +207,14 @@ | ||
193 | 207 | // 画面内の表示位置 |
194 | 208 | o->cons.pPos = Point(0, 0); |
195 | 209 | |
210 | + o->cons.rLine = 0; | |
211 | + | |
212 | + // コマンド履歴バッファ関連 | |
213 | + o->cons.History.buf.Init(COMMAND_MAXLENGTH, COMMAND_HISTORYSIZE); | |
214 | + | |
215 | + o->cons.History.wPos = Point(0, 0); | |
216 | + o->cons.History.rPos = Point(0, 0); | |
217 | + | |
196 | 218 | // 画面のバッファ |
197 | 219 | o->img = new Image( |
198 | 220 | 8 + fontHankaku->GetWidth() * o->cons.width, |
@@ -231,12 +253,20 @@ | ||
231 | 253 | |
232 | 254 | if (msg->from == Message::From::Keyboard) { |
233 | 255 | if (msg->arg1 != 0) { |
234 | - //if (o->cursor) { | |
256 | + if (msg->arg1 < 0x80) { | |
235 | 257 | EraseCursor(o); |
236 | - //} | |
237 | - PutChar(o, msg->arg1); | |
238 | - if (o->cursor) { | |
239 | - ShowCursor(o); | |
258 | + PutChar(o, msg->arg1); | |
259 | + if (o->cursor) { | |
260 | + ShowCursor(o); | |
261 | + } | |
262 | + } else if (msg->arg1 == (uint32_t)ScanCode::Keys::KeyArrowUp) { | |
263 | + PrintHistoryUp(o); | |
264 | + } else if (msg->arg1 == (uint32_t)ScanCode::Keys::KeyArrowDown) { | |
265 | + PrintHistoryDown(o); | |
266 | + } else if (msg->arg1 == (uint32_t)ScanCode::Keys::KeyPageUp) { | |
267 | + ScrollUp(o, o->cons.height - 2); | |
268 | + } else if (msg->arg1 == (uint32_t)ScanCode::Keys::KeyPageDown) { | |
269 | + ScrollDown(o, o->cons.height - 2); | |
240 | 270 | } |
241 | 271 | } |
242 | 272 | } else if (msg->from == Message::From::Timer) { |
@@ -275,6 +305,12 @@ | ||
275 | 305 | o->cons.sbuf.Write(Point(0, o->cons.sbuf.GetHeight() - 1), '\0'); |
276 | 306 | o->cmdlineBegin--; |
277 | 307 | } |
308 | + if (o->cons.wPos.Y >= o->cons.height - 1) { | |
309 | + o->cons.rLine = o->cons.wPos.Y - o->cons.height + 1; | |
310 | + Debug::WriteLine("set rline to %d", o->cons.rLine); | |
311 | + } else { | |
312 | + o->cons.rLine = 0; | |
313 | + } | |
278 | 314 | o->cons.wPos.X = 0; |
279 | 315 | o->cons.pPos.X = 0; |
280 | 316 | if (o->cons.pPos.Y < o->cons.height - 1) { |
@@ -321,7 +357,9 @@ | ||
321 | 357 | NewLine(o); |
322 | 358 | |
323 | 359 | if (pposy == o->cons.pPos.Y) { |
324 | - ConsoleRefreshScreen(o, -1); | |
360 | + // スクロールしたとき | |
361 | + //ConsoleRefreshScreen(o, -1); | |
362 | + ConsoleRefreshScreen(o, o->cons.rLine); | |
325 | 363 | } |
326 | 364 | |
327 | 365 | } else { |
@@ -344,11 +382,23 @@ | ||
344 | 382 | for (int line = o->cmdlineBegin, x = 1; line <= o->cons.wPos.Y; line++) { |
345 | 383 | for (; (c = o->cons.sbuf.Read(Point(x, line))) != '\0'; x++) { |
346 | 384 | o->cmdline[i++] = c; |
385 | + if (i == COMMAND_MAXLENGTH) { | |
386 | + break; | |
387 | + } | |
347 | 388 | } |
348 | 389 | x = 0; |
349 | 390 | } |
350 | 391 | o->cmdline[i] = '\0'; |
351 | 392 | |
393 | + // 履歴を保存 | |
394 | + o->cons.History.buf.Write(o->cons.History.wPos, o->cmdline); | |
395 | + if (o->cons.History.wPos.Y < o->cons.History.buf.GetHeight() - 1) { | |
396 | + o->cons.History.wPos.Y++; | |
397 | + o->cons.History.rPos = o->cons.History.wPos; | |
398 | + } else { | |
399 | + o->cons.History.buf.Scroll(1); | |
400 | + } | |
401 | + | |
352 | 402 | RunCommand(o); |
353 | 403 | |
354 | 404 | o->cmdlineBegin = o->cons.wPos.Y; |
@@ -371,7 +421,11 @@ | ||
371 | 421 | } |
372 | 422 | } |
373 | 423 | |
374 | -void ConsoleRefreshScreen(Valiables* o, int begin) | |
424 | +/* | |
425 | + * begin : 文字列バッファ内の開始位置 | |
426 | + * printBegin : 画面内の開始位置 | |
427 | + */ | |
428 | +void ConsoleRefreshScreen(Valiables* o, int begin, int printBegin) | |
375 | 429 | { |
376 | 430 | if (begin < 0) { |
377 | 431 | // 自動計算モード |
@@ -381,15 +435,26 @@ | ||
381 | 435 | } |
382 | 436 | } |
383 | 437 | |
438 | + if (printBegin < 0) { | |
439 | + printBegin = 0; | |
440 | + } | |
441 | + | |
384 | 442 | // 画面全消去 |
385 | 443 | o->img->DrawRectangleFill( |
386 | - o->cons.backColor, Point(4, 25 + 4), Point(o->img->GetWidth() - 1 - 4, o->img->GetHeight() - 1 - 4)); | |
444 | + o->cons.backColor, | |
445 | + Point(4, 25 + 4 + printBegin * fontHankaku->GetHeight()), | |
446 | + Point(o->img->GetWidth() - 1 - 4, o->img->GetHeight() - 1 - 4)); | |
387 | 447 | |
388 | 448 | // 文字列描画 |
389 | - for (int lines = 0; begin + lines <= o->cons.sbuf.GetHeight() && lines < o->cons.height; lines++) { | |
449 | + const char* p = 0; | |
450 | + for (int lines = printBegin; begin + lines <= o->cons.sbuf.GetHeight() && lines < o->cons.height; lines++) { | |
451 | + p = o->cons.sbuf.GetPointer(Point(0, begin + lines)); | |
452 | + if (p == 0) { | |
453 | + break; | |
454 | + } | |
390 | 455 | o->img->DrawString( |
391 | 456 | o->cons.textColor, |
392 | - o->cons.sbuf.GetPointer(Point(0, begin + lines)), | |
457 | + p, | |
393 | 458 | Point(4, 25 + 4 + lines * fontHankaku->GetHeight()), |
394 | 459 | fontHankaku); |
395 | 460 | } |
@@ -433,6 +498,10 @@ | ||
433 | 498 | |
434 | 499 | void ShowCursor(Valiables* o) |
435 | 500 | { |
501 | + if (o->cons.pPos.X < 0 || o->cons.width <= o->cons.pPos.X || | |
502 | + o->cons.pPos.Y < 0 || o->cons.height <= o->cons.pPos.Y) { | |
503 | + return; | |
504 | + } | |
436 | 505 | Point pos; |
437 | 506 | pos = Point(4 + o->cons.pPos.X * fontHankaku->GetWidth(), 25 + 4 + o->cons.pPos.Y * fontHankaku->GetHeight()); |
438 | 507 | o->sht->DrawRectangleFill( |
@@ -443,6 +512,10 @@ | ||
443 | 512 | |
444 | 513 | void EraseCursor(Valiables* o) |
445 | 514 | { |
515 | + if (o->cons.pPos.X < 0 || o->cons.width <= o->cons.pPos.X || | |
516 | + o->cons.pPos.Y < 0 || o->cons.height <= o->cons.pPos.Y) { | |
517 | + return; | |
518 | + } | |
446 | 519 | Point pos; |
447 | 520 | pos = Point(4 + o->cons.pPos.X * fontHankaku->GetWidth(), 25 + 4 + o->cons.pPos.Y * fontHankaku->GetHeight()); |
448 | 521 | o->sht->DrawRectangleFill( |
@@ -572,4 +645,59 @@ | ||
572 | 645 | PutString0(o, " {_.-``-' {_/\n"); |
573 | 646 | } |
574 | 647 | |
648 | +void PrintHistoryUp(Valiables* o) | |
649 | +{ | |
650 | + if (o->cons.History.rPos.Y >= 0) { | |
651 | + if (o->cons.History.rPos.Y > 0) { | |
652 | + o->cons.History.rPos.Y--; | |
653 | + } | |
654 | + ClearInputString(o); | |
655 | + PutString0(o, o->cons.History.buf.GetPointer(o->cons.History.rPos)); | |
656 | + } | |
575 | 657 | } |
658 | + | |
659 | +void PrintHistoryDown(Valiables* o) | |
660 | +{ | |
661 | + if (o->cons.History.rPos.Y < o->cons.History.wPos.Y) { | |
662 | + if (o->cons.History.rPos.Y < o->cons.History.wPos.Y - 1) { | |
663 | + o->cons.History.rPos.Y++; | |
664 | + } | |
665 | + ClearInputString(o); | |
666 | + PutString0(o, o->cons.History.buf.GetPointer(o->cons.History.rPos)); | |
667 | + } | |
668 | +} | |
669 | + | |
670 | +void ClearInputString(Valiables* o) | |
671 | +{ | |
672 | + o->cons.pPos.Y += o->cmdlineBegin - o->cons.wPos.Y; | |
673 | + o->cons.pPos.X = 1; | |
674 | + o->cons.wPos.Y = o->cmdlineBegin; | |
675 | + o->cons.wPos.X = 1; | |
676 | + o->cons.sbuf.Write(o->cons.wPos, '\0'); | |
677 | + ConsoleRefreshScreen(o, -1, o->cons.pPos.Y); | |
678 | +} | |
679 | + | |
680 | +void ScrollUp(Valiables* o, int lines) | |
681 | +{ | |
682 | + int oldRLine = o->cons.rLine; | |
683 | + o->cons.rLine -= lines; | |
684 | + if (o->cons.rLine < 0) { | |
685 | + o->cons.rLine = 0; | |
686 | + } | |
687 | + Debug::WriteLine("new rline = %d, old = %d", o->cons.rLine, oldRLine); | |
688 | + o->cons.pPos.Y += oldRLine - o->cons.rLine; | |
689 | + ConsoleRefreshScreen(o, o->cons.rLine); | |
690 | +} | |
691 | + | |
692 | +void ScrollDown(Valiables* o, int lines) | |
693 | +{ | |
694 | + int oldRLine = o->cons.rLine; | |
695 | + o->cons.rLine += lines; | |
696 | + if (o->cons.rLine > o->cons.wPos.Y) { | |
697 | + o->cons.rLine = o->cons.wPos.Y; | |
698 | + } | |
699 | + o->cons.pPos.Y += oldRLine - o->cons.rLine; | |
700 | + ConsoleRefreshScreen(o, o->cons.rLine); | |
701 | +} | |
702 | + | |
703 | +} |
@@ -71,6 +71,15 @@ | ||
71 | 71 | ScreenBuffer sbuf; |
72 | 72 | Point wPos; // 書き込みの位置 |
73 | 73 | Point pPos; // 表示の位置 |
74 | + | |
75 | + int rLine; // バッファ内の表示開始行 | |
76 | + | |
77 | + struct { | |
78 | + ScreenBuffer buf; // コマンド履歴バッファ | |
79 | + Point wPos; // 書き込みの位置 | |
80 | + Point rPos; // 読み込みの位置 | |
81 | + } History; | |
82 | + | |
74 | 83 | }; |
75 | 84 | } |
76 | 85 |