REITP.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:115k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*
  2.  * reitp.c
  3.  *
  4.  * Purpose:
  5.  * Test program for RichEdit.  Excercises main RichEdit
  6.  * functionality while providing a good replacement for notepad.
  7.  *
  8.  * Owner:
  9.  *
  10.  *  Copyright (c) 1997 Microsoft Coporation
  11.  */
  12. #include "preinc.h"
  13. #include <windows.h>
  14. #include <windowsx.h>
  15. #include <commdlg.h>
  16. #include <cderr.h>
  17. #include <ctype.h>
  18. #include <stdio.h>
  19. #include <tchar.h>
  20. // for the benefit of the outside world,
  21. // richedit.h uses cpMax instead of cpMost
  22. // I highly prefer cpMost
  23. #ifdef cpMax
  24. #error "cpMax hack won't work"
  25. #endif // cpMax
  26. #define cpMax cpMost
  27. #include <richedit.h>
  28. #undef cpMax
  29. #include "olestd.h"
  30. #include "reguid.h"
  31. #include "dbugit.h"
  32. #include <richole.h>
  33. #include "reitp.h"
  34. #include "reitp.rh"
  35. #include "frmtbar.h"
  36. #include <oledlg.h>
  37. ASSERTDATA
  38. #define SUNKENRICHEDIT
  39. // define to use LiFormatRange() directly instead of via blitting
  40. //#define NOBLIT
  41. // used to make life simpler while testing, should not normally be defined
  42. //#define NO_SAVE_PROMPT
  43. struct _itpcall;
  44. typedef struct _pp
  45. {
  46. BOOL fDone;
  47. HWND hwndDlg;
  48. REDOC *predoc;
  49. LONG cchText;
  50. LONG dxPage;
  51. LONG dyPage;
  52. RECT rc;
  53. FORMATRANGE fr;
  54. #ifndef NOBLIT
  55. HBITMAP hbmp;
  56. HBITMAP hbmpOld;
  57. INT dxBmp;
  58. INT dyBmp;
  59. #endif // !NOBLIT
  60. INT ipage;
  61. INT cpage;
  62. INT cpageMost;
  63. LONG *rgcpPages;
  64. } PRINTPREVIEW;
  65. // number of pages to allocate at once in PRINTPREVIEW.rgcpPages
  66. #define cpageChunk 4
  67. #define szFmtPrintPreview TEXT("Print Preview - Page %d")
  68. typedef struct _assensz
  69. {
  70. WORD wNotification;
  71. LPCSTR szDescription;
  72. } ASSENSZ;
  73. // added to the client rect to get the RichEdit size
  74. #ifdef SUNKENRICHEDIT
  75. #define dxRESize -GetSystemMetrics(SM_CXBORDER)
  76. #define dyRESize -GetSystemMetrics(SM_CYBORDER)
  77. #else // SUNKENRICHEDIT
  78. #define dxRESize 0
  79. #define dyRESize 0
  80. #endif // SUNKENRICHEDIT, else
  81. // Control ID for the format bar
  82. #define FBR_FormatBar 217
  83. #define HinstFromHwnd(_hwnd) ((HINSTANCE) GetWindowLong(_hwnd, GWL_HINSTANCE))
  84. #define uiMFDisabled MF_DISABLED | MF_GRAYED
  85. #define uiMFEnabled MF_ENABLED
  86. // Maximum text to be corrected under PenWin
  87. #define cchMaxCorrectText 4096
  88. #define szClosedName szAppName
  89. static TCHAR szAppName[] = TEXT("REITP");
  90. static const TCHAR szClassRE[] = TEXT(RICHEDIT_CLASS);
  91. static const TCHAR szFmtTitle[] = TEXT("REITP - %s");
  92. static const TCHAR szUntitled[] = TEXT("[Untitled]");
  93. static const TCHAR szRTFSig[] = TEXT("{\rtf");
  94. #define cchRTFSig 5
  95. static TCHAR szRegKey[] = TEXT("software\microsoft\reitp");
  96. static TCHAR szRegValue[] = TEXT("placement");
  97. static const POINT ptMinTrackSize = {300, 90};
  98. // Make sure that these strings match the order of SF_*
  99. static TCHAR szFilterLoad[] = TEXT("Text and Rich Text*.TXT;*.RTFText Files (*.TXT)*.TXTRich Text Format (*.RTF)*.RTFAll Files*.*");
  100. static TCHAR szFilterSave[] = TEXT("Text Files (*.TXT)*.TXTRich Text Format (*.RTF)*.RTFRTF w/o Objects (*.RTF)*.RTFTextized*.TXT");
  101. static HMODULE hmod = 0; // Flag for FreeLibrary()
  102. HWND hwndMain = 0;
  103. static HMENU hmenuLoaded = 0;
  104. HMENU hmenuFull = 0;
  105. static PRINTDLG pdDef = {0};
  106. static BOOL fPrint = fFalse;
  107. static BOOL fWysiwygDefault = fFalse;
  108. static BOOL fWrapDefault = fTrue;
  109. static UINT msgFindReplace = 0;
  110. static HWND hwndFR = 0; // find/replace dialog
  111. HINSTANCE hinst = 0;
  112. static LONG cchTextMost = 0;
  113. static CLIPFORMAT cfTxtObj = 0;
  114. static BOOL fErrSpace = fFalse;
  115. static CHARFORMAT cfDefault =
  116. {
  117. sizeof(CHARFORMAT),
  118. CFM_EFFECTS | CFM_PROTECTED | CFM_SIZE | CFM_OFFSET | CFM_COLOR | CFM_CHARSET | CFM_FACE,
  119. CFE_AUTOCOLOR, // effects
  120. 200, // height, 200 twips == 10 points
  121. 0, // offset
  122. 0, // color (not used since CFE_AUTOCOLOR is specified)
  123. ANSI_CHARSET,
  124. FF_ROMAN, // pitch and family
  125. "Arial" // face name
  126. };
  127. static ASSENSZ rgassenszErrors[] =
  128. {
  129. {EN_ERRSPACE, "Out of memory. Exit some other applications and try again."},
  130. {EN_MAXTEXT, "The maximum text length has been reached."},
  131. {0, NULL}
  132. };
  133. /*
  134.  * ITPOLEINPLACEFRAME
  135.  *
  136.  * Purpose:
  137.  * Frame window support for in place editing
  138.  */
  139. typedef struct _itpoleinplaceframe
  140. {
  141. IOleInPlaceFrameVtbl * lpVtbl; // Virtual table
  142. ULONG cRef; // Reference count
  143. REDOC * predoc; // Document
  144. LPOLEINPLACEACTIVEOBJECT pipaobj; // Current active object
  145. }
  146. ITPOLEINPLACEFRAME;
  147. #define PipframeFromPunk(_p) ((ITPOLEINPLACEFRAME *) (_p))
  148. // Functions for ITP in place frame
  149. ITPOLEINPLACEFRAME * ITPOLEINPLACEFRAME_New(REDOC * predoc);
  150. STDMETHODIMP ITPOLEINPLACEFRAME_QueryInterface(LPUNKNOWN punk, REFIID riid,
  151.    LPUNKNOWN * ppvObj);
  152. STDMETHODIMP_(ULONG) ITPOLEINPLACEFRAME_AddRef(LPUNKNOWN punk);
  153. STDMETHODIMP_(ULONG) ITPOLEINPLACEFRAME_Release(LPUNKNOWN punk);
  154. STDMETHODIMP ITPOLEINPLACEFRAME_GetWindow(ITPOLEINPLACEFRAME * pipframe,
  155.   HWND * phwnd);
  156. STDMETHODIMP ITPOLEINPLACEFRAME_ContextSensitiveHelp(ITPOLEINPLACEFRAME *pipframe,
  157.  BOOL fEnterMode);
  158. STDMETHODIMP ITPOLEINPLACEFRAME_GetBorder(ITPOLEINPLACEFRAME * pipframe,
  159.   LPRECT prcBorder);
  160. STDMETHODIMP ITPOLEINPLACEFRAME_RequestBorderSpace(ITPOLEINPLACEFRAME * pipframe,
  161.    LPCBORDERWIDTHS pbw);
  162. STDMETHODIMP ITPOLEINPLACEFRAME_SetBorderSpace(ITPOLEINPLACEFRAME * pipframe,
  163.    LPCBORDERWIDTHS pbw);
  164. STDMETHODIMP ITPOLEINPLACEFRAME_SetActiveObject(ITPOLEINPLACEFRAME * pipframe,
  165.     LPOLEINPLACEACTIVEOBJECT pipaobj,
  166.     LPCSTR szObjName); 
  167. STDMETHODIMP ITPOLEINPLACEFRAME_InsertMenus(ITPOLEINPLACEFRAME * pipframe,
  168.     HMENU hmenuShared, 
  169.     LPOLEMENUGROUPWIDTHS pmgw);
  170. STDMETHODIMP ITPOLEINPLACEFRAME_SetMenu(ITPOLEINPLACEFRAME * pipframe, 
  171.     HMENU hmenuShared, HOLEMENU holemenu, 
  172.     HWND hwndActiveObject);
  173. STDMETHODIMP ITPOLEINPLACEFRAME_RemoveMenus(ITPOLEINPLACEFRAME * pipframe, 
  174.     HMENU hmenuShared);
  175. STDMETHODIMP ITPOLEINPLACEFRAME_SetStatusText(ITPOLEINPLACEFRAME * pipframe, 
  176.   LPCSTR szStatusText);    
  177. STDMETHODIMP ITPOLEINPLACEFRAME_EnableModeless(ITPOLEINPLACEFRAME * pipframe, 
  178.    BOOL fEnable);
  179. STDMETHODIMP ITPOLEINPLACEFRAME_TranslateAccelerator(ITPOLEINPLACEFRAME *pipframe,
  180.  LPMSG pmsg, WORD wID);
  181. // Virtual table for ole in place frame interface
  182. IOleInPlaceFrameVtbl ITPOLEINPLACEFRAME_Vtbl =
  183. {
  184. (LPVOID) ITPOLEINPLACEFRAME_QueryInterface,
  185. (LPVOID) ITPOLEINPLACEFRAME_AddRef,
  186. (LPVOID) ITPOLEINPLACEFRAME_Release,
  187. (LPVOID) ITPOLEINPLACEFRAME_GetWindow,
  188. (LPVOID) ITPOLEINPLACEFRAME_ContextSensitiveHelp,
  189. (LPVOID) ITPOLEINPLACEFRAME_GetBorder,
  190. (LPVOID) ITPOLEINPLACEFRAME_RequestBorderSpace,
  191. (LPVOID) ITPOLEINPLACEFRAME_SetBorderSpace,
  192. (LPVOID) ITPOLEINPLACEFRAME_SetActiveObject,
  193. (LPVOID) ITPOLEINPLACEFRAME_InsertMenus,
  194. (LPVOID) ITPOLEINPLACEFRAME_SetMenu,
  195. (LPVOID) ITPOLEINPLACEFRAME_RemoveMenus,
  196. (LPVOID) ITPOLEINPLACEFRAME_SetStatusText,
  197. (LPVOID) ITPOLEINPLACEFRAME_EnableModeless,
  198. (LPVOID) ITPOLEINPLACEFRAME_TranslateAccelerator
  199. };
  200. /*
  201.  * ITPCALL
  202.  *
  203.  * Purpose:
  204.  * Callbacks from the Rich Edit OLE support
  205.  */
  206. typedef struct _itpcall
  207. {
  208. IRichEditOleCallbackVtbl * lpVtbl; // Virtual table
  209. ULONG cRef;     // Reference count
  210. REDOC * predoc; // Document
  211. ITPOLEINPLACEFRAME * pipframe; // In place frame object
  212. }
  213. ITPCALL;
  214. #define PitpcallFromPunk(_p) ((ITPCALL *) (_p))
  215. // Functions for ITP callbacks
  216. ITPCALL * ITPCALL_New(REDOC * predoc);
  217. STDMETHODIMP ITPCALL_QueryInterface(LPUNKNOWN punk, REFIID riid,
  218.     LPUNKNOWN * ppvObj);
  219. STDMETHODIMP_(ULONG) ITPCALL_AddRef(LPUNKNOWN punk);
  220. STDMETHODIMP_(ULONG) ITPCALL_Release(LPUNKNOWN punk);
  221. STDMETHODIMP ITPCALL_GetNewStorage(ITPCALL * pitpcall, LPSTORAGE FAR * ppstg);
  222. STDMETHODIMP ITPCALL_GetInPlaceContext(ITPCALL * pitpcall, 
  223.    LPOLEINPLACEFRAME FAR * ppipframe,
  224.    LPOLEINPLACEUIWINDOW FAR* ppipuiDoc,
  225.    LPOLEINPLACEFRAMEINFO pipfinfo);
  226. STDMETHODIMP ITPCALL_ShowContainerUI(ITPCALL * pitpcall, BOOL fShow);
  227. STDMETHODIMP ITPCALL_QueryInsertObject(ITPCALL * pitpcall, LPCLSID pclsid,
  228. LPSTORAGE pstg, LONG cp);
  229. STDMETHODIMP ITPCALL_DeleteObject(ITPCALL * pitpcall, LPOLEOBJECT poleobj);
  230. STDMETHODIMP ITPCALL_QueryAcceptData(ITPCALL * pitpcall, LPDATAOBJECT pdataobj,
  231. CLIPFORMAT *pcfFormat, DWORD reco, BOOL fReally,
  232. HGLOBAL hMetaPict);
  233. STDMETHODIMP ITPCALL_ContextSensitiveHelp(ITPCALL * pitpcall, BOOL fEnterMode);
  234. STDMETHODIMP ITPCALL_GetClipboardData(ITPCALL *pitpcall, CHARRANGE *pchrg,
  235. DWORD reco, LPDATAOBJECT *ppdataobj);
  236. STDMETHODIMP ITPCALL_GetDragDropEffect(ITPCALL *pitpcall, BOOL fDrag,
  237. DWORD grfKeyState, LPDWORD pdwEffect);
  238. STDMETHODIMP ITPCALL_GetContextMenu(ITPCALL *pitpcall, WORD seltype,
  239. LPOLEOBJECT poleobj, CHARRANGE * pchrg, HMENU * phmenu);
  240. // Virtual table for ITP callbacks
  241. IRichEditOleCallbackVtbl ITPCALL_Vtbl =
  242. {
  243. (LPVOID) ITPCALL_QueryInterface,
  244. (LPVOID) ITPCALL_AddRef,
  245. (LPVOID) ITPCALL_Release,
  246. (LPVOID) ITPCALL_GetNewStorage,
  247. (LPVOID) ITPCALL_GetInPlaceContext,
  248. (LPVOID) ITPCALL_ShowContainerUI,
  249. (LPVOID) ITPCALL_QueryInsertObject,
  250. (LPVOID) ITPCALL_DeleteObject,
  251. (LPVOID) ITPCALL_QueryAcceptData,
  252. (LPVOID) ITPCALL_ContextSensitiveHelp,
  253. (LPVOID) ITPCALL_GetClipboardData,
  254. (LPVOID) ITPCALL_GetDragDropEffect,
  255. (LPVOID) ITPCALL_GetContextMenu
  256. };
  257. LOCAL VOID ParseArguments(LPSTR *pszDoc, LPCSTR szCmdLine);
  258. LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
  259. LOCAL LRESULT HandleCreate(REDOC *predoc, LPCSTR szCmdLine);
  260. LOCAL VOID ResizeRedoc(REDOC *predoc, RECT rc);
  261. LOCAL VOID SetupMenu(REDOC *predoc, int iMenu, HMENU hmenu);
  262. LOCAL LRESULT HandleCommand(REDOC *predoc, HWND hwnd, WPARAM wparam,
  263. LPARAM lparam);
  264. LOCAL BOOL ToggleCheck(REDOC *predoc, UINT uiMenuid);
  265. LOCAL BOOL QueryCheck(REDOC *predoc, UINT uiMenuid);
  266. LOCAL LRESULT NewREDoc(REDOC *predoc, BOOL fPrompt, BOOL fUpdateUI);
  267. LOCAL LONG CheckSave(REDOC *predoc);
  268. LOCAL INT CheckRevert(REDOC *predoc);
  269. LOCAL LRESULT CloseREDoc(REDOC *predoc, BOOL fPrompt, BOOL fUpdateUI);
  270. DWORD CALLBACK MyRead(DWORD dwCookie, LPBYTE pbBuffer, LONG cb, LONG *pcb);
  271. LOCAL LRESULT OpenREDoc(REDOC *predoc, BOOL fInsert);
  272. LOCAL LRESULT RevertREDoc(REDOC *predoc);
  273. LOCAL DWORD ReadREDoc(REDOC *predoc, LPCSTR szFile, LPCSTR szTitle,
  274. DWORD dwFormat, BOOL fInsert);
  275. DWORD CALLBACK MyWrite(DWORD dwCookie, LPBYTE pbBuffer, LONG cb, LONG *pcb);
  276. LOCAL LRESULT SaveREDoc(REDOC *predoc);
  277. LOCAL LRESULT SaveREDocAs(REDOC *predoc, BOOL fSelect);
  278. LOCAL LRESULT InsertObject(REDOC *predoc);
  279. LOCAL VOID SelectCharFormat(REDOC *predoc);
  280. LOCAL VOID SaveWindowPos(HWND hwnd);
  281. LOCAL BOOL FRestoreWindowPos(WINDOWPLACEMENT *pwndpl);
  282. LOCAL VOID SetAlignment(REDOC *predoc, WORD wAlignment);
  283. LOCAL VOID IndentFirst(REDOC *predoc, BOOL fIndent);
  284. LOCAL VOID ProtectSelection(REDOC *predoc);
  285. LOCAL VOID SetWordWrap(REDOC *predoc, BOOL fWysiwyg, BOOL fWrap);
  286. LOCAL VOID SetupWordWrapMenu(REDOC *predoc);
  287. LOCAL VOID SetOffset(REDOC *predoc, BOOL fSuperscript);
  288. LRESULT CALLBACK PPDlgProc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam);
  289. LOCAL BOOL FPPInit(PRINTPREVIEW *ppp);
  290. LOCAL VOID PPInitDialogSize(PRINTPREVIEW *ppp);
  291. LOCAL VOID PPChangePage(PRINTPREVIEW *ppp, BOOL fPrev);
  292. LOCAL VOID PPPaint(PRINTPREVIEW *ppp);
  293. VOID DoVerb(REDOC * predoc, INT ioleverb);
  294. LOCAL VOID FindReplace(REDOC *predoc, BOOL fReplace);
  295. LOCAL VOID ProcessFindReplace(REDOC *predoc, FINDREPLACE *pfr);
  296. LOCAL BOOL FEnablePaste(VOID);
  297. LOCAL VOID UpdateFormatBar(REDOC *predoc);
  298. LOCAL VOID ShowMargins(REDOC *predoc);
  299. int PASCAL
  300. WinMain(HINSTANCE hinstCurr, HINSTANCE hinstPrev, LPSTR szCmdLine, int nCmdShow)
  301. {
  302. SCODE sc;
  303. MSG msg;
  304. WNDCLASS wndclass;
  305. WINDOWPLACEMENT wndpl;
  306. TCHAR *szDoc = NULL;
  307. REDOC *predoc = NULL;
  308. HACCEL hAccels;
  309. #ifndef NO_OLE
  310. LPOLEINPLACEACTIVEOBJECT pipaobj;
  311. #endif // NO_OLE
  312.     LoadLibrary("RichEd32.Dll"); // Load the RichEdit DLL to activate the
  313.  // RichEdit classes
  314.     wndclass.style         = CS_HREDRAW | CS_VREDRAW;
  315.     wndclass.lpfnWndProc   = WndProc;
  316.     wndclass.cbClsExtra    = 0;
  317.     wndclass.cbWndExtra    = sizeof(REDOC *);
  318.     wndclass.hInstance     = hinstCurr;
  319.     wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
  320.     wndclass.hbrBackground = (HBRUSH) (COLOR_BACKGROUND + 1);
  321.     wndclass.hIcon        = LoadIcon(hinstCurr, TEXT("IconApp"));
  322.     wndclass.lpszMenuName  = NULL;
  323.     wndclass.lpszClassName = szAppName;
  324. RegisterClass(&wndclass);
  325. hinst = hinstCurr;
  326. #ifdef TEST_OLE_INITIALIZE
  327. OleInitialize(NULL);
  328. OleUninitialize();
  329. OleInitialize(NULL);
  330. OleUninitialize();
  331. #endif // TEST_OLE_INITIALIZE
  332. OleInitialize(NULL);
  333. sc = OleInitialize(NULL);
  334. if (FAILED(sc))
  335. {
  336. TraceError("OleInitialize failed", sc);
  337. goto done; // If OLE can't be initialized abort.
  338. }
  339. // OleStdInitialize();
  340. // Initialize the format bar class
  341. if(!FInitFormatBarClass(hinst))
  342. {
  343. MessageBoxA(NULL, "Unable to register format bar", NULL,
  344. MB_ICONSTOP | MB_OK);
  345. goto done;
  346. }
  347. hmenuLoaded = LoadMenu(hinstCurr, TEXT("LoadedMenu"));
  348. hmenuFull = LoadMenu(hinstCurr, TEXT("FullMenu"));
  349. msgFindReplace = RegisterWindowMessage(TEXT("commdlg_FindReplace"));
  350. cfTxtObj = RegisterClipboardFormat(TEXT(CF_RETEXTOBJ));
  351. ParseArguments(&szDoc, szCmdLine);
  352. if(fPrint && !szDoc)
  353. goto done;
  354. hwndMain = CreateWindow(szAppName, szAppName,
  355.             WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, 
  356.             0, 0, 750, 500, NULL, NULL, hinstCurr, szDoc);
  357. if(!hwndMain)
  358. {
  359. MessageBoxA(NULL, "Unable to create main window", NULL, MB_ICONSTOP | MB_OK);
  360. goto done;
  361. }
  362. SideAssert(predoc = (REDOC *) GetWindowLong(hwndMain, 0));
  363. if(!fPrint)
  364. {
  365. if(FRestoreWindowPos(&wndpl))
  366. SetWindowPlacement(hwndMain, &wndpl);
  367. ShowWindow(hwndMain, nCmdShow);
  368. }
  369. hAccels = LoadAccelerators(hinstCurr, "WARPKEYS");
  370. Assert(hAccels);
  371. while(GetMessage(&msg, NULL, 0, 0))
  372. {
  373. # ifndef NO_OLE
  374. // Translate accelerators for possible in place objects
  375. if(predoc->pitpcall && (pipaobj = predoc->pitpcall->pipframe->pipaobj))
  376. pipaobj->lpVtbl->TranslateAccelerator(pipaobj, &msg);
  377. # endif // NO_OLE
  378. if(predoc->hwndRE && TranslateAccelerator(hwndMain, hAccels, &msg))
  379. continue;
  380. if(!hwndFR || !IsDialogMessage(hwndFR, &msg))
  381. {
  382. TranslateMessage(&msg);
  383. DispatchMessage(&msg);
  384. }
  385. }
  386. done:
  387. if(szDoc)
  388. GlobalFreePtr(szDoc);
  389. if(hwndMain)
  390. DestroyWindow(hwndMain);
  391. if(hmenuLoaded)
  392. DestroyMenu(hmenuLoaded);
  393. if(hmenuFull)
  394. DestroyMenu(hmenuFull);
  395. // OleStdUninitialize();
  396. return msg.wParam;
  397. }
  398. LOCAL VOID ParseArguments(LPSTR *pszDoc, LPCSTR szCmdLine)
  399. {
  400. const TCHAR *pch;
  401. *pszDoc = NULL;
  402. pch = szCmdLine - 1;
  403. while(pch)
  404. {
  405. pch++;
  406. if(*pch == TEXT('/') || *pch == '-')
  407. {
  408. pch++;
  409. switch(*pch)
  410. {
  411. case TEXT('p'):
  412. case TEXT('P'):
  413. fPrint = fTrue;
  414. break;
  415. case TEXT('w'):
  416. case TEXT('W'):
  417. pch++;
  418. if(*pch == 'p' || *pch == 'P')
  419. {
  420. pch++;
  421. fWrapDefault = fTrue;
  422. fWysiwygDefault = fTrue;
  423. }
  424. else if(*pch == 'n' || *pch == 'N')
  425. {
  426. pch++;
  427. fWrapDefault = fFalse;
  428. fWysiwygDefault = fFalse;
  429. }
  430. else
  431. {
  432. fWrapDefault = fTrue;
  433. fWysiwygDefault = fFalse;
  434. }
  435. break;
  436. default:
  437. if(*pch >= TEXT('0') && *pch <= TEXT('9') && !cchTextMost)
  438. {
  439. while(*pch >= TEXT('0') && *pch <= TEXT('9'))
  440. {
  441. cchTextMost *= 10;
  442. cchTextMost += *pch++ - TEXT('0');
  443. }
  444. }
  445. break;
  446. }
  447. }
  448. else if(!*pszDoc)
  449. {
  450. while(*pch == TEXT(' '))
  451. pch++;
  452. if(*pch)
  453. {
  454. INT cch;
  455. const TCHAR *pchT;
  456. pchT = _tcschr(pch, TEXT(' '));
  457. if(pchT)
  458. cch = pchT - pch;
  459. else
  460. cch = lstrlen(pch);
  461. *pszDoc = GlobalAllocPtr(GHND, cch + 1);
  462. if(!*pszDoc)
  463. break;
  464. lstrcpyn(*pszDoc, (LPCSTR) pch, cch + 1);
  465. (*pszDoc)[cch] = '';
  466. }
  467. }
  468. pch = _tcschr(pch, TEXT(' '));
  469. }
  470. }
  471. LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
  472. {
  473. REDOC *predoc = (REDOC *) GetWindowLong(hwnd, 0);
  474. #ifndef NO_OLE
  475. LPOLEINPLACEACTIVEOBJECT pipaobj;
  476. #endif // !NO_OLE
  477.     switch(msg)
  478.     {
  479. case WM_NCCREATE:
  480. predoc = (REDOC *) GlobalAllocPtr(GHND, sizeof(REDOC));
  481. if(!predoc)
  482. return 0;
  483. SetWindowLong(hwnd, 0, (LONG) predoc);
  484. predoc->hwndParent = hwnd;
  485. #ifndef MAC
  486. predoc->pd.lStructSize = sizeof(PRINTDLG);
  487. predoc->pd.hwndOwner = hwnd;
  488. predoc->pd.Flags = PD_RETURNDEFAULT;
  489. if(!PrintDlg(&predoc->pd) && CommDlgExtendedError())
  490. memset(&predoc->pd, 0, sizeof(PRINTDLG));
  491. #endif
  492. break;
  493. case WM_NCDESTROY:
  494. if(predoc)
  495. {
  496. if(predoc->pfr)
  497. GlobalFreePtr(predoc->pfr);
  498. GlobalFreePtr(predoc);
  499. predoc = NULL;
  500. SetWindowLong(hwnd, 0, 0);
  501. }
  502. break;
  503. case WM_CREATE:
  504. hwndMain = hwnd; // a bit of a cheat...
  505. return HandleCreate(predoc,
  506. (LPCSTR) ((CREATESTRUCT *) lparam)->lpCreateParams);
  507.     case WM_DESTROY:
  508. PostQuitMessage(0);
  509.         return 0l;
  510. case WM_ACTIVATEAPP:
  511. #ifndef NO_OLE
  512. // Notify in place active object of frame activation
  513. if(predoc->pitpcall && (pipaobj = predoc->pitpcall->pipframe->pipaobj))
  514. {
  515. TraceTag(tagInPlace, "OnFrameWindowActivate(%d)", !!wparam);
  516. pipaobj->lpVtbl->OnFrameWindowActivate(pipaobj, !!wparam);
  517. }
  518. #endif // !NO_OLE
  519. break;
  520. case WM_INITMENU:
  521. if(predoc->hwndRE)
  522. predoc->fUpdateEditMenu = TRUE;
  523. break;
  524. case WM_INITMENUPOPUP:
  525. if(predoc->hwndRE)
  526. SetupMenu(predoc, (int) lparam, (HMENU) wparam);
  527. return 0;
  528. case WM_GETMINMAXINFO:
  529. ((MINMAXINFO *) lparam)->ptMinTrackSize = ptMinTrackSize;
  530. return 0;
  531. case WM_COMMAND:
  532. return HandleCommand(predoc, hwnd, wparam, lparam);
  533. case WM_CLOSE:
  534. if(predoc && predoc->hwndRE && CloseREDoc(predoc, fTrue, fFalse) < 0)
  535. return 0;
  536. if(!fPrint)
  537. SaveWindowPos(hwnd);
  538. DestroyWindow(hwnd);
  539. return 0;
  540. case WM_ACTIVATE:
  541. if(predoc->hwndRE && LOWORD(wparam))
  542. {
  543. SetFocus(predoc->hwndRE);
  544. return 0;
  545. }
  546. break;
  547. case WM_SIZE:
  548. if(predoc->hwndFormatBar)
  549. SendMessage(predoc->hwndFormatBar, WM_SIZE, 0, 0);
  550. if(predoc->hwndRE)
  551. {
  552. RECT rc;
  553. GetClientRect(hwnd, &rc);
  554. ResizeRedoc(predoc, rc);
  555. #ifdef DEBUG
  556. SendMessage(predoc->hwndRE, EM_REQUESTRESIZE, 0, 0);
  557. #endif // DEBUG
  558. }
  559. break;
  560. case WM_NOTIFY:
  561. switch(((NMHDR *) lparam)->code)
  562. {
  563. case EN_SELCHANGE:
  564. if(predoc->hwndFormatBar)
  565. UpdateFormatBar(predoc);
  566. return 0;
  567. case EN_PROTECTED:
  568. {
  569. ENPROTECTED *penprotected = (ENPROTECTED *) lparam;
  570. // allow change of protected attribute
  571. if(penprotected->msg == EM_SETCHARFORMAT &&
  572. ((CHARFORMAT *) penprotected->lParam)->dwMask & CFM_PROTECTED)
  573. {
  574. return 0;
  575. }
  576. }
  577. MessageBeep(0);
  578. return 1;
  579. case EN_CORRECTTEXT:
  580. {
  581. ENCORRECTTEXT *pct = (ENCORRECTTEXT *) lparam;
  582. if(pct->chrg.cpMost - pct->chrg.cpMin > cchMaxCorrectText)
  583. {
  584. MessageBox(hwndMain,
  585. "You are trying to correct too much text. "
  586. "Decrease the size of your selection.",
  587. "REITP: Correct Text", MB_OK);
  588. return 0;
  589. }
  590. }
  591. return 1;
  592. #ifndef NO_OLE
  593. case EN_DROPFILES:
  594. # ifdef DEBUG
  595. if(!QueryCheck(predoc, IDM_IGNOREDROPS))
  596. return fFalse;
  597. TraceTag(tagGeneral, "Ignoring drop of %d file(s) at position %d",
  598. DragQueryFile(((ENDROPFILES *) lparam)->hDrop, (UINT) -1,
  599. NULL, 0),
  600. ((ENDROPFILES *) lparam)->cp);
  601. // ignore file drops
  602. return fTrue;
  603. # else // DEBUG
  604. return ((ENDROPFILES *) lparam)->fProtected;
  605. # endif // DEBUG, else
  606. #endif // !NO_OLE
  607. #ifdef DEBUG
  608. case EN_MSGFILTER:
  609. {
  610. MSGFILTER * pmsgfilter = (MSGFILTER *) lparam;
  611. // eat left button downs and 'e's
  612. return (pmsgfilter->msg == WM_LBUTTONDOWN) ||
  613. ((pmsgfilter->msg == WM_CHAR) &&
  614. (pmsgfilter->wParam == 'e'));
  615. }
  616. case EN_REQUESTRESIZE:
  617. ResizeRedoc(predoc, ((REQRESIZE *) lparam)->rc);
  618. return 0;
  619. #endif // DEBUG
  620. }
  621. break;
  622. default:
  623. if(msg != msgFindReplace)
  624. break;
  625. if(((FINDREPLACE *) lparam)->Flags & FR_DIALOGTERM)
  626. {
  627. hwndFR = 0;
  628. SendMessage(predoc->hwndRE, EM_HIDESELECTION, fTrue, fTrue);
  629. return 0;
  630. }
  631. ProcessFindReplace(predoc, (FINDREPLACE *) lparam);
  632. return 0;
  633.     }
  634. return DefWindowProc(hwnd, msg, wparam, lparam);
  635. }
  636. LOCAL LRESULT HandleCreate(REDOC *predoc, LPCSTR szFile)
  637. {
  638. DWORD dwError;
  639. if(!szFile || !*szFile)
  640. goto no_file;
  641. if((dwError = ReadREDoc(predoc, szFile, NULL, 0, FALSE)))
  642. {
  643. TCHAR szErr[300];
  644. wsprintf(szErr, TEXT("Error opening %s [%ld]"), szFile, dwError);
  645. MessageBoxA(hwndMain, szErr, NULL, MB_OK);
  646. goto no_file;
  647. }
  648. if(fPrint)
  649. {
  650. PrintREDoc(predoc);
  651. PostQuitMessage(0);
  652. }
  653. else
  654. {
  655. TCHAR szT[256];
  656. wsprintf(szT, szFmtTitle, predoc->szTitle);
  657. SetWindowText(predoc->hwndParent, szT);
  658. SetMenu(hwndMain, hmenuFull);
  659. SetupWordWrapMenu(predoc);
  660. DrawMenuBar(hwndMain);
  661. }
  662. #ifdef TIME_OPEN
  663. PostMessage(hwndMain, WM_CLOSE, 0, 0);
  664. #endif // TIME_OPEN
  665. return 0;
  666. no_file:
  667. if(NewREDoc(predoc, fFalse, fTrue) < 0)
  668. {
  669. SetMenu(hwndMain, hmenuLoaded);
  670. }
  671. else
  672. {
  673. SetMenu(hwndMain, hmenuFull);
  674. SetupWordWrapMenu(predoc);
  675. }
  676. DrawMenuBar(hwndMain);
  677. return 0;
  678. }
  679. LOCAL VOID ResizeRedoc(REDOC *predoc, RECT rc)
  680. {
  681. RECT rcParent;
  682. #ifndef NO_OLE
  683. LPOLEINPLACEACTIVEOBJECT pipaobj = NULL;
  684. #endif // NO_OLE
  685. GetClientRect(predoc->hwndParent, &rcParent);
  686. InflateRect(&rcParent, dxRESize, dyRESize);
  687. // If we have a format bar, take it into account
  688. if(predoc->hwndFormatBar)
  689. {
  690. RECT rcFmtBar;
  691. GetClientRect(predoc->hwndFormatBar, &rcFmtBar);
  692. rcParent.top += rcFmtBar.bottom;
  693. }
  694. rc.top = max(rcParent.top, rc.top);
  695. rc.left = max(rcParent.left, rc.left);
  696. rc.right = min(rcParent.right, rc.right);
  697. rc.bottom = max(rc.bottom, rc.top + ptMinTrackSize.y);
  698. rc.bottom = min(rcParent.bottom, rc.bottom);
  699. MoveWindow(predoc->hwndRE, rc.left, rc.top, rc.right - rc.left,
  700. rc.bottom - rc.top, fTrue);
  701. if(GetMenuState(hmenuFull, IDM_SHOWMARGINS, MF_BYCOMMAND) & MF_CHECKED)
  702. {
  703. rc.bottom -= rc.top;
  704. rc.right -= rc.left;
  705. rc.top = 20;
  706. rc.bottom -= 30;
  707. if(rc.bottom < rc.top)
  708. rc.bottom = rc.top;
  709. rc.left = 30;
  710. rc.right -= 30;
  711. if(rc.right < rc.left)
  712. rc.right = rc.left;
  713. SendMessage(predoc->hwndRE, EM_SETRECT, 0, (LPARAM) &rc);
  714. }
  715. // Notify in place active object of resize
  716. //
  717. // NOTE : Do not change the following line so that it uses an &&
  718. // operation, this causes the Mac to lock up since the compiler
  719. // apparently checks the second half of an AND regardless of the
  720. // initial half's value.
  721. #ifndef NO_OLE
  722. if(predoc->pitpcall && (pipaobj = predoc->pitpcall->pipframe->pipaobj))
  723. {
  724. TraceTag(tagInPlace, "ResizeBorder");
  725. GetClientRect(hwndMain, &rc);
  726. # ifdef MAC
  727. pipaobj->lpVtbl->ResizeBorder(pipaobj, (RectPtr) &rc,
  728.   (LPOLEINPLACEUIWINDOW) predoc->pitpcall->pipframe, TRUE);
  729. // Throw out the mem
  730. # else // MAC
  731. pipaobj->lpVtbl->ResizeBorder(pipaobj, &rc, 
  732.     (LPOLEINPLACEUIWINDOW) predoc->pitpcall->pipframe, TRUE);
  733. # endif // MAC, else
  734. }
  735. #endif  // !NO_OLE
  736. }
  737. LOCAL VOID SetupMenu(REDOC *predoc, int iMenu, HMENU hmenu)
  738. {
  739. DWORD dw;
  740. LPOLEOBJECT poleobj = NULL;
  741. switch(iMenu)
  742. {
  743. case 0: // file
  744. if(!predoc->szFile[0])
  745. dw = 0;
  746. else
  747. dw = (DWORD) SendMessage(predoc->hwndRE, EM_GETMODIFY, 0, 0);
  748. EnableMenuItem(hmenu, IDM_REVERT, dw ? uiMFEnabled : uiMFDisabled);
  749. EnableMenuItem(hmenu, IDM_SAVE, predoc->fReadOnly
  750. ? uiMFDisabled : uiMFEnabled);
  751. break;
  752. case 1: // edit
  753. dw = uiMFDisabled;
  754. // see if something can be pasted
  755. // let RichEdit figure out if it's read-only
  756. if(SendMessage(predoc->hwndRE, EM_CANPASTE, 0, 0))
  757. dw = uiMFEnabled;
  758. EnableMenuItem(hmenu, IDM_PASTE, (UINT) dw);
  759. dw = 0;
  760. if(!predoc->fReadOnly)
  761. dw = (DWORD) SendMessage(predoc->hwndRE, EM_CANUNDO, 0, 0);
  762. EnableMenuItem(hmenu, IDM_UNDO, dw ? uiMFEnabled : uiMFDisabled);
  763. //$ REVIEW: use EN_SELCHANGE?
  764. dw = (DWORD) SendMessage(predoc->hwndRE, EM_SELECTIONTYPE, 0, 0);
  765. EnableMenuItem(hmenu, IDM_COPY, dw ? uiMFEnabled : uiMFDisabled);
  766. #ifdef DEBUG
  767. if(predoc->fReadOnly && !QueryCheck(predoc, IDM_ENABLECUTREADONLY))
  768. dw = 0;
  769. EnableMenuItem(hmenu, IDM_CUT, dw ? uiMFEnabled : uiMFDisabled);
  770. if(predoc->fReadOnly)
  771. dw = 0;
  772. #else // DEBUG
  773. if(predoc->fReadOnly)
  774. dw = 0;
  775. EnableMenuItem(hmenu, IDM_CUT, dw ? uiMFEnabled : uiMFDisabled);
  776. #endif // DEBUG, else
  777. EnableMenuItem(hmenu, IDM_DELETE, dw ? uiMFEnabled : uiMFDisabled);
  778. EnableMenuItem(hmenu, IDM_INSOBJ, predoc->fReadOnly
  779. ? uiMFDisabled : uiMFEnabled);
  780. EnableMenuItem(hmenu, IDM_REPLACE, predoc->fReadOnly ?
  781. uiMFDisabled : uiMFEnabled);
  782. // That's all we need to do
  783. if(!predoc->fUpdateEditMenu)
  784. break;
  785. #ifndef NO_OLE
  786. // Find out if we have a single object to deal with
  787. if(!(dw ^ SEL_OBJECT))
  788. {
  789. REOBJECT reobj = { 0 };
  790. reobj.cbStruct = sizeof(REOBJECT);
  791. reobj.cp = REO_CP_SELECTION;
  792. if(!predoc->preole->lpVtbl->GetObject(predoc->preole,
  793. REO_IOB_USE_CP, &reobj,
  794. REO_GETOBJ_POLEOBJ))
  795. {
  796. poleobj = reobj.poleobj;
  797. }
  798. }
  799. // Ask OLE to build the menu for us
  800. # ifdef MAC
  801. //$ FUTURE MAC
  802. dw = IDM_OBJECTCONVERT;
  803. #  ifdef NEVER
  804. macMenu1 = CheckoutMenu(hmenu, 2);
  805. if(!macMenu1)
  806. DebugStr("pCheckoutMenu(macMenu1) failed");
  807. macMenu2 = CheckoutMenu(predoc->hmenuVerbs, 2);
  808. if(!macMenu2)
  809. DebugStr("pCheckoutMenu(macMenu2) failed");
  810. if(!OleUIAddVerbMenu(poleobj,
  811. NULL, // Ask OLE to look up the name for us
  812. macMenu1, predoc->hmenuVerbs, ipos_Object,
  813. TRUE, (short *) &dw))
  814. {
  815. DebugStr("pOleUIAddVerbMenu failed!");
  816. }
  817. CheckinMenu(hmenu, 2);
  818. CheckinMenu(predoc->hmenuVerbs, 2);
  819. #  endif // NEVER
  820. # else // MAC
  821. OleUIAddVerbMenu(poleobj,
  822. NULL, // Ask OLE to look up the name for us
  823. hmenu, ipos_Object, IDM_OBJECTMIN, 
  824. 0, TRUE, IDM_OBJECTCONVERT, &predoc->hmenuVerbs);
  825. # endif // MAC, else
  826. if(poleobj)
  827. poleobj->lpVtbl->Release(poleobj);
  828. #endif  // !NO_OLE
  829. // We don't have to do all this hard work again unless the user leaves the
  830. // menu
  831. predoc->fUpdateEditMenu = FALSE;
  832. break;
  833. case 2: // format
  834. {
  835. BOOL fReadOnly = !!predoc->fReadOnly;
  836. UINT uiSuperscript = MF_UNCHECKED;
  837. UINT uiSubscript = MF_UNCHECKED;
  838. UINT uiProtected = MF_UNCHECKED;
  839. UINT uiLeft = MF_UNCHECKED;
  840. UINT uiCenter = MF_UNCHECKED;
  841. UINT uiRight = MF_UNCHECKED;
  842. UINT uiFirstIndent = MF_UNCHECKED;
  843. UINT uiFirstOutdent = MF_UNCHECKED;
  844. CHARFORMAT cf;
  845. PARAFORMAT pf;
  846. cf.cbSize = sizeof(CHARFORMAT);
  847. pf.cbSize = sizeof(PARAFORMAT);
  848. SendMessage(predoc->hwndRE, EM_GETCHARFORMAT, fTrue, (LPARAM) &cf);
  849. if(cf.yOffset > 0)
  850. uiSuperscript = MF_CHECKED;
  851. else if(cf.yOffset < 0)
  852. uiSubscript = MF_CHECKED;
  853. if(cf.dwEffects & CFE_PROTECTED)
  854. uiProtected = MF_CHECKED;
  855. SendMessage(predoc->hwndRE, EM_GETPARAFORMAT, 0, (LPARAM) &pf);
  856. if(!pf.wAlignment || pf.wAlignment == PFA_LEFT)
  857. uiLeft = MF_CHECKED;
  858. else if(pf.wAlignment == PFA_CENTER)
  859. uiCenter = MF_CHECKED;
  860. else
  861. uiRight = MF_CHECKED;
  862. if(pf.dxOffset < 0)
  863. uiFirstIndent = MF_CHECKED;
  864. else if(pf.dxOffset > 0)
  865. uiFirstOutdent = MF_CHECKED;
  866. CheckMenuItem(hmenu, IDM_SUPERSCRIPT, uiSuperscript);
  867. CheckMenuItem(hmenu, IDM_SUBSCRIPT, uiSubscript);
  868. CheckMenuItem(hmenu, IDM_PROTECTED, uiProtected);
  869. CheckMenuItem(hmenu, IDM_ALIGNLEFT, uiLeft);
  870. CheckMenuItem(hmenu, IDM_ALIGNCENTER, uiCenter);
  871. CheckMenuItem(hmenu, IDM_ALIGNRIGHT, uiRight);
  872. CheckMenuItem(hmenu, IDM_INDENTFIRST, uiFirstIndent);
  873. CheckMenuItem(hmenu, IDM_OUTDENTFIRST, uiFirstOutdent);
  874. EnableMenuItem(hmenu, IDM_CHARFORMAT, fReadOnly
  875. ? uiMFDisabled : uiMFEnabled);
  876. EnableMenuItem(hmenu, IDM_SUPERSCRIPT, fReadOnly
  877. ? uiMFDisabled : uiMFEnabled);
  878. EnableMenuItem(hmenu, IDM_SUBSCRIPT, fReadOnly
  879. ? uiMFDisabled : uiMFEnabled);
  880. EnableMenuItem(hmenu, IDM_ALIGNLEFT, fReadOnly
  881. ? uiMFDisabled : uiMFEnabled);
  882. EnableMenuItem(hmenu, IDM_ALIGNCENTER, fReadOnly
  883. ? uiMFDisabled : uiMFEnabled);
  884. EnableMenuItem(hmenu, IDM_ALIGNRIGHT, fReadOnly
  885. ? uiMFDisabled : uiMFEnabled);
  886. EnableMenuItem(hmenu, IDM_INDENTFIRST, fReadOnly
  887. ? uiMFDisabled : uiMFEnabled);
  888. EnableMenuItem(hmenu, IDM_OUTDENTFIRST, fReadOnly
  889. ? uiMFDisabled : uiMFEnabled);
  890. }
  891. break;
  892. case 3: // options
  893. {
  894. const DWORD eco = SendMessage(predoc->hwndRE, EM_GETOPTIONS, 0, 0);
  895. UINT uiSelBar = MF_UNCHECKED;
  896. UINT uiAutoWordSel = MF_UNCHECKED;
  897. #ifdef DEBUG
  898. UINT uiReadOnly = MF_UNCHECKED;
  899. UINT uiAutoHScroll = MF_UNCHECKED;
  900. UINT uiAutoVScroll = MF_UNCHECKED;
  901. UINT uiAutoHideSel = MF_UNCHECKED;
  902. #endif // DEBUG
  903. if(eco & ECO_SELECTIONBAR)
  904. uiSelBar = MF_CHECKED;
  905. if(eco & ECO_AUTOWORDSELECTION)
  906. uiAutoWordSel = MF_CHECKED;
  907. #ifdef DEBUG
  908. if(eco & ECO_READONLY)
  909. uiReadOnly = MF_CHECKED;
  910. if(eco & ECO_AUTOHSCROLL)
  911. uiAutoHScroll = MF_CHECKED;
  912. if(eco & ECO_AUTOVSCROLL)
  913. uiAutoVScroll = MF_CHECKED;
  914. if(!(eco & ECO_NOHIDESEL))
  915. uiAutoHideSel = MF_CHECKED;
  916. #endif // DEBUG
  917. CheckMenuItem(hmenu, IDM_SELBAR, uiSelBar);
  918. CheckMenuItem(hmenu, IDM_AUTOWORDSEL, uiAutoWordSel);
  919. #ifdef DEBUG
  920. CheckMenuItem(hmenu, IDM_READONLY, uiReadOnly);
  921. CheckMenuItem(hmenu, IDM_AUTOHSCROLL, uiAutoHScroll);
  922. CheckMenuItem(hmenu, IDM_AUTOVSCROLL, uiAutoVScroll);
  923. CheckMenuItem(hmenu, IDM_AUTOHIDESEL, uiAutoHideSel);
  924. #endif // DEBUG
  925. }
  926. break;
  927. }
  928. }
  929. LOCAL LRESULT HandleCommand(REDOC *predoc, HWND hwnd, WPARAM wparam,
  930. LPARAM lparam)
  931. {
  932. LRESULT lres = 0;
  933. INT nID;
  934. if(GET_WM_COMMAND_HWND(wparam, lparam) == predoc->hwndRE && predoc->hwndRE)
  935. {
  936. WORD wNotification = GET_WM_COMMAND_CMD(wparam, lparam);
  937. ASSENSZ *passensz;
  938. switch(wNotification)
  939. {
  940. case EN_CHANGE:
  941. if(predoc->hwndFormatBar)
  942. UpdateFormatBar(predoc);
  943. break;
  944. case EN_ERRSPACE:
  945. if(fErrSpace)
  946. break;
  947. fErrSpace = fTrue;
  948. // fall through to default
  949. default:
  950. for(passensz = rgassenszErrors; passensz->szDescription; passensz++)
  951. {
  952. if(passensz->wNotification == wNotification)
  953. {
  954. MessageBeep(0);
  955. MessageBoxA(hwndMain, passensz->szDescription, NULL,
  956. MB_ICONSTOP | MB_OK);
  957. return 0;
  958. }
  959. }
  960. break;
  961. }
  962. return 0;
  963. }
  964. fErrSpace = fFalse;
  965. nID = GET_WM_COMMAND_ID(wparam, lparam);
  966. switch(nID)
  967. {
  968. #ifdef DEBUG
  969. case IDM_CLSDBG:
  970. ClearDebugScreen();
  971. break;
  972. case IDM_TRACEDLG:
  973. DoTagsDialog();
  974. break;
  975. #endif // DEBUG
  976. case IDM_NEW:
  977. lres = NewREDoc(predoc, fTrue, fTrue);
  978. #ifdef DEBUG
  979. if(predoc->hwndRE)
  980. SendMessage(predoc->hwndRE, EM_REQUESTRESIZE, 0, 0);
  981. #endif // DEBUG
  982. break;
  983. case IDM_OPEN:
  984. lres = OpenREDoc(predoc, FALSE);
  985. break;
  986. case IDM_REVERT:
  987. lres = RevertREDoc(predoc);
  988. break;
  989. case IDM_PRINT:
  990. PrintREDoc(predoc);
  991. break;
  992. case IDM_PRINTPREVIEW:
  993. DialogBoxParam(HinstFromHwnd(hwndMain), TEXT("PRINTPREVIEW"), hwndMain,
  994. (DLGPROC) PPDlgProc, (LPARAM) predoc);
  995. break;
  996. case IDM_PRINTSETUP:
  997. predoc->pd.lStructSize = sizeof(PRINTDLG);
  998. predoc->pd.Flags = PD_PRINTSETUP;
  999. if(PrintDlg(&predoc->pd) && predoc->fWysiwyg)
  1000. {
  1001. // illegal values to force SetWordWrap() to do something
  1002. predoc->fWrap = fFalse;
  1003. predoc->fWysiwyg = fTrue;
  1004. SetWordWrap(predoc, fTrue, fTrue);
  1005. }
  1006. break;
  1007. case IDM_EXIT:
  1008. PostMessage(hwndMain, WM_CLOSE, 0, 0);
  1009. return 0;
  1010. case IDM_CLOSE:
  1011. return CloseREDoc(predoc, fTrue, fTrue);
  1012. case IDM_SAVE:
  1013. lres = SaveREDoc(predoc);
  1014. break;
  1015. case IDM_SAVEAS:
  1016. lres = SaveREDocAs(predoc, FALSE);
  1017. break;
  1018. case IDM_UNDO:
  1019. lres = SendMessage(predoc->hwndRE, EM_UNDO, 0, 0);
  1020. break;
  1021. case IDM_CUT:
  1022. lres = SendMessage(predoc->hwndRE, WM_CUT, 0, 0);
  1023. break;
  1024. case IDM_COPY:
  1025. lres = SendMessage(predoc->hwndRE, WM_COPY, 0, 0);
  1026. break;
  1027. case IDM_PASTE:
  1028. lres = SendMessage(predoc->hwndRE, WM_PASTE, 0, 0);
  1029. break;
  1030. case IDM_PASTESPECIAL:
  1031. NYI("Paste special");
  1032. break;
  1033. case IDM_DELETE:
  1034. lres = SendMessage(predoc->hwndRE, WM_KEYDOWN,
  1035. (WPARAM) VK_DELETE, 0);
  1036. break;
  1037. case IDM_SELECTALL:
  1038. lres = SendMessage(predoc->hwndRE, EM_SETSEL, 0, (LPARAM) -1);
  1039. break;
  1040. case IDM_FIND:
  1041. FindReplace(predoc, fFalse);
  1042. break;
  1043. case IDM_REPLACE:
  1044. FindReplace(predoc, fTrue);
  1045. break;
  1046. case IDM_OBJECT:
  1047. NYI("Object");
  1048. break;
  1049. case IDM_OBJECTCONVERT:
  1050. NYI("Object Convert");
  1051. break;
  1052. case IDM_INSOBJ:
  1053. return InsertObject(predoc);
  1054. case IDM_INSFILE:
  1055. lres = OpenREDoc(predoc, TRUE);
  1056. break;
  1057. case IDM_SAVESEL:
  1058. lres = SaveREDocAs(predoc, TRUE);
  1059. break;
  1060. case IDM_CHARFORMAT:
  1061. SelectCharFormat(predoc);
  1062. break;
  1063. case IDM_APPLYTOWORD:
  1064. predoc->scf = SCF_SELECTION;
  1065. if(ToggleCheck(predoc, IDM_APPLYTOWORD))
  1066. predoc->scf |= SCF_WORD;
  1067. break;
  1068. case IDM_SUPERSCRIPT:
  1069. SetOffset(predoc, fTrue);
  1070. break;
  1071. case IDM_SUBSCRIPT:
  1072. SetOffset(predoc, fFalse);
  1073. break;
  1074. case IDM_ALIGNLEFT:
  1075. SetAlignment(predoc, PFA_LEFT);
  1076. break;
  1077. case IDM_ALIGNCENTER:
  1078. SetAlignment(predoc, PFA_CENTER);
  1079. break;
  1080. case IDM_ALIGNRIGHT:
  1081. SetAlignment(predoc, PFA_RIGHT);
  1082. break;
  1083. case IDM_INDENTFIRST:
  1084. IndentFirst(predoc, fTrue);
  1085. break;
  1086. case IDM_OUTDENTFIRST:
  1087. IndentFirst(predoc, fFalse);
  1088. break;
  1089. case IDM_MARGINS:
  1090. NYI("set margins");
  1091. break;
  1092. case IDM_TABS:
  1093. NYI("set tabs");
  1094. break;
  1095. case IDM_PROTECTED:
  1096. ProtectSelection(predoc);
  1097. break;
  1098. case IDM_NOWRAP:
  1099. SetWordWrap(predoc, fFalse, fFalse);
  1100. break;
  1101. case IDM_WRAP:
  1102. SetWordWrap(predoc, fFalse, fTrue);
  1103. break;
  1104. case IDM_WYSIWYG:
  1105. SetWordWrap(predoc, fTrue, fTrue);
  1106. break;
  1107. case IDM_SELBAR:
  1108. SendMessage(predoc->hwndRE, EM_SETOPTIONS, ECOOP_XOR, ECO_SELECTIONBAR);
  1109. ToggleCheck(predoc, IDM_SELBAR);
  1110. break;
  1111. case IDM_AUTOWORDSEL:
  1112. SendMessage(predoc->hwndRE, EM_SETOPTIONS, ECOOP_XOR, ECO_AUTOWORDSELECTION);
  1113. ToggleCheck(predoc, IDM_AUTOWORDSEL);
  1114. break;
  1115. case IDM_SHOWMARGINS:
  1116. ShowMargins(predoc);
  1117. break;
  1118. #ifdef DEBUG
  1119. case IDM_READONLY:
  1120. SendMessage(predoc->hwndRE, EM_SETOPTIONS, ECOOP_XOR, ECO_READONLY);
  1121. predoc->fReadOnly = !!ToggleCheck(predoc, IDM_READONLY);
  1122. EnableWindow(predoc->hwndFormatBar, !predoc->fReadOnly);
  1123. break;
  1124. case IDM_AUTOHSCROLL:
  1125. SendMessage(predoc->hwndRE, EM_SETOPTIONS, ECOOP_XOR, ECO_AUTOHSCROLL);
  1126. ToggleCheck(predoc, IDM_AUTOHSCROLL);
  1127. break;
  1128. case IDM_AUTOVSCROLL:
  1129. SendMessage(predoc->hwndRE, EM_SETOPTIONS, ECOOP_XOR, ECO_AUTOVSCROLL);
  1130. ToggleCheck(predoc, IDM_AUTOVSCROLL);
  1131. break;
  1132. case IDM_AUTOHIDESEL:
  1133. SendMessage(predoc->hwndRE, EM_SETOPTIONS, ECOOP_XOR, ECO_NOHIDESEL);
  1134. ToggleCheck(predoc, IDM_AUTOHIDESEL);
  1135. break;
  1136. #endif // DEBUG
  1137. case IDM_GOTOCURSOR:
  1138. {
  1139. CHARRANGE cr;
  1140. POINT pt;
  1141. GetCursorPos(&pt);
  1142. ScreenToClient(predoc->hwndRE, &pt);
  1143. cr.cpMin = SendMessage(predoc->hwndRE, EM_CHARFROMPOS, 0,
  1144. (LPARAM) &pt);
  1145. cr.cpMost = cr.cpMin;
  1146. SendMessage(predoc->hwndRE, EM_EXSETSEL, 0, (LPARAM) &cr);
  1147. }
  1148. break;
  1149. case IDM_MOVECURSOR:
  1150. {
  1151. CHARRANGE cr;
  1152. POINT pt;
  1153. SendMessage(predoc->hwndRE, EM_EXGETSEL, 0, (LPARAM) &cr);
  1154. SendMessage(predoc->hwndRE, EM_POSFROMCHAR, (WPARAM) &pt, cr.cpMin);
  1155. ClientToScreen(predoc->hwndRE, &pt);
  1156. SetCursorPos(pt.x, pt.y);
  1157. }
  1158. break;
  1159. case TBI_IncreaseIndent:
  1160. case TBI_DecreaseIndent:
  1161. if(predoc->fReadOnly)
  1162. {
  1163. MessageBeep(0);
  1164. }
  1165. else
  1166. {
  1167. PARAFORMAT pf;
  1168. pf.cbSize = sizeof(PARAFORMAT);
  1169. if(GetFocus() == predoc->hwndFormatBar)
  1170. SetFocus(predoc->hwndRE);
  1171. pf.dwMask = PFM_OFFSETINDENT;
  1172. pf.dxStartIndent = (nID == TBI_IncreaseIndent)
  1173. ? cxBulletIndent
  1174. : -cxBulletIndent;
  1175. if(!SendMessage(predoc->hwndRE, EM_SETPARAFORMAT, FALSE,
  1176. (LPARAM) &pf))
  1177. {
  1178. MessageBeep(0);
  1179. }
  1180. }
  1181. break;
  1182. case TBI_Name:
  1183. case TBI_Size:
  1184. case TBI_Bold:
  1185. case TBI_Italic:
  1186. case TBI_Underline:
  1187. case TBI_Color:
  1188. {
  1189. CHARFORMAT cf;
  1190. cf.cbSize = sizeof(CHARFORMAT);
  1191. if(GetFocus() == predoc->hwndFormatBar)
  1192. SetFocus(predoc->hwndRE);
  1193. SendMessage(predoc->hwndFormatBar, EM_GETCHARFORMAT, 0,
  1194. (LPARAM) &cf);
  1195. SendMessage(predoc->hwndRE, EM_SETCHARFORMAT, predoc->scf,
  1196. (LPARAM) &cf);
  1197. }
  1198. break;
  1199. case TBI_AccelBold:
  1200. case TBI_AccelItalic:
  1201. case TBI_AccelUnderline:
  1202. {
  1203. CHARFORMAT cf;
  1204. DWORD dwEffects;
  1205. cf.cbSize = sizeof(CHARFORMAT);
  1206. SendMessage(predoc->hwndFormatBar, EM_GETCHARFORMAT, 0,
  1207. (LPARAM) &cf);
  1208. switch (nID)
  1209. {
  1210. case TBI_AccelBold:
  1211. dwEffects = CFE_BOLD;
  1212. break;
  1213. case TBI_AccelItalic:
  1214. dwEffects = CFE_ITALIC;
  1215. break;
  1216. case TBI_AccelUnderline:
  1217. dwEffects = CFE_UNDERLINE;
  1218. break;
  1219. }
  1220. cf.dwMask |= dwEffects;
  1221. cf.dwEffects ^= dwEffects;
  1222. if(GetFocus() == predoc->hwndFormatBar)
  1223. SetFocus(predoc->hwndRE);
  1224. SendMessage(predoc->hwndFormatBar, EM_SETCHARFORMAT, predoc->scf,
  1225. (LPARAM) &cf);
  1226. SendMessage(predoc->hwndRE, EM_SETCHARFORMAT, predoc->scf,
  1227. (LPARAM) &cf);
  1228. }
  1229. break;
  1230. case TBI_Bullet:
  1231. case TBI_Left:
  1232. case TBI_Center:
  1233. case TBI_Right:
  1234. {
  1235. PARAFORMAT pf;
  1236. pf.cbSize = sizeof(PARAFORMAT);
  1237. if(GetFocus() == predoc->hwndFormatBar)
  1238. SetFocus(predoc->hwndRE);
  1239. SendMessage(predoc->hwndFormatBar, EM_GETPARAFORMAT, 0,
  1240. (LPARAM) &pf);
  1241. SendMessage(predoc->hwndRE, EM_SETPARAFORMAT, FALSE, (LPARAM) &pf);
  1242. }
  1243. break;
  1244. #ifdef DEBUG
  1245. case IDM_DBGPED:
  1246. SendMessage(predoc->hwndRE, EM_DBGPED, 0, 0);
  1247. break;
  1248. case IDM_GETTEXT:
  1249. return GetText(predoc);
  1250. case IDM_IGNORELEFTCLICK:
  1251. IgnoreLeftClick(predoc);
  1252. break;
  1253. case IDM_EATES:
  1254. EatEs(predoc);
  1255. break;
  1256. case IDM_BOTTOMLESS:
  1257. Bottomless(predoc);
  1258. break;
  1259. case IDM_IGNOREDROPS:
  1260. case IDM_TEXTONLY:
  1261. case IDM_REFUSEGRAPH:
  1262. case IDM_PPMETA:
  1263. case IDM_ENABLECUTREADONLY:
  1264. case IDM_ENABLEPASTEREADONLY:
  1265. case IDM_ENABLEDRAGREADONLY:
  1266. case IDM_SWAPDRAGEFFECT:
  1267. ToggleCheck(predoc, nID);
  1268. break;
  1269. case IDM_HIDE:
  1270. ShowWindow(predoc->hwndRE, ToggleCheck(predoc, IDM_HIDE) ? SW_HIDE : SW_SHOW);
  1271. break;
  1272. case IDM_PASTEPLAINTEXT:
  1273. lres = SendMessage(predoc->hwndRE, EM_PASTESPECIAL, CF_TEXT, 0);
  1274. break;
  1275. case IDM_PASTETXTOBJ:
  1276. lres = SendMessage(predoc->hwndRE, EM_PASTESPECIAL, cfTxtObj, 0);
  1277. break;
  1278. case IDM_PASTERTFASTEXT:
  1279. lres = SendMessage(predoc->hwndRE, EM_PASTESPECIAL, cfRTFAsText, 0);
  1280. break;
  1281. case IDM_BIGLIMIT:
  1282. SetLimit(predoc);
  1283. break;
  1284. case IDM_FILLERUP:
  1285. FillerUp(predoc);
  1286. break;
  1287. #endif // DEBUG
  1288. default:
  1289. // Pass through OLE verbs
  1290. if(nID >= IDM_OBJECTMIN)
  1291. {
  1292. DoVerb(predoc, nID - IDM_OBJECTMIN);
  1293. }
  1294. return DefWindowProc(hwnd, WM_COMMAND, wparam, lparam);
  1295. }
  1296. return lres;
  1297. }
  1298. VOID DoVerb(REDOC * predoc, INT ioleverb)
  1299. {
  1300. REOBJECT reobj = { 0 };
  1301. POINT pt;
  1302. RECT rc = { 0 };
  1303. reobj.cbStruct = sizeof(REOBJECT);
  1304. if(predoc->preole->lpVtbl->GetObject(predoc->preole, REO_IOB_SELECTION,
  1305. &reobj,
  1306. REO_GETOBJ_POLESITE |
  1307. REO_GETOBJ_POLEOBJ))
  1308. {
  1309. AssertSz(FALSE, "DoVerb without object");
  1310. }
  1311. SendMessage(predoc->hwndRE, EM_POSFROMCHAR, (WPARAM) &pt, reobj.cp);
  1312. XformSizeInHimetricToPixels(NULL, &reobj.sizel, &reobj.sizel);
  1313. rc.right = (INT) reobj.sizel.cx;
  1314. rc.bottom = (INT) reobj.sizel.cy;
  1315. OffsetRect(&rc, pt.x, pt.y);
  1316. reobj.poleobj->lpVtbl->DoVerb(reobj.poleobj, ioleverb, NULL,
  1317. reobj.polesite, 0, predoc->hwndRE, &rc);
  1318. reobj.poleobj->lpVtbl->Release(reobj.poleobj);
  1319. reobj.polesite->lpVtbl->Release(reobj.polesite);
  1320. }
  1321. #ifdef DEBUG
  1322. LOCAL VOID IgnoreLeftClick(REDOC *predoc)
  1323. {
  1324. HMENU hmenu = GetMenu(hwndMain);
  1325. UINT uiMenuFlags;
  1326. DWORD dwMask;
  1327. Assert(predoc->hwndRE);
  1328. dwMask = SendMessage(predoc->hwndRE, EM_GETEVENTMASK, 0, 0);
  1329. uiMenuFlags = GetMenuState(hmenu, IDM_IGNORELEFTCLICK, MF_BYCOMMAND);
  1330. if(uiMenuFlags & MF_CHECKED)
  1331. dwMask &= ~ENM_MOUSEEVENTS;
  1332. else
  1333. dwMask |= ENM_MOUSEEVENTS;
  1334. uiMenuFlags ^= MF_CHECKED;
  1335. CheckMenuItem(hmenu, IDM_IGNORELEFTCLICK, MF_BYCOMMAND |
  1336. (uiMenuFlags & MF_CHECKED));
  1337. SendMessage(predoc->hwndRE, EM_SETEVENTMASK, 0, dwMask);
  1338. }
  1339. LOCAL VOID EatEs(REDOC *predoc)
  1340. {
  1341. HMENU hmenu = GetMenu(hwndMain);
  1342. UINT uiMenuFlags;
  1343. DWORD dwMask;
  1344. Assert(predoc->hwndRE);
  1345. dwMask = SendMessage(predoc->hwndRE, EM_GETEVENTMASK, 0, 0);
  1346. uiMenuFlags = GetMenuState(hmenu, IDM_EATES, MF_BYCOMMAND);
  1347. if(uiMenuFlags & MF_CHECKED)
  1348. dwMask &= ~ENM_KEYEVENTS;
  1349. else
  1350. dwMask |= ENM_KEYEVENTS;
  1351. uiMenuFlags ^= MF_CHECKED;
  1352. CheckMenuItem(hmenu, IDM_EATES, MF_BYCOMMAND | (uiMenuFlags & MF_CHECKED));
  1353. SendMessage(predoc->hwndRE, EM_SETEVENTMASK, 0, dwMask);
  1354. }
  1355. LOCAL VOID Bottomless(REDOC *predoc)
  1356. {
  1357. HMENU hmenu = GetMenu(hwndMain);
  1358. UINT uiMenuFlags;
  1359. DWORD dwMask;
  1360. Assert(predoc->hwndRE);
  1361. dwMask = SendMessage(predoc->hwndRE, EM_GETEVENTMASK, 0, 0);
  1362. uiMenuFlags = GetMenuState(hmenu, IDM_BOTTOMLESS, MF_BYCOMMAND);
  1363. if(uiMenuFlags & MF_CHECKED)
  1364. dwMask &= ~ENM_REQUESTRESIZE;
  1365. else
  1366. dwMask |= ENM_REQUESTRESIZE;
  1367. uiMenuFlags ^= MF_CHECKED;
  1368. CheckMenuItem(hmenu, IDM_BOTTOMLESS,
  1369. MF_BYCOMMAND | (uiMenuFlags & MF_CHECKED));
  1370. SendMessage(predoc->hwndRE, EM_SETEVENTMASK, 0, dwMask);
  1371. if(dwMask & ENM_REQUESTRESIZE)
  1372. {
  1373. SendMessage(predoc->hwndRE, EM_REQUESTRESIZE, 0, 0);
  1374. }
  1375. else
  1376. {
  1377. RECT rc;
  1378. GetClientRect(predoc->hwndParent, &rc);
  1379. ResizeRedoc(predoc, rc);
  1380. }
  1381. }
  1382. #endif // DEBUG
  1383. LOCAL BOOL ToggleCheck(REDOC *predoc, UINT uiMenuid)
  1384. {
  1385. HMENU hmenu = GetMenu(hwndMain);
  1386. UINT uiMenuFlags;
  1387. Assert(predoc->hwndRE);
  1388. uiMenuFlags = GetMenuState(hmenu, uiMenuid, MF_BYCOMMAND);
  1389. uiMenuFlags ^= MF_CHECKED;
  1390. CheckMenuItem(hmenu, uiMenuid, MF_BYCOMMAND | (uiMenuFlags & MF_CHECKED));
  1391. return !!(uiMenuFlags & MF_CHECKED);
  1392. }
  1393. LOCAL BOOL QueryCheck(REDOC *predoc, UINT uiMenuid)
  1394. {
  1395. HMENU hmenu = GetMenu(hwndMain);
  1396. UINT uiMenuFlags;
  1397. Assert(predoc->hwndRE);
  1398. if(!hmenu)
  1399. return fFalse;
  1400. uiMenuFlags = GetMenuState(hmenu, uiMenuid, MF_BYCOMMAND);
  1401. return !!(uiMenuFlags & MF_CHECKED);
  1402. }
  1403. LOCAL LRESULT NewREDoc(REDOC *predoc, BOOL fPrompt, BOOL fUpdateUI)
  1404. {
  1405. RECT rc;
  1406. DWORD dwStyle;
  1407. if(predoc->hwndRE)
  1408. {
  1409. PARAFORMAT pf = {0};
  1410. pf.cbSize = sizeof(PARAFORMAT);
  1411. if(fPrompt && CheckSave(predoc) < 0)
  1412. return -1;
  1413. predoc->szFile[0] = TEXT('');
  1414. lstrcpy(predoc->szTitle, szUntitled);
  1415. SetWindowText(predoc->hwndRE, TEXT(""));
  1416. pf.wAlignment = PFA_LEFT;
  1417. pf.cTabCount = 1;
  1418. pf.rgxTabs[0] = lDefaultTab;
  1419. pf.dwMask = PFM_STARTINDENT | PFM_RIGHTINDENT | PFM_OFFSET |
  1420. PFM_ALIGNMENT | PFM_TABSTOPS | PFM_NUMBERING;
  1421. SendMessage(predoc->hwndRE, EM_SETPARAFORMAT, 0, (LPARAM) &pf);
  1422. SendMessage(predoc->hwndRE, EM_SETCHARFORMAT, 0,
  1423. (LPARAM) (LPVOID) &cfDefault);
  1424. goto done;
  1425. }
  1426. else
  1427. {
  1428. predoc->szFile[0] = TEXT('');
  1429. lstrcpy(predoc->szTitle, szUntitled);
  1430. }
  1431. GetClientRect(predoc->hwndParent, &rc);
  1432. InflateRect(&rc, dxRESize, dyRESize);
  1433. // Create and display the format bar
  1434. if(predoc->hwndFormatBar = HwndCreateFormatBar(predoc->hwndParent,
  1435. FBR_FormatBar, NULL))
  1436. {
  1437. RECT rcFormatBar;
  1438. ShowWindow(predoc->hwndFormatBar, SW_SHOW);
  1439. GetClientRect(predoc->hwndFormatBar, &rcFormatBar);
  1440. rc.top += rcFormatBar.bottom;
  1441. }
  1442. #ifdef SUNKENRICHEDIT
  1443. dwStyle = 
  1444. ES_AUTOHSCROLL |
  1445. ES_AUTOVSCROLL |
  1446. // ES_DISABLENOSCROLL |
  1447. ES_MULTILINE |
  1448. // ES_NOHIDESEL |
  1449. ES_SAVESEL |
  1450. ES_SELECTIONBAR |
  1451. ES_SUNKEN |
  1452. // WS_BORDER |
  1453. WS_CHILD |
  1454. WS_CLIPCHILDREN |
  1455. WS_HSCROLL |
  1456. WS_VISIBLE |
  1457. WS_VSCROLL |
  1458. 0; // zero gets or'd with above
  1459. predoc->hwndRE = CreateWindow(szClassRE, TEXT(""),
  1460. dwStyle,
  1461. rc.left, rc.top,
  1462. rc.right - rc.left, rc.bottom - rc.top, predoc->hwndParent,
  1463. NULL, HinstFromHwnd(predoc->hwndParent), NULL);
  1464. #else // SUNKENRICHEDIT
  1465. ES_AUTOHSCROLL |
  1466. ES_AUTOVSCROLL |
  1467. // ES_DISABLENOSCROLL |
  1468. ES_MULTILINE |
  1469. // ES_NOHIDESEL |
  1470. ES_SAVESEL |
  1471. ES_SELECTIONBAR |
  1472. // ES_SUNKEN |
  1473. // WS_BORDER |
  1474. WS_CHILD |
  1475. WS_CLIPCHILDREN |
  1476. WS_HSCROLL |
  1477. WS_VISIBLE |
  1478. WS_VSCROLL |
  1479. 0; // zero gets or'd with above
  1480. predoc->hwndRE = CreateWindow(szClassRE, TEXT(""),
  1481. dwStyle,
  1482. rc.left, rc.top,
  1483. rc.right - rc.left, rc.bottom - rc.top, predoc->hwndParent,
  1484. NULL, HinstFromHwnd(predoc->hwndParent), NULL);
  1485. #endif // SUNKENRICHEDIT, else
  1486. if(!predoc->hwndRE)
  1487. {
  1488. MessageBoxA(hwndMain, "Unable to create a new document", NULL, MB_ICONSTOP | MB_OK);
  1489. return -1;
  1490. }
  1491. if(cchTextMost)
  1492. SendMessage(predoc->hwndRE, EM_EXLIMITTEXT, 0, cchTextMost);
  1493. #ifndef NO_OLE
  1494. DragAcceptFiles(predoc->hwndRE, TRUE);
  1495. #endif // !NO_OLE
  1496. // request EN_SELCHANGE, EN_CHANGE, EN_PROTECTED, and EN_DROPFILES
  1497. SendMessage(predoc->hwndRE, EM_SETEVENTMASK, 0,
  1498. ENM_SELCHANGE | ENM_CHANGE | ENM_PROTECTED | EN_DROPFILES |
  1499. ENM_CORRECTTEXT);
  1500. SetFocus(predoc->hwndRE);
  1501. predoc->scf = SCF_SELECTION;
  1502. if(GetMenu(hwndMain) && QueryCheck(predoc, IDM_APPLYTOWORD))
  1503. predoc->scf |= SCF_WORD;
  1504. #ifndef NO_OLE
  1505. if(!SendMessage(predoc->hwndRE, EM_GETOLEINTERFACE, 0, (LPARAM) &predoc->preole))
  1506. {
  1507. MessageBoxA(hwndMain, "No OLE interface!", NULL, MB_OK);
  1508. DestroyWindow(predoc->hwndRE);
  1509. predoc->hwndRE = 0;
  1510. return -1;
  1511. }
  1512. if(!(predoc->pstg = OleStdCreateRootStorage(NULL, STGM_SHARE_EXCLUSIVE)))
  1513. {
  1514. MessageBoxA(hwndMain, "No Storage!", NULL, MB_OK);
  1515. DestroyWindow(predoc->hwndRE);
  1516. predoc->hwndRE = 0;
  1517. return -1;
  1518. }
  1519. if(!(predoc->pitpcall = ITPCALL_New(predoc)))
  1520. {
  1521. MessageBoxA(hwndMain, "No callback object!", NULL, MB_OK);
  1522. DestroyWindow(predoc->hwndRE);
  1523. predoc->hwndRE = 0;
  1524. return -1;
  1525. }
  1526. SendMessage(predoc->hwndRE, EM_SETOLECALLBACK, 0, (LPARAM) predoc->pitpcall);
  1527. #endif // !NO_OLE
  1528. done:
  1529. if(fUpdateUI)
  1530. {
  1531. TCHAR szT[64];
  1532. wsprintf(szT, szFmtTitle, predoc->szTitle);
  1533. SetWindowText(predoc->hwndParent, szT);
  1534. SetMenu(hwndMain, hmenuFull);
  1535. DrawMenuBar(hwndMain);
  1536. }
  1537. predoc->fReadOnly = fFalse;
  1538. EnableWindow(predoc->hwndFormatBar, TRUE);
  1539. // illegal values to force SetWordWrap() to do something
  1540. predoc->fWrap = fFalse;
  1541. predoc->fWysiwyg = fTrue;
  1542. SetWordWrap(predoc, fWysiwygDefault, fWrapDefault);
  1543. // if we don't have a default font, use the windows variable width font
  1544. // otherwise, use the default font
  1545. if(cfDefault.dwMask == 0)
  1546. {
  1547. SendMessage(predoc->hwndRE, WM_SETFONT,
  1548. (WPARAM) GetStockObject(ANSI_VAR_FONT), 0);
  1549. SendMessage(predoc->hwndRE, EM_GETCHARFORMAT, FALSE,
  1550. (LPARAM) (LPVOID) &cfDefault);
  1551. }
  1552. else
  1553. {
  1554. SendMessage(predoc->hwndRE, EM_SETCHARFORMAT, 0,
  1555. (LPARAM) (LPVOID) &cfDefault);
  1556. }
  1557. SendMessage(predoc->hwndRE, EM_SETMODIFY, (WPARAM) fFalse, 0);
  1558. SendMessage(predoc->hwndRE, EM_SETREADONLY, (WPARAM) fFalse, 0);
  1559. UpdateFormatBar(predoc);
  1560. return 0;
  1561. }
  1562. LOCAL LONG CheckSave(REDOC *predoc)
  1563. {
  1564. int iMbid;
  1565. TCHAR szT[128];
  1566. #ifdef NO_SAVE_PROMPT
  1567. return 0;
  1568. #endif // NO_SAVE_PROMPT
  1569. if(!SendMessage(predoc->hwndRE, EM_GETMODIFY, 0, 0))
  1570. return 0;
  1571. wsprintf(szT, TEXT("Save changes to %s?"), predoc->szTitle);
  1572. iMbid = MessageBox(hwndMain, szT, szAppName, MB_APPLMODAL |
  1573. MB_ICONQUESTION | MB_YESNOCANCEL);
  1574. switch(iMbid)
  1575. {
  1576. case IDYES:
  1577. if(SaveREDoc(predoc) < 0)
  1578. return -1;
  1579. break;
  1580. case IDCANCEL:
  1581. return -1;
  1582. }
  1583. return 0;
  1584. }
  1585. // returns 0 if no changes have been made
  1586. // returns > 0 if revert should continue
  1587. // returns < 0 if revert should be aborted
  1588. LOCAL INT CheckRevert(REDOC *predoc)
  1589. {
  1590. int iMbid;
  1591. TCHAR szT[128];
  1592. if(!SendMessage(predoc->hwndRE, EM_GETMODIFY, 0, 0))
  1593. return 0;
  1594. #ifdef NO_SAVE_PROMPT
  1595. return 1;
  1596. #endif // NO_SAVE_PROMPT
  1597. wsprintf(szT, TEXT("Revert %s to last saved changes?"), predoc->szTitle);
  1598. iMbid = MessageBox(hwndMain, szT, szAppName, MB_APPLMODAL |
  1599. MB_ICONQUESTION | MB_YESNO);
  1600. return iMbid == IDYES ? 1 : -1;
  1601. }
  1602. LOCAL LRESULT CloseREDoc(REDOC *predoc, BOOL fPrompt, BOOL fUpdateUI)
  1603. {
  1604. if(fPrompt && CheckSave(predoc) < 0)
  1605. return -1;
  1606. if(predoc->hdcTarget)
  1607. {
  1608. DeleteDC(predoc->hdcTarget);
  1609. predoc->hdcTarget = 0;
  1610. }
  1611. #ifndef NO_OLE
  1612. // Deactivate any existing in place object
  1613. //$ FUTURE: This might be some generic I'm gonna close you call
  1614. predoc->preole->lpVtbl->InPlaceDeactivate(predoc->preole);
  1615. ITPCALL_Release((LPUNKNOWN) predoc->pitpcall);
  1616. predoc->pitpcall = NULL;
  1617. predoc->pstg->lpVtbl->Release(predoc->pstg);
  1618. predoc->pstg = NULL;
  1619. predoc->preole->lpVtbl->Release(predoc->preole);
  1620. predoc->preole = NULL;
  1621. predoc->cItem = 0;
  1622. #endif // !NO_OLE
  1623. DestroyWindow(predoc->hwndRE);
  1624. DestroyWindow(predoc->hwndFormatBar);
  1625. predoc->hwndRE = 0;
  1626. predoc->szFile[0] = TEXT('');
  1627. lstrcpy(predoc->szTitle, szUntitled);
  1628. predoc->dwFormat = SF_TEXT;
  1629. predoc->fReadOnly = fFalse;
  1630. EnableWindow(predoc->hwndFormatBar, TRUE);
  1631. #ifdef DEBUG
  1632. CheckMenuItem(hmenuFull, IDM_IGNORELEFTCLICK, MF_BYCOMMAND | MF_UNCHECKED);
  1633. CheckMenuItem(hmenuFull, IDM_EATES, MF_BYCOMMAND | MF_UNCHECKED);
  1634. CheckMenuItem(hmenuFull, IDM_IGNOREDROPS, MF_BYCOMMAND | MF_UNCHECKED);
  1635. CheckMenuItem(hmenuFull, IDM_BOTTOMLESS, MF_BYCOMMAND | MF_UNCHECKED);
  1636. CheckMenuItem(hmenuFull, IDM_TEXTONLY, MF_BYCOMMAND | MF_UNCHECKED);
  1637. if(hwndGT)
  1638. {
  1639. DestroyWindow(hwndGT);
  1640. hwndGT = 0;
  1641. }
  1642. #endif // DEBUG
  1643. if(fUpdateUI)
  1644. {
  1645. SetWindowText(predoc->hwndParent, szClosedName);
  1646. SetMenu(hwndMain, hmenuLoaded);
  1647. DrawMenuBar(hwndMain);
  1648. }
  1649. return 1;
  1650. }
  1651. DWORD CALLBACK MyRead(DWORD dwCookie, LPBYTE pbBuffer, LONG cb, LONG *pcb)
  1652. {
  1653. HFILE hf = (HFILE) dwCookie;
  1654. if(hf == HFILE_ERROR)
  1655. return (DWORD) E_FAIL;
  1656. *pcb = _lread(hf, pbBuffer, cb);
  1657. return (DWORD) (*pcb >= 0 ? NOERROR : (*pcb = 0, E_FAIL));
  1658. }
  1659. // This function gives the Mac version the ability to open and print
  1660. // files via Apple Events.
  1661. LRESULT DoOpen(predoc, szT, szTitle, fInsert)
  1662. REDOC *predoc;
  1663. LPSTR szT, szTitle;
  1664. BOOL fInsert;
  1665. {
  1666. DWORD dwError;
  1667. if((dwError = ReadREDoc(predoc, szT, szTitle, 0, fInsert)))
  1668. goto err;
  1669. wsprintf(szT, szFmtTitle, szTitle);
  1670. SetWindowText(predoc->hwndParent, szT);
  1671. EnableWindow(predoc->hwndFormatBar, !predoc->fReadOnly);
  1672. SendMessage(predoc->hwndRE, EM_SETREADONLY, (WPARAM) predoc->fReadOnly, 0);
  1673. SetMenu(hwndMain, hmenuFull);
  1674. SetupWordWrapMenu(predoc);
  1675. DrawMenuBar(hwndMain);
  1676. return 0;
  1677. err:
  1678. wsprintf(szT, TEXT("Error opening document. [%ld]"), dwError);
  1679. MessageBox(hwndMain, szT, NULL, MB_OK);
  1680. return -1;
  1681. }
  1682. LOCAL LRESULT OpenREDoc(REDOC *predoc, BOOL fInsert)
  1683. {
  1684. DWORD dwError;
  1685. OPENFILENAME ofn;
  1686. TCHAR szTitle[64];
  1687. TCHAR szT[256];
  1688. if(predoc->hwndRE && !fInsert && CheckSave(predoc) < 0)
  1689. return -1;
  1690. if(fInsert && predoc->fReadOnly)
  1691. return -1;
  1692. ofn.lStructSize = sizeof(ofn);
  1693. ofn.hInstance = 0;
  1694. ofn.lpstrFilter = szFilterLoad;
  1695. ofn.lpstrCustomFilter = NULL;
  1696. ofn.nMaxCustFilter = 0;
  1697. ofn.nFilterIndex = 0;
  1698. ofn.lpstrFileTitle = szTitle;
  1699. ofn.nMaxFileTitle = sizeof(szTitle);
  1700. ofn.lpstrInitialDir = NULL;
  1701. ofn.lpstrTitle = fInsert ? "Insert from File" : NULL;
  1702. ofn.nFileOffset = 0;
  1703. ofn.nFileExtension = 0;
  1704. ofn.lpstrDefExt = NULL;
  1705. ofn.lCustData = 0L;
  1706. ofn.lpfnHook = NULL;
  1707. ofn.lpTemplateName = NULL;
  1708. ofn.hwndOwner = hwndMain;
  1709. ofn.lpstrFile = szT;
  1710. ofn.nMaxFile = sizeof(szT);
  1711. ofn.Flags = OFN_FILEMUSTEXIST;
  1712. szTitle[0] = TEXT('');
  1713. szT[0] = TEXT('');
  1714. // Query user for filename for input
  1715.     if(!GetOpenFileName(&ofn))
  1716. {
  1717. if((dwError = CommDlgExtendedError()) != 0)
  1718. {
  1719. wsprintf(szT, TEXT("Error opening document. [%ld]"), dwError);
  1720. MessageBox(hwndMain, szT, NULL, MB_OK);
  1721. return -1;
  1722. }
  1723. return 0;
  1724. }
  1725. predoc->fReadOnly = (ofn.Flags & OFN_READONLY) ? fTrue : fFalse;
  1726. EnableWindow(predoc->hwndFormatBar, !predoc->fReadOnly);
  1727. return(DoOpen(predoc, szT, szTitle, fInsert));
  1728. }
  1729. LOCAL LRESULT RevertREDoc(REDOC *predoc)
  1730. {
  1731. DWORD dwError;
  1732. TCHAR szT[256];
  1733. if(CheckRevert(predoc) <= 0)
  1734. return 0;
  1735. lstrcpy(szT, predoc->szFile);
  1736. dwError = ReadREDoc(predoc, szT, NULL, predoc->dwFormat, FALSE);
  1737. if(!dwError)
  1738. return 0;
  1739. wsprintf(szT, TEXT("Error reading document. [%ld]"), dwError);
  1740. MessageBox(hwndMain, szT, NULL, MB_OK);
  1741. return -1;
  1742. }
  1743. LOCAL DWORD ReadREDoc(REDOC *predoc, LPCSTR szFile, LPCSTR szTitle,
  1744. DWORD dwFormat, BOOL fInsert)
  1745. {
  1746. LONG cch;
  1747. HCURSOR hcur;
  1748. EDITSTREAM es;
  1749. TCHAR szType[cchRTFSig + 1];
  1750.   hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  1751. es.dwCookie = (DWORD) _lopen(szFile, OF_READ);
  1752. if(es.dwCookie == (DWORD) HFILE_ERROR)
  1753. {
  1754. return GetLastError();
  1755. }
  1756. if(!fInsert)
  1757. {
  1758. // save read-only flag across NewREDoc()
  1759. const BOOL fReadOnlySave = predoc->fReadOnly;
  1760. if(NewREDoc(predoc, fFalse, fFalse) < 0)
  1761. {
  1762. _lclose((HFILE) es.dwCookie);
  1763. return (DWORD) -1;
  1764. }
  1765. predoc->fReadOnly = fReadOnlySave;
  1766. }
  1767. if(dwFormat == 0) // unknown format, figure out what it is
  1768. {
  1769. UINT cb = cchRTFSig * sizeof(TCHAR);
  1770. cb = _lread((HFILE) es.dwCookie, szType, cb);
  1771. szType[cb / sizeof(TCHAR)] = TEXT('');
  1772. if(cb == cchRTFSig * sizeof(TCHAR))
  1773. dwFormat = lstrcmpi(szRTFSig, szType) ? SF_TEXT : SF_RTF;
  1774. else
  1775. dwFormat = SF_TEXT; // not big enough to be RTF, assume text
  1776. // move back to the beginning of the file
  1777. _llseek((HFILE) es.dwCookie, 0, 0);
  1778. }
  1779. SendMessage(predoc->hwndRE, WM_SETREDRAW, (WPARAM) fFalse, 0);
  1780. es.dwError = 0;
  1781. es.pfnCallback = MyRead;
  1782. cch = SendMessage(predoc->hwndRE, EM_STREAMIN,
  1783. (WPARAM) (fInsert ? dwFormat | SFF_SELECTION : dwFormat),
  1784. (LPARAM) &es);
  1785. _lclose((HFILE) es.dwCookie);
  1786. #ifdef DEBUG
  1787. if(predoc->hwndRE)
  1788. SendMessage(predoc->hwndRE, EM_REQUESTRESIZE, 0, 0);
  1789. #endif // DEBUG
  1790. SendMessage(predoc->hwndRE, EM_SETMODIFY, (WPARAM) fFalse, 0);
  1791. predoc->dwFormat = dwFormat;
  1792. lstrcpy(predoc->szFile, szFile);
  1793. if(szTitle)
  1794. lstrcpy(predoc->szTitle, szTitle);
  1795. else
  1796. GetFileTitle(szFile, predoc->szTitle, sizeof(predoc->szTitle));
  1797. SendMessage(predoc->hwndRE, WM_SETREDRAW, (WPARAM) fTrue, 0);
  1798. InvalidateRect(predoc->hwndRE, NULL, fTrue);
  1799. UpdateWindow(predoc->hwndRE);
  1800. SetCursor(hcur);
  1801. UpdateFormatBar(predoc);
  1802. return 0;
  1803. }
  1804. DWORD CALLBACK MyWrite(DWORD dwCookie, LPBYTE pbBuffer, LONG cb, LONG *pcb)
  1805. {
  1806. HFILE hf = (HFILE) dwCookie;
  1807. if(hf == HFILE_ERROR)
  1808. return (DWORD) E_FAIL;
  1809. *pcb = _lwrite(hf, pbBuffer, cb);
  1810. return (DWORD) (*pcb == cb ? NOERROR : E_FAIL);
  1811. }
  1812. LOCAL LRESULT SaveREDoc(REDOC *predoc)
  1813. {
  1814. HCURSOR hcur;
  1815. LONG cch;
  1816. DWORD dwError;
  1817. EDITSTREAM es;
  1818. if(!predoc->szFile[0])
  1819. return SaveREDocAs(predoc, FALSE);
  1820. hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  1821. es.dwCookie = _lcreat(predoc->szFile, 0);
  1822. if(es.dwCookie == (DWORD) HFILE_ERROR)
  1823. {
  1824. dwError = GetLastError();
  1825. goto err;
  1826. }
  1827. es.dwError = 0;
  1828. es.pfnCallback = MyWrite;
  1829. cch = SendMessage(predoc->hwndRE, EM_STREAMOUT, (WPARAM) predoc->dwFormat,
  1830. (LPARAM) &es);
  1831. _lclose((HFILE) es.dwCookie);
  1832. SendMessage(predoc->hwndRE, EM_SETMODIFY, (WPARAM) fFalse, 0);
  1833. SendMessage(predoc->hwndRE, EM_SETREADONLY, (WPARAM) fFalse, 0);
  1834. predoc->fReadOnly = fFalse;
  1835. EnableWindow(predoc->hwndFormatBar, TRUE);
  1836. SetCursor(hcur);
  1837. return 0;
  1838. err:
  1839. {
  1840. TCHAR szT[64];
  1841. wsprintf(szT, TEXT("Error saving document. [%ld]"), dwError);
  1842. MessageBox(hwndMain, szT, NULL, MB_OK);
  1843. }
  1844. return -1;
  1845. }
  1846. LOCAL LRESULT SaveREDocAs(REDOC *predoc, BOOL fSelect)
  1847. {
  1848. HCURSOR hcur;
  1849. LONG cch;
  1850. DWORD dwError;
  1851. EDITSTREAM es;
  1852. OPENFILENAME ofn;
  1853. TCHAR szTitle[64];
  1854. TCHAR szT[256];
  1855. ofn.lStructSize = sizeof(ofn);
  1856. ofn.hInstance = 0;
  1857. ofn.lpstrFilter = szFilterSave;
  1858. ofn.lpstrCustomFilter = NULL;
  1859. ofn.nMaxCustFilter = 0;
  1860. ofn.nFilterIndex = 0;
  1861. ofn.lpstrFileTitle = szTitle;
  1862. ofn.nMaxFileTitle = sizeof(szTitle);
  1863. ofn.lpstrInitialDir = NULL;
  1864. ofn.lpstrTitle = fSelect ? "Save Selection As": NULL;
  1865. ofn.nFileOffset = 0;
  1866. ofn.nFileExtension = 0;
  1867.   ofn.lpstrDefExt = NULL;
  1868. ofn.lCustData = 0L;
  1869. ofn.lpfnHook = NULL;
  1870. ofn.lpTemplateName = NULL;
  1871. ofn.hwndOwner = hwndMain;
  1872. ofn.lpstrFile = szT;
  1873. ofn.nMaxFile = sizeof(szT);
  1874. ofn.Flags = OFN_CREATEPROMPT | OFN_HIDEREADONLY |
  1875. OFN_OVERWRITEPROMPT;
  1876. szT[0] = TEXT('');
  1877. szTitle[0] = TEXT('');
  1878. // Query user for filename for input
  1879.     if(!GetSaveFileName(&ofn))
  1880. {
  1881. if((dwError = CommDlgExtendedError()) != 0)
  1882. goto err;
  1883. return -1;
  1884. }
  1885. hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  1886. es.dwCookie = _lcreat(szT, 0);
  1887. if(es.dwCookie == (DWORD) HFILE_ERROR)
  1888. {
  1889. dwError = GetLastError();
  1890. goto err;
  1891. }
  1892. es.dwError = 0;
  1893. es.pfnCallback = MyWrite;
  1894. cch = SendMessage(predoc->hwndRE, EM_STREAMOUT,
  1895. (WPARAM) (fSelect ? ofn.nFilterIndex | SFF_SELECTION
  1896.   : ofn.nFilterIndex),
  1897. (LPARAM) &es);
  1898. _lclose((HFILE) es.dwCookie);
  1899. // Don't mark the doc as clean, nor remember format if only selection
  1900. if(fSelect)
  1901. goto Quit;
  1902. SendMessage(predoc->hwndRE, EM_SETMODIFY, (WPARAM) fFalse, 0);
  1903. predoc->dwFormat = (DWORD) ofn.nFilterIndex;
  1904. predoc->fReadOnly = fFalse;
  1905. EnableWindow(predoc->hwndFormatBar, TRUE);
  1906. lstrcpy(predoc->szFile, szT);
  1907. lstrcpy(predoc->szTitle, szTitle);
  1908. wsprintf(szT, szFmtTitle, szTitle);
  1909. SetWindowText(predoc->hwndParent, szT);
  1910. SendMessage(predoc->hwndRE, EM_SETMODIFY, (WPARAM) fFalse, 0);
  1911. SendMessage(predoc->hwndRE, EM_SETREADONLY, (WPARAM) fFalse, 0);
  1912. Quit:
  1913. SetCursor(hcur);
  1914. return 0;
  1915. err:
  1916. wsprintf(szT, TEXT("Error saving document. [%ld]"), dwError);
  1917. MessageBox(hwndMain, szT, NULL, MB_OK);
  1918. return -1;
  1919. }
  1920. LOCAL LRESULT InsertObject(REDOC *predoc)
  1921. {
  1922. #ifdef NO_OLE
  1923. MessageBox(NULL, "Not yet implemented", NULL, MB_OK);
  1924. return 0;
  1925. #else // NO_OLE
  1926. const LPRICHEDITOLE preole = predoc->preole;
  1927. LPOLECLIENTSITE polesite = NULL;
  1928. LPSTORAGE pstgItem = NULL;
  1929. OLEUIINSERTOBJECT ouio = { 0 };
  1930. REOBJECT reobj = { 0 };
  1931. LPOLEOBJECT poleobj = NULL;
  1932. CHAR szFileA[OLEUI_CCHPATHMAX];
  1933. WCHAR szItemW[OLEUI_CCHPATHMAX];
  1934. DWORD dwRet;
  1935. RECT rect;
  1936. if(!preole)
  1937. return 0;
  1938. if(preole->lpVtbl->SetHostNames(preole, "REITP", predoc->szTitle))
  1939. {
  1940. MessageBoxA(hwndMain, "Can't set host name", NULL, MB_OK);
  1941. goto error;
  1942. }
  1943. if(preole->lpVtbl->GetClientSite(preole, (LPOLECLIENTSITE FAR *) &polesite))
  1944. {
  1945. MessageBoxA(hwndMain, "No client site!", NULL, MB_OK);
  1946. goto error;
  1947. }
  1948. wsprintfW(szItemW, L"REOBJ%ld", ++predoc->cItem);
  1949. if(!(pstgItem = OleStdCreateChildStorage(predoc->pstg, szItemW)))
  1950. {
  1951. MessageBoxW(hwndMain, szItemW, L"No item storage!", MB_OK);
  1952. goto error;
  1953. }
  1954. szFileA[0] = '';
  1955. ouio.cbStruct = sizeof(ouio);
  1956. ouio.dwFlags = IOF_SHOWHELP | IOF_CREATENEWOBJECT | IOF_CREATEFILEOBJECT |
  1957.    IOF_CREATELINKOBJECT | IOF_SELECTCREATENEW;
  1958. //    IOF_VERIFYSERVERSEXIST;
  1959. # ifdef MAC // Mac version doesn't have the same members
  1960. ouio.pszFile = szFileA;
  1961. # else // MAC
  1962. ouio.hWndOwner = hwndMain;
  1963. ouio.lpszFile = szFileA;
  1964. # endif // MAC, else
  1965. ouio.lpszCaption = "Insert Object (REITP)";
  1966. ouio.cchFile = OLEUI_CCHPATHMAX;
  1967. ouio.iid = IID_IOleObject;
  1968. ouio.oleRender = OLERENDER_DRAW;
  1969. ouio.lpIOleClientSite = polesite;
  1970. ouio.lpIStorage = pstgItem;
  1971. ouio.ppvObj = (LPVOID FAR *) &poleobj;
  1972. ouio.clsid = CLSID_NULL;
  1973. if((dwRet = OleUIInsertObject(&ouio)) != OLEUI_SUCCESS)
  1974. {
  1975. if(dwRet == OLEUI_CANCEL)
  1976. goto error;
  1977. if(dwRet == OLEUI_IOERR_SCODEHASERROR)
  1978. wsprintfA(szFileA, "OleUIInsertObject scode is %lx", ouio.sc);
  1979. else
  1980. wsprintfA(szFileA, "OleUIInsertObject returned %ld", dwRet);
  1981. MessageBoxA(hwndMain, szFileA, NULL, MB_OK);
  1982. goto error;
  1983. }
  1984. AssertSz(ouio.sc == S_OK, "Object wasn't created properly");
  1985. reobj.cbStruct = sizeof(REOBJECT);
  1986. reobj.clsid = ouio.clsid;
  1987. reobj.cp = REO_CP_SELECTION;
  1988. reobj.poleobj = poleobj;
  1989. reobj.pstg = pstgItem;
  1990. reobj.polesite = polesite;
  1991. reobj.dvaspect = DVASPECT_CONTENT;
  1992. reobj.dwFlags = REO_RESIZABLE;
  1993. reobj.dwUser = 0;
  1994. if(ouio.dwFlags & IOF_SELECTCREATENEW)
  1995. reobj.dwFlags |= REO_BLANK;
  1996. //$ Raid 101: RichEdit doesn't setup advises if reobj.clsid == CLSID_NULL
  1997. // Try our darnest to get a CLSID
  1998. if(IsEqualCLSID(&reobj.clsid, &CLSID_NULL) &&
  1999. HrGetClassFileA(szFileA, &reobj.clsid))
  2000. {
  2001. MessageBoxA(hwndMain, "No CLSID, but forging on", "Insert Object",
  2002. MB_OK);
  2003. }
  2004. // Do we want an iconized version ?
  2005. if(ouio.dwFlags & IOF_CHECKDISPLAYASICON)
  2006. {
  2007. BOOL fUpdate; // Can't pass in NULL instead of &this
  2008. // OLE call will update dvaspect on success
  2009. # ifdef MAC
  2010. // NOTE : There presently is no Mac equivalent of the <.hMetaPict>
  2011. // member of the tagOleUIInsertObject structure. This is certainly
  2012. // a problem. For now just pass in NULL since the Mac routines will
  2013. // not try to use this member.
  2014. DebugStr("pBefore OleStdSwitchDisplayAspect() call");
  2015. if(OleStdSwitchDisplayAspect(poleobj, &reobj.dvaspect, 
  2016.   DVASPECT_ICON, (Handle) NULL, 
  2017.   TRUE, FALSE, NULL, &fUpdate))
  2018. # else // MAC
  2019. if(OleStdSwitchDisplayAspect(poleobj, &reobj.dvaspect, 
  2020.   DVASPECT_ICON, ouio.hMetaPict, 
  2021.   TRUE, FALSE, NULL, &fUpdate))
  2022. # endif // MAC, else
  2023. {
  2024. // How much do we care about reporting errors?  Alot!! {Mac will have more}
  2025. MessageBoxA(hwndMain, "Object couldn't be displayed as an icon.",
  2026. "Insert Object", MB_OK);
  2027. }
  2028. AssertSz(!fUpdate, "We gave it an hMetaPict, should not need updating");
  2029. }
  2030. // Put the thing in the edit control
  2031. if(preole->lpVtbl->InsertObject(preole, &reobj))
  2032. {
  2033. MessageBoxA(hwndMain, "Object couldn't be inserted",
  2034. "Insert object", MB_OK);
  2035. goto error;
  2036. }
  2037. // Do show verb only on new objects
  2038. if(ouio.dwFlags & IOF_SELECTCREATENEW)
  2039. {
  2040. rect.top = rect.left = 0;
  2041. rect.bottom = rect.right = 50;
  2042. dwRet = (ULONG) poleobj->lpVtbl->DoVerb(poleobj, OLEIVERB_SHOW, NULL,
  2043. polesite, 0, hwndMain, 
  2044. (LPCRECT) &rect);
  2045. }
  2046. error:
  2047. # ifndef MAC
  2048. if(ouio.hMetaPict)
  2049. OleUIMetafilePictIconFree(ouio.hMetaPict);
  2050. # endif // !MAC
  2051. if(polesite)
  2052. polesite->lpVtbl->Release(polesite);
  2053. if(pstgItem)
  2054. pstgItem->lpVtbl->Release(pstgItem);
  2055. if(poleobj)
  2056. poleobj->lpVtbl->Release(poleobj);
  2057. return 0;
  2058. #endif // NO_OLE, else
  2059. }
  2060. #ifdef DEBUG
  2061. LOCAL LRESULT GetText(REDOC *predoc)
  2062. {
  2063. HWND hwndEdit;
  2064. LONG cch;
  2065. TCHAR *pch;
  2066. if(!hwndGT)
  2067. {
  2068. hwndGT = CreateDialog(HinstFromHwnd(hwndMain), TEXT("GETTEXT"),
  2069. hwndMain, (DLGPROC) GTDlgProc);
  2070. if(!hwndGT)
  2071. {
  2072. MessageBoxA(hwndMain, "Unable to create dialog", NULL, MB_ICONSTOP | MB_OK);
  2073. return 0;
  2074. }
  2075. }
  2076. hwndEdit = GetDlgItem(hwndGT, GTCTRL);
  2077. cch = SendMessage(predoc->hwndRE, WM_GETTEXTLENGTH, 0, 0);
  2078. # ifdef WIN16
  2079. if(cch > 65000)
  2080. {
  2081. MessageBoxA(hwndMain, "Text too big, truncating", NULL,
  2082. MB_ICONSTOP | MB_OK);
  2083. cch = 65000;
  2084. }
  2085. # endif // WIN16
  2086. pch = GlobalAllocPtr(GHND, cch + 1);
  2087. if(!pch)
  2088. {
  2089. MessageBoxA(hwndMain, "Not enough memory to hold text", NULL,
  2090. MB_ICONSTOP | MB_OK);
  2091. return 0;
  2092. }
  2093. GetWindowText(predoc->hwndRE, pch, (int) cch + 1);
  2094. *pch = toupper(*pch);
  2095. SetWindowText(hwndEdit, pch);
  2096. GlobalFreePtr(pch);
  2097. return 0;
  2098. }
  2099. LRESULT CALLBACK GTDlgProc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
  2100. {
  2101. switch(msg)
  2102. {
  2103. case WM_INITDIALOG:
  2104. return 1;
  2105. case WM_SIZE:
  2106. MoveWindow(GetDlgItem(hdlg, GTCTRL), 5, 5, LOWORD(lparam)-10,
  2107.    HIWORD(lparam)-10, TRUE);
  2108. return 0;
  2109. case WM_CLOSE:
  2110. EndDialog(hdlg, 0);
  2111. hwndGT = NULL;
  2112. return 1;
  2113. }
  2114. return 0;
  2115. }
  2116. LOCAL VOID ClearDebugScreen(void)
  2117. {
  2118. HFILE hf;
  2119. hf = _lopen("COM1", OF_WRITE);
  2120. if(hf)
  2121. {
  2122. _lwrite(hf, "x1B[Hx1B[J", 6);
  2123. _lclose(hf);
  2124. }
  2125. }
  2126. #endif // DEBUG
  2127. LOCAL VOID SelectCharFormat(REDOC *predoc)
  2128. {
  2129. LOGFONT lf;
  2130. CHOOSEFONT csf = {0};
  2131. CHARFORMAT cf;
  2132. LONG yPerInch;
  2133. HDC hdc;
  2134. cf.cbSize = sizeof(CHARFORMAT);
  2135. hdc = GetDC(hwndMain);
  2136. yPerInch = GetDeviceCaps(hdc, LOGPIXELSY);
  2137. ReleaseDC(hwndMain, hdc);
  2138. (void) SendMessage(predoc->hwndRE, EM_GETCHARFORMAT, (WPARAM) fTrue,
  2139. (LPARAM) &cf);
  2140. csf.lStructSize = sizeof(csf);
  2141. csf.hwndOwner = hwndMain;
  2142. csf.hDC = 0;
  2143. csf.lpLogFont = &lf;
  2144. csf.Flags = CF_EFFECTS | CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT |
  2145. CF_LIMITSIZE;
  2146. csf.nSizeMin = 1;
  2147. csf.nSizeMax = yHeightCharPtsMost;
  2148. csf.rgbColors = cf.crTextColor;
  2149. csf.lpszStyle = NULL;
  2150. csf.nFontType = REGULAR_FONTTYPE | SCREEN_FONTTYPE;
  2151. lf.lfHeight = -(INT) ((cf.yHeight * yPerInch) / 1440);
  2152. lf.lfWidth = 0;
  2153. lf.lfEscapement = 0;
  2154. lf.lfOrientation = 0;
  2155. lf.lfWeight = (cf.dwEffects & CFE_BOLD) ? FW_BOLD : FW_NORMAL;
  2156. lf.lfItalic = (cf.dwEffects & CFE_ITALIC) ? fTrue : fFalse;
  2157. lf.lfUnderline = (cf.dwEffects & CFE_UNDERLINE) ? fTrue : fFalse;
  2158. lf.lfStrikeOut = (cf.dwEffects & CFE_STRIKEOUT) ? fTrue : fFalse;
  2159. lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
  2160. lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  2161. lf.lfQuality = DRAFT_QUALITY;
  2162. lf.lfCharSet = cf.bCharSet;
  2163. lf.lfPitchAndFamily = cf.bPitchAndFamily;
  2164. _tcscpy(lf.lfFaceName, cf.szFaceName);
  2165. if(!ChooseFont(&csf))
  2166. return;
  2167. cf.cbSize = sizeof(CHARFORMAT);
  2168. // don't change read-only bit
  2169. cf.dwMask = CFM_SIZE | CFM_EFFECTS | CFM_COLOR | CFM_FACE | CFM_CHARSET;
  2170. cf.yHeight = (LONG) csf.iPointSize * 2;
  2171. cf.dwEffects = CFM_EFFECTS;
  2172. if(lf.lfWeight < FW_BOLD)
  2173. cf.dwEffects &= ~CFE_BOLD;
  2174. if(!lf.lfItalic)
  2175. cf.dwEffects &= ~CFE_ITALIC;
  2176. if(!lf.lfUnderline)
  2177. cf.dwEffects &= ~CFE_UNDERLINE;
  2178. if(!lf.lfStrikeOut)
  2179. cf.dwEffects &= ~CFE_STRIKEOUT;
  2180. cf.crTextColor = csf.rgbColors;
  2181. cf.bCharSet = lf.lfCharSet;
  2182. cf.bPitchAndFamily = lf.lfPitchAndFamily;
  2183. _tcscpy(cf.szFaceName, lf.lfFaceName);
  2184. if(!SendMessage(predoc->hwndRE, EM_SETCHARFORMAT, predoc->scf,
  2185. (LPARAM) &cf))
  2186. {
  2187. MessageBoxA(hwndMain, "Error setting character format", NULL,
  2188. MB_ICONSTOP | MB_OK);
  2189. }
  2190. }
  2191. LOCAL VOID SaveWindowPos(HWND hwnd)
  2192. {
  2193. WINDOWPLACEMENT wndpl;
  2194. HKEY hkey;
  2195.     wndpl.length = sizeof(wndpl);
  2196.     GetWindowPlacement(hwnd, &wndpl);
  2197.     if(RegCreateKeyEx(HKEY_CURRENT_USER, szRegKey, 0, szAppName, 0,
  2198. KEY_ALL_ACCESS, NULL, &hkey, NULL) == ERROR_SUCCESS)
  2199.     {
  2200.         RegSetValueEx(hkey, szRegValue, 0, REG_BINARY, (LPBYTE) &wndpl,
  2201. sizeof(wndpl));
  2202.         RegCloseKey(hkey);
  2203.     }
  2204. }
  2205. LOCAL BOOL FRestoreWindowPos(WINDOWPLACEMENT *pwndpl)
  2206. {
  2207. BOOL fReturn = fFalse;
  2208. DWORD cb;
  2209. HKEY hkey = 0;
  2210.     if(RegOpenKeyEx(HKEY_CURRENT_USER, szRegKey, 0, KEY_READ, &hkey)
  2211. == ERROR_SUCCESS)
  2212. {
  2213. cb = sizeof(*pwndpl);
  2214. if(RegQueryValueEx(hkey, szRegValue, 0, 0, (LPBYTE) pwndpl,
  2215. &cb) == ERROR_SUCCESS)
  2216. {
  2217. fReturn = (cb == sizeof(*pwndpl));
  2218. }
  2219. RegCloseKey(hkey);
  2220. }
  2221. return fReturn;
  2222. }
  2223. LOCAL VOID SetAlignment(REDOC *predoc, WORD wAlignment)
  2224. {
  2225. PARAFORMAT pf;
  2226. pf.cbSize = sizeof(PARAFORMAT);
  2227. SendMessage(predoc->hwndRE, EM_GETPARAFORMAT, 0, (LPARAM) &pf);
  2228. if(!(pf.dwMask & PFM_ALIGNMENT) || pf.wAlignment != wAlignment)
  2229. {
  2230. pf.dwMask = PFM_ALIGNMENT; // only change the alignment
  2231. pf.wAlignment = wAlignment;
  2232. SendMessage(predoc->hwndRE, EM_SETPARAFORMAT, 0, (LPARAM) &pf);
  2233. }
  2234. }
  2235. LOCAL VOID IndentFirst(REDOC *predoc, BOOL fIndent)
  2236. {
  2237. PARAFORMAT pf;
  2238. pf.cbSize = sizeof(PARAFORMAT);
  2239. SendMessage(predoc->hwndRE, EM_GETPARAFORMAT, 0, (LPARAM) &pf);
  2240. pf.dwMask = PFM_OFFSET | PFM_OFFSETINDENT;
  2241. if(fIndent)
  2242. {
  2243. if(pf.dxOffset < 0)
  2244. {
  2245. pf.dxStartIndent = pf.dxOffset;
  2246. pf.dxOffset = 0;
  2247. }
  2248. else
  2249. {
  2250. pf.dxOffset = pf.dxOffset ? -pf.dxOffset : -lDefaultTab;
  2251. pf.dxStartIndent = -pf.dxOffset;
  2252. }
  2253. }
  2254. else
  2255. {
  2256. if(pf.dxOffset < 0)
  2257. {
  2258. pf.dxStartIndent = pf.dxOffset;
  2259. pf.dxOffset = -pf.dxOffset;
  2260. }
  2261. else
  2262. {
  2263. pf.dxStartIndent = 0;
  2264. pf.dxOffset = pf.dxOffset ? 0 : lDefaultTab;
  2265. }
  2266. }
  2267. SendMessage(predoc->hwndRE, EM_SETPARAFORMAT, 0, (LPARAM) &pf);
  2268. }
  2269. LOCAL VOID ProtectSelection(REDOC *predoc)
  2270. {
  2271. CHARFORMAT cf;
  2272. cf.cbSize = sizeof(CHARFORMAT);
  2273. (void) SendMessage(predoc->hwndRE, EM_GETCHARFORMAT, fTrue, (LPARAM) &cf);
  2274. cf.dwMask = CFM_PROTECTED;
  2275. cf.dwEffects = cf.dwEffects ^ CFE_PROTECTED;
  2276. (void) SendMessage(predoc->hwndRE, EM_SETCHARFORMAT, predoc->scf,
  2277. (LPARAM) &cf);
  2278. }
  2279. LOCAL VOID SetWordWrap(REDOC *predoc, BOOL fWysiwyg, BOOL fWrap)
  2280. {
  2281. HCURSOR hcur;
  2282. HDC hdcDel = predoc->hdcTarget;
  2283. LONG xWidth;
  2284. if(!fWysiwyg == !predoc->fWysiwyg && !fWrap == !predoc->fWrap)
  2285. return;
  2286. hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  2287. if(fWysiwyg)
  2288. {
  2289. POINT pt;
  2290. LPDEVMODE pDevMode;
  2291. LPDEVNAMES pDevNames;
  2292. if(predoc->pd.lStructSize != sizeof(PRINTDLG))
  2293. goto done; // error occured getting default printer
  2294. pDevMode = (LPDEVMODE) GlobalLock(predoc->pd.hDevMode);
  2295. pDevNames = (LPDEVNAMES) GlobalLock(predoc->pd.hDevNames);
  2296. predoc->hdcTarget = CreateIC((LPTSTR) pDevNames +
  2297. pDevNames->wDriverOffset,
  2298. (LPTSTR) pDevNames + pDevNames->wDeviceOffset,
  2299. (LPTSTR) pDevNames + pDevNames->wOutputOffset,
  2300. pDevMode);
  2301. GlobalUnlock(predoc->pd.hDevNames);
  2302. GlobalUnlock(predoc->pd.hDevMode);
  2303. if(!predoc->hdcTarget)
  2304. goto done;
  2305. SetMapMode(predoc->hdcTarget, MM_TEXT);
  2306. if(Escape(predoc->hdcTarget, GETPHYSPAGESIZE, 0, NULL, &pt) > 0)
  2307. {
  2308. const LONG xPerInch = GetDeviceCaps(predoc->hdcTarget, LOGPIXELSX);
  2309. xWidth = (pt.x * 1440l) / xPerInch;
  2310. // leave 1.25" (1800 twips) margins if that will leave >= 1"
  2311. if(xWidth >= 1800 + 1440 + 1800)
  2312. xWidth -= 1800 + 1800;
  2313. }
  2314. else
  2315. {
  2316. const LONG xPerInch = GetDeviceCaps(predoc->hdcTarget, LOGPIXELSX);
  2317. xWidth = (GetDeviceCaps(predoc->hdcTarget, HORZRES) * 1440l) /
  2318. xPerInch;
  2319. }
  2320. }
  2321. else
  2322. {
  2323. predoc->hdcTarget = 0;
  2324. xWidth = (LONG) !fWrap;
  2325. }
  2326. predoc->fWysiwyg = fWysiwyg;
  2327. predoc->fWrap = fWrap;
  2328. SetupWordWrapMenu(predoc);
  2329. SendMessage(predoc->hwndRE, EM_SETTARGETDEVICE,
  2330. (WPARAM) predoc->hdcTarget, (LPARAM) xWidth);
  2331. if(hdcDel)
  2332. DeleteDC(hdcDel);
  2333. done:
  2334. SetCursor(hcur);
  2335. }
  2336. LOCAL VOID SetupWordWrapMenu(REDOC *predoc)
  2337. {
  2338. HMENU hmenu = GetMenu(hwndMain);
  2339. CheckMenuItem(hmenu, IDM_NOWRAP,
  2340. (!predoc->fWysiwyg && !predoc->fWrap) ? MF_CHECKED : MF_UNCHECKED);
  2341. CheckMenuItem(hmenu, IDM_WRAP,
  2342. (!predoc->fWysiwyg && predoc->fWrap) ? MF_CHECKED : MF_UNCHECKED);
  2343. CheckMenuItem(hmenu, IDM_WYSIWYG,
  2344. predoc->fWysiwyg ? MF_CHECKED : MF_UNCHECKED);
  2345. }
  2346. LOCAL VOID SetOffset(REDOC *predoc, BOOL fSuperscript)
  2347. {
  2348. CHARFORMAT cf;
  2349. cf.cbSize = sizeof(CHARFORMAT);
  2350. SendMessage(predoc->hwndRE, EM_GETCHARFORMAT, fTrue, (LPARAM) &cf);
  2351. cf.dwMask = CFM_OFFSET; // only change the yOffset
  2352. if(fSuperscript)
  2353. {
  2354. if(cf.yOffset > 0)
  2355. cf.yOffset = 0;
  2356. else
  2357. cf.yOffset = 50;
  2358. }
  2359. else
  2360. {
  2361. if(cf.yOffset < 0)
  2362. cf.yOffset = 0;
  2363. else
  2364. cf.yOffset = -50;
  2365. }
  2366. SendMessage(predoc->hwndRE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cf);
  2367. }
  2368. VOID PrintREDoc(REDOC *predoc)
  2369. {
  2370. LONG cchText;
  2371. HCURSOR hcur;
  2372. POINT pt;
  2373. DOCINFO di;
  2374. FORMATRANGE fr;
  2375. RECT rc;
  2376. cchText = SendMessage(predoc->hwndRE, WM_GETTEXTLENGTH, 0, 0);
  2377. predoc->pd.nFromPage = 0;
  2378. predoc->pd.nToPage = 0;
  2379. predoc->pd.nMinPage = 0;
  2380. predoc->pd.nMaxPage = 0;
  2381. predoc->pd.nCopies = 1;
  2382. predoc->pd.Flags = 
  2383. PD_NOPAGENUMS | PD_NOSELECTION |
  2384. PD_USEDEVMODECOPIES | PD_COLLATE | PD_RETURNDC;
  2385. if(!PrintDlg(&predoc->pd))
  2386. return;
  2387. hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  2388. di.cbSize = sizeof(DOCINFO);
  2389. di.lpszDocName = predoc->szTitle;
  2390. di.lpszOutput = NULL;
  2391. fr.hdc = predoc->pd.hDC;
  2392. fr.hdcTarget = 0;
  2393. if(Escape(fr.hdc, GETPHYSPAGESIZE, 0, NULL, &pt) > 0)
  2394. {
  2395. const LONG xPerInch = GetDeviceCaps(fr.hdc, LOGPIXELSX);
  2396. const LONG yPerInch = GetDeviceCaps(fr.hdc, LOGPIXELSY);
  2397. rc.left = rc.top = 0;
  2398. fr.rcPage.left = fr.rcPage.top = 0;
  2399. rc.right = (INT) ((pt.x * 1440l) / xPerInch);
  2400. fr.rcPage.right = rc.right;
  2401. // leave 1.25" (1800 twips) margins if that will leave >= 1"
  2402. if(rc.right >= 1800 + 1440 + 1800)
  2403. rc.right -= (rc.left = 1800);
  2404. rc.bottom = (INT) ((pt.y * 1440l) / yPerInch);
  2405. fr.rcPage.bottom = rc.bottom;
  2406. // leave 1" (1440 twips) margins if that will leave >= 1"
  2407. if(rc.bottom >= 1440 + 1440 + 1440)
  2408. rc.bottom -= (rc.top = 1440);
  2409. }
  2410. else
  2411. {
  2412. const LONG xPerInch = GetDeviceCaps(fr.hdc, LOGPIXELSX);
  2413. const LONG yPerInch = GetDeviceCaps(fr.hdc, LOGPIXELSY);
  2414. rc.left = rc.top = 0;
  2415. rc.right = (INT) ((GetDeviceCaps(fr.hdc, HORZRES) * 1440l) /
  2416. xPerInch);
  2417. rc.bottom = (INT) ((GetDeviceCaps(fr.hdc, VERTRES) * 1440l) /
  2418. yPerInch);
  2419. fr.rcPage = rc;
  2420. }
  2421. if(StartDoc(fr.hdc, &di) <= 0)
  2422. goto err;
  2423. // tell RichEdit not to erase before rendering text
  2424. SetBkMode(fr.hdc, TRANSPARENT);
  2425. fr.chrg.cpMin = 0;
  2426. fr.chrg.cpMost = cchText;
  2427. do
  2428. {
  2429. if(StartPage(fr.hdc) <= 0)
  2430. goto abort;
  2431. fr.rc = rc;
  2432. fr.chrg.cpMin = SendMessage(predoc->hwndRE, EM_FORMATRANGE,
  2433. (WPARAM) fTrue, (LPARAM) &fr);
  2434. if(EndPage(fr.hdc) <= 0)
  2435. goto abort;
  2436. } while(fr.chrg.cpMin > 0 && fr.chrg.cpMin < fr.chrg.cpMost);
  2437. if(fr.chrg.cpMin >= 0 && EndDoc(fr.hdc) > 0)
  2438. {
  2439. fr.chrg.cpMin = fr.chrg.cpMost = cchText;
  2440. // free up RichEdit's format range info
  2441. SendMessage(predoc->hwndRE, EM_FORMATRANGE, 0, 0);
  2442. (void) SetCursor(hcur);
  2443. return;
  2444. }
  2445. abort:
  2446. (void) AbortDoc(fr.hdc);
  2447. err:
  2448. fr.chrg.cpMin = fr.chrg.cpMost = cchText;
  2449. // free up RichEdit's format range info
  2450. SendMessage(predoc->hwndRE, EM_FORMATRANGE, 0, 0);
  2451. (void) SetCursor(hcur);
  2452. MessageBoxA(hwndMain, "An error occurred while printing", NULL,
  2453. MB_ICONSTOP | MB_OK);
  2454. }
  2455. LRESULT CALLBACK PPDlgProc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
  2456. {
  2457. PRINTPREVIEW * ppp = (PRINTPREVIEW *) GetWindowLong(hdlg, DWL_USER);
  2458. switch(msg)
  2459. {
  2460. case WM_INITDIALOG:
  2461. // hide the button we use to tell us where the top left is
  2462. ShowWindow(GetDlgItem(hdlg, PSB_TopLeft), SW_HIDE);
  2463. ppp = (PRINTPREVIEW *) GlobalAllocPtr(GHND, sizeof(PRINTPREVIEW));
  2464. SetWindowLong(hdlg, DWL_USER, (LONG) ppp);
  2465. if(!ppp)
  2466. {
  2467. MessageBoxA(hwndMain,
  2468. "Not enough memory for Print Preview window.",
  2469. NULL, MB_ICONSTOP | MB_OK);
  2470. EndDialog(hdlg, 0);
  2471. return 0;
  2472. }
  2473. ppp->hwndDlg = hdlg;
  2474. ppp->predoc = (REDOC *) lparam;
  2475. AssertSz(ppp->predoc, "print preview: no redoc");
  2476. ppp->cchText = -1;
  2477. ppp->ipage = -1;
  2478. PPChangePage(ppp, fFalse);
  2479. if(ppp->ipage < 0)
  2480. {
  2481. ppp->fDone = fTrue; // prevent any movement
  2482. // bail
  2483. PostMessage(hdlg, WM_CLOSE, 0, 0);
  2484. return 0;
  2485. }
  2486. return 1;
  2487. case WM_PAINT:
  2488. PPPaint(ppp);
  2489. break;
  2490. case WM_SIZE:
  2491. // cause complete redraw
  2492. InvalidateRect(hdlg, NULL, fTrue);
  2493. break;
  2494. #if defined(DEBUG) && defined(CLIPMETA)
  2495. case WM_LBUTTONDBLCLK:
  2496. if(ppp->hmf)
  2497. {
  2498. HMETAFILE hmf = 0;
  2499. HANDLE hMfp = 0;
  2500. METAFILEPICT *pmfp;
  2501. if(!OpenClipboard(hwndMain))
  2502. break;
  2503. EmptyClipboard();
  2504. hmf = CopyMetaFile(ppp->hmf, NULL);
  2505. if(!hmf)
  2506. {
  2507. MessageBeep(0);
  2508. break;
  2509. }
  2510. hMfp = GlobalAlloc(GHND | GMEM_DDESHARE, sizeof(METAFILEPICT));
  2511. if(!hMfp)
  2512. goto err;
  2513. pmfp = (METAFILEPICT *) GlobalLock(hMfp);
  2514. pmfp->mm = MM_ANISOTROPIC;
  2515. pmfp->xExt = (INT) ppp->dxPage;
  2516. pmfp->yExt = (INT) ppp->dyPage;
  2517. pmfp->hMF = hmf;
  2518. GlobalUnlock(hMfp);
  2519. SetClipboardData(CF_METAFILEPICT, hMfp);
  2520. CloseClipboard();
  2521. TraceTag(tagNull, "clipped");
  2522. break;
  2523. err:
  2524. if(hmf)
  2525. DeleteMetaFile(hmf);
  2526. if(hMfp)
  2527. GlobalFree(hMfp);
  2528. CloseClipboard();
  2529. }
  2530. break;
  2531. #endif // DEBUG && CLIPMETA
  2532. case WM_COMMAND:
  2533. switch(GET_WM_COMMAND_ID(wparam, lparam))
  2534. {
  2535. case PSB_NextPage:
  2536. PPChangePage(ppp, fFalse);
  2537. break;
  2538. case PSB_PrevPage:
  2539. PPChangePage(ppp, fTrue);
  2540. break;
  2541. case PSB_Close:
  2542. PostMessage(hdlg, WM_CLOSE, 0, 0);
  2543. break;
  2544. }
  2545. break;
  2546. case WM_CLOSE:
  2547. if(ppp)
  2548. {
  2549. // free up RichEdit's format range info
  2550. SendMessage(ppp->predoc->hwndRE, EM_FORMATRANGE, 0, 0);
  2551. #ifdef DEBUG
  2552. if(ppp->hmf)
  2553. DeleteMetaFile(ppp->hmf);
  2554. #endif // DEBUG
  2555. if(ppp->fr.hdc)
  2556. {
  2557. #ifndef NOBLIT
  2558. SelectObject(ppp->fr.hdc, ppp->hbmpOld);
  2559. #endif // !NOBLIT
  2560. DeleteDC(ppp->fr.hdc);
  2561. }
  2562. #ifndef NOBLIT
  2563. if(ppp->hbmp)
  2564. DeleteObject(ppp->hbmp);
  2565. #endif // !NOBLIT
  2566. if(ppp->fr.hdcTarget)
  2567. DeleteDC(ppp->fr.hdcTarget);
  2568. GlobalFreePtr(ppp);
  2569. }
  2570. SetWindowLong(hdlg, DWL_USER, 0);
  2571. EndDialog(hdlg, 0);
  2572. return 1;
  2573. }
  2574. return 0;
  2575. }
  2576. LOCAL BOOL FPPInit(PRINTPREVIEW *ppp)
  2577. {
  2578. LPDEVMODE pDevMode;
  2579. LPDEVNAMES pDevNames;
  2580. POINT pt;
  2581. #ifndef NOBLIT
  2582. ppp->hbmp = ppp->hbmpOld = 0;
  2583. #endif // !NOBLIT
  2584. ppp->fr.hdc = 0;
  2585. ppp->cchText = SendMessage(ppp->predoc->hwndRE, WM_GETTEXTLENGTH, 0, 0);
  2586. if(ppp->predoc->pd.lStructSize != sizeof(PRINTDLG))
  2587. {
  2588. MessageBoxA(hwndMain, "No printer selected.", NULL,
  2589. MB_ICONSTOP | MB_OK);
  2590. return fFalse;
  2591. }
  2592. ppp->cpage = 0;
  2593. ppp->ipage = -1; // first increment will display page 0
  2594. ppp->cpageMost = cpageChunk;
  2595. ppp->rgcpPages = (LONG *) GlobalAllocPtr(GHND, cpageChunk * sizeof(LONG));
  2596. if(!ppp->rgcpPages)
  2597. ppp->cpageMost = 0;
  2598. pDevMode = (LPDEVMODE) GlobalLock(ppp->predoc->pd.hDevMode);
  2599. pDevNames = (LPDEVNAMES) GlobalLock(ppp->predoc->pd.hDevNames);
  2600. ppp->fr.hdcTarget = CreateIC((LPTSTR) pDevNames + pDevNames->wDriverOffset,
  2601. (LPTSTR) pDevNames + pDevNames->wDeviceOffset,
  2602. (LPTSTR) pDevNames + pDevNames->wOutputOffset,
  2603. pDevMode);
  2604. GlobalUnlock(ppp->predoc->pd.hDevNames);
  2605. GlobalUnlock(ppp->predoc->pd.hDevMode);
  2606. if(!ppp->fr.hdcTarget)
  2607. goto err;
  2608. // does this matter?
  2609. SetMapMode(ppp->fr.hdcTarget, MM_TEXT);
  2610. if(Escape(ppp->fr.hdcTarget, GETPHYSPAGESIZE, 0, NULL, &pt) > 0)
  2611. {
  2612. const LONG xPerInch = GetDeviceCaps(ppp->fr.hdcTarget, LOGPIXELSX);
  2613. const LONG yPerInch = GetDeviceCaps(ppp->fr.hdcTarget, LOGPIXELSY);
  2614. ppp->rc.left = ppp->rc.top = 0;
  2615. ppp->dxPage = (pt.x * 1440l) / xPerInch;
  2616. ppp->rc.right = (INT) ppp->dxPage;
  2617. ppp->fr.rcPage.left = 0;
  2618. ppp->fr.rcPage.right = ppp->rc.right;
  2619. // leave 1.25" (1800 twips) margins if that will leave >= 1"
  2620. if(ppp->rc.right >= 1800 + 1440 + 1800)
  2621. ppp->rc.right -= (ppp->rc.left = 1800);
  2622. ppp->dyPage = (pt.y * 1440l) / yPerInch;
  2623. ppp->rc.bottom = (INT) ppp->dyPage;
  2624. ppp->fr.rcPage.top = 0;
  2625. ppp->fr.rcPage.bottom = ppp->rc.bottom;
  2626. // leave 1" (1440 twips) margins if that will leave >= 1"
  2627. if(ppp->rc.bottom >= 1440 + 1440 + 1440)
  2628. ppp->rc.bottom -= (ppp->rc.top = 1440);
  2629. }
  2630. else
  2631. {
  2632. const LONG xPerInch = GetDeviceCaps(ppp->fr.hdcTarget, LOGPIXELSX);
  2633. const LONG yPerInch = GetDeviceCaps(ppp->fr.hdcTarget, LOGPIXELSY);
  2634. const LONG dxRes = GetDeviceCaps(ppp->fr.hdcTarget, HORZRES);
  2635. const LONG dyRes = GetDeviceCaps(ppp->fr.hdcTarget, VERTRES);
  2636. ppp->rc.left = ppp->rc.top = 0;
  2637. ppp->dxPage = (dxRes * 1440l) / xPerInch;
  2638. ppp->rc.right = (INT) ppp->dxPage;
  2639. ppp->dyPage = (dyRes * 1440l) / yPerInch;
  2640. ppp->rc.bottom = (INT) ppp->dyPage;
  2641. ppp->fr.rcPage = ppp->rc;
  2642. }
  2643. PPInitDialogSize(ppp);
  2644. #ifdef DEBUG
  2645. if(!QueryCheck(ppp->predoc, IDM_PPMETA))
  2646. #endif // DEBUG
  2647. {
  2648. HDC hdcT;
  2649. #ifdef NOBLIT
  2650. hdcT = GetDC(ppp->hwndDlg);
  2651. ppp->fr.hdc = CreateCompatibleDC(hdcT);
  2652. ReleaseDC(ppp->hwndDlg, hdcT);
  2653. if(!ppp->fr.hdc)
  2654. goto err;
  2655. #else // NOBLIT
  2656. LONG xPerInch;
  2657. LONG yPerInch;
  2658. hdcT = GetDC(ppp->hwndDlg);
  2659. SaveDC(hdcT);
  2660. SetMapMode(hdcT, MM_TEXT);
  2661. xPerInch = GetDeviceCaps(hdcT, LOGPIXELSX);
  2662. yPerInch = GetDeviceCaps(hdcT, LOGPIXELSY);
  2663. ppp->dxBmp = (INT) ((ppp->dxPage * xPerInch) / 1440l);
  2664. ppp->dyBmp = (INT) ((ppp->dyPage * yPerInch) / 1440l);
  2665. ppp->fr.hdc = CreateCompatibleDC(hdcT);
  2666. ppp->hbmp = CreateCompatibleBitmap(hdcT, ppp->dxBmp, ppp->dyBmp);
  2667. RestoreDC(hdcT, -1);
  2668. ReleaseDC(ppp->hwndDlg, hdcT);
  2669. if(!ppp->fr.hdc)
  2670. {
  2671. if(ppp->hbmp)
  2672. DeleteObject(ppp->hbmp);
  2673. ppp->hbmp = 0;
  2674. goto err;
  2675. }
  2676. if(!ppp->hbmp)
  2677. goto err;
  2678. ppp->hbmpOld = SelectObject(ppp->fr.hdc, ppp->hbmp);
  2679. #endif // NOBLIT, else
  2680. SetMapMode(ppp->fr.hdc, MM_TEXT);
  2681. }
  2682. ppp->fr.chrg.cpMin = 0;
  2683. ppp->fr.chrg.cpMost = ppp->cchText;
  2684. return fTrue;
  2685. err:
  2686. if(ppp->fr.hdcTarget)
  2687. {
  2688. DeleteDC(ppp->fr.hdcTarget);
  2689. ppp->fr.hdcTarget = 0;
  2690. }
  2691. if(ppp->fr.hdc)
  2692. {
  2693. DeleteDC(ppp->fr.hdc);
  2694. ppp->fr.hdc = 0;
  2695. }
  2696. #ifndef NOBLIT
  2697. Assert(!ppp->hbmp);
  2698. Assert(!ppp->hbmpOld);
  2699. #endif // !NOBLIT
  2700. MessageBoxA(hwndMain,
  2701. "An error occurred while processing the print preview",
  2702. NULL, MB_ICONSTOP | MB_OK);
  2703. return fFalse;
  2704. }
  2705. LOCAL VOID PPInitDialogSize(PRINTPREVIEW *ppp)
  2706. {
  2707. LONG dx;
  2708. LONG dy;
  2709. LONG numer;
  2710. LONG denom;
  2711. RECT rc;
  2712. dx = GetSystemMetrics(SM_CXFULLSCREEN) - 2 * GetSystemMetrics(SM_CXBORDER);
  2713. dy = GetSystemMetrics(SM_CYFULLSCREEN) - 2 * GetSystemMetrics(SM_CYBORDER);
  2714. // select initial scale
  2715. if(dy * ppp->dxPage > dx * ppp->dyPage)
  2716. {
  2717. numer = dx;
  2718. denom = ppp->dxPage;
  2719. }
  2720. else
  2721. {
  2722. numer = dy;
  2723. denom = ppp->dyPage;
  2724. }
  2725. rc.top = 0;
  2726. rc.left = 0;
  2727. rc.bottom = (INT) ((numer * ppp->dyPage) / denom);
  2728. rc.right = (INT) ((numer * ppp->dxPage) / denom);
  2729. rc.right += 2 * GetSystemMetrics(SM_CXFRAME);
  2730. rc.bottom += GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME);
  2731. MoveWindow(ppp->hwndDlg, rc.left, rc.top, rc.right, rc.bottom, fTrue);
  2732. ShowWindow(ppp->hwndDlg, SW_SHOW);
  2733. }
  2734. LOCAL VOID PPChangePage(PRINTPREVIEW *ppp, BOOL fPrev)
  2735. {
  2736. HCURSOR hcur;
  2737. TCHAR szCaption[40];
  2738. if(ppp->cchText < 0 && !FPPInit(ppp))
  2739. return;
  2740. if(fPrev)
  2741. {
  2742. // no page before page zero or no page array so we can't go back
  2743. if(ppp->ipage <= 0 || !ppp->rgcpPages)
  2744. {
  2745. MessageBeep(0);
  2746. return;
  2747. }
  2748. Assert(ppp->ipage - 1 < ppp->cpage);
  2749. // backup a page
  2750. ppp->fr.chrg.cpMin = ppp->rgcpPages[ppp->ipage - 1];
  2751. }
  2752. else if(ppp->ipage + 1 >= ppp->cpage)
  2753. {
  2754. if(ppp->fDone)
  2755. {
  2756. MessageBeep(0);
  2757. return;
  2758. }
  2759. if(!ppp->rgcpPages)
  2760. goto doit;
  2761. if(ppp->ipage + 1 >= ppp->cpageMost)
  2762. {
  2763. LONG *pcp;
  2764. pcp = (LONG *) GlobalReAllocPtr(ppp->rgcpPages,
  2765. (ppp->cpageMost + cpageChunk) * sizeof(LONG), GHND);
  2766. if(!pcp)
  2767. {
  2768. GlobalFreePtr(ppp->rgcpPages);
  2769. ppp->rgcpPages = NULL;
  2770. ppp->cpage = ppp->cpageMost = 0;
  2771. goto doit;
  2772. }
  2773. ppp->rgcpPages = pcp;
  2774. ppp->cpageMost += cpageChunk;
  2775. }
  2776. ppp->cpage++;
  2777. ppp->rgcpPages[ppp->ipage + 1] = ppp->fr.chrg.cpMin;
  2778. }
  2779. doit:
  2780. hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  2781. #ifndef NOBLIT
  2782. if(ppp->fr.hdc)
  2783. {
  2784. RECT rc;
  2785. rc.top = rc.left = 0;
  2786. rc.bottom = ppp->dyBmp;
  2787. rc.right = ppp->dxBmp;
  2788. // erase the background
  2789. SetBkColor(ppp->fr.hdc, GetSysColor(COLOR_WINDOW));
  2790. ExtTextOut(ppp->fr.hdc, 0, 0, ETO_OPAQUE, &rc, "", 0, NULL);
  2791. // tell RichEdit not to bother erasing the background
  2792. SetBkMode(ppp->fr.hdc, TRANSPARENT);
  2793. }
  2794. #endif // !NOBLIT
  2795. #ifdef DEBUG
  2796. if(ppp->hmf)
  2797. {
  2798. // delete any metafile left around from the last page
  2799. DeleteMetaFile(ppp->hmf);
  2800. ppp->hmf = NULL;
  2801. }
  2802. if(QueryCheck(ppp->predoc, IDM_PPMETA))
  2803. {
  2804. AssertSz(!ppp->fr.hdc, "How'd that get there?");
  2805. ppp->fr.hdc = CreateMetaFile(NULL);
  2806. if(!ppp->fr.hdc)
  2807. goto err;
  2808. TraceTag(tagEnumMF, "Window Ext = %d, %d", ppp->dxPage, ppp->dyPage);
  2809. }
  2810. #endif // DEBUG
  2811. ppp->fr.rc = ppp->rc;
  2812. ppp->fr.chrg.cpMin = SendMessage(ppp->predoc->hwndRE, EM_FORMATRANGE,
  2813. (WPARAM) fTrue, (LPARAM) &ppp->fr);
  2814. if(!fPrev && ppp->fr.chrg.cpMin >= ppp->fr.chrg.cpMost)
  2815. {
  2816. // free up RichEdit's format range info
  2817. ppp->fr.chrg.cpMin = ppp->fr.chrg.cpMost = ppp->cchText;
  2818. SendMessage(ppp->predoc->hwndRE, EM_FORMATRANGE, 0, 0);
  2819. // setup for a prev
  2820. ppp->fr.chrg.cpMost = ppp->cchText;
  2821. // done with all pages, ppp->cpage is the max # of pages
  2822. ppp->fDone = fTrue;
  2823. }
  2824. #ifdef DEBUG
  2825. if(QueryCheck(ppp->predoc, IDM_PPMETA))
  2826. {
  2827. //$ REVIEW: what happens to ppp->fr.hdc if this fails?
  2828. ppp->hmf = CloseMetaFile(ppp->fr.hdc);
  2829. ppp->fr.hdc = 0;
  2830. if(!ppp->hmf)
  2831. goto err;
  2832. }
  2833. #endif // DEBUG
  2834. // update the current page number
  2835. ppp->ipage += fPrev ? -1 : 1;
  2836. EnableWindow(GetDlgItem(ppp->hwndDlg, PSB_PrevPage), ppp->ipage > 0);
  2837. EnableWindow(GetDlgItem(ppp->hwndDlg, PSB_NextPage),
  2838. !ppp->fDone || ppp->ipage + 1 < ppp->cpage);
  2839. wsprintf(szCaption, szFmtPrintPreview, ppp->ipage + 1);
  2840. SetWindowText(ppp->hwndDlg, szCaption);
  2841. // cause redraw
  2842. InvalidateRect(ppp->hwndDlg, NULL, fTrue);
  2843. (void) SetCursor(hcur);
  2844. return;
  2845. #ifdef DEBUG
  2846. err:
  2847. ppp->fDone = fTrue;
  2848. // free up RichEdit's format range info
  2849. ppp->fr.chrg.cpMin = ppp->fr.chrg.cpMost = ppp->cchText;
  2850. SendMessage(ppp->predoc->hwndRE, EM_FORMATRANGE, 0, 0);
  2851. // setup for a prev
  2852. ppp->fr.chrg.cpMost = ppp->cchText;
  2853. (void) SetCursor(hcur);
  2854. MessageBoxA(hwndMain,
  2855. "An error occurred while processing the print preview",
  2856. NULL, MB_ICONSTOP | MB_OK);
  2857. #endif // DEBUG
  2858. }
  2859. LOCAL VOID PPPaint(PRINTPREVIEW *ppp)
  2860. {
  2861. HDC hdc;
  2862. RECT rc;
  2863. RECT rcClient;
  2864. PAINTSTRUCT ps;
  2865. // if we're iconic, don't bother
  2866. if(IsIconic(ppp->hwndDlg))
  2867. return;
  2868. hdc = BeginPaint(ppp->hwndDlg, &ps);
  2869. SaveDC(hdc);
  2870. GetClientRect(ppp->hwndDlg, &rcClient);
  2871. GetWindowRect(GetDlgItem(ppp->hwndDlg, PSB_TopLeft), &rc);
  2872. MapWindowPoints(GetDesktopWindow(), ppp->hwndDlg, (LPPOINT) &rc, 2);
  2873. rc.bottom = rc.top + GetSystemMetrics(SM_CYBORDER);
  2874. rc.right = rcClient.right;
  2875. SetBkColor(hdc, GetSysColor(COLOR_WINDOWFRAME));
  2876. ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE, &rc, "", 0, NULL);
  2877. rc.top = rc.bottom;
  2878. rc.bottom = rcClient.bottom;
  2879. #ifdef DEBUG
  2880. if(ppp->hmf)
  2881. {
  2882. // erase the background
  2883. SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  2884. ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE, &rc, "", 0, NULL);
  2885. // make the window the same logical size as the page
  2886. SetMapMode(hdc, MM_ANISOTROPIC);
  2887. SetViewportOrgEx(hdc, rc.left, rc.top, NULL);
  2888. TraceTag(tagEnumMF, "Viewport Org = %d, %d", rc.left, rc.top);
  2889. SetViewportExtEx(hdc, rc.right - rc.left, rc.bottom - rc.top, NULL);
  2890. TraceTag(tagEnumMF, "Viewport Ext = %d, %d", rc.right - rc.left, rc.bottom - rc.top);
  2891. if(FFromTag(tagEnumMF))
  2892. EnumMetaFile(hdc, ppp->hmf, MFEnumCallback, 0);
  2893. PlayMetaFile(hdc, ppp->hmf);
  2894. }
  2895. else
  2896. #endif // DEBUG
  2897. if(ppp->ipage >= 0)
  2898. {
  2899. #ifdef NOBLIT
  2900. HDC hdcSave = ppp->fr.hdc;
  2901. LONG xPerInch = GetDeviceCaps(hdc, LOGPIXELSX);
  2902. LONG yPerInch = GetDeviceCaps(hdc, LOGPIXELSY);
  2903. // make the window the same logical size as the page
  2904. SetMapMode(hdc, MM_ANISOTROPIC);
  2905. SetWindowExtEx(hdc, (ppp->dxPage * xPerInch) / 1440,
  2906. (ppp->dyPage * yPerInch) / 1440, NULL);
  2907. SetViewportExtEx(hdc, rc.right - rc.left, rc.bottom - rc.top, NULL);
  2908. // erase the background
  2909. SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  2910. ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE, &rc, "", 0, NULL);
  2911. // tell RichEdit not to bother erasing the background
  2912. SetBkMode(hdc, TRANSPARENT);
  2913. ppp->fr.hdc = hdc;
  2914. ppp->fr.rc = ppp->rc;
  2915. ppp->fr.chrg.cpMin = ppp->rgcpPages[ppp->ipage];
  2916. ppp->fr.chrg.cpMin = SendMessage(ppp->predoc->hwndRE, EM_FORMATRANGE,
  2917. (WPARAM) fTrue, (LPARAM) &ppp->fr);
  2918. ppp->fr.hdc = hdcSave;
  2919. #else // NOBLIT
  2920. // convert RECT to x,y,dx,dy
  2921. rc.right -= rc.left;
  2922. rc.bottom -= rc.top;
  2923. StretchBlt(hdc, rc.left, rc.top, rc.right, rc.bottom,
  2924. ppp->fr.hdc, 0, 0, ppp->dxBmp, ppp->dyBmp, SRCCOPY);
  2925. #endif // NOBLIT, else
  2926. }
  2927. RestoreDC(hdc, -1);
  2928. EndPaint(ppp->hwndDlg, &ps);
  2929. }
  2930. #ifdef DEBUG
  2931. int CALLBACK MFEnumCallback(HDC hdc, HANDLETABLE *lpHTable, METARECORD *pmfr,
  2932. int nObj, LPARAM lparam)
  2933. {
  2934. switch(pmfr->rdFunction)
  2935. {
  2936. case META_SETWINDOWORG:
  2937. TraceTag(tagEnumMF, "SetWindowOrg(): %d, %d", (INT) (SHORT) pmfr->rdParm[1], (INT) (SHORT) pmfr->rdParm[0]);
  2938. break;
  2939. case META_SETVIEWPORTORG:
  2940. TraceTag(tagEnumMF, "SetViewportOrg(): %d, %d", (INT) (SHORT) pmfr->rdParm[1], (INT) (SHORT) pmfr->rdParm[0]);
  2941. break;
  2942. case META_OFFSETWINDOWORG:
  2943. TraceTag(tagEnumMF, "OffsetWindowOrg(): %d, %d", (INT) (SHORT) pmfr->rdParm[1], (INT) (SHORT) pmfr->rdParm[0]);
  2944. break;
  2945. case META_OFFSETVIEWPORTORG:
  2946. TraceTag(tagEnumMF, "OffsetViewportOrg(): %d, %d", (INT) (SHORT) pmfr->rdParm[1], (INT) (SHORT) pmfr->rdParm[0]);
  2947. break;
  2948. case META_SETWINDOWEXT:
  2949. TraceTag(tagEnumMF, "SetWindowExt(): %d, %d", (INT) (SHORT) pmfr->rdParm[1], (INT) (SHORT) pmfr->rdParm[0]);
  2950. break;
  2951. case META_SETVIEWPORTEXT:
  2952. TraceTag(tagEnumMF, "SetViewportExt(): %d, %d", (INT) (SHORT) pmfr->rdParm[1], (INT) (SHORT) pmfr->rdParm[0]);
  2953. break;
  2954. case META_SCALEWINDOWEXT:
  2955. TraceTag(tagEnumMF, "ScaleWindowExt(): %d, %d, %d, %d", (INT) (SHORT) pmfr->rdParm[3], (INT) (SHORT) pmfr->rdParm[2], (INT) (SHORT) pmfr->rdParm[1], (INT) (SHORT) pmfr->rdParm[0]);
  2956. break;
  2957. case META_SCALEVIEWPORTEXT:
  2958. TraceTag(tagEnumMF, "ScaleViewportExt(): %d, %d, %d, %d", (INT) (SHORT) pmfr->rdParm[3], (INT) (SHORT) pmfr->rdParm[2], (INT) (SHORT) pmfr->rdParm[1], (INT) (SHORT) pmfr->rdParm[0]);
  2959. break;
  2960. case META_SAVEDC:
  2961. TraceTag(tagEnumMF, "SaveDC()");
  2962. break;
  2963. case META_RESTOREDC:
  2964. TraceTag(tagEnumMF, "RestoreDC()");
  2965. break;
  2966. case META_SELECTPALETTE:
  2967. TraceTag(tagEnumMF, "Select Palette");
  2968. break;
  2969. case META_SETMAPMODE:
  2970. TraceTag(tagEnumMF, "SetMapMode(): %d", (INT) (SHORT) pmfr->rdParm[0]);
  2971. break;
  2972. case META_EXTTEXTOUT:
  2973. TraceTag(tagEnumMF, "ExtTextOut(): %d, %d", (INT) (SHORT) pmfr->rdParm[1], (INT) (SHORT) pmfr->rdParm[0]);
  2974. break;
  2975. case META_TEXTOUT:
  2976. TraceTag(tagEnumMF, "TextOut(): %d, %d", (INT) (SHORT) pmfr->rdParm[3], (INT) (SHORT) pmfr->rdParm[2]);
  2977. break;
  2978. case META_LINETO:
  2979. TraceTag(tagEnumMF, "LineTo(): %d, %d", (INT) (SHORT) pmfr->rdParm[1], (INT) (SHORT) pmfr->rdParm[0]);
  2980. break;
  2981. case META_RECTANGLE:
  2982. TraceTag(tagEnumMF, "Rectangle(): %d, %d, %d, %d", (INT) (SHORT) pmfr->rdParm[3], (INT) (SHORT) pmfr->rdParm[2], (INT) (SHORT) pmfr->rdParm[1], (INT) (SHORT) pmfr->rdParm[0]);
  2983. break;
  2984. }
  2985. return fTrue;
  2986. }
  2987. #endif // DEBUG
  2988. /*
  2989.  * I T P C A L L   I m p l e m e n t a t i o n
  2990.  */
  2991. /* 
  2992.  * ITPCALL_New
  2993.  *
  2994.  * Purpose:
  2995.  * Creates a new ITPCALL.
  2996.  *
  2997.  * Arguments:
  2998.  * REDOC * Pointer to the document information.
  2999.  *
  3000.  * Returns:
  3001.  * ITPCALL * The newly created ITPCALL.
  3002.  */
  3003. ITPCALL * ITPCALL_New(REDOC * predoc)
  3004. {
  3005. #ifndef NO_OLE
  3006. ITPCALL * pitpcall;
  3007. if(!(pitpcall = (ITPCALL *) GlobalAllocPtr(GHND, sizeof(ITPCALL))))
  3008. goto Error;
  3009. pitpcall->lpVtbl = &ITPCALL_Vtbl;
  3010. pitpcall->cRef = 1; // Start with one reference
  3011. pitpcall->predoc = predoc;
  3012. if(!(pitpcall->pipframe = ITPOLEINPLACEFRAME_New(predoc)))
  3013. GlobalFreePtr(pitpcall);
  3014. else
  3015. return pitpcall;
  3016. Error:
  3017. #endif // !NO_OLE
  3018. return NULL;
  3019. }
  3020. /*
  3021.  * ITPCALL_QueryInterface
  3022.  *
  3023.  * Purpose:
  3024.  * Returns a pointer to the specified site.
  3025.  *
  3026.  * Arguments:
  3027.  * LPUNKNOWN * Object from which we want an interface.
  3028.  * REFIID Interface we want.
  3029.  * LPUNKNOWN * Interface we return.
  3030.  *
  3031.  * Returns:
  3032.  * HRESULT  Error status.
  3033.  */
  3034. STDMETHODIMP ITPCALL_QueryInterface(LPUNKNOWN punk, REFIID riid, 
  3035.    LPUNKNOWN * ppvObj)
  3036. {
  3037. SCODE sc = S_OK;
  3038. if(IsEqualIID(riid, &IID_IUnknown))
  3039. ITPCALL_AddRef(*ppvObj = punk);
  3040. else if(IsEqualIID(riid, &IID_IRichEditOleCallback))
  3041. ITPCALL_AddRef(*ppvObj = punk);
  3042. else
  3043. sc = E_NOINTERFACE, *ppvObj = NULL;
  3044. return sc;
  3045. }
  3046. /*
  3047.  * ITPCALL_AddRef
  3048.  *
  3049.  * Purpose:
  3050.  * Increments reference count on the specified site.
  3051.  *
  3052.  * Arguments:
  3053.  * LPUNKNOWN * Object whose count we want to increment.
  3054.  *
  3055.  * Returns:
  3056.  * ULONG New value of reference count.
  3057.  */
  3058. STDMETHODIMP_(ULONG) ITPCALL_AddRef(LPUNKNOWN punk)
  3059. {
  3060. return ++PitpcallFromPunk(punk)->cRef;
  3061. }
  3062. /*
  3063.  * ITPCALL_Release
  3064.  *
  3065.  * Purpose:
  3066.  * Decrements reference count on the specified site.  If count is
  3067.  * decremented to zero, the object is freed.
  3068.  *
  3069.  * Arguments:
  3070.  * LPUNKNOWN * Object whose count we want to decrement.
  3071.  *
  3072.  * Returns:
  3073.  * ULONG New value of reference count.
  3074.  */
  3075. STDMETHODIMP_(ULONG) ITPCALL_Release(LPUNKNOWN punk)
  3076. {
  3077. #ifndef NO_OLE
  3078. ITPCALL * pitpcall = PitpcallFromPunk(punk);
  3079. ULONG cRef = --pitpcall->cRef;
  3080. if(!cRef)
  3081. {
  3082. // Free stuff we own
  3083. if(pitpcall->pipframe)
  3084. {
  3085. pitpcall->pipframe->lpVtbl->Release((LPOLEINPLACEFRAME) 
  3086.  pitpcall->pipframe);
  3087. }
  3088. // Free memory allocated for us
  3089. GlobalFreePtr(pitpcall);
  3090. TraceTag(tagITPCALL, "ITPCALL_Release: freeing the itpcall");
  3091. }
  3092. AssertSz(cRef >= 0, "ITPCALL_Release: negative cRef");
  3093. return cRef;
  3094. #endif // !NO_OLE
  3095. return (ULONG) NULL;
  3096. }
  3097. /*
  3098.  * ITPCALL_GetNewStorage
  3099.  *
  3100.  * Purpose:
  3101.  * Gets storage for a new object.
  3102.  *
  3103.  * Arguments:
  3104.  * ITPCALL * Callback object.
  3105.  * LPSTORAGE FAR * Where to return storage.
  3106.  *
  3107.  * Returns:
  3108.  * HRESULT Error status.
  3109.  */
  3110. STDMETHODIMP ITPCALL_GetNewStorage(ITPCALL * pitpcall, LPSTORAGE FAR * ppstg)
  3111. {
  3112. SCODE sc = S_OK;
  3113. WCHAR szItemW[OLEUI_CCHPATHMAX];
  3114. wsprintfW(szItemW, L"REOBJ%ld", ++pitpcall->predoc->cItem);
  3115. if(!(*ppstg = OleStdCreateChildStorage(pitpcall->predoc->pstg, szItemW)))
  3116. {
  3117. MessageBoxW(hwndMain, szItemW, L"No item storage!", MB_OK);
  3118. sc = E_FAIL;
  3119. }
  3120. return sc;
  3121. }
  3122. /*
  3123.  * ITPCALL_GetInPlaceContext
  3124.  *
  3125.  * Purpose:
  3126.  * Gets context information for an in place object.
  3127.  *
  3128.  * Arguments:
  3129.  * ITPCALL * Callback object.
  3130.  * LPOLEINPLACEFRAME * Frame window object.
  3131.  * LPOLEINPLACEUIWINDOW * Document window object.
  3132.  * LPOLEINPLACEFRAMEINFO Frame window information.
  3133.  *
  3134.  * Returns:
  3135.  * HRESULT Error status.
  3136.  */
  3137. STDMETHODIMP ITPCALL_GetInPlaceContext(ITPCALL * pitpcall, 
  3138.    LPOLEINPLACEFRAME FAR * ppipframe,
  3139.    LPOLEINPLACEUIWINDOW FAR* ppipuiDoc,
  3140.    LPOLEINPLACEFRAMEINFO pipfinfo)
  3141. {
  3142. #ifndef NO_OLE
  3143. // Return window pointers
  3144. *ppipframe = (LPOLEINPLACEFRAME) pitpcall->pipframe;
  3145. (VOID) (*ppipframe)->lpVtbl->AddRef(*ppipframe);
  3146. *ppipuiDoc = NULL;
  3147. // Fill in frame window information
  3148. pipfinfo->cb = sizeof(OLEINPLACEFRAMEINFO);
  3149. pipfinfo->fMDIApp = FALSE;
  3150. pipfinfo->hwndFrame = pitpcall->predoc->hwndParent;
  3151. pipfinfo->haccel = (long) NULL;
  3152. pipfinfo->cAccelEntries = 0;
  3153. #endif // !NO_OLE
  3154. return S_OK;
  3155. }
  3156. /*
  3157.  * ITPCALL_ShowContainerUI
  3158.  *
  3159.  * Purpose:
  3160.  * Displays or hides REITP's container UI.
  3161.  *
  3162.  * Arguments:
  3163.  * ITPCALL * Callback object.
  3164.  * BOOL
  3165.  *
  3166.  * Returns:
  3167.  * HRESULT Error status.
  3168.  */
  3169. STDMETHODIMP ITPCALL_ShowContainerUI(ITPCALL * pitpcall, BOOL fShow)
  3170. {
  3171. TraceTag(tagITPCALL, "ITPCALL_ShowContainerUI(%d)", fShow);
  3172. // If we're displaying our UI, show our menus
  3173. if(fShow)
  3174. ITPOLEINPLACEFRAME_SetMenu(pitpcall->pipframe, NULL, NULL, NULL);
  3175. return S_OK;
  3176. }
  3177. STDMETHODIMP ITPCALL_QueryInsertObject(ITPCALL * pitpcall, LPCLSID pclsid,
  3178. LPSTORAGE pstg, LONG cp)
  3179. {
  3180. #if !defined(NO_OLE) && defined(DEBUG)
  3181. LPTSTR szProgID;
  3182. if(HrProgIDFromCLSIDA(pclsid, &szProgID))
  3183. {
  3184. TraceTag(tagITPCALL, "QueryInsertObject(): unknown class id");
  3185. }
  3186. else
  3187. {
  3188. SCODE sc = S_OK;
  3189. TraceTag(tagITPCALL, "QueryInsertObject(): %s object", szProgID);
  3190. if(QueryCheck(pitpcall->predoc, IDM_REFUSEGRAPH) &&
  3191. !lstrcmpi(szProgID, "MSGraph"))
  3192. {
  3193. TraceTag(tagITPCALL, "Refusing object");
  3194. sc = S_FALSE;
  3195. }
  3196. OleStdFreeString((LPSTR) szProgID, NULL);
  3197. return sc;
  3198. }
  3199. #endif // !NO_OLE && DEBUG
  3200. return NOERROR;
  3201. }
  3202. STDMETHODIMP ITPCALL_DeleteObject(ITPCALL * pitpcall, LPOLEOBJECT poleobj)
  3203. {
  3204. TraceTag(tagITPCALL, "DeleteObject()");
  3205. return NOERROR;
  3206. }
  3207. STDMETHODIMP ITPCALL_QueryAcceptData(ITPCALL * pitpcall, LPDATAOBJECT pdataobj,
  3208. CLIPFORMAT *pcfFormat, DWORD reco, BOOL fReally,
  3209. HGLOBAL hMetaPict)
  3210. {
  3211. #if !defined(NO_OLE) && defined(DEBUG)
  3212. TraceTag(tagITPCALL, "QueryAcceptData(%s) for %s", fReally ? "really" : "test", (reco == RECO_DROP ? "drop" : (reco == RECO_PASTE ? "paste" : "unknown op")));
  3213. if(pitpcall->predoc->fReadOnly)
  3214. {
  3215. BOOL fDoIt = fFalse;
  3216. HRESULT hr;
  3217. switch(reco)
  3218. {
  3219. case RECO_DROP:
  3220. fDoIt = QueryCheck(pitpcall->predoc, IDM_ENABLEDRAGREADONLY);
  3221. break;
  3222. case RECO_PASTE:
  3223. fDoIt = QueryCheck(pitpcall->predoc, IDM_ENABLEPASTEREADONLY);
  3224. break;
  3225. default:
  3226. TraceTag(tagNull, "QAD: invalid RECO %lx", reco);
  3227. AssertSz(fFalse, "QAD: invalid RECO");
  3228. break;
  3229. }
  3230. if(fDoIt)
  3231. {
  3232. if(fReally)
  3233. {
  3234. LPRICHEDITOLE const preole = pitpcall->predoc->preole;
  3235. // import that sucker
  3236. hr = preole->lpVtbl->ImportDataObject(preole, pdataobj,
  3237. *pcfFormat, hMetaPict);
  3238. TraceError("IRichEditOle::ImportDataObject", hr);
  3239. if(SUCCEEDED(hr))
  3240. hr = S_FALSE; // we did it ourselves
  3241. }
  3242. else
  3243. {
  3244. // return that we'll import it ourselves
  3245. hr = S_FALSE;
  3246. }
  3247. }
  3248. else
  3249. {
  3250. hr = E_FAIL;
  3251. }
  3252. TraceError("IPCALL_QueryAcceptData", hr);
  3253. return hr;
  3254. }
  3255. if(QueryCheck(pitpcall->predoc, IDM_TEXTONLY))
  3256. {
  3257. TraceTag(tagITPCALL, "QueryAcceptData(): asking for text only");
  3258. *pcfFormat = CF_TEXT; // accept only text
  3259. }
  3260. else
  3261. {
  3262. TraceTag(tagITPCALL, "QueryAcceptData(): delegating back to RichEdit");
  3263. }
  3264. #endif // !NO_OLE && DEBUG
  3265. return NOERROR;
  3266. }
  3267. STDMETHODIMP ITPCALL_ContextSensitiveHelp(ITPCALL * pitpcall, BOOL fEnterMode)
  3268. {
  3269. return NOERROR;
  3270. }
  3271. STDMETHODIMP ITPCALL_GetClipboardData(ITPCALL *pitpcall, CHARRANGE *pchrg,
  3272. DWORD reco, LPDATAOBJECT *ppdataobj)
  3273. {
  3274. #if !defined(NO_OLE) && defined(DEBUG)
  3275. TraceTag(tagITPCALL, "GetClipboardData(%d-%d) for %s", pchrg->cpMin, pchrg->cpMost, reco == RECO_COPY ? "copy" : (reco == RECO_CUT ? "cut" : (reco == RECO_DRAG ? "drag" : "unknown op")));
  3276. if(pitpcall->predoc->fReadOnly)
  3277. {
  3278. BOOL fDoIt = fFalse;
  3279. switch(reco)
  3280. {
  3281. case RECO_COPY:
  3282. // prevent assert in default case
  3283. break;
  3284. case RECO_CUT:
  3285. fDoIt = QueryCheck(pitpcall->predoc, IDM_ENABLECUTREADONLY);
  3286. break;
  3287. case RECO_DRAG:
  3288. fDoIt = QueryCheck(pitpcall->predoc, IDM_ENABLEDRAGREADONLY);
  3289. break;
  3290. default:
  3291. TraceTag(tagNull, "GCD: invalid RECO %lx", reco);
  3292. AssertSz(fFalse, "GCD: invalid RECO");
  3293. break;
  3294. }
  3295. if(fDoIt)
  3296. {
  3297. LPRICHEDITOLE const preole = pitpcall->predoc->preole;
  3298. HRESULT hr;
  3299. // delegate to IRichEditOle::GetClipboardData()
  3300. *ppdataobj = NULL;
  3301. hr = preole->lpVtbl->GetClipboardData(preole, pchrg, reco,
  3302. ppdataobj);
  3303. TraceError("IRichEditOle::GetClipboardData", hr);
  3304. if(SUCCEEDED(hr) && *ppdataobj)
  3305. hr = S_FALSE; // we did it ourselves
  3306. TraceError("IPCALL_GetClipboardData", hr);
  3307. return hr;
  3308. }
  3309. // go return E_NOTIMPL & let RichEdit deal with it itself
  3310. }
  3311. #endif // !NO_OLE && DEBUG
  3312. // *ppdataobj isn't used if E_NOTIMPL is returned
  3313. // so we don't need to set it
  3314. // tell RichEdit to do it itself
  3315. TraceTag(tagITPCALL, "GetClipboardData(): delegating back to RichEdit");
  3316. return E_NOTIMPL;
  3317. }
  3318. STDMETHODIMP ITPCALL_GetDragDropEffect(ITPCALL *pitpcall, BOOL fDrag,
  3319. DWORD grfKeyState, LPDWORD pdwEffect)
  3320. {
  3321. TraceTag(tagITPCALL, "GetDragDropEffect(%s)", fDrag ? "drag" : "drop");
  3322. #ifdef DEBUG
  3323. if(QueryCheck(pitpcall->predoc, IDM_SWAPDRAGEFFECT))
  3324. {
  3325. DWORD dwT;
  3326. // strip off move, copy, and link
  3327. dwT = *pdwEffect &
  3328. ~(DWORD) (DROPEFFECT_MOVE | DROPEFFECT_COPY | DROPEFFECT_LINK);
  3329. if(!pitpcall->predoc->fReadOnly ||
  3330. QueryCheck(pitpcall->predoc, IDM_ENABLEDRAGREADONLY))
  3331. {
  3332. if(fDrag)
  3333. dwT = DROPEFFECT_MOVE | DROPEFFECT_COPY;
  3334. else if(grfKeyState & MK_CONTROL)
  3335. dwT = DROPEFFECT_MOVE;
  3336. else
  3337. dwT = DROPEFFECT_COPY;
  3338. }
  3339. *pdwEffect = dwT;
  3340. return NOERROR;
  3341. }
  3342. #endif // DEBUG
  3343. // delegate back to RichEdit
  3344. return E_NOTIMPL;
  3345. }
  3346. STDMETHODIMP ITPCALL_GetContextMenu(ITPCALL *pitpcall, WORD seltype,
  3347. LPOLEOBJECT poleobj, CHARRANGE * pchrg, HMENU * phmenu)
  3348. {
  3349. HMENU hmenu;
  3350. HMENU hmenuParent = NULL;
  3351. HMENU hmenuVerbs = NULL;
  3352. UINT uiT;
  3353. TraceTag(tagITPCALL, "GetContextMenu");
  3354. hmenuParent = CreatePopupMenu();
  3355. if(!hmenuParent)
  3356. goto Cleanup;
  3357. // Put the verbs on the menu
  3358. if(poleobj)
  3359. {
  3360. OleUIAddVerbMenu(poleobj, NULL, hmenuParent, 0, IDM_OBJECTMIN, 
  3361. 0, TRUE, IDM_OBJECTCONVERT, &hmenuVerbs);
  3362. }
  3363. // Determine which menu to pass back to RichEdit
  3364. *phmenu = hmenu = hmenuVerbs ? hmenuVerbs : hmenuParent;
  3365. if(poleobj)
  3366. AppendMenu(hmenu, MF_SEPARATOR, 0, NULL);
  3367. // Add the cut, copy, paste verbs
  3368. uiT = MF_STRING | MF_BYCOMMAND;
  3369. uiT |= pchrg->cpMin == pchrg->cpMost ? uiMFDisabled : uiMFEnabled;
  3370. AppendMenu(hmenu, uiT, IDM_CUT, "Cut");
  3371. AppendMenu(hmenu, uiT, IDM_COPY, "Copy");
  3372. uiT = MF_STRING | MF_BYCOMMAND;
  3373. uiT |= SendMessage(pitpcall->predoc->hwndRE, EM_CANPASTE, 0, 0)
  3374. ? uiMFEnabled : uiMFDisabled;
  3375. AppendMenu(hmenu, uiT, IDM_PASTE, "Paste");
  3376. Cleanup:
  3377. if(hmenu == hmenuVerbs && hmenuParent)
  3378. DestroyMenu(hmenuParent);
  3379. else if(hmenu == hmenuParent && hmenuVerbs)
  3380. DestroyMenu(hmenuVerbs);
  3381. return S_OK;
  3382. }
  3383. /*
  3384.  * I T P O L E I N P L A C E F R A M E  I m p l e m e n t a t i o n
  3385.  */
  3386. /* 
  3387.  * ITPOLEINPLACEFRAME_New
  3388.  *
  3389.  * Purpose:
  3390.  * Creates a new ITPOLEINPLACEFRAME.
  3391.  *
  3392.  * Arguments:
  3393.  * REDOC * Pointer to the document information.
  3394.  *
  3395.  * Returns:
  3396.  * ITPOLEINPLACEFRAME * The newly created ITPOLEINPLACEFRAME.
  3397.  */
  3398. ITPOLEINPLACEFRAME * ITPOLEINPLACEFRAME_New(REDOC * predoc)
  3399. {
  3400. #ifndef NO_OLE
  3401. ITPOLEINPLACEFRAME * pipframe;
  3402. if(!(pipframe = (ITPOLEINPLACEFRAME *) GlobalAllocPtr(GHND, sizeof(ITPOLEINPLACEFRAME))))
  3403. return NULL;
  3404. pipframe->lpVtbl = &ITPOLEINPLACEFRAME_Vtbl;
  3405. pipframe->cRef = 1; // Start with one reference
  3406. pipframe->predoc = predoc;
  3407. return pipframe;
  3408. #endif // !NO_OLE
  3409. return NULL;
  3410. }
  3411. /*
  3412.  * ITPOLEINPLACEFRAME_QueryInterface
  3413.  *
  3414.  * Purpose:
  3415.  * Returns a pointer to the specified site.
  3416.  *
  3417.  * Arguments:
  3418.  * LPUNKNOWN * Object from which we want an interface.
  3419.  * REFIID Interface we want.
  3420.  * LPUNKNOWN * Interface we return.
  3421.  *
  3422.  * Returns:
  3423.  * HRESULT Error status.
  3424.  */
  3425. STDMETHODIMP ITPOLEINPLACEFRAME_QueryInterface(LPUNKNOWN punk, REFIID riid, 
  3426.    LPUNKNOWN * ppvObj)
  3427. {
  3428. SCODE sc = S_OK;
  3429. if(IsEqualIID(riid, &IID_IUnknown) ||
  3430. IsEqualIID(riid, &IID_IOleWindow) ||
  3431. IsEqualIID(riid, &IID_IOleInPlaceUIWindow) ||
  3432. IsEqualIID(riid, &IID_IOleInPlaceFrame))
  3433. {
  3434. ITPOLEINPLACEFRAME_AddRef(*ppvObj = punk);
  3435. }
  3436. else
  3437. {
  3438. sc = E_NOINTERFACE, *ppvObj = NULL;
  3439. }
  3440. return sc;
  3441. }
  3442. /*
  3443.  * ITPOLEINPLACEFRAME_AddRef
  3444.  *
  3445.  * Purpose:
  3446.  * Increments reference count on the specified site.
  3447.  *
  3448.  * Arguments:
  3449.  * LPUNKNOWN * Object whose count we want to increment.
  3450.  *
  3451.  * Returns:
  3452.  * ULONG New value of reference count.
  3453.  */
  3454. STDMETHODIMP_(ULONG) ITPOLEINPLACEFRAME_AddRef(LPUNKNOWN punk)
  3455. {
  3456. return ++PipframeFromPunk(punk)->cRef;
  3457. }
  3458. /*
  3459.  * ITPOLEINPLACEFRAME_Release
  3460.  *
  3461.  * Purpose:
  3462.  * Decrements reference count on the specified site.  If count is
  3463.  * decremented to zero, the object is freed.
  3464.  *
  3465.  * Arguments:
  3466.  * LPUNKNOWN * Object whose count we want to decrement.
  3467.  *
  3468.  * Returns:
  3469.  * ULONG New value of reference count.
  3470.  */
  3471. STDMETHODIMP_(ULONG) ITPOLEINPLACEFRAME_Release(LPUNKNOWN punk)
  3472. {
  3473. ITPOLEINPLACEFRAME * pipframe = PipframeFromPunk(punk);
  3474. ULONG cRef = --pipframe->cRef;
  3475. if(!cRef)
  3476. {
  3477. // Free memory allocated for us
  3478. GlobalFreePtr(pipframe);
  3479. TraceTag(tagInPlace, "ITPOLEINPLACEFRAME_Release: freeing the ipframe");
  3480. }
  3481. AssertSz(cRef >= 0, "ITPOLEINPLACEFRAME_Release: negative cRef");
  3482. return cRef;
  3483. }
  3484. /*
  3485.  * ITPOLEINPLACEFRAME_GetWindow
  3486.  *
  3487.  * Purpose:
  3488.  * Return the window handle of the app-level window for in place use.
  3489.  *
  3490.  * Arguments:
  3491.  * ITPOLEINPLACESITE * Client site.
  3492.  *
  3493.  * Returns:
  3494.  * HRESULT Error status.
  3495.  */
  3496. STDMETHODIMP ITPOLEINPLACEFRAME_GetWindow(ITPOLEINPLACEFRAME * pipframe,
  3497.   HWND * phwnd)
  3498. {
  3499. TraceTag(tagInPlace, "ITPOLEINPLACEFRAME_GetWindow: NYI");
  3500. return E_NOTIMPL;
  3501. }
  3502. /*
  3503.  * ITPOLEINPLACEFRAME_ContextSensitiveHelp
  3504.  *
  3505.  * Purpose:
  3506.  * Notifies the frame that the object has entered Context Help mode.
  3507.  *
  3508.  * Arguments:
  3509.  * ITPOLEINPLACESITE * Client site.
  3510.  *
  3511.  * Returns:
  3512.  * HRESULT Error status.
  3513.  */
  3514. STDMETHODIMP ITPOLEINPLACEFRAME_ContextSensitiveHelp(ITPOLEINPLACEFRAME *pipframe,
  3515.  BOOL fEnterMode)
  3516. {
  3517. TraceTag(tagInPlace, "ITPOLEINPLACEFRAME_ContextSensitiveHelp: NYI");
  3518. TraceError("ITPOLEINPLACEFRAME_ContextSensitiveHelp()", E_NOTIMPL);
  3519. return E_NOTIMPL;
  3520. }
  3521. /*
  3522.  * ITPOLEINPLACEFRAME_GetBorder
  3523.  *
  3524.  * Purpose:
  3525.  * Returns a RECT structure in which the object can put toolbars and 
  3526.  * similar controls while an object is active in place.
  3527.  *
  3528.  * Arguments:
  3529.  * ITPOLEINPLACESITE * Client site.
  3530.  *
  3531.  * Returns:
  3532.  * HRESULT Error status.
  3533.  */
  3534. STDMETHODIMP ITPOLEINPLACEFRAME_GetBorder(ITPOLEINPLACEFRAME * pipframe,
  3535.   LPRECT prcBorder)
  3536. {
  3537. TraceTag(tagInPlace, "ITPOLEINPLACEFRAME_GetBorder: NYI");
  3538. TraceError("ITPOLEINPLACEFRAME_GetBorder()", E_NOTIMPL);
  3539. return E_NOTIMPL;
  3540. }
  3541. /*
  3542.  * ITPOLEINPLACEFRAME_RequestBorderSpace
  3543.  *
  3544.  * Purpose:
  3545.  * Determines whether tools can be installed around the objects 
  3546.  * window frame while the object is active in place.
  3547.  *
  3548.  * Arguments:
  3549.  * ITPOLEINPLACESITE * Client site.
  3550.  *
  3551.  * Returns:
  3552.  * HRESULT Error status.
  3553.  */
  3554. STDMETHODIMP ITPOLEINPLACEFRAME_RequestBorderSpace(ITPOLEINPLACEFRAME * pipframe,
  3555.    LPCBORDERWIDTHS pbw)
  3556. {
  3557. TraceTag(tagInPlace, "ITPOLEINPLACEFRAME_RequestBorderSpace: NYI");
  3558. TraceError("ITPOLEINPLACEFRAME_RequestBorderSpace()", E_NOTIMPL);
  3559. return E_NOTIMPL;
  3560. }
  3561. /*
  3562.  * ITPOLEINPLACEFRAME_SetBorderSpace
  3563.  *
  3564.  * Purpose:
  3565.  * Allocates space for the border requested in the call to the 
  3566.  * RequestBorderSpace member function.
  3567.  *
  3568.  * Arguments:
  3569.  * ITPOLEINPLACESITE * Client site.
  3570.  *
  3571.  * Returns:
  3572.  * HRESULT Error status.
  3573.  */
  3574. STDMETHODIMP ITPOLEINPLACEFRAME_SetBorderSpace(ITPOLEINPLACEFRAME * pipframe,
  3575.    LPCBORDERWIDTHS pbw)
  3576. {
  3577. //$ FUTURE: If NULL, then put our tools back
  3578. TraceTag(tagInPlace, "ITPOLEINPLACEFRAME_SetBorderSpace: NYI");
  3579. TraceError("ITPOLEINPLACEFRAME_SetBorderSpace()", E_NOTIMPL);
  3580. return E_NOTIMPL;
  3581. }
  3582. /*
  3583.  * ITPOLEINPLACEFRAME_SetActiveObject
  3584.  *
  3585.  * Purpose:
  3586.  * Called by the object to provide the frame window a direct channel 
  3587.  * of communication with the active in-place object.
  3588.  *
  3589.  * Arguments:
  3590.  * ITPOLEINPLACESITE * Client site.
  3591.  *
  3592.  * Returns:
  3593.  * HRESULT Error status.
  3594.  */
  3595. STDMETHODIMP ITPOLEINPLACEFRAME_SetActiveObject(ITPOLEINPLACEFRAME * pipframe,
  3596.     LPOLEINPLACEACTIVEOBJECT pipaobj,
  3597.     LPCSTR szObjName)
  3598. {
  3599. #ifndef NO_OLE
  3600. // Free any existing active object
  3601. if(pipframe->pipaobj)
  3602. pipframe->pipaobj->lpVtbl->Release(pipframe->pipaobj);
  3603. // If we're given an object, AddRef it; update our remembered ipaobj
  3604. if(pipaobj)
  3605. pipaobj->lpVtbl->AddRef(pipaobj);
  3606. pipframe->pipaobj = pipaobj;
  3607. TraceTag(tagInPlace, "ITPOLEINPLACEFRAME_SetActiveObject: %s", szObjName ? szObjName : "NULL");
  3608. #endif // !NO_OLE
  3609. return S_OK;
  3610. }
  3611. /*
  3612.  * ITPOLEINPLACEFRAME_InsertMenus
  3613.  *
  3614.  * Purpose:
  3615.  * Called by the object server to allow the container to insert 
  3616.  * its menu groups in the composite menu that will be used during
  3617.  * the in-place session.
  3618.  *
  3619.  * Arguments:
  3620.  * ITPOLEINPLACESITE * Client site.
  3621.  *
  3622.  * Returns:
  3623.  * HRESULT Error status.
  3624.  */
  3625. STDMETHODIMP ITPOLEINPLACEFRAME_InsertMenus(ITPOLEINPLACEFRAME * pipframe,
  3626.     HMENU hmenuShared, 
  3627.     LPOLEMENUGROUPWIDTHS pmgw)
  3628. {
  3629. //$ FUTURE: Do something interesting here
  3630. // Don't actually put any menus on right now
  3631. pmgw->width[0] = pmgw->width[2] = pmgw->width[4] = 0;
  3632. TraceTag(tagInPlace, "ITPOLEINPLACEFRAME_InsertMenus: S_OK");
  3633. return S_OK;
  3634. }
  3635. /*
  3636.  * ITPOLEINPLACEFRAME_SetMenu
  3637.  *
  3638.  * Purpose:
  3639.  * Installs the composite menu into the window frame containing
  3640.  * the object that is being activated in place.
  3641.  *
  3642.  * Arguments:
  3643.  * ITPOLEINPLACESITE * Client site.
  3644.  *
  3645.  * Returns:
  3646.  * HRESULT Error status.
  3647.  */
  3648. STDMETHODIMP ITPOLEINPLACEFRAME_SetMenu(ITPOLEINPLACEFRAME * pipframe, 
  3649.     HMENU hmenuShared, HOLEMENU holemenu, 
  3650.     HWND hwndActiveObject)
  3651. {
  3652. #ifndef NO_OLE
  3653. HWND hwnd = pipframe->predoc->hwndParent;
  3654. TraceTag(tagInPlace, "ITPOLEINPLACEFRAME_SetMenu: hMenuShared=%08lx holemenu=%08lx", (DWORD) (LPVOID) hmenuShared, (DWORD) (LPVOID) holemenu);
  3655. // Did OLE give us a menu, or leave us to ourselves?
  3656. if(hmenuShared && holemenu)
  3657. {
  3658. // Put the merged menu OLE gave us on our menu bar
  3659. SetMenu(hwnd, hmenuShared);
  3660. }
  3661. else
  3662. {
  3663. // Put our regular menu on the menu bar
  3664. SetMenu(hwnd, hmenuFull);
  3665. SetupWordWrapMenu(pipframe->predoc);
  3666. }
  3667. DrawMenuBar(hwnd);
  3668. # ifdef MAC
  3669. DebugStr("pTry calling OleSetMenuDescriptor()");
  3670. # else // MAC
  3671. // Pass the menu descriptor to OLE
  3672. return OleSetMenuDescriptor(holemenu, pipframe->predoc->hwndParent, 
  3673. hwndActiveObject, (LPOLEINPLACEFRAME) pipframe,
  3674. pipframe->pipaobj);
  3675. # endif // MAC, else
  3676. #endif // !NO_OLE
  3677. return S_OK;
  3678. }
  3679. /*
  3680.  * ITPOLEINPLACEFRAME_RemoveMenus
  3681.  *
  3682.  * Purpose:
  3683.  * Called by the object server to give the container a chance to 
  3684.  * remove its menu elements from the in-place composite menu.
  3685.  *
  3686.  * Arguments:
  3687.  * ITPOLEINPLACESITE * Client site.
  3688.  *
  3689.  * Returns:
  3690.  * HRESULT Error status.
  3691.  */
  3692. STDMETHODIMP ITPOLEINPLACEFRAME_RemoveMenus(ITPOLEINPLACEFRAME * pipframe, 
  3693.     HMENU hmenuShared)
  3694. {
  3695. // We didn't put any menus on!
  3696. TraceTag(tagInPlace, "ITPOLEINPLACEFRAME_RemoveMenus: S_OK");
  3697. return S_OK;
  3698. }
  3699. /*
  3700.  * ITPOLEINPLACEFRAME_SetStatusText
  3701.  *
  3702.  * Purpose:
  3703.  * Sets and displays status text about the in-place object in the
  3704.  * containers frame window status line.
  3705.  *
  3706.  * Arguments:
  3707.  * ITPOLEINPLACESITE * Client site.
  3708.  *
  3709.  * Returns:
  3710.  * HRESULT Error status.
  3711.  */
  3712. STDMETHODIMP ITPOLEINPLACEFRAME_SetStatusText(ITPOLEINPLACEFRAME * pipframe, 
  3713.   LPCSTR szStatusText)
  3714. {
  3715. TraceTag(tagInPlace, "ITPOLEINPLACEFRAME_SetStatusText: NYI");
  3716. TraceError("ITPOLEINPLACEFRAME_SetStatusText()", E_NOTIMPL);
  3717. return E_NOTIMPL;
  3718. }
  3719. /*
  3720.  * ITPOLEINPLACEFRAME_EnableModeless
  3721.  *
  3722.  * Purpose:
  3723.  * Enables or disables modeless dialogs of the frame.
  3724.  *
  3725.  * Arguments:
  3726.  * ITPOLEINPLACESITE * Client site.
  3727.  *
  3728.  * Returns:
  3729.  * HRESULT Error status.
  3730.  */
  3731. STDMETHODIMP ITPOLEINPLACEFRAME_EnableModeless(ITPOLEINPLACEFRAME * pipframe, 
  3732.    BOOL fEnable)
  3733. {
  3734. TraceTag(tagInPlace, "ITPOLEINPLACEFRAME_EnableModeless: NYI");
  3735. TraceError("ITPOLEINPLACEFRAME_EnableModeless()", E_NOTIMPL);
  3736. return E_NOTIMPL;
  3737. }
  3738. /*
  3739.  * ITPOLEINPLACEFRAME_TranslateAccelerator
  3740.  *
  3741.  * Purpose:
  3742.  * Translates keystrokes intended for the container frame while
  3743.  * an object is active in place.
  3744.  *
  3745.  * Arguments:
  3746.  * ITPOLEINPLACESITE * Client site.
  3747.  *
  3748.  * Returns:
  3749.  * HRESULT Error status.
  3750.  */
  3751. STDMETHODIMP ITPOLEINPLACEFRAME_TranslateAccelerator(ITPOLEINPLACEFRAME *pipframe,
  3752.  LPMSG pmsg, WORD wID)
  3753. {
  3754. // REITP doesn't have any accelerators!
  3755. return S_FALSE;
  3756. }
  3757. LOCAL VOID FindReplace(REDOC *predoc, BOOL fReplace)
  3758. {
  3759. FINDREPLACE *pfr;
  3760. if(hwndFR)
  3761. return;
  3762. if(!(pfr = predoc->pfr))
  3763. {
  3764. pfr = predoc->pfr = (FINDREPLACE * ) GlobalAllocPtr(GHND,
  3765. sizeof(FINDREPLACE) + 2 * 80 * sizeof(TCHAR));
  3766. if(!predoc->pfr)
  3767. return;
  3768. }
  3769. else
  3770. {
  3771. memset(pfr, 0, sizeof(FINDREPLACE));
  3772. }
  3773. SendMessage(predoc->hwndRE, EM_HIDESELECTION, fFalse, fTrue);
  3774. pfr->lStructSize = sizeof(FINDREPLACE);
  3775. pfr->hwndOwner = predoc->hwndParent;
  3776. pfr->Flags = FR_HIDEUPDOWN;
  3777. pfr->lpstrFindWhat = (LPSTR) (((BYTE *) pfr) + sizeof(FINDREPLACE));
  3778. pfr->lpstrReplaceWith = pfr->lpstrFindWhat + 80;
  3779. pfr->wFindWhatLen = 80 * sizeof(TCHAR);
  3780. pfr->wReplaceWithLen = 80 * sizeof(TCHAR);
  3781. hwndFR = fReplace ? ReplaceText(pfr) : FindText(pfr);
  3782. }
  3783. LOCAL VOID ProcessFindReplace(REDOC *predoc, FINDREPLACE *pfr)
  3784. {
  3785. HCURSOR hcur;
  3786. LONG cszReplaced = 0;
  3787. LONG cpMatch;
  3788. CHARRANGE chrgSave;
  3789. FINDTEXTEX ft;
  3790. SendMessage(predoc->hwndRE, EM_EXGETSEL, 0, (LPARAM) &chrgSave);
  3791. ft.chrg.cpMost = -1; // search through end of the text
  3792. ft.chrg.cpMin = chrgSave.cpMin;
  3793. if(!(pfr->Flags & (FR_REPLACE | FR_REPLACEALL)))
  3794. ft.chrg.cpMin = chrgSave.cpMost;
  3795. ft.lpstrText = pfr->lpstrFindWhat;
  3796. if(pfr->Flags & FR_REPLACEALL)
  3797. {
  3798. hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  3799. SendMessage(predoc->hwndRE, EM_HIDESELECTION, fTrue, fFalse);
  3800. }
  3801. next:
  3802. cpMatch = SendMessage(predoc->hwndRE, EM_FINDTEXTEX,
  3803. (WPARAM) (pfr->Flags),
  3804. (LPARAM) &ft);
  3805. if(cpMatch < 0)
  3806. {
  3807. if(cszReplaced == 0)
  3808. {
  3809. MessageBoxA(hwndFR,
  3810. "The search text is not found.", szAppName, MB_OK);
  3811. }
  3812. else
  3813. {
  3814. char rgch[80];
  3815. wsprintfA(rgch, "Replaced %ld occurances.", cszReplaced);
  3816. MessageBoxA(hwndFR, rgch, szAppName, MB_OK);
  3817. }
  3818. SetFocus(hwndFR);
  3819. goto done;
  3820. }
  3821. // ft.chrg.cpMin = cpMatch;
  3822. // ft.chrg.cpMost = cpMatch + lstrlen(ft.lpstrText);
  3823. ft.chrg.cpMin = ft.chrgText.cpMin;
  3824. ft.chrg.cpMost = ft.chrgText.cpMost;
  3825. SendMessage(predoc->hwndRE, EM_EXSETSEL, 0, (LPARAM) &ft.chrg);
  3826. if(((pfr->Flags & FR_REPLACE) && cszReplaced == 0) ||
  3827. (pfr->Flags & FR_REPLACEALL))
  3828. {
  3829. SendMessage(predoc->hwndRE, EM_REPLACESEL, 0,
  3830. (LPARAM) pfr->lpstrReplaceWith);
  3831. ft.chrg.cpMin = cpMatch + lstrlen(pfr->lpstrReplaceWith);
  3832. ft.chrg.cpMost = -1; // search through end of the text
  3833. cszReplaced++;
  3834. goto next;
  3835. }
  3836. done:
  3837. if(pfr->Flags & FR_REPLACEALL)
  3838. {
  3839. SetCursor(hcur);
  3840. SendMessage(predoc->hwndRE, EM_HIDESELECTION, fFalse, fFalse);
  3841. }
  3842. }
  3843. VOID UpdateFormatBar(REDOC * predoc)
  3844. {
  3845. CHARFORMAT cf;
  3846. PARAFORMAT pf;
  3847. cf.cbSize = sizeof(CHARFORMAT);
  3848. pf.cbSize = sizeof(PARAFORMAT);
  3849. SendMessage(predoc->hwndRE, EM_GETCHARFORMAT, TRUE, (LPARAM) &cf);
  3850. SendMessage(predoc->hwndFormatBar, EM_SETCHARFORMAT, 0, (LPARAM) &cf);
  3851. SendMessage(predoc->hwndRE, EM_GETPARAFORMAT, FALSE, (LPARAM) &pf);
  3852. SendMessage(predoc->hwndFormatBar, EM_SETPARAFORMAT, 0, (LPARAM) &pf);
  3853. }
  3854. LOCAL VOID ShowMargins(REDOC *predoc)
  3855. {
  3856. if(ToggleCheck(predoc, IDM_SHOWMARGINS))
  3857. {
  3858. RECT rc;
  3859. GetClientRect(predoc->hwndParent, &rc);
  3860. ResizeRedoc(predoc, rc);
  3861. }
  3862. else
  3863. {
  3864. SendMessage(predoc->hwndRE, EM_SETRECT, 0, 0);
  3865. }
  3866. }
  3867. # ifdef DEBUG
  3868. LOCAL VOID SetLimit(REDOC *predoc)
  3869. {
  3870. LONG cchLimit = 32767;
  3871. if(ToggleCheck(predoc, IDM_BIGLIMIT))
  3872. cchLimit = 1024 * (LONG) 1024 - 1;
  3873. SendMessage(predoc->hwndRE, EM_EXLIMITTEXT, 0, cchLimit);
  3874. }
  3875. static TCHAR szText[] = "Once upon a time there was an edit control.  "
  3876. "This was a happy edit control until some mean evil tester "
  3877. "(who shall remain nameless) came along and started beating on "
  3878. "the poor little helpless edit control.  The edit control bravely "
  3879. "faced it's unprovoked attacker, but an edit control can only take "
  3880. "so much.  One day when it was being ferociously tortured it thought "
  3881. "to itself "What have I ever done to this poor homely creature to "
  3882. "deserve this type of punishment?".  It stirred up it's self esteem "
  3883. "and stood up and said to the nasty creature "I am an edit control, "
  3884. "hear me roar!  I deserve to be treated with dignity and respect!".  "
  3885. "The evil little tester was taken aback by the edit control's sudden "
  3886. "show of courage, but being the spawn of hell, he dismissed the edit "
  3887. "control's declaration and continued his ghastly attacks.  The edit "
  3888. "control decided that nothing would ever reform this hideous beast "
  3889. "imparting terror upon it so he decided to do something about it.  "
  3890. "The next day when the heathen was preparing to nuke the edit control "
  3891. "the edit control jumped out at the beast and ripped it's heart out.  "
  3892. "The tester stood shocked for a millisecond and then dropped over dead.  "
  3893. "The end.rnrn";
  3894. LOCAL VOID FillerUp(REDOC *predoc)
  3895. {
  3896. const LONG cch = lstrlen(szText);
  3897. LONG cchAdded;
  3898. LONG cchText;
  3899. DWORD dwTicks;
  3900. SetWindowText(predoc->hwndRE, TEXT(""));
  3901. cchText = 0;
  3902. (void) GetAsyncKeyState(VK_ESCAPE); // reset key state
  3903. dwTicks = GetTickCount();
  3904. do
  3905. {
  3906. LONG cchT;
  3907. SendMessage(predoc->hwndRE, EM_REPLACESEL, 0, (LPARAM) (LPSTR) szText);
  3908. cchT = SendMessage(predoc->hwndRE, WM_GETTEXTLENGTH, 0, 0);
  3909. cchAdded = cchT - cchText;
  3910. if(cchText % 8192 > cchT % 8192)
  3911. {
  3912. const DWORD dwT = GetTickCount();
  3913. TraceTag(tagGeneral, "%ld characters, %ld ticks", cchT, dwT - dwTicks);
  3914. dwTicks = dwT;
  3915. }
  3916. cchText = cchT;
  3917. if(GetAsyncKeyState(VK_ESCAPE) & 0x8001)
  3918. {
  3919. TraceTag(tagGeneral, "stopping for escape");
  3920. break;
  3921. }
  3922. } while(cchAdded > 0 && !fErrSpace);
  3923. TraceTag(tagGeneral, "Stopped at %ld character", cchText);
  3924. }
  3925. #endif // DEBUG