[CONSOLE.CPL][CONSRV]
[reactos.git] / win32ss / user / winsrv / consrv / frontends / gui / guisettings.c
index b30d68a..a3969fe 100644 (file)
@@ -98,7 +98,8 @@ GuiConsoleReadUserSettings(IN OUT PGUI_CONSOLE_INFO TermInfo,
         }
         else if (!wcscmp(szValueName, L"FontSize"))
         {
-            TermInfo->FontSize = Value;
+            TermInfo->FontSize.X = LOWORD(Value); // Width
+            TermInfo->FontSize.Y = HIWORD(Value); // Height
             RetVal = TRUE;
         }
         else if (!wcscmp(szValueName, L"FontWeight"))
@@ -159,7 +160,10 @@ do {
 
     SetConsoleSetting(L"FaceName", REG_SZ, (wcslen(TermInfo->FaceName) + 1) * sizeof(WCHAR), TermInfo->FaceName, L'\0'); // wcsnlen
     SetConsoleSetting(L"FontFamily", REG_DWORD, sizeof(DWORD), &TermInfo->FontFamily, FF_DONTCARE);
-    SetConsoleSetting(L"FontSize", REG_DWORD, sizeof(DWORD), &TermInfo->FontSize, 0);
+
+    Storage = MAKELONG(TermInfo->FontSize.X, TermInfo->FontSize.Y); // Width, Height
+    SetConsoleSetting(L"FontSize", REG_DWORD, sizeof(DWORD), &Storage, 0);
+
     SetConsoleSetting(L"FontWeight", REG_DWORD, sizeof(DWORD), &TermInfo->FontWeight, FW_DONTCARE);
 
     Storage = TermInfo->FullScreen;
@@ -193,16 +197,16 @@ GuiConsoleGetDefaultSettings(IN OUT PGUI_CONSOLE_INFO TermInfo,
      * 1. Load the default values
      */
     // wcsncpy(TermInfo->FaceName, L"DejaVu Sans Mono", LF_FACESIZE);
-    // TermInfo->FontSize = MAKELONG(12, 8); // 0x0008000C; // font is 8x12
+    // TermInfo->FontSize = MAKELONG(8, 12); // 0x000C0008; // font is 8x12
     // TermInfo->FontSize = MAKELONG(16, 16); // font is 16x16
     // TermInfo->FontWeight = FW_NORMAL;
 
     wcsncpy(TermInfo->FaceName, L"VGA", LF_FACESIZE); // HACK: !!
     // TermInfo->FaceName[0] = L'\0';
     TermInfo->FontFamily = FF_DONTCARE;
-    TermInfo->FontSize   = 0;
+    TermInfo->FontSize.X = 0;
+    TermInfo->FontSize.Y = 0;
     TermInfo->FontWeight = FW_DONTCARE;
-    TermInfo->UseRasterFonts = TRUE;
 
     TermInfo->FullScreen   = FALSE;
     TermInfo->ShowWindow   = SW_SHOWNORMAL;
@@ -328,7 +332,6 @@ GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData,
         GuiInfo->FontFamily = GuiData->GuiInfo.FontFamily;
         GuiInfo->FontSize   = GuiData->GuiInfo.FontSize;
         GuiInfo->FontWeight = GuiData->GuiInfo.FontWeight;
-        GuiInfo->UseRasterFonts = GuiData->GuiInfo.UseRasterFonts;
         GuiInfo->FullScreen = GuiData->GuiInfo.FullScreen;
         GuiInfo->AutoPosition = GuiData->GuiInfo.AutoPosition;
         GuiInfo->WindowOrigin = GuiData->GuiInfo.WindowOrigin;
@@ -415,6 +418,92 @@ Quit:
     return;
 }
 
+
+
+
+BOOL
+ChangeFont(PGUI_CONSOLE_DATA GuiData,
+           LPWSTR FaceName, // Points to a WCHAR array of LF_FACESIZE elements.
+           ULONG  FontFamily,
+           COORD  FontSize,
+           ULONG  FontWeight)
+{
+    HDC hDC;
+    HFONT OldFont, NewFont;
+    TEXTMETRICW Metrics;
+    SIZE CharSize;
+    SIZE_T Length;
+
+    NewFont = CreateFontW(FontSize.Y,
+                          0, // FontSize.X,
+                          0,
+                          TA_BASELINE,
+                          FontWeight,
+                          FALSE,
+                          FALSE,
+                          FALSE,
+                          OEM_CHARSET,
+                          OUT_DEFAULT_PRECIS,
+                          CLIP_DEFAULT_PRECIS,
+                          NONANTIALIASED_QUALITY,
+                          FIXED_PITCH | FontFamily /* FF_DONTCARE */,
+                          FaceName);
+    if (NewFont == NULL)
+    {
+        DPRINT1("ChangeFont: CreateFont failed\n");
+        return FALSE;
+    }
+
+    hDC = GetDC(GuiData->hWindow);
+    if (hDC == NULL)
+    {
+        DPRINT1("ChangeFont: GetDC failed\n");
+        DeleteObject(NewFont);
+        return FALSE;
+    }
+
+    OldFont = SelectObject(hDC, NewFont);
+    if (OldFont == NULL)
+    {
+        DPRINT1("ChangeFont: SelectObject failed\n");
+        ReleaseDC(GuiData->hWindow, hDC);
+        DeleteObject(NewFont);
+        return FALSE;
+    }
+
+    if (!GetTextMetricsW(hDC, &Metrics))
+    {
+        DPRINT1("ChangeFont: GetTextMetrics failed\n");
+        SelectObject(hDC, OldFont);
+        ReleaseDC(GuiData->hWindow, hDC);
+        DeleteObject(NewFont);
+        return FALSE;
+    }
+    GuiData->CharWidth  = Metrics.tmMaxCharWidth;
+    GuiData->CharHeight = Metrics.tmHeight + Metrics.tmExternalLeading;
+
+    /* Measure real char width more precisely if possible. */
+    if (GetTextExtentPoint32W(hDC, L"R", 1, &CharSize))
+        GuiData->CharWidth = CharSize.cx;
+
+    SelectObject(hDC, OldFont);
+    ReleaseDC(GuiData->hWindow, hDC);
+
+    if (GuiData->Font != NULL) DeleteObject(GuiData->Font);
+    GuiData->Font = NewFont;
+
+    Length = min(wcslen(FaceName) + 1, LF_FACESIZE); // wcsnlen
+    wcsncpy(GuiData->GuiInfo.FaceName, FaceName, LF_FACESIZE);
+    GuiData->GuiInfo.FaceName[Length] = L'\0'; // NULL-terminate
+    GuiData->GuiInfo.FontFamily     = FontFamily;
+    GuiData->GuiInfo.FontSize       = FontSize;
+    GuiData->GuiInfo.FontWeight     = FontWeight;
+
+    return TRUE;
+}
+
+
+
 VOID
 GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData,
                      HANDLE hClientSection,
@@ -457,7 +546,7 @@ GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData,
                                 &ViewSize,
                                 ViewUnmap,
                                 0,
-                                PAGE_READONLY);
+                                PAGE_READWRITE);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("Error when mapping view of file, Status = %lu\n", Status);
@@ -496,6 +585,15 @@ GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData,
 
             // memcpy(&GuiData->GuiInfo, GuiInfo, sizeof(GUI_CONSOLE_INFO));
 
