calc: on editing invalidation of view with different zoom is wrong
[LibreOffice.git] / shell / source / win32 / spsupp / spsuppHelper.cxx
blobaf3509b87c8b9697076c5e50f287ae347f622339
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <prewin.h>
11 #include <postwin.h>
13 #include <comphelper/windowserrorstring.hxx>
14 #include <i18nlangtag/languagetag.hxx>
15 #include <o3tl/char16_t2wchar_t.hxx>
16 #include <osl/file.hxx>
17 #include <rtl/bootstrap.hxx>
18 #include <spsuppStrings.hrc>
19 #include <unotools/resmgr.hxx>
20 #include "res/spsuppDlg.h"
22 // Since we need to show localized messages to user before starting LibreOffice, we need to
23 // bootstrap part of LO (l10n machinery). This implies loading some LO libraries, and since
24 // there are ActiveX controls for both x86 and x64 for use in corresponding clients, they
25 // can't both load the libraries that exist only for one architecture, like sal. Thus we need
26 // a dedicated helper process, which is launched by ActiveX, and handle user interactions.
28 namespace
30 const OUString& GetSofficeExe()
32 static const OUString s_sPath = []() {
33 OUString result;
34 wchar_t sPath[MAX_PATH];
35 if (GetModuleFileNameW(nullptr, sPath, MAX_PATH) == 0)
36 return result;
37 wchar_t* pSlashPos = wcsrchr(sPath, L'\\');
38 if (pSlashPos == nullptr)
39 return result;
40 wcscpy(pSlashPos + 1, L"soffice.exe");
41 result = o3tl::toU(sPath);
42 return result;
43 }();
44 return s_sPath;
47 OUString GetString(TranslateId pResId)
49 static const std::locale s_pLocale = [] {
50 // Initialize soffice bootstrap: see getIniFileName_Impl for reference
51 OUString sPath = GetSofficeExe();
52 if (const sal_Int32 nDotPos = sPath.lastIndexOf('.'); nDotPos >= 0)
54 sPath = sPath.replaceAt(nDotPos, sPath.getLength() - nDotPos, SAL_CONFIGFILE(u""));
55 if (osl::FileBase::getFileURLFromSystemPath(sPath, sPath) == osl::FileBase::E_None)
56 rtl::Bootstrap::setIniFilename(sPath);
58 return Translate::Create("shell", LanguageTag("")); // Use system language
59 }();
60 return Translate::get(pResId, s_pLocale);
63 INT_PTR CALLBACK EditOrRODlgproc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
65 switch (Msg)
67 case WM_INITDIALOG:
69 if (const wchar_t* sFilePath = reinterpret_cast<const wchar_t*>(lParam))
71 OUString sMsg = GetString(RID_STR_SP_VIEW_OR_EDIT_TITLE);
72 SetWindowTextW(hDlg, o3tl::toW(sMsg.getStr()));
73 sMsg = GetString(RID_STR_SP_VIEW_OR_EDIT_MESSAGE)
74 .replaceFirst("%DOCNAME", o3tl::toU(sFilePath));
75 SetWindowTextW(GetDlgItem(hDlg, IDC_EDIT_OR_RO), o3tl::toW(sMsg.getStr()));
76 sMsg = GetString(RID_STR_SP_VIEW_OR_EDIT_VIEW);
77 SetWindowTextW(GetDlgItem(hDlg, ID_RO), o3tl::toW(sMsg.getStr()));
78 sMsg = GetString(RID_STR_SP_VIEW_OR_EDIT_EDIT);
79 SetWindowTextW(GetDlgItem(hDlg, ID_EDIT), o3tl::toW(sMsg.getStr()));
80 sMsg = GetString(RID_STR_SP_VIEW_OR_EDIT_CANCEL);
81 SetWindowTextW(GetDlgItem(hDlg, IDCANCEL), o3tl::toW(sMsg.getStr()));
83 return TRUE; // set default focus
85 case WM_COMMAND:
87 WORD nId = LOWORD(wParam);
88 switch (nId)
90 case IDCANCEL:
91 case ID_RO:
92 case ID_EDIT:
93 EndDialog(hDlg, nId);
94 return TRUE;
96 break;
99 return FALSE;
102 enum class Answer
104 Cancel,
105 ReadOnly,
106 Edit
109 Answer AskIfUserWantsToEdit(const wchar_t* sFilePath)
111 Answer res = Answer::Cancel;
112 INT_PTR nResult = DialogBoxParamW(nullptr, MAKEINTRESOURCEW(IDD_EDIT_OR_RO), nullptr,
113 EditOrRODlgproc, reinterpret_cast<LPARAM>(sFilePath));
114 if (nResult == ID_RO)
115 res = Answer::ReadOnly;
116 else if (nResult == ID_EDIT)
117 res = Answer::Edit;
118 return res;
121 // Returns ERROR_SUCCESS or Win32 error code
122 DWORD LOStart(const wchar_t* sModeArg, const wchar_t* sFilePath)
124 OUString sCmdLine = "\"" + GetSofficeExe() + "\" " + o3tl::toU(sModeArg) + " \""
125 + o3tl::toU(sFilePath) + "\"";
126 LPWSTR pCmdLine = const_cast<LPWSTR>(o3tl::toW(sCmdLine.getStr()));
128 STARTUPINFOW si = {};
129 si.cb = sizeof si;
130 si.dwFlags = STARTF_USESHOWWINDOW;
131 si.wShowWindow = SW_SHOW;
132 PROCESS_INFORMATION pi{};
133 if (!CreateProcessW(nullptr, pCmdLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi))
135 DWORD dwError = GetLastError();
136 const OUString sErrorMsg = "Could not start LibreOffice. Error is 0x"
137 + OUString::number(dwError, 16) + ":\n\n"
138 + WindowsErrorString(dwError);
140 // Report the error to user and return error
141 MessageBoxW(nullptr, o3tl::toW(sErrorMsg.getStr()), nullptr, MB_ICONERROR);
142 return dwError;
144 CloseHandle(pi.hProcess);
145 CloseHandle(pi.hThread);
146 return ERROR_SUCCESS;
149 int CreateNewDocument(LPCWSTR TemplateLocation, LPCWSTR /*DefaultSaveLocation*/)
151 // TODO: resolve the program from varProgID (nullptr -> default?)
152 DWORD nResult = LOStart(L"-n", TemplateLocation);
153 return nResult == ERROR_SUCCESS ? 0 : 2;
156 // UseLocalCopy would be either "0" or "1", denoting boolean value
157 int EditDocument(LPCWSTR DocumentLocation, LPCWSTR /*UseLocalCopy*/, LPCWSTR /*varProgID*/)
159 // TODO: resolve the program from varProgID (nullptr -> default?)
160 DWORD nResult = LOStart(L"-o", DocumentLocation);
161 return nResult == ERROR_SUCCESS ? 0 : 2;
164 // Possible values for OpenType
166 // "0" When checked out, or when the document library does not require check out, the user can read or edit the document
167 // "1" When another user has checked it out, the user can only read the document
168 // "2" When the current user has checked it out, the user can only edit the document
169 // "3" When the document is not checked out and the document library requires that documents be checked out to be edited, the user can only read the document, or check it out and edit it
170 // "4" When the current user has checked it out, the user can only edit the local copy of the document
171 int ViewDocument(LPCWSTR DocumentLocation, LPCWSTR OpenType, LPCWSTR varProgID)
173 if (wcscmp(OpenType, L"0") == 0)
175 switch (AskIfUserWantsToEdit(DocumentLocation))
177 case Answer::Cancel:
178 return 1;
179 case Answer::ReadOnly:
180 break;
181 case Answer::Edit:
182 return EditDocument(DocumentLocation, L"0", varProgID);
185 // TODO: resolve the program from varProgID (nullptr -> default?)
186 DWORD nResult = LOStart(L"--view", DocumentLocation);
187 return nResult == ERROR_SUCCESS ? 0 : 2;
189 } // namespace
191 // Returns 0 on success, 1 when operation wasn't performed because user cancelled, 2 on an error
192 int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
194 int argc = 0;
195 const LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
196 if (argc < 2)
197 return 2; // Wrong argument count
199 if (wcscmp(argv[1], L"CreateNewDocument") == 0)
201 if (argc != 4)
202 return 2; // Wrong argument count
203 return CreateNewDocument(argv[2], argv[3]);
206 if (wcscmp(argv[1], L"ViewDocument") == 0)
208 if (argc != 4 && argc != 5)
209 return 2; // Wrong argument count
210 LPCWSTR pProgId = argc == 5 ? argv[4] : nullptr;
211 return ViewDocument(argv[2], argv[3], pProgId);
214 if (wcscmp(argv[1], L"EditDocument") == 0)
216 if (argc != 4 && argc != 5)
217 return 2; // Wrong argument count
218 LPCWSTR pProgId = argc == 5 ? argv[4] : nullptr;
219 return EditDocument(argv[2], argv[3], pProgId);
222 return 2; // Wrong command
225 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */