--- /dev/null
+/*
+ * LICENSE: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Console Server DLL
+ * FILE: win32ss/user/winsrv/consrv/popup.c
+ * PURPOSE: Console popup windows
+ * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ *
+ * NOTE: Strongly inspired by the DrawBox function
+ * from base/setup/usetup/interface/usetup.c, written by:
+ * Eric Kohl (revision 3753)
+ * Hervé Poussineau (revision 24718)
+ * and *UiDisplayMenu from FreeLdr.
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "consrv.h"
+#include "popup.h"
+
+#define NDEBUG
+#include <debug.h>
+
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+NTSTATUS NTAPI
+ConDrvFillConsoleOutput(IN PCONSOLE Console,
+ IN PTEXTMODE_SCREEN_BUFFER Buffer,
+ IN CODE_TYPE CodeType,
+ IN CODE_ELEMENT Code,
+ IN ULONG NumCodesToWrite,
+ IN PCOORD WriteCoord,
+ OUT PULONG NumCodesWritten OPTIONAL);
+NTSTATUS NTAPI
+ConDrvReadConsoleOutput(IN PCONSOLE Console,
+ IN PTEXTMODE_SCREEN_BUFFER Buffer,
+ IN BOOLEAN Unicode,
+ OUT PCHAR_INFO CharInfo/*Buffer*/,
+ IN OUT PSMALL_RECT ReadRegion);
+NTSTATUS NTAPI
+ConDrvWriteConsoleOutput(IN PCONSOLE Console,
+ IN PTEXTMODE_SCREEN_BUFFER Buffer,
+ IN BOOLEAN Unicode,
+ IN PCHAR_INFO CharInfo/*Buffer*/,
+ IN OUT PSMALL_RECT WriteRegion);
+
+
+static VOID
+DrawBox(PTEXTMODE_SCREEN_BUFFER Buffer,
+ IN SHORT xLeft,
+ IN SHORT yTop,
+ IN SHORT Width,
+ IN SHORT Height)
+{
+ COORD coPos;
+ DWORD Written;
+
+ /* Set screen attributes */
+ coPos.X = xLeft;
+ for (coPos.Y = yTop; coPos.Y < yTop + Height; coPos.Y++)
+ {
+ ConDrvFillConsoleOutput(Buffer->Header.Console,
+ Buffer,
+ CODE_ATTRIBUTE,
+ (CODE_ELEMENT)(WORD)Buffer->PopupDefaultAttrib,
+ Width,
+ &coPos,
+ &Written);
+ }
+
+ /* draw upper left corner */
+ coPos.X = xLeft;
+ coPos.Y = yTop;
+ ConDrvFillConsoleOutput(Buffer->Header.Console,
+ Buffer,
+ CODE_ASCII,
+ (CODE_ELEMENT)(CHAR)0xDA, // '+',
+ 1,
+ &coPos,
+ &Written);
+
+ /* draw upper edge */
+ coPos.X = xLeft + 1;
+ coPos.Y = yTop;
+ ConDrvFillConsoleOutput(Buffer->Header.Console,
+ Buffer,
+ CODE_ASCII,
+ (CODE_ELEMENT)(CHAR)0xC4, // '-',
+ Width - 2,
+ &coPos,
+ &Written);
+
+ /* draw upper right corner */
+ coPos.X = xLeft + Width - 1;
+ coPos.Y = yTop;
+ ConDrvFillConsoleOutput(Buffer->Header.Console,
+ Buffer,
+ CODE_ASCII,
+ (CODE_ELEMENT)(CHAR)0xBF, // '+',
+ 1,
+ &coPos,
+ &Written);
+
+ /* Draw right edge, inner space and left edge */
+ for (coPos.Y = yTop + 1; coPos.Y < yTop + Height - 1; coPos.Y++)
+ {
+ coPos.X = xLeft;
+ ConDrvFillConsoleOutput(Buffer->Header.Console,
+ Buffer,
+ CODE_ASCII,
+ (CODE_ELEMENT)(CHAR)0xB3, // '|',
+ 1,
+ &coPos,
+ &Written);
+
+ coPos.X = xLeft + 1;
+ ConDrvFillConsoleOutput(Buffer->Header.Console,
+ Buffer,
+ CODE_ASCII,
+ (CODE_ELEMENT)(CHAR)' ',
+ Width - 2,
+ &coPos,
+ &Written);
+
+ coPos.X = xLeft + Width - 1;
+ ConDrvFillConsoleOutput(Buffer->Header.Console,
+ Buffer,
+ CODE_ASCII,
+ (CODE_ELEMENT)(CHAR)0xB3, // '|',
+ 1,
+ &coPos,
+ &Written);
+ }
+
+ /* draw lower left corner */
+ coPos.X = xLeft;
+ coPos.Y = yTop + Height - 1;
+ ConDrvFillConsoleOutput(Buffer->Header.Console,
+ Buffer,
+ CODE_ASCII,
+ (CODE_ELEMENT)(CHAR)0xC0, // '+',
+ 1,
+ &coPos,
+ &Written);
+
+ /* draw lower edge */
+ coPos.X = xLeft + 1;
+ coPos.Y = yTop + Height - 1;
+ ConDrvFillConsoleOutput(Buffer->Header.Console,
+ Buffer,
+ CODE_ASCII,
+ (CODE_ELEMENT)(CHAR)0xC4, // '-',
+ Width - 2,
+ &coPos,
+ &Written);
+
+ /* draw lower right corner */
+ coPos.X = xLeft + Width - 1;
+ coPos.Y = yTop + Height - 1;
+ ConDrvFillConsoleOutput(Buffer->Header.Console,
+ Buffer,
+ CODE_ASCII,
+ (CODE_ELEMENT)(CHAR)0xD9, // '+',
+ 1,
+ &coPos,
+ &Written);
+}
+
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+PPOPUP_WINDOW
+CreatePopupWindow(PTEXTMODE_SCREEN_BUFFER Buffer,
+ SHORT xLeft,
+ SHORT yTop,
+ SHORT Width,
+ SHORT Height)
+{
+ PPOPUP_WINDOW Popup;
+ SMALL_RECT Region;
+
+ /* Create the popup window */
+ Popup = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*Popup));
+ if (Popup == NULL) return NULL;
+
+ Popup->ScreenBuffer = Buffer;
+ Popup->Origin.X = xLeft;
+ Popup->Origin.Y = yTop;
+ Popup->Size.X = Width;
+ Popup->Size.Y = Height;
+
+ /* Save old contents */
+ Popup->OldContents = ConsoleAllocHeap(HEAP_ZERO_MEMORY,
+ Popup->Size.X * Popup->Size.Y *
+ sizeof(*Popup->OldContents));
+ if (Popup->OldContents == NULL)
+ {
+ ConsoleFreeHeap(Popup);
+ return NULL;
+ }
+ Region.Left = Popup->Origin.X;
+ Region.Top = Popup->Origin.Y;
+ Region.Right = Popup->Origin.X + Popup->Size.X - 1;
+ Region.Bottom = Popup->Origin.Y + Popup->Size.Y - 1;
+ ConDrvReadConsoleOutput(Buffer->Header.Console,
+ Buffer,
+ TRUE,
+ Popup->OldContents,
+ &Region);
+
+ /* Draw it */
+ DrawBox(Buffer,
+ xLeft, yTop,
+ Width, Height);
+
+ /* Add it into the list of popups */
+ InsertTailList(&Buffer->Header.Console->PopupWindows, &Popup->ListEntry);
+
+ return Popup;
+}
+
+VOID
+DestroyPopupWindow(PPOPUP_WINDOW Popup)
+{
+ SMALL_RECT Region;
+
+ if (Popup == NULL) return;
+
+ /* Remove it from the list of popups */
+ RemoveEntryList(&Popup->ListEntry);
+
+ /* Restore the old screen-buffer contents */
+ Region.Left = Popup->Origin.X;
+ Region.Top = Popup->Origin.Y;
+ Region.Right = Popup->Origin.X + Popup->Size.X - 1;
+ Region.Bottom = Popup->Origin.Y + Popup->Size.Y - 1;
+ ConDrvWriteConsoleOutput(Popup->ScreenBuffer->Header.Console,
+ Popup->ScreenBuffer,
+ TRUE,
+ Popup->OldContents,
+ &Region);
+
+ /* Free memory */
+ ConsoleFreeHeap(Popup->OldContents);
+ ConsoleFreeHeap(Popup);
+}
+
+/* EOF */