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

Windows编程

开发平台:

Visual C++

  1. /*************************************************************************
  2. **
  3. **    OLE 2 Sample Code
  4. **
  5. **    outldoc.c
  6. **
  7. **    This file contains OutlineDoc functions.
  8. **
  9. **    (c) Copyright Microsoft Corp. 1992 - 1996 All Rights Reserved
  10. **
  11. *************************************************************************/
  12. #include "outline.h"
  13. #if !defined( OLE_VERSION )
  14. #include <commdlg.h>
  15. #endif
  16. OLEDBGDATA
  17. extern LPOUTLINEAPP g_lpApp;
  18. #ifdef WIN32S
  19. #define GALLOCFLG (GMEM_SHARE | GMEM_ZEROINIT | GMEM_MOVEABLE)
  20. #else
  21. #define GALLOCFLG (GMEM_SHARE | GMEM_ZEROINIT)
  22. #endif
  23. // REVIEW: should use string resource for messages
  24. OLECHAR ErrMsgDocWnd[] = OLESTR("Can't create Document Window!");
  25. OLECHAR ErrMsgFormatNotSupported[] = OLESTR("Clipboard format not supported!");
  26. OLECHAR MsgSaveFile[] = OLESTR("Save existing file ?");
  27. OLECHAR ErrMsgSaving[] = OLESTR("Error in saving file!");
  28. OLECHAR ErrMsgOpening[] = OLESTR("Error in opening file!");
  29. OLECHAR ErrMsgFormat[] = OLESTR("Improper file format!");
  30. OLECHAR ErrOutOfMemory[] = OLESTR("Error: out of memory!");
  31. static OLECHAR ErrMsgPrint[] = OLESTR("Printing Error!");
  32. static BOOL fCancelPrint;    // TRUE if the user has canceled the print job
  33. static HWND hWndPDlg;       // Handle to the cancel print dialog
  34. /* OutlineDoc_Init
  35.  * ---------------
  36.  *
  37.  *  Initialize the fields of a new OutlineDoc object. The object is initially
  38.  *  not associated with a file or an (Untitled) document. This function sets
  39.  *  the docInitType to DOCTYPE_UNKNOWN. After calling this function the
  40.  *  caller should call:
  41.  *      1. OutlineDoc_InitNewFile to set the OutlineDoc to (Untitled)
  42.  *      2. OutlineDoc_LoadFromFile to associate the OutlineDoc with a file.
  43.  *  This function creates a new window for the document.
  44.  *
  45.  *  NOTE: the window is initially created with a NIL size. it must be
  46.  *        sized and positioned by the caller. also the document is initially
  47.  *        created invisible. the caller must call OutlineDoc_ShowWindow
  48.  *        after sizing it to make the document window visible.
  49.  */
  50. BOOL OutlineDoc_Init(LPOUTLINEDOC lpOutlineDoc, BOOL fDataTransferDoc)
  51. {
  52.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  53. #if defined( INPLACE_CNTR )
  54.    lpOutlineDoc->m_hWndDoc = CreateWindow(
  55.                DOCWNDCLASS,            // Window class name
  56.                NULL,                   // Window's title
  57.                /* NOTE: an in-place contanier MUST use
  58.                **    WS_CLIPCHILDREN window style for the window
  59.                **    that it uses as the parent for the server's
  60.                **    in-place active window so that its
  61.                **    painting does NOT interfere with the painting
  62.                **    of the server's in-place active child window.
  63.                */
  64.                WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
  65.                WS_CHILDWINDOW,
  66.                0, 0,
  67.                0, 0,
  68.                lpOutlineApp->m_hWndApp,// Parent window's handle
  69.                (HMENU)1,               // child window id
  70.                lpOutlineApp->m_hInst,  // Instance of window
  71.                NULL);                  // Create struct for WM_CREATE
  72. #else
  73.    lpOutlineDoc->m_hWndDoc = CreateWindow(
  74.                DOCWNDCLASS,            // Window class name
  75.                NULL,                   // Window's title
  76.                WS_CHILDWINDOW,
  77.                0, 0,
  78.                0, 0,
  79.                lpOutlineApp->m_hWndApp,// Parent window's handle
  80.                (HMENU)1,               // child window id
  81.                lpOutlineApp->m_hInst,  // Instance of window
  82.                NULL);                  // Create struct for WM_CREATE
  83. #endif
  84.    if(! lpOutlineDoc->m_hWndDoc) {
  85.       OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgDocWnd);
  86.       return FALSE;
  87.    }
  88.    SetWindowLong(lpOutlineDoc->m_hWndDoc, 0, (LONG) lpOutlineDoc);
  89.    if (! LineList_Init(&lpOutlineDoc->m_LineList, lpOutlineDoc))
  90.       return FALSE;
  91.    lpOutlineDoc->m_lpNameTable = OutlineDoc_CreateNameTable(lpOutlineDoc);
  92.    if (! lpOutlineDoc->m_lpNameTable )
  93.       return FALSE;
  94.    lpOutlineDoc->m_docInitType = DOCTYPE_UNKNOWN;
  95.    lpOutlineDoc->m_cfSaveFormat = lpOutlineApp->m_cfOutline;
  96.    lpOutlineDoc->m_szFileName[0] = '';
  97.    lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName;
  98.    lpOutlineDoc->m_fDataTransferDoc = fDataTransferDoc;
  99.    lpOutlineDoc->m_uCurrentZoom = IDM_V_ZOOM_100;
  100.    lpOutlineDoc->m_scale.dwSxN  = (DWORD) 1;
  101.    lpOutlineDoc->m_scale.dwSxD  = (DWORD) 1;
  102.    lpOutlineDoc->m_scale.dwSyN  = (DWORD) 1;
  103.    lpOutlineDoc->m_scale.dwSyD  = (DWORD) 1;
  104.    lpOutlineDoc->m_uCurrentMargin = IDM_V_SETMARGIN_0;
  105.    lpOutlineDoc->m_nLeftMargin  = 0;
  106.    lpOutlineDoc->m_nRightMargin = 0;
  107.    lpOutlineDoc->m_nDisableDraw = 0;
  108.    OutlineDoc_SetModified(lpOutlineDoc, FALSE, FALSE, FALSE);
  109. #if defined( USE_HEADING )
  110.    if (! fDataTransferDoc) {
  111.       if (!Heading_Create((LPHEADING)&lpOutlineDoc->m_heading,
  112.             lpOutlineDoc->m_hWndDoc, lpOutlineApp->m_hInst)) {
  113.          return FALSE;
  114.       }
  115.    }
  116. #endif  // USE_HEADING
  117. #if defined( USE_FRAMETOOLS )
  118.    if (! fDataTransferDoc) {
  119.       lpOutlineDoc->m_lpFrameTools = OutlineApp_GetFrameTools(lpOutlineApp);
  120.       FrameTools_AssociateDoc(
  121.             lpOutlineDoc->m_lpFrameTools,
  122.             lpOutlineDoc
  123.       );
  124.    }
  125. #endif  // USE_FRAMETOOLS
  126. #if defined( OLE_VERSION )
  127.    /* NOTE: perform initialization required for OLE */
  128.    if (! OleDoc_Init((LPOLEDOC)lpOutlineDoc, fDataTransferDoc))
  129.       return FALSE;
  130. #endif  // OLE_VERSION
  131.    return TRUE;
  132. }
  133. /* OutlineDoc_InitNewFile
  134.  * ----------------------
  135.  *
  136.  *  Initialize the OutlineDoc object to be a new (Untitled) document.
  137.  *  This function sets the docInitType to DOCTYPE_NEW.
  138.  */
  139. BOOL OutlineDoc_InitNewFile(LPOUTLINEDOC lpOutlineDoc)
  140. {
  141. #if defined( OLE_VERSION )
  142.    // NOTE: call OLE version of this function instead
  143.    return OleDoc_InitNewFile((LPOLEDOC)lpOutlineDoc);
  144. #else
  145.    OleDbgAssert(lpOutlineDoc->m_docInitType == DOCTYPE_UNKNOWN);
  146.    // set file name to untitled
  147.    // REVIEW: should load from string resource
  148.    lstrcpyW(lpOutlineDoc->m_szFileName, UNTITLED);
  149.    lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName;
  150.    lpOutlineDoc->m_docInitType = DOCTYPE_NEW;
  151.    if (! lpOutlineDoc->m_fDataTransferDoc)
  152.       OutlineDoc_SetTitle(lpOutlineDoc, FALSE /*fMakeUpperCase*/);
  153.    return TRUE;
  154. #endif      // BASE OUTLINE VERSION
  155. }
  156. /* OutlineDoc_CreateNameTable
  157.  * --------------------------
  158.  *
  159.  * Allocate a new NameTable of the appropriate type. Each document has
  160.  * a NameTable and a LineList.
  161.  *  OutlineDoc --> creates standard OutlineNameTable type name tables.
  162.  *  ServerDoc  --> creates enhanced SeverNameTable type name tables.
  163.  *
  164.  *      Returns lpNameTable for successful, NULL if error.
  165.  */
  166. LPOUTLINENAMETABLE OutlineDoc_CreateNameTable(LPOUTLINEDOC lpOutlineDoc)
  167. {
  168.    LPOUTLINENAMETABLE lpOutlineNameTable;
  169.    lpOutlineNameTable = (LPOUTLINENAMETABLE)New(
  170.          (DWORD)sizeof(OUTLINENAMETABLE)
  171.    );
  172.    OleDbgAssertSz(lpOutlineNameTable != NULL,"Error allocating NameTable");
  173.    if (lpOutlineNameTable == NULL)
  174.       return NULL;
  175.    // initialize new NameTable
  176.    if (! OutlineNameTable_Init(lpOutlineNameTable, lpOutlineDoc) )
  177.       goto error;
  178.    return lpOutlineNameTable;
  179. error:
  180.    if (lpOutlineNameTable)
  181.       Delete(lpOutlineNameTable);
  182.    return NULL;
  183. }
  184. /* OutlineDoc_ClearCommand
  185.  * -----------------------
  186.  *
  187.  *      Delete selection in list box by calling OutlineDoc_Delete
  188.  */
  189. void OutlineDoc_ClearCommand(LPOUTLINEDOC lpOutlineDoc)
  190. {
  191.    LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
  192.    int i;
  193.    int nNumSel;
  194.    LINERANGE lrSel;
  195.    nNumSel=LineList_GetSel(lpLL, (LPLINERANGE)&lrSel);
  196.    OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE );
  197.    for(i = 0; i < nNumSel; i++)
  198.       OutlineDoc_DeleteLine(lpOutlineDoc, lrSel.m_nStartLine);
  199.    OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE );
  200.    LineList_RecalcMaxLineWidthInHimetric(lpLL, 0);
  201. }
  202. /* OutlineDoc_CutCommand
  203.  * ---------------------
  204.  *
  205.  * Cut selection to clipboard
  206.  */
  207. void OutlineDoc_CutCommand(LPOUTLINEDOC lpOutlineDoc)
  208. {
  209.    OutlineDoc_CopyCommand(lpOutlineDoc);
  210.    OutlineDoc_ClearCommand(lpOutlineDoc);
  211. }
  212. /* OutlineDoc_CopyCommand
  213.  * ----------------------
  214.  *  Copy selection to clipboard.
  215.  *  Post to the clipboard the formats that the app can render.
  216.  *  the actual data is not rendered at this time. using the
  217.  *  delayed rendering technique, Windows will send the clipboard
  218.  *  owner window either a WM_RENDERALLFORMATS or a WM_RENDERFORMAT
  219.  *  message when the actual data is requested.
  220.  *
  221.  *    NOTE: the normal delayed rendering technique where Windows
  222.  *    sends the clipboard owner window either a WM_RENDERALLFORMATS or
  223.  *    a WM_RENDERFORMAT message when the actual data is requested is
  224.  *    NOT exposed to the app calling OleSetClipboard. OLE internally
  225.  *    creates its own window as the clipboard owner and thus our app
  226.  *    will NOT get these WM_RENDER messages.
  227.  */
  228. void OutlineDoc_CopyCommand(LPOUTLINEDOC lpSrcOutlineDoc)
  229. {
  230. #if defined( OLE_VERSION )
  231.    // Call OLE version of this function instead
  232.    OleDoc_CopyCommand((LPOLEDOC)lpSrcOutlineDoc);
  233. #else
  234.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  235.    LPOUTLINEDOC lpClipboardDoc;
  236.    OpenClipboard(lpSrcOutlineDoc->m_hWndDoc);
  237.    EmptyClipboard();
  238.    /* squirrel away a copy of the current selection to the ClipboardDoc */
  239.    lpClipboardDoc = OutlineDoc_CreateDataTransferDoc(lpSrcOutlineDoc);
  240.    if (! lpClipboardDoc)
  241.       return;     // Error: could not create DataTransferDoc
  242.    lpOutlineApp->m_lpClipboardDoc = (LPOUTLINEDOC)lpClipboardDoc;
  243.    SetClipboardData(lpOutlineApp->m_cfOutline, NULL);
  244.    SetClipboardData(CF_TEXT, NULL);
  245.    CloseClipboard();
  246. #endif  // ! OLE_VERSION
  247. }
  248. /* OutlineDoc_ClearAllLines
  249.  * ------------------------
  250.  *
  251.  *      Delete all lines in the document.
  252.  */
  253. void OutlineDoc_ClearAllLines(LPOUTLINEDOC lpOutlineDoc)
  254. {
  255.    LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
  256.    int i;
  257.    for(i = 0; i < lpLL->m_nNumLines; i++)
  258.       OutlineDoc_DeleteLine(lpOutlineDoc, 0);
  259.    LineList_RecalcMaxLineWidthInHimetric(lpLL, 0);
  260. }
  261. /* OutlineDoc_CreateDataTransferDoc
  262.  * --------------------------------
  263.  *
  264.  *      Create a document to be use to transfer data (either via a
  265.  *  drag/drop operation of the clipboard). Copy the selection of the
  266.  *  source doc to the data transfer document. A data transfer document is
  267.  *  the same as a document that is created by the user except that it is
  268.  *  NOT made visible to the user. it is specially used to hold a copy of
  269.  *  data that the user should not be able to change.
  270.  *
  271.  *  NOTE: in the OLE version the data transfer document is used
  272.  *      specifically to provide an IDataObject* that renders the data copied.
  273.  */
  274. LPOUTLINEDOC OutlineDoc_CreateDataTransferDoc(LPOUTLINEDOC lpSrcOutlineDoc)
  275. {
  276. #if defined( OLE_VERSION )
  277.    // Call OLE version of this function instead
  278.    return OleDoc_CreateDataTransferDoc((LPOLEDOC)lpSrcOutlineDoc);
  279. #else
  280.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  281.    LPOUTLINEDOC lpDestOutlineDoc;
  282.    LPLINELIST lpSrcLL = &lpSrcOutlineDoc->m_LineList;
  283.    LINERANGE lrSel;
  284.    int nCopied;
  285.    lpDestOutlineDoc = OutlineApp_CreateDoc(lpOutlineApp, TRUE);
  286.    if (! lpDestOutlineDoc) return NULL;
  287.    // set the ClipboardDoc to an (Untitled) doc.
  288.    if (! OutlineDoc_InitNewFile(lpDestOutlineDoc))
  289.       goto error;
  290.    LineList_GetSel(lpSrcLL, (LPLINERANGE)&lrSel);
  291.    nCopied = LineList_CopySelToDoc(
  292.          lpSrcLL,
  293.          (LPLINERANGE)&lrSel,
  294.          lpDestOutlineDoc
  295.    );
  296.    return lpDestOutlineDoc;
  297. error:
  298.    if (lpDestOutlineDoc)
  299.       OutlineDoc_Destroy(lpDestOutlineDoc);
  300.    return NULL;
  301. #endif  // ! OLE_VERSION
  302. }
  303. /* OutlineDoc_PasteCommand
  304.  * -----------------------
  305.  *
  306.  * Paste lines from clipboard
  307.  */
  308. void OutlineDoc_PasteCommand(LPOUTLINEDOC lpOutlineDoc)
  309. {
  310. #if defined( OLE_VERSION )
  311.    // Call OLE version of this function instead
  312.    OleDoc_PasteCommand((LPOLEDOC)lpOutlineDoc);
  313. #else
  314.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  315.    LPLINELIST lpLL = (LPLINELIST)&lpOutlineDoc->m_LineList;
  316.    int nIndex;
  317.    int nCount;
  318.    HGLOBAL hData;
  319.    LINERANGE lrSel;
  320.    UINT uFormat;
  321.    if (LineList_GetCount(lpLL) == 0)
  322.       nIndex = -1;    // pasting to empty list
  323.    else
  324.       nIndex=LineList_GetFocusLineIndex(lpLL);
  325.    OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE );
  326.    OpenClipboard(lpOutlineDoc->m_hWndDoc);
  327.    uFormat = 0;
  328.    while(uFormat = EnumClipboardFormats(uFormat)) {
  329.       if(uFormat == lpOutlineApp->m_cfOutline) {
  330.          hData = GetClipboardData(lpOutlineApp->m_cfOutline);
  331.          nCount = OutlineDoc_PasteOutlineData(lpOutlineDoc, hData, nIndex);
  332.          break;
  333.       }
  334.       if(uFormat == CF_TEXT) {
  335.          hData = GetClipboardData(CF_TEXT);
  336.          nCount = OutlineDoc_PasteTextData(lpOutlineDoc, hData, nIndex);
  337.          break;
  338.       }
  339.    }
  340.    lrSel.m_nStartLine = nIndex + nCount;
  341.    lrSel.m_nEndLine = nIndex + 1;
  342.    LineList_SetSel(lpLL, &lrSel);
  343.    OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE );
  344.    CloseClipboard();
  345. #endif      // ! OLE_VERSION
  346. }
  347. /* OutlineDoc_PasteOutlineData
  348.  * ---------------------------
  349.  *
  350.  *      Put an array of Line Objects (stored in hOutline) into the document
  351.  *
  352.  * Return the number of items added
  353.  */
  354. int OutlineDoc_PasteOutlineData(LPOUTLINEDOC lpOutlineDoc, HGLOBAL hOutline, int nStartIndex)
  355. {
  356.    int nCount;
  357.    int i;
  358.    LPTEXTLINE arrLine;
  359.    nCount = (int) GlobalSize(hOutline) / sizeof(TEXTLINE);
  360.    arrLine = (LPTEXTLINE)GlobalLock(hOutline);
  361.    if (!arrLine)
  362.       return 0;
  363.    for(i = 0; i < nCount; i++)
  364.       Line_CopyToDoc((LPLINE)&arrLine[i], lpOutlineDoc, nStartIndex+i);
  365.    GlobalUnlock(hOutline);
  366.    return nCount;
  367. }
  368. /* OutlineDoc_PasteTextData
  369.  * ------------------------
  370.  *
  371.  *      Build Line Objects from the strings (separated by 'n') in hText
  372.  * and put them into the document
  373.  */
  374. int OutlineDoc_PasteTextData(LPOUTLINEDOC lpOutlineDoc, HGLOBAL hText, int nStartIndex)
  375. {
  376.    LPLINELIST  lpLL = (LPLINELIST)&lpOutlineDoc->m_LineList;
  377.    HDC         hDC;
  378.    LPSTR       lpszText;
  379.    LPSTR       lpszEnd;
  380.    LPTEXTLINE  lpLine;
  381.    int         nLineCount;
  382.    int         i;
  383.    UINT        nTab;
  384.    char        szBuf[MAXSTRLEN+1];
  385.    lpszText=(LPSTR)GlobalLock(hText);
  386.    if(!lpszText)
  387.       return 0;
  388.    lpszEnd = lpszText + lstrlen(lpszText);
  389.    nLineCount=0;
  390.    while(*lpszText && (lpszText<lpszEnd)) {
  391.       // count the tab level
  392.       nTab = 0;
  393.       while((*lpszText == 't') && (lpszText<lpszEnd)) {
  394.          nTab++;
  395.          lpszText++;
  396.       }
  397.       // collect the text string character by character
  398.       for(i=0; (i<MAXSTRLEN) && (lpszText<lpszEnd); i++) {
  399.          if ((! *lpszText) || (*lpszText == 'n'))
  400.             break;
  401.          szBuf[i] = *lpszText++;
  402.       }
  403.       szBuf[i] = 0;
  404.       lpszText++;
  405.       if ((i > 0) && (szBuf[i-1] == 'r'))
  406.          szBuf[i-1] = 0;     // remove carriage return at the end
  407.       hDC = LineList_GetDC(lpLL);
  408.       lpLine = TextLine_Create(hDC, nTab, szBuf);
  409.       LineList_ReleaseDC(lpLL, hDC);
  410.       OutlineDoc_AddLine(
  411.             lpOutlineDoc,
  412.             (LPLINE)lpLine,
  413.             nStartIndex + nLineCount
  414.       );
  415.       nLineCount++;
  416.    }
  417.    GlobalUnlock(hText);
  418.    return nLineCount;
  419. }
  420. /* OutlineDoc_AddTextLineCommand
  421.  * -----------------------------
  422.  *
  423.  *      Add a new text line following the current focus line.
  424.  */
  425. void OutlineDoc_AddTextLineCommand(LPOUTLINEDOC lpOutlineDoc)
  426. {
  427.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  428.    LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
  429.    HDC hDC;
  430.    int nIndex = LineList_GetFocusLineIndex(lpLL);
  431.    char szBuf[MAXSTRLEN+1];
  432.    UINT nTab = 0;
  433.    LPLINE lpLine;
  434.    LPTEXTLINE lpTextLine;
  435.    szBuf[0] = '';
  436. #if defined( USE_FRAMETOOLS )
  437.    FrameTools_FB_GetEditText(
  438.          lpOutlineDoc->m_lpFrameTools, szBuf, MAXSTRLEN+1);
  439. #else
  440.    if (! InputTextDlg(lpOutlineDoc->m_hWndDoc, szBuf, "Add Line"))
  441.       return;
  442. #endif
  443.    hDC = LineList_GetDC(lpLL);
  444.    lpLine = LineList_GetLine(lpLL, nIndex);
  445.    if (lpLine)
  446.       nTab = Line_GetTabLevel(lpLine);
  447.    lpTextLine=TextLine_Create(hDC, nTab, szBuf);
  448.    LineList_ReleaseDC(lpLL, hDC);
  449.    if (! lpTextLine) {
  450.       OutlineApp_ErrorMessage(lpOutlineApp, ErrOutOfMemory);
  451.       return;
  452.    }
  453.    OutlineDoc_AddLine(lpOutlineDoc, (LPLINE)lpTextLine, nIndex);
  454. }
  455. /* OutlineDoc_AddTopLineCommand
  456.  * ----------------------------
  457.  *
  458.  *      Add a top (margin) line as the first line in the LineList.
  459.  *      (do not change the current selection)
  460.  */
  461. void OutlineDoc_AddTopLineCommand(
  462.       LPOUTLINEDOC        lpOutlineDoc,
  463.       UINT                nHeightInHimetric
  464. )
  465. {
  466.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  467.    LPLINELIST  lpLL = &lpOutlineDoc->m_LineList;
  468.    HDC         hDC = LineList_GetDC(lpLL);
  469.    LPTEXTLINE  lpTextLine = TextLine_Create(hDC, 0, NULL);
  470.    LPLINE      lpLine = (LPLINE)lpTextLine;
  471.    LINERANGE   lrSel;
  472.    int         nNumSel;
  473.    LineList_ReleaseDC(lpLL, hDC);
  474.    if (! lpTextLine) {
  475.       OutlineApp_ErrorMessage(lpOutlineApp, ErrOutOfMemory);
  476.       return;
  477.    }
  478.    Line_SetHeightInHimetric(lpLine, nHeightInHimetric);
  479.    nNumSel=LineList_GetSel(lpLL, (LPLINERANGE)&lrSel);
  480.    if (nNumSel > 0) {
  481.       // adjust current selection to keep equivalent selection
  482.       lrSel.m_nStartLine += 1;
  483.       lrSel.m_nEndLine += 1;
  484.    }
  485.    OutlineDoc_AddLine(lpOutlineDoc, lpLine, -1);
  486.    if (nNumSel > 0)
  487.       LineList_SetSel(lpLL, (LPLINERANGE)&lrSel);
  488. }
  489. #if defined( USE_FRAMETOOLS )
  490. /* OutlineDoc_SetFormulaBarEditText
  491.  * --------------------------------
  492.  *
  493.  *      Fill the edit control in the formula with the text string from a
  494.  * TextLine in focus.
  495.  */
  496. void OutlineDoc_SetFormulaBarEditText(
  497.       LPOUTLINEDOC            lpOutlineDoc,
  498.       LPLINE                  lpLine
  499. )
  500. {
  501.    LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
  502.    char cBuf[MAXSTRLEN+1];
  503.    if (! lpOutlineDoc || ! lpOutlineDoc->m_lpFrameTools)
  504.       return;
  505.    if (Line_GetLineType(lpLine) != TEXTLINETYPE) {
  506.       FrameTools_FB_SetEditText(lpOutlineDoc->m_lpFrameTools, NULL);
  507.    } else {
  508.       TextLine_GetTextData((LPTEXTLINE)lpLine, (LPSTR)cBuf);
  509.       FrameTools_FB_SetEditText(lpOutlineDoc->m_lpFrameTools, (LPSTR)cBuf);
  510.    }
  511. }
  512. /* OutlineDoc_SetFormulaBarEditFocus
  513.  * ---------------------------------
  514.  *
  515.  *  Setup for formula bar to gain or loose edit focus.
  516.  *  if gaining focus, setup up special accelerator table and scroll line
  517.  *      into view.
  518.  *  else restore normal accelerator table.
  519.  */
  520. void OutlineDoc_SetFormulaBarEditFocus(
  521.       LPOUTLINEDOC            lpOutlineDoc,
  522.       BOOL                    fEditFocus
  523. )
  524. {
  525.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  526.    LPLINELIST lpLL;
  527.    int nFocusIndex;
  528.    if (! lpOutlineDoc || ! lpOutlineDoc->m_lpFrameTools)
  529.       return;
  530.    lpOutlineDoc->m_lpFrameTools->m_fInFormulaBar = fEditFocus;
  531.    if (fEditFocus && lpOutlineDoc->m_lpFrameTools) {
  532.       lpLL = OutlineDoc_GetLineList(lpOutlineDoc);
  533.       nFocusIndex = LineList_GetFocusLineIndex(lpLL);
  534.       LineList_ScrollLineIntoView(lpLL, nFocusIndex);
  535.       FrameTools_FB_FocusEdit(lpOutlineDoc->m_lpFrameTools);
  536.    }
  537.    OutlineApp_SetFormulaBarAccel(lpOutlineApp, fEditFocus);
  538. }
  539. /* OutlineDoc_IsEditFocusInFormulaBar
  540. ** ----------------------------------
  541. **    Returns TRUE if edit focus is currently in the formula bar
  542. **    else FALSE if not.
  543. */
  544. BOOL OutlineDoc_IsEditFocusInFormulaBar(LPOUTLINEDOC lpOutlineDoc)
  545. {
  546.    if (! lpOutlineDoc || ! lpOutlineDoc->m_lpFrameTools)
  547.       return FALSE;
  548.    return lpOutlineDoc->m_lpFrameTools->m_fInFormulaBar;
  549. }
  550. /* OutlineDoc_UpdateFrameToolButtons
  551. ** ---------------------------------
  552. **    Update the Enable/Disable states of the buttons in the formula
  553. **    bar and button bar.
  554. */
  555. void OutlineDoc_UpdateFrameToolButtons(LPOUTLINEDOC lpOutlineDoc)
  556. {
  557.    if (! lpOutlineDoc || ! lpOutlineDoc->m_lpFrameTools)
  558.       return;
  559.    FrameTools_UpdateButtons(lpOutlineDoc->m_lpFrameTools, lpOutlineDoc);
  560. }
  561. #endif  // USE_FRAMETOOLS
  562. /* OutlineDoc_EditLineCommand
  563.  * --------------------------
  564.  *
  565.  *      Edit the current focus line.
  566.  */
  567. void OutlineDoc_EditLineCommand(LPOUTLINEDOC lpOutlineDoc)
  568. {
  569.    LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
  570.    HDC hDC = LineList_GetDC(lpLL);
  571.    int nIndex = LineList_GetFocusLineIndex(lpLL);
  572.    LPLINE lpLine = LineList_GetLine(lpLL, nIndex);
  573.    int nOrgLineWidthInHimetric;
  574.    int nNewLineWidthInHimetric;
  575.    BOOL fSizeChanged;
  576.    if (!lpLine)
  577.       return;
  578.    nOrgLineWidthInHimetric = Line_GetTotalWidthInHimetric(lpLine);
  579.    if (Line_Edit(lpLine, lpOutlineDoc->m_hWndDoc, hDC)) {
  580.       nNewLineWidthInHimetric = Line_GetTotalWidthInHimetric(lpLine);
  581.       if (nNewLineWidthInHimetric > nOrgLineWidthInHimetric) {
  582.          fSizeChanged = LineList_SetMaxLineWidthInHimetric(
  583.                lpLL,
  584.                nNewLineWidthInHimetric
  585.             );
  586.       } else {
  587.          fSizeChanged = LineList_RecalcMaxLineWidthInHimetric(
  588.                lpLL,
  589.                nOrgLineWidthInHimetric
  590.             );
  591.       }
  592. #if defined( OLE_SERVER )
  593.       /* Update Name Table */
  594.       ServerNameTable_EditLineUpdate(
  595.             (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable,
  596.             nIndex
  597.       );
  598. #endif
  599.       OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, fSizeChanged);
  600.       LineList_ForceLineRedraw(lpLL, nIndex, TRUE);
  601.    }
  602.    LineList_ReleaseDC(lpLL, hDC);
  603. }
  604. /* OutlineDoc_IndentCommand
  605.  * ------------------------
  606.  *
  607.  *      Indent selection of lines
  608.  */
  609. void OutlineDoc_IndentCommand(LPOUTLINEDOC lpOutlineDoc)
  610. {
  611.    LPLINELIST  lpLL = &lpOutlineDoc->m_LineList;
  612.    LPLINE      lpLine;
  613.    HDC         hDC = LineList_GetDC(lpLL);
  614.    int         i;
  615.    int         nIndex;
  616.    int         nNumSel;
  617.    LINERANGE   lrSel;
  618.    BOOL        fSizeChanged = FALSE;
  619.    nNumSel=LineList_GetSel(lpLL, (LPLINERANGE)&lrSel);
  620.    OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE );
  621.    for(i = 0; i < nNumSel; i++) {
  622.       nIndex = lrSel.m_nStartLine + i;
  623.       lpLine=LineList_GetLine(lpLL, nIndex);
  624.       if (! lpLine)
  625.          continue;
  626.       Line_Indent(lpLine, hDC);
  627.       if (LineList_SetMaxLineWidthInHimetric(lpLL,
  628.          Line_GetTotalWidthInHimetric(lpLine))) {
  629.          fSizeChanged = TRUE;
  630.       }
  631.       LineList_ForceLineRedraw(lpLL, nIndex, TRUE);
  632. #if defined( OLE_SERVER )
  633.       /* Update Name Table */
  634.       ServerNameTable_EditLineUpdate(
  635.             (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable,
  636.             nIndex
  637.       );
  638. #endif
  639.    }
  640.    LineList_ReleaseDC(lpLL, hDC);
  641.    OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, fSizeChanged);
  642.    OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE );
  643. }
  644. /* OutlineDoc_UnindentCommand
  645.  * --------------------------
  646.  *
  647.  *      Unindent selection of lines
  648.  */
  649. void OutlineDoc_UnindentCommand(LPOUTLINEDOC lpOutlineDoc)
  650. {
  651.    LPLINELIST  lpLL = &lpOutlineDoc->m_LineList;
  652.    LPLINE      lpLine;
  653.    HDC         hDC = LineList_GetDC(lpLL);
  654.    int         nOrgLineWidthInHimetric;
  655.    int         nOrgMaxLineWidthInHimetric = 0;
  656.    int         i;
  657.    int         nIndex;
  658.    int         nNumSel;
  659.    LINERANGE   lrSel;
  660.    BOOL        fSizeChanged;
  661.    nNumSel=LineList_GetSel(lpLL, (LPLINERANGE)&lrSel);
  662.    OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE );
  663.    for(i = 0; i < nNumSel; i++) {
  664.       nIndex = lrSel.m_nStartLine + i;
  665.       lpLine=LineList_GetLine(lpLL, nIndex);
  666.       if (!lpLine)
  667.          continue;
  668.       nOrgLineWidthInHimetric = Line_GetTotalWidthInHimetric(lpLine);
  669.       nOrgMaxLineWidthInHimetric =
  670.             (nOrgLineWidthInHimetric > nOrgMaxLineWidthInHimetric ?
  671.                nOrgLineWidthInHimetric : nOrgMaxLineWidthInHimetric);
  672.       Line_Unindent(lpLine, hDC);
  673.       LineList_ForceLineRedraw(lpLL, nIndex, TRUE);
  674. #if defined( OLE_SERVER )
  675.       /* Update Name Table */
  676.       ServerNameTable_EditLineUpdate(
  677.             (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable,
  678.             nIndex
  679.       );
  680. #endif
  681.    }
  682.    LineList_ReleaseDC(lpLL, hDC);
  683.    fSizeChanged = LineList_RecalcMaxLineWidthInHimetric(
  684.          lpLL,
  685.          nOrgMaxLineWidthInHimetric
  686.       );
  687.    OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, fSizeChanged);
  688.    OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE );
  689. }
  690. /* OutlineDoc_SetLineHeightCommand
  691.  * -------------------------------
  692.  *
  693.  *      Set height of the selection of lines
  694.  */
  695. void OutlineDoc_SetLineHeightCommand(LPOUTLINEDOC lpOutlineDoc)
  696. {
  697.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  698.    LPLINELIST  lpLL;
  699.    HDC         hDC;
  700.    LPLINE      lpLine;
  701.    int         nNewHeight;
  702.    int         i;
  703.    int         nIndex;
  704.    int         nNumSel;
  705.    LINERANGE   lrSel;
  706.    if (!lpOutlineDoc)
  707.       return;
  708.    lpLL = &lpOutlineDoc->m_LineList;
  709.    nNumSel=LineList_GetSel(lpLL, (LPLINERANGE)&lrSel);
  710.    lpLine = LineList_GetLine(lpLL, lrSel.m_nStartLine);
  711.    if (!lpLine)
  712.       return;
  713.    nNewHeight = Line_GetHeightInHimetric(lpLine);
  714. #if defined( OLE_VERSION )
  715.    OleApp_PreModalDialog((LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineDoc);
  716. #endif
  717.    DialogBoxParam(
  718.          lpOutlineApp->m_hInst,
  719.          (LPSTR)"SetLineHeight",
  720.          lpOutlineDoc->m_hWndDoc,
  721.          (DLGPROC)SetLineHeightDlgProc,
  722.          (LPARAM)(LPINT)&nNewHeight
  723.    );
  724. #if defined( OLE_VERSION )
  725.    OleApp_PostModalDialog((LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineDoc);
  726. #endif
  727.    if (nNewHeight == 0)
  728.       return;     /* user hit cancel */
  729.    hDC = LineList_GetDC(lpLL);
  730.    for (i = 0; i < nNumSel; i++) {
  731.       nIndex = lrSel.m_nStartLine + i;
  732.       lpLine=LineList_GetLine(lpLL, nIndex);
  733.       if (nNewHeight == -1) {
  734.          switch (Line_GetLineType(lpLine)) {
  735.             case TEXTLINETYPE:
  736.                TextLine_CalcExtents((LPTEXTLINE)lpLine, hDC);
  737.                break;
  738. #if defined( OLE_CNTR )
  739.             case CONTAINERLINETYPE:
  740.                ContainerLine_SetHeightInHimetric(
  741.                      (LPCONTAINERLINE)lpLine, -1);
  742.                break;
  743. #endif
  744.          }
  745.       }
  746.       else
  747.          Line_SetHeightInHimetric(lpLine, nNewHeight);
  748.       LineList_SetLineHeight(lpLL, nIndex,
  749.             Line_GetHeightInHimetric(lpLine));
  750.    }
  751.    LineList_ReleaseDC(lpLL, hDC);
  752.    OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, TRUE);
  753.    LineList_ForceRedraw(lpLL, TRUE);
  754. }
  755. /* OutlineDoc_SelectAllCommand
  756.  * ---------------------------
  757.  *
  758.  *      Select all the lines in the document.
  759.  */
  760. void OutlineDoc_SelectAllCommand(LPOUTLINEDOC lpOutlineDoc)
  761. {
  762.    LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
  763.    LINERANGE lrSel;
  764.    lrSel.m_nStartLine = 0;
  765.    lrSel.m_nEndLine = LineList_GetCount(lpLL) - 1;
  766.    LineList_SetSel(lpLL, &lrSel);
  767. }
  768. /* OutlineDoc_DefineNameCommand
  769.  * ----------------------------
  770.  *
  771.  *      Define a name in the document
  772.  */
  773. void OutlineDoc_DefineNameCommand(LPOUTLINEDOC lpOutlineDoc)
  774. {
  775.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  776. #if defined( OLE_VERSION )
  777.    OleApp_PreModalDialog((LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineDoc);
  778. #endif
  779.    DialogBoxParam(
  780.          lpOutlineApp->m_hInst,
  781.          (LPSTR)"DefineName",
  782.          lpOutlineDoc->m_hWndDoc,
  783.          (DLGPROC)DefineNameDlgProc,
  784.          (LPARAM) lpOutlineDoc
  785.    );
  786. #if defined( OLE_VERSION )
  787.    OleApp_PostModalDialog((LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineDoc);
  788. #endif
  789. }
  790. /* OutlineDoc_GotoNameCommand
  791.  * --------------------------
  792.  *
  793.  *      Goto a predefined name in the document
  794.  */
  795. void OutlineDoc_GotoNameCommand(LPOUTLINEDOC lpOutlineDoc)
  796. {
  797.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  798. #if defined( OLE_VERSION )
  799.    OleApp_PreModalDialog((LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineDoc);
  800. #endif
  801.    DialogBoxParam(
  802.          lpOutlineApp->m_hInst,
  803.          (LPSTR)"GotoName",
  804.          lpOutlineDoc->m_hWndDoc,
  805.          (DLGPROC)GotoNameDlgProc,
  806.          (LPARAM)lpOutlineDoc
  807.    );
  808. #if defined( OLE_VERSION )
  809.    OleApp_PostModalDialog((LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineDoc);
  810. #endif
  811. }
  812. /* OutlineDoc_ShowWindow
  813.  * ---------------------
  814.  *
  815.  *      Show the window of the document to the user.
  816.  */
  817. void OutlineDoc_ShowWindow(LPOUTLINEDOC lpOutlineDoc)
  818. {
  819. #if defined( _DEBUG )
  820.    OleDbgAssertSz(lpOutlineDoc->m_docInitType != DOCTYPE_UNKNOWN,
  821.             "OutlineDoc_ShowWindow: can't show unitialized documentrn");
  822. #endif
  823.    if (lpOutlineDoc->m_docInitType == DOCTYPE_UNKNOWN)
  824.       return;
  825. #if defined( OLE_VERSION )
  826.    // Call OLE version of this function instead
  827.    OleDoc_ShowWindow((LPOLEDOC)lpOutlineDoc);
  828. #else
  829.    ShowWindow(lpOutlineDoc->m_hWndDoc, SW_SHOWNORMAL);
  830.    SetForegroundWindow(lpOutlineDoc->m_hWndDoc);
  831. #endif
  832. }
  833. #if defined( USE_FRAMETOOLS )
  834. void OutlineDoc_AddFrameLevelTools(LPOUTLINEDOC lpOutlineDoc)
  835. {
  836.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  837. #if defined( INPLACE_CNTR )
  838.    // Call OLE In-Place Container version of this function instead
  839.    ContainerDoc_AddFrameLevelTools((LPCONTAINERDOC)lpOutlineDoc);
  840. #else   // ! INPLACE_CNTR
  841.    RECT rcFrameRect;
  842.    BORDERWIDTHS frameToolWidths;
  843. #if defined( INPLACE_SVR )
  844.    LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc;
  845.    LPOLEINPLACEFRAME lpTopIPFrame=ServerDoc_GetTopInPlaceFrame(lpServerDoc);
  846.    // if in-place active, add our tools to our in-place container's frame.
  847.    if (lpTopIPFrame) {
  848.       ServerDoc_AddFrameLevelTools(lpServerDoc);
  849.       return;
  850.    }
  851. #endif  // INPLACE_SVR
  852.    OutlineApp_GetFrameRect(g_lpApp, (LPRECT)&rcFrameRect);
  853.    FrameTools_GetRequiredBorderSpace(
  854.          lpOutlineDoc->m_lpFrameTools,
  855.          (LPBORDERWIDTHS)&frameToolWidths
  856.    );
  857.    OutlineApp_SetBorderSpace(g_lpApp, (LPBORDERWIDTHS)&frameToolWidths);
  858.    FrameTools_AttachToFrame(
  859.          lpOutlineDoc->m_lpFrameTools, OutlineApp_GetWindow(lpOutlineApp));
  860.    FrameTools_Move(lpOutlineDoc->m_lpFrameTools, (LPRECT)&rcFrameRect);
  861. #endif  // ! INPLACE_CNTR
  862. }
  863. #endif  // USE_FRAMETOOLS
  864. /* OutlineDoc_GetWindow
  865.  * --------------------
  866.  *
  867.  *      Get the window handle of the document.
  868.  */
  869. HWND OutlineDoc_GetWindow(LPOUTLINEDOC lpOutlineDoc)
  870. {
  871.    if(! lpOutlineDoc) return NULL;
  872.    return lpOutlineDoc->m_hWndDoc;
  873. }
  874. /* OutlineDoc_AddLine
  875.  * ------------------
  876.  *
  877.  *      Add one line to the Document's LineList
  878.  */
  879. void OutlineDoc_AddLine(LPOUTLINEDOC lpOutlineDoc, LPLINE lpLine, int nIndex)
  880. {
  881.    LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
  882.    LineList_AddLine(lpLL, lpLine, nIndex);
  883.    /* Update Name Table */
  884.    OutlineNameTable_AddLineUpdate(lpOutlineDoc->m_lpNameTable, nIndex);
  885. #if defined( INPLACE_CNTR )
  886.    {
  887.       LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc;
  888.       /* NOTE: after adding a line we need to
  889.       **    update the PosRect of the In-Place active
  890.       **    objects (if any) that follow the added line.
  891.       **    NOTE: nIndex is index of line before new line.
  892.       **          nIndex+1 is index of new line
  893.       **          nIndex+2 is index of line after new line.
  894.       */
  895.       ContainerDoc_UpdateInPlaceObjectRects(lpContainerDoc, nIndex+2);
  896.    }
  897. #endif
  898.    OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, TRUE);
  899. }
  900. /* OutlineDoc_DeleteLine
  901.  * ---------------------
  902.  *
  903.  *
  904.  *      Delete one line from the document's LineList
  905.  */
  906. void OutlineDoc_DeleteLine(LPOUTLINEDOC lpOutlineDoc, int nIndex)
  907. {
  908.    LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
  909. #if defined( OLE_CNTR )
  910.    LPLINE lpLine = LineList_GetLine(lpLL, nIndex);
  911.    LPSTORAGE lpStgDoc = NULL;
  912.    OLECHAR szSaveStgName[CWCSTORAGENAME];
  913.    BOOL fDeleteChildStg = FALSE;
  914.    if (lpLine && (Line_GetLineType(lpLine) == CONTAINERLINETYPE) ) {
  915.       /* NOTE: when a ContainerLine is being deleted by the user,
  916.       **    it is important to delete the object's sub-storage
  917.       **    otherwise it wastes space in the ContainerDoc's file.
  918.       **    this function is called when lines are deleted by the
  919.       **    Clear command and when lines are deleted by a DRAGMOVE
  920.       **    operation.
  921.       */
  922.       LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
  923.       // save name of child storage
  924. //      LSTRCPYN(szSaveStgName, lpContainerLine->m_szStgName,sizeof(szSaveStgName));
  925.       OLESTRCPY(szSaveStgName, lpContainerLine->m_szStgName);
  926.       lpStgDoc = ((LPOLEDOC)lpContainerLine->m_lpDoc)->m_lpStg;
  927.       fDeleteChildStg = TRUE;
  928.    }
  929. #endif  // OLE_CNTR
  930.    LineList_DeleteLine(lpLL, nIndex);
  931. #if defined( OLE_CNTR )
  932.    if (fDeleteChildStg && lpStgDoc) {
  933.       HRESULT hrErr;
  934.       // delete the obsolete child storage. it is NOT fatal if this fails
  935.       hrErr = lpStgDoc->lpVtbl->DestroyElement(lpStgDoc, szSaveStgName);
  936. #if defined( _DEBUG )
  937.       if (hrErr != NOERROR) {
  938.          OleDbgOutHResult("IStorage::DestroyElement return", hrErr);
  939.       }
  940. #endif
  941.    }
  942. #endif  // OLE_CNTR
  943.    /* Update Name Table */
  944.    OutlineNameTable_DeleteLineUpdate(lpOutlineDoc->m_lpNameTable, nIndex);
  945. #if defined( INPLACE_CNTR )
  946.    {
  947.       LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc;
  948.       /* NOTE: after deleting a line we need to
  949.       **    update the PosRect of the In-Place active
  950.       **    objects (if any).
  951.       */
  952.       ContainerDoc_UpdateInPlaceObjectRects(lpContainerDoc, nIndex);
  953.    }
  954. #endif
  955.    OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, TRUE);
  956. #if defined( OLE_VERSION )
  957.    {
  958.       LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  959.       LPOLEDOC    lpClipboardDoc = (LPOLEDOC)lpOutlineApp->m_lpClipboardDoc;
  960.       /* NOTE: if the document that is the source of data on the
  961.       **    clipborad has just had lines deleted, then the copied data
  962.       **    is no longer considered a valid potential link source.
  963.       **    disable the offering of CF_LINKSOURCE from the clipboard
  964.       **    document. this avoids problems that arise when the
  965.       **    editing operation changes or deletes the original data
  966.       **    copied. we will not go to the trouble of determining if
  967.       **    the deleted line actually is part of the link source.
  968.       */
  969.       if (lpClipboardDoc
  970.          && lpClipboardDoc->m_fLinkSourceAvail
  971.          && lpClipboardDoc->m_lpSrcDocOfCopy == (LPOLEDOC)lpOutlineDoc) {
  972.          lpClipboardDoc->m_fLinkSourceAvail = FALSE;
  973.          /* NOTE: since we are changing the list of formats on
  974.          **    the clipboard (ie. removing CF_LINKSOURCE), we must
  975.          **    call OleSetClipboard again. to be sure that the
  976.          **    clipboard datatransfer document object does not get
  977.          **    destroyed we will guard the call to OleSetClipboard
  978.          **    within a pair of AddRef/Release.
  979.          */
  980.          OleDoc_AddRef((LPOLEDOC)lpClipboardDoc);    // guard obj life-time
  981.          OLEDBG_BEGIN2("OleSetClipboard calledrn")
  982.          OleSetClipboard(
  983.                (LPDATAOBJECT)&((LPOLEDOC)lpClipboardDoc)->m_DataObject);
  984.          OLEDBG_END2
  985.          OleDoc_Release((LPOLEDOC)lpClipboardDoc);    // rel. AddRef above
  986.       }
  987.    }
  988. #endif  // OLE_VERSION
  989. }
  990. /* OutlineDoc_AddName
  991.  * ------------------
  992.  *
  993.  *      Add a Name to the Document's NameTable
  994.  */
  995. void OutlineDoc_AddName(LPOUTLINEDOC lpOutlineDoc, LPOUTLINENAME lpOutlineName)
  996. {
  997.    LPOUTLINENAMETABLE lpOutlineNameTable = lpOutlineDoc->m_lpNameTable;
  998.    OutlineNameTable_AddName(lpOutlineNameTable, lpOutlineName);
  999.    OutlineDoc_SetModified(lpOutlineDoc, TRUE, FALSE, FALSE);
  1000. }
  1001. /* OutlineDoc_DeleteName
  1002.  * ---------------------
  1003.  *
  1004.  *
  1005.  *      Delete Name from the document's NameTable
  1006.  */
  1007. void OutlineDoc_DeleteName(LPOUTLINEDOC lpOutlineDoc, int nIndex)
  1008. {
  1009.    LPOUTLINENAMETABLE lpOutlineNameTable = lpOutlineDoc->m_lpNameTable;
  1010.    OutlineNameTable_DeleteName(lpOutlineNameTable, nIndex);
  1011.    OutlineDoc_SetModified(lpOutlineDoc, TRUE, FALSE, FALSE);
  1012. }
  1013. /* OutlineDoc_Destroy
  1014.  * ------------------
  1015.  *
  1016.  *  Free all memory that had been allocated for a document.
  1017.  *      this destroys the LineList & NameTable of the document.
  1018.  */
  1019. void OutlineDoc_Destroy(LPOUTLINEDOC lpOutlineDoc)
  1020. {
  1021.    LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
  1022. #if defined( OLE_VERSION )
  1023.    LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  1024.    LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc;
  1025.    if (lpOleDoc->m_fObjIsDestroying)
  1026.       return;     // doc destruction is in progress
  1027. #endif  // OLE_VERSION
  1028.    OLEDBG_BEGIN3("OutlineDoc_Destroyrn");
  1029. #if defined( OLE_VERSION )
  1030.    /* NOTE: in order to guarantee that the application does not
  1031.    **    prematurely exit before the destruction of the document is
  1032.    **    complete, we intially AddRef the App refcnt later Release it.
  1033.    **    This initial AddRef is artificial; it simply guarantees that
  1034.    **    the app object does not get destroyed until the end of this
  1035.    **    routine.
  1036.    */
  1037.    OleApp_AddRef(lpOleApp);
  1038.    /* NOTE: perform processing required for OLE */
  1039.    OleDoc_Destroy(lpOleDoc);
  1040. #endif
  1041.    LineList_Destroy(lpLL);
  1042.    OutlineNameTable_Destroy(lpOutlineDoc->m_lpNameTable);
  1043. #if defined( USE_HEADING )
  1044.    if (! lpOutlineDoc->m_fDataTransferDoc)
  1045.       Heading_Destroy((LPHEADING)&lpOutlineDoc->m_heading);
  1046. #endif
  1047. #if defined( USE_FRAMETOOLS )
  1048.    if (! lpOutlineDoc->m_fDataTransferDoc)
  1049.       FrameTools_AssociateDoc(lpOutlineDoc->m_lpFrameTools, NULL);
  1050. #endif  // USE_FRAMETOOLS
  1051.    DestroyWindow(lpOutlineDoc->m_hWndDoc);
  1052.    Delete(lpOutlineDoc);   // free memory for doc itself
  1053.    OleDbgOut1("@@@@ DOC DESTROYEDrn");
  1054. #if defined( OLE_VERSION )
  1055.    OleApp_Release(lpOleApp);       // release artificial AddRef above
  1056. #endif
  1057.    OLEDBG_END3
  1058. }
  1059. /* OutlineDoc_ReSize
  1060.  * -----------------
  1061.  *
  1062.  *  Resize the document and its components
  1063.  *
  1064.  * Parameter:
  1065.  *      lpRect  the new size of the document. Use current size if NULL
  1066.  */
  1067. void OutlineDoc_Resize(LPOUTLINEDOC lpOutlineDoc, LPRECT lpRect)
  1068. {
  1069.    RECT            rect;
  1070.    LPLINELIST      lpLL;
  1071. #if defined( USE_HEADING )
  1072.    LPHEADING       lphead;
  1073. #endif  // USE_HEADING
  1074.    LPSCALEFACTOR   lpscale;
  1075.    HWND            hWndLL;
  1076.    if (!lpOutlineDoc)
  1077.       return;
  1078.    lpLL = (LPLINELIST)&lpOutlineDoc->m_LineList;
  1079.    lpscale = (LPSCALEFACTOR)&lpOutlineDoc->m_scale;
  1080.    hWndLL = LineList_GetWindow(lpLL);
  1081.    if (lpRect) {
  1082.       CopyRect((LPRECT)&rect, lpRect);
  1083.       MoveWindow(lpOutlineDoc->m_hWndDoc, rect.left, rect.top,
  1084.             rect.right-rect.left, rect.bottom-rect.top, TRUE);
  1085.    }
  1086.    GetClientRect(lpOutlineDoc->m_hWndDoc, (LPRECT)&rect);
  1087. #if defined( USE_HEADING )
  1088.    lphead = OutlineDoc_GetHeading(lpOutlineDoc);
  1089.    rect.left += Heading_RH_GetWidth(lphead, lpscale);
  1090.    rect.top += Heading_CH_GetHeight(lphead, lpscale);
  1091. #endif  // USE_HEADING
  1092.    if (lpLL) {
  1093.       MoveWindow(hWndLL, rect.left, rect.top,
  1094.             rect.right-rect.left, rect.bottom-rect.top, TRUE);
  1095.    }
  1096. #if defined( USE_HEADING )
  1097.    if (lphead)
  1098.       Heading_Move(lphead, lpOutlineDoc->m_hWndDoc, lpscale);
  1099. #endif  // USE_HEADING
  1100. #if defined( INPLACE_CNTR )
  1101.    ContainerDoc_UpdateInPlaceObjectRects((LPCONTAINERDOC)lpOutlineDoc, 0);
  1102. #endif
  1103. }
  1104. /* OutlineDoc_GetNameTable
  1105.  * -----------------------
  1106.  *
  1107.  *      Get nametable associated with the line list
  1108.  */
  1109. LPOUTLINENAMETABLE OutlineDoc_GetNameTable(LPOUTLINEDOC lpOutlineDoc)
  1110. {
  1111.    if (!lpOutlineDoc)
  1112.       return NULL;
  1113.    else
  1114.       return lpOutlineDoc->m_lpNameTable;
  1115. }
  1116. /* OutlineDoc_GetLineList
  1117.  * ----------------------
  1118.  *
  1119.  *      Get listlist associated with the OutlineDoc
  1120.  */
  1121. LPLINELIST OutlineDoc_GetLineList(LPOUTLINEDOC lpOutlineDoc)
  1122. {
  1123.    if (!lpOutlineDoc)
  1124.       return NULL;
  1125.    else
  1126.       return (LPLINELIST)&lpOutlineDoc->m_LineList;
  1127. }
  1128. /* OutlineDoc_GetNameCount
  1129.  * -----------------------
  1130.  *
  1131.  * Return number of names in table
  1132.  */
  1133. int OutlineDoc_GetNameCount(LPOUTLINEDOC lpOutlineDoc)
  1134. {
  1135.    return OutlineNameTable_GetCount(lpOutlineDoc->m_lpNameTable);
  1136. }
  1137. /* OutlineDoc_GetLineCount
  1138.  * -----------------------
  1139.  *
  1140.  * Return number of lines in the LineList
  1141.  */
  1142. int OutlineDoc_GetLineCount(LPOUTLINEDOC lpOutlineDoc)
  1143. {
  1144.    return LineList_GetCount(&lpOutlineDoc->m_LineList);
  1145. }
  1146. /* OutlineDoc_SetFileName
  1147.  * ----------------------
  1148.  *
  1149.  *      Set the filename of a document.
  1150.  *
  1151.  *  NOTE: If the ServerDoc has a valid filename then, the object is
  1152.  *  registered in the running object table (ROT). if the name of the doc
  1153.  *  changes (eg. via SaveAs) then the previous registration must be revoked
  1154.  *  and the document re-registered under the new name.
  1155.  */
  1156. BOOL OutlineDoc_SetFileName(LPOUTLINEDOC lpOutlineDoc, LPOLESTR lpszNewFileName, LPSTORAGE lpNewStg)
  1157. {
  1158.    OleDbgAssertSz(lpszNewFileName != NULL,   "Can't reset doc to Untitled!");
  1159.    if (lpszNewFileName == NULL)
  1160.       return FALSE;
  1161. //   AnsiLowerBuff(lpszNewFileName, (UINT)OLESTRLEN(lpszNewFileName));
  1162.    CharLowerBuffW(lpszNewFileName, OLESTRLEN(lpszNewFileName));
  1163. #if defined( OLE_CNTR )
  1164.    {
  1165.       LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc;
  1166.       LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc;
  1167.       /* NOTE: the container version of the application keeps its
  1168.       **    storage open at all times. if the document's storage is not
  1169.       **    open, then open it.
  1170.       */
  1171.       if (lpNewStg) {
  1172.          /* CASE 1 -- document is being loaded from a file. lpNewStg is
  1173.          **    still open from the OutlineDoc_LoadFromFile function.
  1174.          */
  1175.          lpOutlineDoc->m_docInitType = DOCTYPE_FROMFILE;
  1176.       } else {
  1177.          /* CASE 2 -- document is being associated with a valid file
  1178.          **    that is not yet open. thus we must now open the file.
  1179.          */
  1180.          if (lpOutlineDoc->m_docInitType == DOCTYPE_FROMFILE &&
  1181.                OLESTRCMP(lpOutlineDoc->m_szFileName,lpszNewFileName)==0) {
  1182.             /* CASE 2a -- new filename is same as current file. if the
  1183.             **    stg is already open, then the lpStg is still valid.
  1184.             **    if it is not open, then open it.
  1185.             */
  1186.             if (! lpOleDoc->m_lpStg) {
  1187.                lpOleDoc->m_lpStg = OleStdOpenRootStorage(
  1188.                      lpszNewFileName,
  1189.                      STGM_READWRITE | STGM_SHARE_DENY_WRITE
  1190.                );
  1191.                if (! lpOleDoc->m_lpStg) return FALSE;
  1192.             }
  1193.          } else {
  1194.             /* CASE 2b -- new filename is NOT same as current file.
  1195.             **    a SaveAs operation is pending. open the new file and
  1196.             **    hold the storage pointer in m_lpNewStg. the
  1197.             **    subsequent call to Doc_SaveToFile will save the
  1198.             **    document into the new storage pointer and release the
  1199.             **    old storage pointer.
  1200.             */
  1201.             lpOutlineDoc->m_docInitType = DOCTYPE_FROMFILE;
  1202.             lpContainerDoc->m_lpNewStg = OleStdCreateRootStorage(
  1203.                   lpszNewFileName,
  1204.                   STGM_READWRITE | STGM_SHARE_DENY_WRITE | STGM_CREATE
  1205.             );
  1206.             if (! lpContainerDoc->m_lpNewStg) return FALSE;
  1207.          }
  1208.       }
  1209.    }
  1210. #endif      // OLE_CNTR
  1211.    if (lpOutlineDoc->m_docInitType != DOCTYPE_FROMFILE ||
  1212.       OLESTRCMP(lpOutlineDoc->m_szFileName, lpszNewFileName) != 0) {
  1213.       /* A new valid file name is being associated with the document */
  1214.       OLESTRCPY(lpOutlineDoc->m_szFileName, lpszNewFileName);
  1215.       lpOutlineDoc->m_docInitType = DOCTYPE_FROMFILE;
  1216.       // set lpszDocTitle to point to filename without path
  1217.       lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName +
  1218.          OLESTRLEN(lpOutlineDoc->m_szFileName) - 1;
  1219.       while (lpOutlineDoc->m_lpszDocTitle > lpOutlineDoc->m_szFileName
  1220.          && ! IS_FILENAME_DELIM(lpOutlineDoc->m_lpszDocTitle[-1])) {
  1221.          lpOutlineDoc->m_lpszDocTitle--;
  1222.       }
  1223.       OutlineDoc_SetTitle(lpOutlineDoc, TRUE /*fMakeUpperCase*/);
  1224. #if defined( OLE_VERSION )
  1225.       {
  1226.          /* NOTE: both containers and servers must properly
  1227.          **    register in the RunningObjectTable. if the document
  1228.          **    is performing a SaveAs operation, then it must
  1229.          **    re-register in the ROT with the new moniker. in
  1230.          **    addition any embedded object, pseudo objects, and/or
  1231.          **    linking clients must be informed that the document's
  1232.          **    moniker has changed.
  1233.          */
  1234.          LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc;
  1235.          if (lpOleDoc->m_lpFileMoniker) {
  1236.             OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpFileMoniker);
  1237.             lpOleDoc->m_lpFileMoniker = NULL;
  1238.          }
  1239.          CreateFileMoniker(lpszNewFileName,&lpOleDoc->m_lpFileMoniker);
  1240.          OleDoc_DocRenamedUpdate(lpOleDoc, lpOleDoc->m_lpFileMoniker);
  1241.       }
  1242. #endif      // OLE_VERSION
  1243.    }
  1244.    return TRUE;
  1245. }
  1246. /* OutlineDoc_SetTitle
  1247.  * -------------------
  1248.  *
  1249.  * Set window text to be current filename.
  1250.  * The following window hierarchy exits:
  1251.  *      hWndApp
  1252.  *          hWndDoc
  1253.  *              hWndListBox
  1254.  *  The frame window is the window which gets the title.
  1255.  */
  1256. void OutlineDoc_SetTitle(LPOUTLINEDOC lpOutlineDoc, BOOL fMakeUpperCase)
  1257. {
  1258.    HWND hWnd;
  1259.    LPSTR lpszText;
  1260.    char  szAnsiStr[256];
  1261.    if (!lpOutlineDoc->m_hWndDoc) return;
  1262.    if ((hWnd = GetParent(lpOutlineDoc->m_hWndDoc)) == NULL) return;
  1263.    lpszText = OleStdMalloc((UINT)(OLESTRLEN(APPNAME) + 4 +
  1264.                            OLESTRLEN(lpOutlineDoc->m_lpszDocTitle)));
  1265.    if (!lpszText) return;
  1266.    W2A(APPNAME, lpszText, OLESTRLEN(APPNAME)+1);
  1267.    lstrcat(lpszText," - ");
  1268.    W2A (lpOutlineDoc->m_lpszDocTitle, szAnsiStr, 256);
  1269.    lstrcat(lpszText, (LPSTR)szAnsiStr);
  1270.    if (fMakeUpperCase)
  1271.       AnsiUpperBuff(lpszText, (UINT)lstrlen(lpszText));
  1272.    SetWindowText(hWnd,lpszText);
  1273.    OleStdFree(lpszText);
  1274. }
  1275. /* OutlineDoc_Close
  1276.  * ----------------
  1277.  *
  1278.  * Close active document. If modified, prompt the user if
  1279.  * he wants to save.
  1280.  *
  1281.  *  Returns:
  1282.  *      FALSE -- user canceled the closing of the doc.
  1283.  *      TRUE -- the doc was successfully closed
  1284.  */
  1285. BOOL OutlineDoc_Close(LPOUTLINEDOC lpOutlineDoc, DWORD dwSaveOption)
  1286. {
  1287.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  1288. #if defined( OLE_VERSION )
  1289.    /* NOTE: call OLE specific function instead */
  1290.    return OleDoc_Close((LPOLEDOC)lpOutlineDoc, dwSaveOption);
  1291. #else
  1292.    if (! lpOutlineDoc)
  1293.       return TRUE;            // active doc's are already destroyed
  1294.    if (! OutlineDoc_CheckSaveChanges(lpOutlineDoc, &dwSaveOption))
  1295.       return FALSE;           // abort closing the doc
  1296.    OutlineDoc_Destroy(lpOutlineDoc);
  1297.    OutlineApp_DocUnlockApp(lpOutlineApp, lpOutlineDoc);
  1298.    return TRUE;
  1299. #endif      // ! OLE_VERSION
  1300. }
  1301. /* OutlineDoc_CheckSaveChanges
  1302.  * ---------------------------
  1303.  *
  1304.  * Check if the document has been modified. if so, prompt the user if
  1305.  *      the changes should be saved. if yes save them.
  1306.  * Returns TRUE if the doc is safe to close (user answered Yes or No)
  1307.  *         FALSE if the user canceled the save changes option.
  1308.  */
  1309. BOOL OutlineDoc_CheckSaveChanges(
  1310.       LPOUTLINEDOC        lpOutlineDoc,
  1311.       LPDWORD             lpdwSaveOption
  1312. )
  1313. {
  1314.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  1315.    int nResponse;
  1316.    char szAnsiString[256];
  1317.    char szAnsiString2[256];
  1318.    if (*lpdwSaveOption == OLECLOSE_NOSAVE)
  1319.       return TRUE;
  1320.    if(! OutlineDoc_IsModified(lpOutlineDoc))
  1321.       return TRUE;    // saving is not necessary
  1322.    /* NOTE: our document is dirty so it needs to be saved. if
  1323.    **    OLECLOSE_PROMPTSAVE the user should be prompted to see if the
  1324.    **    document should be saved. is specified but the document is NOT
  1325.    **    visible to the user, then the user can NOT be prompted. in
  1326.    **    the situation the document should be saved without prompting.
  1327.    **    if OLECLOSE_SAVEIFDIRTY is specified then, the document
  1328.    **    should also be saved without prompting.
  1329.    */
  1330.    if (*lpdwSaveOption == OLECLOSE_PROMPTSAVE &&
  1331.          IsWindowVisible(lpOutlineDoc->m_hWndDoc)) {
  1332.       // prompt the user to see if changes should be saved.
  1333. #if defined( OLE_VERSION )
  1334.       OleApp_PreModalDialog(
  1335.             (LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineApp->m_lpDoc);
  1336. #endif
  1337.       W2A (APPNAME, szAnsiString, 256);
  1338.       W2A (MsgSaveFile, szAnsiString2, 256);
  1339.       nResponse = MessageBox(
  1340.             lpOutlineApp->m_hWndApp,
  1341.             szAnsiString2,
  1342.             szAnsiString,
  1343.             MB_ICONQUESTION | MB_YESNOCANCEL
  1344.       );
  1345. #if defined( OLE_VERSION )
  1346.       OleApp_PostModalDialog(
  1347.             (LPOLEAPP)lpOutlineApp, (LPOLEDOC)lpOutlineApp->m_lpDoc);
  1348. #endif
  1349.       if(nResponse==IDCANCEL)
  1350.          return FALSE;   // close is canceled
  1351.       if(nResponse==IDNO) {
  1352.          // Reset the save option to NOSAVE per user choice
  1353.          *lpdwSaveOption = OLECLOSE_NOSAVE;
  1354.          return TRUE;    // don't save, but is ok to close
  1355.       }
  1356.    } else if (*lpdwSaveOption != OLECLOSE_SAVEIFDIRTY) {
  1357.       OleDbgAssertSz(FALSE, "Invalid dwSaveOptionrn");
  1358.       *lpdwSaveOption = OLECLOSE_NOSAVE;
  1359.       return TRUE;        // unknown *lpdwSaveOption; close w/o saving
  1360.    }
  1361. #if defined( OLE_SERVER )
  1362.    if (lpOutlineDoc->m_docInitType == DOCTYPE_EMBEDDED) {
  1363.       LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc;
  1364.       HRESULT hrErr;
  1365.       /* NOTE: Update the container before closing without prompting
  1366.       **    the user. To update the container, we must ask our container
  1367.       **    to save us.
  1368.       */
  1369.       OleDbgAssert(lpServerDoc->m_lpOleClientSite != NULL);
  1370.       OLEDBG_BEGIN2("IOleClientSite::SaveObject calledrn")
  1371.       hrErr = lpServerDoc->m_lpOleClientSite->lpVtbl->SaveObject(
  1372.             lpServerDoc->m_lpOleClientSite
  1373.       );
  1374.       OLEDBG_END2
  1375.       if (hrErr != NOERROR) {
  1376.          OleDbgOutHResult("IOleClientSite::SaveObject returned", hrErr);
  1377.          return FALSE;
  1378.       }
  1379.       return TRUE;    // doc is safe to be closed
  1380.    } else
  1381. #endif      // OLE_SERVER
  1382.    {
  1383.       return OutlineApp_SaveCommand(lpOutlineApp);
  1384.    }
  1385. }
  1386. /* OutlineDoc_IsModified
  1387.  * ---------------------
  1388.  *
  1389.  * Return modify flag of OUTLINEDOC
  1390.  */
  1391. BOOL OutlineDoc_IsModified(LPOUTLINEDOC lpOutlineDoc)
  1392. {
  1393.    if (lpOutlineDoc->m_fModified)
  1394.       return lpOutlineDoc->m_fModified;
  1395. #if defined( OLE_CNTR )
  1396.    {
  1397.       /* NOTE: if there are OLE objects, then we must ask if any of
  1398.       **    them are dirty. if so we must consider our document
  1399.       **    as modified.
  1400.       */
  1401.       LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc;
  1402.       LPLINELIST  lpLL;
  1403.       int         nLines;
  1404.       int         nIndex;
  1405.       LPLINE      lpLine;
  1406.       HRESULT     hrErr;
  1407.       lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
  1408.       nLines = LineList_GetCount(lpLL);
  1409.       for (nIndex = 0; nIndex < nLines; nIndex++) {
  1410.          lpLine = LineList_GetLine(lpLL, nIndex);
  1411.          if (!lpLine)
  1412.             break;
  1413.          if (Line_GetLineType(lpLine) == CONTAINERLINETYPE) {
  1414.             LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
  1415.             if (lpContainerLine->m_lpPersistStg) {
  1416.                hrErr = lpContainerLine->m_lpPersistStg->lpVtbl->IsDirty(
  1417.                      lpContainerLine->m_lpPersistStg);
  1418.                /* NOTE: we will only accept an explicit "no i
  1419.                **    am NOT dirty statement" (ie. S_FALSE) as an
  1420.                **    indication that the object is clean. eg. if
  1421.                **    the object returns E_NOTIMPL we must
  1422.                **    interpret it as the object IS dirty.
  1423.                */
  1424.                if (GetScode(hrErr) != S_FALSE)
  1425.                   return TRUE;
  1426.             }
  1427.          }
  1428.       }
  1429.    }
  1430. #endif
  1431.    return FALSE;
  1432. }
  1433. /* OutlineDoc_SetModified
  1434.  * ----------------------
  1435.  *
  1436.  *  Set the modified flag of the document
  1437.  *
  1438.  */
  1439. void OutlineDoc_SetModified(LPOUTLINEDOC lpOutlineDoc, BOOL fModified, BOOL fDataChanged, BOOL fSizeChanged)
  1440. {
  1441.    lpOutlineDoc->m_fModified = fModified;
  1442. #if defined( OLE_SERVER )
  1443.    if (! lpOutlineDoc->m_fDataTransferDoc) {
  1444.       LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc;
  1445.       /* NOTE: if the document has changed, then broadcast the change
  1446.       **    to all clients who have set up Advise connections. notify
  1447.       **    them that our data (and possibly also our extents) have
  1448.       **    changed.
  1449.       */
  1450.       if (fDataChanged) {
  1451.          lpServerDoc->m_fDataChanged     = TRUE;
  1452.          lpServerDoc->m_fSizeChanged     = fSizeChanged;
  1453.          lpServerDoc->m_fSendDataOnStop  = TRUE;
  1454.          ServerDoc_SendAdvise(
  1455.                lpServerDoc,
  1456.                OLE_ONDATACHANGE,
  1457.                NULL,   /* lpmkDoc -- not relevant here */
  1458.                0       /* advf -- no flags necessary */
  1459.          );
  1460.       }
  1461.    }
  1462. #endif  // OLE_SERVER
  1463. }
  1464. /* OutlineDoc_SetRedraw
  1465.  * --------------------
  1466.  *
  1467.  *  Enable/Disable the redraw of the document on screen.
  1468.  *  The calls to SetRedraw counted so that nested calls can be handled
  1469.  *  properly. calls to SetRedraw must be balanced.
  1470.  *
  1471.  *  fEnbaleDraw = TRUE      - enable redraw
  1472.  *                FALSE     - disable redraw
  1473.  */
  1474. void OutlineDoc_SetRedraw(LPOUTLINEDOC lpOutlineDoc, BOOL fEnableDraw)
  1475. {
  1476.    static HCURSOR hPrevCursor = NULL;
  1477.    if (fEnableDraw) {
  1478.       if (lpOutlineDoc->m_nDisableDraw == 0)
  1479.          return;     // already enabled; no state transition
  1480.       if (--lpOutlineDoc->m_nDisableDraw > 0)
  1481.          return;     // drawing should still be disabled
  1482.    } else {
  1483.       if (lpOutlineDoc->m_nDisableDraw++ > 0)
  1484.          return;     // already disabled; no state transition
  1485.    }
  1486.    if (lpOutlineDoc->m_nDisableDraw > 0) {
  1487.       // this may take a while, put up hourglass cursor
  1488.       hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  1489.    } else {
  1490.       if (hPrevCursor) {
  1491.          SetCursor(hPrevCursor);     // restore original cursor
  1492.          hPrevCursor = NULL;
  1493.       }
  1494.    }
  1495. #if defined( OLE_SERVER )
  1496.    /* NOTE: for the Server version, while Redraw is disabled
  1497.    **    postpone sending advise notifications until Redraw is re-enabled.
  1498.    */
  1499.    {
  1500.       LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc;
  1501.       LPSERVERNAMETABLE lpServerNameTable =
  1502.             (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable;
  1503.       if (lpOutlineDoc->m_nDisableDraw == 0) {
  1504.          /* drawing is being Enabled. if changes occurred while drawing
  1505.          **    was disabled, then notify clients now.
  1506.          */
  1507.          if (lpServerDoc->m_fDataChanged)
  1508.             ServerDoc_SendAdvise(
  1509.                   lpServerDoc,
  1510.                   OLE_ONDATACHANGE,
  1511.                   NULL,   /* lpmkDoc -- not relevant here */
  1512.                   0       /* advf -- no flags necessary */
  1513.             );
  1514.          /* NOTE: send pending change notifications for pseudo objs. */
  1515.          ServerNameTable_SendPendingAdvises(lpServerNameTable);
  1516.       }
  1517.    }
  1518. #endif      // OLE_SERVER
  1519. #if defined( OLE_CNTR )
  1520.    /* NOTE: for the Container version, while Redraw is disabled
  1521.    **    postpone updating the extents of OLE objects until Redraw is
  1522.    **    re-enabled.
  1523.    */
  1524.    {
  1525.       LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc;
  1526.       /* Update the extents of any OLE object that is marked that
  1527.       **    its size may  have changed. when an
  1528.       **    IAdviseSink::OnViewChange notification is received,
  1529.       **    the corresponding ContainerLine is marked
  1530.       **    (m_fDoGetExtent==TRUE) and a message
  1531.       **    (WM_U_UPDATEOBJECTEXTENT) is posted to the document
  1532.       **    indicating that there are dirty objects.
  1533.       */
  1534.       if (lpOutlineDoc->m_nDisableDraw == 0)
  1535.          ContainerDoc_UpdateExtentOfAllOleObjects(lpContainerDoc);
  1536.    }
  1537. #endif      // OLE_CNTR
  1538.    // enable/disable redraw of the LineList listbox
  1539.    LineList_SetRedraw(&lpOutlineDoc->m_LineList, fEnableDraw);
  1540. }
  1541. /* OutlineDoc_SetSel
  1542.  * -----------------
  1543.  *
  1544.  *      Set the selection in the documents's LineList
  1545.  */
  1546. void OutlineDoc_SetSel(LPOUTLINEDOC lpOutlineDoc, LPLINERANGE lplrSel)
  1547. {
  1548.    LineList_SetSel(&lpOutlineDoc->m_LineList, lplrSel);
  1549. }
  1550. /* OutlineDoc_GetSel
  1551.  * -----------------
  1552.  *
  1553.  *      Get the selection in the documents's LineList.
  1554.  *
  1555.  *      Returns the count of items selected
  1556.  */
  1557. int OutlineDoc_GetSel(LPOUTLINEDOC lpOutlineDoc, LPLINERANGE lplrSel)
  1558. {
  1559.    return LineList_GetSel(&lpOutlineDoc->m_LineList, lplrSel);
  1560. }
  1561. /* OutlineDoc_ForceRedraw
  1562.  * ----------------------
  1563.  *
  1564.  *      Force the document window to repaint.
  1565.  */
  1566. void OutlineDoc_ForceRedraw(LPOUTLINEDOC lpOutlineDoc, BOOL fErase)
  1567. {
  1568.    if (!lpOutlineDoc)
  1569.       return;
  1570.    LineList_ForceRedraw(&lpOutlineDoc->m_LineList, fErase);
  1571.    Heading_CH_ForceRedraw(&lpOutlineDoc->m_heading, fErase);
  1572.    Heading_RH_ForceRedraw(&lpOutlineDoc->m_heading, fErase);
  1573. }
  1574. /* OutlineDoc_RenderFormat
  1575.  * -----------------------
  1576.  *
  1577.  *      Render a clipboard format supported by ClipboardDoc
  1578.  */
  1579. void OutlineDoc_RenderFormat(LPOUTLINEDOC lpOutlineDoc, UINT uFormat)
  1580. {
  1581.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  1582.    HGLOBAL      hData = NULL;
  1583.    if (uFormat == lpOutlineApp->m_cfOutline)
  1584.       hData = OutlineDoc_GetOutlineData(lpOutlineDoc, NULL);
  1585.    else if (uFormat == CF_TEXT)
  1586.       hData = OutlineDoc_GetTextData(lpOutlineDoc, NULL);
  1587.    else {
  1588.       OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgFormatNotSupported);
  1589.       return;
  1590.    }
  1591.    SetClipboardData(uFormat, hData);
  1592. }
  1593. /* OutlineDoc_RenderAllFormats
  1594.  * ---------------------------
  1595.  *
  1596.  *      Render all formats supported by ClipboardDoc
  1597.  */
  1598. void OutlineDoc_RenderAllFormats(LPOUTLINEDOC lpOutlineDoc)
  1599. {
  1600.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  1601.    HGLOBAL      hData = NULL;
  1602.    OpenClipboard(lpOutlineDoc->m_hWndDoc);
  1603.    hData = OutlineDoc_GetOutlineData(lpOutlineDoc, NULL);
  1604.    SetClipboardData(lpOutlineApp->m_cfOutline, hData);
  1605.    hData = OutlineDoc_GetTextData(lpOutlineDoc, NULL);
  1606.    SetClipboardData(CF_TEXT, hData);
  1607.    CloseClipboard();
  1608. }
  1609. /* OutlineDoc_GetOutlineData
  1610.  * -------------------------
  1611.  *
  1612.  * Return a handle to an array of TextLine objects for the desired line
  1613.  *      range.
  1614.  *  NOTE: if lplrSel == NULL, then all lines are returned
  1615.  *
  1616.  */
  1617. HGLOBAL OutlineDoc_GetOutlineData(LPOUTLINEDOC lpOutlineDoc, LPLINERANGE lplrSel)
  1618. {
  1619.    HGLOBAL     hOutline  = NULL;
  1620.    LPLINELIST  lpLL=(LPLINELIST)&lpOutlineDoc->m_LineList;
  1621.    LPLINE      lpLine;
  1622.    LPTEXTLINE  arrLine;
  1623.    int     i;
  1624.    int     nStart = (lplrSel ? lplrSel->m_nStartLine : 0);
  1625.    int     nEnd =(lplrSel ? lplrSel->m_nEndLine : LineList_GetCount(lpLL)-1);
  1626.    int     nLines = nEnd - nStart + 1;
  1627.    int     nCopied = 0;
  1628.    hOutline=GlobalAlloc(GALLOCFLG, sizeof(TEXTLINE)*nLines);
  1629.    if (! hOutline) return NULL;
  1630.    arrLine=(LPTEXTLINE)GlobalLock(hOutline);
  1631.    for (i = nStart; i <= nEnd; i++) {
  1632.       lpLine=LineList_GetLine(lpLL, i);
  1633.       if (lpLine && Line_GetOutlineData(lpLine, &arrLine[nCopied]))
  1634.          nCopied++;
  1635.    }
  1636.    GlobalUnlock(hOutline);
  1637.    return hOutline;
  1638. }
  1639. /* OutlineDoc_GetTextData
  1640.  * ----------------------
  1641.  *
  1642.  * Return a handle to an object's data in text form for the desired line
  1643.  *      range.
  1644.  *  NOTE: if lplrSel == NULL, then all lines are returned
  1645.  *
  1646.  */
  1647. HGLOBAL OutlineDoc_GetTextData(LPOUTLINEDOC lpOutlineDoc, LPLINERANGE lplrSel)
  1648. {
  1649.    LPLINELIST  lpLL=(LPLINELIST)&lpOutlineDoc->m_LineList;
  1650.    LPLINE  lpLine;
  1651.    HGLOBAL hText = NULL;
  1652.    LPOLESTR   lpszText = NULL;
  1653.    DWORD   dwMemSize=0;
  1654.    int     i,j;
  1655.    int     nStart = (lplrSel ? lplrSel->m_nStartLine : 0);
  1656.    int     nEnd =(lplrSel ? lplrSel->m_nEndLine : LineList_GetCount(lpLL)-1);
  1657.    int     nTabLevel;
  1658.    // calculate memory size required
  1659.    for(i = nStart; i <= nEnd; i++) {
  1660.       lpLine=LineList_GetLine(lpLL, i);
  1661.       if (! lpLine)
  1662.          continue;
  1663.       dwMemSize += Line_GetTabLevel(lpLine);
  1664.       dwMemSize += Line_GetTextLen(lpLine);
  1665.       dwMemSize += 2; // add 1 for 'rn' at the end of each line
  1666.    }
  1667.    dwMemSize++;        // add 1 for '' at the end of string
  1668.    if(!(hText = GlobalAlloc(GALLOCFLG, dwMemSize)))
  1669.       return NULL;
  1670.    if(!(lpszText = /*(LPOLESTR)*/GlobalLock(hText)))
  1671.       return NULL;
  1672.    // put line text to memory
  1673.    for(i = nStart; i <= nEnd; i++) {
  1674.       lpLine=LineList_GetLine(lpLL, i);
  1675.       if (! lpLine)
  1676.          continue;
  1677.       nTabLevel=Line_GetTabLevel(lpLine);
  1678.       for(j = 0; j < nTabLevel; j++)
  1679.          *lpszText++='t';
  1680.       Line_GetTextData(lpLine, lpszText);
  1681.       while(*lpszText)
  1682.          lpszText++;     // advance to end of string
  1683.       *lpszText++ = 'r';
  1684.       *lpszText++ = 'n';
  1685.    }
  1686.    GlobalUnlock (hText);
  1687.    return hText;
  1688. }
  1689. /* OutlineDoc_SaveToFile
  1690.  * ---------------------
  1691.  *
  1692.  *      Save the document to a file with the same name as stored in the
  1693.  * document
  1694.  */
  1695. BOOL OutlineDoc_SaveToFile(LPOUTLINEDOC lpOutlineDoc, LPCOLESTR lpszFileName, UINT uFormat, BOOL fRemember)
  1696. {
  1697. #if defined( OLE_CNTR )
  1698.    // Call OLE container specific function instead
  1699.    return ContainerDoc_SaveToFile(
  1700.          (LPCONTAINERDOC)lpOutlineDoc,
  1701.          lpszFileName,
  1702.          uFormat,
  1703.          fRemember
  1704.    );
  1705. #else
  1706.    LPSTORAGE lpDestStg = NULL;
  1707.    HRESULT hrErr;
  1708.    BOOL fStatus;
  1709.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  1710.    if (fRemember) {
  1711.       if (lpszFileName) {
  1712.          fStatus = OutlineDoc_SetFileName(
  1713.                lpOutlineDoc,
  1714.                (LPOLESTR)lpszFileName,
  1715.                NULL
  1716.          );
  1717.          if (! fStatus) goto error;
  1718.       } else
  1719.          lpszFileName = lpOutlineDoc->m_szFileName; // use cur. file name
  1720.    } else if (! lpszFileName) {
  1721.       goto error;
  1722.    }
  1723.    hrErr = StgCreateDocfile(
  1724.          lpszFileName,
  1725.          STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE|STGM_CREATE,
  1726.          0,
  1727.          &lpDestStg
  1728.    );
  1729.    OleDbgAssertSz(hrErr == NOERROR, "Could not create Docfile");
  1730.    if (hrErr != NOERROR)
  1731.       goto error;
  1732. #if defined( OLE_SERVER )
  1733.    /*  NOTE: we must be sure to write our class ID into our
  1734.    **    storage. this information is used by OLE to determine the
  1735.    **    class of the data stored in our storage. Even for top
  1736.    **    "file-level" objects this information should be written to
  1737.    **    the file.
  1738.    */
  1739.    if(WriteClassStg(lpDestStg, &CLSID_APP) != NOERROR)
  1740.       goto error;
  1741. #endif
  1742.    fStatus = OutlineDoc_SaveSelToStg(
  1743.          lpOutlineDoc,
  1744.          NULL,
  1745.          uFormat,
  1746.          lpDestStg,
  1747.          FALSE,      /* fSameAsLoad */
  1748.          fRemember
  1749.    );
  1750.    if (! fStatus) goto error;
  1751.    OleStdRelease((LPUNKNOWN)lpDestStg);
  1752.    if (fRemember)
  1753.       OutlineDoc_SetModified(lpOutlineDoc, FALSE, FALSE, FALSE);
  1754. #if defined( OLE_SERVER )
  1755.    /* NOTE: (SERVER-ONLY) inform any linking clients that the
  1756.    **    document has been saved. in addition, any currently active
  1757.    **    pseudo objects should also inform their clients.
  1758.    */
  1759.    ServerDoc_SendAdvise (
  1760.          (LPSERVERDOC)lpOutlineDoc,
  1761.          OLE_ONSAVE,
  1762.          NULL,   /* lpmkDoc -- not relevant here */
  1763.          0       /* advf -- not relevant here */
  1764.    );
  1765. #endif
  1766.    return TRUE;
  1767. error:
  1768.    if (lpDestStg)
  1769.       OleStdRelease((LPUNKNOWN)lpDestStg);
  1770.    OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgSaving);
  1771.    return FALSE;
  1772. #endif  // ! OLE_CNTR
  1773. }
  1774. /* OutlineDoc_LoadFromFile
  1775.  * -----------------------
  1776.  *
  1777.  *      Load a document from a file
  1778.  */
  1779. BOOL OutlineDoc_LoadFromFile(LPOUTLINEDOC lpOutlineDoc, LPOLESTR lpszFileName)
  1780. {
  1781.    LPOUTLINEAPP    lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  1782.    LPLINELIST      lpLL = &lpOutlineDoc->m_LineList;
  1783.    HRESULT         hrErr;
  1784.    SCODE           sc;
  1785.    LPSTORAGE       lpSrcStg;
  1786.    BOOL            fStatus;
  1787.    hrErr = StgOpenStorage(lpszFileName,
  1788.          NULL,
  1789. #if defined( OLE_CNTR )
  1790.          STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_DENY_WRITE,
  1791. #else
  1792.          STGM_READ | STGM_SHARE_DENY_WRITE,
  1793. #endif
  1794.          NULL,
  1795.          0,
  1796.          &lpSrcStg
  1797.    );
  1798.    if ((sc = GetScode(hrErr)) == STG_E_FILENOTFOUND) {
  1799.       OutlineApp_ErrorMessage(lpOutlineApp, OLESTR("File not found"));
  1800.       return FALSE;
  1801.    } else if (sc == STG_E_FILEALREADYEXISTS) {
  1802.       OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgFormat);
  1803.       return FALSE;
  1804.    } else if (sc != S_OK) {
  1805.       OleDbgOutScode("StgOpenStorage returned", sc);
  1806.       OutlineApp_ErrorMessage(
  1807.             lpOutlineApp,
  1808.             OLESTR("File already in use--could not be opened")
  1809.       );
  1810.       return FALSE;
  1811.    }
  1812.    if(! OutlineDoc_LoadFromStg(lpOutlineDoc, lpSrcStg)) goto error;
  1813.    fStatus = OutlineDoc_SetFileName(lpOutlineDoc, lpszFileName, lpSrcStg);
  1814.    if (! fStatus) goto error;
  1815.    OleStdRelease((LPUNKNOWN)lpSrcStg);
  1816.    return TRUE;
  1817. error:
  1818.    OleStdRelease((LPUNKNOWN)lpSrcStg);
  1819.    OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgOpening);
  1820.    return FALSE;
  1821. }
  1822. /* OutlineDoc_LoadFromStg
  1823.  * ----------------------
  1824.  *
  1825.  *  Load entire document from an open IStorage pointer (lpSrcStg)
  1826.  *      Return TRUE if ok, FALSE if error.
  1827.  */
  1828. BOOL OutlineDoc_LoadFromStg(LPOUTLINEDOC lpOutlineDoc, LPSTORAGE lpSrcStg)
  1829. {
  1830.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  1831.    HRESULT hrErr;
  1832.    BOOL fStatus;
  1833.    ULONG nRead;
  1834.    LINERANGE lrSel = { 0, 0 };
  1835.    LPSTREAM lpLLStm;
  1836.    OUTLINEDOCHEADER docRecord;
  1837.    OUTLINEDOCHEADER_ONDISK docRecordOnDisk;
  1838.    hrErr = lpSrcStg->lpVtbl->OpenStream(
  1839.          lpSrcStg,
  1840.          OLESTR("LineList"),
  1841.          NULL,
  1842.          STGM_READ | STGM_SHARE_EXCLUSIVE,
  1843.          0,
  1844.          &lpLLStm
  1845.    );
  1846.    if (hrErr != NOERROR) {
  1847.       OleDbgOutHResult("Open LineList Stream returned", hrErr);
  1848.       goto error;
  1849.    }
  1850.    /* read OutlineDoc header record */
  1851.    hrErr = lpLLStm->lpVtbl->Read(
  1852.          lpLLStm,
  1853.          (LPVOID)&docRecordOnDisk,
  1854.          sizeof(docRecordOnDisk),
  1855.          &nRead
  1856.    );
  1857.    if (hrErr != NOERROR) {
  1858.       OleDbgOutHResult("Read OutlineDoc header returned", hrErr);
  1859.       goto error;
  1860.     }
  1861.     //  Transform docRecordOnDisk into docRecord
  1862.     //  Compilers should handle aligment correctly
  1863.     OLESTRCPY(docRecord.m_szFormatName, docRecordOnDisk.m_szFormatName);
  1864.     docRecord.m_narrAppVersionNo[0] = (int) docRecordOnDisk.m_narrAppVersionNo[0];
  1865.     docRecord.m_narrAppVersionNo[1] = (int) docRecordOnDisk.m_narrAppVersionNo[1];
  1866.     docRecord.m_fShowHeading = (BOOL) docRecordOnDisk.m_fShowHeading;
  1867.     docRecord.m_reserved1 = docRecordOnDisk.m_reserved1;
  1868.     docRecord.m_reserved2 = docRecordOnDisk.m_reserved2;
  1869.     docRecord.m_reserved3 = docRecordOnDisk.m_reserved3;
  1870.     docRecord.m_reserved4 = docRecordOnDisk.m_reserved4;
  1871.    fStatus = OutlineApp_VersionNoCheck(
  1872.          lpOutlineApp,
  1873.          docRecord.m_szFormatName,
  1874.          docRecord.m_narrAppVersionNo
  1875.    );
  1876.    /* storage is an incompatible version; file can not be read */
  1877.    if (! fStatus)
  1878.       goto error;
  1879.    lpOutlineDoc->m_heading.m_fShow = docRecord.m_fShowHeading;
  1880. #if defined( OLE_SERVER )
  1881.    {
  1882.       // Load ServerDoc specific data
  1883.       LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc;
  1884. #if defined( SVR_TREATAS )
  1885.       LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  1886.       CLSID       clsid;
  1887.       CLIPFORMAT  cfFmt;
  1888.       LPOLESTR       lpszType;
  1889. #endif  // SVR_TREATAS
  1890.       lpServerDoc->m_nNextRangeNo = (ULONG)docRecord.m_reserved1;
  1891. #if defined( SVR_TREATAS )
  1892.       /* NOTE: if the Server is capable of supporting "TreatAs"
  1893.       **    (aka. ActivateAs), it must read the class that is written
  1894.       **    into the storage. if this class is NOT the app's own
  1895.       **    class ID, then this is a TreatAs operation. the server
  1896.       **    then must faithfully pretend to be the class that is
  1897.       **    written into the storage. it must also faithfully write
  1898.       **    the data back to the storage in the SAME format as is
  1899.       **    written in the storage.
  1900.       **
  1901.       **    SVROUTL and ISVROTL can emulate each other. they have the
  1902.       **    simplification that they both read/write the identical
  1903.       **    format. thus for these apps no actual conversion of the
  1904.       **    native bits is actually required.
  1905.       */
  1906.       lpServerDoc->m_clsidTreatAs = CLSID_NULL;
  1907.       if (OleStdGetTreatAsFmtUserType(&CLSID_APP, lpSrcStg, &clsid,
  1908.                      (CLIPFORMAT FAR*)&cfFmt, /*(LPOLESTR FAR*)*/&lpszType)) {
  1909.          if (cfFmt == lpOutlineApp->m_cfOutline) {
  1910.             // We should perform TreatAs operation
  1911.             if (lpServerDoc->m_lpszTreatAsType)
  1912.                OleStdFreeString(lpServerDoc->m_lpszTreatAsType, NULL);
  1913.             lpServerDoc->m_clsidTreatAs = clsid;
  1914.             ((LPOUTLINEDOC)lpServerDoc)->m_cfSaveFormat = cfFmt;
  1915.             lpServerDoc->m_lpszTreatAsType = lpszType;
  1916.             OleDbgOut3("OutlineDoc_LoadFromStg: TreateAs ==> '");
  1917. //          OleDbgOutNoPrefix3(lpServerDoc->m_lpszTreatAsType);
  1918.             OleDbgOutNoPrefix3("'rn");
  1919.          } else {
  1920.             // ERROR: we ONLY support TreatAs for CF_OUTLINE format
  1921.             OleDbgOut("SvrDoc_PStg_InitNew: INVALID TreatAs Formatrn");
  1922.             OleStdFreeString(lpszType, NULL);
  1923.          }
  1924.       }
  1925. #endif  // SVR_TREATAS
  1926.    }
  1927. #endif  // OLE_SVR
  1928. #if defined( OLE_CNTR )
  1929.    {
  1930.       // Load ContainerDoc specific data
  1931.       LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc;
  1932.       lpContainerDoc->m_nNextObjNo = (ULONG)docRecord.m_reserved2;
  1933.    }
  1934. #endif  // OLE_CNTR
  1935.    OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE );
  1936.    if(! LineList_LoadFromStg(&lpOutlineDoc->m_LineList, lpSrcStg, lpLLStm))
  1937.       goto error;
  1938.    if(! OutlineNameTable_LoadFromStg(lpOutlineDoc->m_lpNameTable, lpSrcStg))
  1939.       goto error;
  1940.    OutlineDoc_SetModified(lpOutlineDoc, FALSE, FALSE, FALSE);
  1941.    OutlineDoc_SetSel(lpOutlineDoc, &lrSel);
  1942.    OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE );
  1943.    OleStdRelease((LPUNKNOWN)lpLLStm);
  1944. #if defined( OLE_CNTR )
  1945.    {
  1946.       LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc;
  1947.       /* A ContainerDoc keeps its storage open at all times. it is necessary
  1948.       *   to AddRef the lpSrcStg in order to hang on to it.
  1949.       */
  1950.       if (lpOleDoc->m_lpStg) {
  1951.          OleStdVerifyRelease((LPUNKNOWN)lpOleDoc->m_lpStg,
  1952.                OLESTR("Doc Storage not released properly"));
  1953.       }
  1954.       lpSrcStg->lpVtbl->AddRef(lpSrcStg);
  1955.       lpOleDoc->m_lpStg = lpSrcStg;
  1956.    }
  1957. #endif      // OLE_CNTR
  1958.    return TRUE;
  1959. error:
  1960.    OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE );
  1961.    if (lpLLStm)
  1962.       OleStdRelease((LPUNKNOWN)lpLLStm);
  1963.    return FALSE;
  1964. }
  1965. /* OutlineDoc_SaveSelToStg
  1966.  * -----------------------
  1967.  *
  1968.  *      Save the specified selection of document into an IStorage*. All lines
  1969.  * within the selection along with any names completely contained within the
  1970.  * selection will be written
  1971.  *
  1972.  *      Return TRUE if ok, FALSE if error
  1973.  */
  1974. BOOL OutlineDoc_SaveSelToStg(
  1975.       LPOUTLINEDOC        lpOutlineDoc,
  1976.       LPLINERANGE         lplrSel,
  1977.       UINT                uFormat,
  1978.       LPSTORAGE           lpDestStg,
  1979.       BOOL                fSameAsLoad,
  1980.       BOOL                fRemember
  1981. )
  1982. {
  1983.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  1984.    HRESULT hrErr = NOERROR;
  1985.    LPSTREAM lpLLStm = NULL;
  1986.    LPSTREAM lpNTStm = NULL;
  1987.    ULONG nWritten;
  1988.    BOOL fStatus;
  1989.    OUTLINEDOCHEADER docRecord;
  1990.    OUTLINEDOCHEADER_ONDISK docRecordOnDisk;
  1991.    HCURSOR  hPrevCursor;
  1992.    char szAnsiString[256];
  1993. #if defined( OLE_VERSION )
  1994.    LPOLESTR lpszUserType;
  1995.    LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineDoc;
  1996.    /*  NOTE: we must be sure to write the information required for
  1997.    **    OLE into our docfile. this includes user type
  1998.    **    name, data format, etc. Even for top "file-level" objects
  1999.    **    this information should be written to the file. Both
  2000.    **    containters and servers should write this information.
  2001.    */
  2002. #if defined( OLE_SERVER ) && defined( SVR_TREATAS )
  2003.    LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc;
  2004.    /* NOTE: if the Server is emulating another class (ie.
  2005.    **    "TreatAs" aka. ActivateAs), it must write the same user type
  2006.    **    name and format that was was originally written into the
  2007.    **    storage rather than its own user type name.
  2008.    **
  2009.    **    SVROUTL and ISVROTL can emulate each other. they have the
  2010.    **    simplification that they both read/write the identical
  2011.    **    format. thus for these apps no actual conversion of the
  2012.    **    native bits is actually required.
  2013.    */
  2014.    if (! IsEqualCLSID(&lpServerDoc->m_clsidTreatAs, &CLSID_NULL))
  2015.       lpszUserType = lpServerDoc->m_lpszTreatAsType;
  2016.    else
  2017. #endif  // OLE_SERVER && SVR_TREATAS
  2018.       lpszUserType = /*(LPOLESTR)*/FULLUSERTYPENAME;
  2019.    hrErr = WriteFmtUserTypeStg(lpDestStg, (CLIPFORMAT)uFormat, lpszUserType);
  2020.    if(hrErr != NOERROR) goto error;
  2021.    if (fSameAsLoad) {
  2022.       /* NOTE: we are saving into to same storage that we were
  2023.       **    passed an load time. we deliberatly opened the streams we
  2024.       **    need (lpLLStm and lpNTStm) at load time, so that we can
  2025.       **    robustly save at save time in a low-memory situation.
  2026.       **    this is particulary important the embedded objects do NOT
  2027.       **    consume additional memory when
  2028.       **    IPersistStorage::Save(fSameAsLoad==TRUE) is called.
  2029.       */
  2030.       LARGE_INTEGER libZero;
  2031.       ULARGE_INTEGER ulibZero;
  2032.       LISet32( libZero, 0 );
  2033.       LISet32( ulibZero, 0 );
  2034.       lpLLStm = lpOleDoc->m_lpLLStm;
  2035.       /*  because this is the fSameAsLoad==TRUE case, we will save
  2036.       **    into the streams that we hold open. we will AddRef the
  2037.       **    stream here so that the release below will NOT close the
  2038.       **    stream.
  2039.       */
  2040.       lpLLStm->lpVtbl->AddRef(lpLLStm);
  2041.       // truncate the current stream and seek to beginning
  2042.       lpLLStm->lpVtbl->SetSize(lpLLStm, ulibZero);
  2043.       lpLLStm->lpVtbl->Seek(
  2044.             lpLLStm, libZero, STREAM_SEEK_SET, NULL);
  2045.       lpNTStm = lpOleDoc->m_lpNTStm;
  2046.       lpNTStm->lpVtbl->AddRef(lpNTStm);   // (see comment above)
  2047.       // truncate the current stream and seek to beginning
  2048.       lpNTStm->lpVtbl->SetSize(lpNTStm, ulibZero);
  2049.       lpNTStm->lpVtbl->Seek(
  2050.             lpNTStm, libZero, STREAM_SEEK_SET, NULL);
  2051.    } else
  2052. #endif  // OLE_VERSION
  2053.    {
  2054.       hrErr = lpDestStg->lpVtbl->CreateStream(
  2055.             lpDestStg,
  2056.             OLESTR("LineList"),
  2057.             STGM_WRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
  2058.             0,
  2059.             0,
  2060.             &lpLLStm
  2061.       );
  2062.       if (hrErr != NOERROR) {
  2063.          OleDbgAssertSz(hrErr==NOERROR,"Could not create LineList stream");
  2064.          OleDbgOutHResult("LineList CreateStream returned", hrErr);
  2065.          goto error;
  2066.       }
  2067.       hrErr = lpDestStg->lpVtbl->CreateStream(
  2068.             lpDestStg,
  2069.             OLESTR("NameTable"),
  2070.             STGM_WRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
  2071.             0,
  2072.             0,
  2073.             &lpNTStm
  2074.       );
  2075.       if (hrErr != NOERROR) {
  2076.          OleDbgAssertSz(hrErr==NOERROR,"Could not create NameTable stream");
  2077.          OleDbgOutHResult("NameTable CreateStream returned", hrErr);
  2078.          goto error;
  2079.       }
  2080.    }
  2081.    // this may take a while, put up hourglass cursor
  2082.    hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  2083.    _fmemset((LPOUTLINEDOCHEADER)&docRecord,0,sizeof(OUTLINEDOCHEADER));
  2084.    GetClipboardFormatName(
  2085.          uFormat,
  2086.          szAnsiString,
  2087.          256
  2088.    );
  2089.    A2W(szAnsiString, docRecord.m_szFormatName, sizeof(docRecord.m_szFormatName) / sizeof(WCHAR));
  2090.    OutlineApp_GetAppVersionNo(lpOutlineApp, docRecord.m_narrAppVersionNo);
  2091.    docRecord.m_fShowHeading = lpOutlineDoc->m_heading.m_fShow;
  2092. #if defined( OLE_SERVER )
  2093.    {
  2094.       // Store ServerDoc specific data
  2095.       LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc;
  2096.       docRecord.m_reserved1 = (DWORD)lpServerDoc->m_nNextRangeNo;
  2097.    }
  2098. #endif
  2099. #if defined( OLE_CNTR )
  2100.    {
  2101.       // Store ContainerDoc specific data
  2102.       LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOutlineDoc;
  2103.       docRecord.m_reserved2 = (DWORD)lpContainerDoc->m_nNextObjNo;
  2104.    }
  2105. #endif
  2106.    /* write OutlineDoc header record */
  2107.     //  Transform docRecord into docRecordOnDisk
  2108.     //  Compilers should handle aligment correctly
  2109.     OLESTRCPY(docRecordOnDisk.m_szFormatName, docRecord.m_szFormatName);
  2110.     docRecordOnDisk.m_narrAppVersionNo[0] = (short) docRecord.m_narrAppVersionNo[0];
  2111.     docRecordOnDisk.m_narrAppVersionNo[1] = (short) docRecord.m_narrAppVersionNo[1];
  2112.     docRecordOnDisk.m_fShowHeading = (USHORT) docRecord.m_fShowHeading;
  2113.     docRecordOnDisk.m_reserved1 = docRecord.m_reserved1;
  2114.     docRecordOnDisk.m_reserved2 = docRecord.m_reserved2;
  2115.     docRecordOnDisk.m_reserved3 = docRecord.m_reserved3;
  2116.     docRecordOnDisk.m_reserved4 = docRecord.m_reserved4;
  2117.    hrErr = lpLLStm->lpVtbl->Write(
  2118.          lpLLStm,
  2119.          (LPVOID)&docRecordOnDisk,
  2120.          sizeof(docRecordOnDisk),
  2121.          &nWritten
  2122.       );
  2123.    if (hrErr != NOERROR) {
  2124.       OleDbgOutHResult("Write OutlineDoc header returned", hrErr);
  2125.       goto error;
  2126.     }
  2127.    // Save LineList
  2128.    /* NOTE: A ContainerDoc keeps its storage open at all times. It is
  2129.    **    necessary to pass the current open storage (lpOleDoc->m_lpStg)
  2130.    **    to the LineList_SaveSelToStg method so that currently written data
  2131.    **    for any embeddings is also saved to the new destination
  2132.    **    storage. The data required by a contained object is both the
  2133.    **    ContainerLine information and the associated sub-storage that is
  2134.    **    written directly by the embedded object.
  2135.    */
  2136.    fStatus = LineList_SaveSelToStg(
  2137.       &lpOutlineDoc->m_LineList,
  2138.          lplrSel,
  2139.          uFormat,
  2140. #if defined( OLE_CNTR )
  2141.          lpOleDoc->m_lpStg,
  2142. #else
  2143.          NULL,
  2144. #endif
  2145.          lpDestStg,
  2146.          lpLLStm,
  2147.          fRemember
  2148.    );
  2149.    if (! fStatus) goto error;
  2150.    // Save associated NameTable
  2151.    fStatus = OutlineNameTable_SaveSelToStg(
  2152.          lpOutlineDoc->m_lpNameTable,
  2153.          lplrSel,
  2154.          uFormat,
  2155.          lpNTStm
  2156.    );
  2157.    if (! fStatus) goto error;
  2158.    OleStdRelease((LPUNKNOWN)lpLLStm);
  2159.    lpOutlineDoc->m_cfSaveFormat = uFormat;  // remember format used to save
  2160.    SetCursor(hPrevCursor);     // restore original cursor
  2161.    return TRUE;
  2162. error:
  2163.    if (lpLLStm)
  2164.       OleStdRelease((LPUNKNOWN)lpLLStm);
  2165.    SetCursor(hPrevCursor);     // restore original cursor
  2166.    return FALSE;
  2167. }
  2168. /* OutlineDoc_Print
  2169.  * ----------------
  2170.  *  Prints the contents of the list box in HIMETRIC mapping mode. Origin
  2171.  *  remains to be the upper left corner and the print proceeds down the
  2172.  *  page using a negative y-cordinate.
  2173.  *
  2174.  */
  2175. void OutlineDoc_Print(LPOUTLINEDOC lpOutlineDoc, HDC hDC)
  2176. {
  2177.    LPLINELIST lpLL = &lpOutlineDoc->m_LineList;
  2178.    LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  2179.    WORD    nIndex;
  2180.    WORD    nTotal;
  2181.    int     dy;
  2182.    BOOL    fError = FALSE;
  2183.    LPLINE  lpLine;
  2184.    RECT    rcLine;
  2185.    RECT    rcPix;
  2186.    RECT    rcHim;
  2187.    RECT    rcWindowOld;
  2188.    RECT    rcViewportOld;
  2189.    HFONT   hOldFont;
  2190.    DOCINFO di;         /* Document information for StartDoc function */
  2191.    char    szAnsiStr[256];
  2192.    /* Get dimension of page */
  2193.    rcPix.left = 0;
  2194.    rcPix.top = 0;
  2195.    rcPix.right = GetDeviceCaps(hDC, HORZRES);
  2196.    rcPix.bottom = GetDeviceCaps(hDC, VERTRES);
  2197.    SetDCToDrawInHimetricRect(hDC, (LPRECT)&rcPix, (LPRECT)&rcHim,
  2198.          (LPRECT)&rcWindowOld, (LPRECT)&rcViewportOld);
  2199.    // Set the default font size, and font face name
  2200.    hOldFont = SelectObject(hDC, lpOutlineApp->m_hStdFont);
  2201.    /* Get the lines in document */
  2202.    nIndex     = 0;
  2203.    nTotal  = LineList_GetCount(lpLL);
  2204.    /* Create the Cancel dialog */
  2205.    // REVIEW: should load dialog title from string resource file
  2206.    hWndPDlg = CreateDialog (
  2207.          lpOutlineApp->m_hInst,
  2208.          "Print",
  2209.          lpOutlineApp->m_hWndApp,
  2210.          (DLGPROC)PrintDlgProc
  2211.    );
  2212.    if(!hWndPDlg)
  2213.       goto getout;
  2214.    /* Allow the app. to inform GDI of the abort function to call */
  2215.    if(SetAbortProc(hDC, (ABORTPROC)AbortProc) < 0) {
  2216.       fError = TRUE;
  2217.       goto getout3;
  2218.    }
  2219.    /* Disable the main application window */
  2220.    EnableWindow (lpOutlineApp->m_hWndApp, FALSE);
  2221.    // initialize the rectangle for the first line
  2222.    rcLine.left = rcHim.left;
  2223.    rcLine.bottom = rcHim.top;
  2224.    /* Initialize the document */
  2225.    fCancelPrint = FALSE;
  2226.    di.cbSize = sizeof(DOCINFO);
  2227.    W2A (lpOutlineDoc->m_lpszDocTitle, szAnsiStr, 256);
  2228.    di.lpszDocName = szAnsiStr;
  2229.    di.lpszOutput = NULL;
  2230.    if(StartDoc(hDC, (DOCINFO FAR*)&di) <= 0) {
  2231.       fError = TRUE;
  2232.       OleDbgOut2("StartDoc errorn");
  2233.       goto getout5;
  2234.    }
  2235.    if(StartPage(hDC) <= 0) {       // start first page
  2236.       fError = TRUE;
  2237.       OleDbgOut2("StartPage errorn");
  2238.       goto getout2;
  2239.    }
  2240.    /* While more lines print out the text */
  2241.    while(nIndex < nTotal) {
  2242.       lpLine = LineList_GetLine(lpLL, nIndex);
  2243.       if (! lpLine)
  2244.          continue;
  2245.       dy = Line_GetHeightInHimetric(lpLine);
  2246.       /* Reached end of page. Tell the device driver to eject a page */
  2247.       if(rcLine.bottom - dy < rcHim.bottom) {
  2248.          if (EndPage(hDC) < 0) {
  2249.             fError=TRUE;
  2250.             OleDbgOut2("EndPage errorn");
  2251.             goto getout2;
  2252.          }
  2253.          // NOTE: Reset the Mapping mode of DC
  2254.          SetDCToDrawInHimetricRect(hDC, (LPRECT)&rcPix, (LPRECT)&rcHim,
  2255.                (LPRECT)&rcWindowOld, (LPRECT)&rcViewportOld);
  2256.          // Set the default font size, and font face name
  2257.          SelectObject(hDC, lpOutlineApp->m_hStdFont);
  2258.          if (StartPage(hDC) <= 0) {
  2259.             fError=TRUE;
  2260.             OleDbgOut2("StartPage errorn");
  2261.             goto getout2;
  2262.          }
  2263.          rcLine.bottom = rcHim.top;
  2264.       }
  2265.       rcLine.top = rcLine.bottom;
  2266.       rcLine.bottom -= dy;
  2267.       rcLine.right = rcLine.left + Line_GetWidthInHimetric(lpLine);
  2268.       /* Print the line */
  2269.       Line_Draw(lpLine, hDC, &rcLine, NULL, FALSE /*fHighlight*/);
  2270.       OleDbgOut2("a line is drawnn");
  2271.       /* Test and see if the Abort flag has been set. If yes, exit. */
  2272.       if (fCancelPrint)
  2273.          goto getout2;
  2274.       /* Move down the page */
  2275.       nIndex++;
  2276.    }
  2277.    {
  2278.       int nCode;
  2279.       /* Eject the last page. */
  2280.       if((nCode = EndPage(hDC)) < 0) {
  2281. #if defined( _DEBUG )
  2282.          char szBuf[255];
  2283.          wsprintf(szBuf, "EndPage error code is %dn", nCode);
  2284.          OleDbgOut2(szBuf);
  2285. #endif
  2286.          fError=TRUE;
  2287.          goto getout2;
  2288.       }
  2289.    }
  2290.    /* Complete the document. */
  2291.    if(EndDoc(hDC) < 0) {
  2292.       fError=TRUE;
  2293.       OleDbgOut2("EndDoc errorn");
  2294. getout2:
  2295.       /* Ran into a problem before NEWFRAME? Abort the document */
  2296.       AbortDoc(hDC);
  2297.    }
  2298. getout5:
  2299.    /* Re-enable main app. window */
  2300.    EnableWindow (lpOutlineApp->m_hWndApp, TRUE);
  2301. getout3:
  2302.    /* Close the cancel dialog */
  2303.    DestroyWindow (hWndPDlg);
  2304. getout:
  2305.    /* Error? make sure the user knows... */
  2306.    if(fError || CommDlgExtendedError())
  2307.       OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgPrint);
  2308.    SelectObject(hDC, hOldFont);
  2309. }
  2310. /* OutlineDoc_DialogHelp
  2311.  * ---------------------
  2312.  *
  2313.  *  Show help message for ole2ui dialogs.
  2314.  *
  2315.  * Parameters:
  2316.  *
  2317.  *   hDlg      HWND to the dialog the help message came from - use
  2318.  *             this in the call to WinHelp/MessageBox so that
  2319.  *             activation/focus goes back to the dialog, and not the
  2320.  *             main window.
  2321.  *
  2322.  *   wParam    ID of the dialog (so we know what type of dialog it is).
  2323.  */
  2324. void OutlineDoc_DialogHelp(HWND hDlg, WPARAM wDlgID)
  2325. {
  2326.    char szMessageBoxText[64];
  2327.    if (!IsWindow(hDlg))  // don't do anything if we've got a bogus hDlg.
  2328.     return;
  2329.    lstrcpy(szMessageBoxText, "Help Message for ");
  2330.    switch (wDlgID)
  2331.    {
  2332.    case IDD_CONVERT:
  2333.       lstrcat(szMessageBoxText, "Convert");
  2334.       break;
  2335.    case IDD_CHANGEICON:
  2336.       lstrcat(szMessageBoxText, "Change Icon");
  2337.       break;
  2338.    case IDD_INSERTOBJECT:
  2339.       lstrcat(szMessageBoxText, "Insert Object");
  2340.       break;
  2341.    case IDD_PASTESPECIAL:
  2342.       lstrcat(szMessageBoxText, "Paste Special");
  2343.       break;
  2344.    case IDD_EDITLINKS:
  2345.       lstrcat(szMessageBoxText, "Edit Links");
  2346.       break;
  2347.    case IDD_CHANGESOURCE:
  2348.       lstrcat(szMessageBoxText, "Change Source");
  2349.       break;
  2350.    case IDD_INSERTFILEBROWSE:
  2351.       lstrcat(szMessageBoxText, "Insert From File Browse");
  2352.       break;
  2353.    case IDD_CHANGEICONBROWSE:
  2354.       lstrcat(szMessageBoxText, "Change Icon Browse");
  2355.       break;
  2356.    default:
  2357.       lstrcat(szMessageBoxText, "Unknown");
  2358.       break;
  2359.    }
  2360.    lstrcat(szMessageBoxText, " Dialog.");
  2361.    // You'd probably really a call to WinHelp here.
  2362.    MessageBox(hDlg, szMessageBoxText, "Help", MB_OK);
  2363.    return;
  2364. }
  2365. /* OutlineDoc_SetCurrentZoomCommand
  2366.  * --------------------------------
  2367.  *
  2368.  *  Set current zoom level to be checked in the menu.
  2369.  *  Set the corresponding scalefactor for the document.
  2370.  */
  2371. void OutlineDoc_SetCurrentZoomCommand(
  2372.       LPOUTLINEDOC        lpOutlineDoc,
  2373.       UINT                uCurrentZoom
  2374. )
  2375. {
  2376.    SCALEFACTOR scale;
  2377.    if (!lpOutlineDoc)
  2378.       return;
  2379.    lpOutlineDoc->m_uCurrentZoom = uCurrentZoom;
  2380.    switch (uCurrentZoom) {
  2381. #if !defined( OLE_CNTR )
  2382.          case IDM_V_ZOOM_400:
  2383.             scale.dwSxN = (DWORD) 4;
  2384.             scale.dwSxD = (DWORD) 1;
  2385.             scale.dwSyN = (DWORD) 4;
  2386.             scale.dwSyD = (DWORD) 1;
  2387.             break;
  2388.          case IDM_V_ZOOM_300:
  2389.             scale.dwSxN = (DWORD) 3;
  2390.             scale.dwSxD = (DWORD) 1;
  2391.             scale.dwSyN = (DWORD) 3;
  2392.             scale.dwSyD = (DWORD) 1;
  2393.             break;
  2394.          case IDM_V_ZOOM_200:
  2395.             scale.dwSxN = (DWORD) 2;
  2396.             scale.dwSxD = (DWORD) 1;
  2397.             scale.dwSyN = (DWORD) 2;
  2398.             scale.dwSyD = (DWORD) 1;
  2399.             break;
  2400. #endif      // !OLE_CNTR
  2401.          case IDM_V_ZOOM_100:
  2402.             scale.dwSxN = (DWORD) 1;
  2403.             scale.dwSxD = (DWORD) 1;
  2404.             scale.dwSyN = (DWORD) 1;
  2405.             scale.dwSyD = (DWORD) 1;
  2406.             break;
  2407.          case IDM_V_ZOOM_75:
  2408.             scale.dwSxN = (DWORD) 3;
  2409.             scale.dwSxD = (DWORD) 4;
  2410.             scale.dwSyN = (DWORD) 3;
  2411.             scale.dwSyD = (DWORD) 4;
  2412.             break;
  2413.          case IDM_V_ZOOM_50:
  2414.             scale.dwSxN = (DWORD) 1;
  2415.             scale.dwSxD = (DWORD) 2;
  2416.             scale.dwSyN = (DWORD) 1;
  2417.             scale.dwSyD = (DWORD) 2;
  2418.             break;
  2419.          case IDM_V_ZOOM_25:
  2420.             scale.dwSxN = (DWORD) 1;
  2421.             scale.dwSxD = (DWORD) 4;
  2422.             scale.dwSyN = (DWORD) 1;
  2423.             scale.dwSyD = (DWORD) 4;
  2424.             break;
  2425.    }
  2426.    OutlineDoc_SetScaleFactor(lpOutlineDoc, (LPSCALEFACTOR)&scale, NULL);
  2427. }
  2428. /* OutlineDoc_GetCurrentZoomMenuCheck
  2429.  * ----------------------------------
  2430.  *
  2431.  *  Get current zoom level to be checked in the menu.
  2432.  */
  2433. UINT OutlineDoc_GetCurrentZoomMenuCheck(LPOUTLINEDOC lpOutlineDoc)
  2434. {
  2435.    return lpOutlineDoc->m_uCurrentZoom;
  2436. }
  2437. /* OutlineDoc_SetScaleFactor
  2438.  * -------------------------
  2439.  *
  2440.  *  Set the scale factor of the document which will affect the
  2441.  *      size of the document on the screen
  2442.  *
  2443.  * Parameters:
  2444.  *
  2445.  *   scale      structure containing x and y scales
  2446.  */
  2447. void OutlineDoc_SetScaleFactor(
  2448.       LPOUTLINEDOC        lpOutlineDoc,
  2449.       LPSCALEFACTOR       lpscale,
  2450.       LPRECT              lprcDoc
  2451. )
  2452. {
  2453.    LPLINELIST      lpLL = OutlineDoc_GetLineList(lpOutlineDoc);
  2454.    HWND            hWndLL = LineList_GetWindow(lpLL);
  2455.    if (!lpOutlineDoc || !lpscale)
  2456.       return;
  2457.    InvalidateRect(hWndLL, NULL, TRUE);
  2458.    lpOutlineDoc->m_scale = *lpscale;
  2459.    LineList_ReScale((LPLINELIST)&lpOutlineDoc->m_LineList, lpscale);
  2460. #if defined( USE_HEADING )
  2461.    Heading_ReScale((LPHEADING)&lpOutlineDoc->m_heading, lpscale);
  2462. #endif
  2463.    OutlineDoc_Resize(lpOutlineDoc, lprcDoc);
  2464. }
  2465. /* OutlineDoc_GetScaleFactor
  2466.  * -------------------------
  2467.  *
  2468.  *  Retrieve the scale factor of the document
  2469.  *
  2470.  * Parameters:
  2471.  *
  2472.  */
  2473. LPSCALEFACTOR OutlineDoc_GetScaleFactor(LPOUTLINEDOC lpOutlineDoc)
  2474. {
  2475.    if (!lpOutlineDoc)
  2476.       return NULL;
  2477.    return (LPSCALEFACTOR)&lpOutlineDoc->m_scale;
  2478. }
  2479. /* OutlineDoc_SetCurrentMarginCommand
  2480.  * ----------------------------------
  2481.  *
  2482.  *  Set current Margin level to be checked in the menu.
  2483.  */
  2484. void OutlineDoc_SetCurrentMarginCommand(
  2485.       LPOUTLINEDOC        lpOutlineDoc,
  2486.       UINT                uCurrentMargin
  2487. )
  2488. {
  2489.    if (!lpOutlineDoc)
  2490.       return;
  2491.    lpOutlineDoc->m_uCurrentMargin = uCurrentMargin;
  2492.    switch (uCurrentMargin) {
  2493.       case IDM_V_SETMARGIN_0:
  2494.          OutlineDoc_SetMargin(lpOutlineDoc, 0, 0);
  2495.          break;
  2496.       case IDM_V_SETMARGIN_1:
  2497.          OutlineDoc_SetMargin(lpOutlineDoc, 1000, 1000);
  2498.          break;
  2499.       case IDM_V_SETMARGIN_2:
  2500.          OutlineDoc_SetMargin(lpOutlineDoc, 2000, 2000);
  2501.          break;
  2502.       case IDM_V_SETMARGIN_3:
  2503.          OutlineDoc_SetMargin(lpOutlineDoc, 3000, 3000);
  2504.          break;
  2505.       case IDM_V_SETMARGIN_4:
  2506.          OutlineDoc_SetMargin(lpOutlineDoc, 4000, 4000);
  2507.          break;
  2508.    }
  2509. }
  2510. /* OutlineDoc_GetCurrentMarginMenuCheck
  2511.  * ------------------------------------
  2512.  *
  2513.  *  Get current Margin level to be checked in the menu.
  2514.  */
  2515. UINT OutlineDoc_GetCurrentMarginMenuCheck(LPOUTLINEDOC lpOutlineDoc)
  2516. {
  2517.    return lpOutlineDoc->m_uCurrentMargin;
  2518. }
  2519. /* OutlineDoc_SetMargin
  2520.  * --------------------
  2521.  *
  2522.  *  Set the left and right margin of the document
  2523.  *
  2524.  * Parameters:
  2525.  *      nLeftMargin  - left margin in Himetric values
  2526.  *      nRightMargin - right margin in Himetric values
  2527.  */
  2528. void OutlineDoc_SetMargin(LPOUTLINEDOC lpOutlineDoc, int nLeftMargin, int nRightMargin)
  2529. {
  2530.    LPLINELIST lpLL;
  2531.    int        nMaxWidthInHim;
  2532.    if (!lpOutlineDoc)
  2533.       return;
  2534.    lpOutlineDoc->m_nLeftMargin = nLeftMargin;
  2535.    lpOutlineDoc->m_nRightMargin = nRightMargin;
  2536.    lpLL = OutlineDoc_GetLineList(lpOutlineDoc);
  2537.    // Force recalculation of Horizontal extent
  2538.    nMaxWidthInHim = LineList_GetMaxLineWidthInHimetric(lpLL);
  2539.    LineList_SetMaxLineWidthInHimetric(lpLL, -nMaxWidthInHim);
  2540. #if defined( INPLACE_CNTR )
  2541.    ContainerDoc_UpdateInPlaceObjectRects((LPCONTAINERDOC)lpOutlineDoc, 0);
  2542. #endif
  2543.    OutlineDoc_ForceRedraw(lpOutlineDoc, TRUE);
  2544. }
  2545. /* OutlineDoc_GetMargin
  2546.  * --------------------
  2547.  *
  2548.  *  Get the left and right margin of the document
  2549.  *
  2550.  *  Parameters:
  2551.  *      nLeftMargin  - left margin in Himetric values
  2552.  *      nRightMargin - right margin in Himetric values
  2553.  *
  2554.  *  Returns:
  2555.  *      low order word  - left margin
  2556.  *      high order word - right margin
  2557.  */
  2558. LONG OutlineDoc_GetMargin(LPOUTLINEDOC lpOutlineDoc)
  2559. {
  2560.    if (!lpOutlineDoc)
  2561.       return 0;
  2562.    return MAKELONG(lpOutlineDoc->m_nLeftMargin, lpOutlineDoc->m_nRightMargin);
  2563. }
  2564. #if defined( USE_HEADING )
  2565. /* OutlineDoc_GetHeading
  2566.  * ---------------------
  2567.  *
  2568.  *      Get Heading Object in OutlineDoc
  2569.  */
  2570. LPHEADING OutlineDoc_GetHeading(LPOUTLINEDOC lpOutlineDoc)
  2571. {
  2572.    if (!lpOutlineDoc || lpOutlineDoc->m_fDataTransferDoc)
  2573.       return NULL;
  2574.    else
  2575.       return (LPHEADING)&lpOutlineDoc->m_heading;
  2576. }
  2577. /* OutlineDoc_ShowHeading
  2578.  * ----------------------
  2579.  *
  2580.  *  Show/Hide document row/column headings.
  2581.  */
  2582. void OutlineDoc_ShowHeading(LPOUTLINEDOC lpOutlineDoc, BOOL fShow)
  2583. {
  2584.    LPHEADING   lphead = OutlineDoc_GetHeading(lpOutlineDoc);
  2585. #if defined( INPLACE_SVR )
  2586.    LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOutlineDoc;
  2587. #endif
  2588.    if (! lphead)
  2589.       return;
  2590.    Heading_Show(lphead, fShow);
  2591. #if defined( INPLACE_SVR )
  2592.    if (lpServerDoc->m_fUIActive) {
  2593.       LPINPLACEDATA lpIPData = lpServerDoc->m_lpIPData;
  2594.       /* NOTE: our extents have NOT changed; only our the size of
  2595.       **    our object-frame adornments is changing. we can use the
  2596.       **    current PosRect and ClipRect and simply resize our
  2597.       **    windows WITHOUT informing our in-place container.
  2598.       */
  2599.       ServerDoc_ResizeInPlaceWindow(
  2600.             lpServerDoc,
  2601.             (LPRECT)&(lpIPData->rcPosRect),
  2602.             (LPRECT)&(lpIPData->rcClipRect)
  2603.       );
  2604.    } else
  2605. #else   // !INPLACE_SVR
  2606.    OutlineDoc_Resize(lpOutlineDoc, NULL);
  2607. #if defined( INPLACE_CNTR )
  2608.    ContainerDoc_UpdateInPlaceObjectRects((LPCONTAINERDOC)lpOutlineDoc, 0);
  2609. #endif  // INPLACE_CNTR
  2610. #endif  // INPLACE_SVR
  2611.    OutlineDoc_ForceRedraw(lpOutlineDoc, TRUE);
  2612. }
  2613. #endif  // USE_HEADING
  2614. /* AbortProc
  2615.  * ---------
  2616.  *  AborProc is called by GDI print code to check for user abort.
  2617.  */
  2618. BOOL FAR PASCAL EXPORT AbortProc (HDC hdc, WORD reserved)
  2619. {
  2620.    MSG msg;
  2621.    /* Allow other apps to run, or get abort messages */
  2622.    while(! fCancelPrint && PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
  2623.       if(!hWndPDlg || !IsDialogMessage (hWndPDlg, &msg)) {
  2624.          TranslateMessage (&msg);
  2625.          DispatchMessage  (&msg);
  2626.       }
  2627.    }
  2628.    return !fCancelPrint;
  2629. }
  2630. /* PrintDlgProc
  2631.  * ------------
  2632.  *  Dialog function for the print cancel dialog box.
  2633.  *
  2634.  *  RETURNS    : TRUE  - OK to abort/ not OK to abort
  2635.  *               FALSE - otherwise.
  2636.  */
  2637. BOOL FAR PASCAL EXPORT PrintDlgProc(
  2638.       HWND hwnd,
  2639.       WORD msg,
  2640.       WORD wParam,
  2641.       LONG lParam
  2642. )
  2643. {
  2644.    switch (msg) {
  2645.       case WM_COMMAND:
  2646.       /* abort printing if the only button gets hit */
  2647.          fCancelPrint = TRUE;
  2648.          return TRUE;
  2649.    }
  2650.    return FALSE;
  2651. }