Annotation of mstools/samples/ole/srvrdemo/doc.c, revision 1.1.1.3

1.1       root        1: /*
                      2:   OLE SERVER DEMO           
                      3:   Doc.c             
                      4:                                                                      
                      5:   This file contains document methods and various document-related support 
                      6:   functions.
                      7:                                                                      
                      8:   (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved   
                      9: */                                                                     
                     10:  
                     11: /* 
                     12:    Important Note:
                     13: 
                     14:    No method should ever dispatch a DDE message or allow a DDE message to
                     15:    be dispatched.
                     16:    Therefore, no method should ever enter a message dispatch loop.
                     17:    Also, a method should not show a dialog or message box, because the 
                     18:    processing of the dialog box messages will allow DDE messages to be
                     19:    dispatched.
                     20: */
                     21: 
                     22: 
                     23: 
                     24: #define SERVERONLY
                     25: #include <windows.h>
                     26: #include <ole.h>
                     27: 
                     28: #include "srvrdemo.h"
                     29: 
                     30: /* AssociateClient
                     31:  * ---------------
                     32:  *
                     33:  * Add a client to the list of clients associated with an object.
                     34:  *
                     35:  * This function is necessary only because ServerDemo does not create object
                     36:  * structures as they are requested, but rather has a fixed set of objects.
                     37:  * When DocGetObject is called with a NULL object name, the entire 
                     38:  * document is requested, but ServerDemo does not currently support making
                     39:  * the entire document an object, so DocGetObject returns one object.
                     40:  * That object now goes by two names: NULL and its real name.  Therefore
                     41:  * we need to keep track of both lpoleclient's that were passed to 
                     42:  * DocGetObject.  Ideally, DocGetObject should always create a new OBJ 
                     43:  * structure containing a pointer (or some reference) to the object's native
                     44:  * data and also containing one lpoleclient.
                     45:  *
                     46:  * LPOLECLIENT lpoleclient - the client to be associated with the object.
                     47:  * LPOBJ lpobj             - the object 
                     48:  *
                     49:  * RETURNS: TRUE if successful
                     50:  *          FALSE if out of memory
                     51:  *
                     52:  * CUSTOMIZATION: Server Demo specific
                     53:  *
                     54:  */
                     55: static BOOL AssociateClient (LPOLECLIENT lpoleclient, LPOBJ lpobj)
                     56: {
                     57:    INT i;
                     58:    for (i=0; i < clpoleclient; i++)
                     59:    {
                     60:       if (lpobj->lpoleclient[i]==lpoleclient)
                     61:       {
                     62:          return TRUE;
                     63:       }
                     64:       if (lpobj->lpoleclient[i]==NULL)
                     65:       {
                     66:          lpobj->lpoleclient[i]=lpoleclient;
                     67:          return TRUE;
                     68:       }
                     69:    }
                     70:    return FALSE;
                     71: }
                     72: 
                     73: 
                     74: 
                     75: /* CreateNewDoc
                     76:  * ------------
                     77:  *
                     78:  * If lhdoc == NULL then we must register the new document by calling
                     79:  * OleRegisterServerDoc, which will return a new handle which will be stored
                     80:  * in docMain.lhdoc.
                     81:  * Also if lhdoc==NULL then this document is being created at the request of
                     82:  * the user, not of the client library.
                     83:  *
                     84:  * LONG lhdoc      - Document handle
                     85:  * LPSTR lpszDoc   - Title of the new document
                     86:  * DOCTYPE doctype - What type of document is being created
                     87:  * 
                     88:  * RETURNS: TRUE if successful, FALSE otherwise.
                     89:  *
                     90:  * CUSTOMIZATION: Re-implement
                     91:  *
                     92:  */
                     93: BOOL CreateNewDoc (LONG lhdoc, LPSTR lpszDoc, DOCTYPE doctype)
                     94: {
                     95:    INT i;
                     96: 
                     97:    // Fill in the fields of the document structure.
1.1.1.3 ! root       98: 
        !            99:    docMain.doctype      = doctype;
        !           100:    docMain.oledoc.lpvtbl= &docvtbl;
        !           101: 
        !           102:    if (lhdoc == 0)
1.1       root      103:    {
                    104:       if (OLE_OK != OleRegisterServerDoc 
                    105:                      (srvrMain.lhsrvr, 
                    106:                       lpszDoc,
                    107:                       (LPOLESERVERDOC) &docMain, 
                    108:                       (LHSERVERDOC FAR *) &docMain.lhdoc))
                    109:          return FALSE;
                    110:    }
                    111:    else
                    112:       docMain.lhdoc = lhdoc;
                    113: 
                    114:    // Reset all the flags because no object numbers have been used.
                    115:    for (i=1; i <= cfObjNums; i++)
                    116:       docMain.rgfObjNums[i] = FALSE;
                    117: 
                    118:    fDocChanged = FALSE;
                    119: 
                    120:    SetTitle (lpszDoc, doctype == doctypeEmbedded);
                    121:    return TRUE;
                    122: }
                    123: 
                    124: 
                    125: 
                    126: /* DestroyDoc
                    127:  * ----------
                    128:  *
                    129:  * Free all memory that had been allocated for a document.
                    130:  *
                    131:  *
                    132:  * CUSTOMIZATION: Re-implement.  Your application will probably use some
                    133:  *                other method for enumerating all the objects in a document.
                    134:  *                ServerDemo enumerates the child windows, but if each object 
                    135:  *                does not have its own window, this will not work.
                    136:  *
                    137:  */
                    138: VOID DestroyDoc (VOID)
                    139: {
                    140:    HWND hwnd;
                    141:    HWND hwndNext;
                    142: 
                    143:    // Delete all object windows.  
                    144:    hwnd = SelectedObjectWindow();
                    145:    while (hwnd) 
                    146:    {
                    147:       hwndNext = GetWindow (hwnd, GW_HWNDNEXT);
                    148:       // Each object window frees its own memory upon receiving WM_DESTROY.
                    149:       DestroyWindow (hwnd);
                    150:       hwnd = hwndNext;
                    151:    } 
                    152: 
                    153:    if (docMain.aName)
                    154:    {
                    155:       GlobalDeleteAtom (docMain.aName);
1.1.1.3 ! root      156:       docMain.aName = '\0';
1.1       root      157:    }
                    158: 
                    159:    if (docMain.hpal)
                    160:       DeleteObject (docMain.hpal);
                    161: }
                    162: 
                    163: 
                    164: 
                    165: /* DocClose                DOCUMENT "Close" METHOD
                    166:  * --------
                    167:  *
                    168:  * The library calls this method to unconditionally close the document.
                    169:  *
                    170:  * LPOLESERVERDOC lpoledoc - The server document to close
                    171:  * 
                    172:  * RETURNS: Return value from RevokeDoc.
                    173:  *
                    174:  * CUSTOMIZATION: None
                    175:  *
                    176:  */
                    177: OLESTATUS  APIENTRY DocClose (LPOLESERVERDOC lpoledoc)
                    178: {
                    179:    return RevokeDoc();
                    180: }
                    181: 
                    182: 
                    183: 
                    184: /* DocExecute                DOCUMENT "Execute" METHOD
                    185:  * ----------
                    186:  *
                    187:  * This application does not support the execution of DDE execution commands.
                    188:  * 
                    189:  * LPOLESERVERDOC lpoledoc - The server document
                    190:  * HANDLE hCommands        - DDE execute commands
                    191:  * 
                    192:  * RETURNS: OLE_ERROR_COMMAND
                    193:  *
                    194:  * CUSTOMIZATION: Re-implement if your application supports the execution of
                    195:  *                DDE commands.
                    196:  *
                    197:  */
                    198: OLESTATUS  APIENTRY DocExecute (LPOLESERVERDOC lpoledoc, HANDLE hCommands)
                    199: {
                    200:    return OLE_ERROR_COMMAND;
                    201: }
                    202: 
                    203: 
                    204: 
                    205: /* DocGetObject                DOCUMENT "GetObject" METHOD
                    206:  * ------------
                    207:  *
                    208:  * The library uses this method to get an object's structure for the
                    209:  * client.  Memory needs to be allocated and initialized here for this.
                    210:  * A NULL string indicates that the client has an embedded object
                    211:  * which was started from Create, CreateFromTemplate, or Edit, but not Open.
                    212:  *
                    213:  * First see if the object name is NULL.  If so, you would ordinarily
                    214:  * return the entire document, but Server Demo returns the selected object.
                    215:  * If the object name is not NULL, then go through the list of objects, 
                    216:  * searching for one with that name.  Return an error if there is not one.
                    217:  *
                    218:  * LPOLESERVERDOC lpoledoc        - The server document
1.1.1.3 ! root      219:  * OLE_LPCSTR lpszObjectName           - The name of the object to get data for
1.1       root      220:  * LPOLEOBJECT FAR *lplpoleobject - The object's data is put here
                    221:  * LPOLECLIENT lpoleclient        - The client structure
                    222:  * 
                    223:  * RETURNS:        OLE_OK
                    224:  *                 OLE_ERROR_NAME if object not found
                    225:  *                 OLE_ERROR_MEMORY if no more memory to store lpoleclient
                    226:  *
                    227:  * CUSTOMIZATION: Re-implement.
                    228:  *                lpszObjectName == "" indicates that the whole document 
                    229:  *                should be the object returned.
                    230:  *
                    231:  */
                    232: OLESTATUS  APIENTRY DocGetObject
