From e8265093130028add35cfdff771aca32f0c74577 Mon Sep 17 00:00:00 2001 From: Kevin Walzer Date: Mon, 10 Aug 2020 00:51:58 +0000 Subject: Reduce refactoring of code, not as much needed --- win/tkWinIco.c | 725 +------------------------------------------ win/tkWinIco.h | 45 +-- win/tkWinSysTray.c | 70 +---- win/tkWinWm.c | 885 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 890 insertions(+), 835 deletions(-) diff --git a/win/tkWinIco.c b/win/tkWinIco.c index f24ab79..f158117 100644 --- a/win/tkWinIco.c +++ b/win/tkWinIco.c @@ -121,726 +121,11 @@ BytesPerLine( return WIDTHBYTES(lpBMIH->biWidth * lpBMIH->biPlanes * lpBMIH->biBitCount); } -/* - *---------------------------------------------------------------------- - * - * AdjustIconImagePointers -- - * - * Adjusts internal pointers in icon resource struct, as given by - * LPICONIMAGE lpImage - the resource to handle. Used by titlebar icon - * code. - * - * Results: - * BOOL - TRUE for success, FALSE for failure - * - *---------------------------------------------------------------------- - */ - -static BOOL -AdjustIconImagePointers( - LPICONIMAGE lpImage) -{ - /* - * Sanity check. - */ - - if (lpImage == NULL) { - return FALSE; - } - - /* - * BITMAPINFO is at beginning of bits. - */ - - lpImage->lpbi = (LPBITMAPINFO) lpImage->lpBits; - - /* - * Width - simple enough. - */ - - lpImage->Width = lpImage->lpbi->bmiHeader.biWidth; - - /* - * Icons are stored in funky format where height is doubled so account for - * that. - */ - - lpImage->Height = (lpImage->lpbi->bmiHeader.biHeight)/2; - - /* - * How many colors? - */ - - lpImage->Colors = lpImage->lpbi->bmiHeader.biPlanes - * lpImage->lpbi->bmiHeader.biBitCount; - - /* - * XOR bits follow the header and color table. - */ - - lpImage->lpXOR = (LPBYTE) FindDIBBits((LPSTR) lpImage->lpbi); - - /* - * AND bits follow the XOR bits. - */ - - lpImage->lpAND = lpImage->lpXOR + - lpImage->Height*BytesPerLine((LPBITMAPINFOHEADER) lpImage->lpbi); - return TRUE; -} - -/* - *---------------------------------------------------------------------- - * - * MakeIconOrCursorFromResource -- - * - * Construct an actual HICON structure from the information in a - * resource. - * - * Results: - * Icon - * - *---------------------------------------------------------------------- - */ - -static HICON -MakeIconOrCursorFromResource( - LPICONIMAGE lpIcon, - BOOL isIcon) -{ - HICON hIcon; - - /* - * Sanity Check - */ - - if (lpIcon == NULL || lpIcon->lpBits == NULL) { - return NULL; - } - - /* - * Let the OS do the real work :) - */ - - hIcon = (HICON) CreateIconFromResourceEx(lpIcon->lpBits, - lpIcon->dwNumBytes, isIcon, 0x00030000, - (*(LPBITMAPINFOHEADER) lpIcon->lpBits).biWidth, - (*(LPBITMAPINFOHEADER) lpIcon->lpBits).biHeight/2, 0); - - /* - * It failed, odds are good we're on NT so try the non-Ex way. - */ - - if (hIcon == NULL) { - /* - * We would break on NT if we try with a 16bpp image. - */ - - if (lpIcon->lpbi->bmiHeader.biBitCount != 16) { - hIcon = CreateIconFromResource(lpIcon->lpBits, lpIcon->dwNumBytes, - isIcon, 0x00030000); - } - } - return hIcon; -} - -/* - *---------------------------------------------------------------------- - * - * ReadICOHeader -- - * - * Reads the header from an ICO file, as specfied by channel. - * - * Results: - * UINT - Number of images in file, -1 for failure. If this succeeds, - * there is a decent chance this is a valid icon file. - * - *---------------------------------------------------------------------- - */ - -static int -ReadICOHeader( - Tcl_Channel channel) -{ - union { - WORD word; - char bytes[sizeof(WORD)]; - } input; - - /* - * Read the 'reserved' WORD, which should be a zero word. - */ - - if (Tcl_Read(channel, input.bytes, sizeof(WORD)) != sizeof(WORD)) { - return -1; - } - if (input.word != 0) { - return -1; - } - - /* - * Read the type WORD, which should be of type 1. - */ - - if (Tcl_Read(channel, input.bytes, sizeof(WORD)) != sizeof(WORD)) { - return -1; - } - if (input.word != 1) { - return -1; - } - - /* - * Get and return the count of images. - */ - - if (Tcl_Read(channel, input.bytes, sizeof(WORD)) != sizeof(WORD)) { - return -1; - } - return (int) input.word; -} - -/* - *---------------------------------------------------------------------- - * - * ReadIconFromFile -- - * - * Read the contents of a file (usually .ico, .icr) and extract an icon - * resource, if possible, otherwise check if the shell has an icon - * assigned to the given file and use that. If both of those fail, then - * NULL is returned, and an error message will already be in the - * interpreter. - * - * Results: - * A WinIconPtr structure containing the icons in the file, with its ref - * count already incremented. The calling function should either place - * this structure inside a WmInfo structure, or it should pass it on to - * DecrIconRefCount() to ensure no memory leaks occur. - * - * If the given fileName did not contain a valid icon structure, - * return NULL. - * - * Side effects: - * Memory is allocated for the returned structure and the icons it - * contains. If the structure is not wanted, it should be passed to - * DecrIconRefCount, and in any case a valid ref count should be ensured - * to avoid memory leaks. - * - * Currently icon resources are not shared, so the ref count of one of - * these structures will always be 0 or 1. However all we need do is - * implement some sort of lookup function between filenames and - * WinIconPtr structures and no other code will need to be changed. The - * pseudo-code for this is implemented below in the 'if (0)' branch. It - * did not seem necessary to implement this optimisation here, since - * moving to icon<->image conversions will probably make it obsolete. - * - *---------------------------------------------------------------------- - */ - -static WinIconPtr -ReadIconFromFile( - Tcl_Interp *interp, - Tcl_Obj *fileName) -{ - WinIconPtr titlebaricon = NULL; - BlockOfIconImagesPtr lpIR; - -#if 0 /* TODO: Dead code? */ - if (0 /* If we already have an icon for this filename */) { - titlebaricon = NULL; /* Get the real value from a lookup */ - titlebaricon->refCount++; - return titlebaricon; - } -#endif - - /* - * First check if it is a .ico file. - */ - - lpIR = ReadIconOrCursorFromFile(interp, fileName, TRUE); - - /* - * Then see if we can ask the shell for the icon for this file. We - * want both the regular and small icons so that the Alt-Tab (task- - * switching) display uses the right icon. - */ - - if (lpIR == NULL) { - SHFILEINFOW sfiSM; - Tcl_DString ds, ds2; - DWORD *res; - const char *file; - - file = Tcl_TranslateFileName(interp, Tcl_GetString(fileName), &ds); - if (file == NULL) { - return NULL; - } - Tcl_DStringInit(&ds2); - res = (DWORD *)SHGetFileInfoW(Tcl_UtfToWCharDString(file, -1, &ds2), 0, &sfiSM, - sizeof(SHFILEINFO), SHGFI_SMALLICON|SHGFI_ICON); - Tcl_DStringFree(&ds); - - if (res != 0) { - SHFILEINFOW sfi; - unsigned size; - - Tcl_ResetResult(interp); - res = (DWORD *)SHGetFileInfoW((WCHAR *)Tcl_DStringValue(&ds2), 0, &sfi, - sizeof(SHFILEINFO), SHGFI_ICON); - - /* - * Account for extra icon, if necessary. - */ - - size = sizeof(BlockOfIconImages) - + ((res != 0) ? sizeof(ICONIMAGE) : 0); - lpIR = (BlockOfIconImagesPtr)ckalloc(size); - if (lpIR == NULL) { - if (res != 0) { - DestroyIcon(sfi.hIcon); - } - DestroyIcon(sfiSM.hIcon); - Tcl_DStringFree(&ds2); - return NULL; - } - ZeroMemory(lpIR, size); - - lpIR->nNumImages = ((res != 0) ? 2 : 1); - lpIR->IconImages[0].Width = 16; - lpIR->IconImages[0].Height = 16; - lpIR->IconImages[0].Colors = 4; - lpIR->IconImages[0].hIcon = sfiSM.hIcon; - - /* - * All other IconImages fields are ignored. - */ - - if (res != 0) { - lpIR->IconImages[1].Width = 32; - lpIR->IconImages[1].Height = 32; - lpIR->IconImages[1].Colors = 4; - lpIR->IconImages[1].hIcon = sfi.hIcon; - } - } - Tcl_DStringFree(&ds2); - } - if (lpIR != NULL) { - titlebaricon = (WinIconPtr)ckalloc(sizeof(WinIconInstance)); - titlebaricon->iconBlock = lpIR; - titlebaricon->refCount = 1; - } - return titlebaricon; -} - -/* - *---------------------------------------------------------------------- - * - * GetIconFromPixmap -- - * - * Turn a Tk Pixmap (i.e. a bitmap) into an icon resource, if possible, - * otherwise NULL is returned. - * - * Results: - * A WinIconPtr structure containing a conversion of the given bitmap - * into an icon, with its ref count already incremented. The calling - * function should either place this structure inside a WmInfo structure, - * or it should pass it on to DecrIconRefCount() to ensure no memory - * leaks occur. - * - * If the given pixmap did not contain a valid icon structure, return - * NULL. - * - * Side effects: - * Memory is allocated for the returned structure and the icons it - * contains. If the structure is not wanted, it should be passed to - * DecrIconRefCount, and in any case a valid ref count should be ensured - * to avoid memory leaks. - * - * Currently icon resources are not shared, so the ref count of one of - * these structures will always be 0 or 1. However all we need do is - * implement some sort of lookup function between pixmaps and WinIconPtr - * structures and no other code will need to be changed. - * - *---------------------------------------------------------------------- - */ - -static WinIconPtr -GetIconFromPixmap( - Display *dsPtr, - Pixmap pixmap) -{ - WinIconPtr titlebaricon = NULL; - TkWinDrawable *twdPtr = (TkWinDrawable *) pixmap; - BlockOfIconImagesPtr lpIR; - ICONINFO icon; - HICON hIcon; - int width, height; - - if (twdPtr == NULL) { - return NULL; - } -#if 0 /* TODO: Dead code?*/ - if (0 /* If we already have an icon for this pixmap */) { - titlebaricon = NULL; /* Get the real value from a lookup */ - titlebaricon->refCount++; - return titlebaricon; - } -#endif - - Tk_SizeOfBitmap(dsPtr, pixmap, &width, &height); - - icon.fIcon = TRUE; - icon.xHotspot = 0; - icon.yHotspot = 0; - icon.hbmMask = twdPtr->bitmap.handle; - icon.hbmColor = twdPtr->bitmap.handle; - - hIcon = CreateIconIndirect(&icon); - if (hIcon == NULL) { - return NULL; - } - - lpIR = (BlockOfIconImagesPtr)ckalloc(sizeof(BlockOfIconImages)); - if (lpIR == NULL) { - DestroyIcon(hIcon); - return NULL; - } - - lpIR->nNumImages = 1; - lpIR->IconImages[0].Width = width; - lpIR->IconImages[0].Height = height; - lpIR->IconImages[0].Colors = 1 << twdPtr->bitmap.depth; - lpIR->IconImages[0].hIcon = hIcon; - - /* - * These fields are ignored. - */ - - lpIR->IconImages[0].lpBits = 0; - lpIR->IconImages[0].dwNumBytes = 0; - lpIR->IconImages[0].lpXOR = 0; - lpIR->IconImages[0].lpAND = 0; - - titlebaricon = (WinIconPtr)ckalloc(sizeof(WinIconInstance)); - titlebaricon->iconBlock = lpIR; - titlebaricon->refCount = 1; - return titlebaricon; -} - /* - *---------------------------------------------------------------------- - * - * DecrIconRefCount -- - * - * Reduces the reference count. - * - * Results: - * None. - * - * Side effects: - * If the ref count falls to zero, free the memory associated with the - * icon resource structures. In this case the pointer passed into this - * function is no longer valid. - * - *---------------------------------------------------------------------- + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: */ - -static void -DecrIconRefCount( - WinIconPtr titlebaricon) -{ - if (titlebaricon->refCount-- <= 1) { - if (titlebaricon->iconBlock != NULL) { - FreeIconBlock(titlebaricon->iconBlock); - } - titlebaricon->iconBlock = NULL; - - ckfree(titlebaricon); - } -} - -/* - *---------------------------------------------------------------------- - * - * FreeIconBlock -- - * - * Frees all memory associated with a previously loaded titlebaricon. - * The icon block pointer is no longer valid once this function returns. - * - * Results: - * None. - * - * Side effects: - * - * - *---------------------------------------------------------------------- - */ - -static void -FreeIconBlock( - BlockOfIconImagesPtr lpIR) -{ - int i; - - /* - * Free all the bits. - */ - - for (i=0 ; inNumImages ; i++) { - if (lpIR->IconImages[i].lpBits != NULL) { - ckfree(lpIR->IconImages[i].lpBits); - } - if (lpIR->IconImages[i].hIcon != NULL) { - DestroyIcon(lpIR->IconImages[i].hIcon); - } - } - ckfree(lpIR); -} - -/* - *---------------------------------------------------------------------- - * - * GetIcon -- - * - * Extracts an icon of a given size from an icon resource - * - * Results: - * Returns the icon, if found, else NULL. - * - *---------------------------------------------------------------------- - */ - -static HICON -GetIcon( - WinIconPtr titlebaricon, - int icon_size) -{ - BlockOfIconImagesPtr lpIR; - unsigned int size = (icon_size == 0 ? 16 : 32); - int i; - - if (titlebaricon == NULL) { - return NULL; - } - - lpIR = titlebaricon->iconBlock; - if (lpIR == NULL) { - return NULL; - } - - for (i=0 ; inNumImages ; i++) { - /* - * Take the first or a 32x32 16 color icon - */ - - if ((lpIR->IconImages[i].Height == size) - && (lpIR->IconImages[i].Width == size) - && (lpIR->IconImages[i].Colors >= 4)) { - return lpIR->IconImages[i].hIcon; - } - } - - /* - * If we get here, then just return the first one, it will have to do! - */ - - if (lpIR->nNumImages >= 1) { - return lpIR->IconImages[0].hIcon; - } - return NULL; -} - -#if 0 /* UNUSED */ -static HCURSOR -TclWinReadCursorFromFile( - Tcl_Interp* interp, - Tcl_Obj* fileName) -{ - BlockOfIconImagesPtr lpIR; - HICON res = NULL; - - lpIR = ReadIconOrCursorFromFile(interp, fileName, FALSE); - if (lpIR == NULL) { - return NULL; - } - if (lpIR->nNumImages >= 1) { - res = CopyImage(lpIR->IconImages[0].hIcon, IMAGE_CURSOR, 0, 0, 0); - } - FreeIconBlock(lpIR); - return res; -} -#endif - -/* - *---------------------------------------------------------------------- - * - * ReadIconOrCursorFromFile -- - * - * Reads an Icon Resource from an ICO file, as given by char* fileName - - * Name of the ICO file. This name should be in Utf format. - * - * Results: - * Returns an icon resource, if found, else NULL. - * - * Side effects: - * May leave error messages in the Tcl interpreter. - * - *---------------------------------------------------------------------- - */ - -static BlockOfIconImagesPtr -ReadIconOrCursorFromFile( - Tcl_Interp *interp, - Tcl_Obj *fileName, - BOOL isIcon) -{ - BlockOfIconImagesPtr lpIR; - Tcl_Channel channel; - int i; - DWORD dwBytesRead; - LPICONDIRENTRY lpIDE; - - /* - * Open the file. - */ - - channel = Tcl_FSOpenFileChannel(interp, fileName, "r", 0); - if (channel == NULL) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "error opening file \"%s\" for reading: %s", - Tcl_GetString(fileName), Tcl_PosixError(interp))); - return NULL; - } - if (Tcl_SetChannelOption(interp, channel, "-translation", "binary") - != TCL_OK) { - Tcl_Close(NULL, channel); - return NULL; - } - if (Tcl_SetChannelOption(interp, channel, "-encoding", "binary") - != TCL_OK) { - Tcl_Close(NULL, channel); - return NULL; - } - - /* - * Allocate memory for the resource structure - */ - - lpIR = (BlockOfIconImagesPtr)ckalloc(sizeof(BlockOfIconImages)); - - /* - * Read in the header - */ - - lpIR->nNumImages = ReadICOHeader(channel); - if (lpIR->nNumImages == -1) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("Invalid file header", -1)); - Tcl_Close(NULL, channel); - ckfree(lpIR); - return NULL; - } - - /* - * Adjust the size of the struct to account for the images. - */ - - lpIR = (BlockOfIconImagesPtr)ckrealloc(lpIR, sizeof(BlockOfIconImages) - + (lpIR->nNumImages - 1) * sizeof(ICONIMAGE)); - - /* - * Allocate enough memory for the icon directory entries. - */ - - lpIDE = (LPICONDIRENTRY)ckalloc(lpIR->nNumImages * sizeof(ICONDIRENTRY)); - - /* - * Read in the icon directory entries. - */ - - dwBytesRead = Tcl_Read(channel, (char *) lpIDE, - (int) (lpIR->nNumImages * sizeof(ICONDIRENTRY))); - if (dwBytesRead != lpIR->nNumImages * sizeof(ICONDIRENTRY)) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "error reading file: %s", Tcl_PosixError(interp))); - Tcl_SetErrorCode(interp, "TK", "WM", "ICON", "READ", NULL); - Tcl_Close(NULL, channel); - ckfree(lpIDE); - ckfree(lpIR); - return NULL; - } - - /* - * NULL-out everything to make memory management easier. - */ - - for (i = 0; i < lpIR->nNumImages; i++) { - lpIR->IconImages[i].lpBits = NULL; - } - - /* - * Loop through and read in each image. - */ - - for (i=0 ; inNumImages ; i++) { - /* - * Allocate memory for the resource. - */ - - lpIR->IconImages[i].lpBits = (LPBYTE)ckalloc(lpIDE[i].dwBytesInRes); - lpIR->IconImages[i].dwNumBytes = lpIDE[i].dwBytesInRes; - - /* - * Seek to beginning of this image. - */ - - if (Tcl_Seek(channel, lpIDE[i].dwImageOffset, FILE_BEGIN) == -1) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "error seeking in file: %s", Tcl_PosixError(interp))); - goto readError; - } - - /* - * Read it in. - */ - - dwBytesRead = Tcl_Read(channel, (char *)lpIR->IconImages[i].lpBits, - (int) lpIDE[i].dwBytesInRes); - if (dwBytesRead != lpIDE[i].dwBytesInRes) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "error reading file: %s", Tcl_PosixError(interp))); - goto readError; - } - - /* - * Set the internal pointers appropriately. - */ - - if (!AdjustIconImagePointers(&lpIR->IconImages[i])) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "Error converting to internal format", -1)); - Tcl_SetErrorCode(interp, "TK", "WM", "ICON", "FORMAT", NULL); - goto readError; - } - lpIR->IconImages[i].hIcon = - MakeIconOrCursorFromResource(&lpIR->IconImages[i], isIcon); - } - - /* - * Clean up - */ - - ckfree(lpIDE); - Tcl_Close(NULL, channel); - return lpIR; - - readError: - Tcl_Close(NULL, channel); - for (i = 0; i < lpIR->nNumImages; i++) { - if (lpIR->IconImages[i].lpBits != NULL) { - ckfree(lpIR->IconImages[i].lpBits); - } - } - ckfree(lpIDE); - ckfree(lpIR); - return NULL; -} diff --git a/win/tkWinIco.h b/win/tkWinIco.h index cf2c7f9..fd1e177 100644 --- a/win/tkWinIco.h +++ b/win/tkWinIco.h @@ -64,32 +64,6 @@ typedef struct { ICONDIRENTRY idEntries[1]; /* The entries for each image */ } ICONDIR, *LPICONDIR; -/* - * A pointer to one of these strucutures is associated with each toplevel. - * This allows us to free up all memory associated with icon resources when a - * window is deleted or if the window's icon is changed. They are simply - * reference counted according to: - * - * (1) How many WmInfo structures point to this object - * (2) Whether the ThreadSpecificData defined in this file contains a pointer - * to this object. - * - * The former count is for windows whose icons are individually set, and the - * latter is for the global default icon choice. - * - * Icons loaded from .icr/.icr use the iconBlock field, icons loaded from - * .exe/.dll use the hIcon field. - */ - -typedef struct WinIconInstance { - size_t refCount; /* Number of instances that share this data - * structure. */ - BlockOfIconImagesPtr iconBlock; - /* Pointer to icon resource data for image */ -} WinIconInstance; - -typedef struct WinIconInstance *WinIconPtr; - /* * Used in BytesPerLine @@ -102,27 +76,12 @@ typedef struct WinIconInstance *WinIconPtr; * The following are implemented in tkWinIco.c and also used in tkWinWm.c and tkWinSysTray.c. */ -static BlockOfIconImagesPtr ReadIconOrCursorFromFile(Tcl_Interp *interp, Tcl_Obj* fileName, BOOL isIcon); -static WinIconPtr ReadIconFromFile(Tcl_Interp *interp, - Tcl_Obj *fileName); -static WinIconPtr GetIconFromPixmap(Display *dsPtr, Pixmap pixmap); -static int ReadICOHeader(Tcl_Channel channel); -static BOOL AdjustIconImagePointers(LPICONIMAGE lpImage); -static HICON MakeIconOrCursorFromResource(LPICONIMAGE lpIcon, - BOOL isIcon); -static HICON GetIcon(WinIconPtr titlebaricon, int icon_size); -static int WinSetIcon(Tcl_Interp *interp, - WinIconPtr titlebaricon, Tk_Window tkw); -static void FreeIconBlock(BlockOfIconImagesPtr lpIR); -static void DecrIconRefCount(WinIconPtr titlebaricon); -static HICON MakeIconOrCursorFromResource(LPICONIMAGE lpIcon, - BOOL isIcon); -static BOOL AdjustIconImagePointers( LPICONIMAGE lpImage); + static DWORD BytesPerLine(LPBITMAPINFOHEADER lpBMIH); static LPSTR FindDIBBits(LPSTR lpbi); static WORD PaletteSize(LPSTR lpbi); static WORD DIBNumColors(LPSTR lpbi); static int ReadICOHeader(Tcl_Channel channel); -static HICON GetIcon( WinIconPtr titlebaricon, int icon_size); + diff --git a/win/tkWinSysTray.c b/win/tkWinSysTray.c index 7115d90..8056c46 100644 --- a/win/tkWinSysTray.c +++ b/win/tkWinSysTray.c @@ -21,29 +21,19 @@ */ -#define WIN32_LEAN_AND_MEAN + #include #include #include #include +#include "tkWinIco.h" + #define GETHINSTANCE Tk_GetHINSTANCE() static int isWin32s=-1; #define ISWIN32S isWin32s -#if defined(_MSC_VER) -# define EXPORT(a,b) __declspec(dllexport) a b -# define DllEntryPoint DllMain -# define snprintf _snprintf -#else -# if defined(__BORLANDC__) -# define EXPORT(a,b) a _export b -# else -# define EXPORT(a,b) a b -# endif -#endif - #ifdef HAVE_STDLIB_H #include #endif @@ -57,61 +47,7 @@ static int isWin32s=-1; #define CONST84 #endif -typedef struct { - UINT Width, Height, Colors; /* Width, Height and bpp */ - LPBYTE lpBits; /* ptr to DIB bits */ - DWORD dwNumBytes; /* how many bytes? */ - LPBITMAPINFO lpbi; /* ptr to header */ - LPBYTE lpXOR; /* ptr to XOR image bits */ - LPBYTE lpAND; /* ptr to AND image bits */ - HICON hIcon; /* DAS ICON */ -} LPICONIMAGE, *LPICONIMAGE; - -typedef struct { - BOOL bHasChanged; /* Has image changed? */ - TCHAR szOriginalICOFileName[MAX_PATH]; /* Original name */ - TCHAR szOriginalDLLFileName[MAX_PATH]; /* Original name */ - int nNumImages; /* How many images? */ - LPICONIMAGE LPICONIMAGEs[1]; /* Image entries */ -} ICONRESOURCE, *LPICONRESOURCE; - -/* - * These next two structs represent how the icon information is stored - * in an ICO file. The following two structs are for the use of this - * program in manipulating icons. They are more closely tied to the - * operation of this program than the structures listed above. One of the - * main differences is that they provide a pointer to the DIB - * information of the masks. - */ - -typedef struct { - BYTE bWidth; /* Width of the image */ - BYTE bHeight; /* Height of the image (times 2) */ - BYTE bColorCount; /* Number of colors (0 if >=8bpp) */ - BYTE bReserved; /* Reserved */ - WORD wPlanes; /* Color Planes */ - WORD wBitCount; /* Bits per pixel */ - DWORD dwBytesInRes; /* how many bytes in this resource? */ - DWORD dwImageOffset; /* where in the file is this image */ -} ICONDIRENTRY, *LPICONDIRENTRY; - -typedef struct { - WORD idReserved; /* Reserved */ - WORD idType; /* resource type (1 for icons) */ - WORD idCount; /* how many images? */ - ICONDIRENTRY idEntries[1]; /* the entries for each image */ -} ICONDIR, *LPICONDIR; - -/* How wide, in bytes, would this many bits be, DWORD aligned? */ -#define WIDTHBYTES(bits) ((((bits) + 31)>>5)<<2) - -/* Function prototypes */ -static LPSTR FindDIBBits (LPSTR lpbi); -static WORD DIBNumColors (LPSTR lpbi); -static WORD PaletteSize (LPSTR lpbi); -static DWORD BytesPerLine( LPBITMAPINFOHEADER lpBMIH ); - static BOOL AdjustLPICONIMAGEPointers( LPLPICONIMAGE lpImage ); typedef struct IcoInfo { diff --git a/win/tkWinWm.c b/win/tkWinWm.c index 6916d92..98994ec 100644 --- a/win/tkWinWm.c +++ b/win/tkWinWm.c @@ -14,7 +14,7 @@ */ #include "tkWinInt.h" -#include "tkWinIco.h" +#include "TkWinIco.h" #include /* @@ -80,6 +80,32 @@ typedef struct TkWmStackorderToplevelPair { /* + * A pointer to one of these strucutures is associated with each toplevel. + * This allows us to free up all memory associated with icon resources when a + * window is deleted or if the window's icon is changed. They are simply + * reference counted according to: + * + * (1) How many WmInfo structures point to this object + * (2) Whether the ThreadSpecificData defined in this file contains a pointer + * to this object. + * + * The former count is for windows whose icons are individually set, and the + * latter is for the global default icon choice. + * + * Icons loaded from .icr/.icr use the iconBlock field, icons loaded from + * .exe/.dll use the hIcon field. + */ + +typedef struct WinIconInstance { + size_t refCount; /* Number of instances that share this data + * structure. */ + BlockOfIconImagesPtr iconBlock; + /* Pointer to icon resource data for image */ +} WinIconInstance; + +typedef struct WinIconInstance *WinIconPtr; + +/* * A data structure of the following type holds window-manager-related * information for each top-level window in an application. */ @@ -355,6 +381,21 @@ static LRESULT CALLBACK WmProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); static void WmWaitVisibilityOrMapProc(ClientData clientData, XEvent *eventPtr); +static BlockOfIconImagesPtr ReadIconOrCursorFromFile(Tcl_Interp *interp, + Tcl_Obj* fileName, BOOL isIcon); +static WinIconPtr ReadIconFromFile(Tcl_Interp *interp, + Tcl_Obj *fileName); +static WinIconPtr GetIconFromPixmap(Display *dsPtr, Pixmap pixmap); +static int ReadICOHeader(Tcl_Channel channel); +static BOOL AdjustIconImagePointers(LPICONIMAGE lpImage); +static HICON MakeIconOrCursorFromResource(LPICONIMAGE lpIcon, + BOOL isIcon); +static HICON GetIcon(WinIconPtr titlebaricon, int icon_size); +static int WinSetIcon(Tcl_Interp *interp, + WinIconPtr titlebaricon, Tk_Window tkw); +static void FreeIconBlock(BlockOfIconImagesPtr lpIR); +static void DecrIconRefCount(WinIconPtr titlebaricon); + static int WmAspectCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); @@ -453,6 +494,296 @@ static int WmWithdrawCmd(Tk_Window tkwin, Tcl_Obj *const objv[]); static void WmUpdateGeom(WmInfo *wmPtr, TkWindow *winPtr); +/* + * Used in BytesPerLine + */ + +#define WIDTHBYTES(bits) ((((bits) + 31)>>5)<<2) + +/* + *---------------------------------------------------------------------- + * + * DIBNumColors -- + * + * Calculates the number of entries in the color table, given by LPSTR + * lpbi - pointer to the CF_DIB memory block. Used by titlebar icon code. + * + * Results: + * WORD - Number of entries in the color table. + * + *---------------------------------------------------------------------- + */ + +static WORD +DIBNumColors( + LPSTR lpbi) +{ + WORD wBitCount; + DWORD dwClrUsed; + + dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed; + + if (dwClrUsed) { + return (WORD) dwClrUsed; + } + + wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount; + + switch (wBitCount) { + case 1: + return 2; + case 4: + return 16; + case 8: + return 256; + default: + return 0; + } +} + +/* + *---------------------------------------------------------------------- + * + * PaletteSize -- + * + * Calculates the number of bytes in the color table, as given by LPSTR + * lpbi - pointer to the CF_DIB memory block. Used by titlebar icon code. + * + * Results: + * Number of bytes in the color table + * + *---------------------------------------------------------------------- + */ +static WORD +PaletteSize( + LPSTR lpbi) +{ + return (WORD) (DIBNumColors(lpbi) * sizeof(RGBQUAD)); +} + +/* + *---------------------------------------------------------------------- + * + * FindDIBits -- + * + * Locate the image bits in a CF_DIB format DIB, as given by LPSTR lpbi - + * pointer to the CF_DIB memory block. Used by titlebar icon code. + * + * Results: + * pointer to the image bits + * + * Side effects: None + * + * + *---------------------------------------------------------------------- + */ + +static LPSTR +FindDIBBits( + LPSTR lpbi) +{ + return lpbi + *((LPDWORD) lpbi) + PaletteSize(lpbi); +} + +/* + *---------------------------------------------------------------------- + * + * BytesPerLine -- + * + * Calculates the number of bytes in one scan line, as given by + * LPBITMAPINFOHEADER lpBMIH - pointer to the BITMAPINFOHEADER that + * begins the CF_DIB block. Used by titlebar icon code. + * + * Results: + * number of bytes in one scan line (DWORD aligned) + * + *---------------------------------------------------------------------- + */ + +static DWORD +BytesPerLine( + LPBITMAPINFOHEADER lpBMIH) +{ + return WIDTHBYTES(lpBMIH->biWidth * lpBMIH->biPlanes * lpBMIH->biBitCount); +} + +/* + *---------------------------------------------------------------------- + * + * AdjustIconImagePointers -- + * + * Adjusts internal pointers in icon resource struct, as given by + * LPICONIMAGE lpImage - the resource to handle. Used by titlebar icon + * code. + * + * Results: + * BOOL - TRUE for success, FALSE for failure + * + *---------------------------------------------------------------------- + */ + +static BOOL +AdjustIconImagePointers( + LPICONIMAGE lpImage) +{ + /* + * Sanity check. + */ + + if (lpImage == NULL) { + return FALSE; + } + + /* + * BITMAPINFO is at beginning of bits. + */ + + lpImage->lpbi = (LPBITMAPINFO) lpImage->lpBits; + + /* + * Width - simple enough. + */ + + lpImage->Width = lpImage->lpbi->bmiHeader.biWidth; + + /* + * Icons are stored in funky format where height is doubled so account for + * that. + */ + + lpImage->Height = (lpImage->lpbi->bmiHeader.biHeight)/2; + + /* + * How many colors? + */ + + lpImage->Colors = lpImage->lpbi->bmiHeader.biPlanes + * lpImage->lpbi->bmiHeader.biBitCount; + + /* + * XOR bits follow the header and color table. + */ + + lpImage->lpXOR = (LPBYTE) FindDIBBits((LPSTR) lpImage->lpbi); + + /* + * AND bits follow the XOR bits. + */ + + lpImage->lpAND = lpImage->lpXOR + + lpImage->Height*BytesPerLine((LPBITMAPINFOHEADER) lpImage->lpbi); + return TRUE; +} + +/* + *---------------------------------------------------------------------- + * + * MakeIconOrCursorFromResource -- + * + * Construct an actual HICON structure from the information in a + * resource. + * + * Results: + * Icon + * + *---------------------------------------------------------------------- + */ + +static HICON +MakeIconOrCursorFromResource( + LPICONIMAGE lpIcon, + BOOL isIcon) +{ + HICON hIcon; + + /* + * Sanity Check + */ + + if (lpIcon == NULL || lpIcon->lpBits == NULL) { + return NULL; + } + + /* + * Let the OS do the real work :) + */ + + hIcon = (HICON) CreateIconFromResourceEx(lpIcon->lpBits, + lpIcon->dwNumBytes, isIcon, 0x00030000, + (*(LPBITMAPINFOHEADER) lpIcon->lpBits).biWidth, + (*(LPBITMAPINFOHEADER) lpIcon->lpBits).biHeight/2, 0); + + /* + * It failed, odds are good we're on NT so try the non-Ex way. + */ + + if (hIcon == NULL) { + /* + * We would break on NT if we try with a 16bpp image. + */ + + if (lpIcon->lpbi->bmiHeader.biBitCount != 16) { + hIcon = CreateIconFromResource(lpIcon->lpBits, lpIcon->dwNumBytes, + isIcon, 0x00030000); + } + } + return hIcon; +} + +/* + *---------------------------------------------------------------------- + * + * ReadICOHeader -- + * + * Reads the header from an ICO file, as specfied by channel. + * + * Results: + * UINT - Number of images in file, -1 for failure. If this succeeds, + * there is a decent chance this is a valid icon file. + * + *---------------------------------------------------------------------- + */ + +static int +ReadICOHeader( + Tcl_Channel channel) +{ + union { + WORD word; + char bytes[sizeof(WORD)]; + } input; + + /* + * Read the 'reserved' WORD, which should be a zero word. + */ + + if (Tcl_Read(channel, input.bytes, sizeof(WORD)) != sizeof(WORD)) { + return -1; + } + if (input.word != 0) { + return -1; + } + + /* + * Read the type WORD, which should be of type 1. + */ + + if (Tcl_Read(channel, input.bytes, sizeof(WORD)) != sizeof(WORD)) { + return -1; + } + if (input.word != 1) { + return -1; + } + + /* + * Get and return the count of images. + */ + + if (Tcl_Read(channel, input.bytes, sizeof(WORD)) != sizeof(WORD)) { + return -1; + } + return (int) input.word; +} /* *---------------------------------------------------------------------- @@ -784,7 +1115,551 @@ TkWinGetIcon( return icon; } +/* + *---------------------------------------------------------------------- + * + * ReadIconFromFile -- + * + * Read the contents of a file (usually .ico, .icr) and extract an icon + * resource, if possible, otherwise check if the shell has an icon + * assigned to the given file and use that. If both of those fail, then + * NULL is returned, and an error message will already be in the + * interpreter. + * + * Results: + * A WinIconPtr structure containing the icons in the file, with its ref + * count already incremented. The calling function should either place + * this structure inside a WmInfo structure, or it should pass it on to + * DecrIconRefCount() to ensure no memory leaks occur. + * + * If the given fileName did not contain a valid icon structure, + * return NULL. + * + * Side effects: + * Memory is allocated for the returned structure and the icons it + * contains. If the structure is not wanted, it should be passed to + * DecrIconRefCount, and in any case a valid ref count should be ensured + * to avoid memory leaks. + * + * Currently icon resources are not shared, so the ref count of one of + * these structures will always be 0 or 1. However all we need do is + * implement some sort of lookup function between filenames and + * WinIconPtr structures and no other code will need to be changed. The + * pseudo-code for this is implemented below in the 'if (0)' branch. It + * did not seem necessary to implement this optimisation here, since + * moving to icon<->image conversions will probably make it obsolete. + * + *---------------------------------------------------------------------- + */ + +static WinIconPtr +ReadIconFromFile( + Tcl_Interp *interp, + Tcl_Obj *fileName) +{ + WinIconPtr titlebaricon = NULL; + BlockOfIconImagesPtr lpIR; + +#if 0 /* TODO: Dead code? */ + if (0 /* If we already have an icon for this filename */) { + titlebaricon = NULL; /* Get the real value from a lookup */ + titlebaricon->refCount++; + return titlebaricon; + } +#endif + + /* + * First check if it is a .ico file. + */ + + lpIR = ReadIconOrCursorFromFile(interp, fileName, TRUE); + + /* + * Then see if we can ask the shell for the icon for this file. We + * want both the regular and small icons so that the Alt-Tab (task- + * switching) display uses the right icon. + */ + + if (lpIR == NULL) { + SHFILEINFOW sfiSM; + Tcl_DString ds, ds2; + DWORD *res; + const char *file; + file = Tcl_TranslateFileName(interp, Tcl_GetString(fileName), &ds); + if (file == NULL) { + return NULL; + } + Tcl_DStringInit(&ds2); + res = (DWORD *)SHGetFileInfoW(Tcl_UtfToWCharDString(file, -1, &ds2), 0, &sfiSM, + sizeof(SHFILEINFO), SHGFI_SMALLICON|SHGFI_ICON); + Tcl_DStringFree(&ds); + + if (res != 0) { + SHFILEINFOW sfi; + unsigned size; + + Tcl_ResetResult(interp); + res = (DWORD *)SHGetFileInfoW((WCHAR *)Tcl_DStringValue(&ds2), 0, &sfi, + sizeof(SHFILEINFO), SHGFI_ICON); + + /* + * Account for extra icon, if necessary. + */ + + size = sizeof(BlockOfIconImages) + + ((res != 0) ? sizeof(ICONIMAGE) : 0); + lpIR = (BlockOfIconImagesPtr)ckalloc(size); + if (lpIR == NULL) { + if (res != 0) { + DestroyIcon(sfi.hIcon); + } + DestroyIcon(sfiSM.hIcon); + Tcl_DStringFree(&ds2); + return NULL; + } + ZeroMemory(lpIR, size); + + lpIR->nNumImages = ((res != 0) ? 2 : 1); + lpIR->IconImages[0].Width = 16; + lpIR->IconImages[0].Height = 16; + lpIR->IconImages[0].Colors = 4; + lpIR->IconImages[0].hIcon = sfiSM.hIcon; + + /* + * All other IconImages fields are ignored. + */ + + if (res != 0) { + lpIR->IconImages[1].Width = 32; + lpIR->IconImages[1].Height = 32; + lpIR->IconImages[1].Colors = 4; + lpIR->IconImages[1].hIcon = sfi.hIcon; + } + } + Tcl_DStringFree(&ds2); + } + if (lpIR != NULL) { + titlebaricon = (WinIconPtr)ckalloc(sizeof(WinIconInstance)); + titlebaricon->iconBlock = lpIR; + titlebaricon->refCount = 1; + } + return titlebaricon; +} + +/* + *---------------------------------------------------------------------- + * + * GetIconFromPixmap -- + * + * Turn a Tk Pixmap (i.e. a bitmap) into an icon resource, if possible, + * otherwise NULL is returned. + * + * Results: + * A WinIconPtr structure containing a conversion of the given bitmap + * into an icon, with its ref count already incremented. The calling + * function should either place this structure inside a WmInfo structure, + * or it should pass it on to DecrIconRefCount() to ensure no memory + * leaks occur. + * + * If the given pixmap did not contain a valid icon structure, return + * NULL. + * + * Side effects: + * Memory is allocated for the returned structure and the icons it + * contains. If the structure is not wanted, it should be passed to + * DecrIconRefCount, and in any case a valid ref count should be ensured + * to avoid memory leaks. + * + * Currently icon resources are not shared, so the ref count of one of + * these structures will always be 0 or 1. However all we need do is + * implement some sort of lookup function between pixmaps and WinIconPtr + * structures and no other code will need to be changed. + * + *---------------------------------------------------------------------- + */ + +static WinIconPtr +GetIconFromPixmap( + Display *dsPtr, + Pixmap pixmap) +{ + WinIconPtr titlebaricon = NULL; + TkWinDrawable *twdPtr = (TkWinDrawable *) pixmap; + BlockOfIconImagesPtr lpIR; + ICONINFO icon; + HICON hIcon; + int width, height; + + if (twdPtr == NULL) { + return NULL; + } + +#if 0 /* TODO: Dead code?*/ + if (0 /* If we already have an icon for this pixmap */) { + titlebaricon = NULL; /* Get the real value from a lookup */ + titlebaricon->refCount++; + return titlebaricon; + } +#endif + + Tk_SizeOfBitmap(dsPtr, pixmap, &width, &height); + + icon.fIcon = TRUE; + icon.xHotspot = 0; + icon.yHotspot = 0; + icon.hbmMask = twdPtr->bitmap.handle; + icon.hbmColor = twdPtr->bitmap.handle; + + hIcon = CreateIconIndirect(&icon); + if (hIcon == NULL) { + return NULL; + } + + lpIR = (BlockOfIconImagesPtr)ckalloc(sizeof(BlockOfIconImages)); + if (lpIR == NULL) { + DestroyIcon(hIcon); + return NULL; + } + + lpIR->nNumImages = 1; + lpIR->IconImages[0].Width = width; + lpIR->IconImages[0].Height = height; + lpIR->IconImages[0].Colors = 1 << twdPtr->bitmap.depth; + lpIR->IconImages[0].hIcon = hIcon; + + /* + * These fields are ignored. + */ + + lpIR->IconImages[0].lpBits = 0; + lpIR->IconImages[0].dwNumBytes = 0; + lpIR->IconImages[0].lpXOR = 0; + lpIR->IconImages[0].lpAND = 0; + + titlebaricon = (WinIconPtr)ckalloc(sizeof(WinIconInstance)); + titlebaricon->iconBlock = lpIR; + titlebaricon->refCount = 1; + return titlebaricon; +} + +/* + *---------------------------------------------------------------------- + * + * DecrIconRefCount -- + * + * Reduces the reference count. + * + * Results: + * None. + * + * Side effects: + * If the ref count falls to zero, free the memory associated with the + * icon resource structures. In this case the pointer passed into this + * function is no longer valid. + * + *---------------------------------------------------------------------- + */ + +static void +DecrIconRefCount( + WinIconPtr titlebaricon) +{ + if (titlebaricon->refCount-- <= 1) { + if (titlebaricon->iconBlock != NULL) { + FreeIconBlock(titlebaricon->iconBlock); + } + titlebaricon->iconBlock = NULL; + + ckfree(titlebaricon); + } +} + +/* + *---------------------------------------------------------------------- + * + * FreeIconBlock -- + * + * Frees all memory associated with a previously loaded titlebaricon. + * The icon block pointer is no longer valid once this function returns. + * + * Results: + * None. + * + * Side effects: + * + * + *---------------------------------------------------------------------- + */ + +static void +FreeIconBlock( + BlockOfIconImagesPtr lpIR) +{ + int i; + + /* + * Free all the bits. + */ + + for (i=0 ; inNumImages ; i++) { + if (lpIR->IconImages[i].lpBits != NULL) { + ckfree(lpIR->IconImages[i].lpBits); + } + if (lpIR->IconImages[i].hIcon != NULL) { + DestroyIcon(lpIR->IconImages[i].hIcon); + } + } + ckfree(lpIR); +} + +/* + *---------------------------------------------------------------------- + * + * GetIcon -- + * + * Extracts an icon of a given size from an icon resource + * + * Results: + * Returns the icon, if found, else NULL. + * + *---------------------------------------------------------------------- + */ + +static HICON +GetIcon( + WinIconPtr titlebaricon, + int icon_size) +{ + BlockOfIconImagesPtr lpIR; + unsigned int size = (icon_size == 0 ? 16 : 32); + int i; + + if (titlebaricon == NULL) { + return NULL; + } + + lpIR = titlebaricon->iconBlock; + if (lpIR == NULL) { + return NULL; + } + + for (i=0 ; inNumImages ; i++) { + /* + * Take the first or a 32x32 16 color icon + */ + + if ((lpIR->IconImages[i].Height == size) + && (lpIR->IconImages[i].Width == size) + && (lpIR->IconImages[i].Colors >= 4)) { + return lpIR->IconImages[i].hIcon; + } + } + + /* + * If we get here, then just return the first one, it will have to do! + */ + + if (lpIR->nNumImages >= 1) { + return lpIR->IconImages[0].hIcon; + } + return NULL; +} + +#if 0 /* UNUSED */ +static HCURSOR +TclWinReadCursorFromFile( + Tcl_Interp* interp, + Tcl_Obj* fileName) +{ + BlockOfIconImagesPtr lpIR; + HICON res = NULL; + + lpIR = ReadIconOrCursorFromFile(interp, fileName, FALSE); + if (lpIR == NULL) { + return NULL; + } + if (lpIR->nNumImages >= 1) { + res = CopyImage(lpIR->IconImages[0].hIcon, IMAGE_CURSOR, 0, 0, 0); + } + FreeIconBlock(lpIR); + return res; +} +#endif + +/* + *---------------------------------------------------------------------- + * + * ReadIconOrCursorFromFile -- + * + * Reads an Icon Resource from an ICO file, as given by char* fileName - + * Name of the ICO file. This name should be in Utf format. + * + * Results: + * Returns an icon resource, if found, else NULL. + * + * Side effects: + * May leave error messages in the Tcl interpreter. + * + *---------------------------------------------------------------------- + */ + +static BlockOfIconImagesPtr +ReadIconOrCursorFromFile( + Tcl_Interp *interp, + Tcl_Obj *fileName, + BOOL isIcon) +{ + BlockOfIconImagesPtr lpIR; + Tcl_Channel channel; + int i; + DWORD dwBytesRead; + LPICONDIRENTRY lpIDE; + + /* + * Open the file. + */ + + channel = Tcl_FSOpenFileChannel(interp, fileName, "r", 0); + if (channel == NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "error opening file \"%s\" for reading: %s", + Tcl_GetString(fileName), Tcl_PosixError(interp))); + return NULL; + } + if (Tcl_SetChannelOption(interp, channel, "-translation", "binary") + != TCL_OK) { + Tcl_Close(NULL, channel); + return NULL; + } + if (Tcl_SetChannelOption(interp, channel, "-encoding", "binary") + != TCL_OK) { + Tcl_Close(NULL, channel); + return NULL; + } + + /* + * Allocate memory for the resource structure + */ + + lpIR = (BlockOfIconImagesPtr)ckalloc(sizeof(BlockOfIconImages)); + + /* + * Read in the header + */ + + lpIR->nNumImages = ReadICOHeader(channel); + if (lpIR->nNumImages == -1) { + Tcl_SetObjResult(interp, Tcl_NewStringObj("Invalid file header", -1)); + Tcl_Close(NULL, channel); + ckfree(lpIR); + return NULL; + } + + /* + * Adjust the size of the struct to account for the images. + */ + + lpIR = (BlockOfIconImagesPtr)ckrealloc(lpIR, sizeof(BlockOfIconImages) + + (lpIR->nNumImages - 1) * sizeof(ICONIMAGE)); + + /* + * Allocate enough memory for the icon directory entries. + */ + + lpIDE = (LPICONDIRENTRY)ckalloc(lpIR->nNumImages * sizeof(ICONDIRENTRY)); + + /* + * Read in the icon directory entries. + */ + + dwBytesRead = Tcl_Read(channel, (char *) lpIDE, + (int) (lpIR->nNumImages * sizeof(ICONDIRENTRY))); + if (dwBytesRead != lpIR->nNumImages * sizeof(ICONDIRENTRY)) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "error reading file: %s", Tcl_PosixError(interp))); + Tcl_SetErrorCode(interp, "TK", "WM", "ICON", "READ", NULL); + Tcl_Close(NULL, channel); + ckfree(lpIDE); + ckfree(lpIR); + return NULL; + } + + /* + * NULL-out everything to make memory management easier. + */ + + for (i = 0; i < lpIR->nNumImages; i++) { + lpIR->IconImages[i].lpBits = NULL; + } + + /* + * Loop through and read in each image. + */ + + for (i=0 ; inNumImages ; i++) { + /* + * Allocate memory for the resource. + */ + + lpIR->IconImages[i].lpBits = (LPBYTE)ckalloc(lpIDE[i].dwBytesInRes); + lpIR->IconImages[i].dwNumBytes = lpIDE[i].dwBytesInRes; + + /* + * Seek to beginning of this image. + */ + + if (Tcl_Seek(channel, lpIDE[i].dwImageOffset, FILE_BEGIN) == -1) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "error seeking in file: %s", Tcl_PosixError(interp))); + goto readError; + } + + /* + * Read it in. + */ + + dwBytesRead = Tcl_Read(channel, (char *)lpIR->IconImages[i].lpBits, + (int) lpIDE[i].dwBytesInRes); + if (dwBytesRead != lpIDE[i].dwBytesInRes) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "error reading file: %s", Tcl_PosixError(interp))); + goto readError; + } + + /* + * Set the internal pointers appropriately. + */ + + if (!AdjustIconImagePointers(&lpIR->IconImages[i])) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "Error converting to internal format", -1)); + Tcl_SetErrorCode(interp, "TK", "WM", "ICON", "FORMAT", NULL); + goto readError; + } + lpIR->IconImages[i].hIcon = + MakeIconOrCursorFromResource(&lpIR->IconImages[i], isIcon); + } + + /* + * Clean up + */ + + ckfree(lpIDE); + Tcl_Close(NULL, channel); + return lpIR; + + readError: + Tcl_Close(NULL, channel); + for (i = 0; i < lpIR->nNumImages; i++) { + if (lpIR->IconImages[i].lpBits != NULL) { + ckfree(lpIR->IconImages[i].lpBits); + } + } + ckfree(lpIDE); + ckfree(lpIR); + return NULL; +} /* *---------------------------------------------------------------------- @@ -2482,7 +3357,7 @@ WmColormapwindowsCmd( break; } Tcl_ListObjAppendElement(NULL, resultObj, - TkNewWindowObj((Tk_Window) wmPtr->cmapList[i])); + Tk_NewWindowObj((Tk_Window) wmPtr->cmapList[i])); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; @@ -3643,7 +4518,7 @@ WmIconwindowCmd( } if (objc == 3) { if (wmPtr->icon != NULL) { - Tcl_SetObjResult(interp, TkNewWindowObj(wmPtr->icon)); + Tcl_SetObjResult(interp, Tk_NewWindowObj(wmPtr->icon)); } return TCL_OK; } @@ -4296,7 +5171,7 @@ WmStackorderCmd( resultObj = Tcl_NewObj(); for (windowPtr = windows; *windowPtr ; windowPtr++) { Tcl_ListObjAppendElement(NULL, resultObj, - TkNewWindowObj((Tk_Window) *windowPtr)); + Tk_NewWindowObj((Tk_Window) *windowPtr)); } Tcl_SetObjResult(interp, resultObj); ckfree(windows); @@ -4632,7 +5507,7 @@ WmTransientCmd( } if (objc == 3) { if (masterPtr != NULL) { - Tcl_SetObjResult(interp, TkNewWindowObj((Tk_Window) masterPtr)); + Tcl_SetObjResult(interp, Tk_NewWindowObj((Tk_Window) masterPtr)); } return TCL_OK; } -- cgit v0.12