+            /* Change the font */
+            ChangeFont(GuiData,
+                       GuiInfo->FaceName,
+                       GuiInfo->FontFamily,
+                       GuiInfo->FontSize,
+                       GuiInfo->FontWeight);
+           // HACK, needed because changing font may change the size of the window
+           /**/TermResizeTerminal(Console);/**/
+
             /* Move the window to the user's values */
             GuiData->GuiInfo.AutoPosition = GuiInfo->AutoPosition;
             GuiData->GuiInfo.WindowOrigin = GuiInfo->WindowOrigin;
@@ -544,4 +642,188 @@ Quit:
     return;
 }
 
+/*
+ * Function for dealing with the undocumented message and structure used by
+ * Windows' console.dll for setting console info.
+ * See http://www.catch22.net/sites/default/source/files/setconsoleinfo.c
+ * and http://www.scn.rain.com/~neighorn/PDF/MSBugPaper.pdf
+ * for more information.
+ */
+VOID
+GuiApplyWindowsConsoleSettings(PGUI_CONSOLE_DATA GuiData,
+                               HANDLE hClientSection)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    PCONSOLE Console = GuiData->Console;
+    PCONSOLE_PROCESS_DATA ProcessData;
+    HANDLE hSection = NULL;
+    ULONG ViewSize = 0;
+    PCONSOLE_STATE_INFO pConInfo = NULL;
+    CONSOLE_INFO     ConInfo;
+    GUI_CONSOLE_INFO GuiInfo;
+    SIZE_T Length;
+
+    if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return;
+
+    /* Get the console leader process, our client */
+    ProcessData = ConSrvGetConsoleLeaderProcess(Console);
+
+    /* Duplicate the section handle for ourselves */
+    Status = NtDuplicateObject(ProcessData->Process->ProcessHandle,
+                               hClientSection,
+                               NtCurrentProcess(),
+                               &hSection,
+                               0, 0, DUPLICATE_SAME_ACCESS);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Error when mapping client handle, Status = %lu\n", Status);
+        goto Quit;
+    }
+
+    /* Get a view of the shared section */
+    Status = NtMapViewOfSection(hSection,
+                                NtCurrentProcess(),
+                                (PVOID*)&pConInfo,
+                                0,
+                                0,
+                                NULL,
+                                &ViewSize,
+                                ViewUnmap,
+                                0,
+                                PAGE_READWRITE);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Error when mapping view of file, Status = %lu\n", Status);
+        goto Quit;
+    }
+
+    _SEH2_TRY
+    {
+        /* Check that the section is well-sized */
+        if ( (ViewSize < sizeof(CONSOLE_STATE_INFO)) ||
+             (pConInfo->cbSize != sizeof(CONSOLE_STATE_INFO)) )
+        {
+            DPRINT1("Error: section bad-sized: sizeof(Section) < sizeof(CONSOLE_STATE_INFO)\n");
+            Status = STATUS_INVALID_VIEW_SIZE;
+            _SEH2_YIELD(goto Quit);
+        }
+
+        // TODO: Check that GuiData->hWindow == pConInfo->hConsoleWindow
+
+        /* Retrieve terminal informations */
+
+        // Console information
+        ConInfo.HistoryBufferSize = pConInfo->HistoryBufferSize;
+        ConInfo.NumberOfHistoryBuffers = pConInfo->NumberOfHistoryBuffers;
+        ConInfo.HistoryNoDup = !!pConInfo->HistoryNoDup;
+        ConInfo.QuickEdit = !!pConInfo->QuickEdit;
+        ConInfo.InsertMode = !!pConInfo->InsertMode;
+        ConInfo.ScreenBufferSize = pConInfo->ScreenBufferSize;
+        ConInfo.ConsoleSize = pConInfo->WindowSize;
+        ConInfo.CursorSize = pConInfo->CursorSize;
+        ConInfo.ScreenAttrib = pConInfo->ScreenColors;
+        ConInfo.PopupAttrib = pConInfo->PopupColors;
+        memcpy(&ConInfo.Colors, pConInfo->ColorTable, sizeof(ConInfo.Colors));
+        ConInfo.CodePage = pConInfo->CodePage;
+        /**ConInfo.ConsoleTitle[MAX_PATH + 1] = pConInfo->ConsoleTitle; // FIXME: memcpy**/
+#if 0
+        /* Title of the console, original one corresponding to the one set by the console leader */
+        Length = min(sizeof(pConInfo->ConsoleTitle) / sizeof(pConInfo->ConsoleTitle[0]) - 1,
+               Console->OriginalTitle.Length / sizeof(WCHAR));
+        wcsncpy(pSharedInfo->ci.ConsoleTitle, Console->OriginalTitle.Buffer, Length);
+#endif
+        // ULONG   ConInfo.InputBufferSize = pConInfo->
+        // BOOLEAN ConInfo.CursorBlinkOn = pConInfo->
+        // BOOLEAN ConInfo.ForceCursorOff = pConInfo->
+
+
+        // Terminal information
+        Length = min(wcslen(pConInfo->FaceName) + 1, LF_FACESIZE); // wcsnlen
+        wcsncpy(GuiInfo.FaceName, pConInfo->FaceName, LF_FACESIZE);
+        GuiInfo.FaceName[Length] = L'\0';
+
+        GuiInfo.FontFamily = pConInfo->FontFamily;
+        GuiInfo.FontSize = pConInfo->FontSize;
+        GuiInfo.FontWeight = pConInfo->FontWeight;
+        GuiInfo.FullScreen = !!pConInfo->FullScreen;
+        GuiInfo.AutoPosition = !!pConInfo->AutoPosition;
+        GuiInfo.WindowOrigin = pConInfo->WindowPosition;
+        // WORD  GuiInfo.ShowWindow = pConInfo->
+
+
+
+        /*
+         * If we don't set the default parameters,
+         * apply them, otherwise just save them.
+         */
+#if 0
+        if (pConInfo->ShowDefaultParams == FALSE)
+#endif
+        {
+            /* Set the console informations */
+            ConSrvApplyUserSettings(Console, &ConInfo);
+
+            /* Set the terminal informations */
+
+            // memcpy(&GuiData->GuiInfo, &GuiInfo, sizeof(GUI_CONSOLE_INFO));
+
+            /* Change the font */
+            ChangeFont(GuiData,
+                       GuiInfo.FaceName,
+                       GuiInfo.FontFamily,
+                       GuiInfo.FontSize,
+                       GuiInfo.FontWeight);
+           // HACK, needed because changing font may change the size of the window
+           /**/TermResizeTerminal(Console);/**/
+
+            /* Move the window to the user's values */
+            GuiData->GuiInfo.AutoPosition = GuiInfo.AutoPosition;
+            GuiData->GuiInfo.WindowOrigin = GuiInfo.WindowOrigin;
+            GuiConsoleMoveWindow(GuiData);
+
+            InvalidateRect(GuiData->hWindow, NULL, TRUE);
+
+            /*
+             * Apply full-screen mode.
+             */
+            if (GuiInfo.FullScreen != GuiData->GuiInfo.FullScreen)
+            {
+                SwitchFullScreen(GuiData, GuiInfo.FullScreen);
+            }
+        }
+
+#if 0
+        /*
+         * Save settings if needed
+         */
+        // FIXME: Do it in the console properties applet ??
+        if (SaveSettings)
+        {
+            DWORD ProcessId = HandleToUlong(ProcessData->Process->ClientId.UniqueProcess);
+            ConSrvWriteUserSettings(&ConInfo, ProcessId);
+            GuiConsoleWriteUserSettings(&GuiInfo, ConInfo.ConsoleTitle, ProcessId);
+        }
+#endif
+
+        Status = STATUS_SUCCESS;
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = _SEH2_GetExceptionCode();
+        DPRINT1("GuiApplyUserSettings - Caught an exception, Status = %08X\n", Status);
+    }
+    _SEH2_END;
+
+Quit:
+    /* Finally, close the section and return */
+    if (hSection)
+    {
+        NtUnmapViewOfSection(NtCurrentProcess(), pConInfo);
+        NtClose(hSection);
+    }
+
+    LeaveCriticalSection(&Console->Lock);
+    return;
+}
+
 /* EOF */