1.1.1.3 ! root      233:    (LPOLESERVERDOC lpoledoc, OLE_LPCSTR lpszObjectName, 
1.1       root      234:     LPOLEOBJECT FAR *lplpoleobject, LPOLECLIENT lpoleclient)
                    235: {
                    236:     HWND  hwnd;
                    237:     ATOM  aName;
                    238:     LPOBJ lpobj;
                    239: 
                    240: 
                    241:     if (lpszObjectName == NULL || lpszObjectName[0] == '\0')
                    242:     {   
                    243:         // Return a new object or the selected object.
                    244:         hwnd = SelectedObjectWindow();
                    245:         lpobj = hwnd ? HwndToLpobj (hwnd) : CreateNewObj (FALSE);
                    246:         *lplpoleobject = (LPOLEOBJECT) lpobj;
                    247:         // Associate client with object.
                    248:         if (!AssociateClient (lpoleclient, lpobj))
                    249:             return OLE_ERROR_MEMORY;
                    250:         return OLE_OK;
                    251:     }
                    252: 
                    253:     if (!(aName = GlobalFindAtom (lpszObjectName)))
                    254:         return OLE_ERROR_NAME;
                    255: 
                    256:     hwnd = SelectedObjectWindow();
                    257: 
                    258:     // Go through all the child windows and find the window whose name
                    259:     // matches the given object name.
                    260: 
                    261:     while (hwnd)
                    262:     {
                    263:          lpobj = HwndToLpobj (hwnd);
                    264: 
                    265:          if (aName == lpobj->aName)
                    266:          {
                    267:             // Return the object with the matching name.
                    268:             *lplpoleobject = (LPOLEOBJECT) lpobj;
                    269:             // Associate client with the object.
                    270:             if (!AssociateClient (lpoleclient, lpobj))
                    271:                return OLE_ERROR_MEMORY;
                    272:             return OLE_OK;
                    273:          }
                    274:          hwnd = GetWindow (hwnd, GW_HWNDNEXT);
                    275:     }
                    276: 
                    277:    if (((DOCPTR)lpoledoc)->doctype ==  doctypeEmbedded)
                    278:    {
                    279:       lpobj = CreateNewObj (FALSE);
                    280:       *lplpoleobject = (LPOLEOBJECT) lpobj;
                    281:       
                    282:       // Associate client with object.
                    283:       if (!AssociateClient (lpoleclient, lpobj))
                    284:          return OLE_ERROR_MEMORY;
                    285:       return OLE_OK;
                    286:     }
                    287: 
                    288:     // Object with name lpszObjName was not found.
                    289:     return OLE_ERROR_NAME;
                    290: }
                    291: 
                    292: /* DocRelease                DOCUMENT "Release" METHOD
                    293:  * ----------
                    294:  *
                    295:  * The library uses this method to notify the server that a revoked
                    296:  * document has finally finished all conversations, and can be 
                    297:  * destroyed.
                    298:  * It sets fWaitingForDocRelease to FALSE so a new document can be created
                    299:  * and the user can continue working.
                    300:  *
                    301:  * LPOLESERVERDOC lpoledoc        - The server document
                    302:  * 
                    303:  * RETURNS: OLE_OK
                    304:  *
                    305:  * CUSTOMIZATION: None
                    306:  *
                    307:  */
                    308: OLESTATUS  APIENTRY DocRelease (LPOLESERVERDOC lpoledoc)
                    309: {
                    310:    fWaitingForDocRelease = FALSE;
                    311:    // Free all memory that has been allocated for the document.
                    312:    DestroyDoc();
                    313: 
                    314:    return OLE_OK;
                    315: }
                    316: 
                    317: 
                    318: 
                    319: /* DocSave                DOCUMENT "Save" METHOD
                    320:  * -------
                    321:  *
                    322:  * Save document to a file.
                    323:  *
                    324:  * LPOLESERVERDOC lpoledoc - The document to save
                    325:  * 
                    326:  * RETURNS: OLE_OK
                    327:  *
                    328:  * CUSTOMIZATION: None
                    329:  *
                    330:  */
                    331: OLESTATUS  APIENTRY DocSave (LPOLESERVERDOC lpoledoc)
                    332: {
                    333:     if (docMain.doctype == doctypeFromFile)
                    334:     {
                    335:          // No "File Save As" dialog box will be brought up because the
                    336:          // file name is already known.
                    337:          return SaveDoc() ? OLE_OK : OLE_ERROR_GENERIC;
                    338:     }
                    339:     else
                    340:       return OLE_ERROR_GENERIC;
                    341: }
                    342: 
                    343: 
                    344: 
                    345: /* DocSetDocDimensions        DOCUMENT "SetDocDimensions" METHOD
                    346:  * -------------------
                    347:  *
                    348:  * The library calls this method to tell the server the bounds on
                    349:  * the target device for rendering the document.
                    350:  * A call to this method is ignored for linked objects because the size of
                    351:  * a linked document depends only on the source file.
                    352:  *
                    353:  * LPOLESERVERDOC lpoledoc - The server document
1.1.1.3 ! root      354:  * CONST LPRECT         lprect   - The target size in MM_HIMETRIC units
1.1       root      355:  * 
                    356:  * RETURNS: OLE_OK
                    357:  *
                    358:  * CUSTOMIZATION: Re-implement
                    359:  *                How an object is sized is application-specific. (Server Demo
                    360:  *                uses MoveWindow.)
                    361:  *                     
                    362:  */
                    363: OLESTATUS  APIENTRY DocSetDocDimensions 
