1/*
2 * tkMacOSXBitmap.c --
3 *
4 *	This file handles the implementation of native bitmaps.
5 *
6 * Copyright (c) 1996-1997 Sun Microsystems, Inc.
7 * Copyright 2001, Apple Computer, Inc.
8 * Copyright (c) 2006-2007 Daniel A. Steffen <das@users.sourceforge.net>
9 *
10 * See the file "license.terms" for information on usage and redistribution
11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12 *
13 * RCS: @(#) $Id: tkMacOSXBitmap.c,v 1.2.2.3 2007/04/29 02:26:47 das Exp $
14 */
15
16#include "tkMacOSXInt.h"
17
18/*
19 * Depending on the resource type there are different ways to
20 * draw native icons.
21 */
22#define TYPE1	0		/* Family icon suite. */
23#define TYPE2	1		/* ICON resource. */
24#define TYPE3	2		/* cicn resource. */
25
26/*
27 * This data structure describes the id and type of a given icon.
28 * It is used as the source for native icons.
29 */
30typedef struct {
31    int id;			/* Resource Id for Icon. */
32    long int type;		/* Type of icon. */
33} NativeIcon;
34
35/*
36 * This structure holds information about native bitmaps.
37 */
38
39typedef struct {
40    const char *name;		/* Name of icon. */
41    long int type;		/* Type of icon. */
42    int id;			/* Id of icon. */
43    int size;			/* Size of icon. */
44} BuiltInIcon;
45
46/*
47 * This array mapps a string name to the supported builtin icons
48 * on the Macintosh.
49 */
50
51static BuiltInIcon builtInIcons[] = {
52    {"document",	TYPE1,	kGenericDocumentIconResource,		32},
53    {"stationery",	TYPE1,	kGenericStationeryIconResource,		32},
54    {"edition",		TYPE1,	kGenericEditionFileIconResource,	32},
55    {"application",	TYPE1,	kGenericApplicationIconResource,	32},
56    {"accessory",	TYPE1,	kGenericDeskAccessoryIconResource,	32},
57    {"folder",		TYPE1,	kGenericFolderIconResource,		32},
58    {"pfolder",		TYPE1,	kPrivateFolderIconResource,		32},
59    {"trash",		TYPE1,	kTrashIconResource,			32},
60    {"floppy",		TYPE1,	kFloppyIconResource,			32},
61    {"ramdisk",		TYPE1,	kGenericRAMDiskIconResource,		32},
62    {"cdrom",		TYPE1,	kGenericCDROMIconResource,		32},
63    {"preferences",	TYPE1,	kGenericPreferencesIconResource,	32},
64    {"querydoc",	TYPE1,	kGenericQueryDocumentIconResource,	32},
65    {"stop",		TYPE2,	kStopIcon,				32},
66    {"note",		TYPE2,	kNoteIcon,				32},
67    {"caution",		TYPE2,	kCautionIcon,				32},
68    {NULL,		0,	0,					0}
69};
70
71/*
72 *----------------------------------------------------------------------
73 *
74 * TkpDefineNativeBitmaps --
75 *
76 *	Add native bitmaps.
77 *
78 * Results:
79 *	A standard Tcl result. If an error occurs then TCL_ERROR is
80 *	returned and a message is left in the interp's result.
81 *
82 * Side effects:
83 *	"Name" is entered into the bitmap table and may be used from
84 *	here on to refer to the given bitmap.
85 *
86 *----------------------------------------------------------------------
87 */
88
89void
90TkpDefineNativeBitmaps(void)
91{
92    Tcl_HashTable *tablePtr = TkGetBitmapPredefTable();
93    BuiltInIcon *builtInPtr;
94
95    for (builtInPtr = builtInIcons; builtInPtr->name != NULL; builtInPtr++) {
96	Tcl_HashEntry *predefHashPtr;
97	const char * name;
98	int isNew;
99
100	name = Tk_GetUid(builtInPtr->name);
101	predefHashPtr = Tcl_CreateHashEntry(tablePtr, name, &isNew);
102	if (isNew) {
103	    TkPredefBitmap *predefPtr = (TkPredefBitmap *)
104		    ckalloc(sizeof(TkPredefBitmap));
105	    NativeIcon *nativeIconPtr = (NativeIcon *)
106		    ckalloc(sizeof(NativeIcon));
107
108	    nativeIconPtr->id = builtInPtr->id;
109	    nativeIconPtr->type = builtInPtr->type;
110	    predefPtr->source = (char *) nativeIconPtr;
111	    predefPtr->width = builtInPtr->size;
112	    predefPtr->height = builtInPtr->size;
113	    predefPtr->native = 1;
114	    Tcl_SetHashValue(predefHashPtr, predefPtr);
115	}
116    }
117}
118
119/*
120 *----------------------------------------------------------------------
121 *
122 * TkpCreateNativeBitmap --
123 *
124 *	Add native bitmaps.
125 *
126 * Results:
127 *	A standard Tcl result. If an error occurs then TCL_ERROR is
128 *	returned and a message is left in the interp's result.
129 *
130 * Side effects:
131 *	"Name" is entered into the bitmap table and may be used from
132 *	here on to refer to the given bitmap.
133 *
134 *----------------------------------------------------------------------
135 */
136
137Pixmap
138TkpCreateNativeBitmap(
139    Display *display,
140    CONST char *source)		/* Info about the icon to build. */
141{
142    Pixmap pix;
143    Rect destRect;
144    CGrafPtr savePort;
145    Boolean portChanged;
146    const NativeIcon *nativeIconPtr;
147
148    pix = Tk_GetPixmap(display, None, 32, 32, 0);
149    portChanged = QDSwapPort(TkMacOSXGetDrawablePort(pix), &savePort);
150
151    nativeIconPtr = (const NativeIcon *) source;
152    SetRect(&destRect, 0, 0, 32, 32);
153    if (nativeIconPtr->type == TYPE1) {
154	RGBColor white = {0xFFFF, 0xFFFF, 0xFFFF};
155
156	RGBForeColor(&white);
157	PaintRect(&destRect);
158	PlotIconID(&destRect, atAbsoluteCenter, ttNone, nativeIconPtr->id);
159    } else if (nativeIconPtr->type == TYPE2) {
160	Handle icon = GetIcon(nativeIconPtr->id);
161
162	if (icon != NULL) {
163	    RGBColor black = {0, 0, 0};
164
165	    RGBForeColor(&black);
166	    PlotIcon(&destRect, icon);
167	    ReleaseResource(icon);
168	}
169    }
170
171    if (portChanged) {
172	QDSwapPort(savePort, NULL);
173    }
174    return pix;
175}
176
177/*
178 *----------------------------------------------------------------------
179 *
180 * TkpGetNativeAppBitmap --
181 *
182 *	Add native bitmaps.
183 *
184 * Results:
185 *	A standard Tcl result. If an error occurs then TCL_ERROR is
186 *	returned and a message is left in the interp's result.
187 *
188 * Side effects:
189 *	"Name" is entered into the bitmap table and may be used from
190 *	here on to refer to the given bitmap.
191 *
192 *----------------------------------------------------------------------
193 */
194
195Pixmap
196TkpGetNativeAppBitmap(
197    Display *display,		/* The display. */
198    CONST char *name,		/* The name of the bitmap. */
199    int *width,			/* The width & height of the bitmap. */
200    int *height)
201{
202    Pixmap pix;
203    CGrafPtr savePort;
204    Boolean portChanged;
205    Rect destRect;
206    Handle resource;
207    int type = -1, destWrote;
208    Str255 nativeName;
209    Tcl_Encoding encoding;
210
211    /*
212     * macRoman is the encoding that the resource fork uses.
213     */
214
215    encoding = Tcl_GetEncoding(NULL, "macRoman");
216    Tcl_UtfToExternal(NULL, encoding, name, strlen(name), 0, NULL,
217	    (char *) &nativeName[1], 255, NULL, &destWrote, NULL);
218    nativeName[0] = destWrote;
219    Tcl_FreeEncoding(encoding);
220
221    resource = GetNamedResource('cicn', nativeName);
222    if (resource != NULL) {
223	type = TYPE3;
224    } else {
225	resource = GetNamedResource('ICON', nativeName);
226	if (resource != NULL) {
227	    type = TYPE2;
228	}
229    }
230
231    if (resource == NULL) {
232	return (Pixmap) NULL;
233    }
234
235    pix = Tk_GetPixmap(display, None, 32, 32, 0);
236    portChanged = QDSwapPort(TkMacOSXGetDrawablePort(pix), &savePort);
237
238    SetRect(&destRect, 0, 0, 32, 32);
239    if (type == TYPE2) {
240	RGBColor black = {0, 0, 0};
241
242	RGBForeColor(&black);
243	PlotIcon(&destRect, resource);
244	ReleaseResource(resource);
245    } else if (type == TYPE3) {
246	RGBColor white = {0xFFFF, 0xFFFF, 0xFFFF};
247	short id;
248	ResType theType;
249	Str255 dummy;
250
251	/*
252	 * We need to first paint the background white. Also, for
253	 * some reason we *must* use GetCIcon instead of GetNamedResource
254	 * for PlotCIcon to work - so we use GetResInfo to get the id.
255	 */
256
257	RGBForeColor(&white);
258	PaintRect(&destRect);
259	GetResInfo(resource, &id, &theType, dummy);
260	ReleaseResource(resource);
261	resource = (Handle) GetCIcon(id);
262	PlotCIcon(&destRect, (CIconHandle) resource);
263	DisposeCIcon((CIconHandle) resource);
264    }
265
266    *width = 32;
267    *height = 32;
268    if (portChanged) {
269	QDSwapPort(savePort, NULL);
270    }
271    return pix;
272}
273