|
|
1.1 root 1: /* $Id: win32cio.c,v 1.43 2004/10/20 11:24:26 deuce Exp $ */
2:
3: /****************************************************************************
4: * @format.tab-size 4 (Plain Text/Source Code File Header) *
5: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
6: * *
7: * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html *
8: * *
9: * This library is free software; you can redistribute it and/or *
10: * modify it under the terms of the GNU Lesser General Public License *
11: * as published by the Free Software Foundation; either version 2 *
12: * of the License, or (at your option) any later version. *
13: * See the GNU Lesser General Public License for more details: lgpl.txt or *
14: * http://www.fsf.org/copyleft/lesser.html *
15: * *
16: * Anonymous FTP access to the most recent released source is available at *
17: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
18: * *
19: * Anonymous CVS access to the development source and modification history *
20: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
21: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
22: * (just hit return, no password is necessary) *
23: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
24: * *
25: * For Synchronet coding style and modification guidelines, see *
26: * http://www.synchro.net/source.html *
27: * *
28: * You are encouraged to submit any modifications (preferably in Unix diff *
29: * format) via e-mail to [email protected] *
30: * *
31: * Note: If this box doesn't appear square, then you need to fix your tabs. *
32: ****************************************************************************/
33:
34: #include <windows.h> /* INPUT_RECORD, etc. */
35: #include <genwrap.h>
36: #include <stdio.h> /* stdin */
37:
38: #include "ciolib.h"
39: #include "keys.h"
40: #include "vidmodes.h"
41: #include "win32cio.h"
42:
43: const int cio_tabs[10]={9,17,25,33,41,49,57,65,73,80};
44:
45: struct keyvals {
46: int VirtualKeyCode
47: ,Key
48: ,Shift
49: ,CTRL
50: ,ALT;
51: };
52:
53: const struct keyvals keyval[] =
54: {
55: {VK_BACK, 0x08, 0x08, 0x7f, 0x0e00},
56: {VK_TAB, 0x09, 0x0f00, 0x9400, 0xa500},
57: {VK_RETURN, 0x0d, 0x0d, 0x0a, 0xa600},
58: {VK_ESCAPE, 0x1b, 0x1b, 0x1b, 0x0100},
59: {VK_SPACE, 0x20, 0x20, 0x0300, 0x20,},
60: {'0', '0', ')', 0, 0x8100},
61: {'1', '1', '!', 0, 0x7800},
62: {'2', '2', '@', 0x0300, 0x7900},
63: {'3', '3', '#', 0, 0x7a00},
64: {'4', '4', '$', 0, 0x7b00},
65: {'5', '5', '%', 0, 0x7c00},
66: {'6', '6', '^', 0x1e, 0x7d00},
67: {'7', '7', '&', 0, 0x7e00},
68: {'8', '8', '*', 0, 0x7f00},
69: {'9', '9', '(', 0, 0x8000},
70: {'A', 'a', 'A', 0x01, 0x1e00},
71: {'B', 'b', 'B', 0x02, 0x3000},
72: {'C', 'c', 'C', 0x03, 0x2e00},
73: {'D', 'd', 'D', 0x04, 0x2000},
74: {'E', 'e', 'E', 0x05, 0x1200},
75: {'F', 'f', 'F', 0x06, 0x2100},
76: {'G', 'g', 'G', 0x07, 0x2200},
77: {'H', 'h', 'H', 0x08, 0x2300},
78: {'I', 'i', 'I', 0x09, 0x1700},
79: {'J', 'j', 'J', 0x0a, 0x2400},
80: {'K', 'k', 'K', 0x0b, 0x2500},
81: {'L', 'l', 'L', 0x0c, 0x2600},
82: {'M', 'm', 'M', 0x0d, 0x3200},
83: {'N', 'n', 'N', 0x0e, 0x3100},
84: {'O', 'o', 'O', 0x0f, 0x1800},
85: {'P', 'p', 'P', 0x10, 0x1900},
86: {'Q', 'q', 'Q', 0x11, 0x1000},
87: {'R', 'r', 'R', 0x12, 0x1300},
88: {'S', 's', 'S', 0x13, 0x1f00},
89: {'T', 't', 'T', 0x14, 0x1400},
90: {'U', 'u', 'U', 0x15, 0x1600},
91: {'V', 'v', 'V', 0x16, 0x2f00},
92: {'W', 'w', 'W', 0x17, 0x1100},
93: {'X', 'x', 'X', 0x18, 0x2d00},
94: {'Y', 'y', 'Y', 0x19, 0x1500},
95: {'Z', 'z', 'Z', 0x1a, 0x2c00},
96: {VK_PRIOR, 0x4900, 0x4900, 0x8400, 0x9900},
97: {VK_NEXT, 0x5100, 0x5100, 0x7600, 0xa100},
98: {VK_END, 0x4f00, 0x4f00, 0x7500, 0x9f00},
99: {VK_HOME, 0x4700, 0x4700, 0x7700, 0x9700},
100: {VK_LEFT, 0x4b00, 0x4b00, 0x7300, 0x9b00},
101: {VK_UP, 0x4800, 0x4800, 0x8d00, 0x9800},
102: {VK_RIGHT, 0x4d00, 0x4d00, 0x7400, 0x9d00},
103: {VK_DOWN, 0x5000, 0x5000, 0x9100, 0xa000},
104: {VK_INSERT, 0x5200, 0x5200, 0x9200, 0xa200},
105: {VK_DELETE, 0x5300, 0x5300, 0x9300, 0xa300},
106: {VK_NUMPAD0, '0', 0x5200, 0x9200, 0},
107: {VK_NUMPAD1, '1', 0x4f00, 0x7500, 0},
108: {VK_NUMPAD2, '2', 0x5000, 0x9100, 0},
109: {VK_NUMPAD3, '3', 0x5100, 0x7600, 0},
110: {VK_NUMPAD4, '4', 0x4b00, 0x7300, 0},
111: {VK_NUMPAD5, '5', 0x4c00, 0x8f00, 0},
112: {VK_NUMPAD6, '6', 0x4d00, 0x7400, 0},
113: {VK_NUMPAD7, '7', 0x4700, 0x7700, 0},
114: {VK_NUMPAD8, '8', 0x4800, 0x8d00, 0},
115: {VK_NUMPAD9, '9', 0x4900, 0x8400, 0},
116: {VK_MULTIPLY, '*', '*', 0x9600, 0x3700},
117: {VK_ADD, '+', '+', 0x9000, 0x4e00},
118: {VK_SUBTRACT, '-', '-', 0x8e00, 0x4a00},
119: {VK_DECIMAL, '.', '.', 0x5300, 0x9300},
120: {VK_DIVIDE, '/', '/', 0x9500, 0xa400},
121: {VK_F1, 0x3b00, 0x5400, 0x5e00, 0x6800},
122: {VK_F2, 0x3c00, 0x5500, 0x5f00, 0x6900},
123: {VK_F3, 0x3d00, 0x5600, 0x6000, 0x6a00},
124: {VK_F4, 0x3e00, 0x5700, 0x6100, 0x6b00},
125: {VK_F5, 0x3f00, 0x5800, 0x6200, 0x6c00},
126: {VK_F6, 0x4000, 0x5900, 0x6300, 0x6d00},
127: {VK_F7, 0x4100, 0x5a00, 0x6400, 0x6e00},
128: {VK_F8, 0x4200, 0x5b00, 0x6500, 0x6f00},
129: {VK_F9, 0x4300, 0x5c00, 0x6600, 0x7000},
130: {VK_F10, 0x4400, 0x5d00, 0x6700, 0x7100},
131: {VK_F11, 0x8500, 0x8700, 0x8900, 0x8b00},
132: {VK_F12, 0x8600, 0x8800, 0x8a00, 0x8c00},
133: {0xdc, '\\', '|', 0x1c, 0x2b00},
134: {0xbf, '/', '?', 0, 0x3500},
135: {0xbd, '-', '_', 0x1f, 0x8200},
136: {0xbb, '=', '+', 0, 0x8300},
137: {0xdb, '[', '{', 0x1b, 0x1a00},
138: {0xdd, ']', '}', 0x1d, 0x1b00},
139: {0xba, ';', ':', 0, 0x2700},
140: {0xde, '\'', '"', 0, 0x2800},
141: {0xbc, ',', '<', 0, 0x3300},
142: {0xbe, '.', '>', 0, 0x3400},
143: {0xc0, '`', '~', 0, 0x2900},
144: {0, 0, 0, 0, 0} /** END **/
145: };
146:
147: static int lastch=0;
148: static int domouse=1;
149: static DWORD last_state=0;
150: static int LastX=-1, LastY=-1;
151: static int xpos=1;
152: static int ypos=1;
153:
154: static int currattr=7;
155: static int modeidx=3;
156:
157: WORD DOStoWinAttr(int newattr)
158: {
159: WORD ret=0;
160:
161: if(newattr&0x01)
162: ret|=FOREGROUND_BLUE;
163: if(newattr&0x02)
164: ret|=FOREGROUND_GREEN;
165: if(newattr&0x04)
166: ret|=FOREGROUND_RED;
167: if(newattr&0x08)
168: ret|=FOREGROUND_INTENSITY;
169: if(newattr&0x10)
170: ret|=BACKGROUND_BLUE;
171: if(newattr&0x20)
172: ret|=BACKGROUND_GREEN;
173: if(newattr&0x40)
174: ret|=BACKGROUND_RED;
175: if(newattr&0x80)
176: ret|=BACKGROUND_INTENSITY;
177: return(ret);
178: }
179:
180: unsigned char WintoDOSAttr(WORD newattr)
181: {
182: unsigned char ret=0;
183:
184: if(newattr&FOREGROUND_BLUE)
185: ret|=0x01;
186: if(newattr&FOREGROUND_GREEN)
187: ret|=0x02;
188: if(newattr&FOREGROUND_RED)
189: ret|=0x04;
190: if(newattr&FOREGROUND_INTENSITY)
191: ret|=0x08;
192: if(newattr&BACKGROUND_BLUE)
193: ret|=0x10;
194: if(newattr&BACKGROUND_GREEN)
195: ret|=0x20;
196: if(newattr&BACKGROUND_RED)
197: ret|=0x40;
198: if(newattr&BACKGROUND_INTENSITY)
199: ret|=0x80;
200: return(ret);
201: }
202:
203: int win32_getchcode(WORD code, DWORD state)
204: {
205: int i;
206:
207: for(i=0;keyval[i].Key;i++) {
208: if(keyval[i].VirtualKeyCode==code) {
209: if(state & (RIGHT_ALT_PRESSED|LEFT_ALT_PRESSED))
210: return(keyval[i].ALT);
211: if(state & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED))
212: return(keyval[i].CTRL);
213: if(state & (SHIFT_PRESSED))
214: return(keyval[i].Shift);
215: return(keyval[i].Key);
216: }
217: }
218: return(0);
219: }
220:
221: int win32_keyboardio(int isgetch)
222: {
223: INPUT_RECORD input;
224: DWORD num=0;
225:
226: while(1) {
227: if(lastch) {
228: if(isgetch) {
229: int ch;
230: ch=lastch&0xff;
231: lastch>>=8;
232: return(ch);
233: }
234: else
235: return(TRUE);
236: }
237:
238: while(1) {
239: GetNumberOfConsoleInputEvents(GetStdHandle(STD_INPUT_HANDLE), &num);
240: if(num || mouse_pending())
241: break;
242: if(isgetch)
243: SLEEP(1);
244: else
245: return(FALSE);
246: }
247:
248: if(mouse_pending()) {
249: lastch=CIO_KEY_MOUSE;
250: continue;
251: }
252:
253: if(!ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &input, 1, &num)
254: || !num || (input.EventType!=KEY_EVENT && input.EventType!=MOUSE_EVENT))
255: continue;
256:
257: switch(input.EventType) {
258: case KEY_EVENT:
259: if(input.Event.KeyEvent.bKeyDown)
260: lastch=win32_getchcode(input.Event.KeyEvent.wVirtualKeyCode, input.Event.KeyEvent.dwControlKeyState);
261: break;
262: case MOUSE_EVENT:
263: if(domouse) {
264: if(input.Event.MouseEvent.dwMousePosition.X+1 != LastX || input.Event.MouseEvent.dwMousePosition.Y+1 != LastY) {
265: LastX=input.Event.MouseEvent.dwMousePosition.X+1;
266: LastY=input.Event.MouseEvent.dwMousePosition.Y+1;
267: ciomouse_gotevent(CIOLIB_MOUSE_MOVE,LastX,LastY);
268: }
269: if(last_state != input.Event.MouseEvent.dwButtonState) {
270: switch(input.Event.MouseEvent.dwButtonState ^ last_state) {
271: case FROM_LEFT_1ST_BUTTON_PRESSED:
272: if(input.Event.MouseEvent.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED)
273: ciomouse_gotevent(CIOLIB_BUTTON_1_PRESS,input.Event.MouseEvent.dwMousePosition.X+1,input.Event.MouseEvent.dwMousePosition.Y+1);
274: else
275: ciomouse_gotevent(CIOLIB_BUTTON_1_RELEASE,input.Event.MouseEvent.dwMousePosition.X+1,input.Event.MouseEvent.dwMousePosition.Y+1);
276: break;
277: case FROM_LEFT_2ND_BUTTON_PRESSED:
278: if(input.Event.MouseEvent.dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED)
279: ciomouse_gotevent(CIOLIB_BUTTON_2_PRESS,input.Event.MouseEvent.dwMousePosition.X+1,input.Event.MouseEvent.dwMousePosition.Y+1);
280: else
281: ciomouse_gotevent(CIOLIB_BUTTON_2_RELEASE,input.Event.MouseEvent.dwMousePosition.X+1,input.Event.MouseEvent.dwMousePosition.Y+1);
282: break;
283: case RIGHTMOST_BUTTON_PRESSED:
284: if(input.Event.MouseEvent.dwButtonState & RIGHTMOST_BUTTON_PRESSED)
285: ciomouse_gotevent(CIOLIB_BUTTON_3_PRESS,input.Event.MouseEvent.dwMousePosition.X+1,input.Event.MouseEvent.dwMousePosition.Y+1);
286: else
287: ciomouse_gotevent(CIOLIB_BUTTON_3_RELEASE,input.Event.MouseEvent.dwMousePosition.X+1,input.Event.MouseEvent.dwMousePosition.Y+1);
288: break;
289: }
290: last_state=input.Event.MouseEvent.dwButtonState;
291: }
292: }
293: }
294: }
295: }
296:
297: int win32_kbhit(void)
298: {
299: return(win32_keyboardio(FALSE));
300: }
301:
302: int win32_getch(void)
303: {
304: return(win32_keyboardio(TRUE));
305: }
306:
307: int win32_getche(void)
308: {
309: int ch;
310:
311: ch=win32_getch();
312: if(ch)
313: putch(ch);
314: return(ch);
315: }
316:
317: #ifndef ENABLE_EXTENDED_FLAGS
318: #define ENABLE_INSERT_MODE 0x0020
319: #define ENABLE_QUICK_EDIT_MODE 0x0040
320: #define ENABLE_EXTENDED_FLAGS 0x0080
321: #define ENABLE_AUTO_POSITION 0x0100
322: #endif
323:
324: int win32_initciolib(long inmode)
325: {
326: DWORD conmode;
327: int i,j;
328:
329: if(!isatty(fileno(stdin)))
330: return(0);
331: if(!GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &conmode))
332: return(0);
333: conmode&=~(ENABLE_PROCESSED_INPUT|ENABLE_QUICK_EDIT_MODE);
334: conmode|=ENABLE_MOUSE_INPUT;
335: if(!SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), conmode))
336: return(0);
337:
338: if(!GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &conmode))
339: return(0);
340: conmode&=~ENABLE_PROCESSED_OUTPUT;
341: conmode&=~ENABLE_WRAP_AT_EOL_OUTPUT;
342: if(!SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), conmode))
343: return(0);
344:
345: win32_textmode(inmode);
346: cio_api.mouse=1;
347: return(1);
348: }
349:
350: int win32_hidemouse(void)
351: {
352: /* domouse=0; */
353: return(0);
354: }
355:
356: int win32_showmouse(void)
357: {
358: /* domouse=1; */
359: return(0);
360: }
361:
362: void win32_textmode(int mode)
363: {
364: int i;
365: COORD sz;
366: SMALL_RECT rc;
367:
368: for(i=0;i<NUMMODES;i++) {
369: if(vparams[i].mode==mode)
370: modeidx=i;
371: }
372: sz.X=vparams[modeidx].cols;
373: sz.Y=vparams[modeidx].rows;
374: rc.Left=0;
375: rc.Right=vparams[modeidx].cols-1;
376: rc.Top=0;
377: rc.Bottom=vparams[modeidx].rows-1;
378: SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),sz);
379: SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE),TRUE,&rc);
380: SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),sz);
381: }
382:
383: int win32_gettext(int left, int top, int right, int bottom, void* buf)
384: {
385: CHAR_INFO *ci;
386: int x;
387: int y;
388: COORD bs;
389: COORD bc;
390: SMALL_RECT reg;
391: unsigned char *bu;
392:
393: bu=buf;
394: bs.X=right-left+1;
395: bs.Y=bottom-top+1;
396: bc.X=0;
397: bc.Y=0;
398: reg.Left=left-1;
399: reg.Right=right-1;
400: reg.Top=top-1;
401: reg.Bottom=bottom-1;
402: ci=(CHAR_INFO *)malloc(sizeof(CHAR_INFO)*(bs.X*bs.Y));
403: ReadConsoleOutput(GetStdHandle(STD_OUTPUT_HANDLE),ci,bs,bc,®);
404: for(y=0;y<=(bottom-top);y++) {
405: for(x=0;x<=(right-left);x++) {
406: bu[((y*bs.X)+x)*2]=ci[(y*bs.X)+x].Char.AsciiChar;
407: bu[(((y*bs.X)+x)*2)+1]=WintoDOSAttr(ci[(y*bs.X)+x].Attributes);
408: }
409: }
410: free(ci);
411: return 1;
412: }
413:
414: void win32_gettextinfo(struct text_info* info)
415: {
416: info->currmode=vparams[modeidx].mode;
417: info->curx=xpos;
418: info->cury=ypos;
419: info->attribute=currattr;
420: info->screenheight=vparams[modeidx].rows;
421: info->screenwidth=vparams[modeidx].cols;
422: }
423:
424: void win32_gotoxy(int x, int y)
425: {
426: COORD cp;
427:
428: xpos=x;
429: ypos=y;
430: cp.X=x-1;
431: cp.Y=y-1;
432: if(!dont_move_cursor)
433: SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),cp);
434: }
435:
436: void win32_highvideo(void)
437: {
438: win32_textattr(currattr|0x08);
439: }
440:
441:
442: void win32_lowvideo(void)
443: {
444: win32_textattr(currattr&0xf8);
445: }
446:
447:
448: void win32_normvideo(void)
449: {
450: win32_textattr(7);
451: }
452:
453: int win32_puttext(int left, int top, int right, int bottom, void* buf)
454: {
455: CHAR_INFO *ci;
456: int x;
457: int y;
458: COORD bs;
459: COORD bc;
460: SMALL_RECT reg;
461: unsigned char *bu;
462:
463: bu=buf;
464: bs.X=right-left+1;
465: bs.Y=bottom-top+1;
466: bc.X=0;
467: bc.Y=0;
468: reg.Left=left-1;
469: reg.Right=right-1;
470: reg.Top=top-1;
471: reg.Bottom=bottom-1;
472: ci=(CHAR_INFO *)malloc(sizeof(CHAR_INFO)*(bs.X*bs.Y));
473: for(y=0;y<bs.Y;y++) {
474: for(x=0;x<bs.X;x++) {
475: ci[(y*bs.X)+x].Char.AsciiChar=bu[((y*bs.X)+x)*2];
476: ci[(y*bs.X)+x].Attributes=DOStoWinAttr(bu[(((y*bs.X)+x)*2)+1]);
477: }
478: }
479: WriteConsoleOutput(GetStdHandle(STD_OUTPUT_HANDLE),ci,bs,bc,®);
480: free(ci);
481: return 1;
482: }
483:
484: void win32_textattr(int newattr)
485: {
486: /* SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),DOStoWinAttr(newattr)); */
487: currattr=newattr;
488: }
489:
490:
491: void win32_textbackground(int newcolor)
492: {
493: win32_textattr((currattr&0x0f)|((newcolor&0xf0)<<4));
494: }
495:
496:
497: void win32_textcolor(int newcolor)
498: {
499: win32_textattr((currattr&0xf0)|((newcolor&0x0f)<<4));
500: }
501:
502: void win32_setcursortype(int type)
503: {
504: CONSOLE_CURSOR_INFO ci;
505:
506: switch(type) {
507: case _NOCURSOR:
508: ci.bVisible=FALSE;
509: ci.dwSize=1;
510: break;
511:
512: case _SOLIDCURSOR:
513: ci.bVisible=TRUE;
514: ci.dwSize=99;
515: break;
516:
517: default: /* Normal cursor */
518: ci.bVisible=TRUE;
519: ci.dwSize=13;
520: break;
521: }
522: SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&ci);
523: }
524:
525: int win32_wherex(void)
526: {
527: return(xpos);
528: }
529:
530: int win32_wherey(void)
531: {
532: return(ypos);
533: }
534:
535: int win32_putch(int ch)
536: {
537: struct text_info ti;
538: unsigned char buf[2];
539:
540: buf[0]=ch;
541: buf[1]=currattr;
542:
543: gettextinfo(&ti);
544: switch(ch) {
545: case '\r':
546: win32_gotoxy(1,ypos);
547: break;
548: case '\n':
549: if(ypos==ti.winbottom-ti.wintop+1)
550: wscroll();
551: else
552: win32_gotoxy(xpos,ypos+1);
553: break;
554: case '\b':
555: if(ti.curx>ti.winleft) {
556: buf[0]=' ';
557: win32_gotoxy(xpos-1,ypos);
558: puttext(xpos,ypos,xpos,ypos,buf);
559: }
560: break;
561: case 7: /* Bell */
562: MessageBeep(MB_OK);
563: break;
564: default:
565: if(ypos==ti.winbottom-ti.wintop+1
566: && xpos==ti.winright-ti.winleft+1) {
567: puttext(xpos,ypos,xpos,ypos,buf);
568: win32_gotoxy(1,ypos);
569: wscroll();
570: }
571: else {
572: if(xpos==ti.winright-ti.winleft+1) {
573: puttext(xpos,ypos,xpos,ypos,buf);
574: win32_gotoxy(1,ypos+1);
575: }
576: else {
577: puttext(xpos,ypos,xpos,ypos,buf);
578: win32_gotoxy(xpos+1,ypos);
579: }
580: }
581: break;
582: }
583: return(ch);
584: }
585:
586: void win32_settitle(const char *title)
587: {
588: SetConsoleTitle(title);
589: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.