nss: upgrade to release 3.73
[LibreOffice.git] / onlineupdate / source / update / updater / progressui_win.cxx
blob0b8017823486e7bdd14147f997032a904cb7f066
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifdef _WIN32
8 #include <stdio.h>
9 #ifndef UNICODE
10 #define UNICODE
11 #endif
12 #include <windows.h>
13 #include <commctrl.h>
14 #include <process.h>
15 #include <io.h>
17 #include "resource.h"
18 #include "progressui.h"
19 #include "readstrings.h"
20 #include "errors.h"
22 #define TIMER_ID 1
23 #define TIMER_INTERVAL 100
25 #define RESIZE_WINDOW(hwnd, extrax, extray) \
26 { \
27 RECT windowSize; \
28 GetWindowRect(hwnd, &windowSize); \
29 SetWindowPos(hwnd, 0, 0, 0, windowSize.right - windowSize.left + extrax, \
30 windowSize.bottom - windowSize.top + extray, \
31 SWP_NOMOVE | SWP_NOZORDER); \
34 #define MOVE_WINDOW(hwnd, dx, dy) \
35 { \
36 RECT rc; \
37 POINT pt; \
38 GetWindowRect(hwnd, &rc); \
39 pt.x = rc.left; \
40 pt.y = rc.top; \
41 ScreenToClient(GetParent(hwnd), &pt); \
42 SetWindowPos(hwnd, 0, pt.x + dx, pt.y + dy, 0, 0, \
43 SWP_NOSIZE | SWP_NOZORDER); \
46 static float sProgress; // between 0 and 100
47 static BOOL sQuit = FALSE;
48 static BOOL sIndeterminate = FALSE;
49 static StringTable sUIStrings;
51 static BOOL
52 GetStringsFile(WCHAR filename[MAX_PATH])
54 if (!GetModuleFileNameW(nullptr, filename, MAX_PATH))
55 return FALSE;
57 WCHAR *dot = wcsrchr(filename, '.');
58 if (!dot || wcsicmp(dot + 1, L"exe"))
59 return FALSE;
61 wcscpy(dot + 1, L"ini");
62 return TRUE;
65 static void
66 UpdateDialog(HWND hDlg)
68 int pos = int(sProgress + 0.5f);
69 HWND hWndPro = GetDlgItem(hDlg, IDC_PROGRESS);
70 SendMessage(hWndPro, PBM_SETPOS, pos, 0L);
73 // The code in this function is from MSDN:
74 // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/dialogboxes/usingdialogboxes.asp
75 static void
76 CenterDialog(HWND hDlg)
78 RECT rc, rcOwner, rcDlg;
80 // Get the owner window and dialog box rectangles.
81 HWND desktop = GetDesktopWindow();
83 GetWindowRect(desktop, &rcOwner);
84 GetWindowRect(hDlg, &rcDlg);
85 CopyRect(&rc, &rcOwner);
87 // Offset the owner and dialog box rectangles so that
88 // right and bottom values represent the width and
89 // height, and then offset the owner again to discard
90 // space taken up by the dialog box.
92 OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top);
93 OffsetRect(&rc, -rc.left, -rc.top);
94 OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom);
96 // The new position is the sum of half the remaining
97 // space and the owner's original position.
99 SetWindowPos(hDlg,
100 HWND_TOP,
101 rcOwner.left + (rc.right / 2),
102 rcOwner.top + (rc.bottom / 2),
103 0, 0, // ignores size arguments
104 SWP_NOSIZE);
107 static void
108 InitDialog(HWND hDlg)
110 WCHAR szwTitle[MAX_TEXT_LEN];
111 WCHAR szwInfo[MAX_TEXT_LEN];
113 MultiByteToWideChar(CP_UTF8, 0, sUIStrings.title, -1, szwTitle,
114 sizeof(szwTitle)/sizeof(szwTitle[0]));
115 MultiByteToWideChar(CP_UTF8, 0, sUIStrings.info, -1, szwInfo,
116 sizeof(szwInfo)/sizeof(szwInfo[0]));
118 SetWindowTextW(hDlg, szwTitle);
119 SetWindowTextW(GetDlgItem(hDlg, IDC_INFO), szwInfo);
121 // Set dialog icon
122 HICON hIcon = LoadIcon(GetModuleHandle(nullptr),
123 MAKEINTRESOURCE(IDI_DIALOG));
124 if (hIcon)
125 SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
127 HWND hWndPro = GetDlgItem(hDlg, IDC_PROGRESS);
128 SendMessage(hWndPro, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
129 if (sIndeterminate)
131 LONG_PTR val = GetWindowLongPtr(hWndPro, GWL_STYLE);
132 SetWindowLongPtr(hWndPro, GWL_STYLE, val|PBS_MARQUEE);
133 SendMessage(hWndPro,(UINT) PBM_SETMARQUEE,(WPARAM) TRUE,(LPARAM)50 );
136 // Resize the dialog to fit all of the text if necessary.
137 RECT infoSize, textSize;
138 HWND hWndInfo = GetDlgItem(hDlg, IDC_INFO);
140 // Get the control's font for calculating the new size for the control
141 HDC hDCInfo = GetDC(hWndInfo);
142 HFONT hInfoFont;
143 HFONT hOldFont = 0;
144 hInfoFont = (HFONT)SendMessage(hWndInfo, WM_GETFONT, 0, 0);
146 if (hInfoFont)
147 hOldFont = (HFONT)SelectObject(hDCInfo, hInfoFont);
149 // Measure the space needed for the text on a single line. DT_CALCRECT means
150 // nothing is drawn.
151 if (DrawText(hDCInfo, szwInfo, -1, &textSize,
152 DT_CALCRECT | DT_NOCLIP | DT_SINGLELINE))
154 GetClientRect(hWndInfo, &infoSize);
155 SIZE extra;
156 // Calculate the additional space needed for the text by subtracting from
157 // the rectangle returned by DrawText the existing client rectangle's width
158 // and height.
159 extra.cx = (textSize.right - textSize.left) - \
160 (infoSize.right - infoSize.left);
161 extra.cy = (textSize.bottom - textSize.top) - \
162 (infoSize.bottom - infoSize.top);
163 if (extra.cx < 0)
164 extra.cx = 0;
165 if (extra.cy < 0)
166 extra.cy = 0;
167 if ((extra.cx > 0) || (extra.cy > 0))
169 RESIZE_WINDOW(hDlg, extra.cx, extra.cy);
170 RESIZE_WINDOW(hWndInfo, extra.cx, extra.cy);
171 RESIZE_WINDOW(hWndPro, extra.cx, 0);
172 MOVE_WINDOW(hWndPro, 0, extra.cy);
176 if (hOldFont)
177 SelectObject(hDCInfo, hOldFont);
179 ReleaseDC(hWndInfo, hDCInfo);
181 CenterDialog(hDlg); // make dialog appear in the center of the screen
183 SetTimer(hDlg, TIMER_ID, TIMER_INTERVAL, nullptr);
186 // Message handler for update dialog.
187 static LRESULT CALLBACK
188 DialogProc(HWND hDlg, UINT message, WPARAM /*wParam*/, LPARAM /*lParam*/)
190 switch (message)
192 case WM_INITDIALOG:
193 InitDialog(hDlg);
194 return TRUE;
196 case WM_TIMER:
197 if (sQuit)
199 EndDialog(hDlg, 0);
201 else
203 UpdateDialog(hDlg);
205 return TRUE;
207 case WM_COMMAND:
208 return TRUE;
210 return FALSE;
214 InitProgressUI(int* /*argc*/, WCHAR*** /*argv*/)
216 return 0;
220 * Initializes the progress UI strings
222 * @return 0 on success, -1 on error
225 InitProgressUIStrings()
227 // If we do not have updater.ini, then we should not bother showing UI.
228 WCHAR filename[MAX_PATH];
229 if (!GetStringsFile(filename))
231 strcpy(sUIStrings.title, "LibreOffice Update");
232 strcpy(sUIStrings.info, "Please wait while we update your installation.");
233 return 0;
236 if (_waccess(filename, 04))
238 strcpy(sUIStrings.title, "LibreOffice Update");
239 strcpy(sUIStrings.info, "Please wait while we update your installation.");
240 return 0;
243 // If the updater.ini doesn't have the required strings, then we should not
244 // bother showing UI.
245 if (ReadStrings(filename, &sUIStrings) != OK)
247 strcpy(sUIStrings.title, "LibreOffice Update");
248 strcpy(sUIStrings.info, "Please wait while we update your installation.");
251 return 0;
255 ShowProgressUI(bool indeterminate, bool initUIStrings)
257 sIndeterminate = indeterminate;
258 if (!indeterminate)
260 // Only show the Progress UI if the process is taking a significant amount of
261 // time where a significant amount of time is defined as .5 seconds after
262 // ShowProgressUI is called sProgress is less than 70.
263 Sleep(500);
265 if (sQuit || sProgress > 70.0f)
266 return 0;
269 // Don't load the UI if there's an <exe_name>.Local directory for redirection.
270 WCHAR appPath[MAX_PATH + 1] = { L'\0' };
271 if (!GetModuleFileNameW(nullptr, appPath, MAX_PATH))
273 return -1;
276 if (wcslen(appPath) + wcslen(L".Local") >= MAX_PATH)
278 return -1;
281 wcscat(appPath, L".Local");
283 if (!_waccess(appPath, 04))
285 return -1;
288 // Don't load the UI if the strings for the UI are not provided.
289 if (initUIStrings && InitProgressUIStrings() == -1)
291 return -1;
294 if (!GetModuleFileNameW(nullptr, appPath, MAX_PATH))
296 return -1;
299 // Use an activation context that supports visual styles for the controls.
300 ACTCTXW actx = {0};
301 actx.cbSize = sizeof(ACTCTXW);
302 actx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
303 actx.hModule = GetModuleHandle(NULL); // Use the embedded manifest
304 // This is needed only for Win XP but doesn't cause a problem with other
305 // versions of Windows.
306 actx.lpSource = appPath;
307 actx.lpResourceName = MAKEINTRESOURCE(IDR_COMCTL32_MANIFEST);
309 HANDLE hactx = CreateActCtxW(&actx);
310 ULONG_PTR actxCookie = NULL;
311 if (hactx != INVALID_HANDLE_VALUE)
313 // Push the specified activation context to the top of the activation stack.
314 ActivateActCtx(hactx, &actxCookie);
317 INITCOMMONCONTROLSEX icc =
319 sizeof(INITCOMMONCONTROLSEX),
320 ICC_PROGRESS_CLASS
322 InitCommonControlsEx(&icc);
324 DialogBox(GetModuleHandle(nullptr),
325 MAKEINTRESOURCE(IDD_DIALOG), nullptr,
326 (DLGPROC) DialogProc);
328 if (hactx != INVALID_HANDLE_VALUE)
330 // Deactivate the context now that the comctl32.dll is loaded.
331 DeactivateActCtx(0, actxCookie);
334 return 0;
337 void
338 QuitProgressUI()
340 sQuit = TRUE;
343 void
344 UpdateProgressUI(float progress)
346 sProgress = progress; // 32-bit writes are atomic
348 #endif // _WIN32