Click here to Skip to main content
16,022,122 members
Please Sign up or sign in to vote.
1.00/5 (3 votes)
See more:
Here's my code:
C
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

enum vga_color {
    VGA_COLOR_BLACK = 0,
    VGA_COLOR_BLUE = 1,
    VGA_COLOR_GREEN = 2,
    VGA_COLOR_CYAN = 3,
    VGA_COLOR_RED = 4,
    VGA_COLOR_MAGENTA = 5,
    VGA_COLOR_BROWN = 6,
    VGA_COLOR_LIGHT_GREY = 7,
    VGA_COLOR_DARK_GREY = 8,
    VGA_COLOR_LIGHT_BLUE = 9,
    VGA_COLOR_LIGHT_GREEN = 10,
    VGA_COLOR_LIGHT_CYAN = 11,
    VGA_COLOR_LIGHT_RED = 12,
    VGA_COLOR_LIGHT_MAGENTA = 13,
    VGA_COLOR_LIGHT_BROWN = 14,
    VGA_COLOR_WHITE = 15, };

static inline uint8_t vga_entry_color
 (enum vga_color fg, enum vga_color bg) {
    return fg | bg << 4; }
 
static inline uint16_t vga_entry(unsigned char uc, uint8_t color) {
    return (uint16_t) uc | (uint16_t) color << 8; }
 
size_t strlen(const char* str) {
    size_t len = 0;
    while (str[len])
        len++;
    return len; }
 
static const size_t VGA_WIDTH = 80;
static const size_t VGA_HEIGHT = 25;
 
size_t terminal_row;
size_t terminal_column;
uint8_t terminal_color;
uint16_t* terminal_buffer;

 
void terminal_initialize(void) {
    terminal_row = 0;
    terminal_column = 0;
    terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
    terminal_buffer = (uint16_t*) 0xB8000;
    for (size_t y = 0; y < VGA_HEIGHT; y++) {
        for (size_t x = 0; x < VGA_WIDTH; x++) {
            const size_t index = y * VGA_WIDTH + x;
            terminal_buffer[index] = vga_entry(' ', terminal_color); } } }

void terminal_setcolor(uint8_t color) {
    terminal_color = color; }
 
void terminal_putentryat(char c, uint8_t color, size_t x, size_t y) {
    const size_t index = y * VGA_WIDTH + x;
    terminal_buffer[index] = vga_entry(c, color); }
 
void terminal_scroll(void) {
  for (size_t y = 0; y < VGA_HEIGHT - 1; y++) {
    for (size_t x = 0; x < VGA_WIDTH; x++) {
      const size_t current_index = y * VGA_WIDTH + x;
      const size_t next_line_index = (y + 1) * VGA_WIDTH + x;
      terminal_buffer[current_index] = terminal_buffer[next_line_index]; } }
  const size_t last_row_index = (VGA_HEIGHT - 1) * VGA_WIDTH;
  for (size_t x = 0; x < VGA_WIDTH; x++) {
    terminal_buffer[last_row_index + x] = vga_entry(' ', terminal_color); } }

void terminal_putchar(char c) {
  if (c == '\n') {
    terminal_row++;
    terminal_column = 0; } else {
    terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
    terminal_column++; }

  if (terminal_column >= VGA_WIDTH) {
    terminal_row++;
    terminal_column = 0; }

  if (terminal_row >= VGA_HEIGHT) {
    terminal_scroll();
    terminal_row = VGA_HEIGHT - 1; } }
 
void terminal_write(const char* data, size_t size) {
    for (size_t i = 0; i < size; i++)
        terminal_putchar(data[i]); }
 
void printl(const char* data) {
 terminal_write(data, strlen(data)); }

uint8_t inb(uint16_t port) {
 uint8_t ret;
 asm volatile("inb %1, %0" : "=a"(ret) : "d"(port));
 return ret; }

void outb(uint16_t port, uint8_t data) {
 asm volatile("outb %0, %1" : "=a"(data) : "d"(port)); }

void kernel_main(void) {
    terminal_initialize();
    printl("LainOS\n"); 


What I have tried:

I was trying to add:
C
while (true) {
    char c = inb(0x60);
    if (c != 0) {
    terminal_putchar(c); } } }

In the void kernel_main, it works, but it prints the character all over the screen and not like I expect.
Posted
Updated 27-Oct-23 5:30am
v2
Comments
[no name] 26-Oct-23 7:53am    
You need to check the inb function to see what it is returning.

1 solution

It's a difficult thing to do.

C stdin is not suitable for interactive text input, though people do write programs like vi on top of stdin, and they work after a fashion, but it's very hard for the user to get the hang of how to achieve basic things like editing a line or saving a portion of text.

And so essentially you either have to use a high level interface to text editing facilities, in which case you are piggy backing on someone else's operating system, or you have to treat the keyboard as a device with button on it rather than as something which produces a stream of text, and then write interactive code on top of it.

I had exactly the same problem when writing the Baby X shell. You want to make it easy for the user to edit text. There is just no way of doing so without resorting to OS-specific keyboard event interceptors. You must have keys like arrow keys to allow the user to navigate the caret around the text input area. They cannot do that if the arrow keys are not represented in some way as input from the keyboard. And whilst you can build a decent text eidtor on top of a stream of characters, navifgation, and a raster, it also helps a lot if you cana ccessthe stateof the shift keys in some way. Keyboards will embed control characters as ASCII values under 32. But these are esinged for transmission, not for interactive editing.

And if you go too low level then you find that the keyboard needs to be interrupt driven and the input events put into a buffer and converted to key up / key down events, which need further processing into keyboard events and character input events. And of course this is done routinely for every single device which is connect to a keyboard. And it's 2024 and my Windows OS still gets the Aple keyboard wrong, and it keeeps on reverting to the alternative convention for the double quotes character.

And of course modern users tend to expect Unicode, which is a whole area of complexity added on top. When I'm not writing technical articles about programming, I'm writing religious articles, and Hebrew is not just Latin with a different alphabet. Far more to it than that.

I can point you in the direction of how I added edit boxes to Baby X. But that was a very specific approach to a specific requirement. And I don't think I did a very good job, keyboard handling is not a strength of Baby X, though the text input facilities are usable.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900