source: trunk/src/kernel32/conbuffer.cpp@ 297

Last change on this file since 297 was 297, checked in by phaller, 26 years ago

Fix: Console buffer fixes.

File size: 109.7 KB
Line 
1/* $Id: conbuffer.cpp,v 1.4 1999-07-12 17:45:50 phaller Exp $ */
2
3/*
4 * Win32 Console API Translation for OS/2
5 *
6 * 1998/02/10 Patrick Haller (haller@zebra.fh-weingarten.de)
7 *
8 * @(#) console.cpp 1.0.0 1998/02/10 PH Start from scratch
9 *
10 * Project Odin Software License can be found in LICENSE.TXT
11 *
12 */
13
14
15#ifdef DEBUG
16#define DEBUG_LOCAL
17#define DEBUG_LOCAL2
18#endif
19
20#undef DEBUG_LOCAL
21#undef DEBUG_LOCAL2
22
23
24/*****************************************************************************
25 * Remark *
26 *****************************************************************************
27
28 - DWORD HandlerRoutine (DWORD dwCtrlType)
29 basically an exception handler routine. handles a few signals / excpts.
30 should be somewhere near the exception handling code ... :)
31
32 Hmm, however as PM applications don't really get a ctrl-c signal,
33 I'll have to do this on my own ...
34
35 - supply unicode<->ascii conversions for all the _A and _W function pairs.
36
37 - problem: we can't prevent thread1 from blocking the message queue ?
38 what will happen if a WinTerminate() is issued there ?
39 will the message queue be closed and provide smooth tasking ?
40 how will open32 react on this ?
41
42 - ECHO_LINE_INPUT / ReadFile blocks till CR
43
44 - scrollbars
45 * do some flowchart to exactly determine WHEN to use WHICH setting
46 and perform WHAT action
47
48 - clipboard support
49*/
50
51
52/*****************************************************************************
53 * Includes *
54 *****************************************************************************/
55
56#define INCL_WIN
57#define INCL_DOSMEMMGR
58#define INCL_DOSSEMAPHORES
59#define INCL_DOSERRORS
60#define INCL_DOSPROCESS
61#define INCL_DOSMODULEMGR
62#define INCL_VIO
63#define INCL_AVIO
64#include <os2wrap.h> //Odin32 OS/2 api wrappers
65
66#include <misc.h>
67#include <string.h>
68#include <stdlib.h>
69
70#include "conwin.h" // Windows Header for console only
71#include "HandleManager.h"
72#include "HMDevice.h"
73#include "ConBuffer.H"
74#include "Console2.h"
75
76
77/***********************************
78 * Open32 support for SetLastError *
79 ***********************************/
80#include <os2sel.h>
81
82extern "C"
83{
84 void _System _O32_SetLastError(DWORD dwError);
85}
86
87inline void SetLastError(DWORD a)
88{
89 USHORT sel = GetFS();
90
91 _O32_SetLastError(a);
92 SetFS(sel);
93}
94
95
96/*****************************************************************************
97 * Name : DWORD HMDeviceConsoleBufferClass::CreateFile
98 * Purpose : this is called from the handle manager if a CreateFile() is
99 * performed on a handle
100 * Parameters: LPCSTR lpFileName name of the file / device
101 * PHMHANDLEDATA pHMHandleData data of the NEW handle
102 * PVOID lpSecurityAttributes ignored
103 * PHMHANDLEDATA pHMHandleDataTemplate data of the template handle
104 * Variables :
105 * Result :
106 * Remark :
107 * Status : NO_ERROR - API succeeded
108 * other - what is to be set in SetLastError
109 *
110 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
111 *****************************************************************************/
112
113DWORD HMDeviceConsoleBufferClass::CreateFile (LPCSTR lpFileName,
114 PHMHANDLEDATA pHMHandleData,
115 PVOID lpSecurityAttributes,
116 PHMHANDLEDATA pHMHandleDataTemplate)
117{
118 PCONSOLEBUFFER pConsoleBuffer; /* console buffer structure */
119
120#ifdef DEBUG_LOCAL
121 WriteLog("KERNEL32/CONSOLE:HMDeviceConsoleBufferClass %s(%s,%08x,%08x,%08x)\n",
122 lpHMDeviceName,
123 lpFileName,
124 pHMHandleData->hHMHandle,
125 lpSecurityAttributes,
126 pHMHandleDataTemplate);
127#endif
128
129 pHMHandleData->dwType = FILE_TYPE_CHAR; /* we're a character device */
130
131 pHMHandleData->lpHandlerData = malloc ( sizeof(CONSOLEBUFFER) );
132
133#ifdef DEBUG_LOCAL
134 WriteLog("KERNEL32/CONSOLE:CheckPoint1: %s pHMHandleData=%08xh, lpHandlerData=%08xh\n",
135 lpFileName,
136 pHMHandleData,
137 pHMHandleData->lpHandlerData);
138#endif
139
140
141 if (pHMHandleData->lpHandlerData == NULL) /* check allocation */
142 {
143 SetLastError(ERROR_NOT_ENOUGH_MEMORY); /* set error information */
144 return (INVALID_HANDLE_VALUE); /* raise error condition */
145 }
146 else
147 {
148 pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
149
150 memset(pHMHandleData->lpHandlerData, /* initialize structure */
151 0,
152 sizeof (CONSOLEBUFFER) );
153
154 /* set buffer defaults */
155 pConsoleBuffer->dwConsoleMode = ENABLE_PROCESSED_OUTPUT |
156 ENABLE_WRAP_AT_EOL_OUTPUT;
157
158 pConsoleBuffer->CursorInfo.dwSize = 2; /* 2 scanlines */
159 pConsoleBuffer->CursorInfo.bVisible = TRUE;
160 }
161
162 return(NO_ERROR);
163}
164
165
166/*****************************************************************************
167 * Name :
168 * Purpose :
169 * Parameters:
170 * Variables :
171 * Result :
172 * Remark :
173 * Status :
174 *
175 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
176 *****************************************************************************/
177
178DWORD HMDeviceConsoleBufferClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
179{
180
181#ifdef DEBUG_LOCAL
182 WriteLog("KERNEL32/CONSOLE:HMDeviceConsoleBufferClass::CloseHandle %s(%08x)\n",
183 lpHMDeviceName,
184 pHMHandleData);
185#endif
186
187 if (pHMHandleData->lpHandlerData != NULL) /* check pointer */
188 {
189 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
190
191
192 if (pConsoleBuffer->ppszLine != NULL) /* free line buffer array ! */
193 free (pConsoleBuffer->ppszLine);
194
195 free (pHMHandleData->lpHandlerData); /* free device object data */
196 pHMHandleData->lpHandlerData = NULL;
197 }
198
199 return(NO_ERROR);
200}
201
202
203/*****************************************************************************
204 * Name :
205 * Purpose :
206 * Parameters:
207 * Variables :
208 * Result :
209 * Remark :
210 * Status :
211 *
212 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
213 *****************************************************************************/
214
215DWORD HMDeviceConsoleBufferClass::ReadFile(PHMHANDLEDATA pHMHandleData,
216 LPCVOID lpBuffer,
217 DWORD nNumberOfBytesToRead,
218 LPDWORD lpNumberOfBytesRead,
219 LPOVERLAPPED lpOverlapped)
220{
221
222#ifdef DEBUG_LOCAL
223 WriteLog("KERNEL32/CONSOLE:HMDeviceConsoleBufferClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x)\n",
224 lpHMDeviceName,
225 pHMHandleData->hHMHandle,
226 lpBuffer,
227 nNumberOfBytesToRead,
228 lpNumberOfBytesRead,
229 lpOverlapped);
230#endif
231
232 return(ERROR_ACCESS_DENIED);
233}
234
235
236/*****************************************************************************
237 * Name :
238 * Purpose :
239 * Parameters:
240 * Variables :
241 * Result :
242 * Remark :
243 * Status :
244 *
245 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
246 *****************************************************************************/
247
248DWORD HMDeviceConsoleBufferClass::WriteFile(PHMHANDLEDATA pHMHandleData,
249 LPCVOID lpBuffer,
250 DWORD nNumberOfBytesToWrite,
251 LPDWORD lpNumberOfBytesWritten,
252 LPOVERLAPPED lpOverlapped)
253{
254 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
255 ULONG ulCounter; /* counter for the byte transfer */
256 PSZ pszBuffer = (PSZ)lpBuffer;
257 register UCHAR ucChar;
258
259#ifdef DEBUG_LOCAL2
260 WriteLog("KERNEL32/CONSOLE:HMDeviceConsoleBufferClass:WriteFile %s(%08x,%08x,%08x,%08x,%08x)\n",
261 lpHMDeviceName,
262 pHMHandleData->hHMHandle,
263 lpBuffer,
264 nNumberOfBytesToWrite,
265 lpNumberOfBytesWritten,
266 lpOverlapped);
267#endif
268
269 /* check if we're called with non-existing line buffer */
270 if (pConsoleBuffer->ppszLine == NULL)
271 return (ERROR_SYS_INTERNAL);
272
273 for (ulCounter = 0;
274 ulCounter < nNumberOfBytesToWrite;
275 ulCounter++)
276 {
277 ucChar = pszBuffer[ulCounter]; /* map to register */
278
279 if ( (pConsoleBuffer->dwConsoleMode & ENABLE_PROCESSED_OUTPUT) &&
280 (ucChar < 32) ) /* this is faster than a large switch statement */
281 {
282 switch (ucChar)
283 {
284 case 7: /* BEL */
285 if (pConsoleGlobals->Options.fSpeakerEnabled == TRUE)
286 DosBeep(pConsoleGlobals->Options.ulSpeakerFrequency,
287 pConsoleGlobals->Options.ulSpeakerDuration);
288 break;
289
290 case 8: /* Backspace */
291 if (pConsoleBuffer->coordCursorPosition.X > 0)
292 pConsoleBuffer->coordCursorPosition.X--;
293 break;
294
295 case 9: /* Tab */
296 pConsoleBuffer->coordCursorPosition.X =
297 (pConsoleBuffer->coordCursorPosition.X
298 / pConsoleGlobals->Options.ulTabSize
299 + 1)
300 * pConsoleGlobals->Options.ulTabSize;
301
302 if (pConsoleBuffer->coordCursorPosition.X >=
303 pConsoleBuffer->coordBufferSize.X)
304 {
305 pConsoleBuffer->coordCursorPosition.X = 0;
306 pConsoleBuffer->coordCursorPosition.Y++;
307
308 if (pConsoleBuffer->coordCursorPosition.Y >=
309 pConsoleBuffer->coordBufferSize.Y)
310 {
311 if (pConsoleBuffer->dwConsoleMode & ENABLE_WRAP_AT_EOL_OUTPUT)
312 {
313 iConsoleBufferScrollUp(pConsoleBuffer, /* scroll one line up */
314 1);
315 pConsoleBuffer->coordCursorPosition.Y--;
316 }
317 }
318 }
319 break;
320
321 case 10: /* LINEFEED */
322 pConsoleBuffer->coordCursorPosition.Y++;
323
324 if (pConsoleBuffer->coordCursorPosition.Y >=
325 pConsoleBuffer->coordBufferSize.Y)
326 {
327 iConsoleBufferScrollUp(pConsoleBuffer, /* scroll one line up */
328 1);
329 pConsoleBuffer->coordCursorPosition.Y--;
330 }
331 break;
332
333 case 13: /* CARRIAGE RETURN */
334 pConsoleBuffer->coordCursorPosition.X = 0;
335 break;
336
337 default:
338 break;
339 }
340 }
341 else
342 {
343 /* write character */
344 *(pConsoleBuffer->ppszLine[pConsoleBuffer->coordCursorPosition.Y] +
345 pConsoleBuffer->coordCursorPosition.X * 2) = ucChar;
346
347 pConsoleBuffer->coordCursorPosition.X++;
348
349 if (pConsoleBuffer->coordCursorPosition.X >=
350 pConsoleBuffer->coordBufferSize.X)
351 {
352 pConsoleBuffer->coordCursorPosition.X = 0;
353 pConsoleBuffer->coordCursorPosition.Y++;
354
355 if (pConsoleBuffer->coordCursorPosition.Y >=
356 pConsoleBuffer->coordBufferSize.Y)
357 {
358 if (pConsoleBuffer->dwConsoleMode & ENABLE_WRAP_AT_EOL_OUTPUT)
359 {
360 iConsoleBufferScrollUp(pConsoleBuffer, /* scroll one line up */
361 1);
362 pConsoleBuffer->coordCursorPosition.Y--;
363 }
364 else
365 {
366 /* just stay on last character */
367 pConsoleBuffer->coordCursorPosition.X = pConsoleBuffer->coordBufferSize.X - 1;
368 pConsoleBuffer->coordCursorPosition.Y = pConsoleBuffer->coordBufferSize.Y - 1;
369 }
370 }
371 }
372 }
373 }
374
375 /* update screen if active console */
376 if (pHMHandleData->hHMHandle == pConsoleGlobals->hConsoleBuffer)
377 pConsoleGlobals->fUpdateRequired = TRUE; /* update with next WM_TIMER */
378
379 *lpNumberOfBytesWritten = ulCounter;
380
381 return(ulCounter);
382}
383
384
385/*****************************************************************************
386 * Name :
387 * Purpose :
388 * Parameters:
389 * Variables :
390 * Result :
391 * Remark :
392 * Status :
393 *
394 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
395 *****************************************************************************/
396
397DWORD HMDeviceConsoleBufferClass::_DeviceRequest (PHMHANDLEDATA pHMHandleData,
398 ULONG ulRequestCode,
399 ULONG arg1,
400 ULONG arg2,
401 ULONG arg3,
402 ULONG arg4)
403{
404 switch (ulRequestCode)
405 {
406 case DRQ_FILLCONSOLEOUTPUTATTRIBUTE:
407 {
408 COORD coordWrite;
409
410 ULONG2COORD(coordWrite,arg3);
411
412 return (HMDeviceConsoleBufferClass
413 ::FillConsoleOutputAttribute(pHMHandleData,
414 (WORD)arg1,
415 (DWORD)arg2,
416 coordWrite,
417 (LPDWORD)arg4));
418 }
419
420
421 case DRQ_FILLCONSOLEOUTPUTCHARACTERA:
422 {
423 COORD coordWrite;
424
425 ULONG2COORD(coordWrite,arg3);
426
427 return (HMDeviceConsoleBufferClass
428 ::FillConsoleOutputCharacterA(pHMHandleData,
429 (UCHAR)arg1,
430 (DWORD)arg2,
431 coordWrite,
432 (LPDWORD)arg4));
433 }
434
435
436 case DRQ_FILLCONSOLEOUTPUTCHARACTERW:
437 {
438 COORD coordWrite;
439
440 ULONG2COORD(coordWrite,arg3);
441
442 return (HMDeviceConsoleBufferClass
443 ::FillConsoleOutputCharacterW(pHMHandleData,
444 (WCHAR)arg1,
445 (DWORD)arg2,
446 coordWrite,
447 (LPDWORD)arg4));
448 }
449
450
451 case DRQ_GETCONSOLECURSORINFO:
452 return (HMDeviceConsoleBufferClass
453 ::GetConsoleCursorInfo(pHMHandleData,
454 (PCONSOLE_CURSOR_INFO)arg1));
455
456
457 case DRQ_GETCONSOLEMODE:
458 return (HMDeviceConsoleBufferClass
459 ::GetConsoleMode(pHMHandleData,
460 (LPDWORD)arg1));
461
462
463 case DRQ_GETCONSOLESCREENBUFFERINFO:
464 return (HMDeviceConsoleBufferClass
465 ::GetConsoleScreenBufferInfo(pHMHandleData,
466 (PCONSOLE_SCREEN_BUFFER_INFO)arg1));
467
468
469 case DRQ_GETLARGESTCONSOLEWINDOWSIZE:
470 return (HMDeviceConsoleBufferClass
471 ::GetLargestConsoleWindowSize(pHMHandleData));
472
473
474 case DRQ_READCONSOLEOUTPUTA:
475 {
476 COORD coordDestBufferSize;
477 COORD coordDestBufferCoord;
478
479 ULONG2COORD(coordDestBufferSize, arg2);
480 ULONG2COORD(coordDestBufferCoord, arg3);
481
482 return (HMDeviceConsoleBufferClass
483 ::ReadConsoleOutputA(pHMHandleData,
484 (PCHAR_INFO)arg1,
485 coordDestBufferSize,
486 coordDestBufferCoord,
487 (PSMALL_RECT)arg4));
488 }
489
490
491 case DRQ_READCONSOLEOUTPUTW:
492 {
493 COORD coordDestBufferSize;
494 COORD coordDestBufferCoord;
495
496 ULONG2COORD(coordDestBufferSize, arg2);
497 ULONG2COORD(coordDestBufferCoord, arg3);
498
499 return (HMDeviceConsoleBufferClass
500 ::ReadConsoleOutputW(pHMHandleData,
501 (PCHAR_INFO)arg1,
502 coordDestBufferSize,
503 coordDestBufferCoord,
504 (PSMALL_RECT)arg4));
505 }
506
507
508 case DRQ_READCONSOLEOUTPUTATTRIBUTE:
509 {
510 COORD coordReadCoord;
511
512 ULONG2COORD(coordReadCoord, arg3);
513
514 return (HMDeviceConsoleBufferClass
515 ::ReadConsoleOutputAttribute(pHMHandleData,
516 (LPWORD)arg1,
517 (DWORD)arg2,
518 coordReadCoord,
519 (LPDWORD)arg4));
520 }
521
522
523 case DRQ_READCONSOLEOUTPUTCHARACTERA:
524 {
525 COORD coordReadCoord;
526
527 ULONG2COORD(coordReadCoord, arg3);
528
529 return (HMDeviceConsoleBufferClass
530 ::ReadConsoleOutputCharacterA(pHMHandleData,
531 (LPTSTR)arg1,
532 (DWORD)arg2,
533 coordReadCoord,
534 (LPDWORD)arg4));
535 }
536
537
538 case DRQ_READCONSOLEOUTPUTCHARACTERW:
539 {
540 COORD coordReadCoord;
541
542 ULONG2COORD(coordReadCoord, arg3);
543
544 return (HMDeviceConsoleBufferClass
545 ::ReadConsoleOutputCharacterW(pHMHandleData,
546 (LPWSTR)arg1,
547 (DWORD)arg2,
548 coordReadCoord,
549 (LPDWORD)arg4));
550 }
551
552
553 case DRQ_SCROLLCONSOLESCREENBUFFERA:
554 {
555 COORD coordDestOrigin;
556
557 ULONG2COORD(coordDestOrigin, arg3);
558
559 return (HMDeviceConsoleBufferClass
560 ::ScrollConsoleScreenBufferA(pHMHandleData,
561 (PSMALL_RECT)arg1,
562 (PSMALL_RECT)arg2,
563 coordDestOrigin,
564 (PCHAR_INFO)arg4));
565 }
566
567
568 case DRQ_SCROLLCONSOLESCREENBUFFERW:
569 {
570 COORD coordDestOrigin;
571
572 ULONG2COORD(coordDestOrigin, arg3);
573
574 return (HMDeviceConsoleBufferClass
575 ::ScrollConsoleScreenBufferW(pHMHandleData,
576 (PSMALL_RECT)arg1,
577 (PSMALL_RECT)arg2,
578 coordDestOrigin,
579 (PCHAR_INFO)arg4));
580 }
581
582
583 case DRQ_SETCONSOLEACTIVESCREENBUFFER:
584 return (HMDeviceConsoleBufferClass
585 ::SetConsoleActiveScreenBuffer(pHMHandleData));
586
587
588 case DRQ_SETCONSOLECURSORINFO:
589 return (HMDeviceConsoleBufferClass
590 ::SetConsoleCursorInfo(pHMHandleData,
591 (PCONSOLE_CURSOR_INFO)arg1));
592
593
594 case DRQ_SETCONSOLECURSORPOSITION:
595 {
596 COORD coordCursor;
597
598 ULONG2COORD(coordCursor, arg1);
599
600 return (HMDeviceConsoleBufferClass
601 ::SetConsoleCursorPosition(pHMHandleData,
602 coordCursor));
603 }
604
605
606 case DRQ_SETCONSOLEMODE:
607 return (HMDeviceConsoleBufferClass
608 ::SetConsoleMode(pHMHandleData,
609 (DWORD)arg1));
610
611
612 case DRQ_SETCONSOLESCREENBUFFERSIZE:
613 {
614 COORD coordSize;
615
616 ULONG2COORD(coordSize,arg1);
617
618 return (HMDeviceConsoleBufferClass::
619 SetConsoleScreenBufferSize(pHMHandleData,
620 coordSize));
621 }
622
623
624 case DRQ_SETCONSOLETEXTATTRIBUTE:
625 return (HMDeviceConsoleBufferClass::
626 SetConsoleTextAttribute(pHMHandleData,
627 (WORD)arg1));
628
629
630 case DRQ_SETCONSOLEWINDOWINFO:
631 return (HMDeviceConsoleBufferClass
632 ::SetConsoleWindowInfo(pHMHandleData,
633 (BOOL)arg1,
634 (PSMALL_RECT)arg2));
635
636
637 case DRQ_WRITECONSOLEA:
638 return (HMDeviceConsoleBufferClass
639 ::WriteConsoleA(pHMHandleData,
640 (CONST VOID*)arg1,
641 (DWORD)arg2,
642 (LPDWORD)arg3,
643 (LPVOID)arg4));
644
645
646 case DRQ_WRITECONSOLEW:
647 return (HMDeviceConsoleBufferClass
648 ::WriteConsoleW(pHMHandleData,
649 (CONST VOID*)arg1,
650 (DWORD)arg2,
651 (LPDWORD)arg3,
652 (LPVOID)arg4));
653
654
655 case DRQ_WRITECONSOLEOUTPUTA:
656 {
657 COORD coordSrcBufferSize;
658 COORD coordSrcBufferCoord;
659
660 ULONG2COORD(coordSrcBufferSize, arg2);
661 ULONG2COORD(coordSrcBufferCoord, arg3);
662
663 return (HMDeviceConsoleBufferClass
664 ::WriteConsoleOutputA(pHMHandleData,
665 (PCHAR_INFO)arg1,
666 coordSrcBufferSize,
667 coordSrcBufferCoord,
668 (PSMALL_RECT)arg4));
669 }
670
671
672 case DRQ_WRITECONSOLEOUTPUTW:
673 {
674 COORD coordSrcBufferSize;
675 COORD coordSrcBufferCoord;
676
677 ULONG2COORD(coordSrcBufferSize, arg2);
678 ULONG2COORD(coordSrcBufferCoord, arg3);
679
680 return (HMDeviceConsoleBufferClass
681 ::WriteConsoleOutputA(pHMHandleData,
682 (PCHAR_INFO)arg1,
683 coordSrcBufferSize,
684 coordSrcBufferCoord,
685 (PSMALL_RECT)arg4));
686 }
687
688
689 case DRQ_WRITECONSOLEOUTPUTATTRIBUTE:
690 {
691 COORD coordWriteCoord;
692
693 ULONG2COORD(coordWriteCoord, arg3);
694
695 return (HMDeviceConsoleBufferClass
696 ::WriteConsoleOutputAttribute(pHMHandleData,
697 (LPWORD)arg1,
698 (DWORD)arg2,
699 coordWriteCoord,
700 (LPDWORD)arg4));
701 }
702
703
704 case DRQ_WRITECONSOLEOUTPUTCHARACTERA:
705 {
706 COORD coordWriteCoord;
707
708 ULONG2COORD(coordWriteCoord, arg3);
709
710 return (HMDeviceConsoleBufferClass
711 ::WriteConsoleOutputCharacterA(pHMHandleData,
712 (LPTSTR)arg1,
713 (DWORD)arg2,
714 coordWriteCoord,
715 (LPDWORD)arg4));
716 }
717
718
719 case DRQ_WRITECONSOLEOUTPUTCHARACTERW:
720 {
721 COORD coordWriteCoord;
722
723 ULONG2COORD(coordWriteCoord, arg3);
724
725 return (HMDeviceConsoleBufferClass
726 ::WriteConsoleOutputCharacterW(pHMHandleData,
727 (LPWSTR)arg1,
728 (DWORD)arg2,
729 coordWriteCoord,
730 (LPDWORD)arg4));
731 }
732
733
734 case DRQ_INTERNAL_CONSOLEBUFFERMAP:
735 iConsoleBufferMap((PCONSOLEBUFFER)pHMHandleData->lpHandlerData);
736 return (NO_ERROR);
737
738
739 case DRQ_INTERNAL_CONSOLECURSORSHOW:
740 iConsoleCursorShow((PCONSOLEBUFFER)pHMHandleData->lpHandlerData,
741 (ULONG)arg1);
742 return (NO_ERROR);
743
744
745 case DRQ_INTERNAL_CONSOLEADJUSTWINDOW:
746 iConsoleAdjustWindow((PCONSOLEBUFFER)pHMHandleData->lpHandlerData);
747 return (NO_ERROR);
748 }
749
750
751#ifdef DEBUG_LOCAL
752 WriteLog("KERNEL32/CONSOLE:HMDeviceConsoleBufferClass:_DeviceRequest %s(%08x,%08x,%08x,%08x,%08x,%08x) unknown request\n",
753 lpHMDeviceName,
754 pHMHandleData->hHMHandle,
755 ulRequestCode,
756 arg1,
757 arg2,
758 arg3,
759 arg4);
760#endif
761
762 SetLastError(ERROR_INVALID_FUNCTION); /* request not implemented */
763 return(FALSE); /* we assume this indicates API call failed */
764}
765
766
767/*****************************************************************************
768 * Name : DWORD HMDeviceConsoleBufferClass::FillConsoleOutputAttribute
769 * Purpose : fills the console buffer with a specified attribute
770 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
771 * WORD wAttribute
772 * DWORD nLength
773 * COORD dwWriteCoord
774 * LPDWORD lpNumberOfAttrsWritten
775 * Variables :
776 * Result :
777 * Remark :
778 * Status : UNTESTED
779 *
780 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
781 *****************************************************************************/
782
783DWORD HMDeviceConsoleBufferClass::FillConsoleOutputAttribute(PHMHANDLEDATA pHMHandleData,
784 WORD wAttribute,
785 DWORD nLength,
786 COORD dwWriteCoord,
787 LPDWORD lpNumberOfAttrsWritten)
788{
789 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
790 ULONG ulCounter; /* current character counter */
791
792#ifdef DEBUG_LOCAL2
793 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::FillConsoleOutputAttribute(%08x,attr=%04x,%u,x=%u y=%u,res=%08x).\n",
794 pHMHandleData,
795 wAttribute,
796 nLength,
797 dwWriteCoord.X,
798 dwWriteCoord.Y,
799 lpNumberOfAttrsWritten);
800#endif
801
802 if ( (dwWriteCoord.X < 0) ||
803 (dwWriteCoord.Y < 0) )
804 {
805 if (lpNumberOfAttrsWritten != NULL) /* ensure pointer is valid */
806 *lpNumberOfAttrsWritten = 0; /* complete error handling */
807
808 SetLastError(ERROR_INVALID_PARAMETER);
809 return (FALSE);
810 }
811
812 /* check if dwWriteCoord is within specs */
813 if ( (dwWriteCoord.X >= pConsoleBuffer->coordBufferSize.X) ||
814 (dwWriteCoord.Y >= pConsoleBuffer->coordBufferSize.Y) )
815 {
816 if (lpNumberOfAttrsWritten != NULL) /* ensure pointer is valid */
817 *lpNumberOfAttrsWritten = 0; /* complete error handling */
818
819 SetLastError(ERROR_INVALID_PARAMETER);
820 return (FALSE);
821 }
822
823
824 /* OK, now write the attribute lines */
825 for (ulCounter = 0;
826 ulCounter < nLength;
827 ulCounter++)
828 {
829 /* write attribute into cell */
830 *(pConsoleBuffer->ppszLine[dwWriteCoord.Y] +
831 (dwWriteCoord.X * 2 + 1)
832 ) = (UCHAR)(wAttribute & 0xFF);
833 /* write attribute, don't change characters */
834
835 dwWriteCoord.X++; /* move write position */
836 if (dwWriteCoord.X >= pConsoleBuffer->coordBufferSize.X)
837 {
838 dwWriteCoord.X = 0; /* skip to next line */
839 dwWriteCoord.Y++;
840
841 /* oops, we're at the end of the buffer. Abort now. */
842 if (dwWriteCoord.Y >= pConsoleBuffer->coordBufferSize.Y)
843 {
844 if (lpNumberOfAttrsWritten != NULL) /* ensure pointer is valid */
845 *lpNumberOfAttrsWritten = ulCounter;
846
847 /* update screen if active console */
848 if (pHMHandleData->hHMHandle == pConsoleGlobals->hConsoleBuffer)
849 pConsoleGlobals->fUpdateRequired = TRUE;/* update with next WM_TIMER */
850
851 return (TRUE);
852 }
853 }
854 }
855
856 /* update screen if active console */
857 if (pHMHandleData->hHMHandle == pConsoleGlobals->hConsoleBuffer)
858 pConsoleGlobals->fUpdateRequired = TRUE; /* update with next WM_TIMER */
859
860 if (lpNumberOfAttrsWritten != NULL) /* ensure pointer is valid */
861 *lpNumberOfAttrsWritten = nLength;
862
863 return (TRUE);
864}
865
866
867/*****************************************************************************
868 * Name : DWORD HMDeviceConsoleBufferClass::FillConsoleOutputCharacterA
869 * Purpose : fills the console buffer with a specified ASCII character
870 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
871 * UCHAR ucCharacter
872 * DWORD nLength
873 * COORD dwWriteCoord
874 * LPDWORD lpNumberOfCharsWritten
875 * Variables :
876 * Result :
877 * Remark :
878 * Status : UNTESTED
879 *
880 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
881 *****************************************************************************/
882
883DWORD HMDeviceConsoleBufferClass::FillConsoleOutputCharacterA(PHMHANDLEDATA pHMHandleData,
884 UCHAR ucCharacter,
885 DWORD nLength,
886 COORD dwWriteCoord,
887 LPDWORD lpNumberOfCharsWritten)
888{
889 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
890 ULONG ulCounter; /* current character counter */
891
892#ifdef DEBUG_LOCAL2
893 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::FillConsoleOutputCharacterA(%08x,char=%02x,%u,x=%u y=%u,res=%08x).\n",
894 pHMHandleData,
895 ucCharacter,
896 nLength,
897 dwWriteCoord.X,
898 dwWriteCoord.Y,
899 lpNumberOfCharsWritten);
900#endif
901
902 if ( (dwWriteCoord.X < 0) ||
903 (dwWriteCoord.Y < 0) )
904 {
905 if (lpNumberOfCharsWritten != NULL) /* ensure pointer is valid */
906 *lpNumberOfCharsWritten = 0; /* complete error handling */
907
908 SetLastError(ERROR_INVALID_PARAMETER);
909 return (FALSE);
910 }
911
912
913 /* check if dwWriteCoord is within specs */
914 if ( (dwWriteCoord.X >= pConsoleBuffer->coordBufferSize.X) ||
915 (dwWriteCoord.Y >= pConsoleBuffer->coordBufferSize.Y) )
916 {
917 if (lpNumberOfCharsWritten != NULL) /* ensure pointer is valid */
918 *lpNumberOfCharsWritten = 0; /* complete error handling */
919
920 SetLastError(ERROR_INVALID_PARAMETER);
921 return (FALSE);
922 }
923
924
925 /* OK, now write the attribute lines */
926 for (ulCounter = 0;
927 ulCounter < nLength;
928 ulCounter++)
929 {
930 /* write character into cell */
931 *(pConsoleBuffer->ppszLine[dwWriteCoord.Y] +
932 (dwWriteCoord.X * 2)
933 ) = ucCharacter;
934
935 dwWriteCoord.X++; /* move write position */
936 if (dwWriteCoord.X >= pConsoleBuffer->coordBufferSize.X)
937 {
938 dwWriteCoord.X = 0; /* skip to next line */
939 dwWriteCoord.Y++;
940
941 /* oops, we're at the end of the buffer. Abort now. */
942 if (dwWriteCoord.Y >= pConsoleBuffer->coordBufferSize.Y)
943 {
944 if (lpNumberOfCharsWritten != NULL) /* ensure pointer is valid */
945 *lpNumberOfCharsWritten = ulCounter;
946
947 /* update screen if active console */
948 if (pHMHandleData->hHMHandle == pConsoleGlobals->hConsoleBuffer)
949 pConsoleGlobals->fUpdateRequired = TRUE;/* update with next WM_TIMER */
950
951 return (TRUE);
952 }
953 }
954 }
955
956 /* update screen if active console */
957 if (pHMHandleData->hHMHandle == pConsoleGlobals->hConsoleBuffer)
958 pConsoleGlobals->fUpdateRequired = TRUE; /* update with next WM_TIMER */
959
960 if (lpNumberOfCharsWritten != NULL) /* ensure pointer is valid */
961 *lpNumberOfCharsWritten = nLength;
962
963 return (TRUE);
964}
965
966
967/*****************************************************************************
968 * Name : DWORD HMDeviceConsoleBufferClass::FillConsoleOutputCharacterW
969 * Purpose : fills the console buffer with a specified ASCII character
970 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
971 * WCHAR wcCharacter
972 * DWORD nLength
973 * COORD dwWriteCoord
974 * LPDWORD lpNumberOfCharsWritten
975 * Variables :
976 * Result :
977 * Remark :
978 * Status : UNTESTED
979 *
980 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
981 *****************************************************************************/
982
983DWORD HMDeviceConsoleBufferClass::FillConsoleOutputCharacterW(PHMHANDLEDATA pHMHandleData,
984 WCHAR wcCharacter,
985 DWORD nLength,
986 COORD dwWriteCoord,
987 LPDWORD lpNumberOfCharsWritten)
988{
989 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
990 ULONG ulCounter; /* current character counter */
991
992#ifdef DEBUG_LOCAL2
993 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::FillConsoleOutputCharacterW(%08x,char=%02x,%u,x=%u y=%u,res=%08x).\n",
994 pHMHandleData,
995 wcCharacter,
996 nLength,
997 dwWriteCoord.X,
998 dwWriteCoord.Y,
999 lpNumberOfCharsWritten);
1000#endif
1001
1002 if ( (dwWriteCoord.X < 0) ||
1003 (dwWriteCoord.Y < 0) )
1004 {
1005 if (lpNumberOfCharsWritten != NULL) /* ensure pointer is valid */
1006 *lpNumberOfCharsWritten = 0; /* complete error handling */
1007
1008 SetLastError(ERROR_INVALID_PARAMETER);
1009 return (FALSE);
1010 }
1011
1012
1013 /* check if dwWriteCoord is within specs */
1014 if ( (dwWriteCoord.X >= pConsoleBuffer->coordBufferSize.X) ||
1015 (dwWriteCoord.Y >= pConsoleBuffer->coordBufferSize.Y) )
1016 {
1017 if (lpNumberOfCharsWritten != NULL) /* ensure pointer is valid */
1018 *lpNumberOfCharsWritten = 0; /* complete error handling */
1019
1020 SetLastError(ERROR_INVALID_PARAMETER);
1021 return (FALSE);
1022 }
1023
1024
1025 /* OK, now write the attribute lines */
1026 for (ulCounter = 0;
1027 ulCounter < nLength;
1028 ulCounter++)
1029 {
1030 /* write character into cell */
1031 *(pConsoleBuffer->ppszLine[dwWriteCoord.Y] +
1032 (dwWriteCoord.X * 2)
1033 ) = (UCHAR)wcCharacter; /* @@@PH unicode to ascii conversion ! */
1034
1035 dwWriteCoord.X++; /* move write position */
1036 if (dwWriteCoord.X >= pConsoleBuffer->coordBufferSize.X)
1037 {
1038 dwWriteCoord.X = 0; /* skip to next line */
1039 dwWriteCoord.Y++;
1040
1041 /* oops, we're at the end of the buffer. Abort now. */
1042 if (dwWriteCoord.Y >= pConsoleBuffer->coordBufferSize.Y)
1043 {
1044 if (lpNumberOfCharsWritten != NULL) /* ensure pointer is valid */
1045 *lpNumberOfCharsWritten = ulCounter;
1046
1047 /* update screen if active console */
1048 if (pHMHandleData->hHMHandle == pConsoleGlobals->hConsoleBuffer)
1049 pConsoleGlobals->fUpdateRequired = TRUE;/* update with next WM_TIMER */
1050
1051 return (TRUE);
1052 }
1053 }
1054 }
1055
1056 /* update screen if active console */
1057 if (pHMHandleData->hHMHandle == pConsoleGlobals->hConsoleBuffer)
1058 pConsoleGlobals->fUpdateRequired = TRUE; /* update with next WM_TIMER */
1059
1060 if (lpNumberOfCharsWritten != NULL) /* ensure pointer is valid */
1061 *lpNumberOfCharsWritten = nLength;
1062
1063 return (TRUE);
1064}
1065
1066
1067
1068/*****************************************************************************
1069 * Name : DWORD HMDeviceConsoleBufferClass::GetConsoleMode
1070 * Purpose : queries the current console mode
1071 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
1072 * LPDWORD lpMode
1073 * Variables :
1074 * Result :
1075 * Remark :
1076 * Status : UNTESTED
1077 *
1078 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
1079 *****************************************************************************/
1080
1081DWORD HMDeviceConsoleBufferClass::GetConsoleMode(PHMHANDLEDATA pHMHandleData,
1082 LPDWORD lpMode)
1083{
1084 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
1085
1086#ifdef DEBUG_LOCAL2
1087 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::GetConsoleMode(%08x,%08x).\n",
1088 pHMHandleData,
1089 lpMode);
1090#endif
1091
1092 *lpMode = pConsoleBuffer->dwConsoleMode; /* return current console mode */
1093
1094 return (TRUE);
1095}
1096
1097
1098/*****************************************************************************
1099 * Name : DWORD HMDeviceConsoleBufferClass::GetConsoleCursorInfo
1100 * Purpose : queries the current console's cursor information
1101 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
1102 * PCONSOLE_CURSOR_INFO pCCI
1103 * Variables :
1104 * Result :
1105 * Remark :
1106 * Status : UNTESTED
1107 *
1108 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
1109 *****************************************************************************/
1110
1111DWORD HMDeviceConsoleBufferClass::GetConsoleCursorInfo(PHMHANDLEDATA pHMHandleData,
1112 PCONSOLE_CURSOR_INFO pCCI)
1113{
1114 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
1115
1116#ifdef DEBUG_LOCAL2
1117 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::GetConsoleCursorInfo(%08x,%08x).\n",
1118 pHMHandleData,
1119 pCCI);
1120#endif
1121
1122 memcpy(pCCI, /* just copy the whole information block */
1123 &pConsoleBuffer->CursorInfo,
1124 sizeof (pConsoleBuffer->CursorInfo) );
1125
1126 return (TRUE);
1127}
1128
1129
1130/*****************************************************************************
1131 * Name : DWORD HMDeviceConsoleBufferClass::GetConsoleScreenBufferInfo
1132 * Purpose : queries the current console screen buffer's info
1133 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
1134 * PCONSOLE_SCREEN_BUFFER_INFO pCSBI
1135 * Variables :
1136 * Result :
1137 * Remark :
1138 * Status : UNTESTED
1139 *
1140 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
1141 *****************************************************************************/
1142
1143DWORD HMDeviceConsoleBufferClass::GetConsoleScreenBufferInfo(PHMHANDLEDATA pHMHandleData,
1144 PCONSOLE_SCREEN_BUFFER_INFO pCSBI)
1145{
1146 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
1147
1148#ifdef DEBUG_LOCAL2
1149 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::GetConsoleScreenBufferInfo(%08x,%08x).\n",
1150 pHMHandleData,
1151 pCSBI);
1152#endif
1153
1154 pCSBI->dwSize = pConsoleBuffer->coordBufferSize;
1155 pCSBI->dwCursorPosition = pConsoleBuffer->coordCursorPosition;
1156 pCSBI->wAttributes = (USHORT)pConsoleBuffer->ucDefaultAttribute;
1157
1158 /* @@@PH unsure, but should be OK */
1159 pCSBI->srWindow.Left = pConsoleBuffer->coordWindowPosition.X;
1160 pCSBI->srWindow.Top = pConsoleBuffer->coordWindowPosition.Y;
1161 pCSBI->srWindow.Right = pConsoleBuffer->coordWindowPosition.X +
1162 pConsoleBuffer->coordWindowSize.X - 1;
1163 pCSBI->srWindow.Bottom = pConsoleBuffer->coordWindowPosition.Y +
1164 pConsoleBuffer->coordWindowSize.Y - 1;
1165
1166 pCSBI->dwMaximumWindowSize = pConsoleBuffer->coordBufferSize;
1167
1168 return (TRUE);
1169}
1170
1171
1172/*****************************************************************************
1173 * Name : DWORD HMDeviceConsoleBufferClass::GetLargestConsoleWindowSize
1174 * Purpose : Determine maximum AVIO size
1175 * Parameters:
1176 * Variables :
1177 * Result :
1178 * Remark :
1179 * Status :
1180 *
1181 * Author : Patrick Haller [Tue, 1998/02/10 01:55]
1182 *****************************************************************************/
1183
1184DWORD HMDeviceConsoleBufferClass::GetLargestConsoleWindowSize(PHMHANDLEDATA pHMHandleData)
1185{
1186 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
1187 COORD coordSize; /* maximum avio size */
1188 LONG lScreenCX; /* width and height of display */
1189 LONG lScreenCY;
1190 APIRET rc; /* API returncode */
1191
1192
1193#ifdef DEBUG_LOCAL
1194 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::GetLargestConsoleWindowSize(%08x).\n",
1195 pHMHandleData);
1196#endif
1197
1198 /* @@@PH determine maximum console window size in characters
1199 based on display size and current avio font */
1200
1201 lScreenCX = WinQuerySysValue(HWND_DESKTOP, /* query PM for that */
1202 SV_CXSCREEN);
1203
1204 lScreenCY = WinQuerySysValue(HWND_DESKTOP, /* query PM for that */
1205 SV_CYFULLSCREEN);
1206
1207 if (rc != NO_ERROR)
1208 {
1209 WriteLog("KERNEL32/CONSOLE: VioGetDeviceCellSize failed with #%u.\n",
1210 rc);
1211
1212 return (FALSE); /* say API failed */
1213 }
1214
1215 if ( (pConsoleGlobals->sCellCX == 0) || /* prevent division by zero */
1216 (pConsoleGlobals->sCellCY == 0) )
1217 {
1218 WriteLog("KERNEL32/CONSOLE: VioGetDeviceCellSize returned 0 value.\n");
1219
1220 return (FALSE); /* say API failed */
1221 }
1222
1223 coordSize.X = lScreenCX / pConsoleGlobals->sCellCX; /* calculate */
1224 coordSize.Y = lScreenCY / pConsoleGlobals->sCellCY;
1225
1226 /* these limitations are due to OS/2's current VIO subsystem */
1227 coordSize.X = min(coordSize.X, MAX_OS2_COLUMNS);
1228 coordSize.Y = min(coordSize.Y, MAX_OS2_ROWS);
1229
1230 return (COORD2ULONG(coordSize)); /* return value */
1231}
1232
1233
1234/*****************************************************************************
1235 * Name : DWORD HMDeviceConsoleBufferClass::ReadConsoleOutputA
1236 * Purpose : reads character and color attribute data from screen rectangle
1237 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
1238 * PCHAR_INFO pchiDestBuffer
1239 * COORD coordDestBufferSize
1240 * COORD coordDestBufferCoord
1241 * PSMALL_RECT psrctSourceRect
1242 * Variables :
1243 * Result :
1244 * Remark :
1245 * Status : UNTESTED
1246 *
1247 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
1248 *****************************************************************************/
1249
1250DWORD HMDeviceConsoleBufferClass::ReadConsoleOutputA(PHMHANDLEDATA pHMHandleData,
1251 PCHAR_INFO pchiDestBuffer,
1252 COORD coordDestBufferSize,
1253 COORD coordDestBufferCoord,
1254 PSMALL_RECT psrctSourceRect)
1255{
1256 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
1257 ULONG ulX, ulY; /* current coordinate to be read */
1258 ULONG ulCX, ulCY; /* width and height of target area */
1259 ULONG ulReadX, ulReadY; /* position data is read from */
1260 WORD wCell; /* currently read data */
1261
1262 PCHAR_INFO pchi;
1263
1264#ifdef DEBUG_LOCAL2
1265 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::ReadConsoleOutputA(%08x,%08x,x=%u y=%u,x=%u y=%u, %08x).\n",
1266 pHMHandleData,
1267 pchiDestBuffer,
1268 coordDestBufferSize.X,
1269 coordDestBufferSize.Y,
1270 coordDestBufferCoord.X,
1271 coordDestBufferCoord.Y,
1272 psrctSourceRect);
1273#endif
1274
1275
1276 /* verify psrctSourceRect first */
1277 psrctSourceRect->Left = max(psrctSourceRect->Left, 0);
1278 psrctSourceRect->Top = max(psrctSourceRect->Top, 0);
1279 psrctSourceRect->Right = min(psrctSourceRect->Right, pConsoleBuffer->coordBufferSize.X - 1);
1280 psrctSourceRect->Bottom= min(psrctSourceRect->Bottom,pConsoleBuffer->coordBufferSize.Y - 1);
1281
1282 /* verify target buffer */
1283 if ( (coordDestBufferSize.X < coordDestBufferCoord.X) ||
1284 (coordDestBufferSize.Y < coordDestBufferCoord.Y) )
1285 {
1286 SetLastError(ERROR_INVALID_PARAMETER); /* set detailed error info */
1287 return (FALSE); /* API failed */
1288 }
1289
1290 ulCX = coordDestBufferSize.X - coordDestBufferCoord.X;
1291 ulCY = coordDestBufferSize.Y - coordDestBufferCoord.Y;
1292
1293 ulCX = min(ulCX, (psrctSourceRect->Right - psrctSourceRect->Left));
1294 ulCY = min(ulCY, (psrctSourceRect->Bottom - psrctSourceRect->Top));
1295
1296 /* final calculation of the copy rectangle */
1297 psrctSourceRect->Right = psrctSourceRect->Left + ulCX;
1298 psrctSourceRect->Bottom = psrctSourceRect->Top + ulCY;
1299
1300
1301 for (ulY = 0,
1302 ulReadY = psrctSourceRect->Top;
1303
1304 ulY <= ulCY;
1305
1306 ulY++,
1307 ulReadY++)
1308 {
1309 pchi = pchiDestBuffer + sizeof(CHAR_INFO) * coordDestBufferCoord.X
1310 + sizeof(CHAR_INFO) * (coordDestBufferCoord.Y + ulY)
1311 * coordDestBufferSize.X;
1312 for (ulX = 0,
1313 ulReadX = psrctSourceRect->Left;
1314
1315 ulX <= ulCX;
1316
1317 ulX++,
1318 ulReadX++,
1319 pchi++)
1320 {
1321 /* read character */
1322 wCell = *(pConsoleBuffer->ppszLine[ulReadY] + ulReadX * 2);
1323
1324 pchi->Char.AsciiChar = (UCHAR)(wCell & 0x00FF);
1325 pchi->Attributes = wCell >> 8;
1326 }
1327 }
1328
1329 return (TRUE); /* OK, that's it */
1330}
1331
1332
1333/*****************************************************************************
1334 * Name : DWORD HMDeviceConsoleBufferClass::ReadConsoleOutputW
1335 * Purpose : reads character and color attribute data from screen rectangle
1336 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
1337 * PCHAR_INFO pchiDestBuffer
1338 * COORD coordDestBufferSize
1339 * COORD coordDestBufferCoord
1340 * PSMALL_RECT psrctSourceRect
1341 * Variables :
1342 * Result :
1343 * Remark :
1344 * Status : UNTESTED
1345 *
1346 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
1347 *****************************************************************************/
1348
1349DWORD HMDeviceConsoleBufferClass::ReadConsoleOutputW(PHMHANDLEDATA pHMHandleData,
1350 PCHAR_INFO pchiDestBuffer,
1351 COORD coordDestBufferSize,
1352 COORD coordDestBufferCoord,
1353 PSMALL_RECT psrctSourceRect)
1354{
1355 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
1356 ULONG ulX, ulY; /* current coordinate to be read */
1357 ULONG ulCX, ulCY; /* width and height of target area */
1358 ULONG ulReadX, ulReadY; /* position data is read from */
1359 WORD wCell; /* currently read data */
1360
1361 PCHAR_INFO pchi;
1362
1363#ifdef DEBUG_LOCAL2
1364 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::ReadConsoleOutputW(%08x,%08x,x=%u y=%u,x=%u y=%u, %08x).\n",
1365 pHMHandleData,
1366 pchiDestBuffer,
1367 coordDestBufferSize.X,
1368 coordDestBufferSize.Y,
1369 coordDestBufferCoord.X,
1370 coordDestBufferCoord.Y,
1371 psrctSourceRect);
1372#endif
1373
1374
1375 /* verify psrctSourceRect first */
1376 psrctSourceRect->Left = max(psrctSourceRect->Left, 0);
1377 psrctSourceRect->Top = max(psrctSourceRect->Top, 0);
1378 psrctSourceRect->Right = min(psrctSourceRect->Right, pConsoleBuffer->coordBufferSize.X - 1);
1379 psrctSourceRect->Bottom= min(psrctSourceRect->Bottom,pConsoleBuffer->coordBufferSize.Y - 1);
1380
1381 /* verify target buffer */
1382 if ( (coordDestBufferSize.X < coordDestBufferCoord.X) ||
1383 (coordDestBufferSize.Y < coordDestBufferCoord.Y) )
1384 {
1385 SetLastError(ERROR_INVALID_PARAMETER); /* set detailed error info */
1386 return (FALSE); /* API failed */
1387 }
1388
1389 ulCX = coordDestBufferSize.X - coordDestBufferCoord.X;
1390 ulCY = coordDestBufferSize.Y - coordDestBufferCoord.Y;
1391
1392 ulCX = min(ulCX, (psrctSourceRect->Right - psrctSourceRect->Left));
1393 ulCY = min(ulCY, (psrctSourceRect->Bottom - psrctSourceRect->Top));
1394
1395 /* final calculation of the copy rectangle */
1396 psrctSourceRect->Right = psrctSourceRect->Left + ulCX;
1397 psrctSourceRect->Bottom = psrctSourceRect->Top + ulCY;
1398
1399
1400 for (ulY = 0,
1401 ulReadY = psrctSourceRect->Top;
1402
1403 ulY <= ulCY;
1404
1405 ulY++,
1406 ulReadY++)
1407 {
1408 pchi = pchiDestBuffer + sizeof(CHAR_INFO) * coordDestBufferCoord.X
1409 + sizeof(CHAR_INFO) * (coordDestBufferCoord.Y + ulY)
1410 * coordDestBufferSize.X;
1411 for (ulX = 0,
1412 ulReadX = psrctSourceRect->Left;
1413
1414 ulX <= ulCX;
1415
1416 ulX++,
1417 ulReadX++,
1418 pchi++)
1419 {
1420 /* read character */
1421 wCell = *(pConsoleBuffer->ppszLine[ulReadY] + ulReadX * 2);
1422
1423 /* @@@PH Ascii->Unicode */
1424 pchi->Char.UnicodeChar = (UCHAR)(wCell & 0x00FF);
1425 pchi->Attributes = wCell >> 8;
1426 }
1427 }
1428
1429 return (TRUE); /* OK, that's it */
1430}
1431
1432
1433/*****************************************************************************
1434 * Name : DWORD HMDeviceConsoleBufferClass::ReadConsoleOutputAttribute
1435 * Purpose : read an array with specified attributes from the console
1436 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
1437 * LPWORD lpwAttribute
1438 * DWORD cReadCells
1439 * COORD dwReadCoord
1440 * LPDWORD lpcNumberRead
1441 * Variables :
1442 * Result :
1443 * Remark :
1444 * Status : UNTESTED
1445 *
1446 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
1447 *****************************************************************************/
1448
1449DWORD HMDeviceConsoleBufferClass::ReadConsoleOutputAttribute(PHMHANDLEDATA pHMHandleData,
1450 LPWORD lpwAttribute,
1451 DWORD cReadCells,
1452 COORD dwReadCoord,
1453 LPDWORD lpcNumberRead)
1454{
1455 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
1456 ULONG ulCounter; /* current character counter */
1457
1458#ifdef DEBUG_LOCAL2
1459 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::ReadConsoleOutputAttribute(%08x,pattr=%08x,%u,x=%u y=%u,res=%08x).\n",
1460 pHMHandleData,
1461 lpwAttribute,
1462 cReadCells,
1463 dwReadCoord.X,
1464 dwReadCoord.Y,
1465 lpcNumberRead);
1466#endif
1467
1468 if ( (dwReadCoord.X < 0) ||
1469 (dwReadCoord.Y < 0) )
1470 {
1471 if (lpcNumberRead != NULL) /* ensure pointer is valid */
1472 *lpcNumberRead = 0; /* complete error handling */
1473
1474 SetLastError(ERROR_INVALID_PARAMETER);
1475 return (FALSE);
1476 }
1477
1478 /* check if dwReadCoord is within specs */
1479 if ( (dwReadCoord.X >= pConsoleBuffer->coordBufferSize.X) ||
1480 (dwReadCoord.Y >= pConsoleBuffer->coordBufferSize.Y) )
1481 {
1482 if (lpcNumberRead != NULL) /* ensure pointer is valid */
1483 *lpcNumberRead = 0; /* complete error handling */
1484
1485 SetLastError(ERROR_INVALID_PARAMETER);
1486 return (FALSE);
1487 }
1488
1489
1490 /* OK, now write the attribute lines */
1491 for (ulCounter = 0;
1492 ulCounter < cReadCells;
1493 ulCounter++,
1494 lpwAttribute++)
1495 {
1496 /* write attribute into cell */
1497 *lpwAttribute = (UCHAR)
1498 *(pConsoleBuffer->ppszLine[dwReadCoord.Y] +
1499 (dwReadCoord.X * 2 + 1));
1500
1501 dwReadCoord.X++; /* move write position */
1502 if (dwReadCoord.X >= pConsoleBuffer->coordBufferSize.X)
1503 {
1504 dwReadCoord.X = 0; /* skip to next line */
1505 dwReadCoord.Y++;
1506
1507 /* oops, we're at the end of the buffer. Abort now. */
1508 if (dwReadCoord.Y >= pConsoleBuffer->coordBufferSize.Y)
1509 {
1510 if (lpcNumberRead != NULL) /* ensure pointer is valid */
1511 *lpcNumberRead = ulCounter;
1512
1513 return (TRUE);
1514 }
1515 }
1516 }
1517
1518 if (lpcNumberRead != NULL) /* ensure pointer is valid */
1519 *lpcNumberRead = cReadCells;
1520
1521 return (TRUE);
1522}
1523
1524
1525/*****************************************************************************
1526 * Name : DWORD HMDeviceConsoleBufferClass::ReadConsoleOutputCharacterA
1527 * Purpose : read an array with specified characters from the console
1528 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
1529 * LPWORD lpReadBuffer
1530 * DWORD cRead
1531 * COORD coordReadCoord
1532 * LPDWORD lpcNumberRead
1533 * Variables :
1534 * Result :
1535 * Remark :
1536 * Status : UNTESTED
1537 *
1538 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
1539 *****************************************************************************/
1540
1541DWORD HMDeviceConsoleBufferClass::ReadConsoleOutputCharacterA(PHMHANDLEDATA pHMHandleData,
1542 LPTSTR lpwReadBuffer,
1543 DWORD cchRead,
1544 COORD coordReadCoord,
1545 LPDWORD lpcNumberRead)
1546{
1547 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
1548 ULONG ulCounter; /* current character counter */
1549
1550#ifdef DEBUG_LOCAL2
1551 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::ReadConsoleOutputCharacterA(%08x,pattr=%08x,%u,x=%u y=%u,res=%08x).\n",
1552 pHMHandleData,
1553 lpwReadBuffer,
1554 cchRead,
1555 coordReadCoord.X,
1556 coordReadCoord.Y,
1557 lpcNumberRead);
1558#endif
1559
1560 if ( (coordReadCoord.X < 0) ||
1561 (coordReadCoord.Y < 0) )
1562 {
1563 if (lpcNumberRead != NULL) /* ensure pointer is valid */
1564 *lpcNumberRead = 0; /* complete error handling */
1565
1566 SetLastError(ERROR_INVALID_PARAMETER);
1567 return (FALSE);
1568 }
1569
1570 /* check if coordReadCoord is within specs */
1571 if ( (coordReadCoord.X >= pConsoleBuffer->coordBufferSize.X) ||
1572 (coordReadCoord.Y >= pConsoleBuffer->coordBufferSize.Y) )
1573 {
1574 if (lpcNumberRead != NULL) /* ensure pointer is valid */
1575 *lpcNumberRead = 0; /* complete error handling */
1576
1577 SetLastError(ERROR_INVALID_PARAMETER);
1578 return (FALSE);
1579 }
1580
1581
1582 /* OK, now write the attribute lines */
1583 for (ulCounter = 0;
1584 ulCounter < cchRead;
1585 ulCounter++,
1586 lpwReadBuffer++)
1587 {
1588 /* write character into cell */
1589 *lpwReadBuffer =
1590 *(pConsoleBuffer->ppszLine[coordReadCoord.Y] +
1591 (coordReadCoord.X * 2));
1592
1593 coordReadCoord.X++; /* move write position */
1594 if (coordReadCoord.X >= pConsoleBuffer->coordBufferSize.X)
1595 {
1596 coordReadCoord.X = 0; /* skip to next line */
1597 coordReadCoord.Y++;
1598
1599 /* oops, we're at the end of the buffer. Abort now. */
1600 if (coordReadCoord.Y >= pConsoleBuffer->coordBufferSize.Y)
1601 {
1602 if (lpcNumberRead != NULL) /* ensure pointer is valid */
1603 *lpcNumberRead = ulCounter;
1604
1605 return (TRUE);
1606 }
1607 }
1608 }
1609
1610 if (lpcNumberRead != NULL) /* ensure pointer is valid */
1611 *lpcNumberRead = cchRead;
1612
1613 return (TRUE);
1614}
1615
1616
1617/*****************************************************************************
1618 * Name : DWORD HMDeviceConsoleBufferClass::ReadConsoleOutputCharacterW
1619 * Purpose : read an array with specified characters from the console
1620 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
1621 * LPWORD lpReadBuffer
1622 * DWORD cRead
1623 * COORD coordReadCoord
1624 * LPDWORD lpcNumberRead
1625 * Variables :
1626 * Result :
1627 * Remark :
1628 * Status : UNTESTED
1629 *
1630 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
1631 *****************************************************************************/
1632
1633DWORD HMDeviceConsoleBufferClass::ReadConsoleOutputCharacterW(PHMHANDLEDATA pHMHandleData,
1634 LPWSTR lpwReadBuffer,
1635 DWORD cchRead,
1636 COORD coordReadCoord,
1637 LPDWORD lpcNumberRead)
1638{
1639 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
1640 ULONG ulCounter; /* current character counter */
1641
1642#ifdef DEBUG_LOCAL2
1643 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::ReadConsoleOutputCharacterW(%08x,pattr=%08x,%u,x=%u y=%u,res=%08x).\n",
1644 pHMHandleData,
1645 lpwReadBuffer,
1646 cchRead,
1647 coordReadCoord.X,
1648 coordReadCoord.Y,
1649 lpcNumberRead);
1650#endif
1651
1652 if ( (coordReadCoord.X < 0) ||
1653 (coordReadCoord.Y < 0) )
1654 {
1655 if (lpcNumberRead != NULL) /* ensure pointer is valid */
1656 *lpcNumberRead = 0; /* complete error handling */
1657
1658 SetLastError(ERROR_INVALID_PARAMETER);
1659 return (FALSE);
1660 }
1661
1662 /* check if coordReadCoord is within specs */
1663 if ( (coordReadCoord.X >= pConsoleBuffer->coordBufferSize.X) ||
1664 (coordReadCoord.Y >= pConsoleBuffer->coordBufferSize.Y) )
1665 {
1666 if (lpcNumberRead != NULL) /* ensure pointer is valid */
1667 *lpcNumberRead = 0; /* complete error handling */
1668
1669 SetLastError(ERROR_INVALID_PARAMETER);
1670 return (FALSE);
1671 }
1672
1673
1674 /* OK, now write the attribute lines */
1675 for (ulCounter = 0;
1676 ulCounter < cchRead;
1677 ulCounter++,
1678 lpwReadBuffer++)
1679 {
1680 /* @@@PH Ascii -> Unicode translation */
1681 /* write character into cell */
1682 *lpwReadBuffer =
1683 *(pConsoleBuffer->ppszLine[coordReadCoord.Y] +
1684 (coordReadCoord.X * 2));
1685
1686 coordReadCoord.X++; /* move write position */
1687 if (coordReadCoord.X >= pConsoleBuffer->coordBufferSize.X)
1688 {
1689 coordReadCoord.X = 0; /* skip to next line */
1690 coordReadCoord.Y++;
1691
1692 /* oops, we're at the end of the buffer. Abort now. */
1693 if (coordReadCoord.Y >= pConsoleBuffer->coordBufferSize.Y)
1694 {
1695 if (lpcNumberRead != NULL) /* ensure pointer is valid */
1696 *lpcNumberRead = ulCounter;
1697
1698 return (TRUE);
1699 }
1700 }
1701 }
1702
1703 if (lpcNumberRead != NULL) /* ensure pointer is valid */
1704 *lpcNumberRead = cchRead;
1705
1706 return (TRUE);
1707}
1708
1709
1710/*****************************************************************************
1711 * Name : DWORD HMDeviceConsoleBufferClass::ScrollConsoleScreenBufferA
1712 * Purpose : move a block of data within the screen buffer
1713 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
1714 * PSMALL_RECT psrctSourceRect - source rectangle
1715 * PSMALL_RECT psrctClipRect - clipping rectangle
1716 * COORD coordDestOrigin - destination coordinate
1717 * PCHAR_INFO pchiFill - fill character
1718 * Variables :
1719 * Result :
1720 * Remark : Routine is subject to optimizations.
1721 * @@@PH rewrite -> faster, better handling of overlapped buffers
1722 * copy srctSource to buffer, fill it with fill character
1723 * copy buffer to srctDest ?
1724 * Status : UNTESTED
1725 *
1726 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
1727 *****************************************************************************/
1728
1729DWORD HMDeviceConsoleBufferClass::ScrollConsoleScreenBufferA(PHMHANDLEDATA pHMHandleData,
1730 PSMALL_RECT psrctSourceRect,
1731 PSMALL_RECT psrctClipRect,
1732 COORD coordDestOrigin,
1733 PCHAR_INFO pchiFill)
1734{
1735 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
1736 SMALL_RECT srctView; /* the actual rectangle of "happening" */
1737 SMALL_RECT srctSource; /* the clipped source and dest rectangles */
1738 SMALL_RECT srctDest;
1739 int iX, iY; /* scan loop counters */
1740 PUSHORT pusTarget, pusSource; /* pointer to source, dest cells */
1741 WORD wAttr; /* fill character and attribute */
1742 int iBlitDirection; /* to handle overlapped buffers */
1743
1744#ifdef DEBUG_LOCAL2
1745 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::ScrollConsoleScreenBufferA(%08x,%08x,%08x,x=%u y=%u,%08x).\n",
1746 pHMHandleData,
1747 psrctSourceRect,
1748 psrctClipRect,
1749 coordDestOrigin.X,
1750 coordDestOrigin.Y,
1751 pchiFill);
1752#endif
1753
1754 /* calculate effective clipping rectangle */
1755 if (psrctClipRect != NULL) /* if clipping rectangle was specified */
1756 {
1757 memcpy(&srctView,
1758 psrctClipRect,
1759 sizeof (SMALL_RECT) );
1760
1761 /* check boundary with buffer size */
1762 srctView.Left = max(0, srctView.Left);
1763 srctView.Top = max(0, srctView.Top );
1764 srctView.Right = min(srctView.Right, pConsoleBuffer->coordBufferSize.X);
1765 srctView.Bottom = min(srctView.Bottom, pConsoleBuffer->coordBufferSize.Y);
1766 }
1767 else
1768 {
1769 srctView.Left = 0; /* buffer size is the maximum clipping rectangle */
1770 srctView.Top = 0;
1771 srctView.Right = pConsoleBuffer->coordBufferSize.X;
1772 srctView.Bottom = pConsoleBuffer->coordBufferSize.Y;
1773 }
1774
1775 memcpy(&srctSource, /* copy source rectangle */
1776 psrctSourceRect,
1777 sizeof (srctSource) );
1778 /* check boundary with clipping rectangle */
1779 srctSource.Left = max(srctSource.Left, srctView.Left );
1780 srctSource.Top = max(srctSource.Top, srctView.Top );
1781 srctSource.Right = min(srctSource.Right, srctView.Right );
1782 srctSource.Bottom = min(srctSource.Bottom,srctView.Bottom);
1783
1784 srctDest.Left = max(srctView.Left, coordDestOrigin.X);
1785 srctDest.Top = max(srctView.Top, coordDestOrigin.Y);
1786 srctDest.Right = min(srctView.Right, srctDest.Left + srctSource.Right - srctSource.Left);
1787 srctDest.Bottom= min(srctView.Bottom, srctDest.Top + srctSource.Bottom - srctSource.Top);
1788
1789 /****************************
1790 * first copy the rectangle *
1791 ****************************/
1792
1793 if (srctDest.Left > srctSource.Left) iBlitDirection = 0;
1794 else iBlitDirection = 1;
1795 if (srctDest.Top > srctSource.Top) iBlitDirection += 2;
1796
1797 /* this leaves us with three different cases: */
1798 /* */
1799 /* 0 - dest is to upper left of the source */
1800 /* 1 - dest is to upper right of the source */
1801 /* 2 - dest is to lower left of the source */
1802 /* 3 - dest is to lower right of the source */
1803
1804 switch (iBlitDirection)
1805 {
1806 /**************
1807 * upper left *
1808 **************/
1809 case 0:
1810 for (iY = 0;
1811 iY < srctDest.Bottom - srctDest.Top;
1812 iY++)
1813 {
1814 /* calculate pointer to start of target screen line */
1815 pusTarget = (PUSHORT) (pConsoleBuffer->ppszLine[iY + srctDest.Top] +
1816 (srctDest.Left << 1) );
1817
1818 /* calculate pointer to start of source screen line */
1819 pusSource = (PUSHORT) (pConsoleBuffer->ppszLine[iY + srctSource.Top] +
1820 (srctSource.Left << 1) );
1821
1822 for (iX = srctDest.Left;
1823 iX <= srctDest.Right;
1824 iX++,
1825 pusTarget++,
1826 pusSource++)
1827 *pusTarget = *pusSource; /* copy character */
1828 }
1829 break;
1830
1831 /***************
1832 * upper right *
1833 ***************/
1834 case 1:
1835 for (iY = 0;
1836 iY < srctDest.Bottom - srctDest.Top;
1837 iY++)
1838 {
1839 /* calculate pointer to end of target screen line */
1840 pusTarget = (PUSHORT) (pConsoleBuffer->ppszLine[iY + srctDest.Top] +
1841 ( srctDest.Right << 1) );
1842
1843 /* calculate pointer to end of source screen line */
1844 pusSource = (PUSHORT) (pConsoleBuffer->ppszLine[iY + srctSource.Top] +
1845 ( srctSource.Right << 1) );
1846
1847 for (iX = srctDest.Right;
1848 iX >= srctDest.Left;
1849 iX--,
1850 pusTarget--,
1851 pusSource--)
1852 *pusTarget = *pusSource; /* copy character */
1853 }
1854 break;
1855
1856 /***************
1857 * lower left *
1858 ***************/
1859 case 2:
1860 for (iY = srctDest.Bottom - srctDest.Top - 1;
1861 iY >= 0;
1862 iY--)
1863 {
1864 /* calculate pointer to start of target screen line */
1865 pusTarget = (PUSHORT) (pConsoleBuffer->ppszLine[iY + srctDest.Top] +
1866 (srctDest.Left << 1) );
1867
1868 /* calculate pointer to start of source screen line */
1869 pusSource = (PUSHORT) (pConsoleBuffer->ppszLine[iY + srctSource.Top] +
1870 (srctSource.Left << 1) );
1871
1872 for (iX = srctDest.Left;
1873 iX <= srctDest.Right;
1874 iX++,
1875 pusTarget++,
1876 pusSource++)
1877 *pusTarget = *pusSource; /* copy character */
1878 }
1879 break;
1880
1881 /****************
1882 * lower right *
1883 ****************/
1884 case 3:
1885 for (iY = srctDest.Bottom - srctDest.Top - 1;
1886 iY >= 0;
1887 iY--)
1888 {
1889 /* calculate pointer to end of target screen line */
1890 pusTarget = (PUSHORT) (pConsoleBuffer->ppszLine[iY + srctDest.Top] +
1891 ( srctDest.Right << 1) );
1892
1893 /* calculate pointer to end of source screen line */
1894 pusSource = (PUSHORT) (pConsoleBuffer->ppszLine[iY + srctSource.Top] +
1895 (srctSource.Right << 1) );
1896
1897 for (iX = srctDest.Right;
1898 iX >= srctDest.Left;
1899 iX--,
1900 pusTarget--,
1901 pusSource--)
1902 *pusTarget = *pusSource; /* copy character */
1903 }
1904 break;
1905 }
1906
1907
1908 /* this is the character and attribute for the uncovered cells */
1909 wAttr = (pchiFill->Char.AsciiChar) + (pchiFill->Attributes << 8);
1910
1911 for (iY = srctSource.Top; /* now fill uncovered area with pchi */
1912 iY < srctSource.Bottom;
1913 iY++)
1914 {
1915 pusTarget = (PUSHORT) (pConsoleBuffer->ppszLine[iY] + srctSource.Left);
1916
1917 for (iX = srctSource.Left;
1918 iX < srctSource.Right;
1919 iX++,
1920 pusTarget++)
1921 /* check if covered by srctDest or not */
1922 if ( (iY >= srctDest.Top) &&
1923 (iY <= srctDest.Bottom) &&
1924 (iX >= srctDest.Left) &&
1925 (iX <= srctDest.Right)
1926 )
1927 ; /* should be faster for the optimizer */
1928 else
1929 *pusTarget = wAttr; /* write fill character and attribute */
1930 }
1931
1932 /* update screen if active console */
1933 if (pHMHandleData->hHMHandle == pConsoleGlobals->hConsoleBuffer)
1934 pConsoleGlobals->fUpdateRequired = TRUE; /* update with next WM_TIMER */
1935
1936 return (TRUE);
1937}
1938
1939
1940/*****************************************************************************
1941 * Name : DWORD HMDeviceConsoleBufferClass::ScrollConsoleScreenBufferW
1942 * Purpose : move a block of data within the screen buffer
1943
1944
1945 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
1946 * PSMALL_RECT psrctSourceRect - source rectangle
1947 * PSMALL_RECT psrctClipRect - clipping rectangle
1948 * COORD coordDestOrigin - destination coordinate
1949 * PCHAR_INFO pchiFill - fill character
1950 * Variables :
1951 * Result :
1952 * Remark : Routine is subject to optimizations.
1953 * Status : UNTESTED
1954 *
1955 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
1956 *****************************************************************************/
1957
1958DWORD HMDeviceConsoleBufferClass::ScrollConsoleScreenBufferW(PHMHANDLEDATA pHMHandleData,
1959 PSMALL_RECT psrctSourceRect,
1960 PSMALL_RECT psrctClipRect,
1961 COORD coordDestOrigin,
1962 PCHAR_INFO pchiFill)
1963{
1964 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
1965 SMALL_RECT srctView; /* the actual rectangle of "happening" */
1966 SMALL_RECT srctSource; /* the clipped source and dest rectangles */
1967 SMALL_RECT srctDest;
1968 ULONG ulX, ulY; /* scan loop counters */
1969 PUSHORT pusTarget, pusSource; /* pointer to source, dest cells */
1970 WORD wAttr; /* fill character and attribute */
1971
1972#ifdef DEBUG_LOCAL2
1973 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::ScrollConsoleScreenBufferW(%08x,%08x,%08x,x=%u y=%u,%08x).\n",
1974 pHMHandleData,
1975 psrctSourceRect,
1976 psrctClipRect,
1977 coordDestOrigin.X,
1978 coordDestOrigin.Y,
1979 pchiFill);
1980#endif
1981
1982 /* calculate effective clipping rectangle */
1983 if (psrctClipRect != NULL) /* if clipping rectangle was specified */
1984 {
1985 memcpy(&srctView,
1986 psrctClipRect,
1987 sizeof (SMALL_RECT) );
1988
1989 /* check boundary with buffer size */
1990 srctView.Left = max(0, srctView.Left);
1991 srctView.Top = max(0, srctView.Top );
1992 srctView.Right = min(srctView.Right, pConsoleBuffer->coordBufferSize.X);
1993 srctView.Bottom = min(srctView.Bottom, pConsoleBuffer->coordBufferSize.Y);
1994 }
1995 else
1996 {
1997 srctView.Left = 0; /* buffer size is the maximum clipping rectangle */
1998 srctView.Top = 0;
1999 srctView.Right = pConsoleBuffer->coordBufferSize.X;
2000 srctView.Bottom = pConsoleBuffer->coordBufferSize.Y;
2001 }
2002
2003 memcpy(&srctSource, /* copy source rectangle */
2004 psrctSourceRect,
2005 sizeof (srctSource) );
2006 /* check boundary with clipping rectangle */
2007 srctSource.Left = max(srctSource.Left, srctView.Left );
2008 srctSource.Top = max(srctSource.Top, srctView.Top );
2009 srctSource.Right = min(srctSource.Right, srctView.Right );
2010 srctSource.Bottom = min(srctSource.Bottom,srctView.Bottom);
2011
2012 srctDest.Left = max(srctView.Left, coordDestOrigin.X);
2013 srctDest.Top = max(srctView.Top, coordDestOrigin.Y);
2014 srctDest.Right = min(srctView.Right, srctDest.Left + srctSource.Right - srctSource.Left);
2015 srctDest.Bottom= min(srctView.Bottom, srctDest.Top + srctSource.Bottom - srctSource.Top);
2016
2017 /* first copy the rectangle */
2018 for (ulY = 0;
2019 ulY < srctDest.Bottom - srctDest.Top;
2020 ulY++)
2021 {
2022 /* calculate pointer to start of target screen line */
2023 pusTarget = (PUSHORT) (pConsoleBuffer->ppszLine[ulY + srctDest.Top] +
2024 srctDest.Left);
2025
2026 /* calculate pointer to start of source screen line */
2027 pusSource = (PUSHORT) (pConsoleBuffer->ppszLine[ulY + srctSource.Top] +
2028 srctSource.Left);
2029
2030 for (ulX = srctDest.Left;
2031 ulX < srctDest.Right;
2032 ulX++,
2033 pusTarget++,
2034 pusSource++)
2035 *pusTarget = *pusSource; /* copy character */
2036 }
2037
2038
2039 /* this is the character and attribute for the uncovered cells */
2040 /* @@@PH Unicode->Ascii translation */
2041 wAttr = (pchiFill->Char.UnicodeChar) + (pchiFill->Attributes << 8);
2042
2043 for (ulY = srctSource.Top; /* now fill uncovered area with pchi */
2044 ulY < srctSource.Bottom;
2045 ulY++)
2046 {
2047 pusTarget = (PUSHORT) (pConsoleBuffer->ppszLine[ulY] + srctSource.Left);
2048
2049 for (ulX = srctSource.Left;
2050 ulX < srctSource.Right;
2051 ulX++,
2052 pusTarget++)
2053 *pusTarget = wAttr; /* write fill character and attribute */
2054 }
2055
2056 /* update screen if active console */
2057 if (pHMHandleData->hHMHandle == pConsoleGlobals->hConsoleBuffer)
2058 pConsoleGlobals->fUpdateRequired = TRUE; /* update with next WM_TIMER */
2059
2060 return (TRUE);
2061}
2062
2063
2064/*****************************************************************************
2065 * Name : DWORD HMDeviceConsoleBufferClass::SetConsoleCursorInfo
2066 * Purpose : sets the current console's cursor information
2067 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
2068 * PCONSOLE_CURSOR_INFO pCCI
2069 * Variables :
2070 * Result :
2071 * Remark :
2072 * Status : UNTESTED
2073 *
2074 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
2075 *****************************************************************************/
2076
2077DWORD HMDeviceConsoleBufferClass::SetConsoleCursorInfo(PHMHANDLEDATA pHMHandleData,
2078 PCONSOLE_CURSOR_INFO pCCI)
2079{
2080 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
2081
2082#ifdef DEBUG_LOCAL2
2083 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::SetConsoleCursorInfo(%08x,%08x).\n",
2084 pHMHandleData,
2085 pCCI);
2086#endif
2087
2088 /* validate structure */
2089 if ( (pCCI->dwSize < 1) ||
2090 (pCCI->dwSize > 100) )
2091 {
2092 SetLastError(ERROR_INVALID_PARAMETER); /* set extended error info */
2093 return (FALSE); /* API failed */
2094 }
2095
2096 /* if we're the active buffer, remove cursor from screen first */
2097 if (pHMHandleData->hHMHandle == pConsoleGlobals->hConsoleBuffer)
2098 iConsoleCursorShow(pConsoleBuffer,
2099 CONSOLECURSOR_HIDE);
2100
2101 memcpy(&pConsoleBuffer->CursorInfo, /* copy the whole information block */
2102 pCCI,
2103 sizeof (pConsoleBuffer->CursorInfo) );
2104
2105 return (TRUE);
2106}
2107
2108
2109/*****************************************************************************
2110 * Name : DWORD HMDeviceConsoleBufferClass::SetConsoleCursorPosition
2111 * Purpose : sets the current console's cursor position
2112 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
2113 * COORD coordCursorPosition
2114 * Variables :
2115 * Result :
2116 * Remark :
2117 * Status : UNTESTED
2118 *
2119 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
2120 *****************************************************************************/
2121
2122DWORD HMDeviceConsoleBufferClass::SetConsoleCursorPosition(PHMHANDLEDATA pHMHandleData,
2123 COORD coordCursorPosition)
2124{
2125 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
2126
2127#ifdef DEBUG_LOCAL2
2128 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::SetConsoleCursorPosition(%08x,x=%u.y=%u).\n",
2129 pHMHandleData,
2130 coordCursorPosition.X,
2131 coordCursorPosition.Y);
2132#endif
2133
2134 /* @@@PH remove cursor from screen first ! */
2135 pConsoleBuffer->coordCursorPosition = coordCursorPosition;
2136
2137 return (TRUE);
2138}
2139
2140
2141/*****************************************************************************
2142 * Name : DWORD HMDeviceConsoleBufferClass::SetConsoleMode
2143 * Purpose : sets the current console mode
2144 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
2145 * DWORD dwMode - console mode
2146 * Variables :
2147 * Result :
2148 * Remark :
2149 * Status : UNTESTED
2150 *
2151 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
2152 *****************************************************************************/
2153
2154DWORD HMDeviceConsoleBufferClass::SetConsoleMode(PHMHANDLEDATA pHMHandleData,
2155 DWORD dwMode)
2156{
2157 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
2158
2159#ifdef DEBUG_LOCAL2
2160 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::SetConsoleMode(%08x,%08x).\n",
2161 pHMHandleData,
2162 dwMode);
2163#endif
2164
2165 pConsoleBuffer->dwConsoleMode = dwMode; /* set current console mode */
2166
2167 return (TRUE);
2168}
2169
2170
2171/*****************************************************************************
2172 * Name : DWORD HMDeviceConsoleBufferClass::SetConsoleScreenBufferSize
2173 * Purpose : allocate or re-allocate the screenbuffer and transform the
2174 * old buffer as required
2175 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
2176 * COORD coordSize - the new buffer size
2177 * Variables :
2178 * Result :
2179 * Remark :
2180 * Status : UNTESTED
2181 *
2182 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
2183 *****************************************************************************/
2184
2185DWORD HMDeviceConsoleBufferClass::SetConsoleScreenBufferSize (PHMHANDLEDATA pHMHandleData,
2186 COORD coordSize)
2187{
2188 ULONG ulSize; /* calculated size of the new buffer */
2189 PSZ *ppszNew; /* pointer to the new array */
2190 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
2191 ULONG ulLine; /* line index counter */
2192
2193#ifdef DEBUG_LOCAL2
2194 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::SetConsoleScreenBufferSize(%u,%u).\n",
2195 coordSize.X,
2196 coordSize.Y);
2197#endif
2198
2199
2200 /* re-allocate the whole line-pointer array */
2201 ulSize = coordSize.Y * (coordSize.X * 2 + sizeof (PSZ) );
2202 if (ulSize == 0) /* set new buffer size to zero ? */
2203 {
2204 if (pConsoleBuffer->ppszLine != NULL) /* if old buffer is present */
2205 free (pConsoleBuffer->ppszLine); /* free old buffer */
2206
2207 pConsoleBuffer->ppszLine = NULL;
2208 pConsoleBuffer->coordBufferSize.X = 0;
2209 pConsoleBuffer->coordBufferSize.Y = 0;
2210 pConsoleBuffer->coordWindowSize.X = 0;
2211 pConsoleBuffer->coordWindowSize.Y = 0;
2212 pConsoleBuffer->coordWindowPosition.X = 0;
2213 pConsoleBuffer->coordWindowPosition.Y = 0;
2214
2215 return (TRUE); /* OK */
2216 }
2217
2218
2219 ppszNew = (PSZ *) malloc(ulSize); /* allocate array */
2220 if (ppszNew == NULL) /* check proper allocation */
2221 {
2222 SetLastError(ERROR_NOT_ENOUGH_MEMORY); /* set error information */
2223 return (FALSE); /* raise error condition */
2224 }
2225
2226
2227 for (ulLine = 0; /* setup line pointer array */
2228 ulLine < coordSize.Y;
2229 ulLine++)
2230 {
2231 /* calculate line pointer */
2232 ulSize = (ULONG)ppszNew + (coordSize.Y * sizeof(PSZ) )
2233 + (coordSize.X * ulLine * 2);
2234 ppszNew[ulLine] = (PSZ)ulSize; /* OK, write index pointer */
2235 }
2236
2237 ulSize = ( ((ULONG)(pConsoleBuffer->ucDefaultAttribute) << 8) +
2238 ((ULONG)' ') +
2239 ((ULONG)(pConsoleBuffer->ucDefaultAttribute) << 24) +
2240 ((ULONG)' ' << 16) );
2241
2242 /* scroll the line index */
2243 for (ulLine = 0;
2244 ulLine < coordSize.Y;
2245 ulLine++)
2246 iConsoleBufferFillLine(ulSize,
2247 (PUSHORT)(ppszNew[ulLine]),
2248 coordSize.X);
2249
2250
2251
2252 /* copy lines as required */
2253 if (pConsoleBuffer->ppszLine != NULL) /* previous buffer present ? */
2254 {
2255 ULONG x, y;
2256
2257 /* copy old characters as required */
2258 x = min(pConsoleBuffer->coordBufferSize.X, coordSize.X);
2259 y = min(pConsoleBuffer->coordBufferSize.Y, coordSize.Y);
2260
2261 for (ulLine = 0; /* copy line by line */
2262 ulLine < y;
2263 ulLine++)
2264 memcpy(ppszNew[ulLine],
2265 pConsoleBuffer->ppszLine[ulLine],
2266 x * 2);
2267
2268 free (pConsoleBuffer->ppszLine); /* free previous screen buffer array */
2269 }
2270
2271
2272 pConsoleBuffer->ppszLine = ppszNew; /* poke in the new values */
2273 pConsoleBuffer->coordBufferSize.X = coordSize.X;
2274 pConsoleBuffer->coordBufferSize.Y = coordSize.Y;
2275 pConsoleBuffer->coordCursorPosition.X = 0;
2276 pConsoleBuffer->coordCursorPosition.Y = 0;
2277
2278 /* @@@PH to be changed ! */
2279 pConsoleBuffer->coordWindowSize.X = coordSize.X; /* default */
2280 pConsoleBuffer->coordWindowSize.Y = coordSize.Y;
2281 pConsoleBuffer->coordWindowPosition.X = 0;
2282 pConsoleBuffer->coordWindowPosition.Y = 0;
2283
2284 /* update screen if active console */
2285 if (pHMHandleData->hHMHandle == pConsoleGlobals->hConsoleBuffer)
2286 pConsoleGlobals->fUpdateRequired = TRUE; /* update with next WM_TIMER */
2287
2288 return TRUE;
2289}
2290
2291
2292/*****************************************************************************
2293 * Name :
2294 * Purpose :
2295 * Parameters:
2296 * Variables :
2297 * Result :
2298 * Remark :
2299 * Status :
2300 *
2301 * Author : Patrick Haller [Tue, 1998/02/10 01:55]
2302 *****************************************************************************/
2303
2304DWORD HMDeviceConsoleBufferClass::SetConsoleTextAttribute(PHMHANDLEDATA pHMHandleData,
2305 WORD wAttr)
2306{
2307 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
2308
2309#ifdef DEBUG_LOCAL2
2310 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::SetConsoleTextAttribute(%u).\n",
2311 wAttr);
2312#endif
2313
2314 pConsoleBuffer->ucDefaultAttribute = (UCHAR)wAttr;
2315 return (TRUE);
2316}
2317
2318
2319/*****************************************************************************
2320 * Name :
2321 * Purpose :
2322 * Parameters:
2323 * Variables :
2324 * Result :
2325 * Remark :
2326 * Status :
2327 *
2328 * Author : Patrick Haller [Tue, 1998/02/10 01:55]
2329 *****************************************************************************/
2330
2331DWORD HMDeviceConsoleBufferClass::SetConsoleActiveScreenBuffer(PHMHANDLEDATA pHMHandleData)
2332{
2333 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
2334
2335#ifdef DEBUG_LOCAL
2336 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::SetConsoleActiveScreenBuffer().\n");
2337#endif
2338
2339 /* set new buffer handle to the global console */
2340 pConsoleGlobals->hConsoleBuffer = pHMHandleData->hHMHandle;
2341 pConsoleGlobals->fUpdateRequired = TRUE; /* update with next WM_TIMER */
2342
2343 return (TRUE);
2344}
2345
2346
2347/*****************************************************************************
2348 * Name : BOOL HMDeviceConsoleBufferClass::SetConsoleWindowInfo
2349 * Purpose : set a new size to the console window
2350 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
2351 * BOOL fAbsolute
2352 * PSMALL_RECT psrctWindowRect
2353 * Variables :
2354 * Result :
2355 * Remark :
2356 * Status : UNTESTED
2357 *
2358 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
2359 *****************************************************************************/
2360
2361BOOL HMDeviceConsoleBufferClass::SetConsoleWindowInfo(PHMHANDLEDATA pHMHandleData,
2362 BOOL fAbsolute,
2363 PSMALL_RECT psrctWindowRect)
2364{
2365 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
2366
2367#ifdef DEBUG_LOCAL2
2368 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::SetConsoleWindowInfo(%08x,%u,%08x).\n",
2369 pHMHandleData,
2370 fAbsolute,
2371 psrctWindowRect);
2372#endif
2373
2374 if (fAbsolute == TRUE) /* absolute coordinates provided ? */
2375 {
2376 if ( (psrctWindowRect->Left < 0) || /* check parameters first */
2377 (psrctWindowRect->Top < 0) ||
2378 (psrctWindowRect->Right < 0) ||
2379 (psrctWindowRect->Bottom < 0) ||
2380 (psrctWindowRect->Right <= psrctWindowRect->Left) ||
2381 (psrctWindowRect->Bottom <= psrctWindowRect->Top)
2382 )
2383 {
2384 SetLastError(ERROR_INVALID_PARAMETER); /* set error information */
2385 return (FALSE); /* error */
2386 }
2387
2388 /* check we don't go beyond screen buffer ! */
2389 if ( ((psrctWindowRect->Right - psrctWindowRect->Left) > pConsoleBuffer->coordBufferSize.X) ||
2390 ((psrctWindowRect->Bottom - psrctWindowRect->Top ) > pConsoleBuffer->coordBufferSize.Y) ||
2391 (psrctWindowRect->Left >= pConsoleBuffer->coordBufferSize.X) ||
2392 (psrctWindowRect->Top >= pConsoleBuffer->coordBufferSize.Y)
2393 )
2394 {
2395 SetLastError(ERROR_INVALID_PARAMETER); /* set error information */
2396 return (FALSE); /* error */
2397 }
2398
2399 pConsoleBuffer->coordWindowSize.X = psrctWindowRect->Right -
2400 psrctWindowRect->Left;
2401 pConsoleBuffer->coordWindowSize.Y = psrctWindowRect->Bottom -
2402 psrctWindowRect->Top;
2403
2404 pConsoleBuffer->coordWindowPosition.X = psrctWindowRect->Left;
2405 pConsoleBuffer->coordWindowPosition.Y = psrctWindowRect->Top;
2406 }
2407 else
2408 {
2409 int iSizeX; /* relative coordinates */
2410 int iSizeY;
2411 int iPosX;
2412 int iPosY;
2413
2414 iSizeX = pConsoleBuffer->coordWindowSize.X + psrctWindowRect->Left + psrctWindowRect->Right;
2415 iSizeY = pConsoleBuffer->coordWindowSize.Y + psrctWindowRect->Top + psrctWindowRect->Bottom;
2416 iPosX = pConsoleBuffer->coordWindowPosition.X + psrctWindowRect->Left;
2417 iPosY = pConsoleBuffer->coordWindowPosition.Y + psrctWindowRect->Top;
2418
2419 /* check we don't go beyond screen buffer ! */
2420 if ( (iSizeX > pConsoleBuffer->coordBufferSize.X) ||
2421 (iSizeY > pConsoleBuffer->coordBufferSize.Y) ||
2422 (iPosX >= pConsoleBuffer->coordBufferSize.X) ||
2423 (iPosY >= pConsoleBuffer->coordBufferSize.Y) ||
2424 (iSizeX < 0) ||
2425 (iSizeY < 0) ||
2426 (iPosX < 0) ||
2427 (iPosY < 0)
2428 )
2429 {
2430 SetLastError(ERROR_INVALID_PARAMETER); /* set error information */
2431 return (FALSE); /* error */
2432 }
2433
2434 /* Values are verified for being OK ! */
2435 pConsoleBuffer->coordWindowPosition.X = iPosX;
2436 pConsoleBuffer->coordWindowPosition.Y = iPosY;
2437 pConsoleBuffer->coordWindowSize.X = iSizeX;
2438 pConsoleBuffer->coordWindowSize.Y = iSizeY;
2439 }
2440
2441 /* update window */
2442 /* @@@PH
2443
2444 ConsoleWindowResize(COORD coordWindowSize,
2445 COORD coordWindowPos,
2446
2447 */
2448
2449 /* update window contents (scroll) */
2450 /* update screen if active console */
2451 if (pHMHandleData->hHMHandle == pConsoleGlobals->hConsoleBuffer)
2452 pConsoleGlobals->fUpdateRequired = TRUE; /* update with next WM_TIMER */
2453
2454 return (TRUE); /* OK */
2455}
2456
2457
2458/*****************************************************************************
2459 * Name : DWORD HMDeviceConsoleBufferClass::WriteConsoleA
2460 * Purpose : write a string to the console
2461 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
2462 * LPWORD lpwAttribute
2463 * DWORD cWriteCells
2464 * COORD dwWriteCoord
2465 * LPDWORD lpcWritten
2466 * Variables :
2467 * Result :
2468 * Remark :
2469 * Status : UNTESTED
2470 *
2471 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
2472 *****************************************************************************/
2473
2474DWORD HMDeviceConsoleBufferClass::WriteConsoleA(PHMHANDLEDATA pHMHandleData,
2475 CONST VOID* lpvBuffer,
2476 DWORD cchToWrite,
2477 LPDWORD lpcchWritten,
2478 LPVOID lpvReserved)
2479{
2480 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
2481
2482#ifdef DEBUG_LOCAL2
2483 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::WriteConsoleA(%08x,%08x,%u,%08x,%08x).\n",
2484 pHMHandleData,
2485 lpvBuffer,
2486 cchToWrite,
2487 lpcchWritten,
2488 lpvReserved);
2489#endif
2490
2491 /* simply forward the request to that routine */
2492 return (HMDeviceConsoleBufferClass::WriteFile(pHMHandleData,
2493 lpvBuffer,
2494 cchToWrite,
2495 lpcchWritten,
2496 NULL));
2497}
2498
2499
2500/*****************************************************************************
2501 * Name : DWORD HMDeviceConsoleBufferClass::WriteConsoleW
2502 * Purpose : write a string to the console
2503 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
2504 * LPWORD lpwAttribute
2505 * DWORD cWriteCells
2506 * COORD dwWriteCoord
2507 * LPDWORD lpcWritten
2508 * Variables :
2509 * Result :
2510 * Remark :
2511 * Status : UNTESTED
2512 *
2513 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
2514 *****************************************************************************/
2515
2516DWORD HMDeviceConsoleBufferClass::WriteConsoleW(PHMHANDLEDATA pHMHandleData,
2517 CONST VOID* lpvBuffer,
2518 DWORD cchToWrite,
2519 LPDWORD lpcchWritten,
2520 LPVOID lpvReserved)
2521{
2522 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
2523
2524#ifdef DEBUG_LOCAL2
2525 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::WriteConsoleW(%08x,%08x,%u,%08x,%08x).\n",
2526 pHMHandleData,
2527 lpvBuffer,
2528 cchToWrite,
2529 lpcchWritten,
2530 lpvReserved);
2531#endif
2532
2533 /* @@@PH AScii -> unicode translation */
2534
2535 /* simply forward the request to that routine */
2536 return (HMDeviceConsoleBufferClass::WriteFile(pHMHandleData,
2537 lpvBuffer,
2538 cchToWrite,
2539 lpcchWritten,
2540 NULL));
2541}
2542
2543
2544/*****************************************************************************
2545 * Name : DWORD HMDeviceConsoleBufferClass::WriteConsoleOutputA
2546 * Purpose : write character and color attribute data to screen rectangle
2547 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
2548 * PCHAR_INFO pchiSrcBuffer
2549 * COORD coordSrcBufferSize
2550 * COORD coordSrcBufferCoord
2551 * PSMALL_RECT psrctDestRect
2552 * Variables :
2553 * Result :
2554 * Remark :
2555 * Status : UNTESTED
2556 *
2557 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
2558 *****************************************************************************/
2559
2560DWORD HMDeviceConsoleBufferClass::WriteConsoleOutputA(PHMHANDLEDATA pHMHandleData,
2561 PCHAR_INFO pchiSrcBuffer,
2562 COORD coordSrcBufferSize,
2563 COORD coordSrcBufferCoord,
2564 PSMALL_RECT psrctDestRect)
2565{
2566 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
2567 ULONG ulX, ulY; /* current coordinate to be read */
2568 ULONG ulCX, ulCY; /* width and height of target area */
2569 ULONG ulWriteX, ulWriteY; /* position data is read from */
2570 WORD wCell; /* currently read data */
2571
2572 PCHAR_INFO pchi;
2573 PSZ pszTarget;
2574
2575#ifdef DEBUG_LOCAL2
2576 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::WriteConsoleOutputA(%08x,%08x,x=%u y=%u,x=%u y=%u, %08x).\n",
2577 pHMHandleData,
2578 pchiSrcBuffer,
2579 coordSrcBufferSize.X,
2580 coordSrcBufferSize.Y,
2581 coordSrcBufferCoord.X,
2582 coordSrcBufferCoord.Y,
2583 psrctDestRect);
2584#endif
2585
2586
2587 /* verify psrctDestRect first */
2588 psrctDestRect->Left = max(psrctDestRect->Left, 0);
2589 psrctDestRect->Top = max(psrctDestRect->Top, 0);
2590 psrctDestRect->Right = min(psrctDestRect->Right, pConsoleBuffer->coordBufferSize.X - 1);
2591 psrctDestRect->Bottom= min(psrctDestRect->Bottom,pConsoleBuffer->coordBufferSize.Y - 1);
2592
2593 /* verify target buffer */
2594 if ( (coordSrcBufferSize.X < coordSrcBufferCoord.X) ||
2595 (coordSrcBufferSize.Y < coordSrcBufferCoord.Y) )
2596 {
2597 SetLastError(ERROR_INVALID_PARAMETER); /* set detailed error info */
2598 return (FALSE); /* API failed */
2599 }
2600
2601 ulCX = coordSrcBufferSize.X - coordSrcBufferCoord.X;
2602 ulCY = coordSrcBufferSize.Y - coordSrcBufferCoord.Y;
2603
2604 ulCX = min(ulCX, (psrctDestRect->Right - psrctDestRect->Left));
2605 ulCY = min(ulCY, (psrctDestRect->Bottom - psrctDestRect->Top));
2606
2607 /* final calculation of the copy rectangle */
2608 psrctDestRect->Right = psrctDestRect->Left + ulCX;
2609 psrctDestRect->Bottom = psrctDestRect->Top + ulCY;
2610
2611
2612 for (ulY = 0,
2613 ulWriteY = psrctDestRect->Top;
2614
2615 ulY <= ulCY;
2616
2617 ulY++,
2618 ulWriteY++)
2619 {
2620 pchi = pchiSrcBuffer + sizeof(CHAR_INFO) * coordSrcBufferCoord.X
2621 + sizeof(CHAR_INFO) * (coordSrcBufferCoord.Y + ulY)
2622 * coordSrcBufferSize.X;
2623
2624 /* calculate pointer to start of screen line */
2625 pszTarget = pConsoleBuffer->ppszLine[ulWriteY] + psrctDestRect->Left;
2626
2627 for (ulX = 0,
2628 ulWriteX = psrctDestRect->Left;
2629
2630 ulX <= ulCX;
2631
2632 ulX++,
2633 ulWriteX++,
2634 pchi++)
2635 {
2636 /* write character and attribute */
2637 *pszTarget++ = (UCHAR)pchi->Char.AsciiChar;
2638 *pszTarget++ = (UCHAR)pchi->Attributes;
2639 }
2640 }
2641
2642 /* update screen if active console */
2643 if (pHMHandleData->hHMHandle == pConsoleGlobals->hConsoleBuffer)
2644 pConsoleGlobals->fUpdateRequired = TRUE; /* update with next WM_TIMER */
2645
2646 return (TRUE); /* OK, that's it */
2647}
2648
2649
2650/*****************************************************************************
2651 * Name : DWORD HMDeviceConsoleBufferClass::WriteConsoleOutputW
2652 * Purpose : write character and color attribute data to screen rectangle
2653 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
2654 * PCHAR_INFO pchiSrcBuffer
2655 * COORD coordSrcBufferSize
2656 * COORD coordSrcBufferCoord
2657 * PSMALL_RECT psrctDestRect
2658 * Variables :
2659 * Result :
2660 * Remark :
2661 * Status : UNTESTED
2662 *
2663 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
2664 *****************************************************************************/
2665
2666DWORD HMDeviceConsoleBufferClass::WriteConsoleOutputW(PHMHANDLEDATA pHMHandleData,
2667 PCHAR_INFO pchiSrcBuffer,
2668 COORD coordSrcBufferSize,
2669 COORD coordSrcBufferCoord,
2670 PSMALL_RECT psrctDestRect)
2671{
2672 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
2673 ULONG ulX, ulY; /* current coordinate to be read */
2674 ULONG ulCX, ulCY; /* width and height of target area */
2675 ULONG ulWriteX, ulWriteY; /* position data is read from */
2676 WORD wCell; /* currently read data */
2677
2678 PCHAR_INFO pchi;
2679 PSZ pszTarget;
2680
2681#ifdef DEBUG_LOCAL2
2682 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::WriteConsoleOutputW(%08x,%08x,x=%u y=%u,x=%u y=%u, %08x).\n",
2683 pHMHandleData,
2684 pchiSrcBuffer,
2685 coordSrcBufferSize.X,
2686 coordSrcBufferSize.Y,
2687 coordSrcBufferCoord.X,
2688 coordSrcBufferCoord.Y,
2689 psrctDestRect);
2690#endif
2691
2692
2693 /* verify psrctDestRect first */
2694 psrctDestRect->Left = max(psrctDestRect->Left, 0);
2695 psrctDestRect->Top = max(psrctDestRect->Top, 0);
2696 psrctDestRect->Right = min(psrctDestRect->Right, pConsoleBuffer->coordBufferSize.X - 1);
2697 psrctDestRect->Bottom= min(psrctDestRect->Bottom,pConsoleBuffer->coordBufferSize.Y - 1);
2698
2699 /* verify target buffer */
2700 if ( (coordSrcBufferSize.X < coordSrcBufferCoord.X) ||
2701 (coordSrcBufferSize.Y < coordSrcBufferCoord.Y) )
2702 {
2703 SetLastError(ERROR_INVALID_PARAMETER); /* set detailed error info */
2704 return (FALSE); /* API failed */
2705 }
2706
2707 ulCX = coordSrcBufferSize.X - coordSrcBufferCoord.X;
2708 ulCY = coordSrcBufferSize.Y - coordSrcBufferCoord.Y;
2709
2710 ulCX = min(ulCX, (psrctDestRect->Right - psrctDestRect->Left));
2711 ulCY = min(ulCY, (psrctDestRect->Bottom - psrctDestRect->Top));
2712
2713 /* final calculation of the copy rectangle */
2714 psrctDestRect->Right = psrctDestRect->Left + ulCX;
2715 psrctDestRect->Bottom = psrctDestRect->Top + ulCY;
2716
2717
2718 for (ulY = 0,
2719 ulWriteY = psrctDestRect->Top;
2720
2721 ulY <= ulCY;
2722
2723 ulY++,
2724 ulWriteY++)
2725 {
2726 pchi = pchiSrcBuffer + sizeof(CHAR_INFO) * coordSrcBufferCoord.X
2727 + sizeof(CHAR_INFO) * (coordSrcBufferCoord.Y + ulY)
2728 * coordSrcBufferSize.X;
2729
2730 /* calculate pointer to start of screen line */
2731 pszTarget = pConsoleBuffer->ppszLine[ulWriteY] + psrctDestRect->Left;
2732
2733 for (ulX = 0,
2734 ulWriteX = psrctDestRect->Left;
2735
2736 ulX <= ulCX;
2737
2738 ulX++,
2739 ulWriteX++,
2740 pchi++)
2741 {
2742 /* write character and attribute */
2743 *pszTarget++ = (UCHAR)pchi->Char.UnicodeChar; /* @@@PH unicode->ascii */
2744 *pszTarget++ = (UCHAR)pchi->Attributes;
2745 }
2746 }
2747
2748 /* update screen if active console */
2749 if (pHMHandleData->hHMHandle == pConsoleGlobals->hConsoleBuffer)
2750 pConsoleGlobals->fUpdateRequired = TRUE; /* update with next WM_TIMER */
2751
2752 return (TRUE); /* OK, that's it */
2753}
2754
2755
2756/*****************************************************************************
2757 * Name : DWORD HMDeviceConsoleBufferClass::WriteConsoleOutputAttribute
2758 * Purpose : write an array with specified attributes to the console
2759 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
2760 * LPWORD lpwAttribute
2761 * DWORD cWriteCells
2762 * COORD dwWriteCoord
2763 * LPDWORD lpcWritten
2764 * Variables :
2765 * Result :
2766 * Remark :
2767 * Status : UNTESTED
2768 *
2769 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
2770 *****************************************************************************/
2771
2772DWORD HMDeviceConsoleBufferClass::WriteConsoleOutputAttribute(PHMHANDLEDATA pHMHandleData,
2773 LPWORD lpwAttribute,
2774 DWORD cWriteCells,
2775 COORD dwWriteCoord,
2776 LPDWORD lpcWritten)
2777{
2778 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
2779 ULONG ulCounter; /* current character counter */
2780
2781#ifdef DEBUG_LOCAL2
2782 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::WriteConsoleOutputAttribute(%08x,pattr=%08x,%u,x=%u y=%u,res=%08x).\n",
2783 pHMHandleData,
2784 lpwAttribute,
2785
2786
2787 cWriteCells,
2788 dwWriteCoord.X,
2789 dwWriteCoord.Y,
2790 lpcWritten);
2791#endif
2792
2793 if ( (dwWriteCoord.X < 0) ||
2794 (dwWriteCoord.Y < 0) )
2795 {
2796 if (lpcWritten != NULL) /* ensure pointer is valid */
2797 *lpcWritten = 0; /* complete error handling */
2798
2799 SetLastError(ERROR_INVALID_PARAMETER);
2800 return (FALSE);
2801 }
2802
2803 /* check if dwWriteCoord is within specs */
2804 if ( (dwWriteCoord.X >= pConsoleBuffer->coordBufferSize.X) ||
2805 (dwWriteCoord.Y >= pConsoleBuffer->coordBufferSize.Y) )
2806 {
2807 if (lpcWritten != NULL) /* ensure pointer is valid */
2808 *lpcWritten = 0; /* complete error handling */
2809
2810 SetLastError(ERROR_INVALID_PARAMETER);
2811 return (FALSE);
2812 }
2813
2814
2815 /* OK, now write the attribute lines */
2816 for (ulCounter = 0;
2817 ulCounter < cWriteCells;
2818 ulCounter++,
2819 lpwAttribute++)
2820 {
2821 /* write attribute into cell */
2822 *(pConsoleBuffer->ppszLine[dwWriteCoord.Y] +
2823 (dwWriteCoord.X * 2 + 1)
2824 ) = (UCHAR)*lpwAttribute; /* write attribute and skip to next */
2825
2826 dwWriteCoord.X++; /* move write position */
2827 if (dwWriteCoord.X >= pConsoleBuffer->coordBufferSize.X)
2828 {
2829 dwWriteCoord.X = 0; /* skip to next line */
2830 dwWriteCoord.Y++;
2831
2832 /* oops, we're at the end of the buffer. Abort now. */
2833 if (dwWriteCoord.Y >= pConsoleBuffer->coordBufferSize.Y)
2834 {
2835 if (lpcWritten != NULL) /* ensure pointer is valid */
2836 *lpcWritten = ulCounter;
2837
2838 /* update screen if active console */
2839 if (pHMHandleData->hHMHandle == pConsoleGlobals->hConsoleBuffer)
2840 pConsoleGlobals->fUpdateRequired = TRUE;/* update with next WM_TIMER */
2841
2842 return (TRUE);
2843 }
2844 }
2845 }
2846
2847 /* update screen if active console */
2848 if (pHMHandleData->hHMHandle == pConsoleGlobals->hConsoleBuffer)
2849 pConsoleGlobals->fUpdateRequired = TRUE; /* update with next WM_TIMER */
2850
2851 if (lpcWritten != NULL) /* ensure pointer is valid */
2852 *lpcWritten = cWriteCells;
2853
2854 return (TRUE);
2855}
2856
2857
2858/*****************************************************************************
2859 * Name : DWORD HMDeviceConsoleBufferClass::WriteConsoleOutputCharacterA
2860 * Purpose : fills the console buffer with a specified attribute
2861 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
2862 * LPTSTR lpWriteBuffer
2863 * DWORD cchWrite
2864 * COORD dwWriteCoord
2865 * LPDWORD lpcWritten
2866 * Variables :
2867 * Result :
2868 * Remark :
2869 * Status : UNTESTED
2870 *
2871 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
2872 *****************************************************************************/
2873
2874DWORD HMDeviceConsoleBufferClass::WriteConsoleOutputCharacterA(PHMHANDLEDATA pHMHandleData,
2875 LPTSTR lpWriteBuffer,
2876 DWORD cchWrite,
2877 COORD dwWriteCoord,
2878 LPDWORD lpcWritten)
2879{
2880 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
2881 ULONG ulCounter; /* current character counter */
2882
2883#ifdef DEBUG_LOCAL2
2884 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::WriteConsoleOutputCharacterA(%08x,pstr=%08x,%u,x=%u y=%u,res=%08x).\n",
2885 pHMHandleData,
2886 lpWriteBuffer,
2887 cchWrite,
2888 dwWriteCoord.X,
2889 dwWriteCoord.Y,
2890 lpcWritten);
2891#endif
2892
2893 if ( (dwWriteCoord.X < 0) ||
2894 (dwWriteCoord.Y < 0) )
2895 {
2896 if (lpcWritten != NULL) /* ensure pointer is valid */
2897 *lpcWritten = 0; /* complete error handling */
2898
2899 SetLastError(ERROR_INVALID_PARAMETER);
2900 return (FALSE);
2901 }
2902
2903 /* check if dwWriteCoord is within specs */
2904 if ( (dwWriteCoord.X >= pConsoleBuffer->coordBufferSize.X) ||
2905 (dwWriteCoord.Y >= pConsoleBuffer->coordBufferSize.Y) )
2906 {
2907 if (lpcWritten != NULL) /* ensure pointer is valid */
2908 *lpcWritten = 0; /* complete error handling */
2909
2910 SetLastError(ERROR_INVALID_PARAMETER);
2911 return (FALSE);
2912 }
2913
2914
2915 /* OK, now write the character lines */
2916 for (ulCounter = 0;
2917 ulCounter < cchWrite;
2918 ulCounter++,
2919 lpWriteBuffer++)
2920 {
2921 /* write character into cell */
2922 *(pConsoleBuffer->ppszLine[dwWriteCoord.Y] +
2923 (dwWriteCoord.X * 2)
2924 ) = (UCHAR)*lpWriteBuffer; /* write character and skip to next */
2925
2926 dwWriteCoord.X++; /* move write position */
2927 if (dwWriteCoord.X >= pConsoleBuffer->coordBufferSize.X)
2928 {
2929 dwWriteCoord.X = 0; /* skip to next line */
2930 dwWriteCoord.Y++;
2931
2932 /* oops, we're at the end of the buffer. Abort now. */
2933 if (dwWriteCoord.Y >= pConsoleBuffer->coordBufferSize.Y)
2934 {
2935 if (lpcWritten != NULL) /* ensure pointer is valid */
2936 *lpcWritten = ulCounter;
2937
2938 /* update screen if active console */
2939 if (pHMHandleData->hHMHandle == pConsoleGlobals->hConsoleBuffer)
2940 pConsoleGlobals->fUpdateRequired = TRUE;/* update with next WM_TIMER */
2941
2942 return (TRUE);
2943 }
2944 }
2945 }
2946
2947 /* update screen if active console */
2948 if (pHMHandleData->hHMHandle == pConsoleGlobals->hConsoleBuffer)
2949 pConsoleGlobals->fUpdateRequired = TRUE; /* update with next WM_TIMER */
2950
2951 if (lpcWritten != NULL) /* ensure pointer is valid */
2952 *lpcWritten = cchWrite;
2953
2954 return (TRUE);
2955}
2956
2957
2958/*****************************************************************************
2959 * Name : DWORD HMDeviceConsoleBufferClass::WriteConsoleOutputCharacterW
2960 * Purpose : fills the console buffer with a specified attribute
2961 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
2962 * LPWSTR lpWriteBuffer
2963 * DWORD cchWrite
2964 * COORD dwWriteCoord
2965 * LPDWORD lpcWritten
2966 * Variables :
2967 * Result :
2968 * Remark :
2969 * Status : UNTESTED
2970 *
2971 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
2972 *****************************************************************************/
2973
2974DWORD HMDeviceConsoleBufferClass::WriteConsoleOutputCharacterW(PHMHANDLEDATA pHMHandleData,
2975 LPWSTR lpWriteBuffer,
2976 DWORD cchWrite,
2977 COORD dwWriteCoord,
2978 LPDWORD lpcWritten)
2979{
2980 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
2981 ULONG ulCounter; /* current character counter */
2982
2983#ifdef DEBUG_LOCAL2
2984 WriteLog("KERNEL32/CONSOLE: CONBUFFER$::WriteConsoleOutputCharacterW(%08x,pstr=%08x,%u,x=%u y=%u,res=%08x).\n",
2985 pHMHandleData,
2986 lpWriteBuffer,
2987 cchWrite,
2988 dwWriteCoord.X,
2989 dwWriteCoord.Y,
2990 lpcWritten);
2991#endif
2992
2993 if ( (dwWriteCoord.X < 0) ||
2994 (dwWriteCoord.Y < 0) )
2995 {
2996 if (lpcWritten != NULL) /* ensure pointer is valid */
2997 *lpcWritten = 0; /* complete error handling */
2998
2999 SetLastError(ERROR_INVALID_PARAMETER);
3000 return (FALSE);
3001 }
3002
3003 /* check if dwWriteCoord is within specs */
3004 if ( (dwWriteCoord.X >= pConsoleBuffer->coordBufferSize.X) ||
3005 (dwWriteCoord.Y >= pConsoleBuffer->coordBufferSize.Y) )
3006 {
3007 if (lpcWritten != NULL) /* ensure pointer is valid */
3008 *lpcWritten = 0; /* complete error handling */
3009
3010 SetLastError(ERROR_INVALID_PARAMETER);
3011 return (FALSE);
3012 }
3013
3014
3015 /* OK, now write the character lines */
3016 for (ulCounter = 0;
3017 ulCounter < cchWrite;
3018 ulCounter++,
3019 lpWriteBuffer++)
3020 {
3021 /* write character into cell */
3022 *(pConsoleBuffer->ppszLine[dwWriteCoord.Y] +
3023 (dwWriteCoord.X * 2)
3024 ) = (UCHAR)*lpWriteBuffer; /* write character and skip to next */
3025 /* @@@PH unicode to ascii translation */
3026
3027 dwWriteCoord.X++; /* move write position */
3028 if (dwWriteCoord.X >= pConsoleBuffer->coordBufferSize.X)
3029 {
3030 dwWriteCoord.X = 0; /* skip to next line */
3031 dwWriteCoord.Y++;
3032
3033 /* oops, we're at the end of the buffer. Abort now. */
3034 if (dwWriteCoord.Y >= pConsoleBuffer->coordBufferSize.Y)
3035 {
3036 if (lpcWritten != NULL) /* ensure pointer is valid */
3037 *lpcWritten = ulCounter;
3038
3039 /* update screen if active console */
3040 if (pHMHandleData->hHMHandle == pConsoleGlobals->hConsoleBuffer)
3041 pConsoleGlobals->fUpdateRequired = TRUE;/* update with next WM_TIMER */
3042
3043 return (TRUE);
3044 }
3045 }
3046 }
3047
3048 /* update screen if active console */
3049 if (pHMHandleData->hHMHandle == pConsoleGlobals->hConsoleBuffer)
3050 pConsoleGlobals->fUpdateRequired = TRUE; /* update with next WM_TIMER */
3051
3052 if (lpcWritten != NULL) /* ensure pointer is valid */
3053 *lpcWritten = cchWrite;
3054
3055 return (TRUE);
3056}
3057
Note: See TracBrowser for help on using the repository browser.