4 实现字符输入(harib14d)
要实现字符的输入,只要在键盘被按下的时候向console_task的FIFO发送数据即可。但要发送数据,必须要知道struct FIFO的内存地址才行。唔,这可怎么办呢?
我们可以让任务A在创建task_cons的时候,顺便将FIFO也准备好。这样一来,任务A就能知道task_cons所使用的FIFO的地址,我们的问题便迎刃而解了。
等等,这样还是太麻烦了,我们还是把struct FIFO放到struct TASK里面去吧。基本上没有什么任务是完全用不到FIFO的,因此我们把它们绑定起来。
本次的bootpack.h节选
struct TASK {
int sel, flags; /* sel代表GDT编号 */
int level, priority;
struct FIFO32 fifo; /*这里! */
struct TSS32 tss;
};
■■■■■
接下来我们来修改一下HariMain,使其判断key_to的值并向task_cons的FIFO发送数据。
本次的bootpack.c节选
void HariMain(void)
{
(中略)
for (;;) {
io_cli();
if (fifo32_status(&fifo) == 0) {
task_sleep(task_a);
io_sti();
} else {
i = fifo32_get(&fifo);
io_sti();
if (256 <= i && i <= 511) { /*键盘数据*/
sprintf(s, "%02X", i - 256);
putfonts8_asc_sht(sht_back, 0, 16, COL8_FFFFFF, COL8_008484, s, 2);
/*从此开始*/ if (i < 0x54 + 256 && keytable[i - 256] != 0) { /*一般字符*/
if (key_to == 0) { /*发送给任务A */
if (cursor_x < 128) {
/*显示一个字符之后将光标后移一位*/
s[0] = keytable[i - 256];
s[1] = 0;
putfonts8_asc_sht(sht_win, cursor_x, 28, COL8_000000, COL8_FFFFFF, s, 1);
cursor_x += 8;
}
} else { /*发送给命令行窗口*/
fifo32_put(&task_cons->fifo, keytable[i - 256] + 256);
/*到此结束*/ }
}
if (i == 256 + 0x0e) { /* 退格键 */
/*从此开始*/ if (key_to == 0) { /*发送给任务A */
if (cursor_x > 8) {
/*用空白擦除光标后将光标前移一位*/
putfonts8_asc_sht(sht_win, cursor_x, 28, COL8_000000, COL8_FFFFFF, " ", 1);
cursor_x -= 8;
}
} else { /*发送给命令行窗口*/
fifo32_put(&task_cons->fifo, 8 + 256);
/*到此结束*/ }
}
if (i == 256 + 0x0f) { /* Tab键*/
(中略)
}
/*重新显示光标*/
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);
} else if (512 <= i && i <= 767) { /*鼠标数据*/
(中略)
} else if (i <= 1) { /*光标用定时器*/
(中略)
}
}
}
}
当key_to不为0时,系统会向命令行窗口任务发送键盘数据,支持一般的字符输入和退格键。由于在命令行窗口中也使用了定时器等,为了不与键盘数据冲突,我们在写入FIFO的时候将键盘数据的值加上256。
在向命令行窗口发送键盘数据的时候,并不是直接发送从键盘接收到的原始数据,而是发送经过keytable[]转换后的值。究其原因,是由于这样做可以省去在命令行窗口任务中将按键编码转换成字符编码的步骤。
对于退格键,我们将它的字符编码定义为8,因为在ASCII码中,编码8就对应着退格键,我们只是和它接轨而已。当然,如果你不想用8也完全没有问题。
■■■■■
console_task也需要改写一下,因为我们必须让它能够接收并处理键盘数据。此外,我们还得把&fifo改写成&task—>fifo。
本次的bootpack.c节选
void console_task(struct SHEET *sheet)
{
struct TIMER *timer;
struct TASK *task = task_now();
int i, fifobuf[128], cursor_x = 16, cursor_c = COL8_000000;
char s[2];
fifo32_init(&task->fifo, 128, fifobuf, task);
timer = timer_alloc();
timer_init(timer, &task->fifo, 1);
timer_settime(timer, 50);
/*显示提示符*/
putfonts8_asc_sht(sheet, 8, 28, COL8_FFFFFF, COL8_000000, ">", 1);
for (;;) {
io_cli();
if (fifo32_status(&task->fifo) == 0) {
task_sleep(task);
io_sti();
} else {
i = fifo32_get(&task->fifo);
io_sti();
if (i <= 1) { /*光标用定时器*/
if (i != 0) {
timer_init(timer, &task->fifo, 0); /*接下来置0 */
cursor_c = COL8_FFFFFF;
} else {
timer_init(timer, &task->fifo, 1); /*接下来置1 */
cursor_c = COL8_000000;
}
timer_settime(timer, 50);
}
if (256 <= i && i <= 511) { /*键盘数据(通过任务A) */
if (i == 8 + 256) {
/*退格键*/
if (cursor_x > 16) {
/*用空白擦除光标后将光标前移一位*/
putfonts8_asc_sht(sheet, cursor_x, 28, COL8_FFFFFF, COL8_000000, " ", 1);
cursor_x -= 8;
}
} else {
/*一般字符*/
if (cursor_x < 240) {
/*显示一个字符之后将光标后移一位 */
s[0] = i - 256;
s[1] = 0;
putfonts8_asc_sht(sheet, cursor_x, 28, COL8_FFFFFF, COL8_000000, s, 1);
cursor_x += 8;
}
}
}
/*重新显示光标*/
boxfill8(sheet->buf, sheet->bxsize, cursor_c, cursor_x, 28, cursor_x + 7, 43);
sheet_refresh(sheet, cursor_x, 28, cursor_x + 8, 44);
}
}
}
上面的程序基本是由HariMain照猫画虎而来,唯一的一点区别就是开头显示提示符“>”的地方了。退格键的处理上也对可以删除的界限作了调整,以避免退格时擦掉提示符。
■■■■■
我们来运行一下看看,“make run”。
可以输入了哦!
成功了,真是个伟大的胜利。现在我们可以输入英文、数字和符号了,但还无法输入“!”和“%”。好吧,接下来我们来解决这个问题。