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);
74 * Updates hardware cursor
76 static void update_hwcursor() {
77 uint32_t pos
= cursor
.row
*VIDEOTEXT_WIDTH
+cursor
.col
;
87 static void clearscreen() {
89 for (i
=0;i
<VIDEOTEXT_WIDTH
*VIDEOTEXT_HEIGHT
;i
++) videomem
[i
] = VIDEOTEXT_STDCOLOR
<<8;
90 cursor
.col
= VIDEOTEXT_STDCOL
;
91 cursor
.row
= VIDEOTEXT_STDROW
;
96 * Sets default settings
98 static void default_settings() {
99 settings
.linewrap
= 1;
100 settings
.bell_freq
= 440;
101 settings
.bell_dur
= 100;
102 settings
.color
= VIDEOTEXT_STDCOLOR
;
106 * Prints a character on screen
107 * @param chr Character
109 static int printchar(char chr
) {
110 size_t pos
= cursor_offset();
111 static int escape
= 0;
112 static char escape_buf
[32];
115 escape_buf
[(escape
++)-1] = chr
; // put byte in escape buffer
117 if (isalpha(chr
)) { // escape code finished
118 if (escape
==1 && escape_buf
[0]=='c') default_settings(); // reset device
119 else if (escape
==3 && memcmp(escape_buf
,"[7h",3)==0) settings
.linewrap
= 1; // enable linewrap
120 else if (escape
==3 && memcmp(escape_buf
,"[7l",3)==0) settings
.linewrap
= 0; // disable linewrap
121 else if (escape_buf
[0]=='[' && (escape_buf
[escape
-2]=='H' || escape_buf
[escape
-2]=='f')) { // set cursor position
124 if (escape
>3) sscanf(escape_buf
,escape_buf
[escape
-2]=='H'?"[%d;%dH":"[%d;%df",&row
,&col
);
125 if (row
!=-1 && col
!=-1) {
134 else if (escape_buf
[0]=='[' && escape_buf
[escape
-2]=='A') {
136 if (escape
>3) sscanf(escape_buf
,"[%dA",&up
);
137 if (cursor
.row
>0) cursor
.row
-= up
;
139 else if (escape_buf
[0]=='[' && escape_buf
[escape
-2]=='B') {
141 if (escape
>3) sscanf(escape_buf
,"[%dB",&down
);
142 if (cursor
.row
<VIDEOTEXT_HEIGHT
) cursor
.row
+= down
;
144 else if (escape_buf
[0]=='[' && escape_buf
[escape
-2]=='C') {
146 if (escape
>3) sscanf(escape_buf
,"[%dC",&left
);
147 if (cursor
.col
>0) cursor
.col
-= left
;
149 else if (escape_buf
[0]=='[' && escape_buf
[escape
-2]=='D') {
151 if (escape
>3) sscanf(escape_buf
,"[%dD",&right
);
152 if (cursor
.col
<VIDEOTEXT_WIDTH
) cursor
.col
+= right
;
154 else if (escape_buf
[0]=='[' && (escape_buf
[1]=='s' || escape_buf
[1]=='7')) {
155 memcpy(&saved_cursor
,&cursor
,sizeof(cursor
));
157 else if (escape_buf
[0]=='[' && (escape_buf
[1]=='u' || escape_buf
[1]=='8')) {
158 memcpy(&cursor
,&saved_cursor
,sizeof(cursor
));
160 else if (memcmp(escape_buf
,"[K",2)==0) {
161 memset(videomem
+pos
,0,(VIDEOTEXT_WIDTH
-cursor
.col
+1)*2);
163 else if (memcmp(escape_buf
,"[1K",3)==0) {
164 memset(videomem
+VIDEOTEXT_WIDTH
*cursor
.col
,0,cursor
.row
*2);
166 else if (memcmp(escape_buf
,"[2K",3)==0) {
167 memset(videomem
+VIDEOTEXT_WIDTH
*cursor
.col
,0,VIDEOTEXT_WIDTH
);
169 else if (memcmp(escape_buf
,"[J",2)==0) {
170 memset(videomem
+VIDEOTEXT_WIDTH
*cursor
.col
,0,(VIDEOTEXT_HEIGHT
-cursor
.row
)*VIDEOTEXT_WIDTH
*2);
172 else if (memcmp(escape_buf
,"[1J",3)==0) {
173 memset(videomem
,0,cursor
.row
*VIDEOTEXT_WIDTH
*2);
175 else if (memcmp(escape_buf
,"[2J",3)==0) {
181 else if (chr
=='\a') bell(settings
.bell_freq
,settings
.bell_dur
);
182 else if (chr
=='\b') cursor
.col
= (cursor
.col
-1>0)?(cursor
.col
-1):0;
183 else if (chr
=='\t') cursor
.col
= cursor
.col
+5;
184 else if (chr
=='\n') {
186 cursor
.col
= VIDEOTEXT_STDCOL
;
188 else if (chr
=='\f') clearscreen();
189 else if (chr
=='\r') cursor
.col
= VIDEOTEXT_STDCOL
;
190 else if (chr
==0x1B) escape
= 1;
192 *(videomem
+pos
) = (((uint16_t)settings
.color
)<<8)|chr
;
196 if (cursor
.col
>=VIDEOTEXT_WIDTH
) {
197 cursor
.col
= cursor
.col
-VIDEOTEXT_WIDTH
;
200 while (cursor
.row
>=VIDEOTEXT_HEIGHT
) {
201 memcpy(videomem
,videomem
+VIDEOTEXT_WIDTH
,VIDEOTEXT_SIZE
-VIDEOTEXT_WIDTH
*2);
202 memset(videomem
+VIDEOTEXT_WIDTH
*(VIDEOTEXT_HEIGHT
-1),0,VIDEOTEXT_WIDTH
*2);
212 * Writes characters to screen
213 * @param buffer Chars to write to screen
214 * @param count How many bytes to write to screen
215 * @param dev Device to write to
216 * @return How many bytes written
218 ssize_t
onwrite(devfs_dev_t
*dev
,void *buffer
,size_t count
,off_t offset
) {
221 for (i
=0;i
<count
;i
++) w
+= printchar(((char*)buffer
)[i
]);
226 * Initializes screen driver
227 * @return 0=success; -1=failure
230 videomem
= mem_getvga();
231 if (videomem
==NULL
) return -1;
232 memset(&saved_cursor
,0,sizeof(saved_cursor
));