18.1、控制光标闪烁
前一天发现,切换完窗口,光标在所有窗口都会闪烁,应该是哪个可以输入,该图层闪烁。
18.1.1、切换到task_a
HariMain:
if (i == 256 + 0x0f) { /* Tab */
if (key_to == 0) {
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; /* 不显示光标 */
boxfill8(sht_win->buf, sht_win->bxsize, COL8_FFFFFF, cursor_x, 28, cursor_x + 7, 43);
} else {
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; /* 显示光标 */
}
sheet_refresh(sht_win, 0, 0, sht_win->bxsize, 21);
sheet_refresh(sht_cons, 0, 0, sht_cons->bxsize, 21);
}
// 重新显示光标
if (cursor_c >= 0) {
boxfill8(sht_win->buf, sht_win->bxsize, cursor_c, cursor_x, 28, cursor_x + 7, 43);
}
// 光标定时器
} else if (i <= 1) {
if (i != 0) {
timer_init(timer, &fifo, 0);
if (cursor_c >= 0) {
cursor_c = COL8_000000;
}
} else {
timer_init(timer, &fifo, 1);
if (cursor_c >= 0) {
cursor_c = COL8_FFFFFF;
}
}
timer_settime(timer, 50);
if (cursor_c >= 0) {
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);
}
}
这里引用了一个 cursor_c 变量,当它大于0就显示光标,否则不显示。这样以来当切换到任务A(task_a窗口)就会显示光标,切走则不显示。
18.1.2、切换到命令行窗口
if (key_to == 0) {
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; /* 不显示光标 */
boxfill8(sht_win->buf, sht_win->bxsize, COL8_FFFFFF, cursor_x, 28, cursor_x + 7, 43);
fifo32_put(&task_cons->fifo, 2); /* 命令行窗口光标ON */
} else {
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; /* 显示光标 */
fifo32_put(&task_cons->fifo, 3); /* 命令行窗口光标OFF */
}
通过缓冲区传递数据,之后在命令行窗口,光标定时器一样操作,可以控制光标闪烁。
18.2、对回车键的支持
回车键的扫描码就是0x1c,如果触发就往命令行缓冲区中写入10,命令行任务看到有10,就会处理:
if (i == 256 + 0x1c) { /* Enter */
if (key_to != 0) { /* 发送到命令行窗口 */
fifo32_put(&task_cons->fifo, 10 + 256);
}
}
else if (i == 10 + 256) {
/* Enter */
if (cursor_y < 28 + 112) {
/* 用空格擦除光标 */
putfonts8_asc_sht(sheet, cursor_x, cursor_y, COL8_FFFFFF, COL8_000000, " ", 1);
cursor_y += 16;
/* 显示提示符 > */
putfonts8_asc_sht(sheet, 8, cursor_y, COL8_FFFFFF, COL8_000000, ">", 1);
cursor_x = 16;
}
} else {
18.3、对窗口滚动的支持
命令行窗口:
} else 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 += 16; /* 换行 */
} else {
/* 滚动(把所有像素向上移动一行) */
for (y = 28; y < 28 + 112; y++) {
for (x = 8; x < 8 + 240; 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;
} else {
18.4、mem命令
} 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;
cursor_y = cons_newline(cursor_y, sheet);
/* 执行命令 */
if (cmdline[0] == 'm' && cmdline[1] == 'e' && cmdline[2] == 'm' && cmdline[3] == 0) {
/* mem命令 */
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);
}
/* 显示提示符 */
putfonts8_asc_sht(sheet, 8, cursor_y, COL8_FFFFFF, COL8_000000, ">", 1);
cursor_x = 16;
} else {
/* 一般文字 */
if (cursor_x < 240) {
/* 一文字表示してから、カーソルを1つ進める */
s[0] = i - 256;
s[1] = 0;
cmdline[cursor_x / 8 - 2] = i - 256;
putfonts8_asc_sht(sheet, cursor_x, cursor_y, COL8_FFFFFF, COL8_000000, s, 1);
cursor_x += 8;
}
}
memtotal 是通过栈传递给命令行任务,cmdline 用来保存识别输入的指令。
18.5、cls命令
} 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;
}
18.5、dir命令
软盘文件系统存盘格式:
0x2600 - 0x4200存放文件信息,每条信息32字节,所以可以存放(0x4200-0x2600)/ 0x20 = 224个文件信息。
0x2600地址开始存放文件基础信息
字节 | 信息 |
---|---|
1~8 | 文件名 |
9~11 | 后缀名 |
12 | 属性 |
13~22 | 未知 |
23~24 | 存放文件时间 |
25~26 | 存放文件日期 |
27~28 | 文件从哪个扇区开始存放 |
29~32 | 存放文件大小 |
文件名第一个字节:
0xe5:文件被删除
0x00:这一段不包含任何文件名信息
文件属性:
值 | 意义 |
---|---|
0x01 | 只读文件(不可写入) |
0x02 | 隐藏文件 |
0x04 | 系统文件 |
0x08 | 飞文件信息(比如磁盘名称等) |
0x10 | 目录 |
0x20 | |
0x00 |
} else if (strcmp(cmdline, "dir") == 0) {
/* dir命令 */
for (x = 0; x < 224; x++) {
if (finfo[x].name[0] == 0x00) {
break;
}
if (finfo[x].name[0] != 0xe5) { // 没有被删除
if ((finfo[x].type & 0x18) == 0) { // 排除目录和非文件信息
sprintf(s, "filename.ext %7d", finfo[x].size); // 文件大小
for (y = 0; y < 8; y++) { //文件名
s[y] = finfo[x].name[y];
}
// 后缀
s[ 9] = finfo[x].ext[0];
s[10] = finfo[x].ext[1];
s[11] = finfo[x].ext[2];
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);
}
dir命令: