Stroika Library 3.0d18
 
Loading...
Searching...
No Matches
ActiveLedIt/Sources/LedItView.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. 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"
14
15#include "Stroika/Frameworks/Led/ChunkedArrayTextStore.h"
16#include "Stroika/Frameworks/Led/StdDialogs.h"
17
18#include "DispIDs.h"
19#include "FontMenu.h"
20#include "Resource.h"
21#include "UserConfigCommands.h"
22
23#include "LedItView.h"
24
25#if qFunnyDisplayInDesignMode
26#include "Stroika/Frameworks/Led/HandySimple.h"
27#endif
28
29using namespace Stroika::Foundation;
31using namespace Stroika::Foundation::Execution;
32
33using SearchParameters = LedItView::SearchParameters;
34
35namespace {
36 struct Options_ {
37 SearchParameters fSearchParameters{};
38 };
39
40 struct Options_Storage_IMPL_ {
41 Options_Storage_IMPL_ ()
42 : fOptionsFile_{L"AppSettings"sv,
43 [] () -> ObjectVariantMapper {
45
46 // really should use String, no longer Led_tString, but for now... (note this only works as is for wchar_t Led_tString
47 mapper.Add<Led_tString> ([] (const ObjectVariantMapper& /*mapper*/,
48 const Led_tString* obj) -> VariantValue { return String{*obj}; },
49 [] (const ObjectVariantMapper& /*mapper*/, const VariantValue& d,
50 Led_tString* intoObj) -> void { *intoObj = d.As<String> ().As<Led_tString> (); });
51 mapper.AddCommonType<vector<Led_tString>> ();
52
53 mapper.AddClass<SearchParameters> ({
54 {"MatchString"sv, &SearchParameters::fMatchString},
55 {"WrapSearch"sv, &SearchParameters::fWrapSearch},
56 {"WholeWordSearch"sv, &SearchParameters::fWholeWordSearch},
57 {"CaseSensativeSearch"sv, &SearchParameters::fCaseSensativeSearch},
58 {"RecentMatchStrings"sv, &SearchParameters::fRecentFindStrings},
59 });
60
61 mapper.AddClass<Options_> ({
62 {"Search-Parameters"sv, &Options_::fSearchParameters},
63 });
64 return mapper;
65 }(),
66
68
69 // override the default name mapper to assure folder created, since no installer for activex controls
70 [] (const String& moduleName, const String& fileSuffix) {
71 static const auto kDefaultMapper_ = OptionsFile::mkFilenameMapper (L"ActiveLedIt"sv);
72 filesystem::path fileName = kDefaultMapper_ (moduleName, fileSuffix);
73 filesystem::create_directories (fileName.parent_path ());
74 return fileName;
75 }}
76 , fActualCurrentConfigData_{fOptionsFile_.Read<Options_> (Options_{})}
77 {
78 Set (fActualCurrentConfigData_); // assure derived data (and changed fields etc) up to date
79 }
80 Options_ Get () const
81 {
82 return fActualCurrentConfigData_;
83 }
84 void Set (const Options_& v)
85 {
86 fActualCurrentConfigData_ = v;
87 fOptionsFile_.Write (v);
88 }
89
90 private:
91 OptionsFile fOptionsFile_;
92 Options_ fActualCurrentConfigData_;
93 };
94
96}
97
98class My_CMDNUM_MAPPING : public MFC_CommandNumberMapping {
99public:
100 My_CMDNUM_MAPPING ()
101 {
102 AddAssociation (kFindAgainCmd, LedItView::kFindAgain_CmdID);
103 AddAssociation (kEnterFindStringCmd, LedItView::kEnterFindString_CmdID);
104 AddAssociation (kReplaceCmd, LedItView::kReplace_CmdID);
105 AddAssociation (kReplaceAgainCmd, LedItView::kReplaceAgain_CmdID);
106 AddAssociation (kSpellCheckCmd, LedItView::kSpellCheck_CmdID);
107
108 AddAssociation (kSelectWordCmd, LedItView::kSelectWord_CmdID);
109 AddAssociation (kSelectTextRowCmd, LedItView::kSelectTextRow_CmdID);
110 AddAssociation (kSelectParagraphCmd, LedItView::kSelectParagraph_CmdID);
111 AddAssociation (kSelectTableIntraCellAllCmd, LedItView::kSelectTableIntraCellAll_CmdID);
112 AddAssociation (kSelectTableCellCmd, LedItView::kSelectTableCell_CmdID);
113 AddAssociation (kSelectTableRowCmd, LedItView::kSelectTableRow_CmdID);
114 AddAssociation (kSelectTableColumnCmd, LedItView::kSelectTableColumn_CmdID);
115 AddAssociation (kSelectTableCmd, LedItView::kSelectTable_CmdID);
116
117 AddAssociation (kFontSize9Cmd, LedItView::kFontSize9_CmdID);
118 AddAssociation (kFontSize10Cmd, LedItView::kFontSize10_CmdID);
119 AddAssociation (kFontSize12Cmd, LedItView::kFontSize12_CmdID);
120 AddAssociation (kFontSize14Cmd, LedItView::kFontSize14_CmdID);
121 AddAssociation (kFontSize18Cmd, LedItView::kFontSize18_CmdID);
122 AddAssociation (kFontSize24Cmd, LedItView::kFontSize24_CmdID);
123 AddAssociation (kFontSize36Cmd, LedItView::kFontSize36_CmdID);
124 AddAssociation (kFontSize48Cmd, LedItView::kFontSize48_CmdID);
125 AddAssociation (kFontSize72Cmd, LedItView::kFontSize72_CmdID);
126#if qSupportOtherFontSizeDlg
127 AddAssociation (kFontSizeOtherCmd, LedItView::kFontSizeOther_CmdID);
128#endif
129 AddAssociation (kFontSizeSmallerCmd, LedItView::kFontSizeSmaller_CmdID);
130 AddAssociation (kFontSizeLargerCmd, LedItView::kFontSizeLarger_CmdID);
131
132 AddAssociation (kBlackColorCmd, LedItView::kFontColorBlack_CmdID);
133 AddAssociation (kMaroonColorCmd, LedItView::kFontColorMaroon_CmdID);
134 AddAssociation (kGreenColorCmd, LedItView::kFontColorGreen_CmdID);
135 AddAssociation (kOliveColorCmd, LedItView::kFontColorOlive_CmdID);
136 AddAssociation (kNavyColorCmd, LedItView::kFontColorNavy_CmdID);
137 AddAssociation (kPurpleColorCmd, LedItView::kFontColorPurple_CmdID);
138 AddAssociation (kTealColorCmd, LedItView::kFontColorTeal_CmdID);
139 AddAssociation (kGrayColorCmd, LedItView::kFontColorGray_CmdID);
140 AddAssociation (kSilverColorCmd, LedItView::kFontColorSilver_CmdID);
141 AddAssociation (kRedColorCmd, LedItView::kFontColorRed_CmdID);
142 AddAssociation (kLimeColorCmd, LedItView::kFontColorLime_CmdID);
143 AddAssociation (kYellowColorCmd, LedItView::kFontColorYellow_CmdID);
144 AddAssociation (kBlueColorCmd, LedItView::kFontColorBlue_CmdID);
145 AddAssociation (kFuchsiaColorCmd, LedItView::kFontColorFuchsia_CmdID);
146 AddAssociation (kAquaColorCmd, LedItView::kFontColorAqua_CmdID);
147 AddAssociation (kWhiteColorCmd, LedItView::kFontColorWhite_CmdID);
148 AddAssociation (kFontColorOtherCmd, LedItView::kFontColorOther_CmdID);
149
150 AddAssociation (kJustifyLeftCmd, LedItView::kJustifyLeft_CmdID);
151 AddAssociation (kJustifyCenterCmd, LedItView::kJustifyCenter_CmdID);
152 AddAssociation (kJustifyRightCmd, LedItView::kJustifyRight_CmdID);
153 AddAssociation (kJustifyFullCmd, LedItView::kJustifyFull_CmdID);
154
155#if qSupportParagraphSpacingDlg
156 AddAssociation (kParagraphSpacingCmd, LedItView::kParagraphSpacingCommand_CmdID);
157#endif
158#if qSupportParagraphIndentsDlg
159 AddAssociation (kParagraphIndentsCmd, LedItView::kParagraphIndentsCommand_CmdID);
160#endif
161
162 AddAssociation (kListStyle_NoneCmd, LedItView::kListStyle_None_CmdID);
163 AddAssociation (kListStyle_BulletCmd, LedItView::kListStyle_Bullet_CmdID);
164
165 AddAssociation (kIncreaseIndentCmd, LedItView::kIncreaseIndent_CmdID);
166 AddAssociation (kDecreaseIndentCmd, LedItView::kDecreaseIndent_CmdID);
167
168 AddRangeAssociation (kBaseFontNameCmd, kLastFontNameCmd, LedItView::kFontMenuFirst_CmdID, LedItView::kFontMenuLast_CmdID);
169
170 AddAssociation (kFontStylePlainCmd, LedItView::kFontStylePlain_CmdID);
171 AddAssociation (kFontStyleBoldCmd, LedItView::kFontStyleBold_CmdID);
172 AddAssociation (kFontStyleItalicCmd, LedItView::kFontStyleItalic_CmdID);
173 AddAssociation (kFontStyleUnderlineCmd, LedItView::kFontStyleUnderline_CmdID);
174 AddAssociation (kFontStyleStrikeoutCmd, LedItView::kFontStyleStrikeout_CmdID);
175 AddAssociation (kSubScriptCmd, LedItView::kSubScriptCommand_CmdID);
176 AddAssociation (kSuperScriptCmd, LedItView::kSuperScriptCommand_CmdID);
177 AddAssociation (kChooseFontDialogCmd, LedItView::kChooseFontCommand_CmdID);
178
179 AddAssociation (kInsertTableCmd, LedItView::kInsertTable_CmdID);
180 AddAssociation (kInsertTableRowAboveCmd, LedItView::kInsertTableRowAbove_CmdID);
181 AddAssociation (kInsertTableRowBelowCmd, LedItView::kInsertTableRowBelow_CmdID);
182 AddAssociation (kInsertTableColBeforeCmd, LedItView::kInsertTableColBefore_CmdID);
183 AddAssociation (kInsertTableColAfterCmd, LedItView::kInsertTableColAfter_CmdID);
184 AddAssociation (kInsertURLCmd, LedItView::kInsertURL_CmdID);
185 AddAssociation (kInsertSymbolCmd, LedItView::kInsertSymbol_CmdID);
186
187 // AddAssociation (kPropertiesForSelectionCmd, LedItView::kSelectedEmbeddingProperties_CmdID);
188 AddRangeAssociation (kFirstSelectedEmbeddingCmd, kLastSelectedEmbeddingCmd, LedItView::kFirstSelectedEmbedding_CmdID,
189 LedItView::kLastSelectedEmbedding_CmdID);
190
191// 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)
192#if 0
193 AddAssociation (kHideSelectionCmd, LedItView::kHideSelection_CmdID);
194 AddAssociation (kUnHideSelectionCmd, LedItView::kUnHideSelection_CmdID);
195#endif
196 AddAssociation (kRemoveTableRowsCmd, LedItView::kRemoveTableRows_CmdID);
197 AddAssociation (kRemoveTableColumnsCmd, LedItView::kRemoveTableColumns_CmdID);
198
199// 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)
200#if 0
201 AddAssociation (kShowHideParagraphGlyphsCmd, LedItView::kShowHideParagraphGlyphs_CmdID);
202 AddAssociation (kShowHideTabGlyphsCmd, LedItView::kShowHideTabGlyphs_CmdID);
203 AddAssociation (kShowHideSpaceGlyphsCmd, LedItView::kShowHideSpaceGlyphs_CmdID);
204#endif
205 }
206};
207My_CMDNUM_MAPPING sMy_CMDNUM_MAPPING;
208
209struct ActiveLedIt_DialogSupport : TextInteractor::DialogSupport, WordProcessor::DialogSupport {
210public:
211 using CommandNumber = TextInteractor::DialogSupport::CommandNumber;
212
213public:
214 ActiveLedIt_DialogSupport ()
215 {
216 TextInteractor::SetDialogSupport (this);
217 WordProcessor::SetDialogSupport (this);
218 }
219 ~ActiveLedIt_DialogSupport ()
220 {
221 WordProcessor::SetDialogSupport (NULL);
222 TextInteractor::SetDialogSupport (NULL);
223 }
224
225// TextInteractor::DialogSupport
226#if qSupportStdFindDlg
227public:
228 virtual void DisplayFindDialog (Led_tString* findText, const vector<Led_tString>& recentFindSuggestions, bool* wrapSearch,
229 bool* wholeWordSearch, bool* caseSensative, bool* pressedOK) override
230 {
231 Led_StdDialogHelper_FindDialog findDialog (::AfxGetResourceHandle (), ::GetActiveWindow ());
232
233 findDialog.fFindText = *findText;
234 findDialog.fRecentFindTextStrings = recentFindSuggestions;
235 findDialog.fWrapSearch = *wrapSearch;
236 findDialog.fWholeWordSearch = *wholeWordSearch;
237 findDialog.fCaseSensativeSearch = *caseSensative;
238
239 findDialog.DoModal ();
240
241 *findText = findDialog.fFindText;
242 *wrapSearch = findDialog.fWrapSearch;
243 *wholeWordSearch = findDialog.fWholeWordSearch;
244 *caseSensative = findDialog.fCaseSensativeSearch;
245 *pressedOK = findDialog.fPressedOK;
246 }
247#endif
248#if qSupportStdReplaceDlg
249public:
250 virtual ReplaceButtonPressed DisplayReplaceDialog (Led_tString* findText, const vector<Led_tString>& recentFindSuggestions,
251 Led_tString* replaceText, bool* wrapSearch, bool* wholeWordSearch, bool* caseSensative) override
252 {
253 Led_StdDialogHelper_ReplaceDialog replaceDialog (::AfxGetResourceHandle (), ::GetActiveWindow ());
254
255 replaceDialog.fFindText = *findText;
256 replaceDialog.fRecentFindTextStrings = recentFindSuggestions;
257 replaceDialog.fReplaceText = *replaceText;
258 replaceDialog.fWrapSearch = *wrapSearch;
259 replaceDialog.fWholeWordSearch = *wholeWordSearch;
260 replaceDialog.fCaseSensativeSearch = *caseSensative;
261
262 replaceDialog.DoModal ();
263
264 *findText = replaceDialog.fFindText;
265 *replaceText = replaceDialog.fReplaceText;
266 *wrapSearch = replaceDialog.fWrapSearch;
267 *wholeWordSearch = replaceDialog.fWholeWordSearch;
268 *caseSensative = replaceDialog.fCaseSensativeSearch;
269
270 switch (replaceDialog.fPressed) {
271 case Led_StdDialogHelper_ReplaceDialog::eCancel:
272 return eReplaceButton_Cancel;
273 case Led_StdDialogHelper_ReplaceDialog::eFind:
274 return eReplaceButton_Find;
275 case Led_StdDialogHelper_ReplaceDialog::eReplace:
276 return eReplaceButton_Replace;
277 case Led_StdDialogHelper_ReplaceDialog::eReplaceAll:
278 return eReplaceButton_ReplaceAll;
279 case Led_StdDialogHelper_ReplaceDialog::eReplaceAllInSelection:
280 return eReplaceButton_ReplaceAllInSelection;
281 }
282 Assert (false);
283 return eReplaceButton_Cancel;
284 }
285#endif
286#if qSupportStdSpellCheckDlg
287public:
288 virtual void DisplaySpellCheckDialog (SpellCheckDialogCallback& callback) override
289 {
290 Led_StdDialogHelper_SpellCheckDialog::CallbackDelegator<SpellCheckDialogCallback> delegator{callback};
291#if qStroika_Foundation_Common_Platform_MacOS
292 Led_StdDialogHelper_SpellCheckDialog spellCheckDialog (delegator);
293#elif qStroika_Foundation_Common_Platform_Windows
294 Led_StdDialogHelper_SpellCheckDialog spellCheckDialog (delegator, ::AfxGetResourceHandle (), ::GetActiveWindow ());
295#elif qStroika_FeatureSupported_XWindows
296 Led_StdDialogHelper_SpellCheckDialog spellCheckDialog (delegator, GTK_WINDOW (LedItApplication::Get ().GetAppWindow ()));
297#endif
298
299 spellCheckDialog.DoModal ();
300 }
301#endif
302
303 // WordProcessor::DialogSupport
304public:
305 virtual FontNameSpecifier CmdNumToFontName (CommandNumber cmdNum) override
306 {
307 Require (cmdNum >= WordProcessor::kFontMenuFirst_CmdID);
308 Require (cmdNum <= WordProcessor::kFontMenuLast_CmdID);
309 return ::CmdNumToFontName (MFC_CommandNumberMapping::Get ().ReverseLookup (cmdNum)).c_str ();
310 }
311#if qSupportOtherFontSizeDlg
312 virtual DistanceType PickOtherFontHeight (DistanceType origHeight) override
313 {
314#if qStroika_Foundation_Common_Platform_MacOS
315 Led_StdDialogHelper_OtherFontSizeDialog dlg;
316#elif qStroika_Foundation_Common_Platform_Windows
317 Led_StdDialogHelper_OtherFontSizeDialog dlg (::AfxGetResourceHandle (), ::GetActiveWindow ());
318#endif
319 dlg.InitValues (origHeight);
320 if (dlg.DoModal ()) {
321 return dlg.fFontSize_Result;
322 }
323 else {
324 return 0;
325 }
326 }
327#endif
328#if qSupportParagraphSpacingDlg
329 virtual bool PickNewParagraphLineSpacing (TWIPS* spaceBefore, bool* spaceBeforeValid, TWIPS* spaceAfter, bool* spaceAfterValid,
330 LineSpacing* lineSpacing, bool* lineSpacingValid) override
331 {
332#if qStroika_Foundation_Common_Platform_MacOS
333 Led_StdDialogHelper_ParagraphSpacingDialog dlg;
334#elif qStroika_Foundation_Common_Platform_Windows
335 Led_StdDialogHelper_ParagraphSpacingDialog dlg (::AfxGetResourceHandle (), ::GetActiveWindow ());
336#endif
337 dlg.InitValues (*spaceBefore, *spaceBeforeValid, *spaceAfter, *spaceAfterValid, *lineSpacing, *lineSpacingValid);
338
339 if (dlg.DoModal ()) {
340 *spaceBeforeValid = dlg.fSpaceBefore_Valid;
341 if (*spaceBeforeValid) {
342 *spaceBefore = dlg.fSpaceBefore_Result;
343 }
344 *spaceAfterValid = dlg.fSpaceAfter_Valid;
345 if (*spaceAfterValid) {
346 *spaceAfter = dlg.fSpaceAfter_Result;
347 }
348 *lineSpacingValid = dlg.fLineSpacing_Valid;
349 if (*lineSpacingValid) {
350 *lineSpacing = dlg.fLineSpacing_Result;
351 }
352 return true;
353 }
354 else {
355 return false;
356 }
357 }
358#endif
359#if qSupportParagraphIndentsDlg
360 virtual bool PickNewParagraphMarginsAndFirstIndent (TWIPS* leftMargin, bool* leftMarginValid, TWIPS* rightMargin,
361 bool* rightMarginValid, TWIPS* firstIndent, bool* firstIndentValid) override
362 {
363#if qStroika_Foundation_Common_Platform_MacOS
364 Led_StdDialogHelper_ParagraphIndentsDialog dlg;
365#elif qStroika_Foundation_Common_Platform_Windows
366 Led_StdDialogHelper_ParagraphIndentsDialog dlg (::AfxGetResourceHandle (), ::GetActiveWindow ());
367#endif
368 dlg.InitValues (*leftMargin, *leftMarginValid, *rightMargin, *rightMarginValid, *firstIndent, *firstIndentValid);
369 if (dlg.DoModal ()) {
370 *leftMarginValid = dlg.fLeftMargin_Valid;
371 if (*leftMarginValid) {
372 *leftMargin = dlg.fLeftMargin_Result;
373 }
374 *rightMarginValid = dlg.fRightMargin_Valid;
375 if (*rightMarginValid) {
376 *rightMargin = dlg.fRightMargin_Result;
377 }
378 *firstIndentValid = dlg.fFirstIndent_Valid;
379 if (*firstIndentValid) {
380 *firstIndent = dlg.fFirstIndent_Result;
381 }
382 return true;
383 }
384 else {
385 return false;
386 }
387 }
388#endif
389 virtual void ShowSimpleEmbeddingInfoDialog (const SDKString& embeddingTypeName) override
390 {
391 // unknown embedding...
392 Led_StdDialogHelper_UnknownEmbeddingInfoDialog infoDialog (::AfxGetResourceHandle (), ::GetActiveWindow ());
393 infoDialog.fEmbeddingTypeName = embeddingTypeName;
394 (void)infoDialog.DoModal ();
395 }
396 virtual bool ShowURLEmbeddingInfoDialog (const SDKString& embeddingTypeName, SDKString* urlTitle, SDKString* urlValue) override
397 {
398 Led_StdDialogHelper_URLXEmbeddingInfoDialog infoDialog (::AfxGetResourceHandle (), ::GetActiveWindow ());
399 infoDialog.fEmbeddingTypeName = embeddingTypeName;
400 infoDialog.fTitleText = *urlTitle;
401 infoDialog.fURLText = *urlValue;
402 if (infoDialog.DoModal ()) {
403 *urlTitle = infoDialog.fTitleText;
404 *urlValue = infoDialog.fURLText;
405 return true;
406 }
407 else {
408 return false;
409 }
410 }
411 virtual bool ShowAddURLEmbeddingInfoDialog (SDKString* urlTitle, SDKString* urlValue) override
412 {
413 Led_StdDialogHelper_AddURLXEmbeddingInfoDialog infoDialog (::AfxGetResourceHandle (), ::GetActiveWindow ());
414 infoDialog.fTitleText = *urlTitle;
415 infoDialog.fURLText = *urlValue;
416 if (infoDialog.DoModal ()) {
417 *urlTitle = infoDialog.fTitleText;
418 *urlValue = infoDialog.fURLText;
419 return true;
420 }
421 else {
422 return false;
423 }
424 }
425#if qSupportAddNewTableDlg
426 bool AddNewTableDialog (size_t* nRows, size_t* nCols)
427 {
428 RequireNotNull (nRows);
429 RequireNotNull (nCols);
430 Led_StdDialogHelper_AddNewTableDialog infoDialog (::AfxGetResourceHandle (), ::GetActiveWindow ());
431 infoDialog.fRows = *nRows;
432 infoDialog.fColumns = *nCols;
433 if (infoDialog.DoModal ()) {
434 *nRows = infoDialog.fRows;
435 *nCols = infoDialog.fColumns;
436 return true;
437 }
438 else {
439 return false;
440 }
441 }
442#endif
443#if qSupportEditTablePropertiesDlg
444 virtual bool EditTablePropertiesDialog (TableSelectionPropertiesInfo* tableProperties) override
445 {
446 RequireNotNull (tableProperties);
447
448 using DLGTYPE = Led_StdDialogHelper_EditTablePropertiesDialog;
449#if qStroika_Foundation_Common_Platform_MacOS
450 DLGTYPE infoDialog;
451#elif qStroika_Foundation_Common_Platform_Windows
452 DLGTYPE infoDialog (::AfxGetResourceHandle (), ::GetActiveWindow ());
453#endif
454 DLGTYPE::cvt<DLGTYPE::Info, TableSelectionPropertiesInfo> (&infoDialog.fInfo, *tableProperties);
455 if (infoDialog.DoModal ()) {
456 DLGTYPE::cvt<TableSelectionPropertiesInfo, DLGTYPE::Info> (tableProperties, infoDialog.fInfo);
457 return true;
458 }
459 else {
460 return false;
461 }
462 }
463#endif
464};
465static ActiveLedIt_DialogSupport sActiveLedIt_DialogSupport;
466
467static BOOL CALLBACK _AfxAbortProc (HDC, int)
468{
469 _AFX_WIN_STATE* pWinState = _afxWinState;
470 MSG msg;
471 while (!pWinState->m_bUserAbort && ::PeekMessage (&msg, NULL, NULL, NULL, PM_NOREMOVE)) {
472 if (!AfxGetThread ()->PumpMessage ())
473 return FALSE; // terminate if WM_QUIT received
474 }
475 return !pWinState->m_bUserAbort;
476}
477
478/*
479 ********************************************************************************
480 ************************** LedItViewController *********************************
481 ********************************************************************************
482 */
483LedItViewController::LedItViewController ()
484 : fTextStore ()
485 , fCommandHandler (kMaxNumUndoLevels)
486 , fHidableTextDatabase ()
487
488{
489 fHidableTextDatabase = make_shared<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:333
#define RequireNotNull(p)
Definition Assertions.h:347
#define Verify(c)
Definition Assertions.h:419
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...