Annotation of mstools/ole20/samples/outline/outldoc.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.