source: trunk/src/kernel32/conbuffervio.cpp@ 22059

Last change on this file since 22059 was 22059, checked in by dmik, 13 years ago

kernel32: Fix long string output to stdout in console I/O mode.

Kind of a regression of changes made for #90. See Java ticket 201 for details.

File size: 13.3 KB
Line 
1/* $Id: conbuffervio.cpp,v 1.7 2003-04-11 12:08:35 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#include <stdio.h>
77#include <malloc.h>
78
79#include "conwin.h" // Windows Header for console only
80#include "HandleManager.h"
81#include "HMDevice.h"
82#include "ConBuffervio.H"
83#include "Console2.h"
84#include <heapstring.h>
85
86#define DBG_LOCALLOG DBG_conbuffer
87#include "dbglocal.h"
88
89/*****************************************************************************
90 * Name :
91 * Purpose :
92 * Parameters:
93 * Variables :
94 * Result :
95 * Remark :
96 * Status :
97 *
98 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
99 *****************************************************************************/
100
101BOOL HMDeviceConsoleVioBufferClass::WriteFile(PHMHANDLEDATA pHMHandleData,
102 LPCVOID lpBuffer,
103 DWORD nNumberOfBytesToWrite,
104 LPDWORD lpNumberOfBytesWritten,
105 LPOVERLAPPED lpOverlapped,
106 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
107{
108 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
109 ULONG ulCounter; /* counter for the byte transfer */
110 PSZ pszBuffer;
111 char filler[4] = {' ', 0x07, ' ', 0x07};
112 register UCHAR ucChar;
113 APIRET rc;
114 USHORT Row;
115 USHORT Column;
116 int numchar;
117
118#ifdef DEBUG_LOCAL2
119 WriteLog("KERNEL32/CONSOLE:HMDeviceConsoleVioBufferClass:WriteFile %s(%08x,%08x,%08x,%08x,%08x)\n",
120 lpHMDeviceName,
121 pHMHandleData->hHMHandle,
122 lpBuffer,
123 nNumberOfBytesToWrite,
124 lpNumberOfBytesWritten,
125 lpOverlapped);
126#endif
127
128 if(lpCompletionRoutine) {
129 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
130 }
131
132 /* check if we're called with non-existing line buffer */
133 if (pConsoleBuffer->ppszLine == NULL) {
134 SetLastError(ERROR_OUTOFMEMORY_W);
135 return FALSE;
136 }
137
138 dprintf(("Current cursor position (%d,%d)", pConsoleBuffer->coordCursorPosition.X, pConsoleBuffer->coordCursorPosition.Y));
139
140 if(nNumberOfBytesToWrite > 1024)
141 {
142 int tmp = 0;
143 BOOL retcode;
144
145 while(nNumberOfBytesToWrite) {
146 *lpNumberOfBytesWritten = 0;
147 retcode = WriteFile(pHMHandleData, lpBuffer,
148 min(nNumberOfBytesToWrite, 512), lpNumberOfBytesWritten,
149 lpOverlapped, lpCompletionRoutine);
150 if(retcode != TRUE) break;
151
152 tmp += *lpNumberOfBytesWritten;
153 nNumberOfBytesToWrite -= *lpNumberOfBytesWritten;
154 lpBuffer = (LPCVOID)((char *)lpBuffer + *lpNumberOfBytesWritten);
155 }
156 *lpNumberOfBytesWritten = tmp;
157 return retcode;
158 }
159 pszBuffer = (PSZ)alloca(nNumberOfBytesToWrite);
160 if(pszBuffer == NULL) {
161 DebugInt3();
162 return FALSE;
163 }
164 memcpy(pszBuffer, lpBuffer, nNumberOfBytesToWrite);
165
166 ulCounter = 0;
167 while(ulCounter < nNumberOfBytesToWrite)
168 {
169 ucChar = pszBuffer[ulCounter]; /* map to register */
170
171 if ( (pConsoleBuffer->dwConsoleMode & ENABLE_PROCESSED_OUTPUT) &&
172 (ucChar < 32) ) /* this is faster than a large switch statement */
173 {
174 switch (ucChar)
175 {
176 case 7: /* BEL */
177 if (pConsoleGlobals->Options.fSpeakerEnabled == TRUE)
178 DosBeep(pConsoleGlobals->Options.ulSpeakerFrequency,
179 pConsoleGlobals->Options.ulSpeakerDuration);
180 break;
181
182 case 8: /* Backspace */
183 {
184 BOOL go = FALSE;
185 if (pConsoleBuffer->coordCursorPosition.X > 0)
186 {
187 pConsoleBuffer->coordCursorPosition.X--;
188 go = TRUE;
189 }
190 else if (pConsoleBuffer->coordCursorPosition.Y > 0)
191 {
192 pConsoleBuffer->coordCursorPosition.Y--;
193 pConsoleBuffer->coordCursorPosition.X = pConsoleBuffer->coordBufferSize.X - 1;
194 go = TRUE;
195 }
196 if (go)
197 {
198 *(pConsoleBuffer->ppszLine[pConsoleBuffer->coordCursorPosition.Y] +
199 pConsoleBuffer->coordCursorPosition.X * 2) = 0x20;
200 VioWrtCharStr((PCH)" ", 1, pConsoleBuffer->coordCursorPosition.Y, pConsoleBuffer->coordCursorPosition.X, 0);
201 VioSetCurPos(pConsoleBuffer->coordCursorPosition.Y, pConsoleBuffer->coordCursorPosition.X, 0);
202 }
203 break;
204 }
205
206 case 9: /* Tab */
207 pConsoleBuffer->coordCursorPosition.X =
208 (pConsoleBuffer->coordCursorPosition.X
209 / pConsoleGlobals->Options.ulTabSize
210 + 1)
211 * pConsoleGlobals->Options.ulTabSize;
212
213 if (pConsoleBuffer->coordCursorPosition.X >=
214 pConsoleBuffer->coordBufferSize.X)
215 {
216 pConsoleBuffer->coordCursorPosition.X %= pConsoleBuffer->coordBufferSize.X;
217 pConsoleBuffer->coordCursorPosition.Y++;
218
219 if (pConsoleBuffer->coordCursorPosition.Y >=
220 pConsoleBuffer->coordBufferSize.Y)
221 {
222 if (pConsoleBuffer->dwConsoleMode & ENABLE_WRAP_AT_EOL_OUTPUT)
223 {
224 VioScrollUp(0, 0, pConsoleBuffer->coordWindowSize.Y-1, pConsoleBuffer->coordWindowSize.X-1,
225 1, &filler[0], 0);
226 pConsoleBuffer->coordCursorPosition.Y = pConsoleBuffer->coordWindowSize.Y-1;
227 }
228 }
229 }
230 VioSetCurPos(pConsoleBuffer->coordCursorPosition.Y, pConsoleBuffer->coordCursorPosition.X, 0);
231 break;
232
233 case 13: /* CARRIAGE RETURN */
234 dprintf(("CR"));
235 pConsoleBuffer->coordCursorPosition.X = 0;
236 VioSetCurPos(pConsoleBuffer->coordCursorPosition.Y, pConsoleBuffer->coordCursorPosition.X, 0);
237 break;
238
239 case 10: /* LINEFEED */
240 {
241 dprintf(("LF"));
242 pConsoleBuffer->coordCursorPosition.Y++;
243 pConsoleBuffer->coordCursorPosition.X = 0;
244 if(pConsoleBuffer->coordCursorPosition.Y >= pConsoleBuffer->coordWindowSize.Y) {
245 dprintf(("scrollup"));
246 VioScrollUp(0, 0, pConsoleBuffer->coordWindowSize.Y-1, pConsoleBuffer->coordWindowSize.X-1,
247 1, &filler[0], 0);
248 pConsoleBuffer->coordCursorPosition.Y = pConsoleBuffer->coordWindowSize.Y-1;
249 }
250 VioSetCurPos(pConsoleBuffer->coordCursorPosition.Y, pConsoleBuffer->coordCursorPosition.X, 0);
251 break;
252 }
253 default:
254 break;
255 }
256 ulCounter++;
257 }
258 else
259 {
260//// dprintf(("Current cursor position (%d,%d)", pConsoleBuffer->coordCursorPosition.X, pConsoleBuffer->coordCursorPosition.Y));
261 numchar = ulCounter;
262 while(pszBuffer[numchar] >= 32 && numchar < nNumberOfBytesToWrite) {
263 numchar++;
264 }
265 numchar = numchar - ulCounter;
266
267 while (numchar)
268 {
269 if(pConsoleBuffer->coordCursorPosition.X + numchar > pConsoleBuffer->coordWindowSize.X)
270 {
271 int tmp = pConsoleBuffer->coordWindowSize.X - pConsoleBuffer->coordCursorPosition.X;
272
273 VioWrtCharStr(&pszBuffer[ulCounter], tmp, pConsoleBuffer->coordCursorPosition.Y, pConsoleBuffer->coordCursorPosition.X, 0);
274 ulCounter += tmp;
275 numchar -= tmp;
276
277 pConsoleBuffer->coordCursorPosition.X = 0;
278 pConsoleBuffer->coordCursorPosition.Y++;
279 if(pConsoleBuffer->coordCursorPosition.Y >= pConsoleBuffer->coordWindowSize.Y) {
280 dprintf(("scrollup"));
281 VioScrollUp(0, 0, pConsoleBuffer->coordWindowSize.Y-1, pConsoleBuffer->coordWindowSize.X-1,
282 1, &filler[0], 0);
283 pConsoleBuffer->coordCursorPosition.Y = pConsoleBuffer->coordWindowSize.Y-1;
284 }
285 VioSetCurPos(pConsoleBuffer->coordCursorPosition.Y, pConsoleBuffer->coordCursorPosition.X, 0);
286 }
287 else {
288 VioWrtCharStr(&pszBuffer[ulCounter], numchar, pConsoleBuffer->coordCursorPosition.Y, pConsoleBuffer->coordCursorPosition.X, 0);
289 ulCounter += numchar;
290 pConsoleBuffer->coordCursorPosition.X += numchar;
291 VioSetCurPos(pConsoleBuffer->coordCursorPosition.Y, pConsoleBuffer->coordCursorPosition.X, 0);
292 numchar = 0;
293 }
294 }
295 }
296 }
297
298 *lpNumberOfBytesWritten = ulCounter;
299
300 return TRUE;
301}
302
303DWORD HMDeviceConsoleVioBufferClass::FillConsoleOutputAttribute(PHMHANDLEDATA pHMHandleData,
304 WORD wAttribute,
305 DWORD nLength,
306 COORD dwWriteCoord,
307 LPDWORD lpNumberOfAttrsWritten)
308{
309 APIRET rc;
310
311#ifdef DEBUG_LOCAL2
312 WriteLog("KERNEL32/CONSOLE: HMDeviceConsoleVioBufferClass::FillConsoleOutputAttribute(%08x,attr=%04x,%u,x=%u y=%u,res=%08x).\n",
313 pHMHandleData,
314 wAttribute,
315 nLength,
316 dwWriteCoord.X,
317 dwWriteCoord.Y,
318 lpNumberOfAttrsWritten);
319#endif
320
321 if (HMDeviceConsoleBufferClass::FillConsoleOutputAttribute(pHMHandleData,
322 wAttribute,
323 nLength,
324 dwWriteCoord,
325 lpNumberOfAttrsWritten))
326 {
327 rc = VioWrtNAttr((PBYTE)&wAttribute, *lpNumberOfAttrsWritten, dwWriteCoord.Y, dwWriteCoord.X,
328 0);
329 if (rc == NO_ERROR)
330 {
331 return TRUE;
332 } else
333 {
334 return FALSE;
335 }
336 } else
337 return FALSE;
338}
339
340DWORD HMDeviceConsoleVioBufferClass::FillConsoleOutputCharacterA(PHMHANDLEDATA pHMHandleData,
341 UCHAR ucCharacter,
342 DWORD nLength,
343 COORD dwWriteCoord,
344 LPDWORD lpNumberOfCharsWritten)
345{
346 APIRET rc;
347
348#ifdef DEBUG_LOCAL2
349 WriteLog("KERNEL32/CONSOLE: HMDeviceConsoleVioBufferClass::FillConsoleOutputCharacterA(%08x,char=%02x,%u,x=%u y=%u,res=%08x).\n",
350 pHMHandleData,
351 ucCharacter,
352 nLength,
353 dwWriteCoord.X,
354 dwWriteCoord.Y,
355 lpNumberOfCharsWritten);
356#endif
357 if (HMDeviceConsoleBufferClass::FillConsoleOutputCharacterA(pHMHandleData,
358 ucCharacter,
359 nLength,
360 dwWriteCoord,
361 lpNumberOfCharsWritten))
362 {
363 rc = VioWrtNChar((PCH)&ucCharacter, *lpNumberOfCharsWritten, dwWriteCoord.Y, dwWriteCoord.X,
364 0);
365 if (rc == NO_ERROR)
366 {
367 return TRUE;
368 } else
369 {
370 return FALSE;
371 }
372 } else
373 return FALSE;
374}
375
Note: See TracBrowser for help on using the repository browser.