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

Last change on this file since 22052 was 22052, checked in by dmik, 8 years ago

kernel32: Properly handle backspace and tab characters in console input/output mode.

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