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

Last change on this file since 21916 was 21916, checked in by dmik, 9 years ago

Merge branch gcc-kmk to trunk.

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