#include <stdint.h>
__attribute__((section(".multiboot")))uint32_t mb[3]={0x1BADB002,0x00010003,-(0x1BADB002+0x00010003)};
static inline uint8_t inb(uint16_t p){uint8_t r;__asm__("inb %1,%0":"=a"(r):"Nd"(p));return r;}
static inline void outb(uint16_t p,uint8_t v){__asm__("outb %0,%1": :"a"(v),"Nd"(p));}

// French AZERTY keyboard scan code to character mapping (from vgatexteditor.c)
static const char KMAP[] = {
    0,0,'1','2','3','4','5','6','7','8','9','0','-','=','\b',
    0,'a','z','e','r','t','y','u','i','o','p','^','$','\n',
    0,'q','s','d','f','g','h','j','k','l','m','%','*',
    0,0,'w','x','c','v','b','n',',',';',':','!','\'',
};

// Arial-like font: 7 rows x 5 cols, raw bytes (MSB=left)
static const uint8_t F[95*7] = {
// !"#$%&'()*+,-./
0x3E,0x41,0x41,0x41,0x41,0x41,0x3E,  // !
0x7F,0x49,0x49,0x49,0x49,0x41,0x3F,  // "
0x00,0x6C,0xFE,0x6C,0x00,0x00,0x00,  // #
0x18,0x3E,0x99,0x7E,0x18,0x00,0x00,  // $
0xC6,0xC6,0x00,0x30,0x66,0x66,0x00,  // %
0xC6,0xC6,0x1C,0x36,0x67,0x36,0x00,  // &
0x18,0x3C,0x18,0x00,0x00,0x00,0x00,  // '
0x0C,0x18,0x18,0x18,0x18,0x0C,0x00,  // (
0x18,0x0C,0x0C,0x0C,0x0C,0x18,0x00,  // )
0x6C,0xFF,0x36,0xFF,0x6C,0x00,0x00,  // *
0x18,0x18,0x7E,0x18,0x18,0x00,0x00,  // +
0x00,0x06,0x0C,0x06,0x00,0x00,0x00,  // ,
0x00,0x00,0x7E,0x00,0x00,0x00,0x00,  // -
0x00,0x00,0x06,0x00,0x00,0x00,0x00,  // .
0x06,0x0C,0x18,0x30,0x60,0x00,0x00,  // /
// 0-9
0x3C,0x66,0x66,0x66,0x3C,0x00,0x00,  // 0
0x18,0x38,0x18,0x18,0x7E,0x00,0x00,  // 1
0x3C,0x66,0x06,0x0C,0x78,0x00,0x00,  // 2
0x3C,0x66,0x0C,0x66,0x3C,0x00,0x00,  // 3
0x18,0x3C,0x66,0x7E,0x06,0x00,0x00,  // 4
0x78,0x0C,0x78,0x66,0x3C,0x00,0x00,  // 5
0x3C,0x0C,0x78,0x66,0x3C,0x00,0x00,  // 6
0x7E,0x66,0x0C,0x0C,0x0C,0x00,0x00,  // 7
0x3C,0x66,0x0C,0x18,0x3C,0x00,0x00,  // 8
0x3C,0x66,0x06,0x0C,0x38,0x00,0x00,  // 9
// :;<=>?@
0x00,0x00,0x7E,0x00,0x00,0x00,0x00,  // :
0x06,0x0C,0x18,0x0C,0x06,0x00,0x00,  // ;
0x06,0x0C,0x18,0x0C,0x06,0x00,0x00,  // <
0x00,0x00,0x7E,0x00,0x00,0x00,0x00,  // =
0x06,0x0C,0x18,0x0C,0x06,0x00,0x00,  // >
0x3C,0x66,0x06,0x0C,0x18,0x00,0x00,  // ?
0x1C,0x36,0x63,0x7E,0x66,0x3E,0x00,  // @
// A-Z
0x18,0x3C,0x66,0x66,0x66,0x3C,0x00,  // A
0x78,0x66,0x78,0x66,0x78,0x00,0x00,  // B
0x3C,0x66,0x60,0x60,0x60,0x3C,0x00,  // C
0x78,0x66,0x66,0x66,0x78,0x00,0x00,  // D
0x7E,0x06,0x7C,0x06,0x06,0x00,0x00,  // E
0x7E,0x06,0x7C,0x06,0x06,0x00,0x00,  // F
0x3C,0x66,0x60,0x66,0x3C,0x18,0x00,  // G
0x66,0x66,0x7E,0x66,0x66,0x00,0x00,  // H
0x3C,0x18,0x18,0x18,0x3C,0x00,0x00,  // I
0x1E,0x06,0x06,0x66,0x3C,0x00,0x00,  // J
0x66,0x6C,0x78,0x6C,0x66,0x00,0x00,  // K
0x06,0x06,0x06,0x06,0x7E,0x00,0x00,  // L
0x63,0x77,0x7F,0x6B,0x63,0x00,0x00,  // M
0x61,0x73,0x7B,0x6F,0x67,0x00,0x00,  // N
0x3C,0x66,0x66,0x66,0x3C,0x00,0x00,  // O
0x78,0x66,0x78,0x06,0x06,0x00,0x00,  // P
0x3C,0x66,0x66,0x6E,0x3E,0x1C,0x00,  // Q
0x78,0x66,0x78,0x6C,0x66,0x00,0x00,  // R
0x3C,0x66,0x0C,0x66,0x3C,0x00,0x00,  // S
0x7E,0x18,0x18,0x18,0x3C,0x00,0x00,  // T
0x66,0x66,0x66,0x66,0x3C,0x00,0x00,  // U
0x66,0x66,0x3C,0x18,0x18,0x00,0x00,  // V
0x63,0x63,0x7F,0x63,0x63,0x00,0x00,  // W
0x66,0xC6,0x3C,0xC6,0x66,0x00,0x00,  // X
0x66,0x66,0x1C,0x18,0x18,0x00,0x00,  // Y
0x7E,0x66,0x0C,0x06,0x7E,0x00,0x00,  // Z
// [ \ ] ^ _ `
0x18,0x3C,0x66,0x00,0x00,0x00,0x00,  // [
0x60,0x30,0x18,0x0C,0x06,0x00,0x00,  // \
0x00,0x00,0x66,0x3C,0x18,0x00,0x00,  // ]
0x18,0x3C,0x18,0x00,0x00,0x00,0x00,  // ^
0x60,0x30,0x00,0x00,0x00,0x00,0x00,  // _
0x18,0x3C,0x18,0x00,0x00,0x00,0x00,  // `
// a-z
0x00,0x18,0x3C,0x66,0x66,0x00,0x00,  // a
0x06,0x0C,0x18,0x3C,0x06,0x00,0x00,  // b
0x00,0x18,0x30,0x30,0x18,0x00,0x00,  // c
0x0C,0x06,0x06,0x06,0x3C,0x00,0x00,  // d
0x00,0x18,0x7E,0x60,0x3C,0x00,0x00,  // e
0x18,0x3C,0x18,0x18,0x0C,0x00,0x00,  // f
0x00,0x18,0x3C,0x66,0x7E,0x06,0x00,  // g
0x06,0x0C,0x18,0x18,0x18,0x00,0x00,  // h
0x18,0x00,0x18,0x18,0x3C,0x00,0x00,  // i
0x06,0x00,0x06,0x06,0x3C,0x00,0x00,  // j
0x06,0x0C,0x18,0x18,0x0C,0x00,0x00,  // k
0x18,0x18,0x18,0x18,0x3C,0x00,0x00,  // l
0x00,0x18,0x3C,0x66,0x7E,0x66,0x00,  // m
0x00,0x18,0x1C,0x1E,0x18,0x00,0x00,  // n
0x00,0x18,0x30,0x30,0x18,0x00,0x00,  // o
0x00,0x7C,0x66,0x7C,0x06,0x00,0x00,  // p
0x00,0x06,0x3C,0x66,0x7C,0x18,0x00,  // q
0x00,0x18,0x3C,0x06,0x00,0x00,0x00,  // r
0x00,0x18,0x30,0x78,0x0C,0x00,0x00,  // s
0x1C,0x18,0x3C,0x18,0x18,0x00,0x00,  // t
0x06,0x06,0x06,0x06,0x3C,0x00,0x00,  // u
0x06,0x06,0x18,0x3C,0x06,0x00,0x00,  // v
0x06,0x06,0x18,0x3C,0x18,0x00,0x00,  // w
0x06,0x0C,0x30,0x0C,0x06,0x00,0x00,  // x
0x00,0x18,0x30,0x7E,0x06,0x00,0x00,  // y
0x00,0x7E,0x66,0x0C,0x7E,0x00,0x00,  // z
// { | } ~
0x0C,0x18,0x18,0x18,0x18,0x0C,0x00,  // {
0x18,0x18,0x18,0x18,0x18,0x00,0x00,  // |
0x18,0x18,0x18,0x18,0x0C,0x18,0x00,  // }
0x60,0xC0,0x60,0x00,0x00,0x00,0x00,  // ~
};

