6 大写字母与小写字母(harib14f)

要实现区分大写、小写字母的输入,我们必须要同时判断Shift键的状态以及CapsLock的状态。

CapsLockOFF & Shift键为OFF → 小写英文字母

CapsLockOFF & Shift键为ON → 大写英文字母

CapsLockON & Shift键为OFF → 大写英文字母

CapsLockON & Shift键为ON → 小写英文字母

综上所述,我们可以将需要转换为小写字母的条件总结如下:

  • 输入的字符为英文字母

  • “CapsLock为OFF & Shift键为OFF”或者“CapsLock为ON & Shift键为ON”

我们已经知道如何获取Shift键的状态,但是CapsLock的状态要如何获取呢?BIOS知道CapsLock的状态,可现在我们处于32位模式,没办法向BIOS查询。不过别担心,在asmhead.nas中,我们已经从BIOS获取到了键盘状态,就保存在binfo—>leds中。

binfo->leds的第4位→ ScrollLock状态

binfo->leds的第5位 → NumLock状态

binfo->leds的第6位 → CapsLock状态

只要使用上述数据,我们就可以处理大小写字母的输入了。

■■■■■

在if语句中,除了&&运算符,还有一个||运算符,这个运算符代表“只要其中任意一个条件成立即可”的意思,我们可以用它来改写HariMain,使其能够实现小写字母的输入。

本次的bootpack.c节选

  1. void HariMain(void)
  2. {
  3. (中略)
  4. int key_to = 0, key_shift = 0, key_leds = (binfo->leds >> 4) & 7; /*这里!*/
  5. (中略)
  6. for (;;) {
  7. io_cli();
  8. if (fifo32_status(&fifo) == 0) {
  9. task_sleep(task_a);
  10. io_sti();
  11. } else {
  12. i = fifo32_get(&fifo);
  13. io_sti();
  14. if (256 <= i && i <= 511) { /*键盘数据*/
  15. sprintf(s, "%02X", i - 256);
  16. putfonts8_asc_sht(sht_back, 0, 16, COL8_FFFFFF, COL8_008484, s, 2);
  17. if (i < 0x80 + 256) { /*将按键编码转换为字符编码*/
  18. (中略)
  19. } else {
  20. s[0] = 0;
  21. }
  22. /*从此开始*/ if ('A' <= s[0] && s[0] <= 'Z') { /*当输入字符为英文字母时*/
  23. if (((key_leds & 4) == 0 && key_shift == 0) ||
  24. ((key_leds & 4) != 0 && key_shift != 0)) {
  25. s[0] += 0x20; /*将大写字母转换为小写字母*/
  26. }
  27. /*到此结束*/ }
  28. if (s[0] != 0) { /*一般字符*/
  29. (中略)
  30. }
  31. (中略)
  32. } else if (512 <= i && i <= 767) { /*鼠标数据*/
  33. (中略)
  34. } else if (i <= 1) { /*光标用定时器*/
  35. (中略)
  36. }
  37. }
  38. }
  39. }

要获取CapsLock等锁定键的状态,我们只需要第4~6位的数据,剩下的数据对我们没用,所以在key_leds中只从binfo—>leds取出指定的3个比特即可。这里我们还做了4个比特的右移位,这是为了在下一节中能够更加方便地使用这些数据。

我们所使用的ASCII码中,将大写字母的编码加上0x20,就得到相应的小写字母编码。利用这一性质,我们就可以将大写字母转换为小写字母。

■■■■■

我们来运行一下,“make run”,结果如下。

6 大写字母与小写字母(harib14f) - 图1

可以输入小写字母了!

呀,这样就变得酷多了吧。啥?不能满足于这点成绩?其实这样挺好的不是吗,一步一个脚印,享受每一次进步,这样才有成就感呀。

我们已经实现了根据CapsLock的状态来切换大小写字母的输入,那大家想不想实现在按下CapsLock键的时候切换CapsLock的状态呢?一定很想吧?(哈哈,笔者又在自说自话了。)

COLUMN-10 键盘的设计问题?

在harib14f中,对于同时按住左右Shift键输入字母的情况,我们的程序也做了相应的处理,即同时按下两个Shift键,和只按下其中一个Shift键效果是一样的。

但当笔者试验了一番之后,却发现了一件很有意思的事情——按下左Shift+右Shift+A是无法输入的,可是左Shift+右Shift+Z却可以输入。

一开始笔者还惊慌地想“糟糕!别是bug吧!”,但后来看了一下显示出来的按键编码,发现这貌似是键盘本身设计的问题。其实在Windows中也会发生同样的现象。

笔者用家里好几台电脑试验了一下,发现无论用哪个键盘,ASDF这4个键,在同时按下两边Shift键的情况下都无法输入。不过笔者家里的键盘无一例外都是便宜货,说不定中高级键盘上就不会发生这种问题。大家如果有兴趣的话,也可以用自己的键盘试试看哦。