1.1.1.3 ! root      364:    (LPOLESERVERDOC lpoledoc, OLE_CONST RECT FAR * lprect)
1.1       root      365: {
                    366:    if (docMain.doctype == doctypeEmbedded)
                    367:    {
                    368:       RECT rect = *lprect;
                    369:       
                    370:       // the units are in HIMETRIC
                    371:       rect.right   = rect.right - rect.left;
1.1.1.2   root      372:                // the following was bottom - top
                    373:                rect.bottom  = rect.top -  rect.bottom;
1.1       root      374:                
1.1.1.2   root      375:       HiMetricToDevice ( (LPPOINT) &rect.right );
1.1       root      376:       MoveWindow (SelectedObjectWindow(), 0, 0, 
                    377:                   rect.right + 2 * GetSystemMetrics(SM_CXFRAME), 
                    378:                   rect.bottom + 2 * GetSystemMetrics(SM_CYFRAME), 
                    379:                   TRUE);
                    380:       /* If for some reason your application needs to notify the client that
                    381:          the data has changed because DocSetDocDimensions has been called,
                    382:          then notify the client here.
                    383:          SendDocMsg (OLE_CHANGED);
                    384:       */
                    385:    }
                    386:    return OLE_OK;
                    387: }
                    388: 
                    389: 
                    390: 
                    391: /* DocSetHostNames        DOCUMENT "SetHostNames" METHOD
                    392:  * ---------------
                    393:  *
                    394:  * The library uses this method to set the name of the document
                    395:  * window.
                    396:  * All this function does is change the title bar text, although it could
                    397:  * do more if necesary. 
                    398:  * This function is only called for embedded objects; linked objects
                    399:  * use their filenames for the title bar text.
                    400:  *
                    401:  * LPOLESERVERDOC lpoledoc    - The server document
1.1.1.3 ! root      402:  * OLE_LPCSTR lpszClient           - The name of the client
        !           403:  * OLE_LPCSTR lpszDoc              - The client's name for the document
1.1       root      404:  * 
                    405:  * RETURNS:        OLE_OK
                    406:  * 
                    407:  * CUSTOMIZATION: None
                    408:  *
                    409:  */
                    410: OLESTATUS  APIENTRY DocSetHostNames 