volatile uint32_t *fb;
int pitch=2560, w=640, h=480;

// Draw single character at pixel position with scaling
void dc(int x, int y, char c, uint32_t fg) {
    if(c < ' ' || c > '~') return;
    int idx = (c - 32) * 7;
    const int scale = 4;
    for(int row = 0; row < 7; row++) {
        uint8_t b = F[idx + row];
        for(int col = 0; col < 5; col++) {
            if(b & (1 << (4 - col))) {
                int sx = x + col * scale;
                int sy = y + row * scale;
                for(int dy = 0; dy < scale; dy++) {
                    for(int dx = 0; dx < scale; dx++) {
                        int px = sx + dx, py = sy + dy;
                        if(px >= 0 && px < w && py >= 0 && py < h)
                            fb[py * pitch / 4 + px] = fg;
                    }
                }
            }
        }
    }
}

void dt(int x, int y, char *s, uint32_t fg) {
    while(*s) dc(x, y, *s++, fg);
}

// Line buffer and cursor state
char L[25][80];
int l[25], cl = 0, cc = 0;

void R() {
    // Clear framebuffer with dark background
    for(int j = 0; j < h * pitch / 4; j++) fb[j] = 0x1A1A2E;
    
    // Draw header bar
    for(int x = 0; x < w; x++)
        for(int y = 0; y < 32; y++)
            fb[y * pitch / 4 + x] = 0x1E1E4E;
    
    dt(10, 8, "TEXT EDITOR", 0x00FF00);
    
    // Render each line
    for(int j = 0; j < 25; j++) {
        int ly = j * 32 + 40;
        // Line number
        char n[3];
        n[0] = (j / 10) + '0';
        n[1] = (j % 10) + '0';
        n[2] = 0;
        dt(5, ly, n, 0x8888AA);
        
        // Line content
        for(int k = 0; k < l[j] && k < 78; k++) {
            int cx = 40 + k * 24;
            if(cx > w - 20) break;
            dc(cx, ly, L[j][k], 0xE94560);
        }
        
        // Cursor highlight
        if(j == cl) {
            int cx = 40 + cc * 24;
            for(int py = ly; py < ly + 32 && py < h; py++)
                for(int px = cx; px < cx + 16 && px < w; px++)
                    fb[py * pitch / 4 + px] = 0xFFFFFF;
        }
    }
}

