• 《30天自制操作系统》18_day_学习笔记


    harib15a:
      到这里为止,我们已经能实现窗口的切换了。我们发现所有的窗口都有光标闪烁,而我们只希望可以接受输入的窗口有光标闪烁。这里我们先来修改任务A中的光标闪烁,当按下TAB时,如果让A不现实光标,我们让cursor_c为负值。

    void HariMain(void)
    {    //......
        for (;;) {
                //.....
                if (256 <= i && i <= 511) {       /* 键盘数据  */
                    //.....
                    if (i == 256 + 0x0f) {        /* Tab键 */
                        if (key_to == 0) {        //向CMD任务窗口输入键盘的数据
                            key_to = 1;
                            make_wtitle8(buf_win,  sht_win->bxsize,  "task_a",  0);//A窗口灰色标题
                            make_wtitle8(buf_cons, sht_cons->bxsize, "console", 1);//CMD窗口蓝色标题
                            cursor_c = -1;       /* 此时向CMD发送数据,任务A中没有闪烁图标 */
                            boxfill8(sht_win->buf, sht_win->bxsize, COL8_FFFFFF, cursor_x, 28, cursor_x + 7, 43);
                        } else {              //向任务A窗口发送数据
                            key_to = 0;
                            make_wtitle8(buf_win,  sht_win->bxsize,  "task_a",  1);//A窗口蓝色标题
                            make_wtitle8(buf_cons, sht_cons->bxsize, "console", 0);//CMD窗口灰色
                            cursor_c = COL8_000000; /* 此时A任务窗口会显示光标闪烁 */
                        }
                         //刷新窗口
                        sheet_refresh(sht_win,  0, 0, sht_win->bxsize,  21);
                        sheet_refresh(sht_cons, 0, 0, sht_cons->bxsize, 21);
                    }
                    //.....
                    if (cursor_c >= 0) {       //这里是显示闪烁图标的代码
                         //只对A任务窗口进行闪烁的判断
                        boxfill8(sht_win->buf, sht_win->bxsize, cursor_c, cursor_x, 28, cursor_x + 7, 43);
                    }    //刷线任务A窗口
                    sheet_refresh(sht_win, cursor_x, 28, cursor_x + 8, 44);
                } else if (512 <= i && i <= 767) {  /* 鼠标的数据 */
                    //......
                } else if (i <= 1) {          /* 光标定时器 */
                    if (i != 0) {
                        timer_init(timer, &fifo, 0);/* 想定时器缓冲区中写入0 */
                        if (cursor_c >= 0) {
                            cursor_c = COL8_000000;//设置光标背景颜色白色
                        }
                    } else {
                        timer_init(timer, &fifo, 1);/* 向定时器缓冲区写入1 */
                        if (cursor_c >= 0) {        //设置光标背景黑色
                            cursor_c = COL8_FFFFFF;
                        }
                    }
                    timer_settime(timer, 50);    //定时时间为count的50次中断计数的时间
                    if (cursor_c >= 0) {         //cursor_c>0表示窗口A为活动窗口,可以显示光标
                                        //窗口A图层的填充和刷新
                        boxfill8(sht_win->buf, sht_win->bxsize, cursor_c, cursor_x, 28, cursor_x + 7, 43);
                        sheet_refresh(sht_win, cursor_x, 28, cursor_x + 8, 44);
                    }
                }
            }
        }
    }

    harib15b:
      1、实现CMD窗口的光标的控制,将光标开始闪烁定义为2,停止闪烁定义为3.

    //HariMain节选
      if (i == 256 + 0x0f) {            /* 按下的是TAB键 */
        if (key_to == 0) {            //这是向CMD任务发送数据
          key_to = 1;    
          make_wtitle8(buf_win,  sht_win->bxsize,  "task_a",  0);
          make_wtitle8(buf_cons, sht_cons->bxsize, "console", 1);
          cursor_c = -1;            /* cursor_c管理的是任务A的光标的闪烁情况,A停止闪烁 */
          boxfill8(sht_win->buf, sht_win->bxsize, COL8_FFFFFF, cursor_x, 28, cursor_x + 7, 43);
          fifo32_put(&task_cons->fifo, 2); /* 这个是CMD光标闪烁的情况,此时CMD闪烁打开 */
        } else {                  //向任务A窗口发送数据
          key_to = 0;
          make_wtitle8(buf_win,  sht_win->bxsize,  "task_a",  1);
          make_wtitle8(buf_cons, sht_cons->bxsize, "console", 0);
          cursor_c = COL8_000000;      /* A开始闪烁 */
          fifo32_put(&task_cons->fifo, 3); /* CMD窗口闪烁关闭 */
        }                      //刷新任务A和CMD窗口图层
        sheet_refresh(sht_win,  0, 0, sht_win->bxsize,  21);
        sheet_refresh(sht_cons, 0, 0, sht_cons->bxsize, 21);
      }

      2、对CMD任务窗口进行修改,刚开始时候将cursor_c置为-1,后面的处理和任务A一样

    void console_task(struct SHEET *sheet)
    {
                //i是从CMD缓冲区取得的数据
                if (i <= 1) {                  /* 光标定时器超时 */
                    if (i != 0) {    
                        timer_init(timer, &task->fifo, 0); /* 先向任务缓冲区写入0 */
                        if (cursor_c >= 0) {
                            cursor_c = COL8_FFFFFF;     //设置黑色
                        }
                    } else {
                        timer_init(timer, &task->fifo, 1); /* 想任务缓冲区写入1 */
                        if (cursor_c >= 0) {
                            cursor_c = COL8_000000;    //设置白色
                        }
                    }
                    timer_settime(timer, 50);        //定时器时间
                }
                if (i == 2) {                   /* CMD光标打开了 */
                    cursor_c = COL8_FFFFFF;
                }
                if (i == 3) {                   /* CMD光标关闭 */
                    boxfill8(sheet->buf, sheet->bxsize, COL8_000000, cursor_x, 28, cursor_x + 7, 43);
                    cursor_c = -1;              //关闭之后,重新初始化为-1,回到if判断中间
                }
                if (256 <= i && i <= 511) {         /* 获得了键盘的数据 */
                    if (i == 8 + 256) {
                        /* Backspace键 */
                        if (cursor_x > 16) {        //退格之前至少要16个像素的位置,一个字符+光标
                                             //退格之后,光标的位置写“ ”
                            putfonts8_asc_sht(sheet, cursor_x, 28, COL8_FFFFFF, COL8_000000, " ", 1);
                            cursor_x -= 8;         //光标左移8个像素
                        }
                    } else {
                        /* 获得的是一般的字符 */
                        if (cursor_x < 240) {       //CMD窗口宽度最大为240个像素
                        /* 这里处理的是,每输入一个字符,在CMD中写入一个,光标后移8个像素 */
                            s[0] = i - 256;
                            s[1] = 0;
                            putfonts8_asc_sht(sheet, cursor_x, 28, COL8_FFFFFF, COL8_000000, s, 1);
                            cursor_x += 8;
                        }
                    }
                }
                    /* 重新显示光标 */
                if (cursor_c >= 0) {             //如果在前面设置了光标的颜色,说明光标可以显示
                    boxfill8(sheet->buf, sheet->bxsize, cursor_c, cursor_x, 28, cursor_x + 7, 43);
                }
                sheet_refresh(sheet, cursor_x, 28, cursor_x + 8, 44);//刷新CMD图层
            }
        }
    }

    harib15c:
      1、回车键的响应:这里我们要让CMD窗口的回车键进行响应。这是CMD中实现命令的第一步啊!具体做法就是对输入的回车键进行判断,接着进行相关操作。

    if (i == 256 + 0x1c) {    /* 回车键的键值 */
      if (key_to != 0) {    /* 表示向CMD窗口发送数据 */
        fifo32_put(&task_cons->fifo, 10 + 256);//在CMD任务的缓冲区中写入10+256(其他能够区分的数据也行)
      }
    }

      2、回车键的操作:接下来我们要修改CMD任务函数console-task我们再其中创建一个cursor_y变量,当按下回车键的时候,cursor_y增加16个像素(一个字符宽8高16像素)

    void console_task(struct SHEET *sheet)
    {    //......
        for (;;) {
                    //.....
                    if (i == 10 + 256) {    /* 从缓冲区取得i的值为10+256.Enter */
                        if (cursor_y < 28 + 112) {
                                     /* CMD高度最大为28+112个像素 */
                                      //先用一个空格填充光标的位置
                            putfonts8_asc_sht(sheet, cursor_x, cursor_y, COL8_FFFFFF, COL8_000000, " ", 1);
                            cursor_y += 16;//竖直方向向下移动16个像素,(换行)
                                     /* 先显示第一个字符‘>’ */
                            putfonts8_asc_sht(sheet, 8, cursor_y, COL8_FFFFFF, COL8_000000, ">", 1);
                            cursor_x = 16; //水平方向也向右移动一个字符的位置
                        }
                    } //.....
        }
    }

    harib15d:
      上一步我们虽然实现了CMD对回车键的判断和反应,但当到了CMD窗口的最后一行,下面就没有更多的行了(其实窗口最高为140个像素)。下面我们要实现简单的CMD的窗口的滚动,要实现这个,我们只需要将所有的像素向上移动一行(16个像素)然后把最后一行涂黑就行了。

    void console_task(struct SHEET *sheet)
    {    //.....
        for (;;) {
                    //.....
                    if (i == 10 + 256) {
                        /* Enter */
                        /* 用空格将光标擦除 */
                        putfonts8_asc_sht(sheet, cursor_x, cursor_y, COL8_FFFFFF, COL8_000000, " ", 1);
                        if (cursor_y < 28 + 112) {         //cursor_y小于140,还没有到最后一行,换行
                            cursor_y += 16;             /* 换行 */
                        } else {
                                                  /* 这个时候,cursor_y>140需要进行滚动了 */
                            for (y = 28; y < 28 + 112; y++) {  //从第二行开始,都往上移动一行
                                for (x = 8; x < 8 + 240; x++) {
                                                     //把下一行y+16的,重写写到上一行y,x的值相对不变
                                    sheet->buf[x + y * sheet->bxsize] = sheet->buf[x + (y + 16) * sheet->bxsize];
                                }
                            }
                            for (y = 28 + 112; y < 28 + 128; y++) {//把最后一行涂黑
                                for (x = 8; x < 8 + 240; x++) {    
                                    sheet->buf[x + y * sheet->bxsize] = COL8_000000;
                                }
                            }
                            sheet_refresh(sheet, 8, 28, 8 + 240, 28 + 128);
                        }
                        /* 显示字符 '>' */
                        putfonts8_asc_sht(sheet, 8, cursor_y, COL8_FFFFFF, COL8_000000, ">", 1);
                        cursor_x = 16;
                    } 
            //.....
        }
    }

    harib15e:
      mem命令:到这里为止,我们已经对CMD进行了一些准备工作,下面我们来实现第一个命令:mem命令。这个命令用来显示内存的情况。这里我们还把背景图层上显示的内容全部去掉了。

    void console_task(struct SHEET *sheet, unsigned int memtotal)
    {
        char s[30], cmdline[30];
        //.....
        for (;;) {
            //......
                if (256 <= i && i <= 511) {               /* 键盘的数据 */
                    if (i == 8 + 256) {                 //backspace
                        if (cursor_x > 16) {
                                                    /* cursor_x光标向后移动8个像素 */
                            putfonts8_asc_sht(sheet, cursor_x, cursor_y, COL8_FFFFFF, COL8_000000, " ", 1);
                            cursor_x -= 8;
                        }
                    } else if (i == 10 + 256) {            //enter
                          /* 用空格擦除光标 */
                        putfonts8_asc_sht(sheet, cursor_x, cursor_y, COL8_FFFFFF, COL8_000000, " ", 1);
                        cmdline[cursor_x / 8 - 2] = 0;        //这里进行命令的判断,必须是cmd
                        cursor_y = cons_newline(cursor_y, sheet); //回车键之后得到新的cursor_y
                          /* 从这里开始执行CMD命令 */
                        if (cmdline[0] == 'm' && cmdline[1] == 'e' && cmdline[2] == 'm' && cmdline[3] == 0) {
                            //下面输出内存信息
                            sprintf(s, "total   %dMB", memtotal / (1024 * 1024));
                            putfonts8_asc_sht(sheet, 8, cursor_y, COL8_FFFFFF, COL8_000000, s, 30);
                            cursor_y = cons_newline(cursor_y, sheet);
                            sprintf(s, "free %dKB", memman_total(memman) / 1024);
                            putfonts8_asc_sht(sheet, 8, cursor_y, COL8_FFFFFF, COL8_000000, s, 30);
                            cursor_y = cons_newline(cursor_y, sheet);
                            cursor_y = cons_newline(cursor_y, sheet);
                        } else if (cmdline[0] != 0) {
                            /* 命令错误的判断 */
                            putfonts8_asc_sht(sheet, 8, cursor_y, COL8_FFFFFF, COL8_000000, "Bad command.", 12);
                            cursor_y = cons_newline(cursor_y, sheet);
                            cursor_y = cons_newline(cursor_y, sheet);
                        }
                //.....
                }
        }
    }

    harib15f:
      CLS命令:清空屏幕,在linux中是clear.这里我们使用C语言的字符串比较函strcmmp(#include <string.h>)函数来进行输入命令的判断

    void console_task(struct SHEET *sheet, unsigned int memtotal)
    {    //.....
        for (;;) {
                //.....
                if (256 <= i && i <= 511) {           /* 键盘数据(通过任务A) */
                        //.....
                        } else if (strcmp(cmdline, "cls") == 0) {
                                                /* cls命令 */
                            for (y = 28; y < 28 + 128; y++) { //这里做的事就是把整个窗口涂成黑色的
                                for (x = 8; x < 8 + 240; x++) {
                                    sheet->buf[x + y * sheet->bxsize] = COL8_000000;
                                }
                            }
                            sheet_refresh(sheet, 8, 28, 8 + 240, 28 + 128);
                            cursor_y = 28;
                //.....
            }
    }
  • 相关阅读:
    [剑指Offer] 从尾到头打印链表
    [剑指Offer] 替换空格
    [剑指Offer] 二维数组中的查找
    [LeetCode] 53. Maximum Subarray
    [LeetCode] 283. Move Zeroes
    haproxy + rabbitmq + keepalived的高可用环境搭建
    iis7下站点日志默认位置
    在vs2012中配置使用iisexpress
    tomcat配置域名,单项目指定多域名
    httpget和post
  • 原文地址:https://www.cnblogs.com/pengfeiz/p/5848822.html
Copyright © 2020-2023  润新知