console cursor positioning
[3sys] / sys1 / kern / src / con.c
1 #include <string.h>
2 #include "con.h"
3 #include "vga.h"
4
5 #define NCOLS                   80
6 #define NROWS                   25
7
8 /* must be pow2 */
9 #define TEXTBUF_SIZE    256
10
11 static char textbuf[TEXTBUF_SIZE][NCOLS];
12 static int tbuf_first, tbuf_last;
13
14 static int curx, cury, scroll;
15
16 #define CURSTACK_SIZE   16
17 static unsigned int savecur[CURSTACK_SIZE];
18 static int savecur_top;
19
20
21 static void newline(void);
22
23
24 void con_init(void)
25 {
26         con_reset();
27 }
28
29 void con_reset(void)
30 {
31         vga_reset();
32
33         curx = cury = scroll = 0;
34         tbuf_first = tbuf_last = 0;
35         memset(textbuf[0], 0, sizeof textbuf[0]);
36
37         savecur_top = 0;
38 }
39
40 void con_setcur(int x, int y)
41 {
42         curx = x < 0 ? 0 : (x >= NCOLS ? NCOLS - 1 : x);
43         cury = y < 0 ? 0 : (y >= NROWS ? NROWS - 1 : y);
44 }
45
46 void con_getcur(int *x, int *y)
47 {
48         *x = curx;
49         *y = cury;
50 }
51
52 void con_pushcur(void)
53 {
54         if(savecur_top >= CURSTACK_SIZE) return;
55
56         savecur[savecur_top++] = curx | (cury << 16);
57 }
58
59 void con_popcur(void)
60 {
61         if(savecur_top <= 0) return;
62
63         savecur_top--;
64         curx = savecur[savecur_top] & 0xffff;
65         cury = savecur[savecur_top] >> 16;
66 }
67
68 void con_putchar(int c)
69 {
70         switch(c) {
71         case '\t':
72                 curx = (curx + 8) & 0xfffffff8;
73                 if(curx >= NCOLS) {
74                         newline();
75                 }
76                 break;
77
78         case '\r':
79                 curx = 0;
80                 break;
81
82         case '\n':
83                 newline();
84                 break;
85
86         case '\b':
87                 if(curx > 0) {
88                         textbuf[tbuf_last][--curx] = 0;
89                         vga_drawchar(curx, cury, 0);
90                 }
91                 break;
92
93         default:
94                 textbuf[tbuf_last][curx] = c;
95                 vga_drawchar(curx, cury, c);
96                 if(++curx >= NCOLS) {
97                         newline();
98                 }
99                 break;
100         }
101
102         if(cury >= NROWS) {
103                 cury--;
104                 vga_scroll(++scroll);
105                 vga_clearline(NROWS - 1);
106         }
107
108         vga_setcursor(curx, cury);
109 }
110
111 static void newline(void)
112 {
113         int num;
114
115         curx = 0;
116         cury++;
117
118         num = (tbuf_last + 1) & (TEXTBUF_SIZE - 1);
119
120         if(tbuf_last == tbuf_first) {
121                 tbuf_first = num;
122         }
123         tbuf_last = num;
124 }