1 module scone.output.os.windows.cell_converter;
2 
3 version (Windows)
4 {
5     import core.sys.windows.windows;
6     import scone.output.types.cell : Cell;
7     import scone.output.types.color;
8     import std.conv : ConvOverflowException;
9     import std.conv : to;
10 
11     abstract final class CellConverter
12     {
13         public static CHAR_INFO toCharInfo(Cell cell, WORD initialAttributes)
14         {
15             wchar unicodeCharacter;
16 
17             try
18             {
19                 unicodeCharacter = to!wchar(cell.character);
20             }
21             catch (ConvOverflowException e)
22             {
23                 unicodeCharacter = '?';
24             }
25 
26             CHAR_INFO character;
27             character.UnicodeChar = unicodeCharacter;
28             character.Attributes = typeof(this).attributesFromCell(cell, initialAttributes);
29 
30             return character;
31         }
32 
33         private static WORD attributesFromCell(Cell cell, WORD initialAttributes)
34         {
35             WORD attributes;
36 
37             switch (cell.style.foreground.ansi)
38             {
39             case AnsiColor.initial:
40                 // take the inital colors, and filter out all flags except the foreground ones
41                 attributes |= (initialAttributes & (
42                         FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE));
43                 break;
44             case AnsiColor.blue:
45                 attributes |= FOREGROUND_INTENSITY | FOREGROUND_BLUE;
46                 break;
47             case AnsiColor.blueDark:
48                 attributes |= FOREGROUND_BLUE;
49                 break;
50             case AnsiColor.cyan:
51                 attributes |= FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE;
52                 break;
53             case AnsiColor.cyanDark:
54                 attributes |= FOREGROUND_GREEN | FOREGROUND_BLUE;
55                 break;
56             case AnsiColor.white:
57                 attributes |= FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
58                 break;
59             case AnsiColor.whiteDark:
60                 attributes |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
61                 break;
62             case AnsiColor.black:
63                 attributes |= FOREGROUND_INTENSITY;
64                 break;
65             case AnsiColor.blackDark:
66                 attributes |= 0;
67                 break;
68             case AnsiColor.green:
69                 attributes |= FOREGROUND_INTENSITY | FOREGROUND_GREEN;
70                 break;
71             case AnsiColor.greenDark:
72                 attributes |= FOREGROUND_GREEN;
73                 break;
74             case AnsiColor.magenta:
75                 attributes |= FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE;
76                 break;
77             case AnsiColor.magentaDark:
78                 attributes |= FOREGROUND_RED | FOREGROUND_BLUE;
79                 break;
80             case AnsiColor.red:
81                 attributes |= FOREGROUND_INTENSITY | FOREGROUND_RED;
82                 break;
83             case AnsiColor.redDark:
84                 attributes |= FOREGROUND_RED;
85                 break;
86             case AnsiColor.yellow:
87                 attributes |= FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN;
88                 break;
89             case AnsiColor.yellowDark:
90                 attributes |= FOREGROUND_RED | FOREGROUND_GREEN;
91                 break;
92             default:
93                 break;
94             }
95 
96             switch (cell.style.background.ansi)
97             {
98             case AnsiColor.initial:
99                 // take the inital colors, and filter out all flags except the background ones
100                 attributes |= (initialAttributes & (
101                         BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE));
102                 break;
103             case AnsiColor.blue:
104                 attributes |= BACKGROUND_INTENSITY | BACKGROUND_BLUE;
105                 break;
106             case AnsiColor.blueDark:
107                 attributes |= BACKGROUND_BLUE;
108                 break;
109             case AnsiColor.cyan:
110                 attributes |= BACKGROUND_INTENSITY | BACKGROUND_GREEN | BACKGROUND_BLUE;
111                 break;
112             case AnsiColor.cyanDark:
113                 attributes |= BACKGROUND_GREEN | BACKGROUND_BLUE;
114                 break;
115             case AnsiColor.white:
116                 attributes |= BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
117                 break;
118             case AnsiColor.whiteDark:
119                 attributes |= BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
120                 break;
121             case AnsiColor.black:
122                 attributes |= BACKGROUND_INTENSITY;
123                 break;
124             case AnsiColor.blackDark:
125                 attributes |= 0;
126                 break;
127             case AnsiColor.green:
128                 attributes |= BACKGROUND_INTENSITY | BACKGROUND_GREEN;
129                 break;
130             case AnsiColor.greenDark:
131                 attributes |= BACKGROUND_GREEN;
132                 break;
133             case AnsiColor.magenta:
134                 attributes |= BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_BLUE;
135                 break;
136             case AnsiColor.magentaDark:
137                 attributes |= BACKGROUND_RED | BACKGROUND_BLUE;
138                 break;
139             case AnsiColor.red:
140                 attributes |= BACKGROUND_INTENSITY | BACKGROUND_RED;
141                 break;
142             case AnsiColor.redDark:
143                 attributes |= BACKGROUND_RED;
144                 break;
145             case AnsiColor.yellow:
146                 attributes |= BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN;
147                 break;
148             case AnsiColor.yellowDark:
149                 attributes |= BACKGROUND_RED | BACKGROUND_GREEN;
150                 break;
151             default:
152                 break;
153             }
154 
155             return attributes;
156         }
157     }
158 }