void H(uint8_t s) {
    if(s == 1 || s & 0x80) return;
    
    // Escape sequence state machine
    static int e = 0;
    if(e == 0) {
        if(s == 27) e = 1;
    } else if(e == 1) {
        if(s == '[') e = 2;
        else e = 0;
    } else if(e == 2) {
        e = 0;
        if(s == 'A' && cl > 0) cl--;
        else if(s == 'B' && cl < 24) cl++;
        else if(s == 'C' && cc <= l[cl]) cc++;
        else if(s == 'D' && cc > 0) cc--;
    }
    
    if(e) { R(); return; }
    
    // Raw scan code handling for arrow keys
    if(!e) {
        if(s == 0x48 && cl > 0) cl--;
        else if(s == 0x50 && cl < 24) cl++;
        else if(s == 0x4B && cc > 0) cc--;
        else if(s == 0x4D && cc <= l[cl]) cc++;
    }
    
    if(e) { R(); return; }
    
    // Backspace (0x0E)
    if(s == 0x0E) {
        if(cc > 0) {
            for(int j = cc; j < l[cl]; j++) L[cl][j-1] = L[cl][j];
            l[cl]--; L[cl][l[cl]] = 0; cc--;
        } else if(cl > 0) {
            int p = l[cl-1], c = l[cl];
            for(int j = 0; j <= c; j++) L[cl-1][p+j] = L[cl][j];
            l[cl-1] += c;
            for(int j = cl; j < 24; j++) {
                l[j] = l[j+1];
                for(int k = 0; k <= l[j+1]; k++) L[j][k] = L[j+1][k];
            }
            cl--;
        }
    } else if(s == 0x1C) { // Enter
        int r = l[cl] - cc;
        for(int j = 24; j > cl; j--) {
            l[j] = l[j-1];
            for(int k = 0; k <= l[j-1]; k++) L[j][k] = L[j-1][k];
        }
        if(r > 0)
            for(int j = 0; j < r; j++) L[cl+1][j] = L[cl][cc+j];
        l[cl+1] = r; L[cl+1][r] = 0;
        l[cl] = cc; L[cl][cc] = 0;
        cl++; cc = 0;
    } else if(s < 128 && KMAP[s]) {
        char c = KMAP[s];
        if(cc < 78) {
            for(int j = l[cl]+1; j > cc; j--) L[cl][j] = L[cl][j-1];
            L[cl][cc] = c; l[cl]++; cc++;
        }
    }
    R();
}

void kernel_main(uint32_t m, uint32_t i) {
    if(m != 0x2BADB002) while(1);
    
    // Set VGA mode via BIOS interrupt (same as svgatexteditor.c)
    uint8_t vf = 0x4F;
    __asm__("outb %0,%1" : : "a"(vf), "d"((uint16_t)0x01CF));
    vf = 0x15;
    __asm__("outb %0,%1" : : "a"(vf), "d"((uint16_t)0x01CE));
    
    fb = (volatile uint32_t*)0xE0000000;
    
    // Initialize lines
    for(int j = 0; j < 25; j++) { l[j] = 0; L[j][0] = 0; }
    
    R();
    
    while(1) {
        while(!(inb(0x64) & 1));
        H(inb(0x60));
    }
}