
/****************************** Module Header ******************************\
* Module Name: MAIN.C
*
* PURPOSE: WinMain, WEP and some other misc routines
*
* Created: 1991
*
* Copyright (c) 1990, 1991  Microsoft Corporation
*
* History:
*   Srinik   (04/01/91)  Pulled some routines, into this, from ole.c.
*   curts    Create portable version for win16/32.
*
\***************************************************************************/

#include <windows.h>

#include "dll.h"

#ifndef WF_WLO
#define WF_WLO  0x8000
#endif

// ordinal number new win31 API IsTask
#define ORD_IsTask  320

#define NUM_DLL     30  /* space for this many DLL_ENTRYs is created on */
			/* each alloc/realloc */

OLECLIPFORMAT   cfOwnerLink     = 0;     // global variables for clip frmats
OLECLIPFORMAT   cfObjectLink    = 0;
OLECLIPFORMAT   cfLink          = 0;
OLECLIPFORMAT   cfNative        = 0;
OLECLIPFORMAT   cfBinary        = 0;
OLECLIPFORMAT   cfFileName      = 0;
OLECLIPFORMAT   cfNetworkName   = 0;

ATOM            aStdHostNames;
ATOM            aStdTargetDevice ;
ATOM            aStdDocDimensions;
ATOM            aStdDocName;
ATOM            aStdColorScheme;
ATOM            aNullArg = 0;
ATOM            aSave;
ATOM            aChange;
ATOM            aClose;
ATOM            aSystem;
ATOM            aOle;
ATOM            aClipDoc;
ATOM            aPackage;

// Used in work around for MSDraw bug
ATOM            aMSDraw;

extern LPCLIENTDOC  lpHeadDoc;
extern LPCLIENTDOC  lpTailDoc;

extern RENDER_ENTRY stdRender[];

HANDLE          hInstDLL;

/* HANDLE   hDllTable;          !!! Add this when bug in WEP is fixed */
DLL_ENTRY   lpDllTable[NUM_DLL]; //!!! change this when WEP bug is fixed
DWORD       dllTableSize;
int         iLast = 0;
int         iMax = NUM_DLL -1;
int         iUnloadableDll =  0; // index to handler than can be freed up

char        packageClass[] = "Package";

// For QuerySize() API & methods.
extern  OLESTREAMVTBL  dllStreamVtbl;
extern  CLIENTDOC      lockDoc;

#ifdef FIREWALLS
BOOL        bShowed = FALSE;
char        szDebugBuffer[80];
short       ole_flags;

void FARINTERNAL    ShowVersion (void);
void FARINTERNAL    SetOleFlags(void);
#endif

// LOWWORD - BYTE 0 major verision, BYTE1 minor version,
// HIWORD reserved

DWORD  dwOleVer = 0x0901L;  // change this when we want to update dll version
			    // number

WORD   wReleaseVer = 0x0001;  // This is used while object is being saved to
			      // file. There is no need to change this value
			      // whenever we change ole dll version number

static BOOL  bLibInit = FALSE;



HANDLE  hModule;

#define MAX_HIMETRIC    0x7FFF

int     maxPixelsX = MAX_HIMETRIC;
int     maxPixelsY = MAX_HIMETRIC;
void    SetMaxPixel (void);

VOID FAR PASCAL WEP (int);

#ifdef WIN16                        // begin WIN16
BOOL    bProtMode;
BOOL    bWLO = FALSE;
WORD    wWinVer;
#pragma alloc_text(WEP_TEXT, WEP)

FARPROC lpfnIsTask = NULL;          // the API IsTask() became available from
				    // win31 onwards, hence we are trying to
				    // get it's address through GetProcAddress
#endif                              // end WIN16


//////////////////////////////////////////////////////////////////////////////
//
//  int FAR PASCAL LibMain (hInst, wDataSeg, cbHeapSize, lpszCmdLine)
//
//  The main library entry point. This routine is called when the library
//  is loaded.
//
//  Arguments:
//
//      hInst       -   dll's instance handle
//      wDataSeg    -   DS register value
//      cbHeapSize  -   heap size defined def file
//      lpszCmdLine -   command line info
//
//  Returns:
//
//      0   -   failure
//      1   -   success
//
//  Effects:
//
//////////////////////////////////////////////////////////////////////////////

