3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS VT100 emulator
5 * FILE: drivers/dd/green/screen.c
6 * PURPOSE: Screen part of green management
8 * PROGRAMMERS: Eric Kohl (ekohl@abo.rhein-zeitung.de)
10 * Hervé Poussineau (hpoussin@reactos.com)
17 #define ESC ((UCHAR)0x1b)
19 /* Force a move of the cursor on each printer char.
20 * Very useful for debug, but it is very slow...
22 //#define FORCE_POSITION
24 /* UCHAR is promoted to int when passed through '...',
25 * so we get int with va_arg and cast them back to UCHAR.
29 IN PSCREEN_DEVICE_EXTENSION DeviceExtension
,
30 IN ULONG NumberOfChars
,
34 IO_STATUS_BLOCK ioStatus
;
36 PDEVICE_OBJECT SerialDevice
;
42 SizeLeft
= sizeof(DeviceExtension
->SendBuffer
) - DeviceExtension
->SendBufferPosition
;
43 if (SizeLeft
< NumberOfChars
* 2 || NumberOfChars
== 0)
45 SerialDevice
= ((PGREEN_DEVICE_EXTENSION
)DeviceExtension
->Green
->DeviceExtension
)->Serial
;
46 Irp
= IoBuildSynchronousFsdRequest(
49 DeviceExtension
->SendBuffer
, DeviceExtension
->SendBufferPosition
,
50 NULL
, /* StartingOffset */
55 DPRINT1("Green: IoBuildSynchronousFsdRequest() failed. Unable to flush output buffer\n");
58 Status
= IoCallDriver(SerialDevice
, Irp
);
59 if (!NT_SUCCESS(Status
) && Status
!= STATUS_PENDING
)
61 DPRINT1("Green: IoCallDriver() failed. Status = 0x%08lx\n", Status
);
64 DeviceExtension
->SendBufferPosition
= 0;
65 SizeLeft
= sizeof(DeviceExtension
->SendBuffer
);
68 va_start(args
, NumberOfChars
);
69 while (NumberOfChars
-- > 0)
71 CurrentInt
= va_arg(args
, int);
74 CurrentChar
= (UCHAR
)CurrentInt
;
76 /* Why 0xff chars are printed on a 'dir' ? */
77 if (CurrentChar
== 0xff) CurrentChar
= ' ';
79 DeviceExtension
->SendBuffer
[DeviceExtension
->SendBufferPosition
++] = CurrentChar
;
82 else if (CurrentInt
== 0)
84 DeviceExtension
->SendBuffer
[DeviceExtension
->SendBufferPosition
++] = '0';
89 CurrentInt
= -CurrentInt
;
90 ASSERT(CurrentInt
< 100);
93 DeviceExtension
->SendBuffer
[DeviceExtension
->SendBufferPosition
++] =
94 (CurrentInt
/ 10) % 10 + '0';
97 DeviceExtension
->SendBuffer
[DeviceExtension
->SendBufferPosition
++] =
98 CurrentInt
% 10 + '0';
107 IN PDRIVER_OBJECT DriverObject
,
108 OUT PDEVICE_OBJECT
* ScreenFdo
)
111 PSCREEN_DEVICE_EXTENSION DeviceExtension
;
112 UNICODE_STRING DeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\BlueScreen");
115 DPRINT("Green: ScreenInitialize() called\n");
117 Status
= IoCreateDevice(DriverObject
,
118 sizeof(SCREEN_DEVICE_EXTENSION
),
119 &DeviceName
, /* FIXME: don't hardcode string */
121 FILE_DEVICE_SECURE_OPEN
,
124 if (!NT_SUCCESS(Status
))
127 DeviceExtension
= (PSCREEN_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
128 RtlZeroMemory(DeviceExtension
, sizeof(SCREEN_DEVICE_EXTENSION
));
129 DeviceExtension
->Common
.Type
= Screen
;
130 /* initialize screen */
131 DeviceExtension
->Columns
= 80;
132 DeviceExtension
->Rows
= 25;
133 DeviceExtension
->ScanLines
= 16;
134 DeviceExtension
->VideoMemory
= (PUCHAR
)ExAllocatePool(
136 2 * DeviceExtension
->Columns
* DeviceExtension
->Rows
* sizeof(UCHAR
));
137 if (!DeviceExtension
->VideoMemory
)
140 return STATUS_INSUFFICIENT_RESOURCES
;
142 DeviceExtension
->TabWidth
= 8;
144 /* more initialization */
145 DeviceExtension
->Mode
= ENABLE_PROCESSED_OUTPUT
|
146 ENABLE_WRAP_AT_EOL_OUTPUT
;
148 /* initialize screen at next write */
149 AddToSendBuffer(DeviceExtension
, 2, ESC
, 'c'); /* reset device */
150 AddToSendBuffer(DeviceExtension
, 4, ESC
, '[', '7', 'l'); /* disable line wrap */
151 AddToSendBuffer(DeviceExtension
, 4, ESC
, '[', '3', 'g'); /* clear all tabs */
153 Fdo
->Flags
|= DO_POWER_PAGABLE
| DO_BUFFERED_IO
;
154 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
158 return STATUS_SUCCESS
;
163 IN PDEVICE_OBJECT DeviceObject
,
166 PIO_STACK_LOCATION Stack
;
168 PSCREEN_DEVICE_EXTENSION DeviceExtension
;
169 PUCHAR VideoMemory
; /* FIXME: is it useful? */
170 ULONG VideoMemorySize
; /* FIXME: is it useful? */
173 ULONG CursorX
, CursorY
;
177 DPRINT("Green: IRP_MJ_WRITE\n");
179 Stack
= IoGetCurrentIrpStackLocation (Irp
);
180 Buffer
= Irp
->UserBuffer
;
181 DeviceExtension
= (PSCREEN_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
182 VideoMemory
= DeviceExtension
->VideoMemory
;
184 Columns
= DeviceExtension
->Columns
;
185 Rows
= DeviceExtension
->Rows
;
186 CursorX
= (DeviceExtension
->LogicalOffset
/ 2) % Columns
+ 1;
187 CursorY
= (DeviceExtension
->LogicalOffset
/ 2) / Columns
+ 1;
188 VideoMemorySize
= Columns
* Rows
* 2 * sizeof(UCHAR
);
189 DPRINT1("Y: %lu\n", CursorY
);
191 for (i
= 0; i
< Stack
->Parameters
.Write
.Length
; i
++)
192 DbgPrint(" 0x%02x", Buffer
[i
]);
195 if (!(DeviceExtension
->Mode
& ENABLE_PROCESSED_OUTPUT
))
197 /* raw output mode */
199 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
200 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
202 return STATUS_NOT_SUPPORTED
;
206 for (i
= 0; i
< Stack
->Parameters
.Write
.Length
; i
++, Buffer
++)
215 AddToSendBuffer(DeviceExtension
, 6, ESC
, '[', -(int)CursorY
, ';', -(int)CursorX
, 'H');
216 AddToSendBuffer(DeviceExtension
, 1, ' ');
217 AddToSendBuffer(DeviceExtension
, 6, ESC
, '[', -(int)CursorY
, ';', -(int)CursorX
, 'H');
219 else if (CursorY
> 1)
223 AddToSendBuffer(DeviceExtension
, 6, ESC
, '[', -(int)CursorY
, ';', -(int)CursorX
, 'H');
231 AddToSendBuffer(DeviceExtension
, 6, ESC
, '[', -(int)CursorY
, ';', '1', 'H');
238 AddToSendBuffer(DeviceExtension
, 4, ESC
, '[', -(int)(CursorX
-1), 'D');
245 ULONG Offset
= DeviceExtension
->TabWidth
- (CursorX
% DeviceExtension
->TabWidth
);
246 for (j
= 0; j
< Offset
; j
++)
248 #ifdef FORCE_POSITION
249 AddToSendBuffer(DeviceExtension
, 6, ESC
, '[', -(int)CursorY
, ';', -(int)CursorX
, 'H');
251 AddToSendBuffer(DeviceExtension
, 1, ' ');
253 if (CursorX
> Columns
)
263 #ifdef FORCE_POSITION
264 AddToSendBuffer(DeviceExtension
, 6, ESC
, '[', -(int)CursorY
, ';', -(int)CursorX
, 'H');
266 AddToSendBuffer(DeviceExtension
, 1, *Buffer
);
268 if (CursorX
> Columns
)
271 DPRINT1("Y: %lu -> %lu\n", CursorY
, CursorY
+ 1);
273 AddToSendBuffer(DeviceExtension
, 6, ESC
, '[', -(int)CursorY
, ';', '1', 'H');
280 DPRINT1("Y: %lu -> %lu\n", CursorY
, CursorY
- 1);
282 AddToSendBuffer(DeviceExtension
, 2, ESC
, 'D');
283 AddToSendBuffer(DeviceExtension
, 6, ESC
, '[', -(int)CursorY
, ';', -(int)CursorX
, 'H');
288 DeviceExtension
->LogicalOffset
= ((CursorX
-1) + (CursorY
-1) * Columns
) * 2;
290 /* flush output buffer */
291 AddToSendBuffer(DeviceExtension
, 0);
293 Status
= STATUS_SUCCESS
;
294 Irp
->IoStatus
.Status
= Status
;
295 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
302 IN PDEVICE_OBJECT DeviceObject
,
305 PIO_STACK_LOCATION Stack
;
306 PSCREEN_DEVICE_EXTENSION DeviceExtension
;
309 Stack
= IoGetCurrentIrpStackLocation(Irp
);
310 DeviceExtension
= (PSCREEN_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
312 switch (Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
314 case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO
:
316 PCONSOLE_SCREEN_BUFFER_INFO pcsbi
;
317 DPRINT("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO\n");
319 pcsbi
= (PCONSOLE_SCREEN_BUFFER_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
321 pcsbi
->dwSize
.X
= DeviceExtension
->Columns
;
322 pcsbi
->dwSize
.Y
= DeviceExtension
->Rows
;
324 pcsbi
->dwCursorPosition
.X
= (SHORT
)(DeviceExtension
->LogicalOffset
% DeviceExtension
->Columns
);
325 pcsbi
->dwCursorPosition
.Y
= (SHORT
)(DeviceExtension
->LogicalOffset
/ DeviceExtension
->Columns
);
327 pcsbi
->wAttributes
= DeviceExtension
->CharAttribute
;
329 pcsbi
->srWindow
.Left
= 1;
330 pcsbi
->srWindow
.Right
= DeviceExtension
->Columns
;
331 pcsbi
->srWindow
.Top
= 1;
332 pcsbi
->srWindow
.Bottom
= DeviceExtension
->Rows
;
334 pcsbi
->dwMaximumWindowSize
.X
= DeviceExtension
->Columns
;
335 pcsbi
->dwMaximumWindowSize
.Y
= DeviceExtension
->Rows
;
337 Irp
->IoStatus
.Information
= sizeof(CONSOLE_SCREEN_BUFFER_INFO
);
338 Status
= STATUS_SUCCESS
;
341 case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO
:
343 PCONSOLE_SCREEN_BUFFER_INFO pcsbi
;
344 DPRINT("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO\n");
346 pcsbi
= (PCONSOLE_SCREEN_BUFFER_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
347 /* FIXME: remove */ { pcsbi
->dwCursorPosition
.X
++; }
348 /* FIXME: remove */ { pcsbi
->dwCursorPosition
.Y
++; }
349 ASSERT(pcsbi
->dwCursorPosition
.X
>= 1);
350 ASSERT(pcsbi
->dwCursorPosition
.Y
>= 1);
351 ASSERT(pcsbi
->dwCursorPosition
.X
<= DeviceExtension
->Columns
);
352 ASSERT(pcsbi
->dwCursorPosition
.Y
<= DeviceExtension
->Rows
);
354 DeviceExtension
->LogicalOffset
= (
355 (pcsbi
->dwCursorPosition
.Y
-1) * DeviceExtension
->Columns
+
356 (pcsbi
->dwCursorPosition
.X
-1)) * 2;
357 AddToSendBuffer(DeviceExtension
, 6, ESC
, '[',
358 -(int)pcsbi
->dwCursorPosition
.Y
, ';',
359 -(int)pcsbi
->dwCursorPosition
.X
, 'H');
362 AddToSendBuffer(DeviceExtension
, 0);
364 DeviceExtension
->CharAttribute
= pcsbi
->wAttributes
;
366 Irp
->IoStatus
.Information
= 0;
367 Status
= STATUS_SUCCESS
;
370 case IOCTL_CONSOLE_GET_CURSOR_INFO
:
372 PCONSOLE_CURSOR_INFO pcci
= (PCONSOLE_CURSOR_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
373 DPRINT("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_GET_CURSOR_INFO\n");
376 pcci
->bVisible
= TRUE
;
378 Irp
->IoStatus
.Information
= sizeof (CONSOLE_CURSOR_INFO
);
379 Status
= STATUS_SUCCESS
;
382 case IOCTL_CONSOLE_GET_MODE
:
384 PCONSOLE_MODE pcm
= (PCONSOLE_MODE
)Irp
->AssociatedIrp
.SystemBuffer
;
385 DPRINT("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_GET_MODE\n");
387 pcm
->dwMode
= DeviceExtension
->Mode
;
389 Irp
->IoStatus
.Information
= sizeof(CONSOLE_MODE
);
390 Status
= STATUS_SUCCESS
;
393 case IOCTL_CONSOLE_SET_MODE
:
395 PCONSOLE_MODE pcm
= (PCONSOLE_MODE
)Irp
->AssociatedIrp
.SystemBuffer
;
396 DPRINT("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_SET_MODE\n");
398 DeviceExtension
->Mode
= pcm
->dwMode
;
400 Irp
->IoStatus
.Information
= 0;
401 Status
= STATUS_SUCCESS
;
404 case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE
:
406 DPRINT1("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE\n");
407 Status
= STATUS_NOT_IMPLEMENTED
; /* FIXME: IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE */
410 case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE
:
412 DPRINT1("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE\n");
413 Status
= STATUS_NOT_IMPLEMENTED
; /* FIXME: IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE */
416 case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE
:
418 DPRINT1("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE\n");
419 Status
= STATUS_NOT_IMPLEMENTED
; /* FIXME: IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE */
422 case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE
:
424 DPRINT("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE\n");
426 DeviceExtension
->CharAttribute
= (WORD
)*(PWORD
)Irp
->AssociatedIrp
.SystemBuffer
;
427 Irp
->IoStatus
.Information
= 0;
428 Status
= STATUS_SUCCESS
;
431 case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER
:
433 DPRINT1("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER\n");
434 Status
= STATUS_NOT_IMPLEMENTED
; /* FIXME:IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER */
437 case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER
:
439 DPRINT1("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_READ_OUTPUT_CHARACTER\n");
440 Status
= STATUS_NOT_IMPLEMENTED
; /* FIXME: IOCTL_CONSOLE_READ_OUTPUT_CHARACTER */
443 case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER
:
445 DPRINT1("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER\n");
446 Status
= STATUS_NOT_IMPLEMENTED
; /* FIXME: IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER */
449 case IOCTL_CONSOLE_DRAW
:
451 PCONSOLE_DRAW ConsoleDraw
;
454 BOOLEAN DoOptimization
= FALSE
;
455 DPRINT("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_DRAW\n");
457 ConsoleDraw
= (PCONSOLE_DRAW
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
458 /* FIXME: remove */ { ConsoleDraw
->X
++; ConsoleDraw
->CursorX
++; }
459 /* FIXME: remove */ { ConsoleDraw
->Y
++; ConsoleDraw
->CursorY
++; }
460 DPRINT1("%lu %lu %lu %lu\n",
461 ConsoleDraw
->X
, ConsoleDraw
->Y
,
462 ConsoleDraw
->SizeX
, ConsoleDraw
->SizeY
);
463 ASSERT(ConsoleDraw
->X
>= 1);
464 ASSERT(ConsoleDraw
->Y
>= 1);
465 ASSERT(ConsoleDraw
->X
<= DeviceExtension
->Columns
);
466 ASSERT(ConsoleDraw
->Y
<= DeviceExtension
->Rows
);
467 ASSERT(ConsoleDraw
->X
+ ConsoleDraw
->SizeX
>= 1);
468 ASSERT(ConsoleDraw
->Y
+ ConsoleDraw
->SizeY
>= 1);
469 ASSERT(ConsoleDraw
->X
+ ConsoleDraw
->SizeX
- 1 <= DeviceExtension
->Columns
);
470 ASSERT(ConsoleDraw
->Y
+ ConsoleDraw
->SizeY
- 1 <= DeviceExtension
->Rows
);
471 ASSERT(ConsoleDraw
->CursorX
>= 1);
472 ASSERT(ConsoleDraw
->CursorY
>= 1);
473 ASSERT(ConsoleDraw
->CursorX
<= DeviceExtension
->Columns
);
474 ASSERT(ConsoleDraw
->CursorY
<= DeviceExtension
->Rows
);
477 if (ConsoleDraw
->X
== 1
478 && ConsoleDraw
->Y
== 1
479 && ConsoleDraw
->SizeX
== DeviceExtension
->Columns
480 && ConsoleDraw
->SizeY
== DeviceExtension
->Rows
)
483 /* search if we need to clear all screen */
484 DoOptimization
= TRUE
;
485 Video
= (PUCHAR
)(ConsoleDraw
+ 1);
487 while (DoOptimization
&& x
< DeviceExtension
->Columns
* DeviceExtension
->Rows
)
489 if (Video
[x
++] != ' ')
492 DoOptimization
= FALSE
;
494 /*if (Video[x++] != DeviceExtension->CharAttribute) DoOptimization = FALSE; */
499 AddToSendBuffer(DeviceExtension
, 4, ESC
, '[', '2', 'J');
503 /* add here more optimizations if needed */
507 for (y
= 0; y
< ConsoleDraw
->SizeY
; y
++)
509 AddToSendBuffer(DeviceExtension
, 6, ESC
, '[',
510 -(int)(ConsoleDraw
->Y
+ y
), ';',
511 -(int)(ConsoleDraw
->X
), 'H');
512 Video
= (PUCHAR
)(ConsoleDraw
+ 1);
513 Video
= &Video
[((ConsoleDraw
->Y
+ y
) * DeviceExtension
->Columns
+ ConsoleDraw
->X
) * 2];
514 for (x
= 0; x
< ConsoleDraw
->SizeX
; x
++)
516 AddToSendBuffer(DeviceExtension
, 1, Video
[x
* 2]);
521 DeviceExtension
->LogicalOffset
= (
522 (ConsoleDraw
->CursorY
-1) * DeviceExtension
->Columns
+
523 (ConsoleDraw
->CursorX
-1)) * 2;
524 AddToSendBuffer(DeviceExtension
, 6, ESC
, '[',
525 -(int)(ConsoleDraw
->CursorY
), ';',
526 -(int)(ConsoleDraw
->CursorX
), 'H');
529 AddToSendBuffer(DeviceExtension
, 0);
531 Irp
->IoStatus
.Information
= 0;
532 Status
= STATUS_SUCCESS
;
536 DPRINT1("Green: IRP_MJ_DEVICE_CONTROL / unknown ioctl code 0x%lx\n",
537 Stack
->Parameters
.DeviceIoControl
.IoControlCode
);
538 Status
= STATUS_NOT_IMPLEMENTED
;
541 Irp
->IoStatus
.Status
= Status
;
542 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);