1.1.1.3 ! root      411:    (LPOLESERVERDOC lpoledoc, OLE_LPCSTR lpszClient, OLE_LPCSTR lpszDoc)
1.1       root      412: {
1.1.1.3 ! root      413:    SetTitle ((LPSTR)lpszDoc, TRUE);
1.1       root      414:    lstrcpy ((LPSTR) szClient, lpszClient);
1.1.1.3 ! root      415:    lstrcpy ((LPSTR) szClientDoc, Abbrev((LPSTR)lpszDoc));
1.1       root      416:    UpdateFileMenu (IDM_UPDATE);   
                    417:    return OLE_OK;
                    418: }
                    419: 
                    420: 
                    421: 
                    422: /* DocSetColorScheme                DOCUMENT "SetColorScheme" METHOD
                    423:  * -----------------
                    424:  *
                    425:  * The client calls this method to suggest a color scheme (palette) for
                    426:  * the server to use.
                    427:  * In Server Demo the document's palette is never actually used because each 
                    428:  * object has its own palette.  See ObjSetColorScheme.
                    429:  *
                    430:  * LPOLESERVERDOC lpoledoc - The server document
1.1.1.3 ! root      431:  * CONST LOGPALETTE FAR * lppal    - Suggested palette
1.1       root      432:  *
                    433:  * RETURNS: OLE_ERROR_PALETTE if CreatePalette fails, 
                    434:  *          OLE_OK otherwise
                    435:  *
                    436:  * 
                    437:  * CUSTOMIZATION: If your application supports color schemes, then this 
                    438:  *                function is a good example of how to create and store
                    439:  *                a palette.
                    440:  */
                    441: OLESTATUS  APIENTRY DocSetColorScheme 
