5 启动时只打开一个命令行窗口(harib23e)

昨天我们将命令行窗口的数量增加到了两个,还把碍眼的task_a窗口给去掉了,今天我们要让它看上去更像一个普通的操作系统。

说到这里,首先想到的是系统启动时所打开的命令行窗口数量,普通的操作系统没有一启动就打开两个命令行窗口的吧?一般都是先打开一个命令行窗口,然后根据需要增加。下面我们就将启动时显示的命令行窗口数量改为一个,并且实现可以随意启动新命令行窗口的功能吧。

■■■■■

这里我们需要考虑一下,如果启动一个新窗口需要让用户如何操作呢?比如说,在Windows2000的命令行窗口中输入“start cmd.exe”,就会出现一个新的命令行窗口。那么我们就来模仿一下这个方法,先编写一个用来启动新窗口的命令吧。

不过,实际使用操作系统的用户一般是在运行某个程序的同时突然想做另外一件事情,才需要开新窗口的。这时,如果只能通过命令来启动新窗口,就必须先强制关闭现在正在运行的应用程序,再往命令行窗口中输入命令才行——这也太麻烦了。

在Windows中,即便不在命令行中输入命令,只通过鼠标的操作也可以打开新的命令行窗口(比如可以通过开始菜单),我们的“纸娃娃系统”也可以借鉴一下这种方法。不过鼠标点击开始菜单这种方式实现起来太难,我们还是做快捷键吧,可以规定按下Shift+F2就打开一个新的命令行窗口。之所以用这个组合键,是因为程序改起来方便,如果不喜欢这个组合键的话,完全可以根据下面的范例自行修改哦。

修改后的程序如下:

本次的bootpack.c节选

  1. void HariMain(void)
  2. {
  3. (中略)
  4. /* sht_cons */
  5. sht_cons[0] = open_console(shtctl, memtotal); /*从此开始*/
  6. sht_cons[1] = 0; /*未打开状态*/ /*到此结束*/
  7. (中略)
  8. sheet_slide(sht_back, 0, 0);
  9. sheet_slide(sht_cons[0], 32, 4); /*这里!*/
  10. sheet_slide(sht_mouse, mx, my);
  11. sheet_updown(sht_back, 0);
  12. sheet_updown(sht_cons[0], 1); /*从此开始*/
  13. sheet_updown(sht_mouse, 2); /*到此结束*/
  14. key_win = sht_cons[0];
  15. keywin_on(key_win);
  16. (中略)
  17. for (;;) {
  18. (中略)
  19. if (fifo32_status(&fifo) == 0) {
  20. (中略)
  21. } else {
  22. (中略)
  23. if (256 <= i && i <= 511) { /*键盘数据*/
  24. (中略)
  25. if (i == 256 + 0x3c && key_shift != 0 && sht_cons[1] == 0) { /* Shift+F2 */
  26. sht_cons[1] = open_console(shtctl, memtotal);
  27. sheet_slide(sht_cons[1], 32, 4);
  28. sheet_updown(sht_cons[1], shtctl->top);
  29. /*自动将输入焦点切换到新打开的命令行窗口(这样比较方便吧?) */
  30. keywin_off(key_win);
  31. key_win = sht_cons[1];
  32. keywin_on(key_win);
  33. }
  34. (中略)
  35. } else if (512 <= i && i <= 767) { /*鼠标数据*/
  36. (中略)
  37. }
  38. }
  39. }
  40. }
  41. struct SHEET *open_console(struct SHTCTL *shtctl, unsigned int memtotal)
  42. {
  43. struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
  44. struct SHEET *sht = sheet_alloc(shtctl);
  45. unsigned char *buf = (unsigned char *) memman_alloc_4k(memman, 256 * 165);
  46. struct TASK *task = task_alloc();
  47. int *cons_fifo = (int *) memman_alloc_4k(memman, 128 * 4);
  48. sheet_setbuf(sht, buf, 256, 165, -1); /*无透明色*/
  49. make_window8(buf, 256, 165, "console", 0);
  50. make_textbox8(sht, 8, 28, 240, 128, COL8_000000);
  51. task->tss.esp = memman_alloc_4k(memman, 64 * 1024) + 64 * 1024 - 12;
  52. task->tss.eip = (int) &console_task;
  53. task->tss.es = 1 * 8;
  54. task->tss.cs = 2 * 8;
  55. task->tss.ss = 1 * 8;
  56. task->tss.ds = 1 * 8;
  57. task->tss.fs = 1 * 8;
  58. task->tss.gs = 1 * 8;
  59. *((int *) (task->tss.esp + 4)) = (int) sht;
  60. *((int *) (task->tss.esp + 8)) = memtotal;
  61. task_run(task, 2, 2); /* level=2, priority=2 */
  62. sht->task = task;
  63. sht->flags |= 0x20; /*有光标*/
  64. fifo32_init(&task->fifo, 128, cons_fifo, task);
  65. return sht;
  66. }

首先,我们将打开命令行窗口的程序封装成了一个单独的函数(open_console),然后将没有打开的窗口的sht_cons[]置为0以示区别。当按下Shift+F2且第2个命令行窗口处于未打开状态时将其打开。

■■■■■

那么我们来“make run”吧,先来运行我们特别喜欢的color2.hrb,然后按下Shift+F2打开新的命令行窗口,再运行lines.hrb。成功了,好开心呀!

5 启动时只打开一个命令行窗口(harib23e) - 图1 5 启动时只打开一个命令行窗口(harib23e) - 图2
刚刚启动完毕的画面(只有一个命令行窗口) 成功启动了另一个命令行窗口