[CONSRV]
[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
58 /* Set screen attributes */
59 coPos.X = xLeft;
60 for (coPos.Y = yTop; coPos.Y < yTop + Height; coPos.Y++)
61 {
62 ConDrvFillConsoleOutput(Buffer->Header.Console,
63 Buffer,
64 CODE_ATTRIBUTE,
65 (CODE_ELEMENT)(WORD)Buffer->PopupDefaultAttrib,
66 Width,
67 &coPos,
68 &Written);
69 }
70
71 /* draw upper left corner */
72 coPos.X = xLeft;
73 coPos.Y = yTop;
74 ConDrvFillConsoleOutput(Buffer->Header.Console,
75 Buffer,
76 CODE_ASCII,
77 (CODE_ELEMENT)(CHAR)0xDA, // '+',
78 1,
79 &coPos,
80 &Written);
81
82 /* draw upper edge */
83 coPos.X = xLeft + 1;
84 coPos.Y = yTop;
85 ConDrvFillConsoleOutput(Buffer->Header.Console,
86 Buffer,
87 CODE_ASCII,
88 (CODE_ELEMENT)(CHAR)0xC4, // '-',
89 Width - 2,
90 &coPos,
91 &Written);
92
93 /* draw upper right corner */
94 coPos.X = xLeft + Width - 1;
95 coPos.Y = yTop;
96 ConDrvFillConsoleOutput(Buffer->Header.Console,
97 Buffer,
98 CODE_ASCII,
99 (CODE_ELEMENT)(CHAR)0xBF, // '+',
100 1,
101 &coPos,
102 &Written);
103
104 /* Draw right edge, inner space and left edge */
105 for (coPos.Y = yTop + 1; coPos.Y < yTop + Height - 1; coPos.Y++)
106 {
107 coPos.X = xLeft;
108 ConDrvFillConsoleOutput(Buffer->Header.Console,
109 Buffer,
110 CODE_ASCII,
111 (CODE_ELEMENT)(CHAR)0xB3, // '|',
112 1,
113 &coPos,
114 &Written);
115
116 coPos.X = xLeft + 1;
117 ConDrvFillConsoleOutput(Buffer->Header.Console,
118 Buffer,
119 CODE_ASCII,
120 (CODE_ELEMENT)(CHAR)' ',
121 Width - 2,
122 &coPos,
123 &Written);
124
125 coPos.X = xLeft + Width - 1;
126 ConDrvFillConsoleOutput(Buffer->Header.Console,
127 Buffer,
128 CODE_ASCII,
129 (CODE_ELEMENT)(CHAR)0xB3, // '|',
130 1,
131 &coPos,
132 &Written);
133 }
134
135 /* draw lower left corner */
136 coPos.X = xLeft;
137 coPos.Y = yTop + Height - 1;
138 ConDrvFillConsoleOutput(Buffer->Header.Console,
139 Buffer,
140 CODE_ASCII,
141 (CODE_ELEMENT)(CHAR)0xC0, // '+',
142 1,
143 &coPos,
144 &Written);
145
146 /* draw lower edge */
147 coPos.X = xLeft + 1;
148 coPos.Y = yTop + Height - 1;
149 ConDrvFillConsoleOutput(Buffer->Header.Console,
150 Buffer,
151 CODE_ASCII,
152 (CODE_ELEMENT)(CHAR)0xC4, // '-',
153 Width - 2,
154 &coPos,
155 &Written);
156
157 /* draw lower right corner */
158 coPos.X = xLeft + Width - 1;
159 coPos.Y = yTop + Height - 1;
160 ConDrvFillConsoleOutput(Buffer->Header.Console,
161 Buffer,
162 CODE_ASCII,
163 (CODE_ELEMENT)(CHAR)0xD9, // '+',
164 1,
165 &coPos,
166 &Written);
167 }
168
169
170 /* PUBLIC FUNCTIONS ***********************************************************/
171
172 PPOPUP_WINDOW
173 CreatePopupWindow(PCONSRV_CONSOLE Console,
174 PTEXTMODE_SCREEN_BUFFER Buffer,
175 SHORT xLeft,
176 SHORT yTop,
177 SHORT Width,
178 SHORT Height)
179 {
180 PPOPUP_WINDOW Popup;
181 SMALL_RECT Region;
182
183 ASSERT((PCONSOLE)Console == Buffer->Header.Console);
184
185 /* Create the popup window */
186 Popup = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*Popup));
187 if (Popup == NULL) return NULL;
188
189 Popup->ScreenBuffer = Buffer;
190 Popup->Origin.X = xLeft;
191 Popup->Origin.Y = yTop;
192 Popup->Size.X = Width;
193 Popup->Size.Y = Height;
194
195 /* Save old contents */
196 Popup->OldContents = ConsoleAllocHeap(HEAP_ZERO_MEMORY,
197 Popup->Size.X * Popup->Size.Y *
198 sizeof(*Popup->OldContents));
199 if (Popup->OldContents == NULL)
200 {
201 ConsoleFreeHeap(Popup);
202 return NULL;
203 }
204 Region.Left = Popup->Origin.X;
205 Region.Top = Popup->Origin.Y;
206 Region.Right = Popup->Origin.X + Popup->Size.X - 1;
207 Region.Bottom = Popup->Origin.Y + Popup->Size.Y - 1;
208 ConDrvReadConsoleOutput(Buffer->Header.Console,
209 Buffer,
210 TRUE,
211 Popup->OldContents,
212 &Region);
213
214 /* Draw it */
215 DrawBox(Buffer,
216 xLeft, yTop,
217 Width, Height);
218
219 /* Add it into the list of popups */
220 InsertTailList(&Console->PopupWindows, &Popup->ListEntry);
221
222 return Popup;
223 }
224
225 VOID
226 DestroyPopupWindow(PPOPUP_WINDOW Popup)
227 {
228 SMALL_RECT Region;
229
230 if (Popup == NULL) return;
231
232 /* Remove it from the list of popups */
233 RemoveEntryList(&Popup->ListEntry);
234
235 /* Restore the old screen-buffer contents */
236 Region.Left = Popup->Origin.X;
237 Region.Top = Popup->Origin.Y;
238 Region.Right = Popup->Origin.X + Popup->Size.X - 1;
239 Region.Bottom = Popup->Origin.Y + Popup->Size.Y - 1;
240 ConDrvWriteConsoleOutput(Popup->ScreenBuffer->Header.Console,
241 Popup->ScreenBuffer,
242 TRUE,
243 Popup->OldContents,
244 &Region);
245
246 /* Free memory */
247 ConsoleFreeHeap(Popup->OldContents);
248 ConsoleFreeHeap(Popup);
249 }
250
251 /* EOF */