summaryrefslogtreecommitdiffstats
path: root/private/oleutest/letest/outline/outldoc.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/oleutest/letest/outline/outldoc.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/oleutest/letest/outline/outldoc.c')
-rw-r--r--private/oleutest/letest/outline/outldoc.c3247
1 files changed, 3247 insertions, 0 deletions
diff --git a/private/oleutest/letest/outline/outldoc.c b/private/oleutest/letest/outline/outldoc.c
new file mode 100644
index 000000000..8e36101f0
--- /dev/null
+++ b/private/oleutest/letest/outline/outldoc.c
@@ -0,0 +1,3247 @@
+/*************************************************************************
+**
+** OLE 2 Sample Code
+**
+** outldoc.c
+**
+** This file contains OutlineDoc functions.
+**
+** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
+**
+*************************************************************************/
+
+#include "outline.h"
+
+#if !defined( OLE_VERSION )
+#include <commdlg.h>
+#endif
+
+
+OLEDBGDATA
+
+extern LPOUTLINEAPP g_lpApp;
+
+// REVIEW: should use string resource for messages
+char ErrMsgDocWnd[] = "Can't create Document Window!";
+char ErrMsgFormatNotSupported[] = "Clipboard format not supported!";
+char MsgSaveFile[] = "Save existing file ?";
+char ErrMsgSaving[] = "Error in saving file!";
+char ErrMsgOpening[] = "Error in opening file!";
+char ErrMsgFormat[] = "Improper file format!";
+char ErrOutOfMemory[] = "Error: out of memory!";
+static char ErrMsgPrint[] = "Printing Error!";
+
+static BOOL fCancelPrint; // TRUE if the user has canceled the print job
+static HWND hWndPDlg; // Handle to the cancel print dialog
+
+
+/* OutlineDoc_Init
+ * ---------------
+ *
+ * Initialize the fields of a new OutlineDoc object. The object is initially
+ * not associated with a file or an (Untitled) document. This function sets
+ * the docInitType to DOCTYPE_UNKNOWN. After calling this function the
+ * caller should call:
+ * 1. OutlineDoc_InitNewFile to set the OutlineDoc to (Untitled)
+ * 2. OutlineDoc_LoadFromFile to associate the OutlineDoc with a file.
+ * This function creates a new window for the document.
+ *
+ * NOTE: the window is initially created with a NIL size. it must be
+ * sized and positioned by the caller. also the document is initially
+ * created invisible. the caller must call OutlineDoc_ShowWindow
+ * after sizing it to make the document window visible.
+ */
+BOOL OutlineDoc_Init(LPOUTLINEDOC lpOutlineDoc, BOOL fDataTransferDoc)
+{
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+
+#if defined( INPLACE_CNTR )
+ lpOutlineDoc->m_hWndDoc = CreateWindow(
+ DOCWNDCLASS, // Window class name
+ NULL, // Window's title
+
+ /* OLE2NOTE: an in-place contanier MUST use
+ ** WS_CLIPCHILDREN window style for the window
+ ** that it uses as the parent for the server's
+ ** in-place active window so that its
+ ** painting does NOT interfere with the painting
+ ** of the server's in-place active child window.
+ */
+
+ WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
+ WS_CHILDWINDOW,
+ 0, 0,
+ 0, 0,
+ lpOutlineApp->m_hWndApp,// Parent window's handle
+ (HMENU)1, // child window id
+ lpOutlineApp->m_hInst, // Instance of window
+ NULL); // Create struct for WM_CREATE
+
+#else
+
+ lpOutlineDoc->m_hWndDoc = CreateWindow(
+ DOCWNDCLASS, // Window class name
+ NULL, // Window's title
+ WS_CHILDWINDOW,
+ 0, 0,
+ 0, 0,
+ lpOutlineApp->m_hWndApp,// Parent window's handle
+ (HMENU)1, // child window id
+ lpOutlineApp->m_hInst, // Instance of window
+ NULL); // Create struct for WM_CREATE
+#endif
+
+ if(! lpOutlineDoc->m_hWndDoc) {
+ OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgDocWnd);
+ return FALSE;
+ }
+
+ SetWindowLong(lpOutlineDoc->m_hWndDoc, 0, (LONG) lpOutlineDoc);
+
+ if (! LineList_Init(&lpOutlineDoc->m_LineList, lpOutlineDoc))
+ return FALSE;
+
+ lpOutlineDoc->m_lpNameTable = OutlineDoc_CreateNameTable(lpOutlineDoc);
+ if (! lpOutlineDoc->m_lpNameTable )
+ return FALSE;
+
+ lpOutlineDoc->m_docInitType = DOCTYPE_UNKNOWN;
+ lpOutlineDoc->m_cfSaveFormat = lpOutlineApp->m_cfOutline;
+ lpOutlineDoc->m_szFileName[0] = '\0';
+ lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName;
+ lpOutlineDoc->m_fDataTransferDoc = fDataTransferDoc;
+ lpOutlineDoc->m_uCurrentZoom = IDM_V_ZOOM_100;
+ lpOutlineDoc->m_scale.dwSxN = (DWORD) 1;
+ lpOutlineDoc->m_scale.dwSxD = (DWORD) 1;
+ lpOutlineDoc->m_scale.dwSyN = (DWORD) 1;
+ lpOutlineDoc->m_scale.dwSyD = (DWORD) 1;
+ lpOutlineDoc->m_uCurrentMargin = IDM_V_SETMARGIN_0;
+ lpOutlineDoc->m_nLeftMargin = 0;
+ lpOutlineDoc->m_nRightMargin = 0;
+ lpOutlineDoc->m_nDisableDraw = 0;
+ OutlineDoc_SetModified(lpOutlineDoc, FALSE, FALSE, FALSE);
+
+#if defined( USE_HEADING )
+ if (! fDataTransferDoc) {
+ if (!Heading_Create((LPHEADING)&lpOutlineDoc->m_heading,
+ lpOutlineDoc->m_hWndDoc, lpOutlineApp->m_hInst)) {
+ return FALSE;
+
+ }
+ }
+#endif // USE_HEADING
+
+#if defined( USE_FRAMETOOLS )
+ if (! fDataTransferDoc) {
+ lpOutlineDoc->m_lpFrameTools = OutlineApp_GetFrameTools(lpOutlineApp);
+ FrameTools_AssociateDoc(
+ lpOutlineDoc->m_lpFrameTools,
+ lpOutlineDoc
+ );
+ }
+#endif // USE_FRAMETOOLS
+
+#if defined( OLE_VERSION )
+ /* OLE2NOTE: perform initialization required for OLE */
+ if (! OleDoc_Init((LPOLEDOC)lpOutlineDoc, fDataTransferDoc))
+ return FALSE;
+#endif // OLE_VERSION
+
+ return TRUE;
+}
+
+
+/* OutlineDoc_InitNewFile
+ * ----------------------
+ *
+ * Initialize the OutlineDoc object to be a new (Untitled) document.
+ * This function sets the docInitType to DOCTYPE_NEW.
+ */
+BOOL OutlineDoc_InitNewFile(LPOUTLINEDOC lpOutlineDoc)
+{
+#if defined( OLE_VERSION )
+ // OLE2NOTE: call OLE version of this function instead
+ return OleDoc_InitNewFile((LPOLEDOC)lpOutlineDoc);
+
+#else
+
+ OleDbgAssert(lpOutlineDoc->m_docInitType == DOCTYPE_UNKNOWN);
+
+ // set file name to untitled
+ // REVIEW: should load from string resource
+ lstrcpy(lpOutlineDoc->m_szFileName, UNTITLED);
+ lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName;
+ lpOutlineDoc->m_docInitType = DOCTYPE_NEW;
+
+ if (! lpOutlineDoc->m_fDataTransferDoc)
+ OutlineDoc_SetTitle(lpOutlineDoc, FALSE /*fMakeUpperCase*/);
+
+ return TRUE;
+
+#endif // BASE OUTLINE VERSION
+}
+
+
+/* OutlineDoc_CreateNameTable
+ * --------------------------
+ *
+ * Allocate a new NameTable of the appropriate type. Each document has
+ * a NameTable and a LineList.
+ * OutlineDoc --> creates standard OutlineNameTable type name tables.
+ * ServerDoc --> creates enhanced SeverNameTable type name tables.
+ *
+ * Returns lpNameTable for successful, NULL if error.
+ */
+LPOUTLINENAMETABLE OutlineDoc_CreateNameTable(LPOUTLINEDOC lpOutlineDoc)
+{
+ LPOUTLINENAMETABLE lpOutlineNameTable;
+
+ lpOutlineNameTable = (LPOUTLINENAMETABLE)New(
+ (DWORD)sizeof(OUTLINENAMETABLE)
+ );
+
+ OleDbgAssertSz(lpOutlineNameTable != NULL,"Error allocating NameTable");
+ if (lpOutlineNameTable == NULL)
+ return NULL;
+
+ // initialize new NameTable
+ if (! OutlineNameTable_Init(lpOutlineNameTable, lpOutlineDoc) )
+ goto error;
+
+ return lpOutlineNameTable;
+
+error:
+ if (lpOutlineNameTable)
+ Delete(lpOutlineNameTable);
+ return NULL;
+}
+
+
+/* OutlineDoc_ClearCommand
+ * -----------------------
+ *
+ * Delete selection in list box by calling OutlineDoc_Delete
+ */
+void OutlineDoc_ClearCommand(LPOUTLINEDOC lpOutlineDoc)
+{
+ LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
+ int i;
+ int nNumSel;
+ LINERANGE lrSel;
+
+ nNumSel=LineList_GetSel(lpLL, (LPLINERANGE)&lrSel);
+
+ OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE );
+ for(i = 0; i < nNumSel; i++)
+ OutlineDoc_DeleteLine(lpOutlineDoc, lrSel.m_nStartLine);
+
+ OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE );
+
+ LineList_RecalcMaxLineWidthInHimetric(lpLL, 0);
+}
+
+
+/* OutlineDoc_CutCommand
+ * ---------------------
+ *
+ * Cut selection to clipboard
+ */
+void OutlineDoc_CutCommand(LPOUTLINEDOC lpOutlineDoc)
+{
+ OutlineDoc_CopyCommand(lpOutlineDoc);
+ OutlineDoc_ClearCommand(lpOutlineDoc);
+}
+
+
+/* OutlineDoc_CopyCommand
+ * ----------------------
+ * Copy selection to clipboard.
+ * Post to the clipboard the formats that the app can render.
+ * the actual data is not rendered at this time. using the
+ * delayed rendering technique, Windows will send the clipboard
+ * owner window either a WM_RENDERALLFORMATS or a WM_RENDERFORMAT
+ * message when the actual data is requested.
+ *
+ * OLE2NOTE: the normal delayed rendering technique where Windows
+ * sends the clipboard owner window either a WM_RENDERALLFORMATS or
+ * a WM_RENDERFORMAT message when the actual data is requested is
+ * NOT exposed to the app calling OleSetClipboard. OLE internally
+ * creates its own window as the clipboard owner and thus our app
+ * will NOT get these WM_RENDER messages.
+ */
+void OutlineDoc_CopyCommand(LPOUTLINEDOC lpSrcOutlineDoc)
+{
+#if defined( OLE_VERSION )
+ // Call OLE version of this function instead
+ OleDoc_CopyCommand((LPOLEDOC)lpSrcOutlineDoc);
+
+#else
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+ LPOUTLINEDOC lpClipboardDoc;
+
+ OpenClipboard(lpSrcOutlineDoc->m_hWndDoc);
+ EmptyClipboard();
+
+ /* squirrel away a copy of the current selection to the ClipboardDoc */
+ lpClipboardDoc = OutlineDoc_CreateDataTransferDoc(lpSrcOutlineDoc);
+
+ if (! lpClipboardDoc)
+ return; // Error: could not create DataTransferDoc
+
+ lpOutlineApp->m_lpClipboardDoc = (LPOUTLINEDOC)lpClipboardDoc;
+
+ SetClipboardData(lpOutlineApp->m_cfOutline, NULL);
+ SetClipboardData(CF_TEXT, NULL);
+
+ CloseClipboard();
+
+#endif // ! OLE_VERSION
+}
+
+
+/* OutlineDoc_ClearAllLines
+ * ------------------------
+ *
+ * Delete all lines in the document.
+ */
+void OutlineDoc_ClearAllLines(LPOUTLINEDOC lpOutlineDoc)
+{
+ LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
+ int i;
+
+ for(i = 0; i < lpLL->m_nNumLines; i++)
+ OutlineDoc_DeleteLine(lpOutlineDoc, 0);
+
+ LineList_RecalcMaxLineWidthInHimetric(lpLL, 0);
+}
+
+
+/* OutlineDoc_CreateDataTransferDoc
+ * --------------------------------
+ *
+ * Create a document to be use to transfer data (either via a
+ * drag/drop operation of the clipboard). Copy the selection of the
+ * source doc to the data transfer document. A data transfer document is
+ * the same as a document that is created by the user except that it is
+ * NOT made visible to the user. it is specially used to hold a copy of
+ * data that the user should not be able to change.
+ *
+ * OLE2NOTE: in the OLE version the data transfer document is used
+ * specifically to provide an IDataObject* that renders the data copied.
+ */
+LPOUTLINEDOC OutlineDoc_CreateDataTransferDoc(LPOUTLINEDOC lpSrcOutlineDoc)
+{
+#if defined( OLE_VERSION )
+ // Call OLE version of this function instead
+ return OleDoc_CreateDataTransferDoc((LPOLEDOC)lpSrcOutlineDoc);
+
+#else
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+ LPOUTLINEDOC lpDestOutlineDoc;
+ LPLINELIST lpSrcLL = &lpSrcOutlineDoc->m_LineList;
+ LINERANGE lrSel;
+ int nCopied;
+
+ lpDestOutlineDoc = OutlineApp_CreateDoc(lpOutlineApp, TRUE);
+ if (! lpDestOutlineDoc) return NULL;
+
+ // set the ClipboardDoc to an (Untitled) doc.
+ if (! OutlineDoc_InitNewFile(lpDestOutlineDoc))
+ goto error;
+
+ LineList_GetSel(lpSrcLL, (LPLINERANGE)&lrSel);
+ nCopied = LineList_CopySelToDoc(
+ lpSrcLL,
+ (LPLINERANGE)&lrSel,
+ lpDestOutlineDoc
+ );
+
+ return lpDestOutlineDoc;
+
+error:
+ if (lpDestOutlineDoc)
+ OutlineDoc_Destroy(lpDestOutlineDoc);
+
+ return NULL;
+
+#endif // ! OLE_VERSION
+}
+
+
+/* OutlineDoc_PasteCommand
+ * -----------------------
+ *
+ * Paste lines from clipboard
+ */
+void OutlineDoc_PasteCommand(LPOUTLINEDOC lpOutlineDoc)
+{
+#if defined( OLE_VERSION )
+ // Call OLE version of this function instead
+ OleDoc_PasteCommand((LPOLEDOC)lpOutlineDoc);
+
+#else
+
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+ LPLINELIST lpLL = (LPLINELIST)&lpOutlineDoc->m_LineList;
+ int nIndex;
+ int nCount;
+ HGLOBAL hData;
+ LINERANGE lrSel;
+ UINT uFormat;
+
+ if (LineList_GetCount(lpLL) == 0)
+ nIndex = -1; // pasting to empty list
+ else
+ nIndex=LineList_GetFocusLineIndex(lpLL);
+
+ OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE );
+
+ OpenClipboard(lpOutlineDoc->m_hWndDoc);
+
+ uFormat = 0;
+ while(uFormat = EnumClipboardFormats(uFormat)) {
+ if(uFormat == lpOutlineApp->m_cfOutline) {
+ hData = GetClipboardData(lpOutlineApp->m_cfOutline);
+ nCount = OutlineDoc_PasteOutlineData(lpOutlineDoc, hData, nIndex);
+ break;
+ }
+ if(uFormat == CF_TEXT) {
+ hData = GetClipboardData(CF_TEXT);
+ nCount = OutlineDoc_PasteTextData(lpOutlineDoc, hData, nIndex);
+ break;
+ }
+ }
+
+ lrSel.m_nStartLine = nIndex + nCount;
+ lrSel.m_nEndLine = nIndex + 1;
+ LineList_SetSel(lpLL, &lrSel);
+ OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE );
+
+ CloseClipboard();
+
+#endif // ! OLE_VERSION
+}
+
+
+/* OutlineDoc_PasteOutlineData
+ * ---------------------------
+ *
+ * Put an array of Line Objects (stored in hOutline) into the document
+ *
+ * Return the number of items added
+ */
+int OutlineDoc_PasteOutlineData(LPOUTLINEDOC lpOutlineDoc, HGLOBAL hOutline, int nStartIndex)
+{
+ int nCount;
+ int i;
+ LPTEXTLINE arrLine;
+
+ nCount = (int) GlobalSize(hOutline) / sizeof(TEXTLINE);
+ arrLine = (LPTEXTLINE)GlobalLock(hOutline);
+ if (!arrLine)
+ return 0;
+
+ for(i = 0; i < nCount; i++)
+ Line_CopyToDoc((LPLINE)&arrLine[i], lpOutlineDoc, nStartIndex+i);
+
+ GlobalUnlock(hOutline);
+
+ return nCount;
+}
+
+
+/* OutlineDoc_PasteTextData
+ * ------------------------
+ *
+ * Build Line Objects from the strings (separated by '\n') in hText
+ * and put them into the document
+ */
+int OutlineDoc_PasteTextData(LPOUTLINEDOC lpOutlineDoc, HGLOBAL hText, int nStartIndex)
+{
+ LPLINELIST lpLL = (LPLINELIST)&lpOutlineDoc->m_LineList;
+ HDC hDC;
+ LPSTR lpszText;
+ LPSTR lpszEnd;
+ LPTEXTLINE lpLine;
+ int nLineCount;
+ int i;
+ UINT nTab;
+ char szBuf[MAXSTRLEN+1];
+
+ lpszText=(LPSTR)GlobalLock(hText);
+ if(!lpszText)
+ return 0;
+
+ lpszEnd = lpszText + lstrlen(lpszText);
+ nLineCount=0;
+
+ while(*lpszText && (lpszText<lpszEnd)) {
+
+ // count the tab level
+ nTab = 0;
+ while((*lpszText == '\t') && (lpszText<lpszEnd)) {
+ nTab++;
+ lpszText++;
+ }
+
+ // collect the text string character by character
+ for(i=0; (i<MAXSTRLEN) && (lpszText<lpszEnd); i++) {
+ if ((! *lpszText) || (*lpszText == '\n'))
+ break;
+ szBuf[i] = *lpszText++;
+ }
+ szBuf[i] = 0;
+ lpszText++;
+ if ((i > 0) && (szBuf[i-1] == '\r'))
+ szBuf[i-1] = 0; // remove carriage return at the end
+
+ hDC = LineList_GetDC(lpLL);
+ lpLine = TextLine_Create(hDC, nTab, szBuf);
+ LineList_ReleaseDC(lpLL, hDC);
+
+ OutlineDoc_AddLine(
+ lpOutlineDoc,
+ (LPLINE)lpLine,
+ nStartIndex + nLineCount
+ );
+ nLineCount++;
+
+ }
+
+ GlobalUnlock(hText);
+
+ return nLineCount;
+}
+
+
+/* OutlineDoc_AddTextLineCommand
+ * -----------------------------
+ *
+ * Add a new text line following the current focus line.
+ */
+void OutlineDoc_AddTextLineCommand(LPOUTLINEDOC lpOutlineDoc)
+{
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+ LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
+ HDC hDC;
+ int nIndex = LineList_GetFocusLineIndex(lpLL);
+ char szBuf[MAXSTRLEN+1];
+ UINT nTab = 0;
+ LPLINE lpLine;
+ LPTEXTLINE lpTextLine;
+
+ szBuf[0] = '\0';
+
+#if defined( USE_FRAMETOOLS )
+ FrameTools_FB_GetEditText(
+ lpOutlineDoc->m_lpFrameTools, szBuf, sizeof(szBuf));
+#else
+ if (! InputTextDlg(lpOutlineDoc->m_hWndDoc, szBuf, "Add Line"))
+ return;
+#endif
+
+ hDC = LineList_GetDC(lpLL);
+ lpLine = LineList_GetLine(lpLL, nIndex);
+ if (lpLine)
+ nTab = Line_GetTabLevel(lpLine);
+
+ lpTextLine=TextLine_Create(hDC, nTab, szBuf);
+ LineList_ReleaseDC(lpLL, hDC);
+
+ if (! lpTextLine) {
+ OutlineApp_ErrorMessage(lpOutlineApp, ErrOutOfMemory);
+ return;
+ }
+ OutlineDoc_AddLine(lpOutlineDoc, (LPLINE)lpTextLine, nIndex);
+}
+
+
+/* OutlineDoc_AddTopLineCommand
+ * ----------------------------
+ *
+ * Add a top (margin) line as the first line in the LineList.
+ * (do not change the current selection)
+ */
+void OutlineDoc_AddTopLineCommand(
+ LPOUTLINEDOC lpOutlineDoc,
+ UINT nHeightInHimetric
+)
+{
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+ LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
+ HDC hDC = LineList_GetDC(lpLL);
+ LPTEXTLINE lpTextLine = TextLine_Create(hDC, 0, NULL);
+ LPLINE lpLine = (LPLINE)lpTextLine;
+ LINERANGE lrSel;
+ int nNumSel;
+
+ LineList_ReleaseDC(lpLL, hDC);
+
+ if (! lpTextLine) {
+ OutlineApp_ErrorMessage(lpOutlineApp, ErrOutOfMemory);
+ return;
+ }
+
+ Line_SetHeightInHimetric(lpLine, nHeightInHimetric);
+
+ nNumSel=LineList_GetSel(lpLL, (LPLINERANGE)&lrSel);
+ if (nNumSel > 0) {
+ // adjust current selection to keep equivalent selection
+ lrSel.m_nStartLine += 1;
+ lrSel.m_nEndLine += 1;
+ }
+ OutlineDoc_AddLine(lpOutlineDoc, lpLine, -1);
+ if (nNumSel > 0)
+ LineList_SetSel(lpLL, (LPLINERANGE)&lrSel);
+}
+
+
+#if defined( USE_FRAMETOOLS )
+
+
+/* OutlineDoc_SetFormulaBarEditText
+ * --------------------------------
+ *
+ * Fill the edit control in the formula with the text string from a
+ * TextLine in focus.
+ */
+void OutlineDoc_SetFormulaBarEditText(
+ LPOUTLINEDOC lpOutlineDoc,
+ LPLINE lpLine
+)
+{
+ LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
+ char cBuf[MAXSTRLEN+1];
+
+ if (! lpOutlineDoc || ! lpOutlineDoc->m_lpFrameTools)
+ return;
+
+ if (Line_GetLineType(lpLine) != TEXTLINETYPE) {
+ FrameTools_FB_SetEditText(lpOutlineDoc->m_lpFrameTools, NULL);
+ } else {
+ TextLine_GetTextData((LPTEXTLINE)lpLine, (LPSTR)cBuf);
+ FrameTools_FB_SetEditText(lpOutlineDoc->m_lpFrameTools, (LPSTR)cBuf);
+ }
+}
+
+
+/* OutlineDoc_SetFormulaBarEditFocus
+ * ---------------------------------
+ *
+ * Setup for formula bar to gain or loose edit focus.
+ * if gaining focus, setup up special accelerator table and scroll line
+ * into view.
+ * else restore normal accelerator table.
+ */
+void OutlineDoc_SetFormulaBarEditFocus(
+ LPOUTLINEDOC lpOutlineDoc,
+ BOOL fEditFocus
+)
+{
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+ LPLINELIST lpLL;
+ int nFocusIndex;
+
+ if (! lpOutlineDoc || ! lpOutlineDoc->m_lpFrameTools)
+ return;
+
+ lpOutlineDoc->m_lpFrameTools->m_fInFormulaBar = fEditFocus;
+
+ if (fEditFocus && lpOutlineDoc->m_lpFrameTools) {
+ lpLL = OutlineDoc_GetLineList(lpOutlineDoc);
+
+ nFocusIndex = LineList_GetFocusLineIndex(lpLL);
+ LineList_ScrollLineIntoView(lpLL, nFocusIndex);
+ FrameTools_FB_FocusEdit(lpOutlineDoc->m_lpFrameTools);
+ }
+
+ OutlineApp_SetFormulaBarAccel(lpOutlineApp, fEditFocus);
+}
+
+
+/* OutlineDoc_IsEditFocusInFormulaBar
+** ----------------------------------
+** Returns TRUE if edit focus is currently in the formula bar
+** else FALSE if not.
+*/
+BOOL OutlineDoc_IsEditFocusInFormulaBar(LPOUTLINEDOC lpOutlineDoc)
+{
+ if (! lpOutlineDoc || ! lpOutlineDoc->m_lpFrameTools)
+ return FALSE;
+
+ return lpOutlineDoc->m_lpFrameTools->m_fInFormulaBar;
+}
+
+
+/* OutlineDoc_UpdateFrameToolButtons
+** ---------------------------------
+** Update the Enable/Disable states of the buttons in the formula
+** bar and button bar.
+*/
+void OutlineDoc_UpdateFrameToolButtons(LPOUTLINEDOC lpOutlineDoc)
+{
+ if (! lpOutlineDoc || ! lpOutlineDoc->m_lpFrameTools)
+ return;
+ FrameTools_UpdateButtons(lpOutlineDoc->m_lpFrameTools, lpOutlineDoc);
+}
+#endif // USE_FRAMETOOLS
+
+
+/* OutlineDoc_EditLineCommand
+ * --------------------------
+ *
+ * Edit the current focus line.
+ */
+void OutlineDoc_EditLineCommand(LPOUTLINEDOC lpOutlineDoc)
+{
+ LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
+ HDC hDC = LineList_GetDC(lpLL);
+ int nIndex = LineList_GetFocusLineIndex(lpLL);
+ LPLINE lpLine = LineList_GetLine(lpLL, nIndex);
+ int nOrgLineWidthInHimetric;
+ int nNewLineWidthInHimetric;
+ BOOL fSizeChanged;
+
+ if (!lpLine)
+ return;
+
+ nOrgLineWidthInHimetric = Line_GetTotalWidthInHimetric(lpLine);
+ if (Line_Edit(lpLine, lpOutlineDoc->m_hWndDoc, hDC)) {
+ nNewLineWidthInHimetric = Line_GetTotalWidthInHimetric(lpLine);
+
+ if (nNewLineWidthInHimetric > nOrgLineWidthInHimetric) {
+ fSizeChanged = LineList_SetMaxLineWidthInHimetric(
+ lpLL,
+ nNewLineWidthInHimetric
+ );
+ } else {
+ fSizeChanged = LineList_RecalcMaxLineWidthInHimetric(
+ lpLL,
+ nOrgLineWidthInHimetric
+ );
+ }
+
+#if defined( OLE_SERVER )
+ /* Update Name Table */
+ ServerNameTable_EditLineUpdate(
+ (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable,
+ nIndex
+ );
+#endif
+
+ OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, fSizeChanged);
+
+ LineList_ForceLineRedraw(lpLL, nIndex, TRUE);
+ }
+ LineList_ReleaseDC(lpLL, hDC);
+}
+
+
+/* OutlineDoc_IndentCommand
+ * ------------------------
+ *
+ * Indent selection of lines
+ */
+void OutlineDoc_IndentCommand(LPOUTLINEDOC lpOutlineDoc)
+{
+ LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
+ LPLINE lpLine;
+ HDC hDC = LineList_GetDC(lpLL);
+ int i;
+ int nIndex;
+ int nNumSel;
+ LINERANGE lrSel;
+ BOOL fSizeChanged = FALSE;
+
+ nNumSel=LineList_GetSel(lpLL, (LPLINERANGE)&lrSel);
+
+ OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE );
+
+ for(i = 0; i < nNumSel; i++) {
+ nIndex = lrSel.m_nStartLine + i;
+ lpLine=LineList_GetLine(lpLL, nIndex);
+ if (! lpLine)
+ continue;
+
+ Line_Indent(lpLine, hDC);
+ if (LineList_SetMaxLineWidthInHimetric(lpLL,
+ Line_GetTotalWidthInHimetric(lpLine))) {
+ fSizeChanged = TRUE;
+ }
+ LineList_ForceLineRedraw(lpLL, nIndex, TRUE);
+
+#if defined( OLE_SERVER )
+ /* Update Name Table */
+ ServerNameTable_EditLineUpdate(
+ (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable,
+ nIndex
+ );
+#endif
+
+ }
+
+ LineList_ReleaseDC(lpLL, hDC);
+
+ OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, fSizeChanged);
+ OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE );
+}
+
+
+/* OutlineDoc_UnindentCommand
+ * --------------------------
+ *
+ * Unindent selection of lines
+ */
+void OutlineDoc_UnindentCommand(LPOUTLINEDOC lpOutlineDoc)
+{
+ LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
+ LPLINE lpLine;
+ HDC hDC = LineList_GetDC(lpLL);
+ int nOrgLineWidthInHimetric;
+ int nOrgMaxLineWidthInHimetric = 0;
+ int i;
+ int nIndex;
+ int nNumSel;
+ LINERANGE lrSel;
+ BOOL fSizeChanged;
+
+ nNumSel=LineList_GetSel(lpLL, (LPLINERANGE)&lrSel);
+
+ OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE );
+
+ for(i = 0; i < nNumSel; i++) {
+ nIndex = lrSel.m_nStartLine + i;
+ lpLine=LineList_GetLine(lpLL, nIndex);
+ if (!lpLine)
+ continue;
+
+ nOrgLineWidthInHimetric = Line_GetTotalWidthInHimetric(lpLine);
+ nOrgMaxLineWidthInHimetric =
+ (nOrgLineWidthInHimetric > nOrgMaxLineWidthInHimetric ?
+ nOrgLineWidthInHimetric : nOrgMaxLineWidthInHimetric);
+ Line_Unindent(lpLine, hDC);
+ LineList_ForceLineRedraw(lpLL, nIndex, TRUE);
+
+#if defined( OLE_SERVER )
+ /* Update Name Table */
+ ServerNameTable_EditLineUpdate(
+ (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable,
+ nIndex
+ );
+#endif
+
+ }
+
+ LineList_ReleaseDC(lpLL, hDC);
+
+ fSizeChanged = LineList_RecalcMaxLineWidthInHimetric(
+ lpLL,
+ nOrgMaxLineWidthInHimetric
+ );
+
+ OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, fSizeChanged);
+ OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE );
+}
+
+
+/* OutlineDoc_SetLineHeightCommand
+ * -------------------------------
+ *
+ * Set height of the selection of lines
+ */
+void OutlineDoc_SetLineHeightCommand(LPOUTLINEDOC lpOutlineDoc)
+{
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+ LPLINELIST lpLL;
+ HDC hDC;
+ LPLINE lpLine;
+ int nNewHeight;
+ int i;
+ int nIndex;
+ int nNumSel;
+ LINERANGE lrSel;
+
+ if (!lpOutlineDoc)
+ return;
+
+ lpLL = &lpOutlineDoc->m_LineList;
+ nNumSel=LineList_GetSel(lpLL, (LPLINERANGE)&lrSel);
+ lpLine = LineList_GetLine(lpLL, lrSel.m_nStartLine);
+ if (!lpLine)
+ return;
+
+ nNewHeight = Line_GetHeightInHimetric(lpLine);
+
+#if defined( OLE_VERSION )
+ OleApp_PreModalDialog((LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineDoc);
+#endif
+
+ DialogBoxParam(
+ lpOutlineApp->m_hInst,
+ (LPSTR)"SetLineHeight",
+ lpOutlineDoc->m_hWndDoc,
+ (DLGPROC)SetLineHeightDlgProc,
+ (LPARAM)(LPINT)&nNewHeight
+ );
+
+#if defined( OLE_VERSION )
+ OleApp_PostModalDialog((LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineDoc);
+#endif
+
+ if (nNewHeight == 0)
+ return; /* user hit cancel */
+
+ hDC = LineList_GetDC(lpLL);
+
+ for (i = 0; i < nNumSel; i++) {
+ nIndex = lrSel.m_nStartLine + i;
+ lpLine=LineList_GetLine(lpLL, nIndex);
+ if (nNewHeight == -1) {
+ switch (Line_GetLineType(lpLine)) {
+
+ case TEXTLINETYPE:
+
+ TextLine_CalcExtents((LPTEXTLINE)lpLine, hDC);
+ break;
+
+#if defined( OLE_CNTR )
+ case CONTAINERLINETYPE:
+
+ ContainerLine_SetHeightInHimetric(
+ (LPCONTAINERLINE)lpLine, -1);
+ break;
+#endif
+
+ }
+ }
+ else
+ Line_SetHeightInHimetric(lpLine, nNewHeight);
+
+
+ LineList_SetLineHeight(lpLL, nIndex,
+ Line_GetHeightInHimetric(lpLine));
+ }
+
+ LineList_ReleaseDC(lpLL, hDC);
+
+ OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, TRUE);
+ LineList_ForceRedraw(lpLL, TRUE);
+}
+
+
+
+/* OutlineDoc_SelectAllCommand
+ * ---------------------------
+ *
+ * Select all the lines in the document.
+ */
+void OutlineDoc_SelectAllCommand(LPOUTLINEDOC lpOutlineDoc)
+{
+ LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
+ LINERANGE lrSel;
+
+ lrSel.m_nStartLine = 0;
+ lrSel.m_nEndLine = LineList_GetCount(lpLL) - 1;
+ LineList_SetSel(lpLL, &lrSel);
+}
+
+
+/* OutlineDoc_DefineNameCommand
+ * ----------------------------
+ *
+ * Define a name in the document
+ */
+void OutlineDoc_DefineNameCommand(LPOUTLINEDOC lpOutlineDoc)
+{
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+
+#if defined( OLE_VERSION )
+ OleApp_PreModalDialog((LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineDoc);
+#endif
+
+ DialogBoxParam(
+ lpOutlineApp->m_hInst,
+ (LPSTR)"DefineName",
+ lpOutlineDoc->m_hWndDoc,
+ (DLGPROC)DefineNameDlgProc,
+ (LPARAM) lpOutlineDoc
+ );
+
+#if defined( OLE_VERSION )
+ OleApp_PostModalDialog((LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineDoc);
+#endif
+}
+
+
+/* OutlineDoc_GotoNameCommand
+ * --------------------------
+ *
+ * Goto a predefined name in the document
+ */
+void OutlineDoc_GotoNameCommand(LPOUTLINEDOC lpOutlineDoc)
+{
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+
+#if defined( OLE_VERSION )
+ OleApp_PreModalDialog((LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineDoc);
+#endif
+
+ DialogBoxParam(
+ lpOutlineApp->m_hInst,
+ (LPSTR)"GotoName",
+ lpOutlineDoc->m_hWndDoc,
+ (DLGPROC)GotoNameDlgProc,
+ (LPARAM)lpOutlineDoc
+ );
+
+#if defined( OLE_VERSION )
+ OleApp_PostModalDialog((LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineDoc);
+#endif
+}
+
+
+/* OutlineDoc_ShowWindow
+ * ---------------------
+ *
+ * Show the window of the document to the user.
+ */
+void OutlineDoc_ShowWindow(LPOUTLINEDOC lpOutlineDoc)
+{
+#if defined( _DEBUG )
+ OleDbgAssertSz(lpOutlineDoc->m_docInitType != DOCTYPE_UNKNOWN,
+ "OutlineDoc_ShowWindow: can't show unitialized document\r\n");
+#endif
+ if (lpOutlineDoc->m_docInitType == DOCTYPE_UNKNOWN)
+ return;
+
+#if defined( OLE_VERSION )
+ // Call OLE version of this function instead
+ OleDoc_ShowWindow((LPOLEDOC)lpOutlineDoc);
+#else
+ ShowWindow(lpOutlineDoc->m_hWndDoc, SW_SHOWNORMAL);
+ SetFocus(lpOutlineDoc->m_hWndDoc);
+#endif
+}
+
+
+#if defined( USE_FRAMETOOLS )
+
+void OutlineDoc_AddFrameLevelTools(LPOUTLINEDOC lpOutlineDoc)
+{
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+#if defined( INPLACE_CNTR )
+ // Call OLE In-Place Container version of this function instead
+ ContainerDoc_AddFrameLevelTools((LPCONTAINERDOC)lpOutlineDoc);
+
+#else // ! INPLACE_CNTR
+ RECT rcFrameRect;
+ BORDERWIDTHS frameToolWidths;
+
+#if defined( INPLACE_SVR )
+ LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc;
+ LPOLEINPLACEFRAME lpTopIPFrame=ServerDoc_GetTopInPlaceFrame(lpServerDoc);
+
+ // if in-place active, add our tools to our in-place container's frame.
+ if (lpTopIPFrame) {
+ ServerDoc_AddFrameLevelTools(lpServerDoc);
+ return;
+ }
+#endif // INPLACE_SVR
+
+ OutlineApp_GetFrameRect(g_lpApp, (LPRECT)&rcFrameRect);
+ FrameTools_GetRequiredBorderSpace(
+ lpOutlineDoc->m_lpFrameTools,
+ (LPBORDERWIDTHS)&frameToolWidths
+ );
+ OutlineApp_SetBorderSpace(g_lpApp, (LPBORDERWIDTHS)&frameToolWidths);
+ FrameTools_AttachToFrame(
+ lpOutlineDoc->m_lpFrameTools, OutlineApp_GetWindow(lpOutlineApp));
+ FrameTools_Move(lpOutlineDoc->m_lpFrameTools, (LPRECT)&rcFrameRect);
+#endif // ! INPLACE_CNTR
+
+}
+
+#endif // USE_FRAMETOOLS
+
+
+/* OutlineDoc_GetWindow
+ * --------------------
+ *
+ * Get the window handle of the document.
+ */
+HWND OutlineDoc_GetWindow(LPOUTLINEDOC lpOutlineDoc)
+{
+ if(! lpOutlineDoc) return NULL;
+ return lpOutlineDoc->m_hWndDoc;
+}
+
+
+/* OutlineDoc_AddLine
+ * ------------------
+ *
+ * Add one line to the Document's LineList
+ */
+void OutlineDoc_AddLine(LPOUTLINEDOC lpOutlineDoc, LPLINE lpLine, int nIndex)
+{
+ LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
+
+ LineList_AddLine(lpLL, lpLine, nIndex);
+
+ /* Update Name Table */
+ OutlineNameTable_AddLineUpdate(lpOutlineDoc->m_lpNameTable, nIndex);
+
+#if defined( INPLACE_CNTR )
+ {
+ LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc;
+ /* OLE2NOTE: after adding a line we need to
+ ** update the PosRect of the In-Place active
+ ** objects (if any) that follow the added line.
+ ** NOTE: nIndex is index of line before new line.
+ ** nIndex+1 is index of new line
+ ** nIndex+2 is index of line after new line.
+ */
+ ContainerDoc_UpdateInPlaceObjectRects(lpContainerDoc, nIndex+2);
+ }
+#endif
+
+ OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, TRUE);
+}
+
+
+/* OutlineDoc_DeleteLine
+ * ---------------------
+ *
+ *
+ * Delete one line from the document's LineList
+ */
+void OutlineDoc_DeleteLine(LPOUTLINEDOC lpOutlineDoc, int nIndex)
+{
+ LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
+
+#if defined( OLE_CNTR )
+ LPLINE lpLine = LineList_GetLine(lpLL, nIndex);
+ LPSTORAGE lpStgDoc = NULL;
+ char szSaveStgName[CWCSTORAGENAME];
+ BOOL fDeleteChildStg = FALSE;
+
+ if (lpLine && (Line_GetLineType(lpLine) == CONTAINERLINETYPE) ) {
+
+ /* OLE2NOTE: when a ContainerLine is being deleted by the user,
+ ** it is important to delete the object's sub-storage
+ ** otherwise it wastes space in the ContainerDoc's file.
+ ** this function is called when lines are deleted by the
+ ** Clear command and when lines are deleted by a DRAGMOVE
+ ** operation.
+ */
+ LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
+
+ // save name of child storage
+ LSTRCPYN(szSaveStgName, lpContainerLine->m_szStgName,
+ sizeof(szSaveStgName));
+ lpStgDoc = ((LPOLEDOC)lpContainerLine->m_lpDoc)->m_lpStg;
+ fDeleteChildStg = TRUE;
+ }
+#endif // OLE_CNTR
+
+ LineList_DeleteLine(lpLL, nIndex);
+
+#if defined( OLE_CNTR )
+ if (fDeleteChildStg && lpStgDoc) {
+ HRESULT hrErr;
+
+ // delete the obsolete child storage. it is NOT fatal if this fails
+
+ hrErr = CallIStorageDestroyElementA(lpStgDoc, szSaveStgName);
+
+#if defined( _DEBUG )
+ if (hrErr != NOERROR) {
+ OleDbgOutHResult("IStorage::DestroyElement return", hrErr);
+ }
+#endif
+ }
+#endif // OLE_CNTR
+
+ /* Update Name Table */
+ OutlineNameTable_DeleteLineUpdate(lpOutlineDoc->m_lpNameTable, nIndex);
+
+#if defined( INPLACE_CNTR )
+ {
+ LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc;
+ /* OLE2NOTE: after deleting a line we need to
+ ** update the PosRect of the In-Place active
+ ** objects (if any).
+ */
+ ContainerDoc_UpdateInPlaceObjectRects(lpContainerDoc, nIndex);
+ }
+#endif
+
+ OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, TRUE);
+
+#if defined( OLE_VERSION )
+ {
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+ LPOLEDOC lpClipboardDoc = (LPOLEDOC)lpOutlineApp->m_lpClipboardDoc;
+
+ /* OLE2NOTE: if the document that is the source of data on the
+ ** clipborad has just had lines deleted, then the copied data
+ ** is no longer considered a valid potential link source.
+ ** disable the offering of CF_LINKSOURCE from the clipboard
+ ** document. this avoids problems that arise when the
+ ** editing operation changes or deletes the original data
+ ** copied. we will not go to the trouble of determining if
+ ** the deleted line actually is part of the link source.
+ */
+ if (lpClipboardDoc
+ && lpClipboardDoc->m_fLinkSourceAvail
+ && lpClipboardDoc->m_lpSrcDocOfCopy == (LPOLEDOC)lpOutlineDoc) {
+ lpClipboardDoc->m_fLinkSourceAvail = FALSE;
+
+ /* OLE2NOTE: since we are changing the list of formats on
+ ** the clipboard (ie. removing CF_LINKSOURCE), we must
+ ** call OleSetClipboard again. to be sure that the
+ ** clipboard datatransfer document object does not get
+ ** destroyed we will guard the call to OleSetClipboard
+ ** within a pair of AddRef/Release.
+ */
+ OleDoc_AddRef((LPOLEDOC)lpClipboardDoc); // guard obj life-time
+
+ OLEDBG_BEGIN2("OleSetClipboard called\r\n")
+ OleSetClipboard(
+ (LPDATAOBJECT)&((LPOLEDOC)lpClipboardDoc)->m_DataObject);
+ OLEDBG_END2
+
+ OleDoc_Release((LPOLEDOC)lpClipboardDoc); // rel. AddRef above
+ }
+ }
+#endif // OLE_VERSION
+}
+
+
+/* OutlineDoc_AddName
+ * ------------------
+ *
+ * Add a Name to the Document's NameTable
+ */
+void OutlineDoc_AddName(LPOUTLINEDOC lpOutlineDoc, LPOUTLINENAME lpOutlineName)
+{
+ LPOUTLINENAMETABLE lpOutlineNameTable = lpOutlineDoc->m_lpNameTable;
+
+ OutlineNameTable_AddName(lpOutlineNameTable, lpOutlineName);
+
+ OutlineDoc_SetModified(lpOutlineDoc, TRUE, FALSE, FALSE);
+}
+
+
+/* OutlineDoc_DeleteName
+ * ---------------------
+ *
+ *
+ * Delete Name from the document's NameTable
+ */
+void OutlineDoc_DeleteName(LPOUTLINEDOC lpOutlineDoc, int nIndex)
+{
+ LPOUTLINENAMETABLE lpOutlineNameTable = lpOutlineDoc->m_lpNameTable;
+
+ OutlineNameTable_DeleteName(lpOutlineNameTable, nIndex);
+
+ OutlineDoc_SetModified(lpOutlineDoc, TRUE, FALSE, FALSE);
+}
+
+
+/* OutlineDoc_Destroy
+ * ------------------
+ *
+ * Free all memory that had been allocated for a document.
+ * this destroys the LineList & NameTable of the document.
+ */
+void OutlineDoc_Destroy(LPOUTLINEDOC lpOutlineDoc)
+{
+ LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
+#if defined( OLE_VERSION )
+ LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
+ LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc;
+
+ if (lpOleDoc->m_fObjIsDestroying)
+ return; // doc destruction is in progress
+#endif // OLE_VERSION
+
+ OLEDBG_BEGIN3("OutlineDoc_Destroy\r\n");
+
+#if defined( OLE_VERSION )
+
+ /* OLE2NOTE: in order to guarantee that the application does not
+ ** prematurely exit before the destruction of the document is
+ ** complete, we intially AddRef the App refcnt later Release it.
+ ** This initial AddRef is artificial; it simply guarantees that
+ ** the app object does not get destroyed until the end of this
+ ** routine.
+ */
+ OleApp_AddRef(lpOleApp);
+
+ /* OLE2NOTE: perform processing required for OLE */
+ OleDoc_Destroy(lpOleDoc);
+#endif
+
+ LineList_Destroy(lpLL);
+ OutlineNameTable_Destroy(lpOutlineDoc->m_lpNameTable);
+
+#if defined( USE_HEADING )
+ if (! lpOutlineDoc->m_fDataTransferDoc)
+ Heading_Destroy((LPHEADING)&lpOutlineDoc->m_heading);
+#endif
+
+#if defined( USE_FRAMETOOLS )
+ if (! lpOutlineDoc->m_fDataTransferDoc)
+ FrameTools_AssociateDoc(lpOutlineDoc->m_lpFrameTools, NULL);
+#endif // USE_FRAMETOOLS
+
+ DestroyWindow(lpOutlineDoc->m_hWndDoc);
+ Delete(lpOutlineDoc); // free memory for doc itself
+ OleDbgOut1("@@@@ DOC DESTROYED\r\n");
+
+#if defined( OLE_VERSION )
+ OleApp_Release(lpOleApp); // release artificial AddRef above
+#endif
+
+ OLEDBG_END3
+}
+
+
+/* OutlineDoc_ReSize
+ * -----------------
+ *
+ * Resize the document and its components
+ *
+ * Parameter:
+ * lpRect the new size of the document. Use current size if NULL
+ */
+void OutlineDoc_Resize(LPOUTLINEDOC lpOutlineDoc, LPRECT lpRect)
+{
+ RECT rect;
+ LPLINELIST lpLL;
+
+#if defined( USE_HEADING )
+ LPHEADING lphead;
+#endif // USE_HEADING
+
+ LPSCALEFACTOR lpscale;
+ HWND hWndLL;
+
+ if (!lpOutlineDoc)
+ return;
+
+ lpLL = (LPLINELIST)&lpOutlineDoc->m_LineList;
+ lpscale = (LPSCALEFACTOR)&lpOutlineDoc->m_scale;
+ hWndLL = LineList_GetWindow(lpLL);
+
+ if (lpRect) {
+ CopyRect((LPRECT)&rect, lpRect);
+ MoveWindow(lpOutlineDoc->m_hWndDoc, rect.left, rect.top,
+ rect.right-rect.left, rect.bottom-rect.top, TRUE);
+ }
+
+ GetClientRect(lpOutlineDoc->m_hWndDoc, (LPRECT)&rect);
+
+#if defined( USE_HEADING )
+ lphead = OutlineDoc_GetHeading(lpOutlineDoc);
+ rect.left += Heading_RH_GetWidth(lphead, lpscale);
+ rect.top += Heading_CH_GetHeight(lphead, lpscale);
+#endif // USE_HEADING
+
+ if (lpLL) {
+ MoveWindow(hWndLL, rect.left, rect.top,
+ rect.right-rect.left, rect.bottom-rect.top, TRUE);
+ }
+
+#if defined( USE_HEADING )
+ if (lphead)
+ Heading_Move(lphead, lpOutlineDoc->m_hWndDoc, lpscale);
+#endif // USE_HEADING
+
+#if defined( INPLACE_CNTR )
+ ContainerDoc_UpdateInPlaceObjectRects((LPCONTAINERDOC)lpOutlineDoc, 0);
+#endif
+}
+
+
+/* OutlineDoc_GetNameTable
+ * -----------------------
+ *
+ * Get nametable associated with the line list
+ */
+LPOUTLINENAMETABLE OutlineDoc_GetNameTable(LPOUTLINEDOC lpOutlineDoc)
+{
+ if (!lpOutlineDoc)
+ return NULL;
+ else
+ return lpOutlineDoc->m_lpNameTable;
+}
+
+
+/* OutlineDoc_GetLineList
+ * ----------------------
+ *
+ * Get listlist associated with the OutlineDoc
+ */
+LPLINELIST OutlineDoc_GetLineList(LPOUTLINEDOC lpOutlineDoc)
+{
+ if (!lpOutlineDoc)
+ return NULL;
+ else
+ return (LPLINELIST)&lpOutlineDoc->m_LineList;
+}
+
+
+/* OutlineDoc_GetNameCount
+ * -----------------------
+ *
+ * Return number of names in table
+ */
+int OutlineDoc_GetNameCount(LPOUTLINEDOC lpOutlineDoc)
+{
+ return OutlineNameTable_GetCount(lpOutlineDoc->m_lpNameTable);
+}
+
+
+/* OutlineDoc_GetLineCount
+ * -----------------------
+ *
+ * Return number of lines in the LineList
+ */
+int OutlineDoc_GetLineCount(LPOUTLINEDOC lpOutlineDoc)
+{
+ return LineList_GetCount(&lpOutlineDoc->m_LineList);
+}
+
+
+/* OutlineDoc_SetFileName
+ * ----------------------
+ *
+ * Set the filename of a document.
+ *
+ * OLE2NOTE: If the ServerDoc has a valid filename then, the object is
+ * registered in the running object table (ROT). if the name of the doc
+ * changes (eg. via SaveAs) then the previous registration must be revoked
+ * and the document re-registered under the new name.
+ */
+BOOL OutlineDoc_SetFileName(LPOUTLINEDOC lpOutlineDoc, LPSTR lpszNewFileName, LPSTORAGE lpNewStg)
+{
+ OleDbgAssertSz(lpszNewFileName != NULL, "Can't reset doc to Untitled!");
+ if (lpszNewFileName == NULL)
+ return FALSE;
+
+ AnsiLowerBuff(lpszNewFileName, (UINT)lstrlen(lpszNewFileName));
+
+#if defined( OLE_CNTR )
+ {
+ LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc;
+ LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc;
+
+ /* OLE2NOTE: the container version of the application keeps its
+ ** storage open at all times. if the document's storage is not
+ ** open, then open it.
+ */
+
+ if (lpNewStg) {
+
+ /* CASE 1 -- document is being loaded from a file. lpNewStg is
+ ** still open from the OutlineDoc_LoadFromFile function.
+ */
+
+ lpOutlineDoc->m_docInitType = DOCTYPE_FROMFILE;
+
+ } else {
+
+ /* CASE 2 -- document is being associated with a valid file
+ ** that is not yet open. thus we must now open the file.
+ */
+
+ if (lpOutlineDoc->m_docInitType == DOCTYPE_FROMFILE &&
+ lstrcmp(lpOutlineDoc->m_szFileName,lpszNewFileName)==0) {
+
+ /* CASE 2a -- new filename is same as current file. if the
+ ** stg is already open, then the lpStg is still valid.
+ ** if it is not open, then open it.
+ */
+ if (! lpOleDoc->m_lpStg) {
+ lpOleDoc->m_lpStg = OleStdOpenRootStorage(
+ lpszNewFileName,
+ STGM_READWRITE | STGM_SHARE_DENY_WRITE
+ );
+ if (! lpOleDoc->m_lpStg) return FALSE;
+ }
+
+ } else {
+
+ /* CASE 2b -- new filename is NOT same as current file.
+ ** a SaveAs operation is pending. open the new file and
+ ** hold the storage pointer in m_lpNewStg. the
+ ** subsequent call to Doc_SaveToFile will save the
+ ** document into the new storage pointer and release the
+ ** old storage pointer.
+ */
+
+ lpOutlineDoc->m_docInitType = DOCTYPE_FROMFILE;
+
+ lpContainerDoc->m_lpNewStg = OleStdCreateRootStorage(
+ lpszNewFileName,
+ STGM_READWRITE | STGM_SHARE_DENY_WRITE | STGM_CREATE
+ );
+ if (! lpContainerDoc->m_lpNewStg) return FALSE;
+ }
+ }
+ }
+#endif // OLE_CNTR
+
+ if (lpOutlineDoc->m_docInitType != DOCTYPE_FROMFILE ||
+ lstrcmp(lpOutlineDoc->m_szFileName, lpszNewFileName) != 0) {
+
+ /* A new valid file name is being associated with the document */
+
+ lstrcpy(lpOutlineDoc->m_szFileName, lpszNewFileName);
+ lpOutlineDoc->m_docInitType = DOCTYPE_FROMFILE;
+
+ // set lpszDocTitle to point to filename without path
+ lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName +
+ lstrlen(lpOutlineDoc->m_szFileName) - 1;
+ while (lpOutlineDoc->m_lpszDocTitle > lpOutlineDoc->m_szFileName
+ && ! IS_FILENAME_DELIM(lpOutlineDoc->m_lpszDocTitle[-1])) {
+ lpOutlineDoc->m_lpszDocTitle--;
+ }
+
+ OutlineDoc_SetTitle(lpOutlineDoc, TRUE /*fMakeUpperCase*/);
+
+#if defined( OLE_VERSION )
+ {
+ /* OLE2NOTE: both containers and servers must properly
+ ** register in the RunningObjectTable. if the document
+ ** is performing a SaveAs operation, then it must
+ ** re-register in the ROT with the new moniker. in
+ ** addition any embedded object, pseudo objects, and/or
+ ** linking clients must be informed that the document's
+ ** moniker has changed.
+ */
+
+ LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc;
+
+ if (lpOleDoc->m_lpFileMoniker) {
+ OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpFileMoniker);
+ lpOleDoc->m_lpFileMoniker = NULL;
+ }
+
+ CreateFileMonikerA(lpszNewFileName,
+ &lpOleDoc->m_lpFileMoniker);
+
+ OleDoc_DocRenamedUpdate(lpOleDoc, lpOleDoc->m_lpFileMoniker);
+ }
+#endif // OLE_VERSION
+
+ }
+
+ return TRUE;
+}
+
+
+/* OutlineDoc_SetTitle
+ * -------------------
+ *
+ * Set window text to be current filename.
+ * The following window hierarchy exits:
+ * hWndApp
+ * hWndDoc
+ * hWndListBox
+ * The frame window is the window which gets the title.
+ */
+void OutlineDoc_SetTitle(LPOUTLINEDOC lpOutlineDoc, BOOL fMakeUpperCase)
+{
+ HWND hWnd;
+ LPSTR lpszText;
+
+ if (!lpOutlineDoc->m_hWndDoc) return;
+ if ((hWnd = GetParent(lpOutlineDoc->m_hWndDoc)) == NULL) return;
+
+ lpszText = OleStdMalloc((UINT)(lstrlen(APPNAME) + 4 +
+ lstrlen(lpOutlineDoc->m_lpszDocTitle)));
+ if (!lpszText) return;
+
+ lstrcpy(lpszText, APPNAME);
+ lstrcat(lpszText," - ");
+ lstrcat(lpszText, (LPSTR)lpOutlineDoc->m_lpszDocTitle);
+
+ if (fMakeUpperCase)
+ AnsiUpperBuff(lpszText, (UINT)lstrlen(lpszText));
+
+ SetWindowText(hWnd,lpszText);
+ OleStdFree(lpszText);
+}
+
+
+/* OutlineDoc_Close
+ * ----------------
+ *
+ * Close active document. If modified, prompt the user if
+ * he wants to save.
+ *
+ * Returns:
+ * FALSE -- user canceled the closing of the doc.
+ * TRUE -- the doc was successfully closed
+ */
+BOOL OutlineDoc_Close(LPOUTLINEDOC lpOutlineDoc, DWORD dwSaveOption)
+{
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+
+#if defined( OLE_VERSION )
+ /* OLE2NOTE: call OLE specific function instead */
+ return OleDoc_Close((LPOLEDOC)lpOutlineDoc, dwSaveOption);
+
+#else
+
+ if (! lpOutlineDoc)
+ return TRUE; // active doc's are already destroyed
+
+ if (! OutlineDoc_CheckSaveChanges(lpOutlineDoc, &dwSaveOption))
+ return FALSE; // abort closing the doc
+
+ OutlineDoc_Destroy(lpOutlineDoc);
+
+ OutlineApp_DocUnlockApp(lpOutlineApp, lpOutlineDoc);
+
+ return TRUE;
+
+#endif // ! OLE_VERSION
+}
+
+
+/* OutlineDoc_CheckSaveChanges
+ * ---------------------------
+ *
+ * Check if the document has been modified. if so, prompt the user if
+ * the changes should be saved. if yes save them.
+ * Returns TRUE if the doc is safe to close (user answered Yes or No)
+ * FALSE if the user canceled the save changes option.
+ */
+BOOL OutlineDoc_CheckSaveChanges(
+ LPOUTLINEDOC lpOutlineDoc,
+ LPDWORD lpdwSaveOption
+)
+{
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+ int nResponse;
+
+ if (*lpdwSaveOption == OLECLOSE_NOSAVE)
+ return TRUE;
+
+ if(! OutlineDoc_IsModified(lpOutlineDoc))
+ return TRUE; // saving is not necessary
+
+ /* OLE2NOTE: our document is dirty so it needs to be saved. if
+ ** OLECLOSE_PROMPTSAVE the user should be prompted to see if the
+ ** document should be saved. is specified but the document is NOT
+ ** visible to the user, then the user can NOT be prompted. in
+ ** the situation the document should be saved without prompting.
+ ** if OLECLOSE_SAVEIFDIRTY is specified then, the document
+ ** should also be saved without prompting.
+ */
+ if (*lpdwSaveOption == OLECLOSE_PROMPTSAVE &&
+ IsWindowVisible(lpOutlineDoc->m_hWndDoc)) {
+
+ // prompt the user to see if changes should be saved.
+#if defined( OLE_VERSION )
+ OleApp_PreModalDialog(
+ (LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineApp->m_lpDoc);
+#endif
+ nResponse = MessageBox(
+ lpOutlineApp->m_hWndApp,
+ MsgSaveFile,
+ APPNAME,
+ MB_ICONQUESTION | MB_YESNOCANCEL
+ );
+#if defined( OLE_VERSION )
+ OleApp_PostModalDialog(
+ (LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineApp->m_lpDoc);
+#endif
+ if(nResponse==IDCANCEL)
+ return FALSE; // close is canceled
+ if(nResponse==IDNO) {
+ // Reset the save option to NOSAVE per user choice
+ *lpdwSaveOption = OLECLOSE_NOSAVE;
+ return TRUE; // don't save, but is ok to close
+ }
+ } else if (*lpdwSaveOption != OLECLOSE_SAVEIFDIRTY) {
+ OleDbgAssertSz(FALSE, "Invalid dwSaveOption\r\n");
+ *lpdwSaveOption = OLECLOSE_NOSAVE;
+ return TRUE; // unknown *lpdwSaveOption; close w/o saving
+ }
+
+#if defined( OLE_SERVER )
+ if (lpOutlineDoc->m_docInitType == DOCTYPE_EMBEDDED) {
+ LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc;
+ HRESULT hrErr;
+
+ /* OLE2NOTE: Update the container before closing without prompting
+ ** the user. To update the container, we must ask our container
+ ** to save us.
+ */
+ OleDbgAssert(lpServerDoc->m_lpOleClientSite != NULL);
+ OLEDBG_BEGIN2("IOleClientSite::SaveObject called\r\n")
+ hrErr = lpServerDoc->m_lpOleClientSite->lpVtbl->SaveObject(
+ lpServerDoc->m_lpOleClientSite
+ );
+ OLEDBG_END2
+
+ if (hrErr != NOERROR) {
+ OleDbgOutHResult("IOleClientSite::SaveObject returned", hrErr);
+ return FALSE;
+ }
+
+ return TRUE; // doc is safe to be closed
+
+ } else
+#endif // OLE_SERVER
+ {
+ return OutlineApp_SaveCommand(lpOutlineApp);
+ }
+}
+
+
+/* OutlineDoc_IsModified
+ * ---------------------
+ *
+ * Return modify flag of OUTLINEDOC
+ */
+BOOL OutlineDoc_IsModified(LPOUTLINEDOC lpOutlineDoc)
+{
+ if (lpOutlineDoc->m_fModified)
+ return lpOutlineDoc->m_fModified;
+
+#if defined( OLE_CNTR )
+ {
+ /* OLE2NOTE: if there are OLE objects, then we must ask if any of
+ ** them are dirty. if so we must consider our document
+ ** as modified.
+ */
+ LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc;
+ LPLINELIST lpLL;
+ int nLines;
+ int nIndex;
+ LPLINE lpLine;
+ HRESULT hrErr;
+
+ lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
+ nLines = LineList_GetCount(lpLL);
+
+ for (nIndex = 0; nIndex < nLines; nIndex++) {
+ lpLine = LineList_GetLine(lpLL, nIndex);
+ if (!lpLine)
+ break;
+ if (Line_GetLineType(lpLine) == CONTAINERLINETYPE) {
+ LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
+ if (lpContainerLine->m_lpPersistStg) {
+ hrErr = lpContainerLine->m_lpPersistStg->lpVtbl->IsDirty(
+ lpContainerLine->m_lpPersistStg);
+ /* OLE2NOTE: we will only accept an explicit "no i
+ ** am NOT dirty statement" (ie. S_FALSE) as an
+ ** indication that the object is clean. eg. if
+ ** the object returns E_NOTIMPL we must
+ ** interpret it as the object IS dirty.
+ */
+ if (GetScode(hrErr) != S_FALSE)
+ return TRUE;
+ }
+ }
+ }
+ }
+#endif
+ return FALSE;
+}
+
+
+/* OutlineDoc_SetModified
+ * ----------------------
+ *
+ * Set the modified flag of the document
+ *
+ */
+void OutlineDoc_SetModified(LPOUTLINEDOC lpOutlineDoc, BOOL fModified, BOOL fDataChanged, BOOL fSizeChanged)
+{
+ lpOutlineDoc->m_fModified = fModified;
+
+#if defined( OLE_SERVER )
+ if (! lpOutlineDoc->m_fDataTransferDoc) {
+ LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc;
+
+ /* OLE2NOTE: if the document has changed, then broadcast the change
+ ** to all clients who have set up Advise connections. notify
+ ** them that our data (and possibly also our extents) have
+ ** changed.
+ */
+ if (fDataChanged) {
+ lpServerDoc->m_fDataChanged = TRUE;
+ lpServerDoc->m_fSizeChanged = fSizeChanged;
+ lpServerDoc->m_fSendDataOnStop = TRUE;
+
+ ServerDoc_SendAdvise(
+ lpServerDoc,
+ OLE_ONDATACHANGE,
+ NULL, /* lpmkDoc -- not relevant here */
+ 0 /* advf -- no flags necessary */
+ );
+ }
+ }
+#endif // OLE_SERVER
+}
+
+
+/* OutlineDoc_SetRedraw
+ * --------------------
+ *
+ * Enable/Disable the redraw of the document on screen.
+ * The calls to SetRedraw counted so that nested calls can be handled
+ * properly. calls to SetRedraw must be balanced.
+ *
+ * fEnbaleDraw = TRUE - enable redraw
+ * FALSE - disable redraw
+ */
+void OutlineDoc_SetRedraw(LPOUTLINEDOC lpOutlineDoc, BOOL fEnableDraw)
+{
+ static HCURSOR hPrevCursor = NULL;
+
+ if (fEnableDraw) {
+ if (lpOutlineDoc->m_nDisableDraw == 0)
+ return; // already enabled; no state transition
+
+ if (--lpOutlineDoc->m_nDisableDraw > 0)
+ return; // drawing should still be disabled
+ } else {
+ if (lpOutlineDoc->m_nDisableDraw++ > 0)
+ return; // already disabled; no state transition
+ }
+
+ if (lpOutlineDoc->m_nDisableDraw > 0) {
+ // this may take a while, put up hourglass cursor
+ hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
+ } else {
+ if (hPrevCursor) {
+ SetCursor(hPrevCursor); // restore original cursor
+ hPrevCursor = NULL;
+ }
+ }
+
+#if defined( OLE_SERVER )
+ /* OLE2NOTE: for the Server version, while Redraw is disabled
+ ** postpone sending advise notifications until Redraw is re-enabled.
+ */
+ {
+ LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc;
+ LPSERVERNAMETABLE lpServerNameTable =
+ (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable;
+
+ if (lpOutlineDoc->m_nDisableDraw == 0) {
+ /* drawing is being Enabled. if changes occurred while drawing
+ ** was disabled, then notify clients now.
+ */
+ if (lpServerDoc->m_fDataChanged)
+ ServerDoc_SendAdvise(
+ lpServerDoc,
+ OLE_ONDATACHANGE,
+ NULL, /* lpmkDoc -- not relevant here */
+ 0 /* advf -- no flags necessary */
+ );
+
+ /* OLE2NOTE: send pending change notifications for pseudo objs. */
+ ServerNameTable_SendPendingAdvises(lpServerNameTable);
+
+ }
+ }
+#endif // OLE_SERVER
+
+#if defined( OLE_CNTR )
+ /* OLE2NOTE: for the Container version, while Redraw is disabled
+ ** postpone updating the extents of OLE objects until Redraw is
+ ** re-enabled.
+ */
+ {
+ LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc;
+
+ /* Update the extents of any OLE object that is marked that
+ ** its size may have changed. when an
+ ** IAdviseSink::OnViewChange notification is received,
+ ** the corresponding ContainerLine is marked
+ ** (m_fDoGetExtent==TRUE) and a message
+ ** (WM_U_UPDATEOBJECTEXTENT) is posted to the document
+ ** indicating that there are dirty objects.
+ */
+ if (lpOutlineDoc->m_nDisableDraw == 0)
+ ContainerDoc_UpdateExtentOfAllOleObjects(lpContainerDoc);
+ }
+#endif // OLE_CNTR
+
+ // enable/disable redraw of the LineList listbox
+ LineList_SetRedraw(&lpOutlineDoc->m_LineList, fEnableDraw);
+}
+
+
+/* OutlineDoc_SetSel
+ * -----------------
+ *
+ * Set the selection in the documents's LineList
+ */
+void OutlineDoc_SetSel(LPOUTLINEDOC lpOutlineDoc, LPLINERANGE lplrSel)
+{
+ LineList_SetSel(&lpOutlineDoc->m_LineList, lplrSel);
+}
+
+
+/* OutlineDoc_GetSel
+ * -----------------
+ *
+ * Get the selection in the documents's LineList.
+ *
+ * Returns the count of items selected
+ */
+int OutlineDoc_GetSel(LPOUTLINEDOC lpOutlineDoc, LPLINERANGE lplrSel)
+{
+ return LineList_GetSel(&lpOutlineDoc->m_LineList, lplrSel);
+}
+
+
+/* OutlineDoc_ForceRedraw
+ * ----------------------
+ *
+ * Force the document window to repaint.
+ */
+void OutlineDoc_ForceRedraw(LPOUTLINEDOC lpOutlineDoc, BOOL fErase)
+{
+ if (!lpOutlineDoc)
+ return;
+
+ LineList_ForceRedraw(&lpOutlineDoc->m_LineList, fErase);
+ Heading_CH_ForceRedraw(&lpOutlineDoc->m_heading, fErase);
+ Heading_RH_ForceRedraw(&lpOutlineDoc->m_heading, fErase);
+}
+
+
+/* OutlineDoc_RenderFormat
+ * -----------------------
+ *
+ * Render a clipboard format supported by ClipboardDoc
+ */
+void OutlineDoc_RenderFormat(LPOUTLINEDOC lpOutlineDoc, UINT uFormat)
+{
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+ HGLOBAL hData = NULL;
+
+ if (uFormat == lpOutlineApp->m_cfOutline)
+ hData = OutlineDoc_GetOutlineData(lpOutlineDoc, NULL);
+
+ else if (uFormat == CF_TEXT)
+ hData = OutlineDoc_GetTextData(lpOutlineDoc, NULL);
+
+ else {
+ OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgFormatNotSupported);
+ return;
+ }
+
+ SetClipboardData(uFormat, hData);
+}
+
+
+/* OutlineDoc_RenderAllFormats
+ * ---------------------------
+ *
+ * Render all formats supported by ClipboardDoc
+ */
+void OutlineDoc_RenderAllFormats(LPOUTLINEDOC lpOutlineDoc)
+{
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+ HGLOBAL hData = NULL;
+
+ OpenClipboard(lpOutlineDoc->m_hWndDoc);
+
+ hData = OutlineDoc_GetOutlineData(lpOutlineDoc, NULL);
+ SetClipboardData(lpOutlineApp->m_cfOutline, hData);
+
+ hData = OutlineDoc_GetTextData(lpOutlineDoc, NULL);
+ SetClipboardData(CF_TEXT, hData);
+
+ CloseClipboard();
+}
+
+
+
+/* OutlineDoc_GetOutlineData
+ * -------------------------
+ *
+ * Return a handle to an array of TextLine objects for the desired line
+ * range.
+ * NOTE: if lplrSel == NULL, then all lines are returned
+ *
+ */
+HGLOBAL OutlineDoc_GetOutlineData(LPOUTLINEDOC lpOutlineDoc, LPLINERANGE lplrSel)
+{
+ HGLOBAL hOutline = NULL;
+ LPLINELIST lpLL=(LPLINELIST)&lpOutlineDoc->m_LineList;
+ LPLINE lpLine;
+ LPTEXTLINE arrLine;
+ int i;
+ int nStart = (lplrSel ? lplrSel->m_nStartLine : 0);
+ int nEnd =(lplrSel ? lplrSel->m_nEndLine : LineList_GetCount(lpLL)-1);
+ int nLines = nEnd - nStart + 1;
+ int nCopied = 0;
+
+ hOutline=GlobalAlloc(GMEM_SHARE | GMEM_ZEROINIT,sizeof(TEXTLINE)*nLines);
+
+ if (! hOutline) return NULL;
+
+ arrLine=(LPTEXTLINE)GlobalLock(hOutline);
+
+ for (i = nStart; i <= nEnd; i++) {
+ lpLine=LineList_GetLine(lpLL, i);
+ if (lpLine && Line_GetOutlineData(lpLine, &arrLine[nCopied]))
+ nCopied++;
+ }
+
+ GlobalUnlock(hOutline);
+
+ return hOutline;
+}
+
+
+
+/* OutlineDoc_GetTextData
+ * ----------------------
+ *
+ * Return a handle to an object's data in text form for the desired line
+ * range.
+ * NOTE: if lplrSel == NULL, then all lines are returned
+ *
+ */
+HGLOBAL OutlineDoc_GetTextData(LPOUTLINEDOC lpOutlineDoc, LPLINERANGE lplrSel)
+{
+ LPLINELIST lpLL=(LPLINELIST)&lpOutlineDoc->m_LineList;
+ LPLINE lpLine;
+ HGLOBAL hText = NULL;
+ LPSTR lpszText = NULL;
+ DWORD dwMemSize=0;
+ int i,j;
+ int nStart = (lplrSel ? lplrSel->m_nStartLine : 0);
+ int nEnd =(lplrSel ? lplrSel->m_nEndLine : LineList_GetCount(lpLL)-1);
+ int nTabLevel;
+
+ // calculate memory size required
+ for(i = nStart; i <= nEnd; i++) {
+ lpLine=LineList_GetLine(lpLL, i);
+ if (! lpLine)
+ continue;
+
+ dwMemSize += Line_GetTabLevel(lpLine);
+ dwMemSize += Line_GetTextLen(lpLine);
+
+ dwMemSize += 2; // add 1 for '\r\n' at the end of each line
+ }
+ dwMemSize++; // add 1 for '\0' at the end of string
+
+ if(!(hText = GlobalAlloc(GMEM_SHARE | GMEM_ZEROINIT, dwMemSize)))
+ return NULL;
+
+ if(!(lpszText = (LPSTR)GlobalLock(hText)))
+ return NULL;
+
+ // put line text to memory
+ for(i = nStart; i <= nEnd; i++) {
+ lpLine=LineList_GetLine(lpLL, i);
+ if (! lpLine)
+ continue;
+
+ nTabLevel=Line_GetTabLevel(lpLine);
+ for(j = 0; j < nTabLevel; j++)
+ *lpszText++='\t';
+
+ Line_GetTextData(lpLine, lpszText);
+ while(*lpszText)
+ lpszText++; // advance to end of string
+
+ *lpszText++ = '\r';
+ *lpszText++ = '\n';
+ }
+
+ GlobalUnlock (hText);
+
+ return hText;
+}
+
+
+/* OutlineDoc_SaveToFile
+ * ---------------------
+ *
+ * Save the document to a file with the same name as stored in the
+ * document
+ */
+BOOL OutlineDoc_SaveToFile(LPOUTLINEDOC lpOutlineDoc, LPCSTR lpszFileName, UINT uFormat, BOOL fRemember)
+{
+#if defined( OLE_CNTR )
+ // Call OLE container specific function instead
+ return ContainerDoc_SaveToFile(
+ (LPCONTAINERDOC)lpOutlineDoc,
+ lpszFileName,
+ uFormat,
+ fRemember
+ );
+
+#else
+
+ LPSTORAGE lpDestStg = NULL;
+ HRESULT hrErr;
+ BOOL fStatus;
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+
+ if (fRemember) {
+ if (lpszFileName) {
+ fStatus = OutlineDoc_SetFileName(
+ lpOutlineDoc,
+ (LPSTR)lpszFileName,
+ NULL
+ );
+ if (! fStatus) goto error;
+ } else
+ lpszFileName = lpOutlineDoc->m_szFileName; // use cur. file name
+ } else if (! lpszFileName) {
+ goto error;
+ }
+
+ hrErr = StgCreateDocfileA(
+ lpszFileName,
+ STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE|STGM_CREATE,
+ 0,
+ &lpDestStg
+ );
+
+ OleDbgAssertSz(hrErr == NOERROR, "Could not create Docfile");
+ if (hrErr != NOERROR)
+ goto error;
+
+#if defined( OLE_SERVER )
+
+ /* OLE2NOTE: we must be sure to write our class ID into our
+ ** storage. this information is used by OLE to determine the
+ ** class of the data stored in our storage. Even for top
+ ** "file-level" objects this information should be written to
+ ** the file.
+ */
+ if(WriteClassStg(lpDestStg, &CLSID_APP) != NOERROR)
+ goto error;
+#endif
+
+ fStatus = OutlineDoc_SaveSelToStg(
+ lpOutlineDoc,
+ NULL,
+ uFormat,
+ lpDestStg,
+ FALSE, /* fSameAsLoad */
+ fRemember
+ );
+ if (! fStatus) goto error;
+
+ OleStdRelease((LPUNKNOWN)lpDestStg);
+
+ if (fRemember)
+ OutlineDoc_SetModified(lpOutlineDoc, FALSE, FALSE, FALSE);
+
+#if defined( OLE_SERVER )
+
+ /* OLE2NOTE: (SERVER-ONLY) inform any linking clients that the
+ ** document has been saved. in addition, any currently active
+ ** pseudo objects should also inform their clients.
+ */
+ ServerDoc_SendAdvise (
+ (LPSERVERDOC)lpOutlineDoc,
+ OLE_ONSAVE,
+ NULL, /* lpmkDoc -- not relevant here */
+ 0 /* advf -- not relevant here */
+ );
+
+#endif
+
+ return TRUE;
+
+error:
+ if (lpDestStg)
+ OleStdRelease((LPUNKNOWN)lpDestStg);
+
+ OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgSaving);
+ return FALSE;
+
+#endif // ! OLE_CNTR
+}
+
+
+/* OutlineDoc_LoadFromFile
+ * -----------------------
+ *
+ * Load a document from a file
+ */
+BOOL OutlineDoc_LoadFromFile(LPOUTLINEDOC lpOutlineDoc, LPSTR lpszFileName)
+{
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+ LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
+ HRESULT hrErr;
+ SCODE sc;
+ LPSTORAGE lpSrcStg;
+ BOOL fStatus;
+
+ hrErr = StgOpenStorageA(lpszFileName,
+ NULL,
+#if defined( OLE_CNTR )
+ STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_DENY_WRITE,
+#else
+ STGM_READ | STGM_SHARE_DENY_WRITE,
+#endif
+ NULL,
+ 0,
+ &lpSrcStg
+ );
+
+ if ((sc = GetScode(hrErr)) == STG_E_FILENOTFOUND) {
+ OutlineApp_ErrorMessage(lpOutlineApp, "File not found");
+ return FALSE;
+ } else if (sc == STG_E_FILEALREADYEXISTS) {
+ OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgFormat);
+ return FALSE;
+ } else if (sc != S_OK) {
+ OleDbgOutScode("StgOpenStorage returned", sc);
+ OutlineApp_ErrorMessage(
+ lpOutlineApp,
+ "File already in use--could not be opened"
+ );
+ return FALSE;
+ }
+
+ if(! OutlineDoc_LoadFromStg(lpOutlineDoc, lpSrcStg)) goto error;
+
+ fStatus = OutlineDoc_SetFileName(lpOutlineDoc, lpszFileName, lpSrcStg);
+ if (! fStatus) goto error;
+
+ OleStdRelease((LPUNKNOWN)lpSrcStg);
+
+ return TRUE;
+
+error:
+ OleStdRelease((LPUNKNOWN)lpSrcStg);
+ OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgOpening);
+ return FALSE;
+}
+
+
+
+/* OutlineDoc_LoadFromStg
+ * ----------------------
+ *
+ * Load entire document from an open IStorage pointer (lpSrcStg)
+ * Return TRUE if ok, FALSE if error.
+ */
+BOOL OutlineDoc_LoadFromStg(LPOUTLINEDOC lpOutlineDoc, LPSTORAGE lpSrcStg)
+{
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+ HRESULT hrErr;
+ BOOL fStatus;
+ ULONG nRead;
+ LINERANGE lrSel = { 0, 0 };
+ LPSTREAM lpLLStm;
+ OUTLINEDOCHEADER_ONDISK docRecordOnDisk;
+ OUTLINEDOCHEADER docRecord;
+
+ hrErr = CallIStorageOpenStreamA(
+ lpSrcStg,
+ "LineList",
+ NULL,
+ STGM_READ | STGM_SHARE_EXCLUSIVE,
+ 0,
+ &lpLLStm
+ );
+
+ if (hrErr != NOERROR) {
+ OleDbgOutHResult("Open LineList Stream returned", hrErr);
+ goto error;
+ }
+
+ /* read OutlineDoc header record */
+ hrErr = lpLLStm->lpVtbl->Read(
+ lpLLStm,
+ (LPVOID)&docRecordOnDisk,
+ sizeof(docRecordOnDisk),
+ &nRead
+ );
+
+ if (hrErr != NOERROR) {
+ OleDbgOutHResult("Read OutlineDoc header returned", hrErr);
+ goto error;
+ }
+
+ // Transform docRecordOnDisk into docRecord
+ // Compilers should handle aligment correctly
+ strcpy(docRecord.m_szFormatName, docRecordOnDisk.m_szFormatName);
+ docRecord.m_narrAppVersionNo[0] = (int) docRecordOnDisk.m_narrAppVersionNo[0];
+ docRecord.m_narrAppVersionNo[1] = (int) docRecordOnDisk.m_narrAppVersionNo[1];
+ docRecord.m_fShowHeading = (BOOL) docRecordOnDisk.m_fShowHeading;
+ docRecord.m_reserved1 = docRecordOnDisk.m_reserved1;
+ docRecord.m_reserved2 = docRecordOnDisk.m_reserved2;
+ docRecord.m_reserved3 = docRecordOnDisk.m_reserved3;
+ docRecord.m_reserved4 = docRecordOnDisk.m_reserved4;
+
+ fStatus = OutlineApp_VersionNoCheck(
+ lpOutlineApp,
+ docRecord.m_szFormatName,
+ docRecord.m_narrAppVersionNo
+ );
+
+ /* storage is an incompatible version; file can not be read */
+ if (! fStatus)
+ goto error;
+
+ lpOutlineDoc->m_heading.m_fShow = docRecord.m_fShowHeading;
+
+#if defined( OLE_SERVER )
+ {
+ // Load ServerDoc specific data
+ LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc;
+#if defined( SVR_TREATAS )
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+ CLSID clsid;
+ CLIPFORMAT cfFmt;
+ LPSTR lpszType;
+#endif // SVR_TREATAS
+
+ lpServerDoc->m_nNextRangeNo = (ULONG)docRecord.m_reserved1;
+
+#if defined( SVR_TREATAS )
+ /* OLE2NOTE: if the Server is capable of supporting "TreatAs"
+ ** (aka. ActivateAs), it must read the class that is written
+ ** into the storage. if this class is NOT the app's own
+ ** class ID, then this is a TreatAs operation. the server
+ ** then must faithfully pretend to be the class that is
+ ** written into the storage. it must also faithfully write
+ ** the data back to the storage in the SAME format as is
+ ** written in the storage.
+ **
+ ** SVROUTL and ISVROTL can emulate each other. they have the
+ ** simplification that they both read/write the identical
+ ** format. thus for these apps no actual conversion of the
+ ** native bits is actually required.
+ */
+ lpServerDoc->m_clsidTreatAs = CLSID_NULL;
+ if (OleStdGetTreatAsFmtUserType(&CLSID_APP, lpSrcStg, &clsid,
+ (CLIPFORMAT FAR*)&cfFmt, (LPSTR FAR*)&lpszType)) {
+
+ if (cfFmt == lpOutlineApp->m_cfOutline) {
+ // We should perform TreatAs operation
+ if (lpServerDoc->m_lpszTreatAsType)
+ OleStdFreeString(lpServerDoc->m_lpszTreatAsType, NULL);
+
+ lpServerDoc->m_clsidTreatAs = clsid;
+ ((LPOUTLINEDOC)lpServerDoc)->m_cfSaveFormat = cfFmt;
+ lpServerDoc->m_lpszTreatAsType = lpszType;
+
+ OleDbgOut3("OutlineDoc_LoadFromStg: TreateAs ==> '");
+ OleDbgOutNoPrefix3(lpServerDoc->m_lpszTreatAsType);
+ OleDbgOutNoPrefix3("'\r\n");
+ } else {
+ // ERROR: we ONLY support TreatAs for CF_OUTLINE format
+ OleDbgOut("SvrDoc_PStg_InitNew: INVALID TreatAs Format\r\n");
+ OleStdFreeString(lpszType, NULL);
+ }
+ }
+#endif // SVR_TREATAS
+ }
+#endif // OLE_SVR
+#if defined( OLE_CNTR )
+ {
+ // Load ContainerDoc specific data
+ LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc;
+
+ lpContainerDoc->m_nNextObjNo = (ULONG)docRecord.m_reserved2;
+ }
+#endif // OLE_CNTR
+
+ OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE );
+
+ if(! LineList_LoadFromStg(&lpOutlineDoc->m_LineList, lpSrcStg, lpLLStm))
+ goto error;
+ if(! OutlineNameTable_LoadFromStg(lpOutlineDoc->m_lpNameTable, lpSrcStg))
+ goto error;
+
+ OutlineDoc_SetModified(lpOutlineDoc, FALSE, FALSE, FALSE);
+ OutlineDoc_SetSel(lpOutlineDoc, &lrSel);
+
+ OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE );
+
+ OleStdRelease((LPUNKNOWN)lpLLStm);
+
+#if defined( OLE_CNTR )
+ {
+ LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc;
+
+ /* A ContainerDoc keeps its storage open at all times. it is necessary
+ * to AddRef the lpSrcStg in order to hang on to it.
+ */
+ if (lpOleDoc->m_lpStg) {
+ OleStdVerifyRelease((LPUNKNOWN)lpOleDoc->m_lpStg,
+ "Doc Storage not released properly");
+ }
+ lpSrcStg->lpVtbl->AddRef(lpSrcStg);
+ lpOleDoc->m_lpStg = lpSrcStg;
+ }
+#endif // OLE_CNTR
+
+ return TRUE;
+
+error:
+ OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE );
+ if (lpLLStm)
+ OleStdRelease((LPUNKNOWN)lpLLStm);
+ return FALSE;
+}
+
+BOOL Booga(void)
+{
+ return FALSE;
+}
+
+
+/* OutlineDoc_SaveSelToStg
+ * -----------------------
+ *
+ * Save the specified selection of document into an IStorage*. All lines
+ * within the selection along with any names completely contained within the
+ * selection will be written
+ *
+ * Return TRUE if ok, FALSE if error
+ */
+BOOL OutlineDoc_SaveSelToStg(
+ LPOUTLINEDOC lpOutlineDoc,
+ LPLINERANGE lplrSel,
+ UINT uFormat,
+ LPSTORAGE lpDestStg,
+ BOOL fSameAsLoad,
+ BOOL fRemember
+)
+{
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+ HRESULT hrErr = NOERROR;
+ LPSTREAM lpLLStm = NULL;
+ LPSTREAM lpNTStm = NULL;
+ ULONG nWritten;
+ BOOL fStatus;
+ OUTLINEDOCHEADER docRecord;
+ OUTLINEDOCHEADER_ONDISK docRecordOnDisk;
+ HCURSOR hPrevCursor;
+
+#if defined( OLE_VERSION )
+ LPSTR lpszUserType;
+ LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc;
+
+ /* OLE2NOTE: we must be sure to write the information required for
+ ** OLE into our docfile. this includes user type
+ ** name, data format, etc. Even for top "file-level" objects
+ ** this information should be written to the file. Both
+ ** containters and servers should write this information.
+ */
+
+#if defined( OLE_SERVER ) && defined( SVR_TREATAS )
+ LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc;
+
+ /* OLE2NOTE: if the Server is emulating another class (ie.
+ ** "TreatAs" aka. ActivateAs), it must write the same user type
+ ** name and format that was was originally written into the
+ ** storage rather than its own user type name.
+ **
+ ** SVROUTL and ISVROTL can emulate each other. they have the
+ ** simplification that they both read/write the identical
+ ** format. thus for these apps no actual conversion of the
+ ** native bits is actually required.
+ */
+ if (! IsEqualCLSID(&lpServerDoc->m_clsidTreatAs, &CLSID_NULL))
+ lpszUserType = lpServerDoc->m_lpszTreatAsType;
+ else
+#endif // OLE_SERVER && SVR_TREATAS
+
+ lpszUserType = (LPSTR)FULLUSERTYPENAME;
+
+ hrErr = WriteFmtUserTypeStgA(lpDestStg, (CLIPFORMAT) uFormat,
+ lpszUserType);
+
+ if(hrErr != NOERROR) goto error;
+
+ if (fSameAsLoad) {
+ /* OLE2NOTE: we are saving into to same storage that we were
+ ** passed an load time. we deliberatly opened the streams we
+ ** need (lpLLStm and lpNTStm) at load time, so that we can
+ ** robustly save at save time in a low-memory situation.
+ ** this is particulary important the embedded objects do NOT
+ ** consume additional memory when
+ ** IPersistStorage::Save(fSameAsLoad==TRUE) is called.
+ */
+ LARGE_INTEGER libZero;
+ ULARGE_INTEGER ulibZero;
+ LISet32( libZero, 0 );
+ LISet32( ulibZero, 0 );
+ lpLLStm = lpOleDoc->m_lpLLStm;
+
+ /* because this is the fSameAsLoad==TRUE case, we will save
+ ** into the streams that we hold open. we will AddRef the
+ ** stream here so that the release below will NOT close the
+ ** stream.
+ */
+ lpLLStm->lpVtbl->AddRef(lpLLStm);
+
+ // truncate the current stream and seek to beginning
+ lpLLStm->lpVtbl->SetSize(lpLLStm, ulibZero);
+ lpLLStm->lpVtbl->Seek(
+ lpLLStm, libZero, STREAM_SEEK_SET, NULL);
+
+ lpNTStm = lpOleDoc->m_lpNTStm;
+ lpNTStm->lpVtbl->AddRef(lpNTStm); // (see comment above)
+
+ // truncate the current stream and seek to beginning
+ lpNTStm->lpVtbl->SetSize(lpNTStm, ulibZero);
+ lpNTStm->lpVtbl->Seek(
+ lpNTStm, libZero, STREAM_SEEK_SET, NULL);
+ } else
+#endif // OLE_VERSION
+ {
+ hrErr = CallIStorageCreateStreamA(
+ lpDestStg,
+ "LineList",
+ STGM_WRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
+ 0,
+ 0,
+ &lpLLStm
+ );
+
+ if (hrErr != NOERROR) {
+ OleDbgAssertSz(hrErr==NOERROR,"Could not create LineList stream");
+ OleDbgOutHResult("LineList CreateStream returned", hrErr);
+ goto error;
+ }
+
+ hrErr = CallIStorageCreateStreamA(
+ lpDestStg,
+ "NameTable",
+ STGM_WRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
+ 0,
+ 0,
+ &lpNTStm
+ );
+
+ if (hrErr != NOERROR) {
+ OleDbgAssertSz(hrErr==NOERROR,"Could not create NameTable stream");
+ OleDbgOutHResult("NameTable CreateStream returned", hrErr);
+ goto error;
+ }
+ }
+
+ // this may take a while, put up hourglass cursor
+ hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
+
+ _fmemset((LPOUTLINEDOCHEADER)&docRecord,0,sizeof(OUTLINEDOCHEADER));
+ GetClipboardFormatName(
+ uFormat,
+ docRecord.m_szFormatName,
+ sizeof(docRecord.m_szFormatName)
+ );
+ OutlineApp_GetAppVersionNo(lpOutlineApp, docRecord.m_narrAppVersionNo);
+
+ docRecord.m_fShowHeading = lpOutlineDoc->m_heading.m_fShow;
+
+#if defined( OLE_SERVER )
+ {
+ // Store ServerDoc specific data
+ LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc;
+
+ docRecord.m_reserved1 = (DWORD)lpServerDoc->m_nNextRangeNo;
+ }
+#endif
+#if defined( OLE_CNTR )
+ {
+ // Store ContainerDoc specific data
+ LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc;
+
+ docRecord.m_reserved2 = (DWORD)lpContainerDoc->m_nNextObjNo;
+ }
+#endif
+
+ /* write OutlineDoc header record */
+
+ // Transform docRecord into docRecordOnDisk
+ // Compilers should handle aligment correctly
+ strcpy(docRecordOnDisk.m_szFormatName, docRecord.m_szFormatName);
+ docRecordOnDisk.m_narrAppVersionNo[0] = (short) docRecord.m_narrAppVersionNo[0];
+ docRecordOnDisk.m_narrAppVersionNo[1] = (short) docRecord.m_narrAppVersionNo[1];
+ docRecordOnDisk.m_fShowHeading = (USHORT) docRecord.m_fShowHeading;
+ docRecordOnDisk.m_reserved1 = docRecord.m_reserved1;
+ docRecordOnDisk.m_reserved2 = docRecord.m_reserved2;
+ docRecordOnDisk.m_reserved3 = docRecord.m_reserved3;
+ docRecordOnDisk.m_reserved4 = docRecord.m_reserved4;
+
+ hrErr = lpLLStm->lpVtbl->Write(
+ lpLLStm,
+ (LPVOID)&docRecordOnDisk,
+ sizeof(docRecordOnDisk),
+ &nWritten
+ );
+
+ if (hrErr != NOERROR) {
+ OleDbgOutHResult("Write OutlineDoc header returned", hrErr);
+ goto error;
+ }
+
+ // Save LineList
+ /* OLE2NOTE: A ContainerDoc keeps its storage open at all times. It is
+ ** necessary to pass the current open storage (lpOleDoc->m_lpStg)
+ ** to the LineList_SaveSelToStg method so that currently written data
+ ** for any embeddings is also saved to the new destination
+ ** storage. The data required by a contained object is both the
+ ** ContainerLine information and the associated sub-storage that is
+ ** written directly by the embedded object.
+ */
+ fStatus = LineList_SaveSelToStg(
+ &lpOutlineDoc->m_LineList,
+ lplrSel,
+ uFormat,
+#if defined( OLE_CNTR )
+ lpOleDoc->m_lpStg,
+#else
+ NULL,
+#endif
+ lpDestStg,
+ lpLLStm,
+ fRemember
+ );
+ if (! fStatus) goto error;
+
+ // Save associated NameTable
+ fStatus = OutlineNameTable_SaveSelToStg(
+ lpOutlineDoc->m_lpNameTable,
+ lplrSel,
+ uFormat,
+ lpNTStm
+ );
+
+ if (! fStatus) goto error;
+
+ OleStdRelease((LPUNKNOWN)lpLLStm);
+ lpOutlineDoc->m_cfSaveFormat = uFormat; // remember format used to save
+
+ SetCursor(hPrevCursor); // restore original cursor
+ return TRUE;
+
+error:
+ if (lpLLStm)
+ OleStdRelease((LPUNKNOWN)lpLLStm);
+
+ SetCursor(hPrevCursor); // restore original cursor
+ return FALSE;
+}
+
+
+/* OutlineDoc_Print
+ * ----------------
+ * Prints the contents of the list box in HIMETRIC mapping mode. Origin
+ * remains to be the upper left corner and the print proceeds down the
+ * page using a negative y-cordinate.
+ *
+ */
+void OutlineDoc_Print(LPOUTLINEDOC lpOutlineDoc, HDC hDC)
+{
+ LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
+ LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
+ WORD nIndex;
+ WORD nTotal;
+ int dy;
+ BOOL fError = FALSE;
+ LPLINE lpLine;
+ RECT rcLine;
+ RECT rcPix;
+ RECT rcHim;
+ RECT rcWindowOld;
+ RECT rcViewportOld;
+ HFONT hOldFont;
+ DOCINFO di; /* Document information for StartDoc function */
+
+ /* Get dimension of page */
+ rcPix.left = 0;
+ rcPix.top = 0;
+ rcPix.right = GetDeviceCaps(hDC, HORZRES);
+ rcPix.bottom = GetDeviceCaps(hDC, VERTRES);
+
+ SetDCToDrawInHimetricRect(hDC, (LPRECT)&rcPix, (LPRECT)&rcHim,
+ (LPRECT)&rcWindowOld, (LPRECT)&rcViewportOld);
+
+ // Set the default font size, and font face name
+ hOldFont = SelectObject(hDC, lpOutlineApp->m_hStdFont);
+
+ /* Get the lines in document */
+ nIndex = 0;
+ nTotal = LineList_GetCount(lpLL);
+
+ /* Create the Cancel dialog */
+ // REVIEW: should load dialog title from string resource file
+ hWndPDlg = CreateDialog (
+ lpOutlineApp->m_hInst,
+ "Print",
+ lpOutlineApp->m_hWndApp,
+ (DLGPROC)PrintDlgProc
+ );
+
+ if(!hWndPDlg)
+ goto getout;
+
+ /* Allow the app. to inform GDI of the abort function to call */
+ if(SetAbortProc(hDC, (ABORTPROC)AbortProc) < 0) {
+ fError = TRUE;
+ goto getout3;
+ }
+
+ /* Disable the main application window */
+ EnableWindow (lpOutlineApp->m_hWndApp, FALSE);
+
+ // initialize the rectangle for the first line
+ rcLine.left = rcHim.left;
+ rcLine.bottom = rcHim.top;
+
+ /* Initialize the document */
+ fCancelPrint = FALSE;
+
+ di.cbSize = sizeof(di);
+ di.lpszDocName = lpOutlineDoc->m_lpszDocTitle;
+ di.lpszOutput = NULL;
+
+ if(StartDoc(hDC, (DOCINFO FAR*)&di) <= 0) {
+ fError = TRUE;
+ OleDbgOut2("StartDoc error\n");
+ goto getout5;
+ }
+
+ if(StartPage(hDC) <= 0) { // start first page
+ fError = TRUE;
+ OleDbgOut2("StartPage error\n");
+ goto getout2;
+ }
+
+ /* While more lines print out the text */
+ while(nIndex < nTotal) {
+ lpLine = LineList_GetLine(lpLL, nIndex);
+ if (! lpLine)
+ continue;
+
+ dy = Line_GetHeightInHimetric(lpLine);
+
+ /* Reached end of page. Tell the device driver to eject a page */
+ if(rcLine.bottom - dy < rcHim.bottom) {
+ if (EndPage(hDC) < 0) {
+ fError=TRUE;
+ OleDbgOut2("EndPage error\n");
+ goto getout2;
+ }
+
+ // NOTE: Reset the Mapping mode of DC
+ SetDCToDrawInHimetricRect(hDC, (LPRECT)&rcPix, (LPRECT)&rcHim,
+ (LPRECT)&rcWindowOld, (LPRECT)&rcViewportOld);
+
+ // Set the default font size, and font face name
+ SelectObject(hDC, lpOutlineApp->m_hStdFont);
+
+ if (StartPage(hDC) <= 0) {
+ fError=TRUE;
+ OleDbgOut2("StartPage error\n");
+ goto getout2;
+ }
+
+ rcLine.bottom = rcHim.top;
+ }
+
+ rcLine.top = rcLine.bottom;
+ rcLine.bottom -= dy;
+ rcLine.right = rcLine.left + Line_GetWidthInHimetric(lpLine);
+
+ /* Print the line */
+ Line_Draw(lpLine, hDC, &rcLine, NULL, FALSE /*fHighlight*/);
+
+ OleDbgOut2("a line is drawn\n");
+
+ /* Test and see if the Abort flag has been set. If yes, exit. */
+ if (fCancelPrint)
+ goto getout2;
+
+ /* Move down the page */
+ nIndex++;
+ }
+
+ {
+ int nCode;
+
+ /* Eject the last page. */
+ if((nCode = EndPage(hDC)) < 0) {
+#if defined( _DEBUG )
+ char szBuf[255];
+ wsprintf(szBuf, "EndPage error code is %d\n", nCode);
+ OleDbgOut2(szBuf);
+#endif
+ fError=TRUE;
+ goto getout2;
+ }
+ }
+
+
+ /* Complete the document. */
+ if(EndDoc(hDC) < 0) {
+ fError=TRUE;
+ OleDbgOut2("EndDoc error\n");
+
+getout2:
+ /* Ran into a problem before NEWFRAME? Abort the document */
+ AbortDoc(hDC);
+ }
+
+getout5:
+ /* Re-enable main app. window */
+ EnableWindow (lpOutlineApp->m_hWndApp, TRUE);
+
+getout3:
+ /* Close the cancel dialog */
+ DestroyWindow (hWndPDlg);
+
+getout:
+
+ /* Error? make sure the user knows... */
+ if(fError || CommDlgExtendedError())
+ OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgPrint);
+
+ SelectObject(hDC, hOldFont);
+}
+
+
+
+
+
+/* OutlineDoc_DialogHelp
+ * ---------------------
+ *
+ * Show help message for ole2ui dialogs.
+ *
+ * Parameters:
+ *
+ * hDlg HWND to the dialog the help message came from - use
+ * this in the call to WinHelp/MessageBox so that
+ * activation/focus goes back to the dialog, and not the
+ * main window.
+ *
+ * wParam ID of the dialog (so we know what type of dialog it is).
+ */
+void OutlineDoc_DialogHelp(HWND hDlg, WPARAM wDlgID)
+{
+
+ char szMessageBoxText[64];
+
+ if (!IsWindow(hDlg)) // don't do anything if we've got a bogus hDlg.
+ return;
+
+ lstrcpy(szMessageBoxText, "Help Message for ");
+
+ switch (wDlgID)
+ {
+
+ case IDD_CONVERT:
+ lstrcat(szMessageBoxText, "Convert");
+ break;
+
+ case IDD_CHANGEICON:
+ lstrcat(szMessageBoxText, "Change Icon");
+ break;
+
+ case IDD_INSERTOBJECT:
+ lstrcat(szMessageBoxText, "Insert Object");
+ break;
+
+ case IDD_PASTESPECIAL:
+ lstrcat(szMessageBoxText, "Paste Special");
+ break;
+
+ case IDD_EDITLINKS:
+ lstrcat(szMessageBoxText, "Edit Links");
+ break;
+
+ case IDD_CHANGESOURCE:
+ lstrcat(szMessageBoxText, "Change Source");
+ break;
+
+ case IDD_INSERTFILEBROWSE:
+ lstrcat(szMessageBoxText, "Insert From File Browse");
+ break;
+
+ case IDD_CHANGEICONBROWSE:
+ lstrcat(szMessageBoxText, "Change Icon Browse");
+ break;
+
+ default:
+ lstrcat(szMessageBoxText, "Unknown");
+ break;
+ }
+
+ lstrcat(szMessageBoxText, " Dialog.");
+
+ // You'd probably really a call to WinHelp here.
+ MessageBox(hDlg, szMessageBoxText, "Help", MB_OK);
+
+ return;
+}
+
+
+/* OutlineDoc_SetCurrentZoomCommand
+ * --------------------------------
+ *
+ * Set current zoom level to be checked in the menu.
+ * Set the corresponding scalefactor for the document.
+ */
+void OutlineDoc_SetCurrentZoomCommand(
+ LPOUTLINEDOC lpOutlineDoc,
+ UINT uCurrentZoom
+)
+{
+ SCALEFACTOR scale;
+
+ if (!lpOutlineDoc)
+ return;
+
+ lpOutlineDoc->m_uCurrentZoom = uCurrentZoom;
+
+ switch (uCurrentZoom) {
+
+#if !defined( OLE_CNTR )
+ case IDM_V_ZOOM_400:
+ scale.dwSxN = (DWORD) 4;
+ scale.dwSxD = (DWORD) 1;
+ scale.dwSyN = (DWORD) 4;
+ scale.dwSyD = (DWORD) 1;
+ break;
+
+ case IDM_V_ZOOM_300:
+ scale.dwSxN = (DWORD) 3;
+ scale.dwSxD = (DWORD) 1;
+ scale.dwSyN = (DWORD) 3;
+ scale.dwSyD = (DWORD) 1;
+ break;
+
+ case IDM_V_ZOOM_200:
+ scale.dwSxN = (DWORD) 2;
+ scale.dwSxD = (DWORD) 1;
+ scale.dwSyN = (DWORD) 2;
+ scale.dwSyD = (DWORD) 1;
+ break;
+#endif // !OLE_CNTR
+
+ case IDM_V_ZOOM_100:
+ scale.dwSxN = (DWORD) 1;
+ scale.dwSxD = (DWORD) 1;
+ scale.dwSyN = (DWORD) 1;
+ scale.dwSyD = (DWORD) 1;
+ break;
+
+ case IDM_V_ZOOM_75:
+ scale.dwSxN = (DWORD) 3;
+ scale.dwSxD = (DWORD) 4;
+ scale.dwSyN = (DWORD) 3;
+ scale.dwSyD = (DWORD) 4;
+ break;
+
+ case IDM_V_ZOOM_50:
+ scale.dwSxN = (DWORD) 1;
+ scale.dwSxD = (DWORD) 2;
+ scale.dwSyN = (DWORD) 1;
+ scale.dwSyD = (DWORD) 2;
+ break;
+
+ case IDM_V_ZOOM_25:
+ scale.dwSxN = (DWORD) 1;
+ scale.dwSxD = (DWORD) 4;
+ scale.dwSyN = (DWORD) 1;
+ scale.dwSyD = (DWORD) 4;
+ break;
+ }
+
+ OutlineDoc_SetScaleFactor(lpOutlineDoc, (LPSCALEFACTOR)&scale, NULL);
+}
+
+
+/* OutlineDoc_GetCurrentZoomMenuCheck
+ * ----------------------------------
+ *
+ * Get current zoom level to be checked in the menu.
+ */
+UINT OutlineDoc_GetCurrentZoomMenuCheck(LPOUTLINEDOC lpOutlineDoc)
+{
+ return lpOutlineDoc->m_uCurrentZoom;
+}
+
+
+/* OutlineDoc_SetScaleFactor
+ * -------------------------
+ *
+ * Set the scale factor of the document which will affect the
+ * size of the document on the screen
+ *
+ * Parameters:
+ *
+ * scale structure containing x and y scales
+ */
+void OutlineDoc_SetScaleFactor(
+ LPOUTLINEDOC lpOutlineDoc,
+ LPSCALEFACTOR lpscale,
+ LPRECT lprcDoc
+)
+{
+ LPLINELIST lpLL = OutlineDoc_GetLineList(lpOutlineDoc);
+ HWND hWndLL = LineList_GetWindow(lpLL);
+
+ if (!lpOutlineDoc || !lpscale)
+ return;
+
+ InvalidateRect(hWndLL, NULL, TRUE);
+
+ lpOutlineDoc->m_scale = *lpscale;
+ LineList_ReScale((LPLINELIST)&lpOutlineDoc->m_LineList, lpscale);
+
+#if defined( USE_HEADING )
+ Heading_ReScale((LPHEADING)&lpOutlineDoc->m_heading, lpscale);
+#endif
+
+ OutlineDoc_Resize(lpOutlineDoc, lprcDoc);
+}
+
+
+/* OutlineDoc_GetScaleFactor
+ * -------------------------
+ *
+ * Retrieve the scale factor of the document
+ *
+ * Parameters:
+ *
+ */
+LPSCALEFACTOR OutlineDoc_GetScaleFactor(LPOUTLINEDOC lpOutlineDoc)
+{
+ if (!lpOutlineDoc)
+ return NULL;
+
+ return (LPSCALEFACTOR)&lpOutlineDoc->m_scale;
+}
+
+
+/* OutlineDoc_SetCurrentMarginCommand
+ * ----------------------------------
+ *
+ * Set current Margin level to be checked in the menu.
+ */
+void OutlineDoc_SetCurrentMarginCommand(
+ LPOUTLINEDOC lpOutlineDoc,
+ UINT uCurrentMargin
+)
+{
+ if (!lpOutlineDoc)
+ return;
+
+ lpOutlineDoc->m_uCurrentMargin = uCurrentMargin;
+
+ switch (uCurrentMargin) {
+ case IDM_V_SETMARGIN_0:
+ OutlineDoc_SetMargin(lpOutlineDoc, 0, 0);
+ break;
+
+ case IDM_V_SETMARGIN_1:
+ OutlineDoc_SetMargin(lpOutlineDoc, 1000, 1000);
+ break;
+
+ case IDM_V_SETMARGIN_2:
+ OutlineDoc_SetMargin(lpOutlineDoc, 2000, 2000);
+ break;
+
+ case IDM_V_SETMARGIN_3:
+ OutlineDoc_SetMargin(lpOutlineDoc, 3000, 3000);
+ break;
+
+ case IDM_V_SETMARGIN_4:
+ OutlineDoc_SetMargin(lpOutlineDoc, 4000, 4000);
+ break;
+ }
+}
+
+
+/* OutlineDoc_GetCurrentMarginMenuCheck
+ * ------------------------------------
+ *
+ * Get current Margin level to be checked in the menu.
+ */
+UINT OutlineDoc_GetCurrentMarginMenuCheck(LPOUTLINEDOC lpOutlineDoc)
+{
+ return lpOutlineDoc->m_uCurrentMargin;
+}
+
+
+/* OutlineDoc_SetMargin
+ * --------------------
+ *
+ * Set the left and right margin of the document
+ *
+ * Parameters:
+ * nLeftMargin - left margin in Himetric values
+ * nRightMargin - right margin in Himetric values
+ */
+void OutlineDoc_SetMargin(LPOUTLINEDOC lpOutlineDoc, int nLeftMargin, int nRightMargin)
+{
+ LPLINELIST lpLL;
+ int nMaxWidthInHim;
+
+ if (!lpOutlineDoc)
+ return;
+
+ lpOutlineDoc->m_nLeftMargin = nLeftMargin;
+ lpOutlineDoc->m_nRightMargin = nRightMargin;
+ lpLL = OutlineDoc_GetLineList(lpOutlineDoc);
+
+ // Force recalculation of Horizontal extent
+ nMaxWidthInHim = LineList_GetMaxLineWidthInHimetric(lpLL);
+ LineList_SetMaxLineWidthInHimetric(lpLL, -nMaxWidthInHim);
+
+#if defined( INPLACE_CNTR )
+ ContainerDoc_UpdateInPlaceObjectRects((LPCONTAINERDOC)lpOutlineDoc, 0);
+#endif
+
+ OutlineDoc_ForceRedraw(lpOutlineDoc, TRUE);
+}
+
+
+/* OutlineDoc_GetMargin
+ * --------------------
+ *
+ * Get the left and right margin of the document
+ *
+ * Parameters:
+ * nLeftMargin - left margin in Himetric values
+ * nRightMargin - right margin in Himetric values
+ *
+ * Returns:
+ * low order word - left margin
+ * high order word - right margin
+ */
+LONG OutlineDoc_GetMargin(LPOUTLINEDOC lpOutlineDoc)
+{
+ if (!lpOutlineDoc)
+ return 0;
+
+ return MAKELONG(lpOutlineDoc->m_nLeftMargin, lpOutlineDoc->m_nRightMargin);
+}
+
+#if defined( USE_HEADING )
+
+/* OutlineDoc_GetHeading
+ * ---------------------
+ *
+ * Get Heading Object in OutlineDoc
+ */
+LPHEADING OutlineDoc_GetHeading(LPOUTLINEDOC lpOutlineDoc)
+{
+ if (!lpOutlineDoc || lpOutlineDoc->m_fDataTransferDoc)
+ return NULL;
+ else
+ return (LPHEADING)&lpOutlineDoc->m_heading;
+}
+
+
+/* OutlineDoc_ShowHeading
+ * ----------------------
+ *
+ * Show/Hide document row/column headings.
+ */
+void OutlineDoc_ShowHeading(LPOUTLINEDOC lpOutlineDoc, BOOL fShow)
+{
+ LPHEADING lphead = OutlineDoc_GetHeading(lpOutlineDoc);
+#if defined( INPLACE_SVR )
+ LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc;
+#endif
+
+ if (! lphead)
+ return;
+
+ Heading_Show(lphead, fShow);
+
+#if defined( INPLACE_SVR )
+ if (lpServerDoc->m_fUIActive) {
+ LPINPLACEDATA lpIPData = lpServerDoc->m_lpIPData;
+
+ /* OLE2NOTE: our extents have NOT changed; only our the size of
+ ** our object-frame adornments is changing. we can use the
+ ** current PosRect and ClipRect and simply resize our
+ ** windows WITHOUT informing our in-place container.
+ */
+ ServerDoc_ResizeInPlaceWindow(
+ lpServerDoc,
+ (LPRECT)&(lpIPData->rcPosRect),
+ (LPRECT)&(lpIPData->rcClipRect)
+ );
+ } else
+#else // !INPLACE_SVR
+
+ OutlineDoc_Resize(lpOutlineDoc, NULL);
+
+#if defined( INPLACE_CNTR )
+ ContainerDoc_UpdateInPlaceObjectRects((LPCONTAINERDOC)lpOutlineDoc, 0);
+#endif // INPLACE_CNTR
+
+#endif // INPLACE_SVR
+
+ OutlineDoc_ForceRedraw(lpOutlineDoc, TRUE);
+}
+
+#endif // USE_HEADING
+
+
+/* AbortProc
+ * ---------
+ * AborProc is called by GDI print code to check for user abort.
+ */
+BOOL FAR PASCAL EXPORT AbortProc (HDC hdc, WORD reserved)
+{
+ MSG msg;
+
+ /* Allow other apps to run, or get abort messages */
+ while(! fCancelPrint && PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
+ if(!hWndPDlg || !IsDialogMessage (hWndPDlg, &msg)) {
+ TranslateMessage (&msg);
+ DispatchMessage (&msg);
+ }
+ }
+ return !fCancelPrint;
+}
+
+
+/* PrintDlgProc
+ * ------------
+ * Dialog function for the print cancel dialog box.
+ *
+ * RETURNS : TRUE - OK to abort/ not OK to abort
+ * FALSE - otherwise.
+ */
+BOOL FAR PASCAL EXPORT PrintDlgProc(
+ HWND hwnd,
+ WORD msg,
+ WORD wParam,
+ LONG lParam
+)
+{
+ switch (msg) {
+ case WM_COMMAND:
+ /* abort printing if the only button gets hit */
+ fCancelPrint = TRUE;
+ return TRUE;
+ }
+
+ return FALSE;
+}