1 /* AbiCollab - Code to enable the modification of remote documents.
2  * Copyright (C) 2007 by Ryan Pavlik <abiryan@ryand.net>
3  * Copyright (C) 2006,2008 by Marc Maurer <uwog@uwog.net>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301 USA.
19  */
20 
21 #include <windows.h>
22 #include "xap_App.h"
23 #include "ap_Win32App.h"
24 #include "xap_Win32App.h"
25 #include "xap_Frame.h"
26 #include "xap_Win32DialogHelper.h"
27 #include "ut_string_class.h"
28 #include <session/xp/AbiCollabSessionManager.h>
29 #include <account/xp/AccountHandler.h>
30 
31 #include "ap_Win32Dialog_CollaborationAddAccount.h"
32 
33 // We can't seem to pass user data to our custom message proc,
34 // which is why we have the static dialog pointer below
35 static AP_Win32Dialog_CollaborationAddAccount* s_pThis = NULL;
36 
s_dlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)37 BOOL CALLBACK AP_Win32Dialog_CollaborationAddAccount::s_dlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
38 {
39 	switch (msg)
40 	{
41 		case WM_INITDIALOG:
42 		{
43 			AP_Win32Dialog_CollaborationAddAccount* pThis = (AP_Win32Dialog_CollaborationAddAccount *)lParam;
44 			UT_return_val_if_fail(pThis, false);
45 			SetWindowLongPtrW(hWnd,DWLP_USER,lParam);
46 			return pThis->_onInitDialog(hWnd,wParam,lParam);
47 		}
48 		case WM_COMMAND:
49 		{
50 			AP_Win32Dialog_CollaborationAddAccount* pThis = (AP_Win32Dialog_CollaborationAddAccount *)GetWindowLongPtrW(hWnd,DWLP_USER);
51 			UT_return_val_if_fail(pThis, false);
52 			return pThis->_onCommand(hWnd,wParam,lParam);
53 		}
54 		case WM_DESTROY:
55 		{
56 			UT_DEBUGMSG(("Got WM_DESTROY\n"));
57 			AP_Win32Dialog_CollaborationAddAccount* pThis = (AP_Win32Dialog_CollaborationAddAccount *)GetWindowLongPtrW(hWnd,DWLP_USER);
58 			UT_return_val_if_fail(pThis, false);
59 			DELETEP(pThis->m_pWin32Dialog);
60 			return true;
61 		}
62 		default:
63 			return false;
64 	}
65 }
66 
s_detailsProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)67 BOOL CALLBACK AP_Win32Dialog_CollaborationAddAccount::s_detailsProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
68 {
69 	AP_Win32Dialog_CollaborationAddAccount* pThis = (AP_Win32Dialog_CollaborationAddAccount *)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
70 	UT_return_val_if_fail(pThis, false);
71 
72 	switch (msg)
73 	{
74 		case WM_COMMAND:
75 			if (pThis->_onDetailsCommand(hWnd, msg, wParam, lParam))
76 				return true;
77 			return pThis->detailsProc(hWnd, msg, wParam, lParam);
78 		default:
79 			return pThis->detailsProc(hWnd, msg, wParam, lParam);
80 	}
81 }
82 
static_constructor(XAP_DialogFactory * pFactory,XAP_Dialog_Id id)83 XAP_Dialog * AP_Win32Dialog_CollaborationAddAccount::static_constructor(XAP_DialogFactory * pFactory, XAP_Dialog_Id id)
84 {
85 	return static_cast<XAP_Dialog *>(new AP_Win32Dialog_CollaborationAddAccount(pFactory, id));
86 }
87 pt2Constructor ap_Dialog_CollaborationAddAccount_Constructor = &AP_Win32Dialog_CollaborationAddAccount::static_constructor;
88 
AP_Win32Dialog_CollaborationAddAccount(XAP_DialogFactory * pDlgFactory,XAP_Dialog_Id id)89 AP_Win32Dialog_CollaborationAddAccount::AP_Win32Dialog_CollaborationAddAccount(XAP_DialogFactory * pDlgFactory, XAP_Dialog_Id id)
90 	: AP_Dialog_CollaborationAddAccount(pDlgFactory, id),
91 	m_pWin32Dialog(NULL),
92 	m_hInstance(NULL),
93 	m_hOk(NULL),
94 	m_pOldDetailsProc(NULL),
95 	m_hWnd(NULL),
96 	m_hDetails(NULL),
97 	m_hDetailsHook(NULL)
98 {
99 	AbiCollabSessionManager * pSessionManager = AbiCollabSessionManager::getManager();
100 	if (pSessionManager)
101 	{
102 		m_hInstance=pSessionManager->getInstance();
103 	}
104 
105 	// hack
106 	s_pThis = this;
107 }
108 
runModal(XAP_Frame * pFrame)109 void AP_Win32Dialog_CollaborationAddAccount::runModal(XAP_Frame * pFrame)
110 {
111 	UT_return_if_fail(pFrame);
112 	UT_return_if_fail(m_hInstance);
113 
114 	// create the dialog
115 	LPCTSTR lpTemplate = MAKEINTRESOURCE(AP_RID_DIALOG_COLLABORATIONADDACCOUNT);
116 	int result = DialogBoxParam( m_hInstance, lpTemplate,
117 		static_cast<XAP_Win32FrameImpl*>(pFrame->getFrameImpl())->getTopLevelWindow(),
118 		(DLGPROC)s_dlgProc, (LPARAM)this );
119 	switch (result)
120 	{
121 		case 0:
122 			// MSDN: If the function fails because the hWndParent parameter is invalid, the return value is zero.
123 			break;
124 		case -1:
125 			UT_DEBUGMSG(("Win32 error: %d.  lpTemplate: %d, RID:%d\n", GetLastError(), lpTemplate, AP_RID_DIALOG_COLLABORATIONADDACCOUNT));
126 			break;
127 		default:
128 			break;
129 	};
130 
131 	UnhookWindowsHookEx(m_hDetailsHook);
132 	m_hDetailsHook = NULL;
133 
134 	s_pThis = NULL;
135 }
136 
137 /*****************************************************************/
_onInitDialog(HWND hWnd,WPARAM wParam,LPARAM lParam)138 BOOL AP_Win32Dialog_CollaborationAddAccount::_onInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
139 {
140 	// Store handles for easy access
141 	m_hWnd = hWnd;
142 	m_hOk = GetDlgItem(hWnd, AP_RID_DIALOG_COLLABORATIONADDACCOUNT_OK_BUTTON);
143 	UT_return_val_if_fail(m_hOk, false);
144 	m_hDetails = GetDlgItem(hWnd, AP_RID_DIALOG_COLLABORATIONADDACCOUNT_DETAILS_BOX);
145 	UT_return_val_if_fail(m_hDetails, false);
146 
147 	// trap the messages that will be sent to the m_hDetails window, so we can forward
148 	// them to the account handler
149 	m_pOldDetailsProc = GetWindowLongPtrW(m_hDetails, GWLP_WNDPROC);
150 	SetWindowLongPtrW(m_hDetails, GWLP_WNDPROC, (LPARAM)s_detailsProc);
151 	SetWindowLongPtrW(m_hDetails, GWLP_USERDATA, (LPARAM)this);
152 
153 	// we need to trap the account details window's message hook,
154 	// so we can make TAB stops work
155 	m_hDetailsHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)s_detailsGetMsgProc, m_hInstance, GetCurrentThreadId());
156 
157 	// Get ourselves a custom DialogHelper
158 	DELETEP(m_pWin32Dialog);
159 	m_pWin32Dialog = new XAP_Win32DialogHelper(hWnd);
160 
161 	// Set up dialog initial state
162 	_populateWindowData();
163 
164 	// Center Window
165 	m_pWin32Dialog->centerDialog();
166 
167 	return true;
168 }
169 
170 // return true if we process the command, false otherwise
_onCommand(HWND hWnd,WPARAM wParam,LPARAM lParam)171 BOOL AP_Win32Dialog_CollaborationAddAccount::_onCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
172 {
173 	WORD wNotifyCode = HIWORD(wParam);
174 	WORD wId = LOWORD(wParam);
175 
176 	AccountHandler* pHandler;
177 	switch (wId)
178 	{
179 	case AP_RID_DIALOG_COLLABORATIONADDACCOUNT_TYPECOMBO:
180 		// Oh hey, something happened to the typecombo!
181 		if (wNotifyCode == CBN_SELCHANGE)
182 		{
183 			// New account type selected
184 			UT_DEBUGMSG(("Add Account - New handler type selected\n"));
185 			pHandler = _getActiveAccountHandler();
186 			if (pHandler)
187 			{
188 				UT_DEBUGMSG(("Changed account handler to type: %s\n", pHandler->getDisplayType().utf8_str()));
189 				_setAccountHandler(pHandler);
190 			}
191 			else
192 				UT_DEBUGMSG(("No account handler types to select; this makes abicollab kinda pointless...\n"));
193 
194 			return true;
195 		}
196 		return false;
197 
198 	case AP_RID_DIALOG_COLLABORATIONADDACCOUNT_OK_BUTTON:
199 		UT_DEBUGMSG(("Add Account - OK button clicked\n"));
200 		pHandler = _getActiveAccountHandler();
201 		// if pHandler is no good, then we tell Windows we didn't handle the button
202 		UT_return_val_if_fail(pHandler, 1);
203 		pHandler->storeProperties();
204 		m_answer=AP_Dialog_CollaborationAddAccount::a_OK;
205 		EndDialog(hWnd,0);
206 		return true;
207 
208 	case AP_RID_DIALOG_COLLABORATIONADDACCOUNT_CANCEL_BUTTON:
209 		// Close without applying changes
210 		EndDialog(hWnd,0);
211 		m_answer=AP_Dialog_CollaborationAddAccount::a_CANCEL;
212 		return true;
213 
214 	default:
215 		// WM_COMMAND message NOT processed
216 		return false;
217 	}
218 }
219 
_onDetailsCommand(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)220 BOOL AP_Win32Dialog_CollaborationAddAccount::_onDetailsCommand(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
221 {
222 	AccountHandler* pAccountHandler = _getActiveAccountHandler();
223 	UT_return_val_if_fail(pAccountHandler, false);
224 	return pAccountHandler->_onCommand(hWnd, wParam, lParam);
225 }
226 
detailsProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)227 BOOL AP_Win32Dialog_CollaborationAddAccount::detailsProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
228 {
229 	return CallWindowProc((WNDPROC)m_pOldDetailsProc, hWnd, msg, wParam, lParam);
230 }
231 
s_detailsGetMsgProc(int nCode,WPARAM wParam,LPARAM lParam)232 LRESULT AP_Win32Dialog_CollaborationAddAccount::s_detailsGetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
233 {
234 	if (s_pThis)
235 		return s_pThis->detailsGetMsgProc(nCode, wParam, lParam);
236 	return CallNextHookEx(NULL, nCode, wParam, lParam);
237 }
238 
detailsGetMsgProc(int nCode,WPARAM wParam,LPARAM lParam)239 LRESULT AP_Win32Dialog_CollaborationAddAccount::detailsGetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
240 {
241 	LPMSG lpMsg = (LPMSG)lParam;
242 
243 	if (nCode >= 0 && PM_REMOVE == wParam)
244 	{
245 		// Don't translate non-input events.
246 		if ((lpMsg->message >= WM_KEYFIRST && lpMsg->message <= WM_KEYLAST))
247 		{
248 			AccountHandler* pAccount = _getActiveAccountHandler();
249 			HWND hwnd = pAccount && pAccount->shouldProcessFocus() ? m_hDetails : m_hWnd;
250 			if (IsDialogMessage(hwnd, lpMsg))
251 			{
252 				// The value returned from this hookproc is ignored,
253 				// and it cannot be used to tell Windows the message
254 				// has been handled. To avoid further processing,
255 				// convert the message to WM_NULL before returning.
256 				lpMsg->message = WM_NULL;
257 				lpMsg->lParam = 0;
258 				lpMsg->wParam  = 0;
259 			}
260 		}
261 	}
262 	return CallNextHookEx(NULL, nCode, wParam, lParam);
263 }
264 
_populateWindowData()265 void AP_Win32Dialog_CollaborationAddAccount::_populateWindowData()
266 {
267 	UT_DEBUGMSG(("AP_Win32Dialog_CollaborationAddAccount::_populateWindowData()\n"));
268 
269 	AbiCollabSessionManager* pSessionManager = AbiCollabSessionManager::getManager();
270 	UT_return_if_fail(pSessionManager);
271 
272 	UT_return_if_fail(m_pWin32Dialog);
273 
274 	const std::map<UT_UTF8String, AccountHandlerConstructor>& registeredAccounts = pSessionManager->getRegisteredAccountHandlers();
275 	for (std::map<UT_UTF8String, AccountHandlerConstructor>::const_iterator cit = registeredAccounts.begin(); cit != registeredAccounts.end(); cit++)
276 	{
277 		AccountHandlerConstructor pConstructor = (*cit).second;
278 		UT_continue_if_fail(pConstructor);
279 
280 		// TODO: we need to free these somewhere
281 		AccountHandler* pHandler = pConstructor();
282 		UT_continue_if_fail(pHandler);
283 
284 		UT_sint32 index = m_pWin32Dialog->addItemToCombo(AP_RID_DIALOG_COLLABORATIONADDACCOUNT_TYPECOMBO, (LPCSTR) AP_Win32App::s_fromUTF8ToWinLocale(pHandler->getDisplayType().utf8_str()).c_str());
285 		if (index >= 0)
286 		{
287 			UT_DEBUGMSG(("Added handler to index %d\n", index));
288 			m_vAccountTypeCombo.insert(m_vAccountTypeCombo.begin()+index, pHandler);
289 		}
290 		else
291 			UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
292 	}
293 
294 	// if we have at least one account handler, then make sure the first one is selected
295 	if (pSessionManager->getRegisteredAccountHandlers().size() > 0)
296 	{
297 		m_pWin32Dialog->selectComboItem(AP_RID_DIALOG_COLLABORATIONADDACCOUNT_TYPECOMBO, 0);
298 		// Note, this requires that the backends be alright with having their widgets destroyed before being created.
299 		// TCP does this, but I didn't add such code to any other backends yet.  --RP 22 July 2007
300 		UT_DEBUGMSG(("Add Account - New handler type selected\n"));
301 		AccountHandler* pHandler = _getActiveAccountHandler();
302 		if (pHandler)
303 		{
304 			UT_DEBUGMSG(("Changed account handler to type: %s\n", pHandler->getDisplayType().utf8_str()));
305 			_setAccountHandler(pHandler);
306 		}
307 		else
308 			UT_DEBUGMSG(("No account handler types to select; this makes abicollab kinda pointless...\n"));
309 
310 	}
311 	else
312 	{
313 		// nope, we don't have any account handler :'-(
314 		// Add a sample item to show that we can.  Then, disable the box and the ok button
315 		m_pWin32Dialog->addItemToCombo(AP_RID_DIALOG_COLLABORATIONADDACCOUNT_TYPECOMBO, (LPCSTR) "No Handlers!");
316 		m_pWin32Dialog->selectComboItem(AP_RID_DIALOG_COLLABORATIONADDACCOUNT_TYPECOMBO, 0);
317 		m_pWin32Dialog->enableControl(AP_RID_DIALOG_COLLABORATIONADDACCOUNT_TYPECOMBO, false);
318 		m_pWin32Dialog->enableControl(AP_RID_DIALOG_COLLABORATIONADDACCOUNT_OK_BUTTON, false);
319 	}
320 }
321 
_getEmbeddingParent()322 void* AP_Win32Dialog_CollaborationAddAccount::_getEmbeddingParent()
323 {
324 	return m_hDetails;
325 }
326 
_getActiveAccountHandler()327 AccountHandler* AP_Win32Dialog_CollaborationAddAccount::_getActiveAccountHandler()
328 {
329 	UT_DEBUGMSG(("AP_Win32Dialog_CollaborationAddAccount::_getActiveAccountHandler()\n"));
330 	UT_return_val_if_fail(m_pWin32Dialog, NULL);
331 
332 	int index = m_pWin32Dialog->getComboSelectedIndex(AP_RID_DIALOG_COLLABORATIONADDACCOUNT_TYPECOMBO);
333 	UT_return_val_if_fail(index >= 0 && index < static_cast<UT_sint32>(m_vAccountTypeCombo.size()), NULL);
334 
335 	// check the return value of this function!
336 	return m_vAccountTypeCombo[index];
337 }
338 
setBackendValidity(bool valid)339 void AP_Win32Dialog_CollaborationAddAccount::setBackendValidity(bool valid)
340 {
341 	EnableWindow(m_hOk, valid);
342 }
343 
344