1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir #include <memory>
29*cdf0e10cSrcweir 
30*cdf0e10cSrcweir #include "vos/mutex.hxx"
31*cdf0e10cSrcweir #include "vcl/svapp.hxx"
32*cdf0e10cSrcweir #include "vcl/msgbox.hxx"
33*cdf0e10cSrcweir 
34*cdf0e10cSrcweir #include "com/sun/star/task/XInteractionAbort.hpp"
35*cdf0e10cSrcweir #include "com/sun/star/task/XInteractionApprove.hpp"
36*cdf0e10cSrcweir #include "com/sun/star/task/XInteractionDisapprove.hpp"
37*cdf0e10cSrcweir #include "com/sun/star/task/XInteractionRetry.hpp"
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir #include "tools/errinf.hxx" // ErrorHandler, ErrorContext, ...
40*cdf0e10cSrcweir #include "svtools/svtools.hrc" // RID_ERRHDL
41*cdf0e10cSrcweir 
42*cdf0e10cSrcweir #include "ids.hrc"
43*cdf0e10cSrcweir #include "getcontinuations.hxx"
44*cdf0e10cSrcweir 
45*cdf0e10cSrcweir #include "iahndl.hxx"
46*cdf0e10cSrcweir 
47*cdf0e10cSrcweir using namespace com::sun::star;
48*cdf0e10cSrcweir 
49*cdf0e10cSrcweir namespace {
50*cdf0e10cSrcweir 
51*cdf0e10cSrcweir sal_uInt16
52*cdf0e10cSrcweir executeErrorDialog(
53*cdf0e10cSrcweir     Window * pParent,
54*cdf0e10cSrcweir     task::InteractionClassification eClassification,
55*cdf0e10cSrcweir     rtl::OUString const & rContext,
56*cdf0e10cSrcweir     rtl::OUString const & rMessage,
57*cdf0e10cSrcweir     WinBits nButtonMask)
58*cdf0e10cSrcweir     SAL_THROW((uno::RuntimeException))
59*cdf0e10cSrcweir {
60*cdf0e10cSrcweir     vos::OGuard aGuard(Application::GetSolarMutex());
61*cdf0e10cSrcweir 
62*cdf0e10cSrcweir     rtl::OUStringBuffer aText(rContext);
63*cdf0e10cSrcweir     if (rContext.getLength() != 0 && rMessage.getLength() != 0)
64*cdf0e10cSrcweir         aText.appendAscii(RTL_CONSTASCII_STRINGPARAM(":\n"));
65*cdf0e10cSrcweir             //TODO! must be internationalized
66*cdf0e10cSrcweir     aText.append(rMessage);
67*cdf0e10cSrcweir 
68*cdf0e10cSrcweir     std::auto_ptr< MessBox > xBox;
69*cdf0e10cSrcweir     try
70*cdf0e10cSrcweir     {
71*cdf0e10cSrcweir         switch (eClassification)
72*cdf0e10cSrcweir         {
73*cdf0e10cSrcweir         case task::InteractionClassification_ERROR:
74*cdf0e10cSrcweir             xBox.reset(new ErrorBox(pParent,
75*cdf0e10cSrcweir                                     nButtonMask,
76*cdf0e10cSrcweir                                     aText.makeStringAndClear()));
77*cdf0e10cSrcweir             break;
78*cdf0e10cSrcweir 
79*cdf0e10cSrcweir         case task::InteractionClassification_WARNING:
80*cdf0e10cSrcweir             xBox.reset(new WarningBox(pParent,
81*cdf0e10cSrcweir                                       nButtonMask,
82*cdf0e10cSrcweir                                       aText.makeStringAndClear()));
83*cdf0e10cSrcweir             break;
84*cdf0e10cSrcweir 
85*cdf0e10cSrcweir         case task::InteractionClassification_INFO:
86*cdf0e10cSrcweir             if ((nButtonMask & 0x01F00000) == WB_DEF_OK)
87*cdf0e10cSrcweir                 //TODO! missing win bit button mask define (want to ignore
88*cdf0e10cSrcweir                 // any default button settings)...
89*cdf0e10cSrcweir                 xBox.reset(new InfoBox(pParent,
90*cdf0e10cSrcweir                                        aText.makeStringAndClear()));
91*cdf0e10cSrcweir             else
92*cdf0e10cSrcweir                 xBox.reset(new ErrorBox(pParent,
93*cdf0e10cSrcweir                                         nButtonMask,
94*cdf0e10cSrcweir                                         aText.makeStringAndClear()));
95*cdf0e10cSrcweir             break;
96*cdf0e10cSrcweir 
97*cdf0e10cSrcweir         case task::InteractionClassification_QUERY:
98*cdf0e10cSrcweir             xBox.reset(new QueryBox(pParent,
99*cdf0e10cSrcweir                                     nButtonMask,
100*cdf0e10cSrcweir                                     aText.makeStringAndClear()));
101*cdf0e10cSrcweir             break;
102*cdf0e10cSrcweir 
103*cdf0e10cSrcweir         default:
104*cdf0e10cSrcweir             OSL_ASSERT(false);
105*cdf0e10cSrcweir             break;
106*cdf0e10cSrcweir         }
107*cdf0e10cSrcweir     }
108*cdf0e10cSrcweir     catch (std::bad_alloc const &)
109*cdf0e10cSrcweir     {
110*cdf0e10cSrcweir         throw uno::RuntimeException(
111*cdf0e10cSrcweir             rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("out of memory")),
112*cdf0e10cSrcweir             uno::Reference< uno::XInterface >());
113*cdf0e10cSrcweir     }
114*cdf0e10cSrcweir 
115*cdf0e10cSrcweir     sal_uInt16 aResult = xBox->Execute();
116*cdf0e10cSrcweir     switch( aResult )
117*cdf0e10cSrcweir     {
118*cdf0e10cSrcweir     case BUTTONID_OK:
119*cdf0e10cSrcweir         aResult = ERRCODE_BUTTON_OK;
120*cdf0e10cSrcweir         break;
121*cdf0e10cSrcweir     case BUTTONID_CANCEL:
122*cdf0e10cSrcweir         aResult = ERRCODE_BUTTON_CANCEL;
123*cdf0e10cSrcweir         break;
124*cdf0e10cSrcweir     case BUTTONID_YES:
125*cdf0e10cSrcweir         aResult = ERRCODE_BUTTON_YES;
126*cdf0e10cSrcweir         break;
127*cdf0e10cSrcweir     case BUTTONID_NO:
128*cdf0e10cSrcweir         aResult = ERRCODE_BUTTON_NO;
129*cdf0e10cSrcweir         break;
130*cdf0e10cSrcweir     case BUTTONID_RETRY:
131*cdf0e10cSrcweir         aResult = ERRCODE_BUTTON_RETRY;
132*cdf0e10cSrcweir         break;
133*cdf0e10cSrcweir     }
134*cdf0e10cSrcweir 
135*cdf0e10cSrcweir     return aResult;
136*cdf0e10cSrcweir }
137*cdf0e10cSrcweir 
138*cdf0e10cSrcweir }
139*cdf0e10cSrcweir 
140*cdf0e10cSrcweir void
141*cdf0e10cSrcweir UUIInteractionHelper::handleErrorHandlerRequest(
142*cdf0e10cSrcweir     task::InteractionClassification eClassification,
143*cdf0e10cSrcweir     ErrCode nErrorCode,
144*cdf0e10cSrcweir     std::vector< rtl::OUString > const & rArguments,
145*cdf0e10cSrcweir     uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
146*cdf0e10cSrcweir         rContinuations,
147*cdf0e10cSrcweir     bool bObtainErrorStringOnly,
148*cdf0e10cSrcweir     bool & bHasErrorString,
149*cdf0e10cSrcweir     rtl::OUString & rErrorString)
150*cdf0e10cSrcweir         SAL_THROW((uno::RuntimeException))
151*cdf0e10cSrcweir {
152*cdf0e10cSrcweir     if (bObtainErrorStringOnly)
153*cdf0e10cSrcweir     {
154*cdf0e10cSrcweir         bHasErrorString = isInformationalErrorMessageRequest(rContinuations);
155*cdf0e10cSrcweir         if (!bHasErrorString)
156*cdf0e10cSrcweir             return;
157*cdf0e10cSrcweir     }
158*cdf0e10cSrcweir 
159*cdf0e10cSrcweir     rtl::OUString aMessage;
160*cdf0e10cSrcweir     {
161*cdf0e10cSrcweir         enum Source { SOURCE_DEFAULT, SOURCE_CNT, SOURCE_SVX, SOURCE_UUI };
162*cdf0e10cSrcweir         static char const * const aManager[4]
163*cdf0e10cSrcweir             = { CREATEVERSIONRESMGR_NAME(ofa),
164*cdf0e10cSrcweir                 CREATEVERSIONRESMGR_NAME(cnt),
165*cdf0e10cSrcweir                 CREATEVERSIONRESMGR_NAME(svx),
166*cdf0e10cSrcweir                 CREATEVERSIONRESMGR_NAME(uui) };
167*cdf0e10cSrcweir         static sal_uInt16 const aId[4]
168*cdf0e10cSrcweir             = { RID_ERRHDL,
169*cdf0e10cSrcweir                 RID_CHAOS_START + 12,
170*cdf0e10cSrcweir                 // cf. chaos/source/inc/cntrids.hrc, where
171*cdf0e10cSrcweir                 // #define RID_CHAOS_ERRHDL (RID_CHAOS_START + 12)
172*cdf0e10cSrcweir                 RID_SVX_START + 350, // RID_SVXERRCODE
173*cdf0e10cSrcweir                 RID_UUI_ERRHDL };
174*cdf0e10cSrcweir         ErrCode nErrorId = nErrorCode & ~ERRCODE_WARNING_MASK;
175*cdf0e10cSrcweir         Source eSource = nErrorId < ERRCODE_AREA_LIB1 ?
176*cdf0e10cSrcweir             SOURCE_DEFAULT :
177*cdf0e10cSrcweir             nErrorId >= ERRCODE_AREA_CHAOS
178*cdf0e10cSrcweir             && nErrorId < ERRCODE_AREA_CHAOS_END ?
179*cdf0e10cSrcweir             SOURCE_CNT :
180*cdf0e10cSrcweir             nErrorId >= ERRCODE_AREA_SVX
181*cdf0e10cSrcweir             && nErrorId <= ERRCODE_AREA_SVX_END ?
182*cdf0e10cSrcweir             SOURCE_SVX :
183*cdf0e10cSrcweir             SOURCE_UUI;
184*cdf0e10cSrcweir 
185*cdf0e10cSrcweir         vos::OGuard aGuard(Application::GetSolarMutex());
186*cdf0e10cSrcweir         std::auto_ptr< ResMgr > xManager;
187*cdf0e10cSrcweir         xManager.reset(ResMgr::CreateResMgr(aManager[eSource]));
188*cdf0e10cSrcweir         if (!xManager.get())
189*cdf0e10cSrcweir             return;
190*cdf0e10cSrcweir         ResId aResId(aId[eSource], *xManager.get());
191*cdf0e10cSrcweir         if (!ErrorResource(aResId).getString(nErrorCode, &aMessage))
192*cdf0e10cSrcweir             return;
193*cdf0e10cSrcweir     }
194*cdf0e10cSrcweir 
195*cdf0e10cSrcweir     aMessage = replaceMessageWithArguments( aMessage, rArguments );
196*cdf0e10cSrcweir 
197*cdf0e10cSrcweir     if (bObtainErrorStringOnly)
198*cdf0e10cSrcweir     {
199*cdf0e10cSrcweir         rErrorString = aMessage;
200*cdf0e10cSrcweir         return;
201*cdf0e10cSrcweir     }
202*cdf0e10cSrcweir     else
203*cdf0e10cSrcweir     {
204*cdf0e10cSrcweir         //TODO! It can happen that the buttons calculated below do not match
205*cdf0e10cSrcweir         // the error text from the resource (e.g., some text that is not a
206*cdf0e10cSrcweir         // question, but YES and NO buttons).  Some error texts have
207*cdf0e10cSrcweir         // ExtraData that specifies a set of buttons, but that data is not
208*cdf0e10cSrcweir         // really useful, because a single error text may well make sense
209*cdf0e10cSrcweir         // both with only an OK button and with RETRY and CANCEL buttons.
210*cdf0e10cSrcweir 
211*cdf0e10cSrcweir         uno::Reference< task::XInteractionApprove > xApprove;
212*cdf0e10cSrcweir         uno::Reference< task::XInteractionDisapprove > xDisapprove;
213*cdf0e10cSrcweir         uno::Reference< task::XInteractionRetry > xRetry;
214*cdf0e10cSrcweir         uno::Reference< task::XInteractionAbort > xAbort;
215*cdf0e10cSrcweir         getContinuations(
216*cdf0e10cSrcweir             rContinuations, &xApprove, &xDisapprove, &xRetry, &xAbort);
217*cdf0e10cSrcweir 
218*cdf0e10cSrcweir         // The following mapping uses the bit mask
219*cdf0e10cSrcweir         //     Approve = 8,
220*cdf0e10cSrcweir         //     Disapprove = 4,
221*cdf0e10cSrcweir         //     Retry = 2,
222*cdf0e10cSrcweir         //     Abort = 1
223*cdf0e10cSrcweir         //
224*cdf0e10cSrcweir         // The mapping has five properties on which the code to select the
225*cdf0e10cSrcweir         // correct continuation relies:
226*cdf0e10cSrcweir         // 1  The OK button is mapped to Approve if that is available,
227*cdf0e10cSrcweir         //    otherwise to Abort if that is available, otherwise to none.
228*cdf0e10cSrcweir         // 2  The CANCEL button is always mapped to Abort.
229*cdf0e10cSrcweir         // 3  The RETRY button is always mapped to Retry.
230*cdf0e10cSrcweir         // 4  The NO button is always mapped to Disapprove.
231*cdf0e10cSrcweir         // 5  The YES button is always mapped to Approve.
232*cdf0e10cSrcweir         //
233*cdf0e10cSrcweir         // Because the WinBits button combinations are quite restricted, not
234*cdf0e10cSrcweir         // every request can be served here.
235*cdf0e10cSrcweir         //
236*cdf0e10cSrcweir         // Finally, it seems to be better to leave default button
237*cdf0e10cSrcweir         // determination to VCL (the favouring of CANCEL as default button
238*cdf0e10cSrcweir         // seems to not always be what the user wants)...
239*cdf0e10cSrcweir         WinBits const aButtonMask[16]
240*cdf0e10cSrcweir             = { 0,
241*cdf0e10cSrcweir                 WB_OK /*| WB_DEF_OK*/, // Abort
242*cdf0e10cSrcweir                 0,
243*cdf0e10cSrcweir                 WB_RETRY_CANCEL /*| WB_DEF_CANCEL*/, // Retry, Abort
244*cdf0e10cSrcweir                 0,
245*cdf0e10cSrcweir                 0,
246*cdf0e10cSrcweir                 0,
247*cdf0e10cSrcweir                 0,
248*cdf0e10cSrcweir                 WB_OK /*| WB_DEF_OK*/, // Approve
249*cdf0e10cSrcweir                 WB_OK_CANCEL /*| WB_DEF_CANCEL*/, // Approve, Abort
250*cdf0e10cSrcweir                 0,
251*cdf0e10cSrcweir                 0,
252*cdf0e10cSrcweir                 WB_YES_NO /*| WB_DEF_NO*/, // Approve, Disapprove
253*cdf0e10cSrcweir                 WB_YES_NO_CANCEL /*| WB_DEF_CANCEL*/,
254*cdf0e10cSrcweir                 // Approve, Disapprove, Abort
255*cdf0e10cSrcweir                 0,
256*cdf0e10cSrcweir                 0 };
257*cdf0e10cSrcweir 
258*cdf0e10cSrcweir         WinBits nButtonMask = aButtonMask[(xApprove.is() ? 8 : 0)
259*cdf0e10cSrcweir                                           | (xDisapprove.is() ? 4 : 0)
260*cdf0e10cSrcweir                                           | (xRetry.is() ? 2 : 0)
261*cdf0e10cSrcweir                                           | (xAbort.is() ? 1 : 0)];
262*cdf0e10cSrcweir         if (nButtonMask == 0)
263*cdf0e10cSrcweir             return;
264*cdf0e10cSrcweir 
265*cdf0e10cSrcweir         //TODO! remove this backwards compatibility?
266*cdf0e10cSrcweir         rtl::OUString aContext(getContextProperty());
267*cdf0e10cSrcweir         if (aContext.getLength() == 0 && nErrorCode != 0)
268*cdf0e10cSrcweir         {
269*cdf0e10cSrcweir             vos::OGuard aGuard(Application::GetSolarMutex());
270*cdf0e10cSrcweir             ErrorContext * pContext = ErrorContext::GetContext();
271*cdf0e10cSrcweir             if (pContext)
272*cdf0e10cSrcweir             {
273*cdf0e10cSrcweir                 UniString aContextString;
274*cdf0e10cSrcweir                 if (pContext->GetString(nErrorCode, aContextString))
275*cdf0e10cSrcweir                     aContext = aContextString;
276*cdf0e10cSrcweir             }
277*cdf0e10cSrcweir         }
278*cdf0e10cSrcweir 
279*cdf0e10cSrcweir         sal_uInt16 nResult = executeErrorDialog(
280*cdf0e10cSrcweir             getParentProperty(), eClassification, aContext, aMessage, nButtonMask );
281*cdf0e10cSrcweir 
282*cdf0e10cSrcweir         switch (nResult)
283*cdf0e10cSrcweir         {
284*cdf0e10cSrcweir         case ERRCODE_BUTTON_OK:
285*cdf0e10cSrcweir             OSL_ENSURE(xApprove.is() || xAbort.is(), "unexpected situation");
286*cdf0e10cSrcweir             if (xApprove.is())
287*cdf0e10cSrcweir                 xApprove->select();
288*cdf0e10cSrcweir             else if (xAbort.is())
289*cdf0e10cSrcweir                 xAbort->select();
290*cdf0e10cSrcweir             break;
291*cdf0e10cSrcweir 
292*cdf0e10cSrcweir         case ERRCODE_BUTTON_CANCEL:
293*cdf0e10cSrcweir             OSL_ENSURE(xAbort.is(), "unexpected situation");
294*cdf0e10cSrcweir             if (xAbort.is())
295*cdf0e10cSrcweir                 xAbort->select();
296*cdf0e10cSrcweir             break;
297*cdf0e10cSrcweir 
298*cdf0e10cSrcweir         case ERRCODE_BUTTON_RETRY:
299*cdf0e10cSrcweir             OSL_ENSURE(xRetry.is(), "unexpected situation");
300*cdf0e10cSrcweir             if (xRetry.is())
301*cdf0e10cSrcweir                 xRetry->select();
302*cdf0e10cSrcweir             break;
303*cdf0e10cSrcweir 
304*cdf0e10cSrcweir         case ERRCODE_BUTTON_NO:
305*cdf0e10cSrcweir             OSL_ENSURE(xDisapprove.is(), "unexpected situation");
306*cdf0e10cSrcweir             if (xDisapprove.is())
307*cdf0e10cSrcweir                 xDisapprove->select();
308*cdf0e10cSrcweir             break;
309*cdf0e10cSrcweir 
310*cdf0e10cSrcweir         case ERRCODE_BUTTON_YES:
311*cdf0e10cSrcweir             OSL_ENSURE(xApprove.is(), "unexpected situation");
312*cdf0e10cSrcweir             if (xApprove.is())
313*cdf0e10cSrcweir                 xApprove->select();
314*cdf0e10cSrcweir             break;
315*cdf0e10cSrcweir         }
316*cdf0e10cSrcweir 
317*cdf0e10cSrcweir     }
318*cdf0e10cSrcweir }
319