|
|
1.1 root 1: /* $Id: win32cio.c,v 1.73 2006/05/18 06:22:51 rswindell 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 2005 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: #if defined(_WIN32)
38: #include <malloc.h> /* alloca() on Win32 */
39: #endif
40:
41: #if (defined CIOLIB_IMPORTS)
42: #undef CIOLIB_IMPORTS
43: #endif
44: #if (defined CIOLIB_EXPORTS)
45: #undef CIOLIB_EXPORTS
46: #endif
47:
48: #include "ciolib.h"
49: #include "keys.h"
50: #include "vidmodes.h"
51: #include "win32cio.h"
52:
53: const int cio_tabs[10]={9,17,25,33,41,49,57,65,73,80};
54:
55: struct keyvals {
56: int VirtualKeyCode
57: ,Key
58: ,Shift
59: ,CTRL
60: ,ALT;
61: };
62:
63: const struct keyvals keyval[] =
64: {
65: {VK_BACK, 0x08, 0x08, 0x7f, 0x0e00},
66: {VK_TAB, 0x09, 0x0f00, 0x9400, 0xa500},
67: {VK_RETURN, 0x0d, 0x0d, 0x0a, 0xa600},
68: {VK_ESCAPE, 0x1b, 0x1b, 0x1b, 0x0100},
69: {VK_SPACE, 0x20, 0x20, 0x0300, 0x20,},
70: {'0', '0', ')', 0, 0x8100},
71: {'1', '1', '!', 0, 0x7800},
72: {'2', '2', '@', 0x0300, 0x7900},
73: {'3', '3', '#', 0, 0x7a00},
74: {'4', '4', '$', 0, 0x7b00},
75: {'5', '5', '%', 0, 0x7c00},
76: {'6', '6', '^', 0x1e, 0x7d00},
77: {'7', '7', '&', 0, 0x7e00},
78: {'8', '8', '*', 0, 0x7f00},
79: {'9', '9', '(', 0, 0x8000},
80: {'A', 'a', 'A', 0x01, 0x1e00},
81: {'B', 'b', 'B', 0x02, 0x3000},
82: {'C', 'c', 'C', 0x03, 0x2e00},
83: {'D', 'd', 'D', 0x04, 0x2000},
84: {'E', 'e', 'E', 0x05, 0x1200},
85: {'F', 'f', 'F', 0x06, 0x2100},
86: {'G', 'g', 'G', 0x07, 0x2200},
87: {'H', 'h', 'H', 0x08, 0x2300},
88: {'I', 'i', 'I', 0x09, 0x1700},
89: {'J', 'j', 'J', 0x0a, 0x2400},
90: {'K', 'k', 'K', 0x0b, 0x2500},
91: {'L', 'l', 'L', 0x0c, 0x2600},
92: {'M', 'm', 'M', 0x0d, 0x3200},
93: {'N', 'n', 'N', 0x0e, 0x3100},
94: {'O', 'o', 'O', 0x0f, 0x1800},
95: {'P', 'p', 'P', 0x10, 0x1900},
96: {'Q', 'q', 'Q', 0x11, 0x1000},
97: {'R', 'r', 'R', 0x12, 0x1300},
98: {'S', 's', 'S', 0x13, 0x1f00},
99: {'T', 't', 'T', 0x14, 0x1400},
100: {'U', 'u', 'U', 0x15, 0x1600},
101: {'V', 'v', 'V', 0x16, 0x2f00},
102: {'W', 'w', 'W', 0x17, 0x1100},
103: {'X', 'x', 'X', 0x18, 0x2d00},
104: {'Y', 'y', 'Y', 0x19, 0x1500},
105: {'Z', 'z', 'Z', 0x1a, 0x2c00},
106: {VK_PRIOR, 0x4900, 0x4900, 0x8400, 0x9900},
107: {VK_NEXT, 0x5100, 0x5100, 0x7600, 0xa100},
108: {VK_END, 0x4f00, 0x4f00, 0x7500, 0x9f00},
109: {VK_HOME, 0x4700, 0x4700, 0x7700, 0x9700},
110: {VK_LEFT, 0x4b00, 0x4b00, 0x7300, 0x9b00},
111: {VK_UP, 0x4800, 0x4800, 0x8d00, 0x9800},
112: {VK_RIGHT, 0x4d00, 0x4d00, 0x7400, 0x9d00},
113: {VK_DOWN, 0x5000, 0x5000, 0x9100, 0xa000},
114: {VK_INSERT, 0x5200, 0x5200, 0x9200, 0xa200},
115: {VK_DELETE, 0x5300, 0x5300, 0x9300, 0xa300},
116: {VK_NUMPAD0, '0', 0x5200, 0x9200, 0},
117: {VK_NUMPAD1, '1', 0x4f00, 0x7500, 0},
118: {VK_NUMPAD2, '2', 0x5000, 0x9100, 0},
119: {VK_NUMPAD3, '3', 0x5100, 0x7600, 0},
120: {VK_NUMPAD4, '4', 0x4b00, 0x7300, 0},
121: {VK_NUMPAD5, '5', 0x4c00, 0x8f00, 0},
122: {VK_NUMPAD6, '6', 0x4d00, 0x7400, 0},
123: {VK_NUMPAD7, '7', 0x4700, 0x7700, 0},
124: {VK_NUMPAD8, '8', 0x4800, 0x8d00, 0},
125: {VK_NUMPAD9, '9', 0x4900, 0x8400, 0},
126: {VK_MULTIPLY, '*', '*', 0x9600, 0x3700},
127: {VK_ADD, '+', '+', 0x9000, 0x4e00},
128: {VK_SUBTRACT, '-', '-', 0x8e00, 0x4a00},
129: {VK_DECIMAL, '.', '.', 0x5300, 0x9300},
130: {VK_DIVIDE, '/', '/', 0x9500, 0xa400},
131: {VK_F1, 0x3b00, 0x5400, 0x5e00, 0x6800},
132: {VK_F2, 0x3c00, 0x5500, 0x5f00, 0x6900},
133: {VK_F3, 0x3d00, 0x5600, 0x6000, 0x6a00},
134: {VK_F4, 0x3e00, 0x5700, 0x6100, 0x6b00},
135: {VK_F5, 0x3f00, 0x5800, 0x6200, 0x6c00},
136: {VK_F6, 0x4000, 0x5900, 0x6300, 0x6d00},
137: {VK_F7, 0x4100, 0x5a00, 0x6400, 0x6e00},
138: {VK_F8, 0x4200, 0x5b00, 0x6500, 0x6f00},
139: {VK_F9, 0x4300, 0x5c00, 0x6600, 0x7000},
140: {VK_F10, 0x4400, 0x5d00, 0x6700, 0x7100},
141: {VK_F11, 0x8500, 0x8700, 0x8900, 0x8b00},
142: {VK_F12, 0x8600, 0x8800, 0x8a00, 0x8c00},
143: {0xdc, '\\', '|', 0x1c, 0x2b00},
144: {0xbf, '/', '?', 0, 0x3500},
145: {0xbd, '-', '_', 0x1f, 0x8200},
146: {0xbb, '=', '+', 0, 0x8300},
147: {0xdb, '[', '{', 0x1b, 0x1a00},
148: {0xdd, ']', '}', 0x1d, 0x1b00},
149: {0xba, ';', ':', 0, 0x2700},
150: {0xde, '\'', '"', 0, 0x2800},
151: {0xbc, ',', '<', 0, 0x3300},
152: {0xbe, '.', '>', 0, 0x3400},
153: {0xc0, '`', '~', 0, 0x2900},
154: {0, 0, 0, 0, 0} /** END **/
155: };
156:
157: static int domouse=1;
158: static DWORD last_state=0;
159: static int LastX=-1, LastY=-1;
160: static int xpos=1;
161: static int ypos=1;
162:
163: static int currattr=7;
164: static int modeidx=3;
165:
166: #if defined(_DEBUG)
167: static void dputs(const char* str)
168: {
169: char msg[1024];
170:
171: SAFEPRINTF(msg,"%s\r\n",str);
172: OutputDebugString(msg);
173: }
174: #endif
175:
176: static void dprintf(const char* fmt, ...)
177: {
178: #if defined(_DEBUG)
179: va_list argptr;
180: char sbuf[1024];
181:
182: va_start(argptr,fmt);
183: vsnprintf(sbuf,sizeof(sbuf),fmt,argptr);
184: sbuf[sizeof(sbuf)-1]=0;
185: va_end(argptr);
186: dputs(sbuf);
187: #endif /* _DEBUG */
188: }
189:
190: WORD DOStoWinAttr(int newattr)
191: {
192: WORD ret=0;
193:
194: if(newattr&0x01)
195: ret|=FOREGROUND_BLUE;
196: if(newattr&0x02)
197: ret|=FOREGROUND_GREEN;
198: if(newattr&0x04)
199: ret|=FOREGROUND_RED;
200: if(newattr&0x08)
201: ret|=FOREGROUND_INTENSITY;
202: if(newattr&0x10)
203: ret|=BACKGROUND_BLUE;
204: if(newattr&0x20)
205: ret|=BACKGROUND_GREEN;
206: if(newattr&0x40)
207: ret|=BACKGROUND_RED;
208: if(newattr&0x80)
209: ret|=BACKGROUND_INTENSITY;
210: return(ret);
211: }
212:
213: unsigned char WintoDOSAttr(WORD newattr)
214: {
215: unsigned char ret=0;
216:
217: if(newattr&FOREGROUND_BLUE)
218: ret|=0x01;
219: if(newattr&FOREGROUND_GREEN)
220: ret|=0x02;
221: if(newattr&FOREGROUND_RED)
222: ret|=0x04;
223: if(newattr&FOREGROUND_INTENSITY)
224: ret|=0x08;
225: if(newattr&BACKGROUND_BLUE)
226: ret|=0x10;
227: if(newattr&BACKGROUND_GREEN)
228: ret|=0x20;
229: if(newattr&BACKGROUND_RED)
230: ret|=0x40;
231: if(newattr&BACKGROUND_INTENSITY)
232: ret|=0x80;
233: return(ret);
234: }
235:
236: int win32_getchcode(WORD code, DWORD state)
237: {
238: int i;
239:
240: for(i=0;keyval[i].Key;i++) {
241: if(keyval[i].VirtualKeyCode==code) {
242: if(state & (RIGHT_ALT_PRESSED|LEFT_ALT_PRESSED))
243: return(keyval[i].ALT);
244: if(state & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED))
245: return(keyval[i].CTRL);
246: if((state & (CAPSLOCK_ON)) && isalpha(keyval[i].Key)) {
247: if(!(state & SHIFT_PRESSED))
248: return(keyval[i].Shift);
249: }
250: else {
251: if(state & (SHIFT_PRESSED))
252: return(keyval[i].Shift);
253: }
254: return(keyval[i].Key);
255: }
256: }
257: return(0);
258: }
259:
260: int win32_keyboardio(int isgetch)
261: {
262: INPUT_RECORD input;
263: DWORD num=0;
264: HANDLE h;
265: static WORD lastch;
266:
267: if((h=GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE)
268: return(0);
269:
270: while(1) {
271: if(lastch) {
272: if(isgetch) {
273: BYTE ch;
274: ch=lastch&0xff;
275: lastch>>=8;
276: return(ch);
277: }
278: else
279: return(TRUE);
280: }
281:
282: while(1) {
283: GetNumberOfConsoleInputEvents(h, &num);
284: if(num)
285: break;
286: if(mouse_trywait()) {
287: lastch=CIO_KEY_MOUSE;
288: break;
289: }
290: if(isgetch)
291: SLEEP(1);
292: else
293: return(FALSE);
294: }
295:
296: if(lastch)
297: continue;
298:
299: if(!ReadConsoleInput(h, &input, 1, &num)
300: || !num || (input.EventType!=KEY_EVENT && input.EventType!=MOUSE_EVENT))
301: continue;
302:
303: switch(input.EventType) {
304: case KEY_EVENT:
305:
306: dprintf("KEY_EVENT: KeyDown=%u"
307: ,input.Event.KeyEvent.bKeyDown);
308: dprintf(" RepeatCount=%u"
309: ,input.Event.KeyEvent.wRepeatCount);
310: dprintf(" VirtualKeyCode=0x%04hX"
311: ,input.Event.KeyEvent.wVirtualKeyCode);
312: dprintf(" VirtualScanCode=0x%04hX"
313: ,input.Event.KeyEvent.wVirtualScanCode);
314: dprintf(" uChar.AsciiChar=0x%02X (%u)"
315: ,(BYTE)input.Event.KeyEvent.uChar.AsciiChar
316: ,(BYTE)input.Event.KeyEvent.uChar.AsciiChar);
317: dprintf(" ControlKeyState=0x%08lX"
318: ,input.Event.KeyEvent.dwControlKeyState);
319:
320: if(input.Event.KeyEvent.bKeyDown) {
321: /* Is this an AltGr key? */
322: if(((input.Event.KeyEvent.dwControlKeyState & (RIGHT_ALT_PRESSED|LEFT_CTRL_PRESSED)) == (RIGHT_ALT_PRESSED|LEFT_CTRL_PRESSED))
323: && (BYTE)input.Event.KeyEvent.uChar.AsciiChar) {
324: lastch=(BYTE)input.Event.KeyEvent.uChar.AsciiChar;
325: }
326: /* Is this a modified char? */
327: else if((input.Event.KeyEvent.dwControlKeyState & (RIGHT_ALT_PRESSED|LEFT_ALT_PRESSED|RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED|ENHANCED_KEY))
328: || (input.Event.KeyEvent.wVirtualKeyCode >= VK_F1 && input.Event.KeyEvent.wVirtualKeyCode <= VK_F24)
329: || !input.Event.KeyEvent.uChar.AsciiChar) {
330: lastch=win32_getchcode(input.Event.KeyEvent.wVirtualKeyCode, input.Event.KeyEvent.dwControlKeyState);
331: }
332: /* Must be a normal char then! */
333: else {
334: lastch=(BYTE)input.Event.KeyEvent.uChar.AsciiChar;
335: }
336: } else if(input.Event.KeyEvent.wVirtualKeyCode == VK_MENU)
337: lastch=(BYTE)input.Event.KeyEvent.uChar.AsciiChar;
338:
339: break;
340: case MOUSE_EVENT:
341: if(domouse) {
342: if(input.Event.MouseEvent.dwMousePosition.X+1 != LastX || input.Event.MouseEvent.dwMousePosition.Y+1 != LastY) {
343: LastX=input.Event.MouseEvent.dwMousePosition.X+1;
344: LastY=input.Event.MouseEvent.dwMousePosition.Y+1;
345: ciomouse_gotevent(CIOLIB_MOUSE_MOVE,LastX,LastY);
346: }
347: if(last_state != input.Event.MouseEvent.dwButtonState) {
348: switch(input.Event.MouseEvent.dwButtonState ^ last_state) {
349: case FROM_LEFT_1ST_BUTTON_PRESSED:
350: if(input.Event.MouseEvent.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED)
351: ciomouse_gotevent(CIOLIB_BUTTON_1_PRESS,input.Event.MouseEvent.dwMousePosition.X+1,input.Event.MouseEvent.dwMousePosition.Y+1);
352: else
353: ciomouse_gotevent(CIOLIB_BUTTON_1_RELEASE,input.Event.MouseEvent.dwMousePosition.X+1,input.Event.MouseEvent.dwMousePosition.Y+1);
354: break;
355: case FROM_LEFT_2ND_BUTTON_PRESSED:
356: if(input.Event.MouseEvent.dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED)
357: ciomouse_gotevent(CIOLIB_BUTTON_2_PRESS,input.Event.MouseEvent.dwMousePosition.X+1,input.Event.MouseEvent.dwMousePosition.Y+1);
358: else
359: ciomouse_gotevent(CIOLIB_BUTTON_2_RELEASE,input.Event.MouseEvent.dwMousePosition.X+1,input.Event.MouseEvent.dwMousePosition.Y+1);
360: break;
361: case RIGHTMOST_BUTTON_PRESSED:
362: if(input.Event.MouseEvent.dwButtonState & RIGHTMOST_BUTTON_PRESSED)
363: ciomouse_gotevent(CIOLIB_BUTTON_3_PRESS,input.Event.MouseEvent.dwMousePosition.X+1,input.Event.MouseEvent.dwMousePosition.Y+1);
364: else
365: ciomouse_gotevent(CIOLIB_BUTTON_3_RELEASE,input.Event.MouseEvent.dwMousePosition.X+1,input.Event.MouseEvent.dwMousePosition.Y+1);
366: break;
367: }
368: last_state=input.Event.MouseEvent.dwButtonState;
369: }
370: }
371: }
372: }
373: }
374:
375: int win32_kbhit(void)
376: {
377: return(win32_keyboardio(FALSE));
378: }
379:
380: int win32_getch(void)
381: {
382: int ret=win32_keyboardio(TRUE);
383: dprintf("win32_getch = 0x%02X (%u)", (BYTE)ret, (BYTE)ret);
384: return(ret);
385: }
386:
387: int win32_getche(void)
388: {
389: int ch;
390:
391: ch=win32_getch();
392: if(ch)
393: putch(ch);
394: return(ch);
395: }
396:
397: #ifndef ENABLE_EXTENDED_FLAGS
398: #define ENABLE_INSERT_MODE 0x0020
399: #define ENABLE_QUICK_EDIT_MODE 0x0040
400: #define ENABLE_EXTENDED_FLAGS 0x0080
401: #define ENABLE_AUTO_POSITION 0x0100
402: #endif
403:
404: static DWORD orig_in_conmode=0;
405: static DWORD orig_out_conmode=0;
406: static void * win32_suspendbuf=NULL;
407:
408: void win32_suspend(void)
409: {
410: HANDLE h;
411:
412: if((h=GetStdHandle(STD_INPUT_HANDLE)) != INVALID_HANDLE_VALUE)
413: SetConsoleMode(h, orig_in_conmode);
414: if((h=GetStdHandle(STD_OUTPUT_HANDLE)) != INVALID_HANDLE_VALUE)
415: SetConsoleMode(h, orig_out_conmode);
416: }
417:
418: void win32_resume(void)
419: {
420: DWORD conmode;
421: HANDLE h;
422:
423: conmode=orig_in_conmode;
424: conmode&=~(ENABLE_PROCESSED_INPUT|ENABLE_QUICK_EDIT_MODE);
425: conmode|=ENABLE_MOUSE_INPUT;
426: if((h=GetStdHandle(STD_INPUT_HANDLE)) != INVALID_HANDLE_VALUE)
427: SetConsoleMode(h, conmode);
428:
429: conmode=orig_out_conmode;
430: conmode&=~ENABLE_PROCESSED_OUTPUT;
431: conmode&=~ENABLE_WRAP_AT_EOL_OUTPUT;
432: if((h=GetStdHandle(STD_OUTPUT_HANDLE)) != INVALID_HANDLE_VALUE)
433: SetConsoleMode(h, conmode);
434: }
435:
436: int win32_initciolib(long inmode)
437: {
438: DWORD conmode;
439: int i,j;
440: HANDLE h;
441: CONSOLE_SCREEN_BUFFER_INFO sbuff;
442:
443: if(!isatty(fileno(stdin))) {
444: if(!AllocConsole())
445: return(0);
446: }
447:
448: if((h=GetStdHandle(STD_INPUT_HANDLE))==INVALID_HANDLE_VALUE
449: || !GetConsoleMode(h, &orig_in_conmode))
450: return(0);
451: conmode=orig_in_conmode;
452: conmode&=~(ENABLE_PROCESSED_INPUT|ENABLE_QUICK_EDIT_MODE);
453: conmode|=ENABLE_MOUSE_INPUT;
454: if(!SetConsoleMode(h, conmode))
455: return(0);
456:
457: if((h=GetStdHandle(STD_OUTPUT_HANDLE))==INVALID_HANDLE_VALUE
458: || !GetConsoleMode(h, &orig_out_conmode))
459: return(0);
460: conmode=orig_out_conmode;
461: conmode&=~ENABLE_PROCESSED_OUTPUT;
462: conmode&=~ENABLE_WRAP_AT_EOL_OUTPUT;
463: if(!SetConsoleMode(h, conmode))
464: return(0);
465:
466: if(GetConsoleScreenBufferInfo(h, &sbuff)==0) {
467: win32_textmode(C80);
468: }
469: else {
470: /* Switch to closest mode to current screen size */
471: i=sbuff.srWindow.Right-sbuff.srWindow.Left+1;
472: j=sbuff.srWindow.Bottom-sbuff.srWindow.Top+1;
473: if(i>=80) {
474: if(j<21)
475: win32_textmode(C80X14);
476: else if(j<25)
477: win32_textmode(C80X21);
478: else if(j<28)
479: win32_textmode(C80);
480: else if(j<43)
481: win32_textmode(C80X28);
482: else if(j<50)
483: win32_textmode(C80X43);
484: else if(j<60)
485: win32_textmode(C80X50);
486: else
487: win32_textmode(C80X60);
488: }
489: else {
490: if(j<21)
491: win32_textmode(C40X14);
492: else if(j<25)
493: win32_textmode(C40X21);
494: else if(j<28)
495: win32_textmode(C40);
496: else if(j<43)
497: win32_textmode(C40X28);
498: else if(j<50)
499: win32_textmode(C40X43);
500: else if(j<60)
501: win32_textmode(C40X50);
502: else
503: win32_textmode(C40X60);
504: }
505: }
506:
507: cio_api.mouse=1;
508: return(1);
509: }
510:
511: int win32_hidemouse(void)
512: {
513: /* domouse=0; */
514: return(0);
515: }
516:
517: int win32_showmouse(void)
518: {
519: /* domouse=1; */
520: return(0);
521: }
522:
523: void win32_textmode(int mode)
524: {
525: int i;
526: HANDLE h;
527: COORD sz;
528: SMALL_RECT rc;
529:
530: for(i=0;i<NUMMODES;i++) {
531: if(vparams[i].mode==mode)
532: modeidx=i;
533: }
534: sz.X=vparams[modeidx].cols;
535: sz.Y=vparams[modeidx].rows;
536: rc.Left=0;
537: rc.Right=vparams[modeidx].cols-1;
538: rc.Top=0;
539: rc.Bottom=vparams[modeidx].rows-1;
540:
541: if((h=GetStdHandle(STD_OUTPUT_HANDLE)) != INVALID_HANDLE_VALUE) {
542: SetConsoleScreenBufferSize(h,sz);
543: SetConsoleWindowInfo(h,TRUE,&rc);
544: SetConsoleScreenBufferSize(h,sz);
545: }
546: }
547:
548: int win32_gettext(int left, int top, int right, int bottom, void* buf)
549: {
550: CHAR_INFO *ci;
551: int x;
552: int y;
553: COORD bs;
554: COORD bc;
555: HANDLE h;
556: SMALL_RECT reg;
557: unsigned char *bu;
558:
559: bu=buf;
560: bs.X=right-left+1;
561: bs.Y=bottom-top+1;
562: bc.X=0;
563: bc.Y=0;
564: reg.Left=left-1;
565: reg.Right=right-1;
566: reg.Top=top-1;
567: reg.Bottom=bottom-1;
568: ci=(CHAR_INFO *)alloca(sizeof(CHAR_INFO)*(bs.X*bs.Y));
569: if((h=GetStdHandle(STD_OUTPUT_HANDLE)) != INVALID_HANDLE_VALUE)
570: ReadConsoleOutput(h,ci,bs,bc,®);
571: for(y=0;y<=(bottom-top);y++) {
572: for(x=0;x<=(right-left);x++) {
573: bu[((y*bs.X)+x)*2]=ci[(y*bs.X)+x].Char.AsciiChar;
574: bu[(((y*bs.X)+x)*2)+1]=WintoDOSAttr(ci[(y*bs.X)+x].Attributes);
575: }
576: }
577: return 1;
578: }
579:
580: void win32_gettextinfo(struct text_info* info)
581: {
582: info->currmode=vparams[modeidx].mode;
583: info->curx=xpos;
584: info->cury=ypos;
585: info->attribute=currattr;
586: info->screenheight=vparams[modeidx].rows;
587: info->screenwidth=vparams[modeidx].cols;
588: }
589:
590: void win32_gotoxy(int x, int y)
591: {
592: COORD cp;
593: HANDLE h;
594:
595: xpos=x;
596: ypos=y;
597: cp.X=x-1;
598: cp.Y=y-1;
599: if(!hold_update && (h=GetStdHandle(STD_OUTPUT_HANDLE)) != INVALID_HANDLE_VALUE)
600: SetConsoleCursorPosition(h,cp);
601: }
602:
603: void win32_highvideo(void)
604: {
605: win32_textattr(currattr|0x08);
606: }
607:
608:
609: void win32_lowvideo(void)
610: {
611: win32_textattr(currattr&0xf8);
612: }
613:
614:
615: void win32_normvideo(void)
616: {
617: win32_textattr(7);
618: }
619:
620: int win32_puttext(int left, int top, int right, int bottom, void* buf)
621: {
622: CHAR_INFO *ci;
623: int x;
624: int y;
625: HANDLE h;
626: COORD bs;
627: COORD bc;
628: SMALL_RECT reg;
629: unsigned char *bu;
630:
631: bu=buf;
632: bs.X=right-left+1;
633: bs.Y=bottom-top+1;
634: bc.X=0;
635: bc.Y=0;
636: reg.Left=left-1;
637: reg.Right=right-1;
638: reg.Top=top-1;
639: reg.Bottom=bottom-1;
640: ci=(CHAR_INFO *)alloca(sizeof(CHAR_INFO)*(bs.X*bs.Y));
641: for(y=0;y<bs.Y;y++) {
642: for(x=0;x<bs.X;x++) {
643: ci[(y*bs.X)+x].Char.AsciiChar=bu[((y*bs.X)+x)*2];
644: ci[(y*bs.X)+x].Attributes=DOStoWinAttr(bu[(((y*bs.X)+x)*2)+1]);
645: }
646: }
647: if((h=GetStdHandle(STD_OUTPUT_HANDLE)) != INVALID_HANDLE_VALUE)
648: WriteConsoleOutput(h,ci,bs,bc,®);
649: return 1;
650: }
651:
652: void win32_textattr(int newattr)
653: {
654: /* SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),DOStoWinAttr(newattr)); */
655: currattr=newattr;
656: }
657:
658:
659: void win32_textbackground(int newcolor)
660: {
661: win32_textattr((currattr&0x0f)|((newcolor&0xf0)<<4));
662: }
663:
664:
665: void win32_textcolor(int newcolor)
666: {
667: win32_textattr((currattr&0xf0)|((newcolor&0x0f)<<4));
668: }
669:
670: void win32_setcursortype(int type)
671: {
672: HANDLE h;
673: CONSOLE_CURSOR_INFO ci;
674:
675: switch(type) {
676: case _NOCURSOR:
677: ci.bVisible=FALSE;
678: ci.dwSize=1;
679: break;
680:
681: case _SOLIDCURSOR:
682: ci.bVisible=TRUE;
683: ci.dwSize=99;
684: break;
685:
686: default: /* Normal cursor */
687: ci.bVisible=TRUE;
688: ci.dwSize=13;
689: break;
690: }
691: if((h=GetStdHandle(STD_OUTPUT_HANDLE)) != INVALID_HANDLE_VALUE)
692: SetConsoleCursorInfo(h,&ci);
693: }
694:
695: int win32_wherex(void)
696: {
697: return(xpos);
698: }
699:
700: int win32_wherey(void)
701: {
702: return(ypos);
703: }
704:
705: int win32_putch(int ch)
706: {
707: struct text_info ti;
708: unsigned char buf[2];
709: int i;
710:
711: buf[0]=ch;
712: buf[1]=currattr;
713:
714: switch(ch) {
715: case '\r':
716: gotoxy(1,wherey());
717: break;
718: case '\n':
719: gettextinfo(&ti);
720: if(ti.cury==ti.winbottom-ti.wintop+1)
721: wscroll();
722: else
723: gotoxy(ti.curx,ti.cury+1);
724: break;
725: case '\b':
726: gettextinfo(&ti);
727: if(ti.curx>1) {
728: buf[0]=' ';
729: gotoxy(ti.curx-1,ti.cury);
730: puttext(ti.winleft+ti.curx-2, ti.wintop+ti.cury-1,ti.winleft+ti.curx-2, ti.wintop+ti.cury-1,buf);
731: }
732: break;
733: case 7: /* Bell */
734: MessageBeep(MB_OK);
735: break;
736: case '\t':
737: for(i=0;i<10;i++) {
738: if(cio_tabs[i]>wherex()) {
739: while(wherex()<cio_tabs[i]) {
740: putch(' ');
741: }
742: break;
743: }
744: }
745: if(i==10) {
746: putch('\r');
747: putch('\n');
748: }
749: break;
750: default:
751: gettextinfo(&ti);
752: if(ti.cury==ti.winbottom-ti.wintop+1
753: && ti.curx==ti.winright-ti.winleft+1) {
754: puttext(ti.winleft+ti.curx-1, ti.wintop+ti.cury-1,ti.winleft+ti.curx-1, ti.wintop+ti.cury-1,buf);
755: wscroll();
756: gotoxy(1,ti.cury);
757: }
758: else {
759: if(ti.curx==ti.winright-ti.winleft+1) {
760: puttext(ti.winleft+ti.curx-1, ti.wintop+ti.cury-1,ti.winleft+ti.curx-1, ti.wintop+ti.cury-1,buf);
761: gotoxy(1,ti.cury+1);
762: }
763: else {
764: puttext(ti.winleft+ti.curx-1, ti.wintop+ti.cury-1,ti.winleft+ti.curx-1, ti.wintop+ti.cury-1,buf);
765: gotoxy(ti.curx+1,ti.cury);
766: }
767: }
768: break;
769: }
770: return(ch);
771: }
772:
773: void win32_settitle(const char *title)
774: {
775: SetConsoleTitle(title);
776: }
777:
778: void win32_copytext(const char *text, size_t buflen)
779: {
780: HGLOBAL clipbuf;
781: LPTSTR clip;
782:
783: if(!OpenClipboard(NULL))
784: return;
785: EmptyClipboard();
786: clipbuf=GlobalAlloc(GMEM_MOVEABLE, buflen+1);
787: if(clipbuf==NULL) {
788: CloseClipboard();
789: return;
790: }
791: clip=GlobalLock(clipbuf);
792: memcpy(clip, text, buflen);
793: clip[buflen]=0;
794: GlobalUnlock(clipbuf);
795: SetClipboardData(CF_OEMTEXT, clipbuf);
796: CloseClipboard();
797: }
798:
799: char *win32_getcliptext(void)
800: {
801: HGLOBAL clipbuf;
802: LPTSTR clip;
803: char *ret;
804:
805: if(!IsClipboardFormatAvailable(CF_OEMTEXT))
806: return(NULL);
807: if(!OpenClipboard(NULL))
808: return(NULL);
809: clipbuf=GetClipboardData(CF_OEMTEXT);
810: if(clipbuf!=NULL) {
811: clip=GlobalLock(clipbuf);
812: ret=(char *)malloc(strlen(clip)+1);
813: if(ret != NULL)
814: strcpy(ret, clip);
815: GlobalUnlock(clipbuf);
816: }
817: CloseClipboard();
818:
819: return(ret);
820: }
821:
822: void win32_delay(long msec)
823: {
824: SLEEP(msec);
825: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.