Stroika Library 3.0d23
 
Loading...
Searching...
No Matches
ActiveLedIt/Sources/LedItView.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
6DISABLE_COMPILER_MSC_WARNING_START (5054)
7#include <afxwin.h>
8DISABLE_COMPILER_MSC_WARNING_END (5054)
9
10#include "Stroika/Foundation/DataExchange/OptionsFile.h"
12#include "Stroika/Foundation/Execution/ModuleGetterSetter.h"
13#include "Stroika/Foundation/IO/FileSystem/FileUtils.h"
15
16#include "Stroika/Frameworks/Led/ChunkedArrayTextStore.h"
17#include "Stroika/Frameworks/Led/StdDialogs.h"
18
19#include "DispIDs.h"
20#include "FontMenu.h"
21#include "Resource.h"
22#include "UserConfigCommands.h"
23
24#include "LedItView.h"
25
26#if qFunnyDisplayInDesignMode
27#include "Stroika/Frameworks/Led/HandySimple.h"
28#endif
29
30using namespace Stroika::Foundation;
32using namespace Stroika::Foundation::Execution;
33
34using Memory::MakeSharedPtr;
35
36using SearchParameters = LedItView::SearchParameters;
37
38namespace {
39 struct Options_ {
40 SearchParameters fSearchParameters{};
41 };
42
43 struct Options_Storage_IMPL_ {
44 Options_Storage_IMPL_ ()
45 : fOptionsFile_{L"AppSettings"sv,
46 [] () -> ObjectVariantMapper {
48
49 // really should use String, no longer Led_tString, but for now... (note this only works as is for wchar_t Led_tString
50 mapper.Add<Led_tString> ([] (const ObjectVariantMapper& /*mapper*/,
51 const Led_tString* obj) -> VariantValue { return String{*obj}; },
52 [] (const ObjectVariantMapper& /*mapper*/, const VariantValue& d,
53 Led_tString* intoObj) -> void { *intoObj = d.As<String> ().As<Led_tString> (); });
54 mapper.AddCommonType<vector<Led_tString>> ();
55
56 mapper.AddClass<SearchParameters> ({
57 {"MatchString"sv, &SearchParameters::fMatchString},
58 {"WrapSearch"sv, &SearchParameters::fWrapSearch},
59 {"WholeWordSearch"sv, &SearchParameters::fWholeWordSearch},
60 {"CaseSensativeSearch"sv, &SearchParameters::fCaseSensativeSearch},
61 {"RecentMatchStrings"sv, &SearchParameters::fRecentFindStrings},
62 });
63
64 mapper.AddClass<Options_> ({
65 {"Search-Parameters"sv, &Options_::fSearchParameters},
66 });
67 return mapper;
68 }(),
69
71
72 // override the default name mapper to assure folder created, since no installer for activex controls
73 [] (const String& moduleName, const String& fileSuffix) {
74 static const auto kDefaultMapper_ = OptionsFile::mkFilenameMapper (L"ActiveLedIt"sv);
75 filesystem::path fileName = kDefaultMapper_ (moduleName, fileSuffix);
76 filesystem::create_directories (fileName.parent_path ());
77 return fileName;
78 }}
79 , fActualCurrentConfigData_{fOptionsFile_.Read<Options_> (Options_{})}
80 {
81 Set (fActualCurrentConfigData_); // assure derived data (and changed fields etc) up to date
82 }
83 Options_ Get () const
84 {
85 return fActualCurrentConfigData_;
86 }
87 void Set (const Options_& v)
88 {
89 fActualCurrentConfigData_ = v;
90 fOptionsFile_.Write (v);
91 }
92
93 private:
94 OptionsFile fOptionsFile_;
95 Options_ fActualCurrentConfigData_;
96 };
97
99}
100
101class My_CMDNUM_MAPPING : public MFC_CommandNumberMapping {
102public:
103 My_CMDNUM_MAPPING ()
104 {
105 AddAssociation (kFindAgainCmd, LedItView::kFindAgain_CmdID);
106 AddAssociation (kEnterFindStringCmd, LedItView::kEnterFindString_CmdID);
107 AddAssociation (kReplaceCmd, LedItView::kReplace_CmdID);
108 AddAssociation (kReplaceAgainCmd, LedItView::kReplaceAgain_CmdID);
109 AddAssociation (kSpellCheckCmd, LedItView::kSpellCheck_CmdID);
110
111 AddAssociation (kSelectWordCmd, LedItView::kSelectWord_CmdID);
112 AddAssociation (kSelectTextRowCmd, LedItView::kSelectTextRow_CmdID);
113 AddAssociation (kSelectParagraphCmd, LedItView::kSelectParagraph_CmdID);
114 AddAssociation (kSelectTableIntraCellAllCmd, LedItView::kSelectTableIntraCellAll_CmdID);
115 AddAssociation (kSelectTableCellCmd, LedItView::kSelectTableCell_CmdID);
116 AddAssociation (kSelectTableRowCmd, LedItView::kSelectTableRow_CmdID);
117 AddAssociation (kSelectTableColumnCmd, LedItView::kSelectTableColumn_CmdID);
118 AddAssociation (kSelectTableCmd, LedItView::kSelectTable_CmdID);
119
120 AddAssociation (kFontSize9Cmd, LedItView::kFontSize9_CmdID);
121 AddAssociation (kFontSize10Cmd, LedItView::kFontSize10_CmdID);
122 AddAssociation (kFontSize12Cmd, LedItView::kFontSize12_CmdID);
123 AddAssociation (kFontSize14Cmd, LedItView::kFontSize14_CmdID);
124 AddAssociation (kFontSize18Cmd, LedItView::kFontSize18_CmdID);
125 AddAssociation (kFontSize24Cmd, LedItView::kFontSize24_CmdID);
126 AddAssociation (kFontSize36Cmd, LedItView::kFontSize36_CmdID);
127 AddAssociation (kFontSize48Cmd, LedItView::kFontSize48_CmdID);
128 AddAssociation (kFontSize72Cmd, LedItView::kFontSize72_CmdID);
129#if qSupportOtherFontSizeDlg
130 AddAssociation (kFontSizeOtherCmd, LedItView::kFontSizeOther_CmdID);
131#endif
132 AddAssociation (kFontSizeSmallerCmd, LedItView::kFontSizeSmaller_CmdID);
133 AddAssociation (kFontSizeLargerCmd, LedItView::kFontSizeLarger_CmdID);
134
135 AddAssociation (kBlackColorCmd, LedItView::kFontColorBlack_CmdID);
136 AddAssociation (kMaroonColorCmd, LedItView::kFontColorMaroon_CmdID);
137 AddAssociation (kGreenColorCmd, LedItView::kFontColorGreen_CmdID);
138 AddAssociation (kOliveColorCmd, LedItView::kFontColorOlive_CmdID);
139 AddAssociation (kNavyColorCmd, LedItView::kFontColorNavy_CmdID);
140 AddAssociation (kPurpleColorCmd, LedItView::kFontColorPurple_CmdID);
141 AddAssociation (kTealColorCmd, LedItView::kFontColorTeal_CmdID);
142 AddAssociation (kGrayColorCmd, LedItView::kFontColorGray_CmdID);
143 AddAssociation (kSilverColorCmd, LedItView::kFontColorSilver_CmdID);
144 AddAssociation (kRedColorCmd, LedItView::kFontColorRed_CmdID);
145 AddAssociation (kLimeColorCmd, LedItView::kFontColorLime_CmdID);
146 AddAssociation (kYellowColorCmd, LedItView::kFontColorYellow_CmdID);
147 AddAssociation (kBlueColorCmd, LedItView::kFontColorBlue_CmdID);
148 AddAssociation (kFuchsiaColorCmd, LedItView::kFontColorFuchsia_CmdID);
149 AddAssociation (kAquaColorCmd, LedItView::kFontColorAqua_CmdID);
150 AddAssociation (kWhiteColorCmd, LedItView::kFontColorWhite_CmdID);
151 AddAssociation (kFontColorOtherCmd, LedItView::kFontColorOther_CmdID);
152
153 AddAssociation (kJustifyLeftCmd, LedItView::kJustifyLeft_CmdID);
154 AddAssociation (kJustifyCenterCmd, LedItView::kJustifyCenter_CmdID);
155 AddAssociation (kJustifyRightCmd, LedItView::kJustifyRight_CmdID);
156 AddAssociation (kJustifyFullCmd, LedItView::kJustifyFull_CmdID);
157
158#if qSupportParagraphSpacingDlg
159 AddAssociation (kParagraphSpacingCmd, LedItView::kParagraphSpacingCommand_CmdID);
160#endif
161#if qSupportParagraphIndentsDlg
162 AddAssociation (kParagraphIndentsCmd, LedItView::kParagraphIndentsCommand_CmdID);
163#endif
164
165 AddAssociation (kListStyle_NoneCmd, LedItView::kListStyle_None_CmdID);
166 AddAssociation (kListStyle_BulletCmd, LedItView::kListStyle_Bullet_CmdID);
167
168 AddAssociation (kIncreaseIndentCmd, LedItView::kIncreaseIndent_CmdID);
169 AddAssociation (kDecreaseIndentCmd, LedItView::kDecreaseIndent_CmdID);
170
171 AddRangeAssociation (kBaseFontNameCmd, kLastFontNameCmd, LedItView::kFontMenuFirst_CmdID, LedItView::kFontMenuLast_CmdID);
172
173 AddAssociation (kFontStylePlainCmd, LedItView::kFontStylePlain_CmdID);
174 AddAssociation (kFontStyleBoldCmd, LedItView::kFontStyleBold_CmdID);
175 AddAssociation (kFontStyleItalicCmd, LedItView::kFontStyleItalic_CmdID);
176 AddAssociation (kFontStyleUnderlineCmd, LedItView::kFontStyleUnderline_CmdID);
177 AddAssociation (kFontStyleStrikeoutCmd, LedItView::kFontStyleStrikeout_CmdID);
178 AddAssociation (kSubScriptCmd, LedItView::kSubScriptCommand_CmdID);
179 AddAssociation (kSuperScriptCmd, LedItView::kSuperScriptCommand_CmdID);
180 AddAssociation (kChooseFontDialogCmd, LedItView::kChooseFontCommand_CmdID);
181
182 AddAssociation (kInsertTableCmd, LedItView::kInsertTable_CmdID);
183 AddAssociation (kInsertTableRowAboveCmd, LedItView::kInsertTableRowAbove_CmdID);
184 AddAssociation (kInsertTableRowBelowCmd, LedItView::kInsertTableRowBelow_CmdID);
185 AddAssociation (kInsertTableColBeforeCmd, LedItView::kInsertTableColBefore_CmdID);
186 AddAssociation (kInsertTableColAfterCmd, LedItView::kInsertTableColAfter_CmdID);
187 AddAssociation (kInsertURLCmd, LedItView::kInsertURL_CmdID);
188 AddAssociation (kInsertSymbolCmd, LedItView::kInsertSymbol_CmdID);
189
190 // AddAssociation (kPropertiesForSelectionCmd, LedItView::kSelectedEmbeddingProperties_CmdID);
191 AddRangeAssociation (kFirstSelectedEmbeddingCmd, kLastSelectedEmbeddingCmd, LedItView::kFirstSelectedEmbedding_CmdID,
192 LedItView::kLastSelectedEmbedding_CmdID);
193
194// Not 100% sure why this are disabled??? But they were before in AL (as of 2003-04-04 - AL 3.1a6x so leave it for now)
195#if 0
196 AddAssociation (kHideSelectionCmd, LedItView::kHideSelection_CmdID);
197 AddAssociation (kUnHideSelectionCmd, LedItView::kUnHideSelection_CmdID);
198#endif
199 AddAssociation (kRemoveTableRowsCmd, LedItView::kRemoveTableRows_CmdID);
200 AddAssociation (kRemoveTableColumnsCmd, LedItView::kRemoveTableColumns_CmdID);
201
202// Not 100% sure why this are disabled??? But they were before in AL (as of 2003-04-04 - AL 3.1a6x so leave it for now)
203#if 0
204 AddAssociation (kShowHideParagraphGlyphsCmd, LedItView::kShowHideParagraphGlyphs_CmdID);
205 AddAssociation (kShowHideTabGlyphsCmd, LedItView::kShowHideTabGlyphs_CmdID);
206 AddAssociation (kShowHideSpaceGlyphsCmd, LedItView::kShowHideSpaceGlyphs_CmdID);
207#endif
208 }
209};
210My_CMDNUM_MAPPING sMy_CMDNUM_MAPPING;
211
212struct ActiveLedIt_DialogSupport : TextInteractor::DialogSupport, WordProcessor::DialogSupport {
213public:
214 using CommandNumber = TextInteractor::DialogSupport::CommandNumber;
215
216public:
217 ActiveLedIt_DialogSupport ()
218 {
219 TextInteractor::SetDialogSupport (this);
220 WordProcessor::SetDialogSupport (this);
221 }
222 ~ActiveLedIt_DialogSupport ()
223 {
224 WordProcessor::SetDialogSupport (NULL);
225 TextInteractor::SetDialogSupport (NULL);
226 }
227
228// TextInteractor::DialogSupport
229#if qSupportStdFindDlg
230public:
231 virtual void DisplayFindDialog (Led_tString* findText, const vector<Led_tString>& recentFindSuggestions, bool* wrapSearch,
232 bool* wholeWordSearch, bool* caseSensative, bool* pressedOK) override
233 {
234 Led_StdDialogHelper_FindDialog findDialog (::AfxGetResourceHandle (), ::GetActiveWindow ());
235
236 findDialog.fFindText = *findText;
237 findDialog.fRecentFindTextStrings = recentFindSuggestions;
238 findDialog.fWrapSearch = *wrapSearch;
239 findDialog.fWholeWordSearch = *wholeWordSearch;
240 findDialog.fCaseSensativeSearch = *caseSensative;
241
242 findDialog.DoModal ();
243
244 *findText = findDialog.fFindText;
245 *wrapSearch = findDialog.fWrapSearch;
246 *wholeWordSearch = findDialog.fWholeWordSearch;
247 *caseSensative = findDialog.fCaseSensativeSearch;
248 *pressedOK = findDialog.fPressedOK;
249 }
250#endif
251#if qSupportStdReplaceDlg
252public:
253 virtual ReplaceButtonPressed DisplayReplaceDialog (Led_tString* findText, const vector<Led_tString>& recentFindSuggestions,
254 Led_tString* replaceText, bool* wrapSearch, bool* wholeWordSearch, bool* caseSensative) override
255 {
256 Led_StdDialogHelper_ReplaceDialog replaceDialog (::AfxGetResourceHandle (), ::GetActiveWindow ());
257
258 replaceDialog.fFindText = *findText;
259 replaceDialog.fRecentFindTextStrings = recentFindSuggestions;
260 replaceDialog.fReplaceText = *replaceText;
261 replaceDialog.fWrapSearch = *wrapSearch;
262 replaceDialog.fWholeWordSearch = *wholeWordSearch;
263 replaceDialog.fCaseSensativeSearch = *caseSensative;
264
265 replaceDialog.DoModal ();
266
267 *findText = replaceDialog.fFindText;
268 *replaceText = replaceDialog.fReplaceText;
269 *wrapSearch = replaceDialog.fWrapSearch;
270 *wholeWordSearch = replaceDialog.fWholeWordSearch;
271 *caseSensative = replaceDialog.fCaseSensativeSearch;
272
273 switch (replaceDialog.fPressed) {
274 case Led_StdDialogHelper_ReplaceDialog::eCancel:
275 return eReplaceButton_Cancel;
276 case Led_StdDialogHelper_ReplaceDialog::eFind:
277 return eReplaceButton_Find;
278 case Led_StdDialogHelper_ReplaceDialog::eReplace:
279 return eReplaceButton_Replace;
280 case Led_StdDialogHelper_ReplaceDialog::eReplaceAll:
281 return eReplaceButton_ReplaceAll;
282 case Led_StdDialogHelper_ReplaceDialog::eReplaceAllInSelection:
283 return eReplaceButton_ReplaceAllInSelection;
284 }
285 Assert (false);
286 return eReplaceButton_Cancel;
287 }
288#endif
289#if qSupportStdSpellCheckDlg
290public:
291 virtual void DisplaySpellCheckDialog (SpellCheckDialogCallback& callback) override
292 {
293 Led_StdDialogHelper_SpellCheckDialog::CallbackDelegator<SpellCheckDialogCallback> delegator{callback};
294#if qStroika_Foundation_Common_Platform_MacOS
295 Led_StdDialogHelper_SpellCheckDialog spellCheckDialog (delegator);
296#elif qStroika_Foundation_Common_Platform_Windows
297 Led_StdDialogHelper_SpellCheckDialog spellCheckDialog (delegator, ::AfxGetResourceHandle (), ::GetActiveWindow ());
298#elif qStroika_FeatureSupported_XWindows
299 Led_StdDialogHelper_SpellCheckDialog spellCheckDialog (delegator, GTK_WINDOW (LedItApplication::Get ().GetAppWindow ()));
300#endif
301
302 spellCheckDialog.DoModal ();
303 }
304#endif
305
306 // WordProcessor::DialogSupport
307public:
308 virtual FontNameSpecifier CmdNumToFontName (CommandNumber cmdNum) override
309 {
310 Require (cmdNum >= WordProcessor::kFontMenuFirst_CmdID);
311 Require (cmdNum <= WordProcessor::kFontMenuLast_CmdID);
312 return ::CmdNumToFontName (MFC_CommandNumberMapping::Get ().ReverseLookup (cmdNum)).c_str ();
313 }
314#if qSupportOtherFontSizeDlg
315 virtual DistanceType PickOtherFontHeight (DistanceType origHeight) override
316 {
317#if qStroika_Foundation_Common_Platform_MacOS
318 Led_StdDialogHelper_OtherFontSizeDialog dlg;
319#elif qStroika_Foundation_Common_Platform_Windows
320 Led_StdDialogHelper_OtherFontSizeDialog dlg (::AfxGetResourceHandle (), ::GetActiveWindow ());
321#endif
322 dlg.InitValues (origHeight);
323 if (dlg.DoModal ()) {
324 return dlg.fFontSize_Result;
325 }
326 else {
327 return 0;
328 }
329 }
330#endif
331#if qSupportParagraphSpacingDlg
332 virtual bool PickNewParagraphLineSpacing (TWIPS* spaceBefore, bool* spaceBeforeValid, TWIPS* spaceAfter, bool* spaceAfterValid,
333 LineSpacing* lineSpacing, bool* lineSpacingValid) override
334 {
335#if qStroika_Foundation_Common_Platform_MacOS
336 Led_StdDialogHelper_ParagraphSpacingDialog dlg;
337#elif qStroika_Foundation_Common_Platform_Windows
338 Led_StdDialogHelper_ParagraphSpacingDialog dlg (::AfxGetResourceHandle (), ::GetActiveWindow ());
339#endif
340 dlg.InitValues (*spaceBefore, *spaceBeforeValid, *spaceAfter, *spaceAfterValid, *lineSpacing, *lineSpacingValid);
341
342 if (dlg.DoModal ()) {
343 *spaceBeforeValid = dlg.fSpaceBefore_Valid;
344 if (*spaceBeforeValid) {
345 *spaceBefore = dlg.fSpaceBefore_Result;
346 }
347 *spaceAfterValid = dlg.fSpaceAfter_Valid;
348 if (*spaceAfterValid) {
349 *spaceAfter = dlg.fSpaceAfter_Result;
350 }
351 *lineSpacingValid = dlg.fLineSpacing_Valid;
352 if (*lineSpacingValid) {
353 *lineSpacing = dlg.fLineSpacing_Result;
354 }
355 return true;
356 }
357 else {
358 return false;
359 }
360 }
361#endif
362#if qSupportParagraphIndentsDlg
363 virtual bool PickNewParagraphMarginsAndFirstIndent (TWIPS* leftMargin, bool* leftMarginValid, TWIPS* rightMargin,
364 bool* rightMarginValid, TWIPS* firstIndent, bool* firstIndentValid) override
365 {
366#if qStroika_Foundation_Common_Platform_MacOS
367 Led_StdDialogHelper_ParagraphIndentsDialog dlg;
368#elif qStroika_Foundation_Common_Platform_Windows
369 Led_StdDialogHelper_ParagraphIndentsDialog dlg (::AfxGetResourceHandle (), ::GetActiveWindow ());
370#endif
371 dlg.InitValues (*leftMargin, *leftMarginValid, *rightMargin, *rightMarginValid, *firstIndent, *firstIndentValid);
372 if (dlg.DoModal ()) {
373 *leftMarginValid = dlg.fLeftMargin_Valid;
374 if (*leftMarginValid) {
375 *leftMargin = dlg.fLeftMargin_Result;
376 }
377 *rightMarginValid = dlg.fRightMargin_Valid;
378 if (*rightMarginValid) {
379 *rightMargin = dlg.fRightMargin_Result;
380 }
381 *firstIndentValid = dlg.fFirstIndent_Valid;
382 if (*firstIndentValid) {
383 *firstIndent = dlg.fFirstIndent_Result;
384 }
385 return true;
386 }
387 else {
388 return false;
389 }
390 }
391#endif
392 virtual void ShowSimpleEmbeddingInfoDialog (const SDKString& embeddingTypeName) override
393 {
394 // unknown embedding...
395 Led_StdDialogHelper_UnknownEmbeddingInfoDialog infoDialog (::AfxGetResourceHandle (), ::GetActiveWindow ());
396 infoDialog.fEmbeddingTypeName = embeddingTypeName;
397 (void)infoDialog.DoModal ();
398 }
399 virtual bool ShowURLEmbeddingInfoDialog (const SDKString& embeddingTypeName, SDKString* urlTitle, SDKString* urlValue) override
400 {
401 Led_StdDialogHelper_URLXEmbeddingInfoDialog infoDialog (::AfxGetResourceHandle (), ::GetActiveWindow ());
402 infoDialog.fEmbeddingTypeName = embeddingTypeName;
403 infoDialog.fTitleText = *urlTitle;
404 infoDialog.fURLText = *urlValue;
405 if (infoDialog.DoModal ()) {
406 *urlTitle = infoDialog.fTitleText;
407 *urlValue = infoDialog.fURLText;
408 return true;
409 }
410 else {
411 return false;
412 }
413 }
414 virtual bool ShowAddURLEmbeddingInfoDialog (SDKString* urlTitle, SDKString* urlValue) override
415 {
416 Led_StdDialogHelper_AddURLXEmbeddingInfoDialog infoDialog (::AfxGetResourceHandle (), ::GetActiveWindow ());
417 infoDialog.fTitleText = *urlTitle;
418 infoDialog.fURLText = *urlValue;
419 if (infoDialog.DoModal ()) {
420 *urlTitle = infoDialog.fTitleText;
421 *urlValue = infoDialog.fURLText;
422 return true;
423 }
424 else {
425 return false;
426 }
427 }
428#if qSupportAddNewTableDlg
429 bool AddNewTableDialog (size_t* nRows, size_t* nCols)
430 {
431 RequireNotNull (nRows);
432 RequireNotNull (nCols);
433 Led_StdDialogHelper_AddNewTableDialog infoDialog (::AfxGetResourceHandle (), ::GetActiveWindow ());
434 infoDialog.fRows = *nRows;
435 infoDialog.fColumns = *nCols;
436 if (infoDialog.DoModal ()) {
437 *nRows = infoDialog.fRows;
438 *nCols = infoDialog.fColumns;
439 return true;
440 }
441 else {
442 return false;
443 }
444 }
445#endif
446#if qSupportEditTablePropertiesDlg
447 virtual bool EditTablePropertiesDialog (TableSelectionPropertiesInfo* tableProperties) override
448 {
449 RequireNotNull (tableProperties);
450
451 using DLGTYPE = Led_StdDialogHelper_EditTablePropertiesDialog;
452#if qStroika_Foundation_Common_Platform_MacOS
453 DLGTYPE infoDialog;
454#elif qStroika_Foundation_Common_Platform_Windows
455 DLGTYPE infoDialog (::AfxGetResourceHandle (), ::GetActiveWindow ());
456#endif
457 DLGTYPE::cvt<DLGTYPE::Info, TableSelectionPropertiesInfo> (&infoDialog.fInfo, *tableProperties);
458 if (infoDialog.DoModal ()) {
459 DLGTYPE::cvt<TableSelectionPropertiesInfo, DLGTYPE::Info> (tableProperties, infoDialog.fInfo);
460 return true;
461 }
462 else {
463 return false;
464 }
465 }
466#endif
467};
468static ActiveLedIt_DialogSupport sActiveLedIt_DialogSupport;
469
470static BOOL CALLBACK _AfxAbortProc (HDC, int)
471{
472 _AFX_WIN_STATE* pWinState = _afxWinState;
473 MSG msg;
474 while (!pWinState->m_bUserAbort && ::PeekMessage (&msg, NULL, NULL, NULL, PM_NOREMOVE)) {
475 if (!AfxGetThread ()->PumpMessage ())
476 return FALSE; // terminate if WM_QUIT received
477 }
478 return !pWinState->m_bUserAbort;
479}
480
481/*
482 ********************************************************************************
483 ************************** LedItViewController *********************************
484 ********************************************************************************
485 */
486LedItViewController::LedItViewController ()
487 : fCommandHandler{kMaxNumUndoLevels}
488{
489 fHidableTextDatabase = MakeSharedPtr<ColoredUniformHidableTextMarkerOwner> (fTextStore);
490}
491
492/*
493 ********************************************************************************
494 ************************************ LedItView *********************************
495 ********************************************************************************
496 */
497DISABLE_COMPILER_MSC_WARNING_START (4407) // Not sure this is safe to ignore but I think it is due to qMFCRequiresCWndLeftmostBaseClass
498BEGIN_MESSAGE_MAP (LedItView, LedItView::inherited)
499ON_WM_MOUSEACTIVATE ()
500ON_WM_INITMENUPOPUP ()
501ON_WM_CONTEXTMENU ()
502ON_WM_CHAR ()
503ON_WM_KEYDOWN ()
504ON_WM_KEYUP ()
505ON_WM_SYSKEYDOWN ()
506ON_WM_SYSKEYUP ()
507ON_WM_MOUSEMOVE ()
508ON_WM_LBUTTONDOWN ()
509ON_WM_LBUTTONUP ()
510ON_WM_LBUTTONDBLCLK ()
511ON_WM_RBUTTONDOWN ()
512ON_WM_RBUTTONUP ()
513
514ON_COMMAND (ID_FILE_PRINT, OnFilePrint)
515ON_COMMAND (ID_FILE_PRINT_SETUP, OnFilePrintSetup)
516ON_COMMAND (ID_HELP_FINDER, OnBrowseHelpCommand)
517ON_COMMAND (kCheckForUpdatesWebPageCmdID, OnCheckForUpdatesWebPageCommand)
518ON_COMMAND (ID_APP_ABOUT, OnAboutBoxCommand)
519ON_COMMAND (kPasteFormatTextCmdID, OnPasteAsTextCommand)
520ON_UPDATE_COMMAND_UI (kPasteFormatTextCmdID, OnUpdatePasteAsTextCommand)
521ON_COMMAND_RANGE (kFirstOLEUserCmdCmdID, kLastOLEUserCmdCmdID, OnOLEUserCommand)
522ON_UPDATE_COMMAND_UI_RANGE (kFirstOLEUserCmdCmdID, kLastOLEUserCmdCmdID, OnUpdateOLEUserCommand)
523END_MESSAGE_MAP ()
524DISABLE_COMPILER_MSC_WARNING_END (4407)
525
526LedItView::LedItView ()
527 : inherited ()
528 , fController (NULL)
529 , fSupportContextMenu (true)
530 , fHideDisabledContextMenuItems (true)
531 , fWrapToWindow (true)
532 , fMaxLength (-1)
533 , fEnableAutoChangesBackgroundColor (true)
534 , fInDrawMetaFileMode (false)
535{
536 SetScrollBarType (v, eScrollBarAsNeeded);
537 SetScrollBarType (h, eScrollBarAsNeeded);
538 if (qFunnyDisplayInDesignMode) {
539 SetUseBitmapScrollingOptimization (false);
540 }
541 SetUseSecondaryHilight (true); // default to TRUE since I think this looks better and maybe a differentiator with other controls
542 const TWIPS kLedItViewTopMargin = TWIPS (120);
543 const TWIPS kLedItViewBottomMargin = TWIPS (0);
544 const TWIPS kLedItViewLHSMargin = TWIPS (150);
545 const TWIPS kLedItViewRHSMargin = TWIPS (0);
546 SetDefaultWindowMargins (TWIPS_Rect (kLedItViewTopMargin, kLedItViewLHSMargin, kLedItViewBottomMargin - kLedItViewTopMargin,
547 kLedItViewRHSMargin - kLedItViewLHSMargin));
548}
549
550LedItView::~LedItView ()
551{
552 SetController (NULL);
553}
554
555void LedItView::SetController (LedItViewController* controller)
556{
557 if (fController != NULL) {
558 SetHidableTextDatabase (NULL);
559 SetCommandHandler (NULL);
560 SpecifyTextStore (NULL);
561 }
562 fController = controller;
563 if (fController != NULL) {
564 SpecifyTextStore (&fController->fTextStore);
565 SetCommandHandler (&fController->fCommandHandler);
566 SetHidableTextDatabase (fController->fHidableTextDatabase);
567 }
568}
569
570void LedItView::SetSupportContextMenu (bool allowContextMenu)
571{
572 fSupportContextMenu = allowContextMenu;
573}
574
575void LedItView::SetHideDisabledContextMenuItems (bool hideDisabledContextMenuItems)
576{
577 fHideDisabledContextMenuItems = hideDisabledContextMenuItems;
578}
579
580void LedItView::SetWrapToWindow (bool wrapToWindow)
581{
582 if (fWrapToWindow != wrapToWindow) {
583 fWrapToWindow = wrapToWindow;
584 InvalidateAllCaches ();
585 Refresh ();
586 }
587}
588
589void LedItView::SetMaxLength (long maxLength)
590{
591 fMaxLength = maxLength;
592}
593
594void LedItView::GetLayoutMargins (RowReference row, CoordinateType* lhs, CoordinateType* rhs) const
595{
596 if (GetWrapToWindow ()) {
597 // Make the layout right margin of each line (paragraph) equal to the windowrect. Ie, wrap to the
598 // edge of the window. NB: because of this choice, we must 'InvalidateAllCaches' when the
599 // WindowRect changes in our SetWindowRect() override.
600 CoordinateType l = 0;
601 CoordinateType r = 0;
602 inherited::GetLayoutMargins (row, &l, &r);
603 r = max (static_cast<CoordinateType> (GetWindowRect ().GetWidth ()), l + 1);
604 Ensure (r > l);
605 if (lhs != NULL) {
606 *lhs = l;
607 }
608 if (rhs != NULL) {
609 *rhs = r;
610 }
611 }
612 else {
613 inherited::GetLayoutMargins (row, lhs, rhs);
614 }
615}
616
617void LedItView::SetWindowRect (const Led_Rect& windowRect)
618{
619 // Hook all changes in the window width, so we can invalidate the word-wrap info (see LedItView::GetLayoutMargins)
620 Led_Rect oldWindowRect = GetWindowRect ();
621 if (windowRect != oldWindowRect) {
622 WordWrappedTextImager::SetWindowRect (windowRect); // NB: use XX instead of inherited to avoid infinite recurse, due to sloppy mixin ambiguity resoltion in base classes (LGP990623)
623 if (GetWrapToWindow () and windowRect.GetSize () != oldWindowRect.GetSize ()) {
624 InvalidateAllCaches ();
625 }
626 }
627}
628
629DistanceType LedItView::CalculateFarthestRightMarginInWindow () const
630{
631 if (fWrapToWindow) {
632 return GetWindowRect ().GetWidth ();
633 }
634 else {
635 return inherited::CalculateFarthestRightMarginInWindow () / 20;
636 }
637}
638
639void LedItView::PostNcDestroy ()
640{
641}
642
643int LedItView::OnMouseActivate (CWnd* pDesktopWnd, UINT nHitTest, UINT message)
644{
645 if (fController != NULL) {
646 fController->ForceUIActive ();
647 }
648 return inherited::OnMouseActivate (pDesktopWnd, nHitTest, message);
649}
650
651void LedItView::OnInitMenuPopup (CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
652{
653 // Disable inappropriate commands.
654 // Remove disabled menu items from the popup (to save space).
655 // Remove consecutive (or leading) separators as useless.
656
657 CCmdUI state;
658 state.m_pSubMenu = NULL;
659 state.m_pMenu = pPopupMenu;
660 Assert (state.m_pOther == NULL);
661 Assert (state.m_pParentMenu == NULL);
662
663 // Set the enable/disable state of each menu item.
664 state.m_nIndexMax = pPopupMenu->GetMenuItemCount ();
665 for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax; ++state.m_nIndex) {
666 state.m_nID = pPopupMenu->GetMenuItemID (state.m_nIndex);
667 if (state.m_nID != 0) {
668 Assert (state.m_pOther == NULL);
669 Assert (state.m_pMenu != NULL);
670 state.DoUpdate (this, true);
671 }
672 }
673
674 // Remove disabled items (and unneeded separators)
675 if (GetHideDisabledContextMenuItems ()) {
676 bool prevItemSep = true; // prevent initial separators
677 for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;) {
678 state.m_nID = pPopupMenu->GetMenuItemID (state.m_nIndex);
679 if (state.m_nID == 0 and prevItemSep) {
680 pPopupMenu->RemoveMenu (state.m_nIndex, MF_BYPOSITION);
681 --state.m_nIndexMax;
682 continue;
683 }
684 if (state.m_nID != 0) {
685 MENUITEMINFO mInfo;
686 memset (&mInfo, 0, sizeof (mInfo));
687 mInfo.cbSize = sizeof (mInfo);
688 mInfo.fMask = MIIM_STATE;
689 Verify (::GetMenuItemInfo (pPopupMenu->GetSafeHmenu (), state.m_nIndex, true, &mInfo));
690 if (mInfo.fState & MFS_DISABLED) {
691 pPopupMenu->RemoveMenu (state.m_nIndex, MF_BYPOSITION);
692 --state.m_nIndexMax;
693 continue;
694 }
695 }
696 prevItemSep = bool (state.m_nID == 0);
697 state.m_nIndex++;
698 }
699 // if LAST item is a separator - remove THAT
700 if (prevItemSep) {
701 pPopupMenu->RemoveMenu (state.m_nIndexMax - 1, MF_BYPOSITION);
702 }
703 }
704
705 inherited::OnInitMenuPopup (pPopupMenu, nIndex, bSysMenu);
706}
707
708void LedItView::OnContextMenu (CWnd* /*pWnd*/, CPoint pt)
709{
710 if (GetSupportContextMenu ()) {
711 CMenu menu;
712 AssertNotNull (fController);
713 if (menu.Attach (fController->GenerateContextMenu ())) {
714 menu.TrackPopupMenu (TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, this);
715 }
716 }
717}
718extern short AFXAPI _AfxShiftState ();
719
720void LedItView::OnSysKeyDown (UINT nChar, UINT nRepCnt, UINT nFlags)
721{
722 if (fController != NULL) {
723 USHORT shortChar = static_cast<USHORT> (nChar);
724 fController->FireKeyDown (&shortChar, _AfxShiftState ());
725 }
726 inherited::OnSysKeyDown (nChar, nRepCnt, nFlags);
727}
728
729void LedItView::OnSysKeyUp (UINT nChar, UINT nRepCnt, UINT nFlags)
730{
731 if (fController != NULL) {
732 USHORT shortChar = static_cast<USHORT> (nChar);
733 fController->FireKeyUp (&shortChar, _AfxShiftState ());
734 }
735 inherited::OnSysKeyUp (nChar, nRepCnt, nFlags);
736}
737
738void LedItView::OnKeyDown (UINT nChar, UINT nRepCnt, UINT nFlags)
739{
740 if (fController != NULL) {
741 USHORT shortChar = static_cast<USHORT> (nChar);
742 fController->FireKeyDown (&shortChar, _AfxShiftState ());
743 }
744 inherited::OnKeyDown (nChar, nRepCnt, nFlags);
745}
746
747void LedItView::OnKeyUp (UINT nChar, UINT nRepCnt, UINT nFlags)
748{
749 if (fController != NULL) {
750 USHORT shortChar = static_cast<USHORT> (nChar);
751 fController->FireKeyUp (&shortChar, _AfxShiftState ());
752 }
753 inherited::OnKeyUp (nChar, nRepCnt, nFlags);
754}
755
756void LedItView::OnTypedNormalCharacter (Led_tChar theChar, bool optionPressed, bool shiftPressed, bool commandPressed, bool controlPressed, bool altKeyPressed)
757{
758 if (fController != NULL) {
759 USHORT shortChar = theChar;
760 fController->FireKeyPress (&shortChar);
761 }
762 inherited::OnTypedNormalCharacter (theChar, optionPressed, shiftPressed, commandPressed, controlPressed, altKeyPressed);
763}
764
765void LedItView::OnLButtonDown (UINT nFlags, CPoint oPoint)
766{
767 if (fController != NULL) {
768 fController->FireMouseDown (LEFT_BUTTON, _AfxShiftState (), oPoint.x, oPoint.y);
769 }
770 inherited::OnLButtonDown (nFlags, oPoint);
771}
772
773void LedItView::OnLButtonUp (UINT nFlags, CPoint oPoint)
774{
775 if (fController != NULL) {
776 fController->FireMouseUp (LEFT_BUTTON, _AfxShiftState (), oPoint.x, oPoint.y);
777 if (GetCurClickCount () == 1) {
778 fController->FireClick ();
779 }
780 }
781 inherited::OnLButtonUp (nFlags, oPoint);
782}
783
784void LedItView::OnLButtonDblClk (UINT nFlags, CPoint oPoint)
785{
786 if (fController != NULL) {
787 fController->FireDblClick ();
788 }
789 inherited::OnLButtonDblClk (nFlags, oPoint);
790}
791
792void LedItView::OnRButtonDown (UINT nFlags, CPoint oPoint)
793{
794 if (fController != NULL) {
795 fController->FireMouseDown (RIGHT_BUTTON, _AfxShiftState (), oPoint.x, oPoint.y);
796 }
797 inherited::OnRButtonDown (nFlags, oPoint);
798}
799
800void LedItView::OnRButtonUp (UINT nFlags, CPoint oPoint)
801{
802 if (fController != NULL) {
803 fController->FireMouseUp (RIGHT_BUTTON, _AfxShiftState (), oPoint.x, oPoint.y);
804 }
805 inherited::OnRButtonUp (nFlags, oPoint);
806}
807
808void LedItView::OnMouseMove (UINT nFlags, CPoint oPoint)
809{
810 if (fController != NULL) {
811 fController->FireMouseMove (LEFT_BUTTON, _AfxShiftState (), oPoint.x, oPoint.y);
812 }
813 inherited::OnMouseMove (nFlags, oPoint);
814}
815
816void LedItView::OnPasteAsTextCommand ()
817{
818 InteractiveModeUpdater iuMode (*this);
819 BreakInGroupedCommands ();
820
821 if (OnPasteCommand_Before ()) {
822 try {
823 UndoableContextHelper undoContext (*this, Led_SDK_TCHAROF ("Paste Text"), false);
824 {
825 OnPasteCommand_PasteFlavor_Specific (kTEXTClipFormat);
826 }
827 undoContext.CommandComplete ();
828 }
829 catch (...) {
830 OnPasteCommand_After ();
831 throw;
832 }
833 OnPasteCommand_After ();
834 }
835 BreakInGroupedCommands ();
836}
837
838void LedItView::OnUpdatePasteAsTextCommand (CCmdUI* pCmdUI)
839{
840 OnUpdatePasteCommand (Led_MFC_TmpCmdUpdater (pCmdUI));
841}
842
843void LedItView::OnOLEUserCommand (UINT nID)
844{
845 if (fController != NULL) {
846 fController->FireUserCommand (UserCommandNameNumberRegistry::Get ().Lookup (nID));
847 }
848}
849
850void LedItView::OnUpdateOLEUserCommand (CCmdUI* pCmdUI)
851{
852 if (fController != NULL) {
853 VARIANT_BOOL enabled = true;
854 VARIANT_BOOL checked = false;
855 wstring name;
856 // SHOULD DO BETTER TO GRAB THIS VALUE FROM THE pCMDUI GUY- BUT NOT CRITICAL...
857 fController->FireUpdateUserCommand (UserCommandNameNumberRegistry::Get ().Lookup (pCmdUI->m_nID), &enabled, &checked, &name);
858 pCmdUI->Enable (enabled);
859 pCmdUI->SetCheck (checked);
860 if (not name.empty ()) {
861 pCmdUI->SetText (String{name}.AsSDKString ().c_str ());
862 }
863 }
864}
865
866LedItView::SearchParameters LedItView::GetSearchParameters () const
867{
868 return sOptions_.Get ().fSearchParameters;
869}
870
871void LedItView::SetSearchParameters (const SearchParameters& sp)
872{
873 sOptions_.Update ([=] (Options_ d) {
874 d.fSearchParameters = sp;
875 return d;
876 });
877}
878
879void LedItView::SetSelection (size_t start, size_t end)
880{
881 bool changed = start != GetSelectionStart () or end != GetSelectionEnd ();
882 inherited::SetSelection (start, end);
883 if (changed and fController != NULL) {
884 fController->FireOLEEvent (DISPID_SelChange);
885 }
886}
887
888void LedItView::AboutToUpdateText (const UpdateInfo& updateInfo)
889{
890 if (GetMaxLength () != -1) {
891 long textAdded = static_cast<long> (updateInfo.fTextLength) - static_cast<long> (updateInfo.fReplaceTo - updateInfo.fReplaceFrom);
892 if (textAdded + static_cast<long> (GetLength ()) > GetMaxLength ()) {
893 throw "";
894 }
895 }
896
897 inherited::AboutToUpdateText (updateInfo);
898}
899
900void LedItView::EraseBackground (Tablet* tablet, const Led_Rect& subsetToDraw, bool printing)
901{
902 if (fEnableAutoChangesBackgroundColor) {
903 inherited::EraseBackground (tablet, subsetToDraw, printing);
904 }
905 else {
906 TextImager::EraseBackground (tablet, subsetToDraw, printing);
907 }
908
909#if qFunnyDisplayInDesignMode
910 if (fController->IsInDesignMode ()) {
911 Led_tString message = LED_TCHAR_OF ("Design Mode");
912 static WaterMarkHelper<> waterMarkerImager (message); // make this static - just as a performance hack. Also could be an instance variable of 'this'.
913 waterMarkerImager.SetWatermarkColor (Color::kYellow);
914 Led_Rect designModeRect = Led_Rect (0, 0, 20, 150);
915 Led_Rect wr = GetWindowRect ();
916 {
917 if (static_cast<DistanceType> (designModeRect.bottom) > wr.GetHeight ()) {
918 designModeRect.bottom = wr.GetHeight ();
919 }
920 if (static_cast<DistanceType> (designModeRect.right) > wr.GetWidth ()) {
921 designModeRect.right = wr.GetWidth ();
922 }
923 designModeRect = CenterRectInRect (designModeRect, wr);
924 DistanceType h = designModeRect.GetHeight ();
925 designModeRect.bottom = wr.bottom;
926 designModeRect.top = designModeRect.bottom - h;
927 }
928 waterMarkerImager.DrawWatermark (tablet, designModeRect, subsetToDraw);
929 if (fController->DrawExtraDesignModeBorder ()) {
930 Color useBorderColor = Color::kBlack;
931 {
932 Color defBackgrndColor = Led_GetTextBackgroundColor ();
933 if (GetHWND () != NULL) {
934 DWORD dwStyle = GetStyle ();
935 if (((dwStyle & WS_DISABLED) or (dwStyle & ES_READONLY)) and (not printing)) {
936 defBackgrndColor = Color (::GetSysColor (COLOR_BTNFACE));
937 }
938 }
939 // opposite of background color
940 useBorderColor = Color (~defBackgrndColor.GetRed (), ~defBackgrndColor.GetGreen (), ~defBackgrndColor.GetBlue ());
941 }
942
943 Led_Rect wmr = tablet->CvtFromTWIPS (GetDefaultWindowMargins ());
944 Led_Rect cr = wr;
945 cr.top -= wmr.GetTop ();
946 cr.left -= wmr.GetLeft ();
947 cr.bottom += wmr.GetBottom ();
948 cr.right += wmr.GetRight ();
949 tablet->FrameRectangle (cr, useBorderColor, 1);
950 }
951 }
952#endif
953}
954
955long LedItView::OLE_FindReplace (long searchFrom, const Led_tString& findText, const Led_tString& replaceText, BOOL wrapSearch,
956 BOOL wholeWordSearch, BOOL caseSensativeSearch)
957{
958 TextStore::SearchParameters parameters;
959 parameters.fMatchString = findText;
960 parameters.fWrapSearch = !!wrapSearch;
961 parameters.fWholeWordSearch = !!wholeWordSearch;
962 parameters.fCaseSensativeSearch = !!caseSensativeSearch;
963
964 size_t whereTo = GetTextStore ().Find (parameters, searchFrom);
965 if (whereTo != kBadIndex) {
966 size_t replaceStart = whereTo;
967 size_t replaceEnd = whereTo + parameters.fMatchString.length ();
968 TextInteractor::UndoableContextHelper undoContext (*this, TextInteractor::GetCommandNames ().fReplaceCommandName, replaceStart,
969 replaceEnd, GetSelectionStart (), GetSelectionEnd (), false);
970 {
971 InteractiveReplace_ (undoContext.GetUndoRegionStart (), undoContext.GetUndoRegionEnd (), replaceText.c_str (), replaceText.length ());
972 }
973 undoContext.CommandComplete ();
974 return static_cast<long> (whereTo + replaceText.length ());
975 }
976
977 return -1;
978}
979
980void LedItView::UpdateScrollBars ()
981{
982 if (fInDrawMetaFileMode) {
983 return; // ignore while in print mode...
984 }
985 inherited::UpdateScrollBars ();
986}
987
988void LedItView::OnBrowseHelpCommand ()
989{
990 if (fController != NULL) {
991 fController->OnBrowseHelpCommand ();
992 }
993}
994
995void LedItView::OnCheckForUpdatesWebPageCommand ()
996{
997 Led_URLManager::Get ().Open (MakeSophistsAppNameVersionURL ("/Led/CheckForUpdates.asp", kAppName, ""));
998}
999
1000void LedItView::OnAboutBoxCommand ()
1001{
1002 if (fController != NULL) {
1003 fController->OnAboutBoxCommand ();
1004 }
1005}
1006
1007void LedItView::OnFilePrintOnce ()
1008{
1009 DoPrintHelper (false);
1010}
1011
1012void LedItView::OnFilePrint ()
1013{
1014 DoPrintHelper (true);
1015}
1016
1017void LedItView::OnFilePrintSetup ()
1018{
1019 CPrintDialog pd (TRUE);
1020 AfxGetApp ()->DoPrintDialog (&pd);
1021}
1022
1023/*
1024 * Based on CView::OnFilePrint() - but with one bug fixed (at least originally). That code was buggy when used in an OCX cuz there
1025 * is no doc and no frame window (perhaps I could have created one - but I wasn't sure what other bugs/problems that might create).
1026 *
1027 * Then - when I tried to compile that code here - there were all sorts of things that wouldn't compile. So I had to make a bunch of
1028 * OTHER changes due to the fact that I don't include all the private MFC headers here. And as long as I was making such bug changes - I threw away
1029 * a bunch of detritus as well.
1030 *
1031 * - LGP 2001-04-17
1032 */
1033void LedItView::DoPrintHelper (bool showPrintDlg)
1034{
1035 class CPrintingDialog : public CDialog {
1036 public:
1037 enum {
1038 IDD = AFX_IDD_PRINTDLG
1039 };
1040 CPrintingDialog (CWnd* pParent)
1041 {
1042 Create (CPrintingDialog::IDD, pParent); // modeless !
1043 _afxWinState->m_bUserAbort = FALSE;
1044 }
1045 virtual ~CPrintingDialog ()
1046 {
1047 }
1048 virtual BOOL OnInitDialog ()
1049 {
1050 SetWindowText (AfxGetAppName ());
1051 CenterWindow ();
1052 return CDialog::OnInitDialog ();
1053 }
1054 virtual void OnCancel ()
1055 {
1056 _afxWinState->m_bUserAbort = TRUE; // flag that user aborted print
1057 CDialog::OnCancel ();
1058 }
1059 };
1060
1061 // get default print info
1062 CPrintInfo printInfo;
1063 ASSERT (printInfo.m_pPD != NULL); // must be set
1064
1065 if (not showPrintDlg) {
1066 printInfo.m_bDirect = true;
1067 printInfo.m_dwFlags &= ~PRINTFLAG_PROMPTUSER;
1068 }
1069
1070 if (OnPreparePrinting (&printInfo)) {
1071 // hDC must be set (did you remember to call DoPreparePrinting?)
1072 ASSERT (printInfo.m_pPD->m_pd.hDC != NULL);
1073
1074 // gather file to print to if print-to-file selected
1075 CString strOutput;
1076 if (printInfo.m_pPD->m_pd.Flags & PD_PRINTTOFILE && !printInfo.m_bDocObject) {
1077 // construct CFileDialog for browsing
1078 CString strDef (MAKEINTRESOURCE (AFX_IDS_PRINTDEFAULTEXT));
1079 CString strPrintDef (MAKEINTRESOURCE (AFX_IDS_PRINTDEFAULT));
1080 CString strFilter (MAKEINTRESOURCE (AFX_IDS_PRINTFILTER));
1081 CString strCaption (MAKEINTRESOURCE (AFX_IDS_PRINTCAPTION));
1082 CFileDialog dlg (FALSE, strDef, strPrintDef, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, strFilter);
1083 dlg.m_ofn.lpstrTitle = strCaption;
1084
1085 if (dlg.DoModal () != IDOK)
1086 return;
1087
1088 // set output device to resulting path name
1089 strOutput = dlg.GetPathName ();
1090 }
1091
1092 // set up document info and start the document printing process
1093 CString strTitle = "ActiveLedIt! document";
1094 DOCINFO docInfo;
1095 memset (&docInfo, 0, sizeof (DOCINFO));
1096 docInfo.cbSize = sizeof (DOCINFO);
1097 docInfo.lpszDocName = strTitle;
1098 CString strPortName;
1099 int nFormatID;
1100 if (strOutput.IsEmpty ()) {
1101 docInfo.lpszOutput = NULL;
1102 strPortName = printInfo.m_pPD->GetPortName ();
1103 nFormatID = AFX_IDS_PRINTONPORT;
1104 }
1105 else {
1106 docInfo.lpszOutput = strOutput;
1107 extern UINT AFXAPI AfxGetFileTitle (LPCTSTR lpszPathName, LPTSTR lpszTitle, UINT nMax);
1108 AfxGetFileTitle (strOutput, strPortName.GetBuffer (_MAX_PATH), _MAX_PATH);
1109 nFormatID = AFX_IDS_PRINTTOFILE;
1110 }
1111
1112 // setup the printing DC
1113 CDC dcPrint;
1114 if (!printInfo.m_bDocObject) {
1115 dcPrint.Attach (printInfo.m_pPD->m_pd.hDC); // attach printer dc
1116 dcPrint.m_bPrinting = TRUE;
1117 }
1118 OnBeginPrinting (&dcPrint, &printInfo);
1119
1120 if (!printInfo.m_bDocObject) {
1121 dcPrint.SetAbortProc (_AfxAbortProc);
1122 }
1123
1124 // disable main window while printing & init printing status dialog
1125 HWND mainWnd = AfxGetMainWnd ()->m_hWnd;
1126 ::EnableWindow (mainWnd, FALSE);
1127 CPrintingDialog dlgPrintStatus (this);
1128 BOOL bError = FALSE;
1129 try {
1130 CString strTemp;
1131 dlgPrintStatus.SetDlgItemText (AFX_IDC_PRINT_DOCNAME, strTitle);
1132 dlgPrintStatus.SetDlgItemText (AFX_IDC_PRINT_PRINTERNAME, printInfo.m_pPD->GetDeviceName ());
1133 AfxFormatString1 (strTemp, nFormatID, strPortName);
1134 dlgPrintStatus.SetDlgItemText (AFX_IDC_PRINT_PORTNAME, strTemp);
1135 dlgPrintStatus.ShowWindow (SW_SHOW);
1136 dlgPrintStatus.UpdateWindow ();
1137
1138 // start document printing process
1139 if (!printInfo.m_bDocObject && dcPrint.StartDoc (&docInfo) == SP_ERROR) {
1140 // enable main window before proceeding
1141 ::EnableWindow (mainWnd, true);
1142
1143 // cleanup and show error message
1144 OnEndPrinting (&dcPrint, &printInfo);
1145 dlgPrintStatus.DestroyWindow ();
1146 dcPrint.Detach (); // will be cleaned up by CPrintInfo destructor
1147 AfxMessageBox (AFX_IDP_FAILED_TO_START_PRINT);
1148 return;
1149 }
1150
1151 // Guarantee values are in the valid range
1152 UINT nEndPage = printInfo.GetToPage ();
1153 UINT nStartPage = printInfo.GetFromPage ();
1154
1155 if (nEndPage < printInfo.GetMinPage ())
1156 nEndPage = printInfo.GetMinPage ();
1157 if (nEndPage > printInfo.GetMaxPage ())
1158 nEndPage = printInfo.GetMaxPage ();
1159
1160 if (nStartPage < printInfo.GetMinPage ())
1161 nStartPage = printInfo.GetMinPage ();
1162 if (nStartPage > printInfo.GetMaxPage ())
1163 nStartPage = printInfo.GetMaxPage ();
1164
1165 int nStep = (nEndPage >= nStartPage) ? 1 : -1;
1166 nEndPage = (nEndPage == 0xffff) ? 0xffff : nEndPage + nStep;
1167
1168 VERIFY (strTemp.LoadString (AFX_IDS_PRINTPAGENUM));
1169
1170 // If it's a doc object, we don't loop page-by-page
1171 // because doc objects don't support that kind of levity.
1172
1173 if (printInfo.m_bDocObject) {
1174 OnPrepareDC (&dcPrint, &printInfo);
1175 OnPrint (&dcPrint, &printInfo);
1176 }
1177 else {
1178 // begin page printing loop
1179 for (printInfo.m_nCurPage = nStartPage; printInfo.m_nCurPage != nEndPage; printInfo.m_nCurPage += nStep) {
1180 OnPrepareDC (&dcPrint, &printInfo);
1181
1182 // check for end of print
1183 if (!printInfo.m_bContinuePrinting)
1184 break;
1185
1186 // write current page
1187 TCHAR szBuf[80];
1188 wsprintf (szBuf, strTemp, printInfo.m_nCurPage);
1189 dlgPrintStatus.SetDlgItemText (AFX_IDC_PRINT_PAGENUM, szBuf);
1190
1191 // set up drawing rect to entire page (in logical coordinates)
1192 printInfo.m_rectDraw.SetRect (0, 0, dcPrint.GetDeviceCaps (HORZRES), dcPrint.GetDeviceCaps (VERTRES));
1193 dcPrint.DPtoLP (&printInfo.m_rectDraw);
1194
1195 // attempt to start the current page
1196 if (dcPrint.StartPage () < 0) {
1197 bError = TRUE;
1198 break;
1199 }
1200
1201 // must call OnPrepareDC on newer versions of Windows because
1202 // StartPage now resets the device attributes.
1203 BOOL bMarked4 = false;
1204 {
1205 DISABLE_COMPILER_MSC_WARNING_START (4996)
1206 DWORD dwVersion = ::GetVersion ();
1207 BOOL bWin4 = (BYTE)dwVersion >= 4;
1208 // determine various metrics based on EXE subsystem version mark
1209 if (bWin4) {
1210 bMarked4 = (GetProcessVersion (0) >= 0x00040000);
1211 }
1212 DISABLE_COMPILER_MSC_WARNING_END (4996)
1213 }
1214 if (bMarked4)
1215 OnPrepareDC (&dcPrint, &printInfo);
1216
1217 ASSERT (printInfo.m_bContinuePrinting);
1218
1219 // page successfully started, so now render the page
1220 OnPrint (&dcPrint, &printInfo);
1221 if (dcPrint.EndPage () < 0 || !_AfxAbortProc (dcPrint.m_hDC, 0)) {
1222 bError = TRUE;
1223 break;
1224 }
1225 }
1226 }
1227 }
1228 catch (...) {
1229 // cleanup document printing process
1230 if (!printInfo.m_bDocObject) {
1231 dcPrint.AbortDoc ();
1232 }
1233
1234 ::EnableWindow (mainWnd, true);
1235
1236 OnEndPrinting (&dcPrint, &printInfo); // clean up after printing
1237 throw;
1238 }
1239
1240 // cleanup document printing process
1241 if (!printInfo.m_bDocObject) {
1242 if (!bError)
1243 dcPrint.EndDoc ();
1244 else
1245 dcPrint.AbortDoc ();
1246 }
1247
1248 ::EnableWindow (mainWnd, true);
1249
1250 OnEndPrinting (&dcPrint, &printInfo); // clean up after printing
1251 dlgPrintStatus.DestroyWindow ();
1252
1253 dcPrint.Detach (); // will be cleaned up by CPrintInfo destructor
1254 }
1255}
1256
1257#ifdef _DEBUG
1258void LedItView::AssertValid () const
1259{
1260 inherited::AssertValid ();
1261}
1262
1263void LedItView::Dump (CDumpContext& dc) const
1264{
1265 inherited::Dump (dc);
1266}
1267#endif //_DEBUG
#define AssertNotNull(p)
Definition Assertions.h:334
#define RequireNotNull(p)
Definition Assertions.h:348
#define Verify(c)
Definition Assertions.h:420
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
nonvirtual SDKString AsSDKString() const
Definition String.inl:806
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
ObjectVariantMapper can be used to map C++ types to and from variant-union types, which can be transp...
static const ModuleDataUpgraderType kDefaultUpgrader
Simple variant-value (case variant union) object, with (variant) basic types analogous to a value in ...
Helper to define synchronized, lazy constructed, module initialization (intended to work with DataExc...