46
46
47
47
#include "reb-host.h"
48
48
#include "host-lib.h"
49
+ #include "sys-scan.h"
49
50
50
51
#define BUF_SIZE (16*1024) // MS restrictions apply
51
52
@@ -66,6 +67,32 @@ static BOOL Redir_Inp = 0;
66
67
extern REBDEV * Devices [];
67
68
68
69
70
+ //** ANSI emulation definition ******************************************
71
+ #define FOREGROUND_BLACK 0x0000
72
+ //#define FOREGROUND_BLUE 0x0001
73
+ //#define FOREGROUND_GREEN 0x0002
74
+ #define FOREGROUND_CYAN 0x0003
75
+ //#define FOREGROUND_RED 0x0004
76
+ #define FOREGROUND_MAGENTA 0x0005
77
+ #define FOREGROUND_YELLOW 0x0006
78
+ #define FOREGROUND_GREY 0x0007
79
+ //#define FOREGROUND_INTENSITY 0x0008
80
+ #define FOREGROUND_WHITE 0x000F
81
+ //#define BACKGROUND_BLUE 0x0010
82
+ #define BACKGROUND_CYAN 0x0030
83
+ //#define BACKGROUND_GREEN 0x0020
84
+ //#define BACKGROUND_RED 0x0040
85
+ #define BACKGROUND_MAGENTA 0x0050
86
+ #define BACKGROUND_YELLOW 0x0060
87
+ #define BACKGROUND_GREY 0x0070
88
+ //#define BACKGROUND_INTENSITY 0x0080
89
+ #define COMMON_LVB_UNDERSCORE 0x8000
90
+
91
+ static COORD Std_coord = {0 , 0 };
92
+
93
+ int Update_Graphic_Mode (int attribute , int value );
94
+ REBYTE * Parse_ANSI_sequence (REBYTE * cp , REBYTE * ep );
95
+
69
96
//**********************************************************************
70
97
71
98
BOOL WINAPI Handle_Break (DWORD dwCtrlType )
@@ -82,7 +109,7 @@ BOOL WINAPI Handle_Break(DWORD dwCtrlType)
82
109
static dbgout (char * fmt , int d , char * s )
83
110
{
84
111
char buf [255 ];
85
- FILE * f = fopen ("dbgout.txt" , "w " );
112
+ FILE * f = fopen ("dbgout.txt" , "a " );
86
113
sprintf (buf , fmt , d , s );
87
114
fwrite (buf , strlen (buf ), 1 , f );
88
115
fclose (f );
@@ -234,6 +261,9 @@ static void close_stdio(void)
234
261
long len ;
235
262
long total = 0 ;
236
263
BOOL ok = FALSE;
264
+ REBYTE * bp ;
265
+ REBYTE * cp ;
266
+ REBYTE * ep ;
237
267
238
268
if (GET_FLAG (req -> modes , RDM_NULL )) {
239
269
req -> actual = req -> length ;
@@ -244,21 +274,41 @@ static void close_stdio(void)
244
274
245
275
if (Redir_Out ) { // Always UTF-8
246
276
ok = WriteFile (Std_Out , req -> data , req -> length , & total , 0 );
277
+ if (!ok ) {
278
+ req -> error = GetLastError ();
279
+ return DR_ERROR ;
280
+ }
247
281
}
248
282
else {
249
283
// Convert UTF-8 buffer to Win32 wide-char format for console.
250
284
// Thankfully, MS provides something other than mbstowcs();
251
285
// however, if our buffer overflows, it's an error. There's no
252
286
// efficient way at this level to split-up the input data,
253
287
// because its UTF-8 with variable char sizes.
254
- len = MultiByteToWideChar (CP_UTF8 , 0 , req -> data , req -> length , Std_Buf , BUF_SIZE );
255
- if (len > 0 ) // no error
256
- ok = WriteConsoleW (Std_Out , Std_Buf , len , & total , 0 );
257
- }
258
-
259
- if (!ok ) {
260
- req -> error = GetLastError ();
261
- return DR_ERROR ;
288
+ bp = req -> data ;
289
+ ep = bp + req -> length ;
290
+
291
+ do {
292
+ cp = Skip_To_Char (bp , ep , (REBYTE )27 ); //find ANSI escape char "^["
293
+ //if found, write to the console content before it starts, else everything
294
+ if (cp ){
295
+ len = MultiByteToWideChar (CP_UTF8 , 0 , bp , cp - bp , Std_Buf , BUF_SIZE );
296
+ } else {
297
+ len = MultiByteToWideChar (CP_UTF8 , 0 , bp , ep - bp , Std_Buf , BUF_SIZE );
298
+ bp = ep ;
299
+ }
300
+ if (len > 0 ) {// no error
301
+ ok = WriteConsoleW (Std_Out , Std_Buf , len , & total , 0 );
302
+ if (!ok ) {
303
+ req -> error = GetLastError ();
304
+ return DR_ERROR ;
305
+ }
306
+ }
307
+ //is escape char was found, parse the ANSI sequence...
308
+ if (cp ) {
309
+ bp = Parse_ANSI_sequence (++ cp , ep );
310
+ }
311
+ } while (bp < ep );
262
312
}
263
313
264
314
req -> actual = req -> length ; // do not use "total" (can be byte or wide)
@@ -377,6 +427,198 @@ DEFINE_DEV(Dev_StdIO, "Standard IO", 1, Dev_Cmds, RDC_MAX, 0);
377
427
378
428
379
429
430
+ /***********************************************************************
431
+ **
432
+ */ int Update_Graphic_Mode (int attribute , int value )
433
+ /*
434
+ **
435
+ ***********************************************************************/
436
+ {
437
+ CONSOLE_SCREEN_BUFFER_INFO csbiInfo ;
438
+ int tmp ;
439
+
440
+ if (attribute < 0 ) {
441
+ GetConsoleScreenBufferInfo (Std_Out , & csbiInfo );
442
+ attribute = csbiInfo .wAttributes ;
443
+ }
444
+
445
+ switch (value ) {
446
+ case 0 : attribute = FOREGROUND_GREY ; break ;
447
+ case 1 : attribute = attribute | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY ; break ;
448
+ case 4 : attribute = attribute | COMMON_LVB_UNDERSCORE ; break ;
449
+ case 7 : tmp = (attribute & 0xF0 ) >> 4 ;
450
+ attribute = ((attribute & 0x0F ) << 4 ) | tmp ; break ; //reverse
451
+ case 30 : attribute = attribute & 0xF8 ; break ;
452
+ case 31 : attribute = (attribute & 0xF8 ) | FOREGROUND_RED ; break ;
453
+ case 32 : attribute = (attribute & 0xF8 ) | FOREGROUND_GREEN ; break ;
454
+ case 33 : attribute = (attribute & 0xF8 ) | FOREGROUND_YELLOW ; break ;
455
+ case 34 : attribute = (attribute & 0xF8 ) | FOREGROUND_BLUE ; break ;
456
+ case 35 : attribute = (attribute & 0xF8 ) | FOREGROUND_MAGENTA ; break ;
457
+ case 36 : attribute = (attribute & 0xF8 ) | FOREGROUND_CYAN ; break ;
458
+ case 37 : attribute = (attribute & 0xF8 ) | FOREGROUND_GREY ; break ;
459
+ case 39 : attribute = attribute & 0xF7 ; break ; //FOREGROUND_INTENSITY reset
460
+ case 40 : attribute = attribute & 0x8F ; break ;
461
+ case 41 : attribute = (attribute & 0x8F ) | BACKGROUND_RED ; break ;
462
+ case 42 : attribute = (attribute & 0x8F ) | BACKGROUND_GREEN ; break ;
463
+ case 43 : attribute = (attribute & 0x8F ) | BACKGROUND_YELLOW ; break ;
464
+ case 44 : attribute = (attribute & 0x8F ) | BACKGROUND_BLUE ; break ;
465
+ case 45 : attribute = (attribute & 0x8F ) | BACKGROUND_MAGENTA ; break ;
466
+ case 46 : attribute = (attribute & 0x8F ) | BACKGROUND_CYAN ; break ;
467
+ case 47 : attribute = (attribute & 0x8F ) | BACKGROUND_GREY ; break ;
468
+ case 49 : attribute = attribute & 0x7F ; break ; //BACKGROUND_INTENSITY reset
469
+ default : attribute = value ;
470
+ }
471
+ return attribute ;
472
+ }
473
+
474
+ /***********************************************************************
475
+ **
476
+ */ REBYTE * Parse_ANSI_sequence (REBYTE * cp , REBYTE * ep )
477
+ /*
478
+ ** Parses ANSI sequence and return number of bytes used.
479
+ ** Based on http://ascii-table.com/ansi-escape-sequences.php
480
+ **
481
+ ***********************************************************************/
482
+ {
483
+ if (* cp != '[' ) return cp ;
484
+
485
+ int state = 1 ;
486
+ int value1 = 0 ;
487
+ int value2 = 0 ;
488
+ int attribute = -1 ;
489
+ int num ;
490
+ int len ;
491
+ COORD coordScreen ;
492
+ CONSOLE_SCREEN_BUFFER_INFO csbiInfo ;
493
+
494
+
495
+ do {
496
+ if (++ cp == ep ) return cp ;
497
+
498
+ switch (state ) {
499
+
500
+ case 1 : //value1 start
501
+ if ( * cp >= (int )'0' && * cp <= (int )'9' ) {
502
+ value1 = ((value1 * 10 ) + (* cp - (int )'0' )) % 0xFFFF ;
503
+ state = 2 ;
504
+ } else if (* cp == ';' ) {
505
+ //do nothing
506
+ } else if (* cp == 's' ) {
507
+ //Saves the current cursor position.
508
+ GetConsoleScreenBufferInfo (Std_Out , & csbiInfo );
509
+ Std_coord .X = csbiInfo .dwCursorPosition .X ;
510
+ Std_coord .Y = csbiInfo .dwCursorPosition .Y ;
511
+ state = -1 ;
512
+ } else if (* cp == 'u' ) {
513
+ //Returns the cursor to the position stored by the Save Cursor Position sequence.
514
+ SetConsoleCursorPosition (Std_Out , Std_coord );
515
+ state = -1 ;
516
+ } else if (* cp == 'K' ) {
517
+ //TODO: Erase Line.
518
+ state = -1 ;
519
+ } else if (* cp == 'J' ) {
520
+ //TODO: Clear screen from cursor down.
521
+ state = -1 ;
522
+ } else if (* cp == 'H' || * cp == 'f' ) {
523
+ coordScreen .X = 0 ;
524
+ coordScreen .Y = 0 ;
525
+ SetConsoleCursorPosition (Std_Out , coordScreen );
526
+ state = -1 ;
527
+ } else {
528
+ state = -1 ;
529
+ }
530
+ break ;
531
+ case 2 : //value1 continue
532
+ if ( * cp >= (int )'0' && * cp <= (int )'9' ) {
533
+ value1 = ((value1 * 10 ) + (* cp - (int )'0' )) % 0xFFFF ;
534
+ state = 2 ;
535
+ } else if (* cp == ';' ) {
536
+ state = 3 ;
537
+ } else if (* cp == 'm' ) {
538
+ attribute = Update_Graphic_Mode (attribute , value1 );
539
+ SetConsoleTextAttribute (Std_Out , attribute );
540
+ state = -1 ;
541
+ } else if (* cp == 'A' ) {
542
+ //Cursor Up.
543
+ GetConsoleScreenBufferInfo (Std_Out , & csbiInfo );
544
+ csbiInfo .dwCursorPosition .Y = MAX (0 , csbiInfo .dwCursorPosition .Y - value1 );
545
+ SetConsoleCursorPosition (Std_Out , csbiInfo .dwCursorPosition );
546
+ state = -1 ;
547
+ } else if (* cp == 'B' ) {
548
+ //Cursor Down.
549
+ GetConsoleScreenBufferInfo (Std_Out , & csbiInfo );
550
+ csbiInfo .dwCursorPosition .Y = MIN (csbiInfo .dwSize .Y , csbiInfo .dwCursorPosition .Y + value1 );
551
+ SetConsoleCursorPosition (Std_Out , csbiInfo .dwCursorPosition );
552
+ state = -1 ;
553
+ } else if (* cp == 'C' ) {
554
+ //Cursor Forward.
555
+ GetConsoleScreenBufferInfo (Std_Out , & csbiInfo );
556
+ csbiInfo .dwCursorPosition .X = MIN (csbiInfo .dwSize .X , csbiInfo .dwCursorPosition .X + value1 );
557
+ SetConsoleCursorPosition (Std_Out , csbiInfo .dwCursorPosition );
558
+ state = -1 ;
559
+ } else if (* cp == 'D' ) {
560
+ //Cursor Backward.
561
+ GetConsoleScreenBufferInfo (Std_Out , & csbiInfo );
562
+ csbiInfo .dwCursorPosition .X = MAX (0 , csbiInfo .dwCursorPosition .X - value1 );
563
+ SetConsoleCursorPosition (Std_Out , csbiInfo .dwCursorPosition );
564
+ state = -1 ;
565
+ } else if (* cp == 'J' ) {
566
+ if (value1 == 2 ) {
567
+ GetConsoleScreenBufferInfo (Std_Out , & csbiInfo );
568
+ len = csbiInfo .dwSize .X * csbiInfo .dwSize .Y ;
569
+ coordScreen .X = 0 ;
570
+ coordScreen .Y = 0 ;
571
+ FillConsoleOutputCharacter (Std_Out , (TCHAR )' ' , len , coordScreen , & num );
572
+ FillConsoleOutputAttribute (Std_Out , csbiInfo .wAttributes , len , coordScreen , & num );
573
+ SetConsoleCursorPosition (Std_Out , coordScreen );
574
+ }
575
+ state = -1 ;
576
+ } else {
577
+ state = -1 ;
578
+ }
579
+ break ; //End CASE 2
580
+ case 3 : //value2 start
581
+ if ( * cp >= (int )'0' && * cp <= (int )'9' ) {
582
+ value2 = ((value2 * 10 ) + (* cp - (int )'0' )) % 0xFFFF ;
583
+ state = 4 ;
584
+ } else if (* cp == ';' ) {
585
+ //do nothing
586
+ } else {
587
+ state = -1 ;
588
+ }
589
+ break ; //End CASE 3
590
+ case 4 : //value2 continue
591
+ if ( * cp >= (int )'0' && * cp <= (int )'9' ) {
592
+ value2 = ((value2 * 10 ) + (* cp - (int )'0' )) % 0xFFFF ;
593
+ state = 4 ;
594
+ } else if (* cp == 'm' ) {
595
+ attribute = Update_Graphic_Mode (attribute , value1 );
596
+ attribute = Update_Graphic_Mode (attribute , value2 );
597
+ SetConsoleTextAttribute (Std_Out , attribute );
598
+ state = -1 ;
599
+ } else if (* cp == ';' ) {
600
+ attribute = Update_Graphic_Mode (attribute , value1 );
601
+ attribute = Update_Graphic_Mode (attribute , value2 );
602
+ SetConsoleTextAttribute (Std_Out , attribute );
603
+ value1 = 0 ;
604
+ value2 = 0 ;
605
+ state = 1 ;
606
+ } else if (* cp == 'H' || * cp == 'f' ) {
607
+ coordScreen .X = value1 ;
608
+ coordScreen .Y = value2 ;
609
+ SetConsoleCursorPosition (Std_Out , coordScreen );
610
+ state = -1 ;
611
+ } else {
612
+ state = -1 ;
613
+ }
614
+
615
+
616
+ } //End: switch (state)
617
+ } while (state >= 0 );
618
+
619
+ return ++ cp ;
620
+ }
621
+
380
622
//*** Old fragments ***************************************************
381
623
382
624
#if OLD_CONSOLE_FILE_IO
0 commit comments