1 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */
2
3 /* AbiWord
4 * Copyright (C) 1998-2000 AbiSource, Inc.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301 USA.
20 */
21
22 /*****************************************************************
23 ** Only one of these is created by the application.
24 *****************************************************************/
25
26 #define WIN32_LEAN_AND_MEAN
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include <stdlib.h>
33 #include <windows.h>
34 #include <commctrl.h> // includes the common control header
35 #ifdef _MSC_VER
36 #include <crtdbg.h>
37 #endif
38 #include <sys/types.h>
39 #include <sys/stat.h>
40
41 #include <stdio.h>
42 #include <string.h>
43 #include <io.h>
44 #include <fcntl.h>
45
46 #if !defined(__WINE__) && (!defined(_MSC_VER) || _MSC_VER < 1310) && !defined(__MINGW32__)
47 #include <iostream.h>
48 #elif _MSC_VER >= 1310
49 #include <iostream>
50 #endif
51
52 #include <ole2.h>
53
54 #include "ut_debugmsg.h"
55 #include "ut_bytebuf.h"
56 #include "ut_string.h"
57 #include "xap_Args.h"
58 #include "ap_Args.h"
59 #include "ap_Convert.h"
60 #include "ap_Win32Frame.h"
61 #include "ap_Win32App.h"
62 #include "spell_manager.h"
63
64 #include "ap_Strings.h"
65 #include "ap_LoadBindings.h"
66 #include "xap_EditMethods.h"
67 #include "xap_Menu_Layouts.h"
68 #include "xap_Menu_ActionSet.h"
69 #include "xap_Toolbar_ActionSet.h"
70 #include "xap_EncodingManager.h"
71 #include "xap_ModuleManager.h"
72 #include "ev_EditMethod.h"
73 #include "xap_Module.h"
74 #include "abi-builtin-plugins.h"
75
76 #include "ap_Win32Resources.rc2"
77 #include "ap_Clipboard.h"
78 #include "ap_EditMethods.h"
79
80 #include "fp_Run.h"
81 #include "ut_path.h"
82 #include "ut_Win32OS.h"
83 #include "ut_Win32Idle.h"
84 #include "ut_Language.h"
85 #include "ut_Win32LocaleString.h"
86
87 #include "ie_impexp_Register.h"
88
89 #include "ie_exp.h"
90 #include "ie_exp_RTF.h"
91 #include "ie_exp_Text.h"
92
93 #include "ie_imp.h"
94 #include "ie_imp_RTF.h"
95 #include "ie_imp_Text.h"
96 #include "ie_impGraphic.h"
97 #include "fg_Graphic.h"
98 #include "xav_View.h"
99 #include "xad_Document.h"
100 #include "ap_FrameData.h"
101 #include "ut_Win32Locale.h"
102
103 #include "ap_Strings.h"
104
105 #include "pt_PieceTable.h"
106
107 #include "gr_Painter.h"
108 // extern prototype - this is defined in ap_EditMethods.cpp
109 extern XAP_Dialog_MessageBox::tAnswer s_CouldNotLoadFileMessage(XAP_Frame * pFrame, const char * pNewFile, UT_Error errorCode);
110 /*****************************************************************/
111
AP_Win32App(HINSTANCE hInstance,const char * szAppName)112 AP_Win32App::AP_Win32App(HINSTANCE hInstance, const char * szAppName)
113 : AP_App(hInstance, szAppName)
114 {
115 m_pStringSet = NULL;
116 m_pClipboard = NULL;
117 }
118
~AP_Win32App(void)119 AP_Win32App::~AP_Win32App(void)
120 {
121 DELETEP(m_pStringSet);
122 DELETEP(m_pClipboard);
123
124 IE_ImpExp_UnRegisterXP ();
125 }
126
s_createDirectoryIfNecessary(const char * szDir)127 static bool s_createDirectoryIfNecessary(const char * szDir)
128 {
129 struct _stat statbuf;
130 UT_Win32LocaleString str;
131
132 str.fromUTF8(szDir);
133
134 if (_wstat(str.c_str(),&statbuf) == 0) // if it exists
135 {
136 if ( (statbuf.st_mode & _S_IFDIR) == _S_IFDIR ) // and is a directory
137 return true;
138
139 UT_DEBUGMSG(("Pathname [%s] is not a directory.\n",szDir));
140 return false;
141 }
142
143 if (CreateDirectoryW(str.c_str(),NULL))
144 return true;
145
146 UT_DEBUGMSG(("Could not create Directory [%s].\n",szDir));
147 return false;
148 }
149
150 typedef BOOL __declspec(dllimport) (CALLBACK *InitCommonControlsEx_fn)(LPINITCOMMONCONTROLSEX lpInitCtrls);
151
initialize(void)152 bool AP_Win32App::initialize(void)
153 {
154 bool bSuccess = true;
155 const char * szUserPrivateDirectory = getUserPrivateDirectory();
156 bool bVerified = s_createDirectoryIfNecessary(szUserPrivateDirectory);
157
158 UT_return_val_if_fail (bVerified, false);
159
160 // create templates directory
161 UT_String sTemplates = szUserPrivateDirectory;
162 sTemplates += "/templates";
163 s_createDirectoryIfNecessary(sTemplates.c_str());
164
165 // load the preferences.
166
167 m_prefs = new AP_Win32Prefs();
168 UT_return_val_if_fail (m_prefs, false);
169
170 m_prefs->fullInit();
171
172 // now that preferences are established, let the xap init
173
174 m_pClipboard = new AP_Win32Clipboard();
175 UT_return_val_if_fail (m_pClipboard, false);
176
177 m_pEMC = AP_GetEditMethods();
178 UT_return_val_if_fail (m_pEMC, false);
179
180 m_pBindingSet = new AP_BindingSet(m_pEMC);
181 UT_return_val_if_fail (m_pBindingSet, false);
182
183 m_pMenuActionSet = AP_CreateMenuActionSet();
184 UT_return_val_if_fail (m_pMenuActionSet,false);
185
186 m_pToolbarActionSet = AP_CreateToolbarActionSet();
187 UT_return_val_if_fail (m_pToolbarActionSet,false);
188
189 //////////////////////////////////////////////////////////////////
190 // load the dialog and message box strings
191 //////////////////////////////////////////////////////////////////
192
193 {
194 // assume we will be using the builtin set (either as the main
195 // set or as the fallback set).
196
197 AP_BuiltinStringSet * pBuiltinStringSet = new AP_BuiltinStringSet(this,AP_PREF_DEFAULT_StringSet);
198 UT_return_val_if_fail (pBuiltinStringSet, false);
199 m_pStringSet = pBuiltinStringSet;
200
201 // see if we should load an alternate set from the disk
202
203 const char * szDirectory = NULL;
204 const char * szStringSet = NULL;
205
206 if ( (getPrefsValue(AP_PREF_KEY_StringSet,&szStringSet))
207 && (szStringSet)
208 && (*szStringSet)
209 && (g_ascii_strcasecmp(szStringSet,AP_PREF_DEFAULT_StringSet) != 0))
210 {
211 getPrefsValueDirectory(true,AP_PREF_KEY_StringSetDirectory,&szDirectory);
212 UT_return_val_if_fail ((szDirectory) && (*szDirectory), false);
213
214 char * szPathname = (char *)UT_calloc(sizeof(char),strlen(szDirectory)+strlen(szStringSet)+100);
215 UT_return_val_if_fail (szPathname, false);
216
217 sprintf(szPathname,"%s%s%s.strings",
218 szDirectory,
219 ((szDirectory[strlen(szDirectory)-1]=='\\') ? "" : "\\"),
220 szStringSet);
221
222 AP_DiskStringSet * pDiskStringSet = new AP_DiskStringSet(this);
223 UT_return_val_if_fail (pDiskStringSet, false);
224
225 if (pDiskStringSet->loadStringsFromDisk(szPathname))
226 {
227 pDiskStringSet->setFallbackStringSet(m_pStringSet);
228 m_pStringSet = pDiskStringSet;
229 UT_Language_updateLanguageNames();
230 UT_DEBUGMSG(("Using StringSet [%s]\n",szPathname));
231 }
232 else
233 {
234 UT_DEBUGMSG(("Unable to load StringSet [%s] -- using builtin strings instead.\n",szPathname));
235 DELETEP(pDiskStringSet);
236 }
237
238 g_free(szPathname);
239 }
240 }
241
242 // AP_App::initilize() calls for us XAP_Win32App::initialize()
243 if (! AP_App::initialize())
244 return false;
245
246
247 // let various window types register themselves
248
249 if (!AP_Win32Frame::RegisterClass(this))
250 {
251 UT_DEBUGMSG(("couldn't register class\n"));
252 return false;
253 }
254
255 //////////////////////////////////////////////////////////////////
256 // Initialize the importers/exporters
257 //////////////////////////////////////////////////////////////////
258 IE_ImpExp_RegisterXP ();
259
260 //////////////////////////////////////////////////////////////////
261 // initializes the spell checker.
262 //////////////////////////////////////////////////////////////////
263
264 {
265 #if ENABLE_SPELL
266 SpellManager::instance();
267 #endif
268 }
269
270
271 // Now we have the strings loaded we can populate the field names correctly
272 int i;
273
274 for (i = 0; fp_FieldTypes[i].m_Type != FPFIELDTYPE_END; i++)
275 {
276 (&fp_FieldTypes[i])->m_Desc = m_pStringSet->getValue(fp_FieldTypes[i].m_DescId);
277 UT_DEBUGMSG(("Setting field type desc for type %d, desc=%s\n", fp_FieldTypes[i].m_Type, fp_FieldTypes[i].m_Desc));
278 }
279
280 for (i = 0; fp_FieldFmts[i].m_Tag != NULL; i++)
281 {
282 (&fp_FieldFmts[i])->m_Desc = m_pStringSet->getValue(fp_FieldFmts[i].m_DescId);
283 UT_DEBUGMSG(("Setting field desc for field %s, desc=%s\n", fp_FieldFmts[i].m_Tag, fp_FieldFmts[i].m_Desc));
284 }
285
286 ///////////////////////////////////////////////////////////////////////
287 /// Build a labelset so the plugins can add themselves to something ///
288 ///////////////////////////////////////////////////////////////////////
289
290 const char * szMenuLabelSetName = NULL;
291 if (getPrefsValue( AP_PREF_KEY_StringSet, (const gchar**)&szMenuLabelSetName)
292 && (szMenuLabelSetName) && (*szMenuLabelSetName))
293 {
294 ;
295 }
296 else
297 szMenuLabelSetName = AP_PREF_DEFAULT_StringSet;
298
299 getMenuFactory()->buildMenuLabelSet(szMenuLabelSetName);
300
301 //////////////////////////////////////////////////////////////////
302 // Check for necessary DLLs now that we can do localized error messages
303 //////////////////////////////////////////////////////////////////
304
305 // Ensure that common control DLL is loaded
306 HINSTANCE hinstCC = LoadLibraryW(L"comctl32.dll");
307 UT_return_val_if_fail (hinstCC, false);
308 InitCommonControlsEx_fn pInitCommonControlsEx = NULL;
309 if( hinstCC != NULL )
310 pInitCommonControlsEx = (InitCommonControlsEx_fn)GetProcAddress( hinstCC, "InitCommonControlsEx");
311 if( pInitCommonControlsEx != NULL )
312 {
313 INITCOMMONCONTROLSEX icex;
314 icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
315 icex.dwICC = ICC_COOL_CLASSES | ICC_BAR_CLASSES // load the rebar and toolbar
316 | ICC_TAB_CLASSES | ICC_UPDOWN_CLASS // and tab and spin controls
317 | ICC_STANDARD_CLASSES;
318 pInitCommonControlsEx(&icex);
319 }
320 else
321 {
322 InitCommonControls();
323
324 UT_Win32LocaleString err;
325 err.fromUTF8 (m_pStringSet->getValue(AP_STRING_ID_WINDOWS_COMCTL_WARNING));
326 MessageBoxW(NULL, err.c_str(), NULL, MB_OK);
327 }
328
329 //////////////////////////////////////////////////////////////////
330 // load the all Plugins from the correct directory
331 //////////////////////////////////////////////////////////////////
332
333 #ifndef DISABLE_BUILTIN_PLUGINS
334 abi_register_builtin_plugins();
335 #endif
336
337 bool bLoadPlugins = true;
338 bool bFound = getPrefsValueBool(XAP_PREF_KEY_AutoLoadPlugins,&bLoadPlugins);
339
340 if(bLoadPlugins || !bFound)
341 {
342 WCHAR szPath[PATH_MAX];
343 WCHAR szPlugin[PATH_MAX];
344 _getExeDir( szPath, PATH_MAX);
345 #ifdef _MSC_VER
346 lstrcatW(szPath, L"..\\plugins\\*.dll");
347 #else
348 #define ABI_WIDE_STRING(t) L ## t
349 lstrcatW(szPath, ABI_WIDE_STRING("..\\lib\\" PACKAGE L"-" ABIWORD_SERIES L"\\plugins\\*.dll"));
350 #endif
351
352 WIN32_FIND_DATAW cfile;
353 HANDLE findtag = FindFirstFileW( szPath, &cfile );
354 if( findtag != INVALID_HANDLE_VALUE )
355 {
356 do
357 {
358 _getExeDir( szPlugin, PATH_MAX );
359 #ifdef _MSC_VER
360 lstrcatW( szPlugin, L"..\\plugins\\" );
361 #else
362 lstrcatW( szPlugin, ABI_WIDE_STRING("..\\lib\\" PACKAGE L"-" ABIWORD_SERIES L"\\plugins\\" ));
363 #endif
364 lstrcatW( szPlugin, cfile.cFileName );
365 XAP_ModuleManager::instance().loadModule( getUTF8String(szPlugin) );
366 } while( FindNextFileW ( findtag, &cfile ) );
367 FindClose( findtag );
368 }
369
370 UT_String pluginName( getUserPrivateDirectory() );
371 UT_String pluginDir( getUserPrivateDirectory() );
372 pluginDir += "\\AbiWord\\plugins\\*.dll";
373 UT_Win32LocaleString str;
374 str.fromUTF8(pluginDir.c_str());
375 findtag = FindFirstFileW( str.c_str(), &cfile );
376 if( findtag != INVALID_HANDLE_VALUE )
377 {
378 do
379 {
380 pluginName = getUserPrivateDirectory();
381 pluginName += "\\AbiWord\\plugins\\";
382 pluginName += getUTF8String(cfile.cFileName);
383 XAP_ModuleManager::instance().loadModule( pluginName.c_str() );
384 } while( FindNextFileW( findtag, &cfile ) );
385 FindClose( findtag );
386 }
387 }
388 return bSuccess;
389 }
390
391
392 // if app is NULL then we use 'this'
newFrame(void)393 XAP_Frame * AP_Win32App::newFrame(void)
394 {
395 AP_Win32Frame * pWin32Frame = new AP_Win32Frame();
396
397 if (pWin32Frame)
398 pWin32Frame->initialize();
399
400 return pWin32Frame;
401 }
402
403
shutdown(void)404 bool AP_Win32App::shutdown(void)
405 {
406 if (m_prefs->getAutoSavePrefs())
407 m_prefs->savePrefsFile();
408
409 delete m_prefs;
410 m_prefs = NULL;
411
412 return true;
413 }
414
getPrefsValueDirectory(bool bAppSpecific,const gchar * szKey,const gchar ** pszValue) const415 bool AP_Win32App::getPrefsValueDirectory(bool bAppSpecific,
416 const gchar * szKey, const gchar ** pszValue) const
417 {
418 if (!m_prefs)
419 return false;
420
421 const gchar * psz = NULL;
422 if (!m_prefs->getPrefsValue(szKey,&psz))
423 return false;
424
425 if ((*psz == '/') || (*psz == '\\'))
426 {
427 *pszValue = psz;
428 return true;
429 }
430
431 const gchar * dir = ((bAppSpecific) ? getAbiSuiteAppDir() : getAbiSuiteLibDir());
432
433 static gchar buf[1024];
434 UT_return_val_if_fail ((strlen(dir) + strlen(psz) + 2) < sizeof(buf), false);
435
436 sprintf(buf,"%s\\%s",dir,psz);
437 *pszValue = buf;
438 return true;
439 }
440
getAbiSuiteAppDir(void) const441 const char * AP_Win32App::getAbiSuiteAppDir(void) const
442 {
443 return getAbiSuiteLibDir();
444 }
445
getIcon(void)446 HICON AP_Win32App::getIcon(void)
447 {
448
449 int sy = GetSystemMetrics(SM_CYICON);
450 int sx = GetSystemMetrics(SM_CXICON);
451 UT_DEBUGMSG(("GetIcon(): system metrics [%d %d]\n",sx,sy));
452
453 if ((sx==32) && (sy==32))
454 return LoadIconW(getInstance(), MAKEINTRESOURCEW(AP_RID_ICON_APPLICATION_32));
455 else
456 return (HICON) LoadImageW(getInstance(), MAKEINTRESOURCEW(AP_RID_ICON_APPLICATION_32), IMAGE_ICON, 0,0,0);
457 }
458
getSmallIcon(void)459 HICON AP_Win32App::getSmallIcon(void)
460 {
461
462 int sy = GetSystemMetrics(SM_CYICON);
463 int sx = GetSystemMetrics(SM_CXICON);
464 UT_DEBUGMSG(("GetIcon(): system metrics [%d %d]\n",sx,sy));
465
466 if ((sx==16) && (sy==16))
467 return LoadIconW(getInstance(), MAKEINTRESOURCEW(AP_RID_ICON_APPLICATION_16));
468 else
469 return (HICON) LoadImageW(getInstance(), MAKEINTRESOURCEW(AP_RID_ICON_APPLICATION_16), IMAGE_ICON, 0,0,0);
470 }
471
getStringSet(void) const472 const XAP_StringSet * AP_Win32App::getStringSet(void) const
473 {
474 return m_pStringSet;
475 }
476
477 #ifdef COPY_ON_DEMAND
478 /*!
479 indicate to the clipboard that we can provide data in this format
480 on demand
481 */
_indicateFmtToClipboard(const char * pszFmt) const482 void AP_Win32App::_indicateFmtToClipboard(const char * pszFmt) const
483 {
484 UT_return_if_fail(m_pClipboard && pszFmt);
485 UINT iFmt = m_pClipboard->convertFormatString(pszFmt);
486
487 SetClipboardDataW(iFmt, NULL);
488 }
489
_cacheClipboardDoc(PD_DocumentRange * pDocRange)490 bool AP_Win32App::_cacheClipboardDoc(PD_DocumentRange *pDocRange)
491 {
492 UT_return_val_if_fail(m_pClipboard && pDocRange, false);
493
494 UT_ByteBuf buf;
495 UT_Error status;;
496 UT_Byte b = 0;
497
498 IE_Exp_RTF * pExpRtf = new IE_Exp_RTF(pDocRange->m_pDoc);
499 if (pExpRtf)
500 {
501 status = pExpRtf->copyToBuffer(pDocRange,&buf);
502
503 if(status != UT_OK)
504 return false;
505
506 buf.append(&b,1); // NULL terminate the string
507 DELETEP(pExpRtf);
508 }
509 else
510 {
511 return false;
512 }
513
514 // now create a subdocument ...
515 PD_Document * pDoc = new PD_Document();
516
517 if(!pDoc)
518 return false;
519
520 pDoc->newDocument();
521
522 PD_DocumentRange DocRange(pDoc, 2, 2);
523
524 IE_Imp * pImp = 0;
525 IE_Imp::constructImporter(pDoc, IE_Imp::fileTypeForSuffix(".rtf"),&pImp,0);
526
527 if(pImp)
528 {
529 pImp->pasteFromBuffer(&DocRange,buf.getPointer(0),buf.getLength(),NULL);
530 delete pImp;
531 }
532 else
533 {
534 return false;
535 }
536
537 m_pClipboard->setClipboardDoc(pDoc);
538 return true;
539 }
540
541 /*!
542 copy the required format to the clipboard on demand
543 see docs on WM_RENDERFORMAT
544 */
copyFmtToClipboardOnDemand(UINT iFmt)545 bool AP_Win32App::copyFmtToClipboardOnDemand(UINT iFmt)
546 {
547 UT_return_val_if_fail(m_pClipboard, false);
548
549 PD_DocumentRange DocRange;
550 DocRange.m_pDoc = m_pClipboard->getClipboardDoc();
551 UT_return_val_if_fail(DocRange.m_pDoc, false);
552
553 DocRange.m_pos1 = 2;
554 DocRange.m_pos2 = DocRange.m_pDoc->getLastFrag()->getPos() + DocRange.m_pDoc->getLastFrag()->getLength();
555
556 if(!_copyFmtToClipboard(&DocRange, iFmt))
557 return false;
558
559 return true;
560 }
561
562 /*!
563 copy data to the clipboard in all formats on demand (this is
564 called when application is exiting and leaving data on clipboard
565 that and indicating that data in addtional formats is available
566 see docs on WM_RENDERALLFORMATS
567 */
copyAllFmtsToClipboardOnDemand()568 bool AP_Win32App::copyAllFmtsToClipboardOnDemand()
569 {
570 UT_return_val_if_fail(m_pClipboard, false);
571
572 // I will use NULL here, since we are about to shut down anyway ...
573 if(!m_pClipboard->openClipboard(NULL)) // try to lock the clipboard
574 return false;
575
576 // need to clear clipboard in order to become its owners
577 m_pClipboard->clearClipboard();
578
579 // what we need is to get the data from the clipboard and convert
580 // it to the format requested
581 PD_DocumentRange DocRange;
582 DocRange.m_pDoc = m_pClipboard->getClipboardDoc();
583 UT_return_val_if_fail(DocRange.m_pDoc, false);
584
585 DocRange.m_pos1 = 2;
586 DocRange.m_pos2 = DocRange.m_pDoc->getLastFrag()->getPos() + DocRange.m_pDoc->getLastFrag()->getLength();
587
588 _copyFmtToClipboard(&DocRange, AP_CLIPBOARD_RTF);
589 _copyFmtToClipboard(&DocRange, AP_CLIPBOARD_TEXTPLAIN_UCS2);
590 _copyFmtToClipboard(&DocRange, AP_CLIPBOARD_TEXTPLAIN_8BIT);
591
592 return true;
593 }
594
595 #endif // COPY_ON_DEMAND
596
597 /*!
598 copy data in required format to the clipboard
599 */
_copyFmtToClipboard(PD_DocumentRange * pDocRange,UINT iFmt)600 bool AP_Win32App::_copyFmtToClipboard(PD_DocumentRange * pDocRange, UINT iFmt)
601 {
602 UT_return_val_if_fail(m_pClipboard, false);
603 const char * pszFmt = m_pClipboard->convertToFormatString(iFmt);
604 UT_return_val_if_fail(pszFmt, false);
605
606 return _copyFmtToClipboard(pDocRange, pszFmt);
607 }
608
609 /*!
610 copy data in required format to the clipboard
611 */
_copyFmtToClipboard(PD_DocumentRange * pDocRange,const char * pszFmt)612 bool AP_Win32App::_copyFmtToClipboard(PD_DocumentRange * pDocRange, const char * pszFmt)
613 {
614 UT_return_val_if_fail(m_pClipboard && pszFmt, false);
615
616 UT_ByteBuf buf;
617 UT_Error status;
618
619 if(0 == strcmp(AP_CLIPBOARD_TEXTPLAIN_8BIT, pszFmt))
620 {
621 IE_Exp_Text * pExpText = new IE_Exp_Text(pDocRange->m_pDoc);
622 if (pExpText)
623 {
624 status = pExpText->copyToBuffer(pDocRange,&buf);
625
626 if(status != UT_OK)
627 return false;
628
629 UT_Byte b = 0;
630 buf.append(&b,1); // NULL terminate the string
631 m_pClipboard->addData(AP_CLIPBOARD_TEXTPLAIN_8BIT,
632 (UT_Byte *)buf.getPointer(0),buf.getLength());
633 DELETEP(pExpText);
634 UT_DEBUGMSG(("CopyToClipboard: copying %d bytes in TEXTPLAIN format.\n",
635 buf.getLength()));
636 }
637 else
638 {
639 return false;
640 }
641
642 }
643 else if(0 == strcmp(AP_CLIPBOARD_TEXTPLAIN_UCS2, pszFmt))
644 {
645 const char *szEnc = XAP_EncodingManager::get_instance()->getNativeUnicodeEncodingName();
646 IE_Exp_Text * pExpUnicodeText = new IE_Exp_Text(pDocRange->m_pDoc,szEnc);
647 if (pExpUnicodeText)
648 {
649 status = pExpUnicodeText->copyToBuffer(pDocRange,&buf);
650
651 if(status != UT_OK)
652 return false;
653
654 UT_Byte b[2] = {0,0};
655 buf.append(b,2); // NULL terminate the string
656 m_pClipboard->addData(AP_CLIPBOARD_TEXTPLAIN_UCS2,
657 (UT_Byte *)buf.getPointer(0),buf.getLength());
658 DELETEP(pExpUnicodeText);
659 UT_DEBUGMSG(("CopyToClipboard: copying %d bytes in TEXTPLAIN UNICODE format.\n",
660 buf.getLength()*2));
661 }
662 else
663 {
664 return false;
665 }
666 }
667 else if(0 == strcmp(AP_CLIPBOARD_RTF, pszFmt))
668 {
669 IE_Exp_RTF * pExpRtf = new IE_Exp_RTF(pDocRange->m_pDoc);
670 if (pExpRtf)
671 {
672 status = pExpRtf->copyToBuffer(pDocRange,&buf);
673
674 if(status != UT_OK)
675 return false;
676
677 UT_Byte b = 0;
678 buf.append(&b,1); // NULL terminate the string
679 m_pClipboard->addData(AP_CLIPBOARD_RTF,(UT_Byte *)buf.getPointer(0),buf.getLength());
680 DELETEP(pExpRtf);
681 UT_DEBUGMSG(("CopyFmtToClipboard: copying %d bytes in RTF format.\n",
682 buf.getLength()));
683 }
684 else
685 {
686 return false;
687 }
688 }
689
690 return true;
691 }
692
693 /*!
694 copy data to the clipboard; this is what gets called when the user
695 presses Ctrl+C
696 */
copyToClipboard(PD_DocumentRange * pDocRange,bool)697 void AP_Win32App::copyToClipboard(PD_DocumentRange * pDocRange, bool /*bUseClipboard*/)
698 {
699 // copy the given subset of the given document to the
700 // system clipboard in a variety of formats.
701 // MSFT requests that we post them in the order of
702 // importance to us (most preserving to most lossy).
703 //
704 // TODO do we need to put something in .ABW format on the clipboard ??
705
706 AP_Win32FrameImpl * pFrameImp = static_cast<AP_Win32FrameImpl*>(getLastFocussedFrame()->getFrameImpl());
707 UT_return_if_fail(pFrameImp);
708
709 if (!m_pClipboard->openClipboard(pFrameImp->getHwndDocument()))
710 return;
711
712 m_pClipboard->clearClipboard(); // this also gives us the ownership
713
714 // Be smart: always place RTF on clipboard; the
715 // remaining formats we will generate on demand.
716 // most of the time it will save us creating multiple importers,
717 // but when the user requests other than the default format, it
718 // will be a little bit more involved
719 // Tomas, June 28, 2003.
720
721 #ifndef COPY_ON_DEMAND
722 _copyFmtToClipboard(pDocRange, AP_CLIPBOARD_RTF);
723 #else
724 // we need to both cache the present doc and put rtf version on
725 // the clipboard, because win32 will ask for it immediately;
726 // appart from that, the rtf exporter needs some layout info to
727 // deal with bidi issues, which means we cannot construct the rtf
728 // from the chached doc properly
729 _cacheClipboardDoc(pDocRange);
730 _copyFmtToClipboard(pDocRange, AP_CLIPBOARD_RTF);
731 #endif
732
733 // TODO Should use a finer-grain technique than IsWinNT()
734 // since Win98 supports unicode clipboard.
735 if (UT_IsWinNT())
736 {
737 // put raw unicode text on the clipboard
738 #ifndef COPY_ON_DEMAND
739 _copyFmtToClipboard(pDocRange, AP_CLIPBOARD_TEXTPLAIN_UCS2);
740 #else
741 _indicateFmtToClipboard(AP_CLIPBOARD_TEXTPLAIN_UCS2);
742 #endif
743 }
744 else
745 {
746 // put raw 8bit text on the clipboard
747 #ifndef COPY_ON_DEMAND
748 _copyFmtToClipboard(pDocRange, AP_CLIPBOARD_TEXTPLAIN_8BIT);
749 #else
750 _indicateFmtToClipboard(AP_CLIPBOARD_TEXTPLAIN_8BIT);
751 #endif
752 }
753
754 m_pClipboard->closeClipboard(); // release clipboard lock
755 }
756
757 //
758 //
759 //
CreateBitmapInfoStruct(HBITMAP hBmp)760 PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp)
761 {
762 BITMAP bmp;
763 PBITMAPINFO pbmi;
764 WORD cClrBits;
765
766 // Retrieve the bitmap's color format, width, and height.
767 if (!GetObjectW(hBmp, sizeof(BITMAP), (LPSTR)&bmp))
768 return NULL;
769
770 if (bmp.bmBitsPixel==16) bmp.bmBitsPixel=24; // 16 bit BMPs are not supported by all programs
771
772
773 // Convert the color format to a count of bits.
774 cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
775
776 if (cClrBits == 1)
777 cClrBits = 1;
778 else if (cClrBits <= 4)
779 cClrBits = 4;
780 else if (cClrBits <= 8)
781 cClrBits = 8;
782 else if (cClrBits <= 16)
783 cClrBits = 16;
784 else if (cClrBits <= 24)
785 cClrBits = 24;
786 else cClrBits = 32;
787
788 // Allocate memory for the BITMAPINFO structure. (This structure
789 // contains a BITMAPINFOHEADER structure and an array of RGBQUAD
790 // data structures.)
791
792 if (cClrBits != 24)
793 pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
794 sizeof(BITMAPINFOHEADER) +
795 sizeof(RGBQUAD) * (1<< cClrBits));
796
797 // There is no RGBQUAD array for the 24-bit-per-pixel format.
798 else
799 pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
800 sizeof(BITMAPINFOHEADER));
801
802 // Initialize the fields in the BITMAPINFO structure.
803
804 pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
805 pbmi->bmiHeader.biWidth = bmp.bmWidth;
806 pbmi->bmiHeader.biHeight = bmp.bmHeight;
807 pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
808 pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
809 if (cClrBits < 24)
810 pbmi->bmiHeader.biClrUsed = (1<<cClrBits);
811
812 // If the bitmap is not compressed, set the BI_RGB flag.
813 pbmi->bmiHeader.biCompression = BI_RGB;
814
815 // Compute the number of bytes in the array of color
816 // indices and store the result in biSizeImage.
817 // For Windows NT/2000, the width must be DWORD aligned unless
818 // the bitmap is RLE compressed.
819 pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
820 * pbmi->bmiHeader.biHeight;
821 // Set biClrImportant to 0, indicating that all of the
822 // device colors are important.
823 pbmi->bmiHeader.biClrImportant = 0;
824 return pbmi;
825 }
826
827 //
828 //
829 //
CreateBMP(HWND,UT_ByteBuf & pBB,PBITMAPINFO pbi,HBITMAP hBMP,HDC hDC)830 void CreateBMP(HWND /*hwnd*/, UT_ByteBuf & pBB, PBITMAPINFO pbi,
831 HBITMAP hBMP, HDC hDC)
832 {
833 BITMAPFILEHEADER hdr; // bitmap file-header
834 PBITMAPINFOHEADER pbih; // bitmap info-header
835 LPBYTE lpBits; // memory pointer
836
837 if (!hBMP) return;
838
839 pbih = (PBITMAPINFOHEADER) pbi;
840 lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
841
842 if (!lpBits) return;
843
844 // Retrieve the color table (RGBQUAD array) and the bits
845 // (array of palette indices) from the DIB.
846 if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi,
847 DIB_RGB_COLORS))
848 return;
849
850 hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M"
851 // Compute the size of the entire file.
852 hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) +
853 pbih->biSize + pbih->biClrUsed
854 * sizeof(RGBQUAD) + pbih->biSizeImage);
855 hdr.bfReserved1 = 0;
856 hdr.bfReserved2 = 0;
857
858 // Compute the offset to the array of color indices.
859 hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) +
860 pbih->biSize + pbih->biClrUsed
861 * sizeof (RGBQUAD);
862
863 pBB.truncate (0);
864
865 // Copy the BITMAPFILEHEADER into the .BMP file.
866 pBB.append ((const UT_Byte *)&hdr, sizeof(BITMAPFILEHEADER));
867 pBB.append ((const UT_Byte *)pbih, sizeof(BITMAPINFOHEADER) + pbih->biClrUsed * sizeof (RGBQUAD));
868
869 // Copy the array of color indices into the .BMP file.
870 pBB.append ((const UT_Byte *)lpBits, (int) pbih->biSizeImage);
871
872 GlobalFree((HGLOBAL)lpBits);
873 }
874
875
876
pasteFromClipboard(PD_DocumentRange * pDocRange,bool,bool bHonorFormatting)877 void AP_Win32App::pasteFromClipboard(PD_DocumentRange * pDocRange, bool /*bUseClipboard*/, bool bHonorFormatting)
878 {
879 // paste from the system clipboard using the best-for-us format
880 // that is present.
881
882 // We get a handle to the object in the requested format
883 // and then lock it an use the system buffer -- rather
884 // then copying it into our own.
885 //
886 // we jump thru a few bogus steps w/r/t the length of the
887 // object because MSFT docs state that the length of the
888 // object may be less than the length actually returned by
889 // GlobalSize().
890 //
891 // therefore, we do a strlen() and **hope** that this is
892 // right. Oh, and the value returned by GlobalSize() varies
893 // from call-to-call on the same object.... sigh.
894 AP_Win32FrameImpl * pFrameImp = static_cast<AP_Win32FrameImpl*>(getLastFocussedFrame()->getFrameImpl());
895 UT_return_if_fail(pFrameImp);
896
897 if (!m_pClipboard->openClipboard(pFrameImp->getHwndDocument())) // lock clipboard
898 return;
899
900 {
901 // TODO Paste the most detailed version unless user overrides.
902 // TODO decide if we need to support .ABW on the clipboard.
903 if (!((bHonorFormatting && _pasteFormatFromClipboard(pDocRange, AP_CLIPBOARD_RTF, ".rtf", false)) ||
904 _pasteFormatFromClipboard(pDocRange, AP_CLIPBOARD_TEXTPLAIN_UCS2, ".txt", true) ||
905 _pasteFormatFromClipboard(pDocRange, AP_CLIPBOARD_BMP, ".bmp", false) ||
906 _pasteFormatFromClipboard(pDocRange, AP_CLIPBOARD_TEXTPLAIN_8BIT, ".txt", false)))
907 {
908 // TODO figure out what to do with an image and other formats....
909 UT_DEBUGMSG(("PasteFromClipboard: TODO support this format..."));
910 }
911 }
912
913 m_pClipboard->closeClipboard(); // release clipboard lock
914 return;
915 }
916
_pasteFormatFromClipboard(PD_DocumentRange * pDocRange,const char * szFormat,const char * szType,bool bWide)917 bool AP_Win32App::_pasteFormatFromClipboard(PD_DocumentRange * pDocRange, const char * szFormat,
918 const char * szType, bool bWide)
919 {
920 HANDLE hData;
921 bool bSuccess = false;
922
923 if (!(hData = m_pClipboard->getHandleInFormat(szFormat)))
924 return bSuccess;
925
926 // It's a bitmap
927 if (g_ascii_strcasecmp(szFormat, AP_CLIPBOARD_BMP)==0)
928 {
929 HBITMAP hBitmap;
930 PBITMAPINFO bi;
931 HWND hWnd;
932 HDC hdc;
933 IE_ImpGraphic* pIEG = NULL;
934 FG_Graphic* pFG = NULL;
935 UT_Error errorCode;
936 UT_ByteBuf byteBuf;
937 IEGraphicFileType iegft = IEGFT_BMP;
938 XAP_Frame* pFrame;
939 AP_FrameData* pFrameData;
940 FL_DocLayout* pDocLy;
941 FV_View* pView;
942 UT_ByteBuf* bBufBMP = new UT_ByteBuf;
943
944 hBitmap = (HBITMAP)hData;
945 hWnd = GetDesktopWindow();
946 hdc = GetDC(hWnd);
947
948 // Create a BMP file from a BITMAP
949 bi = CreateBitmapInfoStruct(hBitmap);
950 CreateBMP(hWnd, *bBufBMP, bi, hBitmap,hdc);
951
952 // Since we are providing the file type, there is not need to pass the bytebuff filled up
953 errorCode = IE_ImpGraphic::constructImporter(*bBufBMP, iegft, &pIEG);
954
955 if(errorCode != UT_OK)
956 return false;
957
958 errorCode = pIEG->importGraphic(bBufBMP, &pFG);
959
960 if(errorCode != UT_OK || !pFG)
961 {
962 DELETEP(bBufBMP);
963 DELETEP(pIEG);
964 return false;
965 }
966 // sunk in importGraphic
967 bBufBMP = NULL;
968
969 // Insert graphic in the view
970 pFrame = getLastFocussedFrame();
971 pFrameData = (AP_FrameData*) pFrame->getFrameData();
972 pDocLy = pFrameData->m_pDocLayout;
973 pView = pDocLy->getView();
974
975 errorCode = pView->cmdInsertGraphic(pFG);
976
977 DELETEP(pIEG);
978 //DELETEP(pFG);
979
980 bSuccess = true;
981 }
982 else
983 {
984 unsigned char * pData = static_cast<unsigned char *>(GlobalLock(hData));
985 UT_DEBUGMSG(("Paste: [fmt %s %s][hdata 0x%08lx][pData 0x%08lx]\n",
986 szFormat, szType, hData, pData));
987 UT_uint32 iSize = GlobalSize(hData);
988 UT_uint32 iStrLen = bWide
989 ? wcslen(reinterpret_cast<const wchar_t *>(pData)) * 2
990 : strlen(reinterpret_cast<const char *>(pData));
991 UT_uint32 iLen = UT_MIN(iSize,iStrLen);
992
993
994 IE_Imp * pImp = 0;
995 IE_Imp::constructImporter(pDocRange->m_pDoc, IE_Imp::fileTypeForSuffix(szType), &pImp, 0);
996 if (pImp)
997 {
998 const char * szEncoding = 0;
999 if (bWide)
1000 {
1001 szEncoding = XAP_EncodingManager::get_instance()->getUCS2LEName();
1002 }
1003 else
1004 {
1005 ; // TODO Get code page using CF_LOCALE
1006 }
1007 pImp->pasteFromBuffer(pDocRange,pData,iLen,szEncoding);
1008 delete pImp;
1009 }
1010
1011 GlobalUnlock(hData);
1012 bSuccess = true;
1013 }
1014 return bSuccess;
1015 }
1016
canPasteFromClipboard(void)1017 bool AP_Win32App::canPasteFromClipboard(void)
1018 {
1019 if (!getLastFocussedFrame())
1020 return false;
1021
1022 AP_Win32FrameImpl * pFrameImp = static_cast<AP_Win32FrameImpl*>(getLastFocussedFrame()->getFrameImpl());
1023 UT_return_val_if_fail(pFrameImp, false);
1024
1025 if (!m_pClipboard->openClipboard(pFrameImp->getHwndDocument()))
1026 return false;
1027
1028 // TODO decide if we need to support .ABW format on the clipboard.
1029 if (m_pClipboard->hasFormat(AP_CLIPBOARD_RTF))
1030 goto ReturnTrue;
1031 if (m_pClipboard->hasFormat(AP_CLIPBOARD_TEXTPLAIN_UCS2))
1032 goto ReturnTrue;
1033 if (m_pClipboard->hasFormat(AP_CLIPBOARD_TEXTPLAIN_8BIT))
1034 goto ReturnTrue;
1035
1036 // If IEGFT_BMP!=0 we have a plugin that can deal with BMP format
1037 if (m_pClipboard->hasFormat(AP_CLIPBOARD_BMP) && IEGFT_BMP)
1038 goto ReturnTrue;
1039
1040 m_pClipboard->closeClipboard();
1041 return false;
1042
1043 ReturnTrue:
1044 m_pClipboard->closeClipboard();
1045 return true;
1046 }
1047
1048 /*****************************************************************/
1049
1050 #if defined(_DEBUG) && defined(_MSC_VER)
1051 #define SET_CRT_DEBUG_FIELD(a) \
1052 _CrtSetDbgFlag((a) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))
1053 #define CLEAR_CRT_DEBUG_FIELD(a) \
1054 _CrtSetDbgFlag(~(a) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG))
1055 #else
1056 #define SET_CRT_DEBUG_FIELD(a) ((void) 0)
1057 #define CLEAR_CRT_DEBUG_FIELD(a) ((void) 0)
1058 #endif
1059
1060 /*****************************************************************/
1061
WinMain(const char * szAppName,HINSTANCE hInstance,HINSTANCE,PSTR,int iCmdShow)1062 int AP_Win32App::WinMain(const char * szAppName, HINSTANCE hInstance,
1063 HINSTANCE /*hPrevInstance*/, PSTR /*szCmdLine*/, int iCmdShow)
1064 {
1065 #if !GLIB_CHECK_VERSION(2,32,0)
1066 if (!g_thread_supported ())
1067 g_thread_init (NULL);
1068 #endif
1069
1070 bool bShowApp = true;
1071 BOOL bInitialized = FALSE;
1072
1073 // this is a static function and doesn't have a 'this' pointer.
1074 MSG msg;
1075
1076 #ifdef _MSC_VER
1077 _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_DEBUG );
1078 _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG );
1079 _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_WNDW);
1080 #endif
1081
1082 // HACK: load least-common-denominator Rich Edit control
1083 // TODO: fix Spell dlg so we don't rely on this
1084 // ALT: make it a Preview widget instead
1085
1086 HINSTANCE hinstRich = LoadLibraryW(L"riched32.dll");
1087 if (!hinstRich)
1088 hinstRich = LoadLibraryW(L"riched20.dll");
1089 UT_return_val_if_fail (hinstRich, 1);
1090
1091 AP_Win32App * pMyWin32App;
1092
1093 // OLE Stuff
1094 if (SUCCEEDED(OleInitialize(NULL)))
1095 bInitialized = TRUE;
1096
1097
1098 // We put this in a block to force the destruction of Args in the stack
1099 {
1100 UT_Win32LocaleString scnv;
1101 UT_UTF8String sUTFCmdLine;
1102
1103 // Load the command line into an XAP_Args class
1104 scnv.fromLocale(GetCommandLineW());
1105 sUTFCmdLine=scnv.utf8_str();
1106 XAP_Args XArgs = XAP_Args(sUTFCmdLine.utf8_str());
1107
1108 // Step 1: Initialize our application.
1109 pMyWin32App = new AP_Win32App(hInstance, szAppName);
1110 AP_Args Args = AP_Args(&XArgs, szAppName, pMyWin32App);
1111
1112 Args.parseOptions();
1113 pMyWin32App->initialize();
1114
1115 // Step 2: Handle all non-window args.
1116 // process args (calls common arg handler, which then calls platform specific)
1117 // As best I understand, it returns true to continue and show window, or
1118 // false if no window should be shown (and thus we should simply exit).
1119 bool windowlessArgsWereSuccessful = true;
1120 if (!Args.doWindowlessArgs(windowlessArgsWereSuccessful))
1121 {
1122 pMyWin32App->shutdown(); // properly shutdown the app 1st
1123 delete pMyWin32App;
1124 return (windowlessArgsWereSuccessful ? 0 : -1);
1125 }
1126
1127 // Step 3: Create windows as appropriate.
1128 // if some args are botched, it returns false and we should
1129 // continue out the door.
1130 // We used to check for bShowApp here. It shouldn't be needed
1131 // anymore, because doWindowlessArgs was supposed to bail already. -PL
1132 if (!pMyWin32App->openCmdLineFiles(&Args))
1133 {
1134 pMyWin32App->shutdown(); // properly shutdown the app 1st
1135 delete pMyWin32App;
1136 return 0;
1137 }
1138 }
1139 //
1140 // This block is controlled by the Structured Exception Handle
1141 // if any crash happens here we will recover it and save the file (cross fingers)
1142 //
1143
1144
1145 try
1146 {
1147 UT_uint32 iHeight = 0, iWidth = 0, t_flag =0;
1148 UT_sint32 iPosX = 0, iPosY = 0;
1149
1150 if (!((XAP_App::getApp()->getGeometry(&iPosX,&iPosY,&iWidth,&iHeight,&t_flag)) &&
1151 ((iWidth > 0) && (iHeight > 0))) )
1152 XAP_App::getApp()->getDefaultGeometry(iWidth,iHeight,t_flag);
1153
1154 if ((t_flag & PREF_FLAG_GEOMETRY_MAXIMIZED)==PREF_FLAG_GEOMETRY_MAXIMIZED)
1155 iCmdShow = SW_SHOWMAXIMIZED;
1156
1157 if (bShowApp)
1158 {
1159 // display the windows
1160 for(UT_sint32 i = 0; i < pMyWin32App->m_vecFrames.getItemCount(); i++)
1161 {
1162 AP_Win32Frame * curFrame = (AP_Win32Frame*)pMyWin32App->m_vecFrames[i];
1163 UT_continue_if_fail(curFrame);
1164
1165 HWND hwnd = curFrame->getTopLevelWindow();
1166 ShowWindow(hwnd, iCmdShow);
1167 UpdateWindow(hwnd);
1168 }
1169
1170 // do dispatch loop
1171 while(UT_GetMessage(&msg, NULL, 0, 0))
1172 {
1173 // TranslateMessage is not called because AbiWord
1174 // has its own way of decoding keyboard accelerators
1175 if (pMyWin32App->handleModelessDialogMessage(&msg))
1176 continue;
1177
1178 TranslateMessage(&msg);
1179 UT_DispatchMessage(&msg);
1180
1181 // Check for idle condition
1182 while( !UT_Win32Idle::_isEmpty() &&
1183 !PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE) )
1184 {
1185 // Fire idle functions when no pending messages
1186 UT_Win32Idle::_fireall();
1187 }
1188 }
1189 }
1190
1191 // Un-init OLE
1192 if (bInitialized)
1193 OleUninitialize();
1194
1195 FreeLibrary(hinstRich);
1196
1197 // unload all loaded plugins (remove some of the memory leaks shown at shutdown :-)
1198 XAP_ModuleManager::instance().unloadAllPlugins();
1199
1200 // Step 4: Destroy the App. It should take care of deleting all frames.
1201 pMyWin32App->shutdown();
1202 delete pMyWin32App;
1203
1204
1205 }// end of thes block is controlled by the Exception Handler
1206
1207 //
1208 // If an exception happens, with "catch" the block
1209 // and then the save it into disk
1210 //
1211 catch (...)
1212 {
1213 #ifdef DEBUG
1214 throw;
1215 #endif
1216
1217 AP_Win32App *pApp = (AP_Win32App *) XAP_App::getApp();
1218
1219 UT_return_val_if_fail (pApp,1);
1220
1221 // first of all, try to save the current prefs (so that any log entries are dumped
1222 // onto disk -- this allows us to save useful info for dbg purposes) we will enclose
1223 // this inside of a try/catch block, so that in the (unlikely) case something goes
1224 // badly wrong when writing the prefs file, we still get chance to save the open
1225 // documents
1226
1227 try
1228 {
1229 if(pApp->getPrefs())
1230 {
1231 pApp->getPrefs()->savePrefsFile();
1232 }
1233 }
1234 catch(...)
1235 {
1236 // do nothing
1237 }
1238
1239 IEFileType abiType = IE_Imp::fileTypeForSuffix(".abw");
1240 for (UT_sint32 i = 0; i < pApp->m_vecFrames.getItemCount(); i++)
1241 {
1242 AP_Win32Frame * curFrame = (AP_Win32Frame*)pApp->m_vecFrames[i];
1243 UT_continue_if_fail(curFrame);
1244
1245 // again, we want to catch any exception thrown while saving individual documents,
1246 // in order to run through the whole loop
1247 try
1248 {
1249 if (NULL == curFrame->getFilename())
1250 curFrame->backup(".abw.saved", abiType);
1251 else
1252 curFrame->backup(".saved", abiType);
1253 }
1254 catch(...)
1255 {
1256 // do nothing
1257 }
1258 }
1259
1260 // Tell the user was has just happened
1261 AP_Win32Frame * curFrame = (AP_Win32Frame*)pApp->m_vecFrames[0];
1262 if (curFrame)
1263 {
1264 curFrame->showMessageBox(AP_STRING_ID_MSG_Exception,XAP_Dialog_MessageBox::b_O, XAP_Dialog_MessageBox::a_OK);
1265
1266 }
1267 }// end of except
1268
1269 SET_CRT_DEBUG_FIELD( _CRTDBG_LEAK_CHECK_DF );
1270 return msg.wParam;
1271 }
1272
1273 /* This function takes a description and compares it all the registerd
1274 importers descriptions and returns either the appropriate importer's
1275 IEFileType or returns IEFT_Unknown if no match was made.
1276 */
_getFileTypeFromDesc(const char * desc)1277 IEFileType AP_Win32App::_getFileTypeFromDesc(const char *desc)
1278 {
1279 const char *iftDesc;
1280 const char *iftSuffixList;
1281 IEFileType ift;
1282
1283 // no description given or description == 'UNKNOWN' then unknown
1284 if (!desc || !*desc || (g_ascii_strcasecmp(desc, "Unknown")==0))
1285 return IEFT_Unknown;
1286
1287 UT_uint32 i = 0;
1288 while (IE_Imp::enumerateDlgLabels(i, &iftDesc, &iftSuffixList, &ift))
1289 {
1290 // TODO: change to actually test all but suffixes,
1291 // ie if iftDesc == 'Some FileType (*.sft, *.someft)' then only
1292 // test against 'Some FileType'
1293 if (g_ascii_strncasecmp(iftDesc, desc, strlen(desc)) == 0)
1294 return ift;
1295
1296 // try next importer
1297 i++;
1298 }
1299
1300 // if we made it here then description didn't match anything, so unknown.
1301 return IEFT_Unknown;
1302 }
1303
fileOpen(XAP_Frame * pFrame,const char * pNewFile)1304 UT_Error AP_Win32App::fileOpen(XAP_Frame * pFrame, const char * pNewFile)
1305 {
1306 return ::fileOpen(pFrame, pNewFile, IEFT_Unknown);
1307 }
1308
handleModelessDialogMessage(MSG * msg)1309 bool AP_Win32App::handleModelessDialogMessage( MSG * msg )
1310 {
1311 int iCounter;
1312 HWND hWnd = NULL;
1313
1314 // Try to knock off the easy case quickly
1315 if( m_IdTable[ 0 ].id == -1 )
1316 return false;
1317
1318 for( iCounter = 0; iCounter <= NUM_MODELESSID; iCounter++ )
1319 {
1320 if( m_IdTable[ iCounter ].id != -1 )
1321 {
1322 hWnd = (HWND) m_IdTable[ iCounter ].pDialog->pGetWindowHandle();
1323
1324 if( hWnd && IsDialogMessageW( hWnd, msg ) )
1325 return true;
1326 }
1327 else
1328 break;
1329 }
1330
1331 return false;
1332 }
1333
1334 // cmdline processing call back I reckon
errorMsgBadArg(const char * msg)1335 void AP_Win32App::errorMsgBadArg(const char *msg)
1336 {
1337 char *pszMessage;
1338 UT_Win32LocaleString str;
1339
1340 pszMessage = g_strdup_printf ("%s\nRun with --help' to see a full list of available command line options.\n", msg);
1341 str.fromUTF8(pszMessage);
1342 MessageBoxW(NULL, str.c_str(), L"Command Line Option Error", MB_OK|MB_ICONERROR);
1343 g_free( pszMessage );
1344 }
1345
1346 // cmdline processing call back I reckon
errorMsgBadFile(XAP_Frame * pFrame,const char * file,UT_Error error)1347 void AP_Win32App::errorMsgBadFile(XAP_Frame * pFrame, const char * file,
1348 UT_Error error)
1349 {
1350 s_CouldNotLoadFileMessage (pFrame, file, error);
1351 }
1352
1353 /*!
1354 * A callback for AP_Args's doWindowlessArgs call which handles
1355 * platform-specific windowless args.
1356 * return false if we should exit normally but Window should not be displayed
1357 */
doWindowlessArgs(const AP_Args * Args,bool & bSuccess)1358 bool AP_Win32App::doWindowlessArgs(const AP_Args *Args, bool & bSuccess)
1359 {
1360 bSuccess = true;
1361
1362 AP_Win32App * pMyWin32App = static_cast<AP_Win32App*>(Args->getApp());
1363
1364 if (Args->m_sGeometry)
1365 {
1366 // [--geometry <X geometry string>]
1367 #if 0
1368 gint x = 0;
1369 gint y = 0;
1370 guint width = 0;
1371 guint height = 0;
1372
1373 XParseGeometry(Args->m_sGeometry, &x, &y, &width, &height);
1374
1375 // set the xap-level geometry for future frame use
1376 Args->getApp()->setGeometry(x, y, width, height, f);
1377 #endif
1378
1379 parseAndSetGeometry(Args->m_sGeometry);
1380 }
1381 else
1382 if (Args->m_sPrintTo)
1383 {
1384 if (Args->m_sFiles[0])
1385 {
1386 UT_DEBUGMSG(("DOM: Printing file %s\n", Args->m_sFiles[0]));
1387 AP_Convert conv ;
1388
1389 if (Args->m_sMerge)
1390 conv.setMergeSource (Args->m_sMerge);
1391
1392 if (Args->m_impProps)
1393 conv.setImpProps (Args->m_impProps);
1394 if (Args->m_expProps)
1395 conv.setExpProps (Args->m_expProps);
1396
1397 UT_String s = "AbiWord: ";
1398 s+= Args->m_sFiles[0];
1399
1400 UT_Win32LocaleString prn, doc;
1401 prn.fromASCII (Args->m_sPrintTo);
1402 doc.fromASCII (s.c_str());
1403 GR_Graphics * pG = GR_Win32Graphics::getPrinterGraphics(prn.c_str(), doc.c_str());
1404 if(!pG)
1405 {
1406 // do not assert here, if the graphics creation failed, the static
1407 // constructor has asserted already somewhere more relevant
1408 return false;
1409 }
1410
1411 conv.setVerbose(Args->m_iVerbose);
1412 conv.print (Args->m_sFiles[0], pG, Args->m_sFileExtension);
1413
1414 delete pG;
1415 }
1416 else
1417 {
1418 // couldn't load document
1419 UT_DEBUGMSG(("Error: no file to print!\n"));
1420 bSuccess = false;
1421 }
1422
1423 return false;
1424 }
1425
1426 if(Args->m_sPluginArgs)
1427 {
1428 //
1429 // Start a plugin rather than the main abiword application.
1430 //
1431 const char * szName = NULL;
1432 XAP_Module * pModule = NULL;
1433 bool bFound = false;
1434 if(Args->m_sPluginArgs[0])
1435 {
1436 const char * szRequest = Args->m_sPluginArgs[0];
1437 const UT_GenericVector<XAP_Module*> * pVec = XAP_ModuleManager::instance().enumModules ();
1438 UT_DEBUGMSG((" %d plugins loaded \n",pVec->getItemCount()));
1439 for (UT_sint32 i = 0; (i < pVec->size()) && !bFound; i++)
1440 {
1441 pModule = pVec->getNthItem (i);
1442 szName = pModule->getModuleInfo()->name;
1443 UT_DEBUGMSG(("%s\n", szName));
1444 if(strcmp(szName,szRequest) == 0)
1445 {
1446 bFound = true;
1447 }
1448 }
1449 }
1450 if(!bFound)
1451 {
1452 UT_DEBUGMSG(("Plugin %s not found or loaded \n",Args->m_sPluginArgs[0]));
1453 bSuccess = false;
1454 return false;
1455 }
1456
1457 //
1458 // You must put the name of the ev_EditMethod in the usage field
1459 // of the plugin registered information.
1460 //
1461 const char * evExecute = pModule->getModuleInfo()->usage;
1462 EV_EditMethodContainer* pEMC = pMyWin32App->getEditMethodContainer();
1463 const EV_EditMethod * pInvoke = pEMC->findEditMethodByName(evExecute);
1464 if(!pInvoke)
1465 {
1466 UT_DEBUGMSG(("Plugin %s invoke method %s not found \n",
1467 Args->m_sPluginArgs[0],evExecute));
1468 bSuccess = false;
1469 return false;
1470 }
1471 //
1472 // Execute the plugin, then quit
1473 //
1474 ev_EditMethod_invoke(pInvoke, UT_String("Called From App"));
1475 return false;
1476 }
1477
1478 return true;
1479 }
1480
1481
1482 /*
1483 Get the user interface languages installed
1484 Caller should delete the allocated vector
1485 */
getInstalledUILanguages(void)1486 UT_Vector* AP_Win32App::getInstalledUILanguages(void)
1487 {
1488 UT_Vector* pVec = new UT_Vector(64,16);
1489 UT_Language lang;
1490
1491 for (UT_uint32 i=0; i< lang.getCount(); i++)
1492 {
1493 const char *pLangCode = (const char*)lang.getNthLangCode(i);
1494 if (doesStringSetExist(pLangCode))
1495 pVec->addItem(g_strdup((char*)pLangCode));
1496 else
1497 {
1498 /*The en-US is the default internal string set and wont be found on disk but it should be also listed*/
1499 if (strcmp(pLangCode, "en-US")==0)
1500 pVec->addItem(g_strdup((char*)pLangCode));
1501 }
1502
1503 }
1504
1505 return pVec;
1506 }
1507
1508 /*
1509 Does a stringSet exist on disk?
1510 */
doesStringSetExist(const char * pLocale)1511 bool AP_Win32App::doesStringSetExist(const char* pLocale)
1512 {
1513 HANDLE in;
1514 const char * szDirectory = NULL;
1515
1516 UT_return_val_if_fail(pLocale, false);
1517
1518 getPrefsValueDirectory(true,AP_PREF_KEY_StringSetDirectory,&szDirectory);
1519 UT_return_val_if_fail(((szDirectory) && (*szDirectory)), false);
1520
1521 char *szPathname = (char*) UT_calloc(sizeof(char),strlen(szDirectory)+strlen(pLocale)+100);
1522 UT_return_val_if_fail(szPathname, false);
1523
1524 char *szDest = szPathname;
1525 strcpy(szDest, szDirectory);
1526 szDest += strlen(szDest);
1527 if ((szDest > szPathname) && (szDest[-1]!='\\'))
1528 *szDest++='\\';
1529 lstrcpyA(szDest,pLocale);
1530 lstrcatA(szDest,".strings");
1531
1532 UT_Win32LocaleString wsFilename;
1533 wsFilename.fromUTF8(szPathname);
1534
1535 in = CreateFileW(wsFilename.c_str(),0,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,
1536 OPEN_EXISTING,0,NULL);
1537 g_free (szPathname);
1538
1539 if (in!=INVALID_HANDLE_VALUE)
1540 {
1541 CloseHandle(in);
1542 return true;
1543 }
1544
1545 return false;
1546 }
1547
1548
1549 /* From UCS4 To WinLocale */
s_fromUCS4ToWinLocale(const UT_UCS4Char * szIn)1550 UT_Win32LocaleString AP_Win32App::s_fromUCS4ToWinLocale(const UT_UCS4Char * szIn)
1551 {
1552 UT_Win32LocaleString sRslt;
1553 sRslt.fromUCS4(szIn);
1554 //UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
1555 return sRslt;
1556 }
1557
1558 /* From WinLocale To UCS4*/
s_fromWinLocaleToUCS4(const char * szIn)1559 UT_UCS4String AP_Win32App::s_fromWinLocaleToUCS4(const char* szIn)
1560 {
1561 UT_UCS4Char * src = new UT_UCS4Char[strlen(szIn)+1];
1562 UT_UCS4_strcpy_char(src, (char*)szIn);
1563 UT_UCS4String sRslt(src);
1564 delete [] src;
1565
1566 return sRslt;
1567 }
1568
1569 /* From UTF8 To WinLocale */
s_fromUTF8ToWinLocale(const char * szInUTF8)1570 UT_Win32LocaleString AP_Win32App::s_fromUTF8ToWinLocale(const char* szInUTF8)
1571 {
1572 UT_UTF8String utf8(szInUTF8);
1573 UT_UCS4String sUCS4(utf8.ucs4_str());
1574 return AP_Win32App::s_fromUCS4ToWinLocale(sUCS4.ucs4_str());
1575 }
1576
1577 /* From WinLocale To UTF8*/
s_fromWinLocaleToUTF8(const char * szIn)1578 UT_UTF8String AP_Win32App::s_fromWinLocaleToUTF8(const char* szIn)
1579 {
1580 UT_UCS4String sUCS4 = AP_Win32App::s_fromWinLocaleToUCS4(szIn);
1581 UT_UTF8String sRslt(sUCS4.utf8_str());
1582
1583 return sRslt;
1584 }
1585
newDefaultScreenGraphics() const1586 GR_Graphics * AP_Win32App::newDefaultScreenGraphics() const
1587 {
1588 XAP_Frame * pFrame = findValidFrame();
1589 UT_return_val_if_fail( pFrame, NULL );
1590
1591 AP_Win32FrameImpl * pFI = (AP_Win32FrameImpl *) pFrame->getFrameImpl();
1592 UT_return_val_if_fail( pFI, NULL );
1593
1594 return pFI->createDocWndGraphics();
1595 }
1596