home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic 4 Unleashed / Visual_Basic_4_Unleashed_SAMS_Publishing_1995.iso / tedevkit / ter_ole2.h < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-25  |  49.0 KB  |  1,240 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. #if !defined(WIN32) || defined(__TURBOC__)
  18.   #include "coguid.h"
  19.   #include "oleguid.h"
  20. #else
  21.   #include "cguid.h"
  22.   #include "olectlid.h"
  23. #endif
  24.  
  25. #include "ole2ver.h"
  26.  
  27.  
  28. /*******************************************************************************
  29.     InitOle:
  30.     Create the OLE client structure
  31. *******************************************************************************/
  32. BOOL InitOle(PTERWND w)
  33. {
  34.     DWORD OleVer;
  35.     HRESULT result;
  36.     int i,TaskIdx;
  37.     HTASK CurTask;
  38.  
  39.     // check if OLE already initialized for this task
  40.     CurTask=GetWindowTask(hTerWnd);
  41.     for (i=0;i<TotalWinTasks;i++) if (WinTask[i].count>0 && WinTask[i].task==CurTask) break;
  42.     if (i==TotalWinTasks) {  // look for an unused slot
  43.        for (i=0;i<TotalWinTasks;i++) if (WinTask[i].count==0) break;
  44.     }
  45.     if (i==TotalWinTasks) {
  46.        if (TotalWinTasks<MAX_TASKS) {
  47.           i=TotalWinTasks;
  48.           WinTask[i].count=0;
  49.           TotalWinTasks++;
  50.        }
  51.        else return PrintError(w,"Ran out of task table!");
  52.     }
  53.  
  54.     // update the task slot
  55.     TaskIdx=i;
  56.     WinTask[TaskIdx].task=CurTask;
  57.     WinTask[TaskIdx].count++;
  58.  
  59.     // initialize OLE
  60.     if (WinTask[TaskIdx].count==1) {      // first window for this application instance
  61.        OleVer=OleBuildVersion();
  62.        if (HIWORD(OleVer) !=rmm || LOWORD(OleVer) < rup) {
  63.           return PrintError(w,"Invalid OLE version!");
  64.        }
  65.  
  66.        result=OleInitialize(NULL);
  67.        if (GetScode(result)!=S_OK && GetScode(result)!=S_FALSE) {
  68.           PrintOleError(w,result);
  69.           return PrintError(w,"Error initializing OLE!");
  70.        }
  71.  
  72.        // create and open a document storage - created one per DLL task
  73.        result=StgCreateDocfile(NULL,STGM_TRANSACTED|STGM_READWRITE
  74.                  |STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_DELETEONRELEASE,0,&(WinTask[TaskIdx].pDocStg));
  75.        if (result!=NOERROR) {
  76.           PrintOleError(w,result);
  77.           return PrintError(w,"Error creating OLE storage!");       
  78.        }
  79.     }
  80.     
  81.     pDocStorage=WinTask[TaskIdx].pDocStg;  // use it from the table
  82.      
  83.     
  84.     // create the OLE1 compatible streams
  85.     OleStreamVtbl.Get=NULL;     // Ole stream get callback function
  86.     OleStreamVtbl.Put=NULL;     // Ole stream put callback function
  87.  
  88.     // Create the client structure
  89.     if ( NULL==(OleStreamVtbl.Get=(LPVOID) MakeProcInstance((FARPROC)TerOleGet,hTerInst))
  90.       || NULL==(OleStreamVtbl.Put=(LPVOID) MakeProcInstance((FARPROC)TerOlePut,hTerInst)) ){
  91.        MessageBox(hTerWnd,"Can not create ole stream callback instances!",NULL,MB_OK);
  92.        return FALSE;
  93.     }
  94.  
  95.     OleStream.stream.lpstbl=&OleStreamVtbl;
  96.     OleStream.TerData=w;
  97.  
  98.     // enable drag/drop
  99.     DragAcceptFiles(hTerWnd,TRUE);
  100.  
  101.     return TRUE;
  102. }
  103.  
  104. /*******************************************************************************
  105.     ExitOle:
  106.     Exit ole logic. Called by CloseTer
  107. *******************************************************************************/
  108. BOOL ExitOle(PTERWND w)
  109. {
  110.     int i;
  111.     HTASK CurTask;
  112.  
  113.     #if !defined(WIN32) 
  114.        if (OleStreamVtbl.Get)      FreeProcInstance((FARPROC)OleStreamVtbl.Get);
  115.        if (OleStreamVtbl.Put)      FreeProcInstance((FARPROC)OleStreamVtbl.Put);
  116.     #endif
  117.     DragAcceptFiles(hTerWnd,FALSE);
  118.  
  119.     // check if the last window for the task
  120.     CurTask=GetWindowTask(hTerWnd);
  121.     for (i=0;i<TotalWinTasks;i++) if (WinTask[i].count>0 && WinTask[i].task==CurTask) break;
  122.     
  123.     if (i<TotalWinTasks) {
  124.       WinTask[i].count--;
  125.  
  126.       if (WinTask[i].count==0) {
  127.          if (WinTask[i].pDocStg) (WinTask[i].pDocStg)->lpVtbl->Release(WinTask[i].pDocStg);
  128.          OleUninitialize();
  129.       }
  130.     }
  131.  
  132.     return TRUE;
  133. }
  134.  
  135. /*******************************************************************************
  136.     OlePostProcessing:
  137.     This function gets the data from the application's persistence stroage to 
  138.     the IStorage interface residing in OLE2.DLL.
  139. *******************************************************************************/
  140. OlePostProcessing(PTERWND w)
  141. {
  142.     return TRUE;
  143. }
  144.  
  145. /*******************************************************************************
  146.     TerPasteSpecial:
  147.     Accept a string from the user along with other parameters and search for 
  148.     the first instances of the string.
  149. *******************************************************************************/
  150. TerPasteSpecial(PTERWND w)
  151. {
  152.     int index,len,i;
  153.     int select;
  154.     UINT ClipFormat,PasteFormat;
  155.     long BuffSize;
  156.     BYTE class[MAX_WIDTH+1],doc[MAX_WIDTH+1],item[MAX_WIDTH+1],PasteFmts[MAX_PASTE_FORMATS];
  157.     BOOL PasteLink=FALSE;
  158.  
  159.     if (FontsReleased) RecreateFonts(w,hTerDC);    // recreate fonts
  160.  
  161.     // Build the source description string
  162.     ClipFormat=GetOleClipItem(w,class,doc,item);
  163.  
  164.     if (ClipFormat>0) {
  165.        // get the class name
  166.        BuffSize=sizeof(TempString);
  167.        RegQueryValue(HKEY_CLASSES_ROOT,class,TempString,&BuffSize);
  168.  
  169.        // Build the item string
  170.        len=lstrlen(doc);
  171.        for (i=len;i>0;i--) if (doc[i-1]=='\\') break;
  172.        lstrcpy(TempString1,&(doc[i]));
  173.        if (lstrlen(TempString1)>0) lstrcat(TempString1," ");
  174.        lstrcat(TempString1,item);
  175.     }
  176.     else {
  177.        lstrcpy(TempString,"Unknown");
  178.        lstrcpy(TempString1,"");
  179.     }
  180.  
  181.     // build the datatype table
  182.     for (i=0;i<MAX_PASTE_FORMATS;i++) PasteFmts[i]=FALSE;    // list of available formats
  183.     if (IsClipboardFormatAvailable(OwnerLinkClipFormat)) PasteFmts[PASTE_OBJECT]=TRUE;
  184.     if (IsClipboardFormatAvailable(CF_METAFILEPICT))     PasteFmts[PASTE_PICT]=TRUE;
  185.     if (IsClipboardFormatAvailable(CF_BITMAP))           PasteFmts[PASTE_BM]=TRUE;
  186.     if (IsClipboardFormatAvailable(CF_DIB))              PasteFmts[PASTE_DIB]=TRUE;
  187.     if (IsClipboardFormatAvailable(RtfClipFormat))       PasteFmts[PASTE_RTF]=TRUE;
  188.     if (IsClipboardFormatAvailable(CF_TEXT))             PasteFmts[PASTE_TEXT]=TRUE;
  189.  
  190.     // check if atleast one format available
  191.     for (i=0;i<MAX_PASTE_FORMATS;i++) if (PasteFmts[i]) break;
  192.     if (i==MAX_PASTE_FORMATS) return TRUE;             // no formats available
  193.  
  194.     index=CallDialogBox(w,"PasteSpecialParam",PasteSpecialParam,(long)(LPBYTE)PasteFmts);
  195.     if (index<0) return TRUE;                          // operation cancelled
  196.     
  197.     // extract the selected clipboard format
  198.     if (index>=MAX_PASTE_FORMATS) {                    // Is object linking selected
  199.        index-=MAX_PASTE_FORMATS;
  200.        PasteLink=TRUE;
  201.     }
  202.     for (i=0;i<MAX_PASTE_FORMATS;i++) {
  203.        if (PasteFmts[i]) index--;
  204.        if (index<0) break;
  205.     }
  206.     select=i;                                           // selected format
  207.  
  208.     // get the paste format
  209.     if      (select==PASTE_TEXT)   PasteFormat=CF_TEXT;
  210.     else if (select==PASTE_RTF)    PasteFormat=RtfClipFormat;
  211.     else if (select==PASTE_PICT)   PasteFormat=CF_METAFILEPICT;
  212.     else if (select==PASTE_DIB)    PasteFormat=CF_DIB;
  213.     else if (select==PASTE_BM)     PasteFormat=CF_BITMAP;
  214.     else                           PasteFormat=NativeClipFormat;
  215.     
  216.     // Retrieve the text formats from the clipboard
  217.     if (select==PASTE_RTF || select==PASTE_TEXT)  return CopyFromClipboard(w,PasteFormat);
  218.  
  219.     // Process the ole objects
  220.     if (select==PASTE_OBJECT)  return TerOleFromClipboard(w,PasteFormat,PasteLink);
  221.  
  222.     // Process the non-ole picture formats
  223.     if (select==PASTE_PICT || select==PASTE_DIB || select==PASTE_BM)  return TerPastePicture(hTerWnd,PasteFormat,NULL,0,ALIGN_BOT,TRUE);
  224.  
  225.     return TRUE;
  226. }
  227.  
  228. /*******************************************************************************
  229.     TerOleFromClipboard:
  230.     Embed an OLE object from clipboard.
  231. *******************************************************************************/
  232. TerOleFromClipboard(PTERWND w, UINT format,BOOL PasteLink) 
  233. {
  234.     int obj;
  235.     LPDATAOBJECT pDataObject;
  236.     FORMATETC OleFmt;
  237.     LPSTORAGE pObjStg;
  238.     LPOLECLIENTSITE pObjSite;
  239.     STGMEDIUM med;
  240.     HRESULT result;
  241.  
  242.     // Erase any previously highlighted text
  243.     if (HilightType==HILIGHT_CHAR) BlockDelete(w);
  244.  
  245.     if ((obj=FindOpenSlot(w))==-1) return FALSE;  // find an empty slot
  246.  
  247.     // get the data object from the clipboard
  248.     result=OleGetClipboard(&pDataObject);
  249.     if (result!=NOERROR) return PrintError(w,"Error retrieving the clipboard data(TerOleFromClipboard");
  250.  
  251.  
  252.     // create IOleClientSite and IStorage interfaces for the object
  253.     if (!TerOlePreCreate(w,obj,&pObjSite,&pObjStg,&OleFmt)) return FALSE;
  254.  
  255.     // Create the object
  256.     if (PasteLink) result=OleCreateLinkFromData(pDataObject,&IID_IOleObject,OLERENDER_FORMAT,&OleFmt,pObjSite,pObjStg,(LPVOID far *)&(TerFont[obj].pObject));
  257.     else           result=OleCreateFromData(pDataObject,&IID_IOleObject,OLERENDER_FORMAT,&OleFmt,pObjSite,pObjStg,(LPVOID far *)&(TerFont[obj].pObject));
  258.     if (result!=NOERROR || !(TerFont[obj].pObject)) {
  259.        pObjSite->lpVtbl->Release(pObjSite);    // release the client site
  260.        PrintOleError(w,result);
  261.        wsprintf(TempString,"Object creation error: %lx",(ULONG)result);
  262.        return PrintError(w,TempString);
  263.     }
  264.  
  265.     // make advisory connection and display the object
  266.     TerOlePostCreate(w,obj);
  267.  
  268.     // retrieve the presentation data
  269.     if (NOERROR!=(pDataObject->lpVtbl->GetData(pDataObject,&OleFmt,&med)) || med.tymed!=TYMED_MFPICT) {
  270.        return PrintError(w,"Error retrieving presentation data(TerOleFromClipboard)");
  271.     }
  272.     if (TerCreateMetafile(w,med.u.hGlobal,obj)<0) return FALSE;   // extract metafile
  273.     ReleaseStgMedium(&med);                      // release data handle
  274.     pDataObject->lpVtbl->Release(pDataObject);   // this data object needs to be released
  275.  
  276.     if (PasteLink) TerFont[obj].ObjectType=OBJ_LINK;
  277.     else           TerFont[obj].ObjectType=OBJ_EMBED;
  278.  
  279.     TerInsertObjectId(hTerWnd,obj,TRUE);   // insert this object into text
  280.     FitPictureInFrame(w,CurLine,FALSE);
  281.     
  282.     return TRUE;
  283. }
  284.  
  285. /******************************************************************************
  286.      TerInsertObject:
  287.      Insert a new ole object. This function activates the OLE server.  the
  288.      second part of this function (TerInsertObjectId) is called from the
  289.      ole post processing function to actually insert the object into the
  290.      text.
  291. ******************************************************************************/
  292. BOOL TerInsertObject(PTERWND w)
  293. {
  294.     int SubKey;
  295.     int obj;
  296.     CLSID ClassId;
  297.     FORMATETC OleFmt;
  298.     LPSTORAGE pObjStg;
  299.     LPOLECLIENTSITE pObjSite;
  300.     HRESULT result;
  301.     LPOLEOBJECT pObject;
  302.  
  303.     if ((SubKey=CallDialogBox(w,"InsertObjectParam",InsertObjectParam,0L))<0) return TRUE;
  304.     
  305.     // get the class id
  306.     RegEnumKey(HKEY_CLASSES_ROOT,SubKey,TempString,sizeof(TempString)-1);
  307.     result=CLSIDFromProgID(StrToOleStr(TempString,TempString1),&ClassId);
  308.     if (NOERROR!=result)  return PrintError(w,"OLE class not found in the Registration Database!");     // convert to class id
  309.  
  310.     // create the object
  311.     if ((obj=FindOpenSlot(w))==-1) return FALSE; // find an empty slot to make the object name
  312.     TerFont[obj].InUse=TRUE;
  313.     TerFont[obj].ObjectType=OBJ_EMBED_INSERT;    // object to be inserted
  314.     TerFont[obj].style=PICT;
  315.     TerFont[obj].PictType=PICT_METAFILE;
  316.     TerFont[obj].hMeta=0;
  317.     
  318.     // create IOleClientSite and IStorage interfaces for the object
  319.     if (!TerOlePreCreate(w,obj,&pObjSite,&pObjStg,&OleFmt)) return FALSE;
  320.  
  321.     // Create the object
  322.     result=OleCreate(&ClassId,&IID_IOleObject,OLERENDER_FORMAT,&OleFmt,pObjSite,pObjStg,(LPVOID far *)&(TerFont[obj].pObject));
  323.     if (result!=NOERROR || !(TerFont[obj].pObject)) {
  324.        TerFont[obj].InUse=FALSE;
  325.        pObjSite->lpVtbl->Release(pObjSite);    // release the client site
  326.        wsprintf(TempString,"Object creation error: %lx",(ULONG)result);
  327.        return PrintError(w,TempString);
  328.     }
  329.  
  330.     // make advisory connection and display the object
  331.     TerOlePostCreate(w,obj);
  332.  
  333.     // Show the object window if not alredy shown
  334.     pObject=TerFont[obj].pObject;
  335.     result=pObject->lpVtbl->DoVerb(pObject,OLEIVERB_SHOW,NULL,pObjSite,0,hTerWnd,NULL);
  336.     
  337.     return TRUE;
  338. }
  339.  
  340. /******************************************************************************
  341.      TerOlePreCreate:
  342.      This function creates IOleClientSite and IStorage interface needed
  343.      to create an object.
  344. ******************************************************************************/
  345. BOOL TerOlePreCreate(PTERWND w,int obj, LPOLECLIENTSITE far *ppObjSite, LPSTORAGE far *ppObjStg,FORMATETC far *OleFmt)
  346. {
  347.     BYTE ObjName[20];
  348.     HRESULT result;
  349.  
  350.     // create a new storage for this object
  351.     StorageId++;
  352.     wsprintf(ObjName,"TerObj%dId%d",obj,StorageId);
  353.     result=pDocStorage->lpVtbl->CreateStorage(pDocStorage,StrToOleStr(ObjName,TempString),
  354.            STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE,0,0,ppObjStg);
  355.     if (result!=NOERROR || !(*ppObjStg)) {
  356.        TerFont[obj].InUse=FALSE;
  357.        wsprintf(TempString,"Error creating object storage: %lx",(ULONG)result);
  358.        return PrintError(w,TempString);
  359.     }
  360.  
  361.     // create a client site interface for this object
  362.     if (NULL==((*ppObjSite)=CreateOleClientSite(w,obj,(*ppObjStg)))) {
  363.        TerFont[obj].InUse=FALSE;
  364.        return PrintError(w,"Error creating client site!");
  365.     }
  366.     TerFont[obj].pObjSite=(*ppObjSite);
  367.  
  368.     // set ole format
  369.     OleFmt->cfFormat=CF_METAFILEPICT;
  370.     OleFmt->ptd=NULL;
  371.     OleFmt->dwAspect=DVASPECT_CONTENT;
  372.     OleFmt->lindex=-1;
  373.     OleFmt->tymed=TYMED_MFPICT;
  374.  
  375.     return TRUE;
  376. }
  377.  
  378. /******************************************************************************
  379.      TerOlePostCreate:
  380.      Make advisory connection and display object
  381. ******************************************************************************/
  382. BOOL TerOlePostCreate(PTERWND w,int obj)
  383. {
  384.     BYTE ObjName[129];
  385.     LPOLEOBJECT pObject;
  386.     LPOLECLIENTSITE pObjSite;
  387.     LPSTRCLIENTSITE pSite;
  388.     LPVIEWOBJECT pViewObject;
  389.     HRESULT result;
  390.  
  391.     // extract object pointers
  392.     pObject=TerFont[obj].pObject;
  393.     pObjSite=TerFont[obj].pObjSite;
  394.     pSite=(LPSTRCLIENTSITE )pObjSite;
  395.  
  396.     // set the client site
  397.     pObject->lpVtbl->SetClientSite(pObject,pObjSite);
  398.  
  399.     // set the object name
  400.     if (lstrlen(TerArg.file)>0) wsprintf(ObjName,"%s, obj#%d",(LPSTR)TerArg.file,obj);
  401.     else                        wsprintf(ObjName,"TerObject#%d",obj);
  402.     pObject->lpVtbl->SetHostNames(pObject,
  403.                                  StrToOleStr(TerArg.file,TempString),
  404.                                  StrToOleStr(ObjName,TempString1));
  405.  
  406.     // set the advise link to the pObject
  407.     pObject->lpVtbl->Advise(pObject,pSite->pObjAdvise,&(pSite->ConnectToken));
  408.  
  409.     // set the advise link to the pViewObject
  410.     result=pObject->lpVtbl->QueryInterface(pObject,&IID_IViewObject,(LPVOID far *)&pViewObject);
  411.     if (result!=NOERROR)   return PrintError(w,"Error retrieving view object(TerOlePostCreate)");
  412.     result=pViewObject->lpVtbl->SetAdvise(pViewObject,DVASPECT_CONTENT,0,pSite->pObjAdvise);
  413.     if (result!=NOERROR)   return PrintError(w,"Error setting the data advise connection(TerOlePostCreate)");
  414.  
  415.     OleSetContainedObject((LPUNKNOWN)pObject,TRUE);      // soft lock maintenance function
  416.  
  417.     pObjSite->lpVtbl->SaveObject(pObjSite);  // save the initial status to the storage
  418.  
  419.     return TRUE;
  420. }
  421.  
  422. /******************************************************************************
  423.      TerInsertDragObject:
  424.      Insert an ole object inserted using drag/drop.  Only the first file
  425.      in the drag/drop buffer is processed.
  426. ******************************************************************************/
  427. BOOL TerInsertDragObject(PTERWND w,HDROP hDrop)
  428. {
  429.     int obj;
  430.     POINT pt;
  431.     DWORD lParam;
  432.     BYTE file[129];
  433.     LPOLEOBJECT pObject;
  434.     LPDATAOBJECT pDataObject;
  435.     FORMATETC OleFmt;
  436.     LPSTORAGE pObjStg;
  437.     LPOLECLIENTSITE pObjSite;
  438.     STGMEDIUM med;
  439.     HRESULT result;
  440.  
  441.     // Extract the dropped file
  442.     if (!DragQueryPoint(hDrop,&pt)) return TRUE;
  443.     DragQueryFile(hDrop,0,file,sizeof(file)-1);  // get the first file 
  444.     DragFinish(hDrop);             // release the drag buffer
  445.  
  446.     // get cursor location at the drag point
  447.     lParam=pt.y;
  448.     lParam=lParam<<16;             // high word
  449.     lParam=lParam+pt.x;
  450.     TerMousePos(w,lParam);
  451.     CurLine=MouseLine;
  452.     CurCol=MouseCol;
  453.  
  454.     // create the object
  455.     if ((obj=FindOpenSlot(w))==-1) return FALSE;  // find an empty slot to make the object name
  456.     TerFont[obj].InUse=TRUE;
  457.     TerFont[obj].style=PICT;
  458.     TerFont[obj].PictType=PICT_METAFILE;
  459.     TerFont[obj].hMeta=0;
  460.  
  461.     // create IOleClientSite and IStorage interfaces for the object
  462.     if (!TerOlePreCreate(w,obj,&pObjSite,&pObjStg,&OleFmt)) return FALSE;
  463.  
  464.     // Create the object
  465.     result=OleCreateFromFile(&CLSID_NULL,StrToOleStr(file,TempString),&IID_IOleObject,OLERENDER_FORMAT,&OleFmt,pObjSite,pObjStg,(LPVOID far *)&(TerFont[obj].pObject));
  466.     if (result!=NOERROR || !(TerFont[obj].pObject)) {
  467.        pObjSite->lpVtbl->Release(pObjSite);    // release the client site
  468.        TerFont[obj].InUse=FALSE;
  469.        wsprintf(TempString,"Object creation error: %lx",(ULONG)result);
  470.        return PrintError(w,TempString);
  471.     }
  472.     pObject=TerFont[obj].pObject;
  473.  
  474.     // make advisory connection and display the object
  475.     TerOlePostCreate(w,obj);
  476.  
  477.  
  478.     // get the IDataObject Interface
  479.     result=pObject->lpVtbl->QueryInterface(pObject,&IID_IDataObject,(LPVOID far *)&pDataObject);
  480.     if (result!=NOERROR)   return PrintError(w,"Error retrieving data object(TerInsertDragObject)");
  481.  
  482.     // retrieve the presentation data
  483.     if (NOERROR!=(pDataObject->lpVtbl->GetData(pDataObject,&OleFmt,&med)) || med.tymed!=TYMED_MFPICT) {
  484.        return PrintError(w,"Error retrieving presentation data(TerInsertDragObject)");
  485.     }
  486.  
  487.     if (TerCreateMetafile(w,med.u.hGlobal,obj)<0) return FALSE;   // extract metafile
  488.     TerFont[obj].ObjectType=OBJ_EMBED;
  489.  
  490.     ReleaseStgMedium(&med);                      // release data handle
  491.  
  492.     TerInsertObjectId(hTerWnd,obj,TRUE);   // insert this object into text
  493.  
  494.     return TRUE;
  495. }
  496.  
  497. /******************************************************************************
  498.      TerEditOle:
  499.      If the current item represents an OLE object, this functions calls the
  500.      server to update the item.
  501. ******************************************************************************/
  502. BOOL TerEditOle(PTERWND w)
  503. {
  504.     int   obj;
  505.     LPOLEOBJECT pObject;
  506.  
  507.     // get current font id
  508.     obj=GetCurCfmt(w,CurLine,CurCol);
  509.     if (!(TerFont[obj].style&PICT)) return FALSE;
  510.     if (TerArg.ReadOnly || TerFont[obj].style&PROTECT) return FALSE;
  511.  
  512.     // If necessary, convert picture objects to temporary OLE objects
  513.     if (TerFont[obj].ObjectType==OBJ_NONE) TerCreateTempOle(w,obj);
  514.     if (TerFont[obj].ObjectType==OBJ_NONE) return FALSE;
  515.  
  516.     // run the ole object
  517.     pObject=TerFont[obj].pObject;
  518.     pObject->lpVtbl->DoVerb(pObject,OLEIVERB_SHOW,NULL,TerFont[obj].pObjSite,0,hTerWnd,NULL);
  519.  
  520.     return TRUE;
  521. }
  522.  
  523. /******************************************************************************
  524.      TerCreateTempOle:
  525.      This function creates a temporary ole object from a metafile picture.  The
  526.      temporary metafile object is used to edit picture using MSDRAW.
  527. ******************************************************************************/
  528. TerCreateTempOle(PTERWND w,int obj)
  529. {
  530.     HANDLE hMeta;
  531.     METAHEADER far *hdr;
  532.     LPWORD pNative;
  533.     LPBYTE pStr;
  534.     int len;
  535.     long far *pLong;
  536.     long   ObjSize,bmWidth,bmHeight,MetaSize;
  537.     struct StrFont SaveDIBObj,SaveMetaObj;
  538.     CLSID ClassId;
  539.     LPOLECLIENTSITE pObjSite;
  540.     LPSTORAGE pObjStg;
  541.     FORMATETC OleFmt;
  542.  
  543.     if (!(TerFont[obj].style&PICT)) return FALSE;
  544.     if (TerFont[obj].ObjectType!=OBJ_NONE) return FALSE;
  545.  
  546.     // get the class id for MSDRAW program
  547.     if (NOERROR!=CLSIDFromProgID(StrToOleStr(MSDRAW_CLASS,TempString),&ClassId)) return FALSE;   // MS draw program not found
  548.  
  549.     // Convert DIB to metafile if necessary
  550.     if (TerFont[obj].PictType==PICT_DIBITMAP) {
  551.        SaveDIBObj=TerFont[obj];    // save DIB object
  552.        if (DIB2Metafile(w,obj)) {
  553.           SaveMetaObj=TerFont[obj];// save metafile object
  554.           TerFont[obj]=SaveDIBObj; // restore to delete
  555.           DeleteTerObject(w,obj);
  556.           TerFont[obj]=SaveMetaObj;// restore metafile object
  557.        }
  558.     }
  559.     if (TerFont[obj].PictType!=PICT_METAFILE) return FALSE;  
  560.  
  561.     // Make a native object from the metafile 
  562.     hMeta=TerGetMetaFileBits(TerFont[obj].hMeta);   // convert to global handle
  563.     if (NULL==(hdr=(METAHEADER far *)GlobalLock(hMeta)) ) {
  564.         MessageBox(hTerWnd,"Error accessing meta file data",NULL,MB_OK);
  565.         TerFont[obj].ObjectType=OBJ_NONE;           // restore to plain picture
  566.         return FALSE;
  567.     }
  568.     MetaSize=hdr->mtSize*2;
  569.  
  570.     // calculate the size of the tempporary ole object
  571.     ObjSize=2*sizeof(long);                        // ver and indentifier
  572.     ObjSize+=sizeof(long)+lstrlen(MSDRAW_CLASS)+1; // class id + null terminator
  573.     ObjSize+=2*sizeof(long);                       // length of topic and item string
  574.     ObjSize+=sizeof(long);                         // length of native data
  575.     ObjSize+=3*sizeof(WORD);                       // native data header
  576.     ObjSize+=MetaSize;                             // native data bytes
  577.  
  578.     ObjSize+=2*sizeof(long);                       // presentation data, ole ver and id
  579.     ObjSize+=sizeof(long)+strlen("METAFILEPICT")+1;// format
  580.     ObjSize+=2*sizeof(long);                       // width and height
  581.     ObjSize+=sizeof(long);                         // size of presentation data
  582.     ObjSize+=MetaSize;                             // presentation data bits
  583.  
  584.     if (  NULL==(hOleData=GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,ObjSize))  // allocate memory for the text data in our format
  585.        || NULL==(pOleData=GlobalLock(hOleData)) ){
  586.         MessageBox(hTerWnd,"Ran out of memory","TerCreateTempOle",MB_OK);
  587.         TerFont[obj].ObjectType=OBJ_NONE;           // restore to plain picture
  588.         return FALSE;
  589.     }
  590.     
  591.     // set the object header
  592.     pLong=(LPLONG)pOleData;
  593.     *pLong=0x501;pLong++;                           // ole version number
  594.     *pLong=2;pLong++;                               // native data id
  595.  
  596.     len=lstrlen(MSDRAW_CLASS);                      // length of class string
  597.     *pLong=(len+1);pLong++;                         // length of class string plus NULL terminator
  598.     pStr=(LPBYTE)pLong;
  599.     lstrcpy(pStr,MSDRAW_CLASS);
  600.     pStr=&(pStr[len]);                              // NULL not included
  601.     *pStr=0;pStr++;                                 // add the numm terminator
  602.     pLong=(LPLONG)pStr;                
  603.  
  604.     *pLong=0;pLong++;                               // length of topic string
  605.     *pLong=0;pLong++;                               // length of item string
  606.  
  607.     *pLong=MetaSize+3*sizeof(WORD);                 // size of native bits
  608.     pLong++;
  609.  
  610.     // set native data
  611.     pNative=(LPWORD)pLong;
  612.     bmHeight=ScrToPointsY(TerFont[obj].bmHeight);   // objure height in pointsize
  613.     bmWidth=ScrToPointsX(TerFont[obj].bmWidth);     // objure width in pointsize
  614.     pNative[0]=MM_ANISOTROPIC;                      // mapping mode
  615.     pNative[1]=(WORD)((bmWidth*2500)/72);           // width in HIMETRIC
  616.     pNative[2]=(WORD)((bmHeight*2500)/72);          // height in HIMETIC
  617.  
  618.     pStr=(LPBYTE)&(pNative[3]);
  619.     HugeMove(hdr,pStr,MetaSize);                     // move the rtf data
  620.  
  621.     pLong=(LPLONG)&(((char huge *)pStr)[MetaSize]);  // advance the pointer
  622.  
  623.     // set the presentation data
  624.     *pLong=0x501;pLong++;                           // ole version number
  625.     *pLong=5;pLong++;                               // presentation data id
  626.  
  627.     len=lstrlen("METAFILEPICT");                    // length of class string
  628.     *pLong=(len+1);pLong++;                         // length of class string plus NULL terminator
  629.     pStr=(LPBYTE)pLong;
  630.     lstrcpy(pStr,"METAFILEPICT");
  631.     pStr=&(pStr[(int)len]);                         // NULL not included
  632.     *pStr=0;pStr++;                                 // add the numm terminator
  633.     pLong=(LPLONG)pStr;                
  634.  
  635.     *pLong=pNative[1];pLong++;                      // width of presentation
  636.     *pLong=pNative[2];pLong++;                      // height of presentation
  637.  
  638.     *pLong=MetaSize;pLong++;                       // size of the presentation bits
  639.     HugeMove(hdr,pLong,MetaSize);              // move the rtf data
  640.  
  641.     TerFont[obj].hMeta=TerSetMetaFileBits(hMeta);   // restore the metafile handle
  642.  
  643.     // create an ole object 
  644.     if (!TerOlePreCreate(w,obj,&pObjSite,&pObjStg,&OleFmt)) return FALSE;
  645.  
  646.     // copy OLE1 stream data to OLE2 storage
  647.     OleStream.MaxSize=ObjSize;                 // object size
  648.     OleStream.offset=0;                         // beginning offset in the buffer
  649.     if (NOERROR!=(OleConvertOLESTREAMToIStorage(&(OleStream.stream),pObjStg,NULL))) {
  650.        return PrintError(w,"OLE data conversion error(TerCreateTempOle)");
  651.     }
  652.  
  653.     TerFont[obj].ObjectType=OBJ_EMBED_TEMP;         // mark as temporary embedded object
  654.     if (NOERROR!=(OleLoad(pObjStg,&(IID_IOleObject),pObjSite,(LPVOID far *)&(TerFont[obj].pObject)))) {
  655.        return PrintError(w,"OLE load error(TerCreateTempOle)");
  656.     }
  657.  
  658.     TerOlePostCreate(w,obj);                        // postcreation tasks
  659.  
  660.     GlobalUnlock(hOleData);                         // free the temporary data
  661.     GlobalFree(hOleData);
  662.  
  663.     return TRUE;
  664. }
  665.  
  666. /*******************************************************************************
  667.     TerOleLoad:
  668.     This function supplies the ole data in the temporary handle (TerFont.hObject).
  669.     and creates the OLE object. This functions frees the temporary memory
  670.     handle.
  671. *******************************************************************************/
  672. TerOleLoad(PTERWND w,int obj)
  673. {
  674.     FORMATETC OleFmt;
  675.     LPSTORAGE pObjStg;
  676.     LPOLECLIENTSITE pObjSite;
  677.     HRESULT result;
  678.     LPLONG pLong;
  679.     CLSID  ClassId;
  680.  
  681.     if (!TerFont[obj].hObject) return FALSE;
  682.  
  683.     hOleData=TerFont[obj].hObject;       // initialize the buffer
  684.     pOleData=NULL;
  685.  
  686.     if (NULL==(pOleData=GlobalLock(hOleData)) ){
  687.         MessageBox(hTerWnd,"Ran out of memory","TerOleLoad",MB_OK);
  688.         return FALSE;
  689.     }
  690.  
  691.     // create internal interfaces for the object
  692.     if (!TerOlePreCreate(w,obj,&pObjSite,&pObjStg,&OleFmt)) return FALSE;
  693.  
  694.     // Create the CompObj stream for a link object
  695.     pLong=(LPLONG)pOleData;
  696.     if (pLong[1]==1) {         // link type object
  697.        lstrcpy(TempString,(LPSTR)&(pOleData[3*sizeof(LONG)]));    // prog id
  698.        result=CLSIDFromProgID(StrToOleStr(TempString,TempString1),&ClassId);
  699.        if (NOERROR!=result)  return PrintError(w,"OLE class not found in the Registration Database(TerOleLoad)!");     // convert to class id
  700.  
  701.        result=WriteClassStg(pObjStg,&ClassId);
  702.        if (NOERROR!=result)  return PrintError(w,"Error writing class id(TerOleLoad)!");     // convert to class id
  703.  
  704.        result=WriteFmtUserTypeStg(pObjStg,0,StrToOleStr("",TempString));
  705.        if (NOERROR!=result)  return PrintError(w,"Error writing user type(TerOleLoad)!");     // convert to class id
  706.     }
  707.  
  708.     // copy OLE1 stream data to OLE2 storage
  709.     OleStream.MaxSize=TerFont[obj].ObjectSize;  // object size
  710.     OleStream.offset=0;                         // beginning offset in the buffer
  711.     result=OleConvertOLESTREAMToIStorage(&(OleStream.stream),pObjStg,NULL);
  712.     if (result!=NOERROR) return PrintError(w,"OLE data conversion error");
  713.  
  714.     result=OleLoad(pObjStg,&(IID_IOleObject),pObjSite,(LPVOID far *)&(TerFont[obj].pObject));
  715.     if (result!=NOERROR || !TerFont[obj].pObject) return PrintError(w,"OLE load error");
  716.  
  717.     // make advisory connection and display the object
  718.     TerOlePostCreate(w,obj);
  719.  
  720.     GlobalUnlock(hOleData);
  721.     GlobalFree(hOleData);
  722.     TerFont[obj].hObject=NULL;
  723.  
  724.     return TRUE;
  725. }
  726.  
  727. /*******************************************************************************
  728.     TerOleUnload:
  729.     This function delete the OLE object.
  730. *******************************************************************************/
  731. TerOleUnload(PTERWND w,int obj)
  732. {
  733.     LPOLEOBJECT pObject=TerFont[obj].pObject;
  734.     LPOLECLIENTSITE pObjSite=TerFont[obj].pObjSite;
  735.     LPSTRCLIENTSITE pSite=(LPSTRCLIENTSITE )pObjSite;
  736.  
  737.     if (pObject) {
  738.        pObject->lpVtbl->Unadvise(pObject,pSite->ConnectToken);
  739.        pObject->lpVtbl->Release(pObject);
  740.     }
  741.  
  742.     // release the IOleClientSite object
  743.     while(TerFont[obj].pObjSite) {
  744.        pObjSite=TerFont[obj].pObjSite;
  745.        pObjSite->lpVtbl->Release(pObjSite);
  746.     }
  747.  
  748.     return TRUE;
  749. }
  750.  
  751. /*******************************************************************************
  752.     TerOleQuerySize:
  753.     This function returns the size of the specified object storage.
  754. *******************************************************************************/
  755. BOOL TerOleQuerySize(PTERWND w, int obj, DWORD far *size)
  756. {
  757.     LPSTRCLIENTSITE pSite=(LPSTRCLIENTSITE)TerFont[obj].pObjSite;
  758.     LPSTORAGE pObjStg=pSite->pObjStg;
  759.     HRESULT result;
  760.     BYTE huge * pSaveData;
  761.     HGLOBAL hSaveData;
  762.  
  763.     (*size)=0;
  764.  
  765.     hSaveData=hOleData;         // save these global variables
  766.     pSaveData=pOleData;
  767.     hOleData=NULL;
  768.     pOleData=0;                 // set TerOlePut in query mode
  769.  
  770.     OleStream.MaxSize=0;        // initialize the size output variable
  771.     OleStream.offset=0;         // beginning offset in the buffer
  772.     result=OleConvertIStorageToOLESTREAM(pObjStg,&(OleStream.stream));
  773.     if (result!=NOERROR) {
  774.        PrintOleError(w,result);
  775.        wsprintf(TempString,"OLE data conversion error: %lx (TerOleQuerySize)",(DWORD)result);
  776.        return PrintError(w,TempString);
  777.     }
  778.  
  779.     (*size)=OleStream.MaxSize;  // buffer size
  780.  
  781.     hOleData=hSaveData;         // restore these global variables
  782.     pOleData=pSaveData;
  783.  
  784.     return TRUE;
  785. }
  786.  
  787. /*******************************************************************************
  788.     GetOleStorageData:
  789.     This function extracts the OLE storage data in a global buffer.  This
  790.     function allocates a new global buffer and leaves it locked.  The calling
  791.     fuction must unlock and free the buffer when done.
  792. *******************************************************************************/
  793. GetOleStorageData(PTERWND w,int obj)
  794. {
  795.     LPSTRCLIENTSITE pSite=(LPSTRCLIENTSITE)TerFont[obj].pObjSite;
  796.     LPSTORAGE pObjStg=pSite->pObjStg;
  797.     HRESULT result;
  798.     DWORD ObjectSize;
  799.  
  800.     // get the data size requirement and allocate memory
  801.     if (!TerOleQuerySize(w,obj,&ObjectSize) || ObjectSize==0) {
  802.         MessageBox(hTerWnd,"Error getting object size!","GetOleStorageData",MB_OK);
  803.         return FALSE;
  804.     }
  805.  
  806.     hOleData=NULL;       // initialize the buffer
  807.     pOleData=NULL;
  808.  
  809.     if (  NULL==(hOleData=GlobalAlloc(GMEM_MOVEABLE,ObjectSize))  // allocate memory for the ole data
  810.        || NULL==(pOleData=GlobalLock(hOleData)) ){
  811.         MessageBox(hTerWnd,"Ran out of memory","GetOleStorageData",MB_OK);
  812.         return FALSE;
  813.     }
  814.  
  815.     // set to object to the global buffer
  816.     OleStream.MaxSize=ObjectSize;      // size of the object to read
  817.     OleStream.offset=0;                // beginning buffer offset
  818.     result=OleConvertIStorageToOLESTREAM(pObjStg,&(OleStream.stream));
  819.     if (result!=NOERROR) {
  820.         MessageBox(hTerWnd,"Error getting object data","GetOleStorageData",MB_OK);
  821.         GlobalUnlock(hOleData);
  822.         GlobalFree(hOleData);
  823.         return FALSE;
  824.     }
  825.  
  826.     return TRUE;
  827. }
  828.  
  829. /*******************************************************************************
  830.     StrToOleStr:
  831.     Wait for an ole async operation to be over
  832. *******************************************************************************/
  833. LPOLESTR StrToOleStr(LPSTR str,LPSTR OleStr)
  834. {
  835.     #if defined(OLE2ANSI)
  836.        lstrcpy(OleStr,str);
  837.        return OleStr;
  838.     #else
  839.        int i,len;
  840.        LPOLESTR str1=(LPOLESTR)OleStr;
  841.  
  842.        len=lstrlen(str);
  843.        for (i=0;i<len;i++) str1[i]=str[i];
  844.        str1[i]=0;
  845.  
  846.        return str1;
  847.     #endif
  848. }
  849.  
  850. /*******************************************************************************
  851.     PrintOleError:
  852.     Print Ole error messages.
  853. *******************************************************************************/
  854. PrintOleError(PTERWND w, HRESULT result)
  855. {
  856.     DWORD code=(DWORD)result;
  857.     char  desc[100];
  858.     
  859.     desc[0]=0;
  860.  
  861.     if      (code==REGDB_E_CLASSNOTREG) lstrcpy(desc,"Class Not Registered");
  862.     else if (code==REGDB_E_CLASSNOTREG) lstrcpy(desc,"Share Utility Required");
  863.  
  864.     if (desc[0]!=0) wsprintf(desc,"Error Code: %lx",(DWORD)result);
  865.     
  866.     MessageBox(NULL,desc,"OLE Error",MB_OK);
  867.  
  868.     return TRUE;
  869. }
  870.  
  871. /*****************************************************************************
  872.     Implementation of IOleClientSite Interface
  873. ******************************************************************************/
  874.  
  875. /*****************************************************************************
  876.     CreateOleClientSite:
  877.     This function creates an instance of IOleClientSite interface.  The use
  878.     count for the interface is set to 1.
  879. ******************************************************************************/
  880. LPOLECLIENTSITE CreateOleClientSite(PTERWND w, int obj, LPSTORAGE pObjStg)
  881. {
  882.     LPSTRCLIENTSITE pTerSite;
  883.     LPOLECLIENTSITE pSite;
  884.  
  885.     // allocate and inititialize pTerSite
  886.     if (NULL==(pTerSite=(LPSTRCLIENTSITE )OurAlloc(sizeof(struct StrClientSite)))) return NULL;
  887.     pTerSite->count=1;                     // count for the interface
  888.     pTerSite->w=w;                         // window pointer for the pSite
  889.     pTerSite->obj=obj;                     // object id for the pSite
  890.     pTerSite->pObjStg=pObjStg;             // object IStorage
  891.     
  892.     // create IAdviseSink interface
  893.     pTerSite->pObjAdvise=CreateAdviseSink(w,obj,pObjStg,(LPOLECLIENTSITE)pTerSite);
  894.     if (!(pTerSite->pObjAdvise)) return NULL;
  895.  
  896.  
  897.     // allocate and intialize the CLIENTSITE virtual functions
  898.     pSite=(LPOLECLIENTSITE)pTerSite;
  899.     if (NULL==(pSite->lpVtbl=OurAlloc(sizeof(struct IOleClientSiteVtbl)))) return NULL;
  900.     if ( NULL==(pSite->lpVtbl->QueryInterface=(LPVOID) MakeProcInstance((FARPROC)IocsQueryInterface,hTerInst)) 
  901.       || NULL==(pSite->lpVtbl->AddRef=(LPVOID) MakeProcInstance((FARPROC)IocsAddRef,hTerInst)) 
  902.       || NULL==(pSite->lpVtbl->Release=(LPVOID) MakeProcInstance((FARPROC)IocsRelease,hTerInst)) 
  903.       || NULL==(pSite->lpVtbl->GetContainer=(LPVOID) MakeProcInstance((FARPROC)IocsGetContainer,hTerInst)) 
  904.       || NULL==(pSite->lpVtbl->OnShowWindow=(LPVOID) MakeProcInstance((FARPROC)IocsOnShowWindow,hTerInst)) 
  905.       || NULL==(pSite->lpVtbl->GetMoniker=(LPVOID) MakeProcInstance((FARPROC)IocsGetMoniker,hTerInst)) 
  906.       || NULL==(pSite->lpVtbl->RequestNewObjectLayout=(LPVOID) MakeProcInstance((FARPROC)IocsRequestNewObjectLayout,hTerInst)) 
  907.       || NULL==(pSite->lpVtbl->SaveObject=(LPVOID) MakeProcInstance((FARPROC)IocsSaveObject,hTerInst)) 
  908.       || NULL==(pSite->lpVtbl->ShowObject=(LPVOID) MakeProcInstance((FARPROC)IocsShowObject,hTerInst)) ){
  909.        MessageBox(hTerWnd,"ClientSite Creation Error!",NULL,MB_OK);
  910.        return NULL;
  911.     }
  912.  
  913.     return pSite;
  914. }
  915.  
  916. /*****************************************************************************
  917.     IocsQueryInterface: Query interface function for IOleClientSite
  918. ******************************************************************************/
  919. HRESULT STDMETHODCALLTYPE IocsQueryInterface(LPOLECLIENTSITE this,REFIID riid,LPVOID far *obj)
  920. {
  921.     LPSTRCLIENTSITE pSite=(LPSTRCLIENTSITE )this;
  922.  
  923.     (*obj)=NULL;    // set to NULL if interface not supported
  924.  
  925.     if (IsEqualIID(riid,&IID_IUnknown)) (*obj)=this;
  926.     if (IsEqualIID(riid,&IID_IOleClientSite)) (*obj)=this;
  927.     if (IsEqualIID(riid,&IID_IAdviseSink)) (*obj)=pSite->pObjAdvise;
  928.  
  929.     if (*obj) {
  930.        LPUNKNOWN far *ppUnk=(LPUNKNOWN far *)obj;
  931.        (*ppUnk)->lpVtbl->AddRef(*ppUnk);
  932.        return ResultFromScode(S_OK);
  933.     }
  934.     else return ResultFromScode(E_NOINTERFACE);
  935. }
  936.  
  937. /*****************************************************************************
  938.     IocsAddRef: AddRef function for IOleClientSite interface
  939. ******************************************************************************/
  940. ULONG STDMETHODCALLTYPE IocsAddRef(LPOLECLIENTSITE this)
  941. {
  942.     LPSTRCLIENTSITE pSite=(LPSTRCLIENTSITE )this;
  943.  
  944.     pSite->count++;
  945.     return pSite->count;
  946. }
  947. /*****************************************************************************
  948.     IocsRelease: Release function for the IOleClientSite interface
  949. ******************************************************************************/
  950. ULONG STDMETHODCALLTYPE IocsRelease(LPOLECLIENTSITE this)
  951. {
  952.     int obj;
  953.     PTERWND w;
  954.  
  955.  
  956.     LPSTRCLIENTSITE pSite=(LPSTRCLIENTSITE )this;
  957.     w=pSite->w;
  958.     obj=pSite->obj;
  959.  
  960.     pSite->count--;
  961.  
  962.     if (pSite->count==0) {      // unallocate pSite interface
  963.  
  964.        // reduce the ref count for IAdviseSink added during creation
  965.        if (pSite->pObjAdvise) pSite->pObjAdvise->lpVtbl->Release(pSite->pObjAdvise);
  966.  
  967.        #if !defined(WIN32)
  968.           FreeProcInstance((FARPROC)(this->lpVtbl->QueryInterface));
  969.           FreeProcInstance((FARPROC)(this->lpVtbl->AddRef));
  970.           FreeProcInstance((FARPROC)(this->lpVtbl->Release));
  971.           FreeProcInstance((FARPROC)(this->lpVtbl->GetContainer));
  972.           FreeProcInstance((FARPROC)(this->lpVtbl->OnShowWindow));
  973.           FreeProcInstance((FARPROC)(this->lpVtbl->GetMoniker));
  974.           FreeProcInstance((FARPROC)(this->lpVtbl->RequestNewObjectLayout));
  975.           FreeProcInstance((FARPROC)(this->lpVtbl->SaveObject));
  976.           FreeProcInstance((FARPROC)(this->lpVtbl->ShowObject));
  977.        #endif
  978.  
  979.        OurFree(this->lpVtbl);
  980.        OurFree(this);
  981.  
  982.        TerFont[obj].pObjSite=NULL;      // object deleted
  983.  
  984.        return 0;
  985.     }
  986.  
  987.     return pSite->count;
  988. }
  989.  
  990. /*****************************************************************************
  991.     IocsSaveObject: SaveObject function for the IOleClientSite interface
  992.     This function brings the data from the IPersistStorage to the IStorage
  993.     interface.
  994. ******************************************************************************/
  995. HRESULT STDMETHODCALLTYPE IocsSaveObject(LPOLECLIENTSITE this)
  996. {
  997.     PTERWND w;
  998.     LPSTRCLIENTSITE pSite=(LPSTRCLIENTSITE )this;
  999.     LPOLEOBJECT pObject;
  1000.     LPPERSISTSTORAGE lpPS;
  1001.     LPSTORAGE lpStg;
  1002.     HRESULT result;
  1003.  
  1004.     w=pSite->w;                  // window data pointer
  1005.  
  1006.     pObject=TerFont[pSite->obj].pObject; // object pointer
  1007.     lpStg=pSite->pObjStg;                 // object storage
  1008.  
  1009.     if (NOERROR!=(result=pObject->lpVtbl->QueryInterface(pObject,&IID_IPersistStorage,(LPVOID far *)&lpPS))) {
  1010.        MessageBox(hTerWnd,"Error retrieving the OLE storage","IocsSaveObject",MB_OK);
  1011.        return result;
  1012.     }
  1013.     
  1014.     if (NOERROR!=(result=OleSave(lpPS,lpStg,TRUE))) {
  1015.        MessageBox(hTerWnd,"Error saving the OLE object","IocsSaveObject",MB_OK);
  1016.        return result;
  1017.     }
  1018.     
  1019.     lpPS->lpVtbl->SaveCompleted(lpPS,NULL);   
  1020.     lpPS->lpVtbl->Release(lpPS);            // decrement for QueryInterface
  1021.  
  1022.     TerArg.modified++;                       // file modified
  1023.  
  1024.     return ResultFromScode(S_OK);
  1025. }
  1026.  
  1027. /*****************************************************************************
  1028.     Unimplemented functions for the IOleClientSite interface
  1029. ******************************************************************************/
  1030. HRESULT STDMETHODCALLTYPE IocsGetContainer(LPOLECLIENTSITE this,LPOLECONTAINER far * ppContainer)
  1031. {
  1032.    (*ppContainer)=NULL;
  1033.    return ResultFromScode(E_NOTIMPL);
  1034. }
  1035. HRESULT STDMETHODCALLTYPE IocsOnShowWindow(LPOLECLIENTSITE this,BOOL show)
  1036. {
  1037.    return ResultFromScode(S_OK);
  1038. }
  1039. HRESULT STDMETHODCALLTYPE IocsGetMoniker(LPOLECLIENTSITE this,DWORD dwAssign,DWORD dwWhichMoniker,LPMONIKER far * ppmk)
  1040. {
  1041.    (*ppmk)=NULL;
  1042.    return ResultFromScode(E_NOTIMPL);
  1043. }
  1044. HRESULT STDMETHODCALLTYPE IocsRequestNewObjectLayout(LPOLECLIENTSITE this)
  1045. {
  1046.    return ResultFromScode(E_NOTIMPL);
  1047. }
  1048. HRESULT STDMETHODCALLTYPE IocsShowObject(LPOLECLIENTSITE this)
  1049. {
  1050.    return NOERROR;
  1051. }
  1052.  
  1053. /*****************************************************************************
  1054.     Implementation of IAdviseSink Interface
  1055. ******************************************************************************/
  1056.  
  1057. /*****************************************************************************
  1058.     CreateAdviseSink:
  1059.     This function creates an instance of IAdviseSink interface.  The use
  1060.     count for the interface is set to 1.
  1061. ******************************************************************************/
  1062. LPADVISESINK CreateAdviseSink(PTERWND w, int obj, LPSTORAGE pObjStg, LPOLECLIENTSITE pObjSite)
  1063. {
  1064.     LPSTRADVISESINK pTerAdvise;
  1065.     LPADVISESINK pAdvise;
  1066.  
  1067.     // allocate and inititialize pTerSite
  1068.     if (NULL==(pTerAdvise=(LPSTRADVISESINK )OurAlloc(sizeof(struct StrAdviseSink)))) return NULL;
  1069.     pTerAdvise->count=1;                     // count for the interface
  1070.     pTerAdvise->w=w;                         // window pointer for the pAdvise
  1071.     pTerAdvise->obj=obj;                   // object id for the pAdvise
  1072.     pTerAdvise->pObjStg=pObjStg;             // object IStorage
  1073.     pTerAdvise->pObjSite=pObjSite;           // client site for the object
  1074.  
  1075.     // allocate and intialize the CLIENTSITE virtual functions
  1076.     pAdvise=(LPADVISESINK)pTerAdvise;
  1077.     if (NULL==(pAdvise->lpVtbl=OurAlloc(sizeof(struct IAdviseSinkVtbl)))) return NULL;
  1078.     if ( NULL==(pAdvise->lpVtbl->QueryInterface=(LPVOID) MakeProcInstance((FARPROC)IasQueryInterface,hTerInst)) 
  1079.       || NULL==(pAdvise->lpVtbl->AddRef=(LPVOID) MakeProcInstance((FARPROC)IasAddRef,hTerInst)) 
  1080.       || NULL==(pAdvise->lpVtbl->Release=(LPVOID) MakeProcInstance((FARPROC)IasRelease,hTerInst)) 
  1081.       || NULL==(pAdvise->lpVtbl->OnDataChange=(LPVOID) MakeProcInstance((FARPROC)IasOnDataChange,hTerInst)) 
  1082.       || NULL==(pAdvise->lpVtbl->OnViewChange=(LPVOID) MakeProcInstance((FARPROC)IasOnViewChange,hTerInst)) 
  1083.       || NULL==(pAdvise->lpVtbl->OnRename=(LPVOID) MakeProcInstance((FARPROC)IasOnRename,hTerInst)) 
  1084.       || NULL==(pAdvise->lpVtbl->OnSave=(LPVOID) MakeProcInstance((FARPROC)IasOnSave,hTerInst)) 
  1085.       || NULL==(pAdvise->lpVtbl->OnClose=(LPVOID) MakeProcInstance((FARPROC)IasOnClose,hTerInst)) ){
  1086.        MessageBox(hTerWnd,"AdviseSink Creation Error!",NULL,MB_OK);
  1087.        return NULL;
  1088.     }
  1089.  
  1090.     return pAdvise;
  1091. }
  1092.  
  1093. /*****************************************************************************
  1094.     IasQueryInterface: Query interface function for IAdviseSink.
  1095.     This function simply delegates to the IOleClientSite::QueryInterface
  1096. ******************************************************************************/
  1097. HRESULT STDMETHODCALLTYPE IasQueryInterface(LPADVISESINK this,REFIID riid,LPVOID far *obj)
  1098. {
  1099.     LPSTRADVISESINK pAdvise=(LPSTRADVISESINK )this;
  1100.     LPOLECLIENTSITE pObjSite=pAdvise->pObjSite;
  1101.  
  1102.     return pObjSite->lpVtbl->QueryInterface(pObjSite,riid,obj);
  1103. }
  1104.  
  1105. /*****************************************************************************
  1106.     IasAddRef: AddRef function for IAdviseSink interface
  1107. ******************************************************************************/
  1108. ULONG STDMETHODCALLTYPE IasAddRef(LPADVISESINK this)
  1109. {
  1110.     LPSTRADVISESINK pAdvise=(LPSTRADVISESINK )this;
  1111.  
  1112.     pAdvise->count++;
  1113.     return pAdvise->count;
  1114. }
  1115.  
  1116. /*****************************************************************************
  1117.     IasRelease: Release function for the IAdviseSink interface
  1118. ******************************************************************************/
  1119. ULONG STDMETHODCALLTYPE IasRelease(LPADVISESINK this)
  1120. {
  1121.     LPSTRADVISESINK pAdvise=(LPSTRADVISESINK )this;
  1122.     LPOLECLIENTSITE pObjSite=pAdvise->pObjSite;
  1123.     LPSTRCLIENTSITE pSite=(LPSTRCLIENTSITE )pObjSite;
  1124.  
  1125.     pAdvise->count--;
  1126.  
  1127.     if (pAdvise->count==0) {      // unallocate pAdvise interface
  1128.        #if !defined(WIN32)
  1129.           FreeProcInstance((FARPROC)(this->lpVtbl->QueryInterface));
  1130.           FreeProcInstance((FARPROC)(this->lpVtbl->AddRef));
  1131.           FreeProcInstance((FARPROC)(this->lpVtbl->Release));
  1132.           FreeProcInstance((FARPROC)(this->lpVtbl->OnDataChange));
  1133.           FreeProcInstance((FARPROC)(this->lpVtbl->OnViewChange));
  1134.           FreeProcInstance((FARPROC)(this->lpVtbl->OnRename));
  1135.           FreeProcInstance((FARPROC)(this->lpVtbl->OnSave));
  1136.           FreeProcInstance((FARPROC)(this->lpVtbl->OnClose));
  1137.        #endif
  1138.        OurFree(this->lpVtbl);
  1139.        OurFree(this);
  1140.  
  1141.        // reset the pointer in the IOleClientSite interface
  1142.        if (pSite) pSite->pObjAdvise=NULL;
  1143.  
  1144.        return 0;
  1145.     }
  1146.  
  1147.     return pAdvise->count;
  1148. }
  1149.  
  1150. /*****************************************************************************
  1151.     IasOnViewChange: OnViewChange function for the IAdviseSink interface
  1152. ******************************************************************************/
  1153. void STDMETHODCALLTYPE IasOnViewChange(LPADVISESINK this, DWORD dwAspect, LONG index) 
  1154. {
  1155.     LPSTRADVISESINK pAdvise=(LPSTRADVISESINK )this;
  1156.     LPOLECLIENTSITE pObjSite=pAdvise->pObjSite;
  1157.     LPSTRCLIENTSITE pSite=(LPSTRCLIENTSITE )pObjSite;
  1158.     int obj,i;
  1159.     LPOLEOBJECT pObject;
  1160.     LPDATAOBJECT pDataObject;
  1161.     PTERWND w;
  1162.     STGMEDIUM med;
  1163.     struct StrFont font;
  1164.     int    FontCharWidth[256];
  1165.     FORMATETC OleFmt;
  1166.  
  1167.     // retrieve the current ole item
  1168.     w=pSite->w;
  1169.     obj=pSite->obj;                         // item number in the font table
  1170.     pObject=TerFont[obj].pObject;
  1171.  
  1172.     // get the IDataObject Interface
  1173.     if (NOERROR!=(pObject->lpVtbl->QueryInterface(pObject,&IID_IDataObject,(LPVOID far *)&pDataObject))) {
  1174.        PrintError(w,"Error retrieving data object(IasOnViewChange)");
  1175.        return;
  1176.     }
  1177.  
  1178.     // get the metafile picture representation of the data
  1179.     OleFmt.cfFormat=CF_METAFILEPICT;
  1180.     OleFmt.ptd=NULL;
  1181.     OleFmt.dwAspect=DVASPECT_CONTENT;
  1182.     OleFmt.lindex=-1;
  1183.     OleFmt.tymed=TYMED_MFPICT;
  1184.     if (NOERROR!=(pDataObject->lpVtbl->GetData(pDataObject,&OleFmt,&med)) || med.tymed!=TYMED_MFPICT) {
  1185.        PrintError(w,"Error retrieving presentation data(IasOnViewChange)");
  1186.        return;
  1187.     }
  1188.  
  1189.     // Incorporate this data into our font table
  1190.     font=TerFont[obj];                       // make a copy of the exiting font structure
  1191.     FarMove(TerFont[obj].CharWidth,FontCharWidth,sizeof(FontCharWidth));
  1192.  
  1193.     InitTerObject(w,obj);                    // freeup this slot
  1194.     if (TerCreateMetafile(w,(HGLOBAL)(med.u.hGlobal),obj)<0) {
  1195.        TerFont[obj]=font;                    // restore the previous structure
  1196.        ReleaseStgMedium(&med);                      // release data handle
  1197.        return;
  1198.     }
  1199.     
  1200.     ReleaseStgMedium(&med);                      // release data handle
  1201.  
  1202.     // Apply the previous values
  1203.     TerFont[obj].ObjectType=font.ObjectType;
  1204.     TerFont[obj].pObject=font.pObject;
  1205.     TerFont[obj].pObjSite=font.pObjSite;
  1206.     TerFont[obj].ObjectSize=font.ObjectSize;
  1207.     TerFont[obj].AuxId=font.AuxId;
  1208.     TerFont[obj].style=font.style;
  1209.  
  1210.     // Apply the previous size
  1211.     if (TerFont[obj].ObjectType==OBJ_EMBED_INSERT) {  // item being inserted
  1212.         TerFont[obj].ObjectType=OBJ_EMBED;
  1213.         TerInsertObjectId(hTerWnd,obj,TRUE);        // this is a new object to be inserted
  1214.     }
  1215.     else {
  1216.         TerFont[obj].PictHeight=font.PictHeight;
  1217.         TerFont[obj].PictWidth=font.PictWidth;
  1218.         TerFont[obj].height=font.height;
  1219.         for (i=0;i<256;i++) TerFont[obj].CharWidth[i]=FontCharWidth[i];
  1220.         XlateSizeForPrt(w,obj);          // convert size to printer resolution
  1221.         
  1222.         if (font.hMeta) DeleteMetaFile(font.hMeta); // delete the previous metafile
  1223.     }
  1224.  
  1225.     //** reset the text map as the contents of the picture has changed
  1226.     TerArg.modified++;                              // file modified
  1227.     for (i=0;i<TotalSegments;i++) DeleteTextSeg(w,i);
  1228.     TotalSegments=0;
  1229.     PaintTer(w);
  1230.  
  1231. }
  1232.  
  1233. /*****************************************************************************
  1234.     Unimplemented functions for the IAdviseSink interface
  1235. ******************************************************************************/
  1236. void STDMETHODCALLTYPE IasOnSave(LPADVISESINK this) {}
  1237. void STDMETHODCALLTYPE IasOnClose(LPADVISESINK this) {}
  1238. void STDMETHODCALLTYPE IasOnDataChange(LPADVISESINK this, FORMATETC far * fmt, STGMEDIUM far * med) {}
  1239. void STDMETHODCALLTYPE IasOnRename(LPADVISESINK this, LPMONIKER pmk) {}
  1240.