NT4/private/windows/win4help/winhelp/drawicon.c
2020-09-30 17:12:29 +02:00

463 lines
12 KiB
C

/*****************************************************************************
*
* drawicon.c
*
* Copyright (C) Microsoft Corporation 1990.
* All Rights reserved.
*
******************************************************************************
*
* Module Intent
* Contains the functions to display an icon present in the helpfile most
* suitable for the current display driver.
* ALERT: This module strongly depends on the Windows source tree
* \\pucus\corero!core\user.It is dependent on files
* core\shell\progman\newexe.h and pmextrac.c and \core\user\rmload.c
* It uses some of the undocumented calls of Windows.
* 1. HICON STDCALL LoadIconHandler(HICON, BOOL);
* 2. DWORD STDCALL DirectResAlloc(HANDLE, WORD, WORD);
*
******************************************************************************
*
* Revision History: Created 09/27/90 by Maha
* 04-Oct-1990 LeoN hwndHelp => ahwnd[iCurWindow].hwndParent; hwndTopic => hwndTopicCur
* 26-Oct-1990 LeoN Move overloaded icon into additional window word
* 18-Jul-1991 RussPJ Fixed 3.1 #1219 - Losing authored icon no more.
*
*****************************************************************************/
#include "help.h"
#pragma hdrstop
#include "inc\hwproc.h"
/*****************************************************************************
*
* Defines
*
*****************************************************************************/
#define NSMOVE 0x0010
#define VER 0x0300
#define MAGIC_ICON30 0
// The width of the name field in the Data for the group resources
#define NAMELEN 14
/*****************************************************************************
*
* Types
*
*****************************************************************************/
/**
** Header for the New version of RC.EXE. This contains the structures
** for new format of BITMAP files.
**/
#ifndef RES_ICON
typedef struct tagNEWHEADER
{
WORD Reserved;
WORD ResType;
WORD ResCount;
} NEWHEADER;
typedef NEWHEADER *LPNEWHEADER;
#endif
typedef struct tagDESCRIPTOR
{
WORD xPixelsPerInch;
WORD yPixelsPerInch;
WORD xHotSpot;
WORD yHotSpot;
DWORD BytesInRes;
DWORD OffsetToBits;
} DESCRIPTOR;
typedef DESCRIPTOR *LPDESCRIPTOR;
typedef struct tagRESDIR
{
WORD xPixelsPerInch;
WORD yPixelsPerInch;
WORD Planes;
WORD BitCount;
DWORD BytesInRes;
BYTE ResName[NAMELEN];
} RESDIR;
typedef RESDIR *LPRESDIR;
typedef struct
{
BYTE Width;
BYTE Height;
BYTE ColorCount;
BYTE Reserved;
} RESINFO, * LPRESINFO;
typedef struct tagBITMAPHEADER
{
DWORD Size;
WORD Width;
WORD Height;
WORD Planes;
WORD BitCount;
} BITMAPHEADER;
typedef struct new_exe NEWEXEHDR;
typedef NEWEXEHDR *PNEWEXEHDR;
typedef struct rsrc_nameinfo RESNAMEINFO;
typedef RESNAMEINFO *LPRESNAMEINFO;
typedef struct rsrc_typeinfo RESTYPEINFO;
typedef RESTYPEINFO *LPRESTYPEINFO;
/*****************************************************************************
*
* Prototypes
*
*****************************************************************************/
extern HICON STDCALL LoadIconHandler(HICON, BOOL);
extern DWORD STDCALL DirectResAlloc(HANDLE, WORD, WORD);
HICON STDCALL MyLoadIcon(HDC, LPSTR);
__inline static WORD STDCALL MyGetBestFormIcon(HDC, LPRESDIR, WORD);
__inline static WORD STDCALL MyGetIconId(HDC hdc, HANDLE hRes);
/* ## */
/*****************************************************************************
*
* Variables
*
*****************************************************************************/
BOOL STDCALL FMyLoadIcon(GH ghIconFile)
{
/*
* BUGBUG: Lynn, this uses some undocumented API calls which apparently
* aren't supported by the Win32 API, namely LoadIconHandler and
* DirectResAlloc. Tom just blew this off in the NT code, but I'd like you to
* look at this and see if there is some way of supporting it -- basically
* loading and icon from a help file and using that as the class icon instead
* of loading it from a resource file.
*/
#if 0
WORD wMagic;
HANDLE hIconDir; // Icon directory
WORD nIconIndex;
HICON hIcon = NULL;
QB qv, qvSave, qvCur;
HDC hdc;
WORD fIcon;
if (ghIconFile == NULL || ((qv = qvSave = PtrFromGh(ghIconFile)) == NULL))
return( FALSE );
/* Return 1 if the file is not an EXE or ICO file. */
hIcon = 1;
hdc = GetDC( ahwnd[iCurWindow].hwndParent );
if ( hdc == NULL )
return( FALSE );
wMagic = (WORD)*((WORD *)qv );
qv += 2;
switch (wMagic) {
case MAGIC_ICON30:
{
INT16 i;
DWORD DescOffset;
LPSTR lpIcon;
NEWHEADER NewHeader;
LPNEWHEADER lpHeader;
LPRESDIR lpResDir;
DESCRIPTOR Descriptor;
BITMAPHEADER BitMapHeader;
// Read the header and check if it is a valid ICO file.
MoveMemory(((char *) &NewHeader) + 2, qv, (sizeof(NEWHEADER) - 2));
qv += ( sizeof( NEWHEADER ) -2 );
NewHeader.Reserved = MAGIC_ICON30;
// Check if the file is in correct format
if (NewHeader.ResType != 1)
goto EICleanup1;
// Allocate enough space to create a Global Directory Resource.
hIconDir = GlobalAlloc(GPTR,
(LONG) (sizeof(NEWHEADER) + NewHeader.ResCount * sizeof(RESDIR)));
if (hIconDir == NULL)
goto EICleanup1;
if ((lpHeader = (LPNEWHEADER) PtrFromGh(hIconDir)) == NULL)
goto EICleanup2;
// Assign the values in the header that has been read already.
*lpHeader = NewHeader;
lpResDir = (LPRESDIR)(lpHeader + 1);
// Now Fillup the Directory structure by reading all resource descriptors.
for (i = 1; i <= (INT16) NewHeader.ResCount; i++) {
// Read the Descriptor.
MoveMemory((char *) &Descriptor, qv, sizeof(DESCRIPTOR));
// Save the current offset
qvCur = qv;
qv = qvSave + Descriptor.OffsetToBits;
// Get the bitcount and Planes data
MoveMemory((char *) &BitMapHeader, qv, sizeof(BITMAPHEADER));
lpResDir->xPixelsPerInch = Descriptor.xPixelsPerInch;
lpResDir->yPixelsPerInch = Descriptor.yPixelsPerInch;
lpResDir->Planes = BitMapHeader.Planes;
lpResDir->BitCount = BitMapHeader.BitCount;
lpResDir->BytesInRes = Descriptor.BytesInRes;
// Form the unique name for this resource.
lpResDir->ResName[0] = (char)i;
lpResDir->ResName[1] = 0;
// Save the offset to the bits of the icon as a part of the name.
*((DWORD *)&(lpResDir->ResName[4])) = Descriptor.OffsetToBits;
qv = qvCur;
lpResDir++;
}
/*
* Now that we have the Complete resource directory, let us
* find out the suitable form of icon (that matches the current
* display driver). Because we built the ResDir such that the
* IconId to be the same as the index of the Icon, we can use the
* return value of GetIconId() as the Index; No need to call
* GetResIndex();
*/
nIconIndex = MyGetIconId(hdc, hIconDir) - 1;
lpResDir = (LPRESDIR)(lpHeader+1) + nIconIndex;
// The offset to Bits of the selected Icon is also part of ResName.
DescOffset = *((DWORD *)&(lpResDir->ResName[4]));
// Allocate memory for the Resource to be loaded.
if ((hIcon =
(WORD)DirectResAlloc(hInsNow, NSMOVE, (WORD)lpResDir->BytesInRes)) == NULL)
goto EICleanup3;
if ((lpIcon = PtrFromGh(hIcon)) == NULL)
goto EICleanup4;
qv = qvSave + DescOffset;
MoveMemory((QV) lpIcon, qv, (INT16) lpResDir->BytesInRes);
// Stretch and shrink the icon depending upon resolution of display
hIcon = LoadIconHandler(hIcon, TRUE);
/*------------------------------------------------------------*\
| hIcon may now be discardable; let's change that!
\*------------------------------------------------------------*/
fIcon = GlobalFlags( hIcon );
fIcon &= ~GMEM_DISCARDABLE;
GlobalReAlloc( hIcon, 0, GMEM_MODIFY | fIcon );
goto EICleanup3;
EICleanup4:
GlobalFree(hIcon);
hIcon = (HICON)1;
EICleanup3:
EICleanup2:
GlobalFree(hIconDir);
EICleanup1:
break;
}
}
ReleaseDC( ahwnd[iCurWindow].hwndParent, hdc );
// Set up the icon word in the window struct appropriately.
if ( hIcon && hIcon != 1 ) {
SetWindowLong (ahwnd[iCurWindow].hwndParent, GHWL_HICON, (LONG) hIcon);
return(TRUE);
}
#endif
SetWindowLong(ahwnd[iCurWindow].hwndParent, (int) GHWL_HICON, 0);
return FALSE;
}
#if 0
/***************************************************************************
*
- Name MyGetIconId()
-
* Purpose Used for finding the index no. of the icon to be used.
* Arguments Display context handle and the handle to the icon resource
* resource directory present in the icon file.
*
* Returns
* The icon no. to be used.
*
* +++
*
* Notes
*
***************************************************************************/
__inline static WORD STDCALL MyGetIconId(HDC hdc, HANDLE hRes)
{
LPRESDIR ResDirPtr;
LPNEWHEADER DataPtr;
WORD RetIndex;
WORD ResCount;
if ((DataPtr = (LPNEWHEADER) PtrFromGh(hRes)) == NULL)
return(0);
ResCount = DataPtr->ResCount;
ResDirPtr = (LPRESDIR) (DataPtr + 1);
RetIndex = MyGetBestFormIcon(hdc, ResDirPtr, ResCount);
if (RetIndex == ResCount)
RetIndex = 0;
ResCount = (WORD)(((LPRESDIR)(ResDirPtr+RetIndex))->ResName[0]);
return ResCount;
}
/***************************************************************************
*
- Name MyBestFormIcon()
-
* Purpose Used for finding the index no. of the icon to be used.
* Among the different forms of Icons present, choose the one that
* matches the PixelsPerInch values and the number of colors of the
* current display.
* Arguments Display context handle and the
* resource directory pointer present in the icon file and
* resource count present in the resource file.
*
* Returns
* The icon no. to be used.
*
* +++
*
* Notes
*
***************************************************************************/
__inline static WORD STDCALL MyGetBestFormIcon(HDC hdc,
LPRESDIR ResDirPtr, WORD ResCount)
{
UINT16 wIndex;
UINT16 ColorCount;
UINT16 MaxColorCount;
UINT16 MaxColorIndex;
UINT16 MoreColorCount;
UINT16 MoreColorIndex;
UINT16 LessColorCount;
UINT16 LessColorIndex;
INT16 cxIcon, cyIcon, ScreenBitCount;
LPRESINFO lpResInfo;
cxIcon = GetSystemMetrics(SM_CXICON);
cyIcon = GetSystemMetrics(SM_CYICON);
ScreenBitCount = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
// Initialse all the values to zero
MaxColorCount = MaxColorIndex = MoreColorCount =
MoreColorIndex = LessColorIndex = LessColorCount = 0;
for (wIndex = 0; wIndex < ResCount; wIndex++, ResDirPtr++) {
lpResInfo = (LPRESINFO)ResDirPtr;
// Check for the number of colors
if ((ColorCount = (WORD)(lpResInfo->ColorCount)) <= (WORD)(1 << ScreenBitCount))
{
if (ColorCount > MaxColorCount)
{
MaxColorCount = ColorCount;
MaxColorIndex = wIndex;
}
}
/* Check for the size */
/* Match the pixels per inch information */
if ((lpResInfo->Width == (BYTE)cxIcon) &&
(lpResInfo->Height == (BYTE)cyIcon))
{
/* Matching size found */
/* Check if the color also matches */
if (ColorCount == (WORD)(1 << ScreenBitCount))
return(wIndex); /* Exact match found */
if (ColorCount < (WORD)(1 << ScreenBitCount))
{
/* Choose the one with max colors, but less than reqd */
if (ColorCount > LessColorCount)
{
LessColorCount = ColorCount;
LessColorIndex = wIndex;
}
}
else
{
if ((LessColorCount == 0) && (ColorCount < MoreColorCount))
{
MoreColorCount = ColorCount;
MoreColorIndex = wIndex;
}
}
}
}
// Check if we have a correct sized but with less colors than reqd
if (LessColorCount)
return(LessColorIndex);
// Check if we have a correct sized but with more colors than reqd
if (MoreColorCount)
return(MoreColorIndex);
// Check if we have one that has maximum colors but less than reqd
if (MaxColorCount)
return(MaxColorIndex);
return(0);
}
#endif // 0