home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic 4 Unleashed / Visual_Basic_4_Unleashed_SAMS_Publishing_1995.iso / tedevkit / ter_ole1.h < prev    next >
Encoding:
Text File  |  1995-08-22  |  29.4 KB  |  722 lines

  1. /*==============================================================================
  2.    TER_OLE.C
  3.    TER Object Linking and Embedding functions
  4.  
  5.    TER Editor Developer's Kit    
  6.    Sub Systems, Inc.
  7.    Software License Agreement  (1994)              
  8.    ----------------------------------
  9.    This license agreement allows the purchaser the right to modify the 
  10.    source code to incorporate in an application larger than the editor itself.
  11.    The target application must not be a programmer's utility 'like' a text editor.
  12.    Sub Systems, Inc. reserves the right to prosecute anybody found to be 
  13.    making illegal copies of the executable software or compiling the source
  14.    code for the purpose of selling there after.
  15. ===============================================================================*/
  16.  
  17. /*******************************************************************************
  18.     InitOle:
  19.     Create the OLE client structure
  20. *******************************************************************************/
  21. BOOL InitOle(PTERWND w)
  22. {
  23.     OLESTATUS status;
  24.     BYTE DocName[129];
  25.     
  26.  
  27.     // initialize variables
  28.     TerClientVtbl.CallBack=NULL;// Ole client callback function
  29.     OleStreamVtbl.Get=NULL;     // Ole stream get callback function
  30.     OleStreamVtbl.Put=NULL;     // Ole stream put callback function
  31.     lhDoc=0;                    // document handle
  32.  
  33.     // Create the client structure
  34.     if ( NULL==(TerClientVtbl.CallBack=(CLIENT_CALLBACK) MakeProcInstance((FARPROC)ClientCallback,hTerInst))
  35.       || NULL==(OleStreamVtbl.Get=(OLESTREAM_GET)        MakeProcInstance((FARPROC)TerOleGet,hTerInst))
  36.       || NULL==(OleStreamVtbl.Put=(OLESTREAM_PUT)        MakeProcInstance((FARPROC)TerOlePut,hTerInst)) ){
  37.        MessageBox(hTerWnd,"Can not create ole callback function instances!",NULL,MB_OK);
  38.        return FALSE;
  39.     }
  40.  
  41.     TerClient.client.lpvtbl=&TerClientVtbl;
  42.     TerClient.TerData=w;                    // store the handle of the data area
  43.     
  44.     OleStream.stream.lpstbl=&OleStreamVtbl;
  45.     OleStream.TerData=w;
  46.  
  47.     // register the document
  48.     wsprintf(DocName,"%s (%x)",TerArg.file,(UINT)hTerWnd);
  49.     if (OLE_OK!=(status=OleRegisterClientDoc(TER_CLASS,DocName,0,&lhDoc))) return PrintOleErrorMessage(w,"Document Registration Error",status);
  50.  
  51.     // enable drag/drop
  52.     DragAcceptFiles(hTerWnd,TRUE);
  53.  
  54.     return TRUE;
  55. }
  56.  
  57. /*******************************************************************************
  58.     ExitOle:
  59.     Exit ole logic. Called by CloseTer
  60. *******************************************************************************/
  61. BOOL ExitOle(PTERWND w)
  62. {
  63.     DragAcceptFiles(hTerWnd,FALSE);
  64.  
  65.     #if !defined(WIN32) 
  66.        if (TerClientVtbl.CallBack) FreeProcInstance((FARPROC)TerClientVtbl.CallBack);
  67.        if (OleStreamVtbl.Get)      FreeProcInstance((FARPROC)OleStreamVtbl.Get);
  68.        if (OleStreamVtbl.Put)      FreeProcInstance((FARPROC)OleStreamVtbl.Put);
  69.     #endif
  70.     if (lhDoc) OleRevokeClientDoc(lhDoc);
  71.  
  72.     return TRUE;
  73. }
  74.  
  75. /*******************************************************************************
  76.     ClientCallback:
  77.     The OLE client callback function.
  78. *******************************************************************************/
  79. int CALLBACK _export ClientCallback(LPOLECLIENT client, OLE_NOTIFICATION notice, LPOLEOBJECT pObject)
  80. {
  81.     PTERWND w;
  82.     OLESTATUS status;
  83.     MSG msg;
  84.     int i,OleItem;
  85.  
  86.     w=((struct StrClient far *)client)->TerData;   // retrieve the TER window data pointer
  87.  
  88.     if (notice==OLE_RELEASE) {
  89.        WaitForOle--;                               // wait is over
  90.        if (pObject) {
  91.           OleReleaseMethod=OleQueryReleaseMethod(pObject);
  92.           if (OLE_OK!=(status=OleQueryReleaseError(pObject))) PrintOleErrorMessage(w,"Object Release Error",status);
  93.        }
  94.        return TRUE;
  95.     }
  96.     if (notice!=OLE_SAVED && notice!=OLE_CHANGED && notice!=OLE_CLOSED) return TRUE;
  97.     if (pObject==NULL) return TRUE;
  98.  
  99.      // get the item number
  100.     OleItem=-1;
  101.     for (i=0;i<TotalFonts;i++) {
  102.       if (!TerFont[i].InUse 
  103.        || !(TerFont[i].style&PICT) 
  104.        || TerFont[i].ObjectType==OBJ_NONE) continue;
  105.        if (TerFont[i].pObject==pObject) {
  106.           OleItem=i;
  107.           break;
  108.        }
  109.     }
  110.     if (OleItem<0) return TRUE;
  111.  
  112.     if (notice==OLE_SAVED)   TerFont[OleItem].OleNotice|=OLENOT_SAVED;
  113.     if (notice==OLE_CHANGED) TerFont[OleItem].OleNotice|=OLENOT_CHANGED;
  114.     if (notice==OLE_CLOSED)  TerFont[OleItem].OleNotice|=OLENOT_CLOSED;
  115.  
  116.     // Post a message to the TER window to activate idle time activity
  117.     if (!PeekMessage(&msg,hTerWnd,0,0,PM_NOREMOVE|PM_NOYIELD)) PostMessage(hTerWnd,TER_IDLE,0,0L);
  118.  
  119.     return TRUE;
  120. }
  121.  
  122. /*******************************************************************************
  123.     OlePostProcessing:
  124.     This function is called by the TER window main loop to process any
  125.     pending messages from the ClientCallback function.
  126. *******************************************************************************/
  127. OlePostProcessing(PTERWND w)
  128. {
  129.     OLESTATUS status;
  130.     HANDLE hData;
  131.     struct StrFont font;
  132.     int i,OleItem;
  133.     BOOL repaint=FALSE;
  134.  
  135.     // examine each object for pending OLE notification
  136.     for (OleItem=0;OleItem<TotalFonts;OleItem++) {
  137.        if ( !TerFont[OleItem].InUse 
  138.          || !(TerFont[OleItem].style&PICT) 
  139.          || TerFont[OleItem].ObjectType==OBJ_NONE
  140.          || TerFont[OleItem].OleNotice==0) {
  141.           continue;
  142.        }
  143.  
  144.        // process OLE_SAVED notice
  145.        if (TerFont[OleItem].OleNotice&(OLENOT_SAVED|OLENOT_CHANGED)) {
  146.           // update the presentation data
  147.           status=OleGetData(TerFont[OleItem].pObject,CF_METAFILEPICT,&hData);
  148.           if (status!=OLE_OK && status!=OLE_WARN_DELETE_DATA) {
  149.              PrintOleErrorMessage(w,"Error getting ole data (OlePostProcessing)",status);
  150.              goto END;
  151.           }
  152.  
  153.           font=TerFont[OleItem];                       // make a copy of the exiting font structure
  154.           InitTerObject(w,OleItem);                    // freeup this slot
  155.           if (TerCreateMetafile(w,(HGLOBAL)hData,OleItem)<0) {
  156.              TerFont[OleItem]=font;                    // restore the previous structure
  157.              goto END;
  158.           }
  159.           if (status==OLE_WARN_DELETE_DATA)  DeleteMetaFile((HMETAFILE)hData); // delete metafile 
  160.  
  161.           // Apply the previous flags
  162.           TerFont[OleItem].ObjectType=font.ObjectType;
  163.           TerFont[OleItem].pObject=font.pObject;
  164.           TerFont[OleItem].OleNotice=font.OleNotice;
  165.  
  166.           // Apply the previous size
  167.           if (TerFont[OleItem].ObjectType==OBJ_EMBED_INSERT) {  // item being inserted
  168.               TerFont[OleItem].ObjectType=OBJ_EMBED;
  169.               TerInsertObjectId(hTerWnd,OleItem,TRUE);   // this is a new object to be inserted
  170.           }
  171.           else {
  172.               TerFont[OleItem].PictHeight=font.PictHeight;
  173.               TerFont[OleItem].PictWidth=font.PictWidth;
  174.               TerFont[OleItem].height=font.height;
  175.               for (i=0;i<256;i++) TerFont[OleItem].CharWidth[i]=font.CharWidth[i];
  176.               XlateSizeForPrt(w,OleItem);          // convert size to printer resolution
  177.               
  178.               if (font.hMeta) DeleteMetaFile(font.hMeta); // delete the previous metafile
  179.           }
  180.           
  181.           TerArg.modified++;                       // file modified
  182.        }
  183.        if (TerFont[OleItem].OleNotice&OLENOT_CLOSED) {
  184.           if (TerFont[OleItem].ObjectType==OBJ_EMBED_TEMP) {   // delete the temporary object
  185.              status=OleDelete(TerFont[OleItem].pObject);
  186.              if (status==OLE_WAIT_FOR_RELEASE) TerOleWaitForRelease(w,TerFont[OleItem].pObject);
  187.              TerFont[OleItem].ObjectType=OBJ_NONE;
  188.              TerFont[OleItem].pObject=NULL; 
  189.           }
  190.           else if (TerFont[OleItem].ObjectType==OBJ_EMBED_INSERT) { // item not inserted
  191.              TerFont[OleItem].InUse=FALSE;
  192.           }
  193.        }
  194.  
  195.        repaint=TRUE;
  196.  
  197.        END:
  198.        TerFont[OleItem].OleNotice=0;
  199.     }
  200.  
  201.     if (repaint) {
  202.        //** reset the text map as the contents of the picture has changed
  203.        for (i=0;i<TotalSegments;i++) DeleteTextSeg(w,i);
  204.        TotalSegments=0;
  205.        PaintTer(w);
  206.     }
  207.  
  208.     return TRUE;
  209. }
  210.  
  211. /*******************************************************************************
  212.     TerPasteSpecial:
  213.     Accept a string from the user along with other parameters and search for 
  214.     the first instances of the string.
  215. *******************************************************************************/
  216. TerPasteSpecial(PTERWND w)
  217. {
  218.     int index,len,i;
  219.     int select;
  220.     UINT ClipFormat,PasteFormat;
  221.     long BuffSize;
  222.     BYTE class[MAX_WIDTH+1],doc[MAX_WIDTH+1],item[MAX_WIDTH+1],PasteFmts[MAX_PASTE_FORMATS];
  223.     BOOL PasteLink=FALSE;
  224.  
  225.     if (WaitForOle) return TRUE;                   // ole operation in progress
  226.     if (FontsReleased) RecreateFonts(w,hTerDC);    // recreate fonts
  227.  
  228.     // Build the source description string
  229.     ClipFormat=GetOleClipItem(w,class,doc,item);
  230.  
  231.     if (ClipFormat>0) {
  232.        // get the class name
  233.        BuffSize=sizeof(TempString);
  234.        RegQueryValue(HKEY_CLASSES_ROOT,class,TempString,&BuffSize);
  235.  
  236.        // Build the item string
  237.        len=lstrlen(doc);
  238.        for (i=len;i>0;i--) if (doc[i-1]=='\\') break;
  239.        lstrcpy(TempString1,&(doc[i]));
  240.        if (lstrlen(TempString1)>0) lstrcat(TempString1," ");
  241.        lstrcat(TempString1,item);
  242.     }
  243.     else {
  244.        lstrcpy(TempString,"Unknown");
  245.        lstrcpy(TempString1,"");
  246.     }
  247.  
  248.     // build the datatype table
  249.     for (i=0;i<MAX_PASTE_FORMATS;i++) PasteFmts[i]=FALSE;    // list of available formats
  250.     if (IsClipboardFormatAvailable(OwnerLinkClipFormat)) PasteFmts[PASTE_OBJECT]=TRUE;
  251.     if (IsClipboardFormatAvailable(CF_METAFILEPICT))     PasteFmts[PASTE_PICT]=TRUE;
  252.     if (IsClipboardFormatAvailable(CF_BITMAP))           PasteFmts[PASTE_BM]=TRUE;
  253.     if (IsClipboardFormatAvailable(CF_DIB))              PasteFmts[PASTE_DIB]=TRUE;
  254.     if (IsClipboardFormatAvailable(RtfClipFormat))       PasteFmts[PASTE_RTF]=TRUE;
  255.     if (IsClipboardFormatAvailable(CF_TEXT))             PasteFmts[PASTE_TEXT]=TRUE;
  256.  
  257.     // check if atleast one format available
  258.     for (i=0;i<MAX_PASTE_FORMATS;i++) if (PasteFmts[i]) break;
  259.     if (i==MAX_PASTE_FORMATS) return TRUE;             // no formats available
  260.  
  261.     index=CallDialogBox(w,"PasteSpecialParam",PasteSpecialParam,(long)(LPBYTE)PasteFmts);
  262.     if (index<0) return TRUE;                          // operation cancelled
  263.     
  264.     // extract the selected clipboard format
  265.     if (index>=MAX_PASTE_FORMATS) {                    // Is object linking selected
  266.        index-=MAX_PASTE_FORMATS;
  267.        PasteLink=TRUE;
  268.     }
  269.     for (i=0;i<MAX_PASTE_FORMATS;i++) {
  270.        if (PasteFmts[i]) index--;
  271.        if (index<0) break;
  272.     }
  273.     select=i;                                           // selected format
  274.  
  275.     // get the paste format
  276.     if      (select==PASTE_TEXT)   PasteFormat=CF_TEXT;
  277.     else if (select==PASTE_RTF)    PasteFormat=RtfClipFormat;
  278.     else if (select==PASTE_PICT)   PasteFormat=CF_METAFILEPICT;
  279.     else if (select==PASTE_DIB)    PasteFormat=CF_DIB;
  280.     else if (select==PASTE_BM)     PasteFormat=CF_BITMAP;
  281.     else                           PasteFormat=NativeClipFormat;
  282.     
  283.     // Retrieve the text formats from the clipboard
  284.     if (select==PASTE_RTF || select==PASTE_TEXT)  return CopyFromClipboard(w,PasteFormat);
  285.  
  286.     // Process the ole objects
  287.     if (select==PASTE_OBJECT)  return TerOleFromClipboard(w,PasteFormat,PasteLink);
  288.  
  289.     // Process the non-ole picture formats
  290.     if (select==PASTE_PICT || select==PASTE_DIB || select==PASTE_BM)  return TerPastePicture(hTerWnd,PasteFormat,NULL,0,ALIGN_BOT,TRUE);
  291.  
  292.     return TRUE;
  293. }
  294.  
  295. /*******************************************************************************
  296.     TerOleFromClipboard:
  297.     Embed an OLE object from clipboard.
  298. *******************************************************************************/
  299. TerOleFromClipboard(PTERWND w, UINT format,BOOL PasteLink) 
  300. {
  301.     int pict;
  302.     BYTE ObjectName[20];
  303.     OLESTATUS status;
  304.     HANDLE hData;
  305.     LPOLEOBJECT pObject;
  306.  
  307.     // Erase any previously highlighted text
  308.     if (HilightType==HILIGHT_CHAR) BlockDelete(w);
  309.  
  310.     if ((pict=FindOpenSlot(w))==-1) return FALSE;  // find an empty slot
  311.     wsprintf(ObjectName,"Ter Object# %d",pict);
  312.  
  313.     // create from clipboard
  314.     if (!OpenClipboard(hTerWnd)) return FALSE;
  315.     if (PasteLink) status=OleCreateLinkFromClip("StdFileEditing",&(TerClient.client),lhDoc,ObjectName,&pObject,olerender_format,CF_METAFILEPICT);
  316.     else           status=OleCreateFromClip("StdFileEditing",&(TerClient.client),lhDoc,ObjectName,&pObject,olerender_format,CF_METAFILEPICT);
  317.     if (status==OLE_ERROR_PROTOCOL) {
  318.        if (PasteLink) status=OleCreateLinkFromClip("Static",&(TerClient.client),lhDoc,ObjectName,&pObject,olerender_format,CF_METAFILEPICT);
  319.        else           status=OleCreateFromClip("Static",&(TerClient.client),lhDoc,ObjectName,&pObject,olerender_format,CF_METAFILEPICT);
  320.     }
  321.     CloseClipboard();
  322.  
  323.     if (status!=OLE_OK && status!=OLE_WAIT_FOR_RELEASE) return PrintOleErrorMessage(w,"OleCreateFromClip",status);
  324.     if (status==OLE_WAIT_FOR_RELEASE) TerOleWaitForRelease(w,pObject);
  325.  
  326.     // Get the metafile data
  327.     status=OleGetData(pObject,CF_METAFILEPICT,&hData);
  328.     if (status!=OLE_OK && status!=OLE_WARN_DELETE_DATA) return PrintOleErrorMessage(w,"Error getting ole data (TerOleCreateFromClipboard)",status);
  329.  
  330.     pict=TerCreateMetafile(w,(HGLOBAL)hData,-1);    // extract metafile
  331.     if (status==OLE_WARN_DELETE_DATA)  DeleteMetaFile((HMETAFILE)hData); // delete metafile 
  332.     if (PasteLink) TerFont[pict].ObjectType=OBJ_LINK;
  333.     else           TerFont[pict].ObjectType=OBJ_EMBED;
  334.  
  335.     TerFont[pict].pObject=pObject;
  336.  
  337.     TerInsertObjectId(hTerWnd,pict,TRUE);   // insert this object into text
  338.     FitPictureInFrame(w,CurLine,FALSE);
  339.     
  340.     return TRUE;
  341. }
  342.  
  343. /******************************************************************************
  344.      TerInsertObject:
  345.      Insert a new ole object. This function activates the OLE server.  the
  346.      second part of this function (TerInsertObjectId) is called from the
  347.      ole post processing function to actually insert the object into the
  348.      text.
  349. ******************************************************************************/
  350. BOOL TerInsertObject(PTERWND w)
  351. {
  352.     int SubKey;
  353.     long BuffSize;
  354.     BYTE class[100];
  355.     int pict;
  356.     BYTE ObjectName[20];
  357.     OLESTATUS status;
  358.  
  359.  
  360.     if ((SubKey=CallDialogBox(w,"InsertObjectParam",InsertObjectParam,0L))<0) return TRUE;
  361.     
  362.     // get the class name
  363.     RegEnumKey(HKEY_CLASSES_ROOT,SubKey,class,sizeof(class)-1);
  364.     BuffSize=sizeof(TempString)-1;
  365.     RegQueryValue(HKEY_CLASSES_ROOT,class,TempString,&BuffSize);
  366.  
  367.     // create the object
  368.     if ((pict=FindOpenSlot(w))==-1) return FALSE;  // find an empty slot to make the object name
  369.     TerFont[pict].InUse=TRUE;
  370.     TerFont[pict].ObjectType=OBJ_EMBED_INSERT;  // object to be inserted
  371.     TerFont[pict].style=PICT;
  372.     TerFont[pict].PictType=PICT_METAFILE;
  373.     TerFont[pict].hMeta=0;
  374.  
  375.     wsprintf(ObjectName,"Ter Object# %d",pict);
  376.  
  377.     status=OleCreate("StdFileEditing",&(TerClient.client),class,lhDoc,ObjectName,&(TerFont[pict].pObject),olerender_format,CF_METAFILEPICT);
  378.     if (status==OLE_ERROR_PROTOCOL) {
  379.        status=OleCreate("Static",&(TerClient.client),class,lhDoc,ObjectName,&(TerFont[pict].pObject),olerender_format,CF_METAFILEPICT);
  380.     }
  381.  
  382.     if (status!=OLE_OK && status!=OLE_WAIT_FOR_RELEASE) {
  383.         TerFont[pict].InUse=FALSE;
  384.         return PrintOleErrorMessage(w,"TerInsertObject",status);
  385.     }
  386.     if (status==OLE_WAIT_FOR_RELEASE) TerOleWaitForRelease(w,TerFont[pict].pObject);
  387.  
  388.     return TRUE;
  389. }
  390.  
  391. /******************************************************************************
  392.      TerInsertDragObject:
  393.      Insert an ole object inserted using drag/drop.  Only the first file
  394.      in the drag/drop buffer is processed.
  395. ******************************************************************************/
  396. BOOL TerInsertDragObject(PTERWND w,HDROP hDrop)
  397. {
  398.     int pict;
  399.     BYTE ObjectName[20];
  400.     OLESTATUS status;
  401.     POINT pt;
  402.     DWORD lParam;
  403.     BYTE file[129];
  404.  
  405.     // Extract the dropped file
  406.     if (!DragQueryPoint(hDrop,&pt)) return TRUE;
  407.     DragQueryFile(hDrop,0,file,sizeof(file)-1);  // get the first file 
  408.     DragFinish(hDrop);             // release the drag buffer
  409.  
  410.     // get cursor location at the drag point
  411.     lParam=pt.y;
  412.     lParam=lParam<<16;             // high word
  413.     lParam=lParam+pt.x;
  414.     TerMousePos(w,lParam);
  415.     CurLine=MouseLine;
  416.     CurCol=MouseCol;
  417.  
  418.     // create the object
  419.     if ((pict=FindOpenSlot(w))==-1) return FALSE;  // find an empty slot to make the object name
  420.     TerFont[pict].InUse=TRUE;
  421.     TerFont[pict].ObjectType=OBJ_EMBED_INSERT;  // object to be inserted
  422.     TerFont[pict].style=PICT;
  423.     TerFont[pict].PictType=PICT_METAFILE;
  424.     TerFont[pict].hMeta=0;
  425.  
  426.     wsprintf(ObjectName,"Ter Object# %d",pict);
  427.  
  428.     status=OleCreateFromFile("StdFileEditing",&(TerClient.client),"Package",file,lhDoc,ObjectName,&(TerFont[pict].pObject),olerender_format,CF_METAFILEPICT);
  429.     if (status==OLE_ERROR_PROTOCOL) {
  430.        status=OleCreateFromFile("Static",&(TerClient.client),"Package",file,lhDoc,ObjectName,&(TerFont[pict].pObject),olerender_format,CF_METAFILEPICT);
  431.     }
  432.  
  433.     if (status!=OLE_OK && status!=OLE_WAIT_FOR_RELEASE) {
  434.        TerFont[pict].InUse=FALSE;
  435.        return PrintOleErrorMessage(w,"TerInsertObject",status);
  436.     }
  437.  
  438.     if (status==OLE_WAIT_FOR_RELEASE) TerOleWaitForRelease(w,TerFont[pict].pObject);
  439.     OlePostProcessing(w);           // shows changes as we don't have focus now
  440.  
  441.     return TRUE;
  442. }
  443.  
  444. /******************************************************************************
  445.      TerEditOle:
  446.      If the current item represents an OLE object, this functions calls the
  447.      server to update the item.
  448. ******************************************************************************/
  449. BOOL TerEditOle(PTERWND w)
  450. {
  451.     int   obj;
  452.     OLESTATUS status;
  453.     RECT  rect;
  454.  
  455.     // get current font id
  456.     obj=GetCurCfmt(w,CurLine,CurCol);
  457.     if (!(TerFont[obj].style&PICT)) return FALSE;
  458.     if (TerArg.ReadOnly || TerFont[obj].style&PROTECT) return FALSE;
  459.  
  460.     // If necessary, convert picture objects to temporary OLE objects
  461.     if (TerFont[obj].ObjectType==OBJ_NONE) TerCreateTempOle(w,obj);
  462.     if (TerFont[obj].ObjectType==OBJ_NONE) return FALSE;
  463.  
  464.     // build the bounding rectangle
  465.     rect.left=ColToUnits(w,CurCol,CurLine,LEFT);
  466.     rect.right=rect.left+TerFont[obj].CharWidth[0];
  467.     rect.top=LineToUnits(w,CurLine);
  468.     rect.bottom=rect.top+TerFont[obj].height;
  469.  
  470.     // Call server to edit the object
  471.     status=OleActivate(TerFont[obj].pObject,0,TRUE,TRUE,hTerWnd,&rect);
  472.     if (status==OLE_ERROR_LAUNCH) {
  473.        TerFont[obj].ObjectType=OBJ_NONE;      // restore to plain picture
  474.        MessageBox(hTerWnd,"Server program not available","Server Launch Error",MB_OK);
  475.        return FALSE;
  476.     }
  477.  
  478.     if (status!=OLE_OK && status!=OLE_WAIT_FOR_RELEASE) return PrintOleErrorMessage(w,"Ole Activation",status);
  479.     if (status==OLE_WAIT_FOR_RELEASE) {
  480.        TerOleWaitForRelease(w,TerFont[obj].pObject);
  481.        if (OLE_OK!=OleQueryReleaseError(TerFont[obj].pObject)) return FALSE;
  482.     }
  483.  
  484.     return TRUE;
  485. }
  486.  
  487. /******************************************************************************
  488.      TerCreateTempOle:
  489.      This function creates a temporary ole object from a metafile picture.  The
  490.      temporary metafile object is used to edit picture using MSDRAW.
  491. ******************************************************************************/
  492. TerCreateTempOle(PTERWND w,int obj)
  493. {
  494.     OLESTATUS status;
  495.     BYTE ObjectName[20];
  496.     LPOLEOBJECT pObject;
  497.     HANDLE hMeta,hNative;
  498.     LPWORD pNative;
  499.     long   MetaSize,bmWidth,bmHeight;
  500.     METAHEADER far *hdr;         // metafile header
  501.     struct StrFont SaveDIBObj,SaveMetaObj;
  502.  
  503.     if (!(TerFont[obj].style&PICT)) return FALSE;
  504.     if (TerFont[obj].ObjectType!=OBJ_NONE) return FALSE;
  505.  
  506.     // Convert DIB to metafile if necessary
  507.     if (TerFont[obj].PictType==PICT_DIBITMAP) {
  508.        SaveDIBObj=TerFont[obj];    // save DIB object
  509.        if (DIB2Metafile(w,obj)) {
  510.           SaveMetaObj=TerFont[obj];// save metafile object
  511.           TerFont[obj]=SaveDIBObj; // restore to delete
  512.           DeleteTerObject(w,obj);
  513.           TerFont[obj]=SaveMetaObj;// restore metafile object
  514.        }
  515.     }
  516.     if (TerFont[obj].PictType!=PICT_METAFILE) return FALSE;  
  517.  
  518.     // create an OLE object
  519.     wsprintf(ObjectName,"Ter Object# %d",obj);
  520.     TerFont[obj].ObjectType=OBJ_EMBED_TEMP;   // temporary embedded object
  521.     status=OleCreateInvisible("StdFileEditing",&(TerClient.client),MSDRAW_CLASS,lhDoc,ObjectName,&pObject,olerender_format,CF_METAFILEPICT,FALSE);
  522.  
  523.     if (status!=OLE_OK && status!=OLE_WAIT_FOR_RELEASE) {
  524.        TerFont[obj].ObjectType=OBJ_NONE;      // restore to plain picture
  525.        return PrintOleErrorMessage(w,"TerCreateTempOle(A)",status);
  526.     }
  527.     if (status==OLE_WAIT_FOR_RELEASE) TerOleWaitForRelease(w,pObject);
  528.  
  529.     // get the object data
  530.     hMeta=TerGetMetaFileBits(TerFont[obj].hMeta);      // convert to global handle
  531.     if (NULL==(hdr=(METAHEADER far *)GlobalLock(hMeta)) ) {
  532.         MessageBox(hTerWnd,"Error accessing meta file data",NULL,MB_OK);
  533.         TerFont[obj].ObjectType=OBJ_NONE;             // restore to plain picture
  534.         return FALSE;
  535.     }
  536.     MetaSize=(hdr->mtSize*2)+3*sizeof(WORD);          // add 3 integers for additional header
  537.     if (  NULL==(hNative=GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,MetaSize))  // allocate memory for the text data in our format
  538.        || NULL==(pNative=GlobalLock(hNative)) ){
  539.         MessageBox(hTerWnd,"Ran out of memory","TerCreateTempOle",MB_OK);
  540.         TerFont[obj].ObjectType=OBJ_NONE;      // restore to plain picture
  541.         return FALSE;
  542.     }
  543.            // copy data
  544.     bmHeight=ScrToPointsY(TerFont[obj].bmHeight);   // objure height in pointsize
  545.     bmWidth=ScrToPointsX(TerFont[obj].bmWidth);     // objure width in pointsize
  546.     pNative[0]=MM_ANISOTROPIC;                      // mapping mode
  547.     pNative[1]=(WORD)((bmWidth*2500)/72);           // width in HIMETRIC
  548.     pNative[2]=(WORD)((bmHeight*2500)/72);          // height in HIMETIC
  549.     HugeMove(hdr,&(pNative[3]),hdr->mtSize*2);      // move the rtf data
  550.  
  551.     GlobalUnlock(hNative);
  552.     GlobalUnlock(hMeta);
  553.     TerFont[obj].hMeta=TerSetMetaFileBits(hMeta);      // convert to metafile handle
  554.  
  555.     // set the object data
  556.     status=OleSetData(pObject,NativeClipFormat,hNative);
  557.     if (status==OLE_WAIT_FOR_RELEASE) TerOleWaitForRelease(w,pObject);
  558.     if (status!=OLE_OK) {
  559.        TerFont[obj].ObjectType=OBJ_NONE;            // restore to plain picture
  560.        return PrintOleErrorMessage(w,"TerCreateTempOle(B)",status);
  561.     }
  562.  
  563.     TerFont[obj].pObject=pObject;                   // temporary object pointer
  564.  
  565.     return TRUE;
  566. }
  567.  
  568. /*******************************************************************************
  569.     TerOleLoad:
  570.     This function supplies the ole data in the temporary handle (TerFont.hObject).
  571.     and creates the OLE object. This functions frees the temporary memory
  572.     handle.
  573. *******************************************************************************/
  574. TerOleLoad(PTERWND w,int obj)
  575. {
  576.     BYTE ObjectName[20];
  577.     OLESTATUS status;
  578.  
  579.     if (!TerFont[obj].hObject) return FALSE;
  580.  
  581.     hOleData=TerFont[obj].hObject;       // initialize the buffer
  582.     pOleData=NULL;
  583.  
  584.     if (NULL==(pOleData=GlobalLock(hOleData)) ){
  585.         MessageBox(hTerWnd,"Ran out of memory","TerOleLoad",MB_OK);
  586.         return FALSE;
  587.     }
  588.  
  589.     // load the object
  590.     wsprintf(ObjectName,"Ter Object# %d",obj);
  591.     OleStream.MaxSize=TerFont[obj].ObjectSize;  // object size
  592.     OleStream.offset=0;                         // beginning offset in the buffer
  593.     status=OleLoadFromStream(&(OleStream.stream),"StdFileEditing",&(TerClient.client),lhDoc,ObjectName,&(TerFont[obj].pObject));
  594.     if (status==OLE_ERROR_PROTOCOL) {
  595.         OleStream.offset=0;                         // beginning offset in the buffer
  596.         status=OleLoadFromStream(&(OleStream.stream),"Static",&(TerClient.client),lhDoc,ObjectName,&(TerFont[obj].pObject));
  597.     }
  598.  
  599.     if (status!=OLE_OK && status!=OLE_WAIT_FOR_RELEASE) return PrintOleErrorMessage(w,"TerOleLoad",status);
  600.     if (status==OLE_WAIT_FOR_RELEASE) TerOleWaitForRelease(w,TerFont[obj].pObject);
  601.  
  602.     GlobalUnlock(hOleData);
  603.     GlobalFree(hOleData);
  604.     TerFont[obj].hObject=NULL;
  605.  
  606.     return TRUE;
  607. }
  608.  
  609. /*******************************************************************************
  610.     TerOleUnload:
  611.     This function delete the OLE object.
  612. *******************************************************************************/
  613. TerOleUnload(PTERWND w,int obj)
  614. {
  615.    OLESTATUS status;
  616.    status=OleDelete(TerFont[obj].pObject);
  617.    if (status==OLE_WAIT_FOR_RELEASE) TerOleWaitForRelease(w,TerFont[obj].pObject);
  618.  
  619.    return TRUE;
  620. }
  621.  
  622. /*******************************************************************************
  623.     TerOleQuerySize:
  624.     This function returns the size of the specified object storage.
  625. *******************************************************************************/
  626. BOOL TerOleQuerySize(PTERWND w, int obj, DWORD far *size)
  627. {
  628.     (*size)=0;
  629.     if (OLE_OK!=OleQuerySize(TerFont[obj].pObject,size)) return FALSE;
  630.  
  631.     return TRUE;
  632. }
  633.  
  634. /*******************************************************************************
  635.     GetOleStorageData:
  636.     This function extracts the OLE storage data in a global buffer.  This
  637.     function allocates a new global buffer and leaves it locked.  The calling
  638.     fuction must unlock and free the buffer when done.
  639. *******************************************************************************/
  640. GetOleStorageData(PTERWND w,int obj)
  641. {
  642.     DWORD ObjectSize;
  643.     LPOLEOBJECT pObject=TerFont[obj].pObject;
  644.  
  645.     hOleData=NULL;       // initialize the buffer
  646.     pOleData=NULL;
  647.  
  648.     // get the data size requirement and allocate memory
  649.     if (OLE_OK!=OleQuerySize(pObject,&ObjectSize) || ObjectSize==0) {
  650.         MessageBox(hTerWnd,"Error getting object size!","GetOleStorageData",MB_OK);
  651.         return FALSE;
  652.     }
  653.  
  654.     if (  NULL==(hOleData=GlobalAlloc(GMEM_MOVEABLE,ObjectSize))  // allocate memory for the ole data
  655.        || NULL==(pOleData=GlobalLock(hOleData)) ){
  656.         MessageBox(hTerWnd,"Ran out of memory","GetOleStorageData",MB_OK);
  657.         return FALSE;
  658.     }
  659.  
  660.     // set to object to the global buffer
  661.     OleStream.MaxSize=ObjectSize;      // size of the object to read
  662.     OleStream.offset=0;                // beginning buffer offset
  663.     if (OLE_OK!=OleSaveToStream(pObject,&(OleStream.stream))) {
  664.         MessageBox(hTerWnd,"Error getting object data","GetOleStorageData",MB_OK);
  665.         GlobalUnlock(hOleData);
  666.         GlobalFree(hOleData);
  667.         return FALSE;
  668.     }
  669.  
  670.     return TRUE;
  671. }
  672.  
  673. /*******************************************************************************
  674.     TerOleWaitForRelease:
  675.     Wait for an ole async operation to be over
  676. *******************************************************************************/
  677. TerOleWaitForRelease(PTERWND w,LPOLEOBJECT pObject)
  678. {
  679.     MSG msg;
  680.     
  681.     WaitForOle++;                // suspend Ter window message processing
  682.  
  683.     while (WaitForOle) {
  684.        // message loop
  685.        while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
  686.            TranslateMessage(&msg);
  687.            DispatchMessage(&msg);
  688.        }
  689.     }
  690.  
  691.     return TRUE;
  692. }
  693.  
  694. /*******************************************************************************
  695.     PrintOleErrorMessage:
  696.     Prints an OLE error message and return FALSE
  697. *******************************************************************************/
  698. BOOL PrintOleErrorMessage(PTERWND w,LPBYTE topic,OLESTATUS status)
  699. {
  700.     BYTE string[40];
  701.  
  702.     if      (status==OLE_ERROR_ALREADY_REGISTERED) MessageBox(hTerWnd,"Already Registered!",topic,MB_OK);
  703.     else if (status==OLE_ERROR_MEMORY)             MessageBox(hTerWnd,"Ran out of memory!",topic,MB_OK);
  704.     else if (status==OLE_ERROR_NAME)               MessageBox(hTerWnd,"Naming Error or Duplicate Name!",topic,MB_OK);
  705.     else if (status==OLE_ERROR_CLIPBOARD)          MessageBox(hTerWnd,"Failed to get/set clipboard data",topic,MB_OK);
  706.     else if (status==OLE_ERROR_FORMAT)             MessageBox(hTerWnd,"Requested format not available",topic,MB_OK);
  707.     else if (status==OLE_ERROR_HANDLE)             MessageBox(hTerWnd,"OLE_ERROR_HANDLE",topic,MB_OK);
  708.     else if (status==OLE_ERROR_OPTION)             MessageBox(hTerWnd,"OLE_ERROR_OPTION",topic,MB_OK);
  709.     else if (status==OLE_ERROR_PROTOCOL)           MessageBox(hTerWnd,"OLE_ERROR_PROTOCOL",topic,MB_OK);
  710.     else if (status==OLE_ERROR_OBJECT)             MessageBox(hTerWnd,"Error: Not a valid object",topic,MB_OK);
  711.     else if (status==OLE_ERROR_LAUNCH)             MessageBox(hTerWnd,"Error: Server Not Available",topic,MB_OK);
  712.     else if (status==OLE_ERROR_CLASS)              MessageBox(hTerWnd,"Error: Invalid Ole Class",topic,MB_OK);
  713.     else if (status==OLE_ERROR_POKE_NATIVE)        MessageBox(hTerWnd,"Server Does Not Accept Data",topic,MB_OK);
  714.     else if (status==OLE_BUSY)                     MessageBox(hTerWnd,"Object Busy",topic,MB_OK);
  715.     else {                                          
  716.        wsprintf(string,"Ole Error #%d Encountered!",(UINT)status);
  717.        MessageBox(hTerWnd,string,topic,MB_OK);
  718.     }
  719.  
  720.     return FALSE;
  721. }
  722.