editor: #undef O after use
[0verkill.git] / winconsole.c
blobddd95facea704b256abb048bf88f28abc1df2d90
1 /* CONSOLE INTERFACE FOR WINDOWS */
2 #include "cfg.h"
3 #include "console.h"
4 #include "error.h"
6 int console_ok=1;
8 //#define STD_CONSOLE
9 //#define RAW_MIN_CONSOLE
10 #define RAW_CONSOLE
11 #define RAW_CONSOLE_DIRTY
12 /* allow max 6 character holes when printing blocks of dirty characters (RAW_CONSOLE_DIRTY defined) */
13 #define MAX_SURPLUS 6
15 #ifdef RAW_CONSOLE_DIRTY
16 #ifndef RAW_CONSOLE
17 #error RAW_CONSOLE_DIRTY without RAW_CONSOLE
18 #endif
19 #endif
21 HANDLE hMyConsole;
23 #define DEF_ATTR (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
24 char curattr=DEF_ATTR,
25 color=(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE),
26 bkcolor=0,
27 hilight=0,
28 bkhilight=0;
29 #ifdef STD_CONSOLE
30 #define generate_attributes() { curattr=translate(color)+bkcolor*0x10+hilight*FOREGROUND_INTENSITY+bkhilight*BACKGROUND_INTENSITY; \
31 SetConsoleTextAttribute(hMyConsole, curattr); }
32 #else
33 #define generate_attributes() curattr=translate(color)+bkcolor*0x10+hilight*FOREGROUND_INTENSITY+bkhilight*BACKGROUND_INTENSITY
34 #endif
35 #ifdef RAW_MIN_CONSOLE
36 COORD curpos;
37 #endif
38 #ifdef RAW_CONSOLE
39 char *screenC=NULL;
40 WORD *screenA=NULL;
41 #ifdef RAW_CONSOLE_DIRTY
42 unsigned char *dirtyChars=NULL,
43 *dirtyLines=NULL;
44 int *dirtyBlockStart=NULL;
45 #endif
46 int curpos,
47 width,
48 height;
49 #endif
51 void c_init(int w, int h) {
52 COORD crd;
53 SMALL_RECT sr;
55 hMyConsole=GetStdHandle(STD_OUTPUT_HANDLE);
57 SetConsoleMode(hMyConsole, 0);
59 #ifdef RAW_MIN_CONSOLE
60 curpos.X=0;
61 curpos.Y=0;
62 #endif
63 #ifdef RAW_CONSOLE
64 curpos=0;
65 #endif
67 if ( w==-1 ) {
68 CONSOLE_SCREEN_BUFFER_INFO sbi;
69 GetConsoleScreenBufferInfo(hMyConsole, &sbi);
70 w=sbi.srWindow.Right-sbi.srWindow.Left+1;
71 h=sbi.srWindow.Bottom-sbi.srWindow.Top+1;
73 #ifdef RAW_CONSOLE
74 width=w;
75 height=h;
76 if ( !(screenC=mem_alloc(w*h)) )
77 {exit(1);}
78 if ( !(screenA=mem_alloc(sizeof(SHORT)*w*h)) )
79 {exit(1);}
80 memset(screenC, 0, w*h);
81 memset(screenA, 0, w*h*sizeof(SHORT));
82 #ifdef RAW_CONSOLE_DIRTY
83 if ( !(dirtyChars=mem_alloc(w*h)) )
84 {exit(1);}
85 if ( !(dirtyLines=mem_alloc(h)) )
86 {exit(1);}
87 if ( !(dirtyBlockStart=mem_alloc(h*sizeof(int))) )
88 {exit(1);}
89 memset(dirtyChars, 1, w*h);
90 memset(dirtyLines, 1, h);
91 memset(dirtyBlockStart, 0, h*sizeof(int));
92 #endif
93 #endif
95 crd.X=w;
96 crd.Y=h;
98 SetConsoleScreenBufferSize(hMyConsole, crd);
99 crd=GetLargestConsoleWindowSize(hMyConsole);
100 sr.Left=0;
101 sr.Top=0;
102 sr.Right=min(crd.X-1, w-1);
103 sr.Bottom=min(crd.Y-1, h-1);
104 SetConsoleWindowInfo(hMyConsole, TRUE, &sr);
105 kbd_init();
106 c_cls();
109 void c_shutdown(void) {
110 kbd_close();
111 #ifdef RAW_CONSOLE
112 if ( screenC ) {
113 mem_free(screenC);
114 screenC=NULL;
116 if ( screenA ) {
117 mem_free(screenA);
118 screenA=NULL;
120 #ifdef RAW_CONSOLE_DIRTY
121 if ( dirtyChars ) {
122 mem_free(dirtyChars);
123 dirtyChars=NULL;
125 /* dalsi chyba woken ... */
126 /*if ( dirtyLines ) {
127 mem_free(dirtyLines);
128 dirtyLines=NULL;
130 if ( dirtyBlockStart ) {
131 mem_free(dirtyBlockStart);
132 dirtyBlockStart=NULL;
134 #endif
135 #endif
136 c_cursor(1);
139 void c_cls(void) {
140 // clears the screen:
141 #ifndef RAW_CONSOLE
142 COORD coord;
143 DWORD written;
144 int x,
146 c_get_size(&x, &y);
147 coord.X=coord.Y=0;
148 FillConsoleOutputCharacter(hMyConsole, 0, x*y, coord, &written);
149 FillConsoleOutputAttribute(hMyConsole, 0, x*y, coord, &written);
150 #else
151 memset(screenC, 0, width*height);
152 memset(screenA, 0, width*height);
153 #ifdef RAW_CONSOLE_DIRTY
154 memset(dirtyChars, 1, width*height);
155 memset(dirtyLines, 1, height);
156 memset(dirtyBlockStart, 0xFF, height*sizeof(int));
157 #endif
158 #endif
161 void c_print(char *text) {
162 #ifdef RAW_CONSOLE
163 int firstNonDirty=-1;
164 while( *text ) {
165 if ( curpos>width*height )
166 return;
167 #ifdef RAW_CONSOLE_DIRTY
168 if ( dirtyChars[curpos]==0 ) {
169 if ( firstNonDirty!=-1 )
170 firstNonDirty=curpos;
171 else
172 dirtyChars[curpos]=-1;
174 else if ( firstNonDirty!=-1 ) {
175 dirtyChars[firstNonDirty]=curpos-firstNonDirty;
176 firstNonDirty=-1;
178 #endif
179 screenA[curpos]=curattr;//curpos/2;
180 screenC[curpos++]=*(text++);//'0'+((( curpos%2 )? curpos/2 : curpos/20)%10);
182 #ifdef RAW_CONSOLE_DIRTY
183 if ( firstNonDirty!=-1 )
184 dirtyChars[firstNonDirty]=curpos-firstNonDirty;
185 dirtyBlockStart[curpos/width]=-1;
186 dirtyLines[curpos/width]=1;
187 #endif
188 #endif
189 #ifdef STD_CONSOLE
190 DWORD written;
191 WriteConsole(hMyConsole, text, strlen(text), &written, NULL);
192 #endif
193 #ifdef RAW_MIN_CONSOLE
194 DWORD wr,
195 len=strlen(text);
196 WriteConsoleOutputCharacter(hMyConsole, text, len, curpos, &wr);
197 FillConsoleOutputAttribute(hMyConsole, curattr, len, curpos, &wr);
198 curpos.X+=(SHORT)len;
199 #endif
202 void c_print_l(char * text, int len)
204 int l = 0;
205 char b[2] = {0,0};
206 while(l++ < len) {
207 b[0] = *text++;
208 c_print(b);
212 void c_putc(char c) {
213 #ifdef RAW_CONSOLE
214 if ( curpos>width*height )
215 return;
216 #ifdef RAW_CONSOLE_DIRTY
217 if ( dirtyChars[curpos]==0 ) {
218 if ( dirtyBlockStart[curpos/width]==-1 ) {
219 dirtyBlockStart[curpos/width]=curpos%width;
220 dirtyChars[curpos]=1;
221 dirtyLines[curpos/width]=1;
223 else if ( dirtyBlockStart[curpos/width]+dirtyChars[dirtyBlockStart[curpos/width]]==curpos%width ) {
224 dirtyChars[curpos]=-1;
225 if ( ++dirtyChars[dirtyBlockStart[curpos/width]]==254 )
226 dirtyBlockStart[curpos/width]=-1;
228 else {
229 dirtyBlockStart[curpos/width]=curpos%width;
230 dirtyChars[curpos]=1;
233 #endif
234 screenA[curpos]=curattr;//curpos/2;
235 screenC[curpos++]=c;//'0'+((( curpos%2 )? curpos/2 : curpos/20)%10;
236 #endif
237 #ifdef STD_CONSOLE
238 DWORD written;
239 WriteConsole(hMyConsole, &c, sizeof(c), &written, NULL);
240 #endif
241 #ifdef RAW_MIN_CONSOLE
242 DWORD wr;
243 WriteConsoleOutputCharacter(hMyConsole, &c, 1, curpos, &wr);
244 FillConsoleOutputAttribute(hMyConsole, curattr, 1, curpos, &wr);
245 ++curpos.X;
246 #endif
249 void c_goto(int x, int y) {
250 #ifdef STD_CONSOLE
251 COORD coord;
252 coord.X=x;
253 coord.Y=y;
254 SetConsoleCursorPosition(hMyConsole, coord);
255 #endif
256 #ifdef RAW_MIN_CONSOLE
257 curpos.X=x;
258 curpos.Y=y;
259 #endif
260 #ifdef RAW_CONSOLE
261 curpos=x+y*width;
262 #endif
265 void c_clear(int x1,int y1,int x2, int y2) {
266 #ifndef RAW_CONSOLE
267 COORD coord;
268 DWORD written;
269 int y,
270 w=x2-x1;
271 if ( w<=0 )
272 return;
273 coord.X=x1;
274 for(y=y1; y<=y2; y++) {
275 coord.Y=y;
276 FillConsoleOutputCharacter(hMyConsole, 0, w, coord, &written);
277 FillConsoleOutputAttribute(hMyConsole, 0, w, coord, &written);
279 #else
280 int y;
281 if ( x1>=x2 )
282 return;
283 for(y=y1; y<=y2; y++) {
284 memset(screenC+x1+y*width, 0, x2-x1);
285 memset(screenA+x1+y*width, DEF_ATTR, x2-x1);
286 memset(dirtyChars+x1+y*width, 1, x2-x1);
288 #ifdef RAW_CONSOLE_DIRTY
289 memset(dirtyLines+y1, 1, y2-y1);
290 memset(dirtyBlockStart+y1, 0xFF, (y2-y1)*sizeof(int));
291 #endif
292 #endif
295 void c_cursor(int c) {
296 CONSOLE_CURSOR_INFO ci;
297 GetConsoleCursorInfo(hMyConsole, &ci);
298 ci.bVisible=( c==C_NORMAL );
299 SetConsoleCursorInfo(hMyConsole, &ci);
302 void c_bell(void) {
303 MessageBeep(0xFFFFFFFF);
306 int translate(int a) {
307 int ma=a;
308 /*switch(a&0x7) {
309 case 0:
310 ma=0;
311 break;
312 case 1:
313 ma=FOREGROUND_RED;
314 break;
315 case 2:
316 ma=FOREGROUND_GREEN;
317 break;
318 case 3:
319 ma=FOREGROUND_RED|FOREGROUND_GREEN;
320 break;
321 case 4:
322 ma=FOREGROUND_BLUE;
323 break;
324 case 5:
325 ma=FOREGROUND_BLUE|FOREGROUND_RED;
326 break;
327 case 6:
328 ma=FOREGROUND_BLUE|FOREGROUND_GREEN;
329 break;
330 case 7:
331 ma=FOREGROUND_BLUE|FOREGROUND_RED|FOREGROUND_GREEN;
332 break;
334 ma=(a&0xFA)+0x4*(a&0x1)+(( a&0x4 )? 1 : 0);
335 return ma;
338 /* set complete foreground color */
339 void c_setcolor(unsigned char a) {
340 /*CONSOLE_SCREEN_BUFFER_INFO ci;
341 GetConsoleScreenBufferInfo(hMyConsole, &ci);
342 SetConsoleTextAttribute(hMyConsole, (a&0xF)+(ci.wAttributes&~0x000F));*/
343 //translate(&a);
344 color=a&0x7;
345 hilight=( a>>3 ) ? 1 : 0;
346 generate_attributes();
349 /* set complete foreground color and background color */
350 void c_setcolor_bg(unsigned char fg,unsigned char bg) {
351 /*CONSOLE_SCREEN_BUFFER_INFO ci;
352 GetConsoleScreenBufferInfo(hMyConsole, &ci);
353 SetConsoleTextAttribute(hMyConsole, (fg&0xF)+((bg&0xF)<<8)+(ci.wAttributes&~0x00FF));*/
354 //translate(&fg);
355 //translate(&bg);
356 //curattr=(curattr&~0xFF)|(fg&0xF)|((bg&0xF)<<8);
357 fg&=0xF;
358 if (!(fg>>3)&&!bg) {
359 color=fg&0x7;
360 hilight=( fg>>3 ) ? 1 : 0;
362 else {
363 color=fg&0x7;
364 bkcolor=bg&0x7;
365 hilight=( fg>>3 ) ? 1 : 0;
366 //bkhilight=( bg>>3 ) ? 1 : 0;
368 generate_attributes();
371 void c_setcolor_3b(unsigned char a) {
372 /*CONSOLE_SCREEN_BUFFER_INFO ci;
373 GetConsoleScreenBufferInfo(hMyConsole, &ci);
374 SetConsoleTextAttribute(hMyConsole, (a&0x7)+(ci.wAttributes&~0x0007));*/
375 //translate(&a);
376 color=a&0x7;
377 generate_attributes();
380 void c_setcolor_3b_bg(unsigned char fg,unsigned char bg) {
381 /*CONSOLE_SCREEN_BUFFER_INFO ci;
382 GetConsoleScreenBufferInfo(hMyConsole, &ci);
383 SetConsoleTextAttribute(hMyConsole, (fg&0x7)+((bg&0x7)<<8)+(ci.wAttributes&~0x0077))*/;
384 //translate(&fg);
385 //translate(&bg);
386 color=fg&0x7;
387 bkcolor=bg&0x7;
388 generate_attributes();
391 /* set highlight color */
392 void c_sethlt(unsigned char a) {
393 /*CONSOLE_SCREEN_BUFFER_INFO ci;
394 GetConsoleScreenBufferInfo(hMyConsole, &ci);
395 SetConsoleTextAttribute(hMyConsole, (a ? FOREGROUND_INTENSITY : 0)+(ci.wAttributes&~FOREGROUND_INTENSITY));*/
396 hilight=a ? 1 : 0;
397 generate_attributes();
400 /* set highlight and background color */
401 void c_sethlt_bg(unsigned char hlt,unsigned char bg) {
402 /*CONSOLE_SCREEN_BUFFER_INFO ci;
403 GetConsoleScreenBufferInfo(hMyConsole, &ci);
404 SetConsoleTextAttribute(hMyConsole, (hlt ? BACKGROUND_INTENSITY : 0)+((bg&0xF)<<8)+(ci.wAttributes&~0x00F0));*/
405 //translate(&bg);
406 bkcolor=bg&0x7;
407 hilight=hlt ? 1 : 0;
408 generate_attributes();
411 /* set background color */
412 void c_setbgcolor(unsigned char a) {
413 /*CONSOLE_SCREEN_BUFFER_INFO ci;
414 GetConsoleScreenBufferInfo(hMyConsole, &ci);
415 SetConsoleTextAttribute(hMyConsole, ((a&0xF)<<8)+(ci.wAttributes&~0x00F0));*/
416 //translate(&a);
417 //bkhilight=( a>>3 ) ? 1 : 0;
418 bkcolor=a&0x7;
419 generate_attributes();
422 void c_refresh(void) {
423 #ifdef STD_CONSOLE
424 FlushFileBuffers(hMyConsole);
425 #endif
426 #ifdef RAW_CONSOLE
427 #ifndef RAW_CONSOLE_DIRTY
428 COORD coord;
429 DWORD written;
430 coord.X=coord.Y=0;
431 WriteConsoleOutputCharacter(hMyConsole, screenC, width*height, coord, &written);
432 WriteConsoleOutputAttribute(hMyConsole, screenA, width*height, coord, &written);
433 #else
434 DWORD written;
435 int chr,
436 base,
437 cnt=0,
438 sur;
439 COORD coord;
440 for(coord.Y=0; coord.Y<height; coord.Y++) if ( dirtyLines[coord.Y] ) {
441 base=((DWORD)coord.Y)*width;
442 sur=0;
443 for(chr=0; chr<width; chr++) {
444 if ( dirtyChars[base+chr] ) {
445 if ( sur ) {
446 cnt+=sur;
447 sur=0;
449 if ( dirtyChars[base+chr]==-1 )
450 dirtyChars[base+chr]=1;
451 cnt+=dirtyChars[base+chr];
452 chr+=dirtyChars[base+chr]-1; // -1 ... ++
454 else if ( cnt ) {
455 if ( ++sur>1 ) {
456 coord.X=chr-(cnt+sur-1);
457 WriteConsoleOutputCharacter(hMyConsole, screenC+base+coord.X, cnt, coord, &written);
458 WriteConsoleOutputAttribute(hMyConsole, screenA+base+coord.X, cnt, coord, &written);
459 cnt=0;
460 sur=0;
464 if ( cnt ) {
465 coord.X=chr-(cnt+sur);
466 WriteConsoleOutputCharacter(hMyConsole, screenC+base+coord.X, cnt, coord, &written);
467 WriteConsoleOutputAttribute(hMyConsole, screenA+base+coord.X, cnt, coord, &written);
468 cnt=0;
471 memset(dirtyChars, 0, width*height);
472 memset(dirtyLines, 0, height);
473 memset(dirtyBlockStart, 0xFF, height*sizeof(int));
474 #endif
475 #endif
478 void c_get_size(int *x,int *y) {
479 CONSOLE_SCREEN_BUFFER_INFO sbi;
480 if ( !hMyConsole )
481 hMyConsole=GetStdHandle(STD_OUTPUT_HANDLE);
482 GetConsoleScreenBufferInfo(hMyConsole, &sbi);
483 *x=sbi.srWindow.Right-sbi.srWindow.Left+1;
484 *y=sbi.srWindow.Bottom-sbi.srWindow.Top+1;
487 int c_pressed(int k) {
488 return kbd_is_pressed(k);
491 int c_was_pressed(int k) {
492 return kbd_was_pressed(k);
495 void c_wait_for_key(void) {
496 kbd_wait_for_key();
499 void c_update_kbd(void) {
500 kbd_update();