46d3af57268a06c2f17b5836f5f8ef6ed279c1ee
[reactos.git] / win32ss / user / winsrv / consrv / popup.c
1 /*
2 * LICENSE: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/winsrv/consrv/popup.c
5 * PURPOSE: Console popup windows
6 * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
7 *
8 * NOTE: Strongly inspired by the DrawBox function
9 * from base/setup/usetup/interface/usetup.c, written by:
10 * Eric Kohl (revision 3753)
11 * Hervé Poussineau (revision 24718)
12 * and *UiDisplayMenu from FreeLdr.
13 */
14
15 /* INCLUDES *******************************************************************/
16
17 #include "consrv.h"
18 #include "popup.h"
19
20 #define NDEBUG
21 #include <debug.h>
22
23
24 /* PRIVATE FUNCTIONS **********************************************************/
25
26 NTSTATUS NTAPI
27 ConDrvFillConsoleOutput(IN PCONSOLE Console,
28 IN PTEXTMODE_SCREEN_BUFFER Buffer,
29 IN CODE_TYPE CodeType,
30 IN CODE_ELEMENT Code,
31 IN ULONG NumCodesToWrite,
32 IN PCOORD WriteCoord,
33 OUT PULONG NumCodesWritten OPTIONAL);
34 NTSTATUS NTAPI
35 ConDrvReadConsoleOutput(IN PCONSOLE Console,
36 IN PTEXTMODE_SCREEN_BUFFER Buffer,
37 IN BOOLEAN Unicode,
38 OUT PCHAR_INFO CharInfo/*Buffer*/,
39 IN OUT PSMALL_RECT ReadRegion);
40 NTSTATUS NTAPI
41 ConDrvWriteConsoleOutput(IN PCONSOLE Console,
42 IN PTEXTMODE_SCREEN_BUFFER Buffer,
43 IN BOOLEAN Unicode,
44 IN PCHAR_INFO CharInfo/*Buffer*/,
45 IN OUT PSMALL_RECT WriteRegion);
46
47
48 static VOID
49 DrawBox(PTEXTMODE_SCREEN_BUFFER Buffer,
50 IN SHORT xLeft,
51 IN SHORT yTop,
52 IN SHORT Width,
53 IN SHORT Height)
54 {
55 COORD coPos;
56 DWORD Written;
57 CODE_ELEMENT Code;
58
59 /* Set screen attributes */
60 coPos.X = xLeft;
61 for (coPos.Y = yTop; coPos.Y < yTop + Height; coPos.Y++)
62 {
63 Code.Attribute = Buffer->PopupDefaultAttrib;
64 ConDrvFillConsoleOutput(Buffer->Header.Console,
65 Buffer,
66 CODE_ATTRIBUTE,
67 Code,
68 Width,
69 &coPos,
70 &Written);
71 }
72
73 /* draw upper left corner */
74 coPos.X = xLeft;
75 coPos.Y = yTop;
76 Code.AsciiChar = 0xDA; // '+'
77 ConDrvFillConsoleOutput(Buffer->Header.Console,
78 Buffer,
79 CODE_ASCII,
80 Code,
81 1,
82 &coPos,
83 &Written);
84
85 /* draw upper edge */
86 coPos.X = xLeft + 1;
87 coPos.Y = yTop;
88 Code.AsciiChar = 0xC4; // '-'
89 ConDrvFillConsoleOutput(Buffer->Header.Console,
90 Buffer,
91 CODE_ASCII,
92 Code,
93 Width - 2,
94 &coPos,
95 &Written);
96
97 /* draw upper right corner */
98 coPos.X = xLeft + Width - 1;
99 coPos.Y = yTop;
100 Code.AsciiChar = 0xBF; // '+'
101 ConDrvFillConsoleOutput(Buffer->Header.Console,
102 Buffer,
103 CODE_ASCII,
104 Code,
105 1,
106 &coPos,
107 &Written);
108
109 /* Draw right edge, inner space and left edge */
110 for (coPos.Y = yTop + 1; coPos.Y < yTop + Height - 1; coPos.Y++)
111 {
112 coPos.X = xLeft;
113 Code.AsciiChar = 0xB3; // '|'
114 ConDrvFillConsoleOutput(Buffer->Header.Console,
115 Buffer,
116 CODE_ASCII,
117 Code,
118 1,
119 &coPos,
120 &Written);
121
122 coPos.X = xLeft + 1;
123 Code.AsciiChar = ' ';
124 ConDrvFillConsoleOutput(Buffer->Header.Console,
125 Buffer,
126 CODE_ASCII,
127 Code,
128 Width - 2,
129 &coPos,
130 &Written);
131
132 coPos.X = xLeft + Width - 1;
133 Code.AsciiChar = 0xB3; // '|'
134 ConDrvFillConsoleOutput(Buffer->Header.Console,
135 Buffer,
136 CODE_ASCII,
137 Code,
138 1,
139 &coPos,
140 &Written);
141 }
142
143 /* draw lower left corner */
144 coPos.X = xLeft;
145 coPos.Y = yTop + Height - 1;
146 Code.AsciiChar = 0xC0; // '+'
147 ConDrvFillConsoleOutput(Buffer->Header.Console,
148 Buffer,
149 CODE_ASCII,
150 Code,
151 1,
152 &coPos,
153 &Written);
154
155 /* draw lower edge */
156 coPos.X = xLeft + 1;
157 coPos.Y = yTop + Height - 1;
158 Code.AsciiChar = 0xC4; // '-'
159 ConDrvFillConsoleOutput(Buffer->Header.Console,
160 Buffer,
161 CODE_ASCII,
162 Code,
163 Width - 2,
164 &coPos,
165 &Written);
166
167 /* draw lower right corner */
168 coPos.X = xLeft + Width - 1;
169 coPos.Y = yTop + Height - 1;
170 Code.AsciiChar = 0xD9; // '+'
171 ConDrvFillConsoleOutput(Buffer->Header.Console,
172 Buffer,
173 CODE_ASCII,
174 Code,
175 1,
176 &coPos,
177 &Written);
178 }
179
180
181 /* PUBLIC FUNCTIONS ***********************************************************/
182
183 PPOPUP_WINDOW
184 CreatePopupWindow(
185 IN PCONSRV_CONSOLE Console,
186 IN PCONSOLE_SCREEN_BUFFER ScreenBuffer,
187 IN SHORT xLeft,
188 IN SHORT yTop,
189 IN SHORT Width,
190 IN SHORT Height)
191 {
192 PTEXTMODE_SCREEN_BUFFER Buffer;
193 PPOPUP_WINDOW Popup;
194 SMALL_RECT Region;
195
196 ASSERT((PCONSOLE)Console == ScreenBuffer->Header.Console);
197
198 if (GetType(ScreenBuffer) != TEXTMODE_BUFFER)
199 return NULL;
200
201 Buffer = (PTEXTMODE_SCREEN_BUFFER)ScreenBuffer;
202
203 /* Create the popup window */
204 Popup = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*Popup));
205 if (Popup == NULL) return NULL;
206
207 Popup->ScreenBuffer = Buffer;
208 Popup->Origin.X = xLeft;
209 Popup->Origin.Y = yTop;
210 Popup->Size.X = Width;
211 Popup->Size.Y = Height;
212
213 /* Save old contents */
214 Popup->OldContents = ConsoleAllocHeap(HEAP_ZERO_MEMORY,
215 Popup->Size.X * Popup->Size.Y *
216 sizeof(*Popup->OldContents));
217 if (Popup->OldContents == NULL)
218 {
219 ConsoleFreeHeap(Popup);
220 return NULL;
221 }
222 Region.Left = Popup->Origin.X;
223 Region.Top = Popup->Origin.Y;
224 Region.Right = Popup->Origin.X + Popup->Size.X - 1;
225 Region.Bottom = Popup->Origin.Y + Popup->Size.Y - 1;
226 ConDrvReadConsoleOutput(Buffer->Header.Console,
227 Buffer,
228 TRUE,
229 Popup->OldContents,
230 &Region);
231
232 /* Draw it */
233 DrawBox(Buffer,
234 xLeft, yTop,
235 Width, Height);
236
237 /* Add it into the list of popups */
238 InsertTailList(&Console->PopupWindows, &Popup->ListEntry);
239
240 return Popup;
241 }
242
243 VOID
244 DestroyPopupWindow(
245 IN PPOPUP_WINDOW Popup)
246 {
247 SMALL_RECT Region;
248
249 if (Popup == NULL) return;
250
251 /* Remove it from the list of popups */
252 RemoveEntryList(&Popup->ListEntry);
253
254 /* Restore the old screen-buffer contents */
255 Region.Left = Popup->Origin.X;
256 Region.Top = Popup->Origin.Y;
257 Region.Right = Popup->Origin.X + Popup->Size.X - 1;
258 Region.Bottom = Popup->Origin.Y + Popup->Size.Y - 1;
259 ConDrvWriteConsoleOutput(Popup->ScreenBuffer->Header.Console,
260 Popup->ScreenBuffer,
261 TRUE,
262 Popup->OldContents,
263 &Region);
264
265 /* Free memory */
266 ConsoleFreeHeap(Popup->OldContents);
267 ConsoleFreeHeap(Popup);
268 }
269
270 /* EOF */