#ifdef WIN16
int APIENTRY LibMain(
   HANDLE  hInst,
   WORD    wDataSeg,
   WORD    cbHeapSize,
   LPSTR   lpszCmdLine
#endif

#ifdef WIN32
BOOL LibMain(
   HANDLE hInst,
   ULONG Reason,
   PCONTEXT Context
#endif  // WIN32

){
    WNDCLASS  wc;
    int     i;
#ifdef WIN32
    char szDocClass[] = "OleDocWndClass" ;
    char szSrvrClass[] = "OleSrvrWndClass" ;
#endif

    Puts("LibMain");

#ifdef  FIREWALLS
    SetOleFlags();
#endif

#ifdef WIN32                        // begin WIN32
    UNREFERENCED_PARAMETER(Context);
    if (Reason == DLL_PROCESS_DETACH)
    {
	WEP(0);
   UnregisterClass (szDocClass, hInst) ;
   UnregisterClass (szSrvrClass, hInst) ;
	return TRUE;
    }
    else if (Reason != DLL_PROCESS_ATTACH)
	return TRUE;
#endif                              // end WIN32

    bLibInit  = TRUE;
    hInstDLL  = hInst;
    hModule = GetModuleHandle ("OLECLI");

#ifdef WIN16                        // begin WIN16
    bProtMode = (BOOL) (GetWinFlags() & WF_PMODE);
    bWLO      = (BOOL) (GetWinFlags() & WF_WLO);
    wWinVer   = (WORD) GetVersion();
#endif                              // end WIN16

    // REGISTER LINK FORMAT

    cfObjectLink    = (OLECLIPFORMAT)RegisterClipboardFormat("ObjectLink");
    cfLink          = (OLECLIPFORMAT)RegisterClipboardFormat("Link");
    cfOwnerLink     = (OLECLIPFORMAT)RegisterClipboardFormat("OwnerLink");
    cfNative        = (OLECLIPFORMAT)RegisterClipboardFormat("Native");
    cfBinary        = (OLECLIPFORMAT)RegisterClipboardFormat("Binary");
    cfFileName      = (OLECLIPFORMAT)RegisterClipboardFormat("FileName");
    cfNetworkName   = (OLECLIPFORMAT)RegisterClipboardFormat("NetworkName");

    if (!(cfObjectLink && cfOwnerLink && cfNative && cfLink))
	return 0;

    // SET UP OLEWNDCLASS
    wc.style        = 0;
    wc.lpfnWndProc  = DocWndProc;
    wc.cbClsExtra   = 0;
    wc.cbWndExtra   = sizeof(LONG_PTR);     //we are storing longs
    wc.hInstance    = hInst;
    wc.hIcon        = NULL;
    wc.hCursor      = NULL;
    wc.hbrBackground= NULL;
    wc.lpszMenuName =  NULL;
    wc.lpszClassName= szDocClass;
    if (!RegisterClass(&wc))
	     return 0;

    wc.lpfnWndProc = (WNDPROC)SrvrWndProc;
    wc.lpszClassName = szSrvrClass ;

    if (!RegisterClass(&wc))
	return 0;
/*
    // !!! Add this when bug in WEP is fixed.
    // Allocate memory for DLL table
    dllTableSize = NUM_DLL * sizeof(DLL_ENTRY);
    if (!(hDllTable = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT,
			    dllTableSize)))
	return 0;

    if (!(lpDllTable = (DLL_ENTRY FAR *) GlobalLock (hDllTable)))
	return 0;
*/

    // !!! remove the following when WEP bug is fixed
    for (i = 0; i < NUM_DLL; i++)
	lpDllTable[i].aDll = (ATOM)0;

    // !!! BEGIN hack for Pbrush.

    lpDllTable[0].hDll                  = NULL;
    lpDllTable[0].aDll                  = GlobalAddAtom ((LPSTR) "ole");
    lpDllTable[0].Load                  = PbLoadFromStream;
    lpDllTable[0].Clip                  = PbCreateFromClip;
    lpDllTable[0].Link                  = PbCreateLinkFromClip;
    lpDllTable[0].Create                = PbCreate;
    lpDllTable[0].CreateFromTemplate    = PbCreateFromTemplate;
    lpDllTable[0].CreateFromFile        = PbCreateFromFile;
    lpDllTable[0].CreateLinkFromFile    = PbCreateLinkFromFile;
    lpDllTable[0].CreateInvisible       = PbCreateInvisible;


    // !!! END hack for pbrush

    // For ObjectSize API
    dllStream.lpstbl      = (LPOLESTREAMVTBL) &dllStreamVtbl;
    dllStream.lpstbl->Put = DllPut;

    // add the atoms required.
    aStdDocName       = GlobalAddAtom ((LPSTR)"StdDocumentName");
    aSave             = GlobalAddAtom ((LPSTR)"Save");
    aChange           = GlobalAddAtom ((LPSTR)"Change");
    aClose            = GlobalAddAtom ((LPSTR)"Close");
    aSystem           = GlobalAddAtom ((LPSTR)"System");
    aOle              = GlobalAddAtom ((LPSTR)"OLEsystem");
    aPackage          = GlobalAddAtom ((LPSTR) packageClass);

    // Used in work around for MSDraw bug
    aMSDraw           = GlobalAddAtom ((LPSTR) "MSDraw");

    // clipboard document name atom
    aClipDoc          = GlobalAddAtom ((LPSTR)"Clipboard");

    stdRender[0].aClass = GlobalAddAtom ("METAFILEPICT");
    stdRender[1].aClass = GlobalAddAtom ("DIB");
    stdRender[2].aClass = GlobalAddAtom ("BITMAP");
    stdRender[3].aClass = GlobalAddAtom ("ENHMETAFILE");

    SetMaxPixel();

#ifdef WIN16                        // begin WIN16
    if (wWinVer != 0x0003) {
	HANDLE  hModule;

	if (hModule = GetModuleHandle ("KERNEL"))
	    lpfnIsTask = GetProcAddress (hModule,
				(LPSTR) MAKELONG (ORD_IsTask, 0));
    }

    if (cbHeapSize != 0)
	UnlockData(0);
#endif                              // end WIN16

    return 1;
}



//////////////////////////////////////////////////////////////////////////////
//
//  VOID FAR PASCAL WEP (nParameter)
//
//  Called just before the library is being unloaded. Delete all the atoms
//  added by this dll and also frees up all unloaded handler dlls.
//
//  Arguments:
//
//      nParameter  -   Termination code
//
//  Returns:
//
//      none
//
//  Effects:
//
//////////////////////////////////////////////////////////////////////////////


VOID FAR PASCAL WEP (int nParameter)
{
    int i;


    Puts("LibExit");

#ifdef WIN32                        // begin WIN32
	UNREFERENCED_PARAMETER(nParameter);
	DEBUG_OUT ("---L&E DLL EXIT---\n",0)
#endif                              // end WIN32
    // case when the DLLs are missing

    if (!bLibInit)
	return;

#ifdef WIN16                        // begin WIN16
    if (nParameter == WEP_SYSTEM_EXIT)
	DEBUG_OUT ("---L&E DLL EXIT on system exit---",0)
    else if (nParameter == WEP_FREE_DLL)
	DEBUG_OUT ("---L&E DLL EXIT---\n",0)
    else
	return;
#endif                              // end WIN16


    // Delete atoms added by us

    for (i = 0; i < NUM_RENDER; i++) {
	if (stdRender[i].aClass)
	    GlobalDeleteAtom (stdRender[i].aClass);
    }

    if (aStdDocName)
	GlobalDeleteAtom (aStdDocName);
    if (aSave)
	GlobalDeleteAtom (aSave);
    if (aChange)
	GlobalDeleteAtom (aChange);
    if (aClose)
	GlobalDeleteAtom (aClose);
    if (aSystem)
	GlobalDeleteAtom (aSystem);
    if (aOle)
	GlobalDeleteAtom (aOle);
    if (aPackage)
	GlobalDeleteAtom (aPackage);
    if (aClipDoc)
	GlobalDeleteAtom (aClipDoc);
    if (aMSDraw)
	GlobalDeleteAtom (aMSDraw);

    // Free handler dlls if there are any still loaded. Entry 0 is used for
    // Pbrush handler which is part of this dll.


    for (i = 0; i <= iLast; i++) {
	if (lpDllTable[i].aDll)
	    GlobalDeleteAtom (lpDllTable[i].aDll);

	if (lpDllTable[i].hDll)
	    FreeLibrary (lpDllTable[i].hDll);
    }


#ifdef FIREWALLS
    ASSERT(!lpHeadDoc, "Some client doc structures are not deleted");
    ASSERT(!lockDoc.lpHeadObj, "Some servers are left in a locked state");
#endif

/* !!! Add this when bug in WEP is fixed

    if (lpDllTable)
	GlobalUnlock (hDllTable);

    if (hDllTable)
	GlobalFree (hDllTable);
*/
}


//////////////////////////////////////////////////////////////////////////////
//
//  void FARINTERNAL SetOleFlags()
//
//  Sets the debug level flags for controlling the level of debug information
//  on the comm terminal. This will be included only in the debug version.
//
//  Arguments:
//
//      none
//
//  Returns:
//
//      none
//
//  Effects:
//
//////////////////////////////////////////////////////////////////////////////

#ifdef  FIREWALLS

void FARINTERNAL SetOleFlags()
{

    char    buffer[80];

    if(GetProfileString ("OLE",
	"Puts","", (LPSTR)buffer, 80))
	ole_flags = DEBUG_PUTS;
    else
	ole_flags = 0;


    if(GetProfileString ("OLE",
	"DEBUG_OUT","", (LPSTR)buffer, 80))
	ole_flags |= DEBUG_DEBUG_OUT;


    if(GetProfileString ("OLE",
	"MESSAGEBOX","", (LPSTR)buffer, 80))
	ole_flags |= DEBUG_MESSAGEBOX;

}



//////////////////////////////////////////////////////////////////////////////
//
//  void FARINTERNAL ShowVersion (void)
//
//  Displays version, date, time and copyright info in client app's window.
//  Called by all the object create functions after checking the flag bShowed.
//  This will be included only in the debug version.
//
//  Arguments:
//
//      none
//
//  Returns:
//
//      none
//
//  Effects:
//
//      sets bShowed
//
//////////////////////////////////////////////////////////////////////////////

void FARINTERNAL ShowVersion ()
{

    if (!bShowed && (ole_flags & DEBUG_MESSAGEBOX)) {
	MessageBox (NULL, "\
		       VER: 1.09.000\n\
		    TIME: 00:00:00\n\
		   DATE: 02/01/1992\n\
	 Copyright (c) 1990, 1991 Microsoft Corp.\n\
		  All Rights Reserved.",
      "Ole Client Library",
      MB_OK | MB_TASKMODAL);
	bShowed = TRUE;
    }
}

#endif




int FARINTERNAL LoadDll (LPCSTR   lpClass)
{
    char        str[MAX_STR];
    char        str1[MAX_STR];
    ATOM        aDll = (ATOM)0;
    int         index;
    int         iEmpty;
    BOOL        found = FALSE;
    HANDLE      hDll;
#ifdef WIN16
    int         refcnt;
#endif
    LONG        cb = MAX_STR;

    if (!lstrcmpi (lpClass, "Pbrush"))
	return 0;

    lstrcpy (str, lpClass);
    lstrcat (str, "\\protocol\\StdFileEditing\\handler32");
    if (RegQueryValue (HKEY_CLASSES_ROOT, str, str1, &cb))
	return INVALID_INDEX;

    if (aDll = GlobalFindAtom (str1)) {
	for (index = 1; index <= iLast; index++) {
	    if (lpDllTable[index].aDll == aDll) { // Dll already loaded
		lpDllTable[index].cObj ++;

		if (index == iUnloadableDll)  {
		    // since the object count is not zero anymore, this
		    // handler can not be freed up.
		    iUnloadableDll = 0;
		}

		return index;
	    }
	}
    }

    aDll = GlobalAddAtom (str1);

    // Look for an empty entry
    for (iEmpty = 1; iEmpty <= iLast; iEmpty++) {
	if (!lpDllTable[iEmpty].aDll) {
	    found = TRUE;
	    break;
	}
    }

    if (iEmpty > iMax)
	goto errLoad;
/*
    if (!found) {// no empty entry exists create a new one if necessary.
	if (iEmpty > iMax) {
	    dllTableSize += (blockSize = NUM_DLL * sizeof(DLL_ENTRY));
	    hTable = GlobalReAlloc (hDllTable, dllTableSize,
				GMEM_MOVEABLE | GMEM_ZEROINIT);
	    if (hTable == hDllTable)
		iMax += NUM_DLL;
	    else {
		dllTableSize -= blockSize;
		iEmpty = INVALID_INDEX;
	    }
	}
    }
*/
#ifdef WIN16
    // !!! reference count of OLECLI is increasing by 2 when the handlers are
    // are loaded, looks like windows bug. Following is a temporary fix.

    refcnt = GetModuleUsage (hModule);
    hDll = LoadLibrary ((LPSTR) str1);
    refcnt = (GetModuleUsage (hModule) - refcnt);

    while (refcnt > 1) {
	FreeModule (hModule);
	refcnt--;
    }
#endif

#ifdef WIN32
    hDll = LoadLibrary ((LPSTR) str1);
#endif

    if (MAPVALUE(hDll < 32, !hDll))
	goto errLoad;

    if (!(lpDllTable[iEmpty].Load = (_LOAD)GetProcAddress(hDll,
					  "DllLoadFromStream")))
	goto errLoad;

    if (!(lpDllTable[iEmpty].Clip = (_CLIP)GetProcAddress (hDll,
					    "DllCreateFromClip")))
	goto errLoad;

    if (!(lpDllTable[iEmpty].Link = (_LINK)GetProcAddress (hDll,
					    "DllCreateLinkFromClip")))
	goto errLoad;

    if (!(lpDllTable[iEmpty].CreateFromTemplate = (_CREATEFROMTEMPLATE)
					     GetProcAddress (hDll,
					    "DllCreateFromTemplate")))
	goto errLoad;

    if (!(lpDllTable[iEmpty].Create = (_CREATE)GetProcAddress (hDll,
					  "DllCreate")))
	goto errLoad;

    if (!(lpDllTable[iEmpty].CreateFromFile = (_CREATEFROMFILE)GetProcAddress (hDll,
						    "DllCreateFromFile")))
	goto errLoad;

    if (!(lpDllTable[iEmpty].CreateLinkFromFile = (_CREATELINKFROMFILE)GetProcAddress (hDll,
					    "DllCreateLinkFromFile")))
	goto errLoad;

    lpDllTable[iEmpty].CreateInvisible = (_CREATEINVISIBLE)GetProcAddress (hDll,
					    "DllCreateInvisible");

    lpDllTable[iEmpty].aDll = aDll;
    lpDllTable[iEmpty].cObj = 1;
    lpDllTable[iEmpty].hDll = hDll;
    if (iEmpty > iLast)
	iLast++;
    return iEmpty;

errLoad:
    if (aDll)
	GlobalDeleteAtom (aDll);
    if (MAPVALUE(hDll >= 32, !hDll))
	FreeLibrary (hDll);
    return INVALID_INDEX;
}


// unload the the handler that can be free up (whose object count is NULL)

void FARINTERNAL UnloadDll ()
{
    if (!iUnloadableDll)
	return;

    if (iUnloadableDll == iLast)
	iLast--;

    if (lpDllTable[iUnloadableDll].aDll)
	GlobalDeleteAtom (lpDllTable[iUnloadableDll].aDll);
    lpDllTable[iUnloadableDll].aDll = (ATOM)0;
    FreeLibrary (lpDllTable[iUnloadableDll].hDll);
    lpDllTable[iUnloadableDll].hDll = NULL;

    iUnloadableDll = 0;
}


//
// Reduce the object count of the handler, refered to by the index, by one.
// If the object count becomes NULL, free up the handler that is ready to be
// freed (refered to by index iUnloadableDll), and then make this handler the
// freeable one.
//
// As you can see we are trying to implement a simple mechanism of caching.
//

void FARINTERNAL DecreaseHandlerObjCount (int iTable)
{
    if (!iTable)
	return;

    if (iTable != INVALID_INDEX) {
	ASSERT (lpDllTable[iTable].cObj, "Handler Obj count is already NULL");
	if (!--lpDllTable[iTable].cObj) {
	    UnloadDll ();
	    iUnloadableDll = iTable;
	}
    }
}



/***************************** Public  Function ****************************\
*
* OLESTATUS FARINTERNAL CreatePictFromClip (lpclient, lhclientdoc, lpobjname, lplpoleobject, optRender, cfFormat, lpClass, ctype)
*
*  CreatePictFromClip: This function creates the LP to an object
*  from the clipboard.  It will try to create a static picture object if
*  it understands any rendering formats on the clipboard. Currently, it
*  understands only bitmaps and metafiles.
*
* Effects:
*
* History:
* Wrote it.
\***************************************************************************/

OLESTATUS FARINTERNAL CreatePictFromClip (
   LPOLECLIENT         lpclient,
   LHCLIENTDOC         lhclientdoc,
   LPSTR               lpobjname,
   LPOLEOBJECT FAR *   lplpobj,
   OLEOPT_RENDER       optRender,
   OLECLIPFORMAT       cfFormat,
   LPSTR               lpClass,
   LONG                objType
){
    OLESTATUS   retVal = OLE_ERROR_OPTION;

    *lplpobj = NULL;

    if (optRender == olerender_none)
	return OLE_OK;
    else if (optRender == olerender_format) {
	switch (cfFormat) {
	    case 0:
		return OLE_ERROR_FORMAT;

	    case CF_ENHMETAFILE:
		return EmfPaste (lpclient, lhclientdoc, lpobjname,
			    lplpobj, objType);

	    case CF_METAFILEPICT:
		return MfPaste (lpclient, lhclientdoc, lpobjname,
			    lplpobj, objType);

	    case CF_DIB:
		return DibPaste (lpclient, lhclientdoc, lpobjname,
			    lplpobj, objType);

	    case CF_BITMAP:
		return BmPaste (lpclient, lhclientdoc, lpobjname,
			    lplpobj, objType);

	    default:
		return GenPaste (lpclient, lhclientdoc, lpobjname, lplpobj,
			    lpClass, cfFormat, objType);
	}
    }
    else if (optRender == olerender_draw) {
	cfFormat = (OLECLIPFORMAT)EnumClipboardFormats (0);
	while ((cfFormat) && (retVal > OLE_WAIT_FOR_RELEASE)) {
	    switch (cfFormat) {

		case CF_ENHMETAFILE:
		    retVal = EmfPaste (lpclient, lhclientdoc, lpobjname,
			    lplpobj, objType);
		    break;

		case CF_METAFILEPICT:
		    retVal = MfPaste (lpclient, lhclientdoc,
				lpobjname, lplpobj, objType);
		    break;

		case CF_DIB:
		    retVal = DibPaste (lpclient, lhclientdoc,
				lpobjname, lplpobj, objType);
		    break;

		case CF_BITMAP:
		    retVal = BmPaste (lpclient, lhclientdoc,
				lpobjname, lplpobj, objType);
		    break;
	    }

	    cfFormat = (OLECLIPFORMAT)EnumClipboardFormats (cfFormat);
	}
    }

    return retVal;
}



OLESTATUS FARINTERNAL CreatePackageFromClip (
   LPOLECLIENT         lpclient,
   LHCLIENTDOC         lhclientdoc,
   LPSTR               lpobjname,
   LPOLEOBJECT FAR *   lplpobj,
   OLEOPT_RENDER       optRender,
   OLECLIPFORMAT       cfFormat,
   LONG                objType
){
    char    file[MAX_STR+6];
    HANDLE  hData;
    LPSTR   lpFileName;

    if (!(hData = GetClipboardData (cfFileName))
	    || !(lpFileName = GlobalLock (hData)))
	return OLE_ERROR_CLIPBOARD;


    if (objType == OT_LINK) {
	lstrcpy (file, lpFileName);
	lstrcat (file, "/Link");
	lpFileName = (LPSTR) file;
    }

    GlobalUnlock (hData);

    return  CreateEmbLnkFromFile (lpclient, packageClass, lpFileName,
			NULL, lhclientdoc, lpobjname, lplpobj,
			optRender, cfFormat, OT_EMBEDDED);
}



void FARINTERNAL RemoveLinkStringFromTopic (
   LPOBJECT_LE lpobj
){
    char    buf[MAX_STR+6];
    int     i = 0;

    if (GlobalGetAtomName (lpobj->topic, buf, sizeof(buf))) {
	// scan the topic for "/Link"
	while (buf[i] != '/') {
	    if (!buf[i])
		return;
	    i++;
	}

	buf[i] = '\0';
	if (lpobj->topic)
	    GlobalDeleteAtom (lpobj->topic);
	lpobj->topic = GlobalAddAtom (buf);
    }
}


void SetMaxPixel ()
{
    HDC hdc;
    // find out the pixel equivalent of MAX_HIMETRIC in X and Y directions

    if (hdc = GetDC (NULL)) {
	maxPixelsX = MulDiv (MAX_HIMETRIC, GetDeviceCaps(hdc, LOGPIXELSX),
			2540);
	maxPixelsY = MulDiv (MAX_HIMETRIC, GetDeviceCaps(hdc, LOGPIXELSY),
			2540);
	ReleaseDC (NULL, hdc);
    }
}
