2 应用程序运行时关闭命令行窗口(harib24b)*

终于除掉了bug,神清气爽。命令行窗口的功能已经实现得差不多了,不过还有一个地方不太满意,就是在应用程序运行的时候无法关闭所对应的命令行窗口。

我们先不考虑ncst命令,用普通的方法运行应用程序的时候,在应用程序退出之前,我们是无法关闭用来启动这个程序的命令行窗口的。直到程序运行之后才觉得命令行窗口太碍事了,但事已至此也不想再重新启动应用程序(比如说,热水已经倒好了,总不能这个时候重新启动noodle.hrb吧!),于是就只好将就了。

因此还是想办法解决这个问题比较好。

■■■■■

首先我们来修改bootpack.c。

本次的bootpack.c节选

  1. void HariMain(void)
  2. {
  3. (中略)
  4. struct SHEET *sht = 0, *key_win, *sht2; /*添加sht2 */
  5. (中略)
  6. for (;;) {
  7. (中略)
  8. if (fifo32_status(&fifo) == 0) {
  9. (中略)
  10. } else {
  11. (中略)
  12. if (256 <= i && i <= 511) { /*键盘数据*/
  13. (中略)
  14. } else if (512 <= i && i <= 767) { /*鼠标数据*/
  15. (中略)
  16. if (mouse_decode(&mdec, i - 512) != 0) {
  17. (中略)
  18. if ((mdec.btn & 0x01) != 0) {
  19. /*按下左键的情形*/
  20. if (mmx < 0) {
  21. (中略)
  22. for (j = shtctl->top - 1; j > 0; j--) {
  23. (中略)
  24. if (0 <= x && x < sht->bxsize && 0 <= y && y < sht->bysize) {
  25. if (sht->buf[y * sht->bxsize + x] != sht->col_inv) {
  26. (中略)
  27. if (sht->bxsize - 21 <= x && x < sht->bxsize - 5 && 5 <= y && y < 19) {
  28. /* 点击“×”按钮*/
  29. if ((sht->flags & 0x10) != 0) { /*是否为应用程序窗口*/
  30. (中略)
  31. } else { /*命令行窗口*/
  32. task = sht->task;
  33. /*从此开始*/ sheet_updown(sht, -1); /*暂且隐藏该图层*/
  34. keywin_off(key_win);
  35. key_win = shtctl->sheets[shtctl->top - 1];
  36. /*到此结束*/ keywin_on(key_win);
  37. io_cli();
  38. fifo32_put(&task->fifo, 4);
  39. io_sti();
  40. }
  41. }
  42. break;
  43. }
  44. }
  45. }
  46. } else {
  47. (中略)
  48. }
  49. } else {
  50. (中略)
  51. }
  52. }
  53. } else if (768 <= i && i <= 1023) { /*命令行结束处理*/
  54. close_console(shtctl->sheets0 + (i - 768));
  55. } else if (1024 <= i && i <= 2023) {
  56. close_constask(taskctl->tasks0 + (i - 1024));
  57. } else if (2024 <= i && i <= 2279) { /*只关闭命令行窗口*/ /*从此开始*/
  58. sht2 = shtctl->sheets0 + (i - 2024);
  59. memman_free_4k(memman, (int) sht2->buf, 256 * 165);
  60. sheet_free(sht2); /*到此结束*/
  61. }
  62. }
  63. }
  64. }

我们修改了bootpack.c中的两个地方。前面一个地方的修改是让系统在按下“×”按钮时暂且将命令行窗口从画面上隐藏起来。为什么要耍这样一个小聪明呢?这是因为关闭有的应用程序的命令行窗口时需要消耗一定的时间,如果点了按钮还不关闭用户会觉得很烦躁,先隐藏窗口就可以避免这样的问题。总之这只是一个小技巧而已,并不是本次修改的重点。

后面一处修改是当FIFO接收到从console.c发送的“关闭窗口”请求数据时所进行的处理,主要是释放指定的图层。关于这一处修改的内容,看了对console.c进行修改的部分之后会更容易理解。

■■■■■

下面就是对console.c的修改。

本次的console.c节选

  1. void console_task(struct SHEET *sheet, int memtotal)
  2. {
  3. (中略)
  4. if (cons.sht != 0) { /*这里!*/
  5. (中略)
  6. }
  7. (中略)
  8. for (;;) {
  9. io_cli();
  10. if (fifo32_status(&task->fifo) == 0) {
  11. (中略)
  12. } else {
  13. (中略)
  14. if (i <= 1 && cons.sht != 0) { /*光标用定时器*/ /*这里!*/
  15. (中略)
  16. }
  17. (中略)
  18. if (i == 3) { /*光标OFF */
  19. if (cons.sht != 0) { /*这里!*/
  20. boxfill8(cons.sht->buf, cons.sht->bxsize, COL8_000000, /*这里!*/
  21. cons.cur_x, cons.cur_y, cons.cur_x + 7, cons.cur_y + 15);
  22. }
  23. cons.cur_c = -1;
  24. }
  25. (中略)
  26. if (256 <= i && i <= 511) { /*键盘数据(通过任务A)*/
  27. if (i == 8 + 256) {
  28. (中略)
  29. } else if (i == 10 + 256) {
  30. (中略)
  31. if (cons.sht == 0) { /*这里!*/
  32. cmd_exit(&cons, fat);
  33. }
  34. (中略)
  35. } else {
  36. (中略)
  37. }
  38. }
  39. /*重新显示光标*/
  40. if (cons.sht != 0) { /*这里!*/
  41. if (cons.cur_c >= 0) {
  42. boxfill8(cons.sht->buf, cons.sht->bxsize, cons.cur_c, /*这里!*/
  43. cons.cur_x, cons.cur_y, cons.cur_x + 7, cons.cur_y + 15);
  44. }
  45. /*这里!*/ sheet_refresh(cons.sht, cons.cur_x, cons.cur_y, cons.cur_x + 8, cons.cur_y + 16);
  46. }
  47. }
  48. }
  49. }

修改的要点是将变量sheet的部分改用变量cons.sht代替。虽然两个变量的值基本上是一致的,但cons.sht在命令行窗口关闭后会被置为0,而sheet则不变,因此在这里我们需要使用前者。

接下来我们来修改API中键盘输入的部分。

本次的console.c节选

  1. int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax)
  2. {
  3. (中略)
  4. struct FIFO32 *sys_fifo = (struct FIFO32 *) *((int *) 0x0fec); /*这里!*/
  5. (中略)
  6. } else if (edx == 15) {
  7. for (;;) {
  8. (中略)
  9. if (i == 4) { /*只关闭命令行窗口*/ /*从此开始*/
  10. timer_cancel(cons->timer);
  11. io_cli();
  12. fifo32_put(sys_fifo, cons->sht - shtctl->sheets0 + 2024); /*2024~2279*/
  13. cons->sht = 0;
  14. io_sti();
  15. } /*到此结束*/
  16. (中略)
  17. }
  18. } else if (edx == 16) {
  19. (中略)
  20. }

在等待键盘输入期间,如果FIFO中接收到4这个数据,则表示收到了关闭命令行窗口的信号,此时取消定时器,并发出清理图层的消息,然后将cons—>sht置为0。

■■■■■

好,大功告成了,我们来“make run”吧。

我们故意不使用ncst命令,而是用一般的方法运行笔者最喜欢的color2.hrb,程序启动后尝试关闭命令行窗口……耶!

2 应用程序运行时关闭命令行窗口(harib24b)* - 图1 2 应用程序运行时关闭命令行窗口(harib24b)* - 图2
color2.hrb启动时的样子 关闭命令行窗口后的样子