/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* $XConsortium: icon.c /main/3 1995/10/27 10:39:09 rswiston $ */ /***************************************************************************** ***************************************************************************** ** ** File: icon.c ** ** Description: Icon support functions for the CDE Drag & Drop Demo. ** ** (c) Copyright 1993, 1994 Hewlett-Packard Company ** (c) Copyright 1993, 1994 International Business Machines Corp. ** (c) Copyright 1993, 1994 Sun Microsystems, Inc. ** (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of ** Novell, Inc. ** **************************************************************************** ************************************<+>*************************************/ #include #include #include
#include
#include "icon.h" /************************************************************************* * * Data Structures & Private Declarations For Icon Handling Functions * **************************************************************************/ #define ICON_TEXT_YGAP 2 #define ICON_PATH "/usr/dt/appconfig/icons/C" #define ICON_BITMAP_SUFFIX "m.bm" #define ICON_MASK_SUFFIX "m_m.bm" /* * Default Generic Icon Bitmap & Mask */ #define iconWidth 32 #define iconHeight 32 static unsigned char iconBits[] = { 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x0f, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x88, 0x9d, 0x6d, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x88, 0xf9, 0xed, 0x08, 0x08, 0x00, 0x00, 0x08, 0xc8, 0x6e, 0x7d, 0x08, 0x08, 0x00, 0x00, 0x08, 0xc8, 0x9d, 0xef, 0x09, 0x08, 0x00, 0x00, 0x08, 0xc8, 0xdd, 0xb3, 0x08, 0x08, 0x00, 0x00, 0x08, 0xc8, 0xdf, 0xfd, 0x09, 0x08, 0x00, 0x00, 0x08, 0xc8, 0xf6, 0xde, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x88, 0xed, 0xd2, 0x08, 0x08, 0x00, 0x00, 0x08, 0xc8, 0xbb, 0xf3, 0x08, 0x08, 0x00, 0x00, 0x08, 0x48, 0xdf, 0x5e, 0x08, 0x08, 0x00, 0x00, 0x08, 0xc8, 0x36, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0xf8, 0xff, 0xff, 0x0f}; #define iconMaskWidth 32 #define iconMaskHeight 32 static unsigned char iconMaskBits[] = { 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f}; /* * Blank Bitmap */ #define blankWidth 16 #define blankHeight 16 static unsigned char blankBits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* * Private Icon Handling Function Declarations */ static void iconClearBitmap(Display*, Window, GC, Pixmap, int, int); static Pixmap iconDefaultBitmap(Display*, Window, IconBitmapPart, unsigned short*, unsigned short*); static void iconFree(IconInfo*); static Pixmap iconGetBitmap(Widget, char*, IconBitmapPart, unsigned short*, unsigned short*); static char *iconGetIconPath(void*, int, IconTyping, IconBitmapPart); static Pixmap iconMergeBitmaps(Widget, Pixmap, int, int, Pixmap, int, int, int, int, Boolean); /************************************************************************* * * Public Icon Handling Functions * **************************************************************************/ /* * IconCreateDouble * * Create a double icon from a single icon. The double icon has a bitmap * consisting of 2 images of the original bitmap offset from one another. */ void IconCreateDouble( Widget widget, IconInfo *oldIcon, int xOffset, int yOffset, IconInfo *newIcon, short xx, short yy) { newIcon->bitmap = iconMergeBitmaps(widget, oldIcon->bitmap, oldIcon->icon.width, oldIcon->icon.height, oldIcon->bitmap, oldIcon->icon.width, oldIcon->icon.height, xOffset, yOffset, False); newIcon->mask = iconMergeBitmaps(widget, oldIcon->mask, oldIcon->icon.width, oldIcon->icon.height, oldIcon->mask, oldIcon->icon.width, oldIcon->icon.height, xOffset, yOffset, True); newIcon->icon.width = oldIcon->icon.width + 10; newIcon->icon.height = oldIcon->icon.height + 10; newIcon->name = XtNewString("Multiple"); newIcon->icon.x = xx; newIcon->icon.y = yy; newIcon->dragIcon = DtDndCreateSourceIcon(widget, newIcon->bitmap, newIcon->mask); } /* * IconDelete * * Remove the icon from its list and deallocate memory used by the icon. */ void IconDelete( Widget drawArea, IconInfo *iconPtr) { IconInfo *iconList; if (iconPtr == NULL || drawArea == NULL) { return; } if (iconPtr->next != NULL) { /* iconPtr is not the tail of the list */ iconPtr->next->prev = iconPtr->prev; } if (iconPtr->prev != NULL) { /* iconPtr is not the head of the list */ iconPtr->prev->next = iconPtr->next; } if (iconPtr->next == NULL) { /* iconPtr is the tail of the list */ iconList = iconPtr->prev; } else { iconList = iconPtr->next; } while (iconList != NULL && iconList->prev != NULL) { iconList = iconList->prev; } iconFree(iconPtr); XtVaSetValues(drawArea, XmNuserData, iconList, NULL); } /* * IconDraw * * Render given icon in the window of the given widget. */ void IconDraw( Widget widget, IconInfo *iconPtr) { static GC graphicsContext = NULL; static XFontStruct *fontStruct; Display *display = XtDisplayOfObject(widget); Window window = XtWindow(widget); int screen = DefaultScreen(display); XGCValues gcValues; if (graphicsContext == NULL) { gcValues.foreground = BlackPixel(display, screen); gcValues.background = WhitePixel(display, screen); graphicsContext = XCreateGC(display, window, GCForeground | GCBackground, &gcValues); } /* * Draw icon */ gcValues.clip_mask = iconPtr->mask; gcValues.clip_x_origin = iconPtr->icon.x; gcValues.clip_y_origin = iconPtr->icon.y; XChangeGC(display, graphicsContext, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcValues); XCopyPlane(display, iconPtr->bitmap, window, graphicsContext, 0, 0, iconPtr->icon.width, iconPtr->icon.height, iconPtr->icon.x, iconPtr->icon.y, 1L); /* * Draw icon name centered below icon */ if (iconPtr->name != NULL) { int nameX, nameY; int direction, ascent, decent; XCharStruct overall; Widget xmScreen; if (fontStruct == NULL) { xmScreen = XmGetXmScreen(XtScreen(widget)); XtVaGetValues(xmScreen, XmNfont, &fontStruct, NULL); } XTextExtents(fontStruct, iconPtr->name, strlen(iconPtr->name), &direction, &ascent, &decent, &overall); nameX = (iconPtr->icon.x + (iconPtr->icon.width/2)) - (overall.width/2); nameY = iconPtr->icon.y + iconPtr->icon.height + ICON_TEXT_YGAP + ascent; gcValues.font = fontStruct->fid; gcValues.clip_mask = None; XChangeGC(display, graphicsContext, GCFont | GCClipMask, &gcValues); XDrawString(display, window, graphicsContext, nameX, nameY, iconPtr->name, strlen(iconPtr->name)); } } /* * IconInitialize * * Initialize given icon with given data. Get icon bitmap based on data * associated with the icon. This data may be a file name, a buffer or * a type name. Create source icon for dragging based on the bitmap and mask. */ void IconInitialize( Widget widget, IconInfo *iconPtr, short x, short y, void *data, int dataLen, char *name, IconTyping typing) { char *iconPath; iconPath = iconGetIconPath(data, dataLen, typing, IconMask); iconPtr->mask = iconGetBitmap(widget, iconPath, IconMask, &(iconPtr->icon.width), &(iconPtr->icon.height)); XtFree(iconPath); iconPath = iconGetIconPath(data, dataLen, typing, IconBitmap); iconPtr->bitmap = iconGetBitmap(widget, iconPath, IconBitmap, &(iconPtr->icon.width), &(iconPtr->icon.height)); XtFree(iconPath); iconPtr->icon.x = x; iconPtr->icon.y = y; iconPtr->name = XtNewString(name); iconPtr->dragIcon = DtDndCreateSourceIcon(widget, iconPtr->bitmap, iconPtr->mask); } /* * IconNew * * Allocate memory for a new icon structure and clear. */ IconInfo* IconNew() { IconInfo *iconPtr; iconPtr = (IconInfo*) XtMalloc(sizeof(IconInfo)); memset(iconPtr, 0x00, sizeof(IconInfo)); return iconPtr; } /************************************************************************* * * Private Icon Handling Functions * **************************************************************************/ /* * iconClearBitmap * * Clear a bitmap by filling it with zeros. */ static void iconClearBitmap( Display *display, Window window, GC graphicsContext, Pixmap bitmap, int width, int height) { int xx, yy; static Pixmap blankBitmap = NULL; if (blankBitmap == NULL) { blankBitmap = XCreateBitmapFromData(display, window, (char *)blankBits, blankWidth, blankHeight); } for (xx = 0; xx < width + blankWidth; xx += blankWidth) { for (yy = 0; yy < height + blankHeight; yy += blankHeight) { XCopyArea(display, blankBitmap, bitmap, graphicsContext, 0, 0, blankWidth, blankHeight, xx, yy); } } } /* * iconDefaultBitmap * * Create default icon bitmap or mask and set width and height accordingly. */ static Pixmap iconDefaultBitmap( Display *display, Window window, IconBitmapPart iconPart, unsigned short *width, unsigned short *height) { static Pixmap bitmap; static Pixmap mask; if (iconPart == IconMask) { /* create default mask */ if (mask == NULL) { mask = XCreateBitmapFromData(display, window, (char *)iconMaskBits, iconMaskWidth, iconMaskHeight); } *width = iconMaskWidth; *height = iconMaskHeight; return mask; } else { /* create default bitmap */ if (bitmap == NULL) { bitmap = XCreateBitmapFromData(display, window, (char *)iconBits, iconWidth, iconHeight); } *width = iconWidth; *height = iconHeight; return bitmap; } } /* * iconFree * * Deallocate the icon and associated resources. */ static void iconFree( IconInfo *iconPtr) { Display *display = XtDisplayOfObject(iconPtr->dragIcon); if (iconPtr == NULL) { return; } XtFree(iconPtr->name); /* * REMIND: This needs to free other things too... * XFreePixmap(display, iconPtr->bitmap); * XFreePixmap(display, iconPtr->mask); * Free(iconPtr->dragIcon); */ XtFree((char *)iconPtr); } /* * iconGetBitmap * * Get a bitmap for the icon based on the path and name of the icon. * If no bitmap file is found use a built-in default. */ static Pixmap iconGetBitmap( Widget widget, char *iconPath, IconBitmapPart iconPart, unsigned short *returnWidth, unsigned short *returnHeight) { Display *display = XtDisplayOfObject(widget); Window window = DefaultRootWindow(display); int status; int xHot, yHot; Pixmap bitmap; unsigned int width, height; *returnWidth = *returnHeight = 0; if (iconPath != NULL) { status = XReadBitmapFile(display, window, iconPath, &width, &height, &bitmap, &xHot, &yHot); if (status == BitmapSuccess) { *returnWidth = (unsigned short) width; *returnHeight = (unsigned short) height; } else { printf( "Unable to read icon from bitmap file \"%s\".\n" "Using default icon bitmap.\n", iconPath, NULL); bitmap = iconDefaultBitmap(display, window, iconPart, returnWidth, returnHeight); } } else { bitmap = iconDefaultBitmap(display, window, iconPart, returnWidth, returnHeight); } return bitmap; } /* * iconGetIconPath * * Get the file path and name for an icon based on the given data and * method of typing that data. This function assumes the data typing * database has been loaded with DtDtsLoadDataTypes(). */ static char* iconGetIconPath( void *data, int dataLen, IconTyping typing, IconBitmapPart iconPart) { char iconPath[MAXPATHLEN + 1], *iconName, *iconSuffix; switch (typing) { case IconByFile: iconName = DtDtsFileToAttributeValue(data, "ICON"); break; case IconByData: iconName = DtDtsBufferToAttributeValue(data, dataLen, "ICON", NULL); break; case IconByType: iconName = DtDtsDataTypeToAttributeValue(data, "ICON", NULL); break; default: iconName = NULL; } if (iconName != NULL) { if (iconPart == IconMask) { iconSuffix = ICON_MASK_SUFFIX; } else { iconSuffix = ICON_BITMAP_SUFFIX; } sprintf(iconPath, "%s/%s.%s", ICON_PATH, iconName, iconSuffix); DtDtsFreeAttributeValue(iconName); } return XtNewString(iconPath); } /* * iconMergeBitmaps * * Create new bitmap consisting of the offset composition of the given bitmaps. */ static Pixmap iconMergeBitmaps( Widget widget, Pixmap bitmap1, int width1, int height1, Pixmap bitmap2, int width2, int height2, int xOffset, int yOffset, Boolean clear) { Display *display = XtDisplayOfObject(widget); Window window = DefaultRootWindow(display); int screen = DefaultScreen(display); Pixmap mergedBitmap, blankBitmap; int extraX, extraY, width, height; static GC graphicsContext = NULL; XGCValues gcValues; extraX = width2 - width1 + xOffset + 1; if (extraX < 0) extraX = 0; width = width1 + extraX; extraY = height2 - height1 + yOffset + 1; if (extraY < 0) extraY = 0; height = height1 + extraY; mergedBitmap = XCreatePixmap(display, window, width, height, 1); if (graphicsContext == NULL) { graphicsContext = XCreateGC(display, mergedBitmap, 0L, NULL); } if (clear) { iconClearBitmap(display, window, graphicsContext, mergedBitmap, width, height); } XCopyArea(display, bitmap2, mergedBitmap, graphicsContext, 0, 0, width2, height2, xOffset, yOffset); XCopyArea(display, bitmap1, mergedBitmap, graphicsContext, 0, 0, width1, height1, 0, 0); return mergedBitmap; }