1.1.1.3 ! root      442:    (LPOLESERVERDOC lpoledoc, OLE_CONST LOGPALETTE FAR * lppal)
1.1       root      443: {
                    444:    HPALETTE hpal = CreatePalette (lppal);
                    445: 
                    446:    if (hpal==NULL)
                    447:       return OLE_ERROR_PALETTE;
                    448: 
                    449:    if (docMain.hpal) 
                    450:    {
                    451:       // Delete old palette
                    452:       DeleteObject (docMain.hpal);
                    453:    }
                    454:    // Store handle to new palette
                    455:    docMain.hpal = hpal;
                    456:    return OLE_OK;
                    457: }
                    458: 
                    459: 
                    460: 
                    461: /* RevokeDoc
                    462:  * ---------
                    463:  *
                    464:  * Call OleRevokeServerDoc.
                    465:  * If the return value is OLE_WAIT_FOR_BUSY, then set fWaitingForDocRelease
                    466:  * and enter a message-dispatch loop until fWaitingForDocRelease is reset.
                    467:  * As long as fWaitingForDocRelease is set, the user interface will be 
                    468:  * disabled so that the user will not be able to manipulate the document.
                    469:  * When the DocRelease method is called, it will reset fWaitingForDocRelease,
                    470:  * allowing RevokeDoc to free the document's memory and return.
                    471:  *
                    472:  * This is essentially a way to make an asynchronous operation synchronous.
                    473:  * We need to wait until the old document is revoked before we can delete
                    474:  * its data and create a new one.
                    475:  *
                    476:  * Note that we cannot call RevokeDoc from a method because it is illegal to
                    477:  * enter a message-dispatch loop within a method.
                    478:  *
                    479:  * RETURNS: The return value of OleRevokeServerDoc.
                    480:  *
                    481:  * CUSTOMIZATION: lhdoc may need to be passed in as a parameter if your 
                    482:  *                application does not have a global variable corresponding 
                    483:  *                to docMain.
                    484:  * 
                    485:  */
                    486: OLESTATUS RevokeDoc (VOID)
                    487: {
                    488:    OLESTATUS olestatus;
                    489: 
                    490:    if ((olestatus = OleRevokeServerDoc(docMain.lhdoc)) > OLE_WAIT_FOR_RELEASE)
                    491:       DestroyDoc();
                    492: 
1.1.1.3 ! root      493:    docMain.lhdoc = 0; // A NULL handle indicates that the document 
1.1       root      494:                          // has been revoked or is being revoked.
                    495:    return olestatus;
                    496: 
                    497: }
                    498: 
                    499: 
                    500: 
                    501: /* SaveChangesOption
                    502:  * -----------------
                    503:  *
                    504:  * Give the user the opportunity to save changes to the current document
                    505:  * before continuing.
                    506:  *
                    507:  * BOOL *pfUpdateLater - Will be set to TRUE if the client does not accept
                    508:  *                       the update and needs to be updated when the document
                    509:  *                       is closed.  In that case, OLE_CLOSED will be sent.
                    510:  *
                    511:  * RETURNS: IDYES, IDNO, or IDCANCEL
                    512:  *
                    513:  * CUSTOMIZATION: None
                    514:  *
                    515:  */
                    516: INT SaveChangesOption (BOOL *pfUpdateLater)
                    517: {
                    518:    INT  nReply;
                    519:    CHAR szBuf[cchFilenameMax];
                    520:    
                    521:    *pfUpdateLater = FALSE;
                    522:    
                    523:    if (fDocChanged)
                    524:    {
                    525:        CHAR szTmp[cchFilenameMax];
                    526:        
                    527:        if (docMain.aName) 
                    528:            GlobalGetAtomName (docMain.aName, szTmp, cchFilenameMax);
                    529:        else 
1.1.1.3 ! root      530:            szTmp[0] = '\0';
1.1       root      531: 
                    532:        if (docMain.doctype == doctypeEmbedded)
                    533:            wsprintf (szBuf, "The object has been changed.\n\nUpdate %s before closing the object?", Abbrev (szTmp));        
                    534:        else
                    535:            lstrcpy (szBuf, (LPSTR) "Save changes?");         
                    536:      
                    537:        nReply = MessageBox (hwndMain, szBuf, szAppName, 
                    538:                       MB_ICONEXCLAMATION | MB_YESNOCANCEL);
                    539:                   
                    540:        switch (nReply)
                    541:        {
                    542:           case IDYES:
                    543:               if (docMain.doctype != doctypeEmbedded)
                    544:                   SaveDoc();
                    545:               else
                    546:                   switch (OleSavedServerDoc (docMain.lhdoc))
                    547:                   {
                    548:                       case OLE_ERROR_CANT_UPDATE_CLIENT:
                    549:                           *pfUpdateLater = TRUE;
                    550:                           break;
                    551:                       case OLE_OK:
                    552:                           break;
                    553:                       default:
                    554:                           ErrorBox ("Fatal Error: Cannot update.");
                    555:                   }                                      
                    556:               return IDYES;
                    557:           case IDNO:
                    558:               return IDNO;
                    559:          case IDCANCEL:
                    560:               return IDCANCEL;
                    561:        }
                    562:    }
                    563:    return TRUE;
                    564: }
                    565: 
                    566: 
                    567: 
                    568: /* SendDocMsg
                    569:  * ----------
                    570:  *
                    571:  * This function sends messages to all the objects in a document when
                    572:  * the document has changed.
                    573:  *
                    574:  * WORD wMessage - The message to send
                    575:  * 
                    576:  * CUSTOMIZATION: The means of enumerating all the objects in a document
                    577:  *                is application specific.
                    578:  */
                    579: VOID SendDocMsg (WORD wMessage)
                    580: {
                    581:     HWND    hwnd;
                    582: 
                    583:     // Get handle to first object window.
                    584:     hwnd = SelectedObjectWindow();
                    585: 
                    586:     // Send message to all object windows.
                    587:     while (hwnd)
                    588:     {
                    589:         SendObjMsg (HwndToLpobj(hwnd), wMessage);
                    590:         hwnd = GetWindow (hwnd, GW_HWNDNEXT);
                    591:     }
                    592: }
                    593: 
                    594: 

unix.superglobalmegacorp.com

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