2 meinOS - A unix-like x86 microkernel operating system
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
30 #define VIDEOTEXT_WIDTH 80 // 80 Cols (chars per line)
31 #define VIDEOTEXT_HEIGHT 25 // 25 Rows (lines)
32 #define VIDEOTEXT_SIZE 4000 // Video size
33 #define VIDEOTEXT_STDCOLOR 0x07 // Default color: black background, lightgray foreground
34 #define VIDEOTEXT_STDCOL 0 // Default col
35 #define VIDEOTEXT_STDROW 0 // Default row
37 #define SCREEN_DEFAULT_FONT "standard"
39 #define cursor_offset() (cursor.row*VIDEOTEXT_WIDTH+cursor.col)
41 // see http://files.osdev.org/mirrors/geezer/osd/graphics/modes.c
47 } cursor
,saved_cursor
;
56 static uint16_t *videomem
;
60 * @param freq Frequency
61 * @param dur Duration time
63 static void bell(int freq
,int dur
) {
66 outb(0x42,(uint8_t)freq
);
67 outb(0x42,(uint8_t)(freq
>>8));
68 outb(0x61,inb(0x61)|3);
70 outb(0x61,inb(0x61)&~3);
76 static void clearscreen() {
77 memset(videomem
,0,VIDEOTEXT_SIZE
);
78 cursor
.col
= VIDEOTEXT_STDCOL
;
79 cursor
.row
= VIDEOTEXT_STDROW
;
83 * Sets default settings
85 static void default_settings() {
86 settings
.linewrap
= 1;
87 settings
.bell_freq
= 440;
88 settings
.bell_dur
= 100;
89 settings
.color
= VIDEOTEXT_STDCOLOR
;
93 * Prints a character on screen
94 * @param chr Character
96 static int printchar(char chr
) {
97 size_t pos
= cursor_offset();
98 static int escape
= 0;
99 static char escape_buf
[32];
102 escape_buf
[(escape
++)-1] = chr
; // put byte in escape buffer
104 if (isalpha(chr
)) { // escape code finished
106 if (escape
==1 && escape_buf
[0]=='c') default_settings(); // reset device
107 else if (escape
==3 && memcmp(escape_buf
,"[7h",3)==0) settings
.linewrap
= 1; // enable linewrap
108 else if (escape
==3 && memcmp(escape_buf
,"[7l",3)==0) settings
.linewrap
= 0; // disable linewrap
109 else if (escape_buf
[0]=='[' && (escape_buf
[escape
-2]=='H' || escape_buf
[escape
-2]=='f')) { // set cursor position
112 if (escape
>3) sscanf(escape_buf
,escape_buf
[escape
-2]=='H'?"[%d;%dH":"[%d;%df",&row
,&col
);
113 if (row
!=-1 && col
!=-1) {
122 else if (escape_buf
[0]=='[' && escape_buf
[escape
-2]=='A') {
124 if (escape
>3) sscanf(escape_buf
,"[%dA",&up
);
125 if (cursor
.row
>0) cursor
.row
-= up
;
127 else if (escape_buf
[0]=='[' && escape_buf
[escape
-2]=='B') {
129 if (escape
>3) sscanf(escape_buf
,"[%dB",&down
);
130 if (cursor
.row
<VIDEOTEXT_HEIGHT
) cursor
.row
+= down
;
132 else if (escape_buf
[0]=='[' && escape_buf
[escape
-2]=='C') {
134 if (escape
>3) sscanf(escape_buf
,"[%dC",&left
);
135 if (cursor
.col
>0) cursor
.col
-= left
;
137 else if (escape_buf
[0]=='[' && escape_buf
[escape
-2]=='D') {
139 if (escape
>3) sscanf(escape_buf
,"[%dD",&right
);
140 if (cursor
.col
<VIDEOTEXT_WIDTH
) cursor
.col
+= right
;
142 else if (escape_buf
[0]=='[' && (escape_buf
[1]=='s' || escape_buf
[1]=='7')) {
143 memcpy(&saved_cursor
,&cursor
,sizeof(cursor
));
145 else if (escape_buf
[0]=='[' && (escape_buf
[1]=='u' || escape_buf
[1]=='8')) {
146 memcpy(&cursor
,&saved_cursor
,sizeof(cursor
));
148 else if (memcmp(escape_buf
,"[K",2)==0) {
149 memset(videomem
+pos
,0,(VIDEOTEXT_WIDTH
-cursor
.col
+1)*2);
151 else if (memcmp(escape_buf
,"[1K",3)==0) {
152 memset(videomem
+VIDEOTEXT_WIDTH
*cursor
.col
,0,cursor
.row
*2);
154 else if (memcmp(escape_buf
,"[2K",3)==0) {
155 memset(videomem
+VIDEOTEXT_WIDTH
*cursor
.col
,0,VIDEOTEXT_WIDTH
);
157 else if (memcmp(escape_buf
,"[J",2)==0) {
158 memset(videomem
+VIDEOTEXT_WIDTH
*cursor
.col
,0,(VIDEOTEXT_HEIGHT
-cursor
.row
)*VIDEOTEXT_WIDTH
*2);
160 else if (memcmp(escape_buf
,"[1J",3)==0) {
161 memset(videomem
,0,cursor
.row
*VIDEOTEXT_WIDTH
*2);
163 else if (memcmp(escape_buf
,"[2J",3)==0) {
168 else if (chr
=='\a') bell(settings
.bell_freq
,settings
.bell_dur
);
169 else if (chr
=='\b') cursor
.col
= (cursor
.col
-1>0)?(cursor
.col
-1):0;
170 else if (chr
=='\t') cursor
.col
= cursor
.col
+5;
171 else if (chr
=='\n') {
173 cursor
.col
= VIDEOTEXT_STDCOL
;
175 else if (chr
=='\f') clearscreen();
176 else if (chr
=='\r') cursor
.col
= VIDEOTEXT_STDCOL
;
177 else if (chr
==0x1B) escape
= 1;
179 *(videomem
+pos
) = (((uint16_t)settings
.color
)<<8)|chr
;
183 if (cursor
.col
>=VIDEOTEXT_WIDTH
) {
184 cursor
.col
= cursor
.col
-VIDEOTEXT_WIDTH
;
187 while (cursor
.row
>=VIDEOTEXT_HEIGHT
) {
188 memcpy(videomem
,videomem
+VIDEOTEXT_WIDTH
,VIDEOTEXT_SIZE
-VIDEOTEXT_WIDTH
*2);
189 memset(videomem
+VIDEOTEXT_WIDTH
*(VIDEOTEXT_HEIGHT
-1),0,VIDEOTEXT_WIDTH
*2);
196 * Writes characters to screen
197 * @param buffer Chars to write to screen
198 * @param count How many bytes to write to screen
199 * @param dev Device to write to
200 * @return How many bytes written
202 ssize_t
onwrite(devfs_dev_t
*dev
,void *buffer
,size_t count
,off_t offset
) {
205 for (i
=0;i
<count
;i
++) w
+= printchar(((char*)buffer
)[i
]);
210 * Initializes screen driver
211 * @return 0=success; -1=failure
214 videomem
= mem_getvga();
215 if (videomem
==NULL
) return -1;
216 memset(&saved_cursor
,0,sizeof(saved_cursor
));