mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
1052 lines
26 KiB
C
1052 lines
26 KiB
C
/*
|
||
* 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
|
||
*/
|
||
/*
|
||
* (c) Copyright 1989, 1990, 1991, 1992, 1993 OPEN SOFTWARE FOUNDATION, INC.
|
||
* ALL RIGHTS RESERVED
|
||
*/
|
||
/*
|
||
* Motif Release 1.2.3
|
||
*/
|
||
/*
|
||
* (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
|
||
|
||
/*
|
||
* Included Files:
|
||
*/
|
||
|
||
#include "WmGlobal.h"
|
||
|
||
#define MWM_NEED_IIMAGE
|
||
#include "WmIBitmap.h"
|
||
|
||
#include <Xm/XmosP.h>
|
||
/* Copied from XmosI.h */
|
||
extern String _XmOSInitPath(
|
||
String file_name,
|
||
String env_pathname,
|
||
Boolean *user_path) ;
|
||
#include <Xm/IconFile.h>
|
||
#include <Dt/GetDispRes.h>
|
||
|
||
#define MATCH_XBM 'B' /* .xbm character: see XmGetPixmap */
|
||
#define MATCH_PATH "XBMLANGPATH"
|
||
|
||
/*
|
||
* include extern functions
|
||
*/
|
||
|
||
#include "WmImage.h"
|
||
#include "WmGraphics.h"
|
||
#include "WmResource.h"
|
||
#include "WmResParse.h"
|
||
#include "WmMenu.h"
|
||
#include "WmError.h"
|
||
|
||
/******************************<->*************************************
|
||
*
|
||
* MakeClientIconPixmap (pCD, iconBitmap, iconMask)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* This function takes a client supplied icon image pixmap and mask
|
||
* bitmap and makes it into a colored pixmap suitable for use as an
|
||
* icon image.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pCD = pointer to client data (icon colors and tiles)
|
||
*
|
||
* iconBitmap = icon bitmap
|
||
* iconMask = mask bitmap
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* RETURN = icon pixmap (NULL if error)
|
||
*
|
||
******************************<->***********************************/
|
||
|
||
Pixmap MakeClientIconPixmap (
|
||
ClientData *pCD,
|
||
Pixmap iconBitmap,
|
||
Pixmap iconMask)
|
||
{
|
||
Window root;
|
||
int x;
|
||
int y;
|
||
unsigned int bitmapWidth;
|
||
unsigned int bitmapHeight;
|
||
unsigned int border;
|
||
unsigned int depth;
|
||
|
||
|
||
/*
|
||
* Check out the attributes of the bitmap to insure that it is usable.
|
||
*/
|
||
|
||
if (!XGetGeometry (DISPLAY, iconBitmap, &root, &x, &y,
|
||
&bitmapWidth, &bitmapHeight, &border, &depth))
|
||
{
|
||
Warning (((char *)GETMESSAGE(38, 1, "Invalid icon bitmap")));
|
||
return ((Pixmap)NULL);
|
||
}
|
||
|
||
if (ROOT_FOR_CLIENT(pCD) != root)
|
||
{
|
||
/*
|
||
* The bitmap was not made with usable parameters.
|
||
*/
|
||
Warning (((char *)GETMESSAGE(38, 9, "Icon bitmap cannot be used on this screen")));
|
||
return ((Pixmap)NULL);
|
||
}
|
||
|
||
#ifdef DISALLOW_DEEP_ICONS
|
||
if (depth != 1)
|
||
{
|
||
Warning (((char *)GETMESSAGE(38, 10, "Color icon pixmap not supported")));
|
||
return ((Pixmap)NULL);
|
||
}
|
||
#endif
|
||
|
||
/*
|
||
* Color the bitmap, center it in a pixmap ....
|
||
*/
|
||
|
||
return (MakeIconPixmap (pCD, iconBitmap, (Pixmap)iconMask,
|
||
bitmapWidth, bitmapHeight, depth));
|
||
|
||
|
||
} /* END OF FUNCTION MakeClientIconPixmap */
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* MakeNamedIconPixmap (pCD, iconName)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* This function makes an icon pixmap for a particular client given the
|
||
* name of a bitmap file.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pCD = (nonNULL) pointer to client data
|
||
* iconName = pointer to the icon name (bitmap file path name or NULL)
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* RETURN = icon pixmap or NULL
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
Pixmap MakeNamedIconPixmap (ClientData *pCD, String iconName)
|
||
{
|
||
int bitmapIndex;
|
||
Pixmap pixmap, pixmap_r, mask;
|
||
Window root;
|
||
int x, y;
|
||
unsigned int width, height, border_width, depth;
|
||
String sIconFileName;
|
||
int iconSizeDesired;
|
||
|
||
/*
|
||
* Get the bitmap cache entry (will read data from file if necessary).
|
||
* If unable to find the iconName file return NULL.
|
||
*/
|
||
|
||
if ((bitmapIndex = GetBitmapIndex (PSD_FOR_CLIENT(pCD), iconName,
|
||
False)) < 0)
|
||
{
|
||
if ((PSD_FOR_CLIENT(pCD)->displayResolutionType == LOW_RES_DISPLAY) ||
|
||
(PSD_FOR_CLIENT(pCD)->displayResolutionType == VGA_RES_DISPLAY))
|
||
{
|
||
iconSizeDesired = XmMEDIUM_ICON_SIZE;
|
||
}
|
||
else
|
||
{
|
||
iconSizeDesired = XmLARGE_ICON_SIZE;
|
||
}
|
||
|
||
pixmap = XmUNSPECIFIED_PIXMAP;
|
||
|
||
sIconFileName = XmGetIconFileName(
|
||
XtScreen(PSD_FOR_CLIENT(pCD)->screenTopLevelW1),
|
||
NULL,
|
||
iconName,
|
||
NULL,
|
||
iconSizeDesired);
|
||
|
||
if (sIconFileName != NULL)
|
||
{
|
||
pixmap = XmGetPixmap (
|
||
XtScreen (PSD_FOR_CLIENT(pCD)->screenTopLevelW1),
|
||
sIconFileName,
|
||
pCD->iconImageForeground,
|
||
pCD->iconImageBackground);
|
||
}
|
||
|
||
if (pixmap == XmUNSPECIFIED_PIXMAP)
|
||
{
|
||
pixmap = XmGetPixmap (
|
||
XtScreen (PSD_FOR_CLIENT(pCD)->screenTopLevelW1),
|
||
iconName,
|
||
pCD->iconImageForeground,
|
||
pCD->iconImageBackground);
|
||
}
|
||
|
||
if (pixmap == XmUNSPECIFIED_PIXMAP)
|
||
{
|
||
MWarning (((char *)GETMESSAGE(38, 7, "Unable to read bitmap file %s\n")), iconName);
|
||
}
|
||
else
|
||
{
|
||
mask = XmeGetMask (XtScreen(PSD_FOR_CLIENT(pCD)->screenTopLevelW1),
|
||
(sIconFileName == NULL) ? iconName : sIconFileName);
|
||
if (mask == XmUNSPECIFIED_PIXMAP)
|
||
{
|
||
mask = (Pixmap) NULL;
|
||
}
|
||
|
||
if (sIconFileName != NULL)
|
||
XtFree(sIconFileName);
|
||
|
||
/*
|
||
* We need to synchronize DISPLAY1 here because the pixmap and mask
|
||
* were created on that display connection, and we must ensure that
|
||
* the server has processed those requests before we attempt to use
|
||
* the pixmap and mask on DISPLAY. We thus assume that the
|
||
* subsequent XGetGeometry() call is successful.
|
||
*/
|
||
XSync(DISPLAY1, False);
|
||
|
||
(void) XGetGeometry (DISPLAY, pixmap, &root, &x, &y, &width,
|
||
&height, &border_width, &depth);
|
||
|
||
pixmap_r = MakeIconPixmap (pCD, pixmap, mask,
|
||
width, height, depth);
|
||
|
||
XmDestroyPixmap (XtScreen (PSD_FOR_CLIENT(pCD)->screenTopLevelW1),
|
||
pixmap);
|
||
if (mask)
|
||
XmDestroyPixmap (
|
||
XtScreen (PSD_FOR_CLIENT(pCD)->screenTopLevelW1), mask);
|
||
|
||
return (pixmap_r);
|
||
}
|
||
|
||
if (sIconFileName != NULL)
|
||
XtFree (sIconFileName);
|
||
return ((Pixmap)NULL);
|
||
}
|
||
|
||
/*
|
||
* Color the bitmap, center it in a pixmap ....
|
||
*/
|
||
|
||
return (MakeCachedIconPixmap (pCD, bitmapIndex, (Pixmap)NULL));
|
||
|
||
} /* END OF FUNCTION MakeNamedIconPixmap */
|
||
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* Pixmap
|
||
* MakeCachedIconPixmap (pCD, bitmapIndex, mask)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Convert the cached bitmap and mask into an icon pixmap.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pCD - (nonNULL) pointer to client data (icon colors and tiles)
|
||
* bitmapIndex - bitmap cache index of image to be converted
|
||
* mask - bitmap mask, 1 for bits of "bitmap" to be kept
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* RETURN - icon pixmap or NULL
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* o "mask" is not used.
|
||
*
|
||
*************************************<->***********************************/
|
||
Pixmap MakeCachedIconPixmap (ClientData *pCD, int bitmapIndex, Pixmap mask)
|
||
{
|
||
BitmapCache *bitmapc;
|
||
PixmapCache *pixmapc;
|
||
Pixmap pixmap = (Pixmap)NULL;
|
||
WmScreenData *pSD = PSD_FOR_CLIENT(pCD);
|
||
|
||
if (bitmapIndex < 0)
|
||
{
|
||
return ((Pixmap)NULL);
|
||
}
|
||
bitmapc = &(pSD->bitmapCache[bitmapIndex]);
|
||
|
||
/*
|
||
* Search for an icon pixmap matching the client icon colors.
|
||
*/
|
||
|
||
pixmapc = bitmapc->pixmapCache;
|
||
while (pixmapc)
|
||
{
|
||
if ((pixmapc->pixmapType == ICON_PIXMAP) &&
|
||
(pixmapc->foreground == pCD->iconImageForeground) &&
|
||
(pixmapc->background == pCD->iconImageBackground))
|
||
{
|
||
pixmap = pixmapc->pixmap;
|
||
break;
|
||
}
|
||
pixmapc = pixmapc->next;
|
||
}
|
||
|
||
/*
|
||
* If a matching pixmap was not found in the pixmap cache for this bitmap
|
||
* then create the icon pixmap with the appropriate colors.
|
||
* If have sufficient memory, save the pixmap info in the pixmapCache.
|
||
*/
|
||
|
||
if (!pixmap &&
|
||
(pixmap = MakeIconPixmap (pCD, bitmapc->bitmap, mask,
|
||
bitmapc->width, bitmapc->height, 1)) &&
|
||
(pixmapc = (PixmapCache *) XtMalloc (sizeof (PixmapCache))))
|
||
{
|
||
|
||
pixmapc->pixmapType = ICON_PIXMAP;
|
||
pixmapc->foreground = pCD->iconImageForeground;
|
||
pixmapc->background = pCD->iconImageBackground;
|
||
pixmapc->pixmap = pixmap;
|
||
pixmapc->next = bitmapc->pixmapCache;
|
||
bitmapc->pixmapCache = pixmapc;
|
||
}
|
||
|
||
return (pixmap);
|
||
|
||
} /* END OF FUNCTION MakeCachedIconPixmap */
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* MakeIconPixmap (pCD, bitmap, mask, width, height, depth)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Convert the bitmap and mask into an icon pixmap.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pCD - pointer to client data (icon colors and tiles)
|
||
* pWS - pointer to workspace data
|
||
* bitmap - bitmap image to be converted
|
||
* mask - bitmap mask, 1 for bits of "bitmap" to be kept
|
||
* width - pixel width of bitmap
|
||
* height - pixel height of bitmap
|
||
* depth - depth of bitmap (pixmap, really)
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* RETURN - icon pixmap or NULL
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* o "mask" is not used.
|
||
*
|
||
*************************************<->***********************************/
|
||
Pixmap MakeIconPixmap (ClientData *pCD, Pixmap bitmap, Pixmap mask, unsigned int width, unsigned int height, unsigned int depth)
|
||
{
|
||
Pixmap iconPixmap;
|
||
GC imageGC, topGC, botGC;
|
||
XGCValues gcv;
|
||
unsigned long gc_mask;
|
||
XmPixelSet *pPS = NULL;
|
||
unsigned int imageWidth;
|
||
unsigned int imageHeight;
|
||
int dest_x, dest_y;
|
||
#ifndef NO_CLIP_CENTER
|
||
int src_x, src_y;
|
||
#endif /* NO_CLIP_CENTER */
|
||
Pixel fg;
|
||
Pixel bg;
|
||
static RList *top_rects = NULL;
|
||
static RList *bot_rects = NULL;
|
||
WmScreenData *pSD;
|
||
|
||
if ((top_rects == NULL) &&
|
||
(top_rects = AllocateRList
|
||
((unsigned)2 * ICON_INTERNAL_SHADOW_WIDTH)) == NULL)
|
||
{
|
||
/* Out of memory! */
|
||
Warning (((char *)GETMESSAGE(38, 3, "Insufficient memory to bevel icon image")));
|
||
return ((Pixmap)NULL);
|
||
}
|
||
|
||
if ((bot_rects == NULL) &&
|
||
(bot_rects = AllocateRList
|
||
((unsigned)2 * ICON_INTERNAL_SHADOW_WIDTH)) == NULL)
|
||
{
|
||
/* Out of memory! */
|
||
Warning (((char *)GETMESSAGE(38, 4, "Insufficient memory to bevel icon image")));
|
||
return ((Pixmap)NULL);
|
||
}
|
||
|
||
if (pCD)
|
||
{
|
||
pSD = pCD->pSD;
|
||
}
|
||
else
|
||
{
|
||
pSD = wmGD.pActiveSD;
|
||
}
|
||
|
||
/* don't make icon pixmap if bitmap is too small */
|
||
|
||
if ((width < pSD->iconImageMinimum.width) ||
|
||
(height < pSD->iconImageMinimum.height))
|
||
{
|
||
/* bitmap is too small */
|
||
return ((Pixmap)NULL);
|
||
}
|
||
#ifndef NO_CLIP_CENTER
|
||
|
||
/* copy the center of the icon if too big */
|
||
if (width > pSD->iconImageMaximum.width)
|
||
{
|
||
src_x = (width - pSD->iconImageMaximum.width)/2;
|
||
}
|
||
else
|
||
{
|
||
src_x = 0;
|
||
}
|
||
if (height > pSD->iconImageMaximum.height)
|
||
{
|
||
src_y = (height - pSD->iconImageMaximum.height)/2;
|
||
}
|
||
else
|
||
{
|
||
src_y = 0;
|
||
}
|
||
#endif /* NO_CLIP_CENTER */
|
||
|
||
/*
|
||
* SLAB frameStyle adds a single pixel of background color around
|
||
* the image to set it off from the beveling.
|
||
*/
|
||
imageWidth = pSD->iconImageMaximum.width +
|
||
2 * ICON_INTERNAL_SHADOW_WIDTH +
|
||
((wmGD.frameStyle == WmSLAB) ? 2 : 0);
|
||
imageHeight = pSD->iconImageMaximum.height +
|
||
2 * ICON_INTERNAL_SHADOW_WIDTH +
|
||
((wmGD.frameStyle == WmSLAB) ? 2 : 0);
|
||
|
||
/* create a pixmap (to be returned) */
|
||
|
||
iconPixmap = XCreatePixmap (DISPLAY, pSD->rootWindow,
|
||
imageWidth, imageHeight,
|
||
DefaultDepth(DISPLAY, pSD->screen));
|
||
|
||
/*
|
||
* If a client is not specified use icon component colors, otherwise
|
||
* use the client-specific icon colors.
|
||
*/
|
||
|
||
if (pCD)
|
||
{
|
||
bg = pCD->iconImageBackground;
|
||
fg = pCD->iconImageForeground;
|
||
}
|
||
else
|
||
{
|
||
bg = pSD->iconAppearance.background;
|
||
fg = pSD->iconAppearance.foreground;
|
||
}
|
||
|
||
/* create a GC to use */
|
||
gc_mask = GCForeground | GCBackground | GCGraphicsExposures;
|
||
if (mask)
|
||
{
|
||
if (pSD->pPrimaryPixelSet != NULL)
|
||
{
|
||
pPS = pSD->pPrimaryPixelSet;
|
||
gcv.background = pPS->bg;
|
||
/* set fg to bg color to clear it first */
|
||
gcv.foreground = pPS->bg;
|
||
}
|
||
else
|
||
{
|
||
gcv.background = ICON_APPEARANCE(pCD).background;
|
||
/* set fg to bg color to clear it first */
|
||
gcv.foreground = ICON_APPEARANCE(pCD).background;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
gcv.foreground = bg; /* clear it first! */
|
||
gcv.background = bg;
|
||
}
|
||
gcv.graphics_exposures = False;
|
||
|
||
imageGC = XCreateGC (DISPLAY, iconPixmap, gc_mask, &gcv);
|
||
|
||
/*
|
||
* Format the image.
|
||
*/
|
||
|
||
/* fill in background */
|
||
|
||
XFillRectangle(DISPLAY, iconPixmap, imageGC, 0, 0,
|
||
imageWidth, imageHeight);
|
||
|
||
/* center the image */
|
||
|
||
if (width > pSD->iconImageMaximum.width)
|
||
{
|
||
width = pSD->iconImageMaximum.width;
|
||
}
|
||
if (height > pSD->iconImageMaximum.height)
|
||
{
|
||
height = pSD->iconImageMaximum.height;
|
||
}
|
||
/* center the image */
|
||
|
||
dest_x = (imageWidth - width) / 2;
|
||
dest_y = (imageHeight - height) / 2;
|
||
|
||
if (mask)
|
||
{
|
||
if (pPS != NULL)
|
||
{
|
||
gcv.foreground = pPS->fg;
|
||
}
|
||
else
|
||
{
|
||
gcv.foreground = ICON_APPEARANCE(pCD).foreground;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
gcv.foreground = fg;
|
||
}
|
||
gc_mask = GCForeground;
|
||
if (mask)
|
||
{
|
||
gcv.clip_mask = mask;
|
||
#ifndef NO_CLIP_CENTER
|
||
gcv.clip_x_origin = dest_x - src_x;
|
||
gcv.clip_y_origin = dest_y - src_y;
|
||
#else /* NO_CLIP_CENTER */
|
||
gcv.clip_x_origin = dest_x;
|
||
gcv.clip_y_origin = dest_y;
|
||
#endif /* NO_CLIP_CENTER */
|
||
gc_mask |= GCClipXOrigin | GCClipYOrigin | GCClipMask;
|
||
}
|
||
|
||
XChangeGC (DISPLAY, imageGC, gc_mask, &gcv);
|
||
|
||
/* copy the bitmap to the pixmap */
|
||
#ifndef DISALLOW_DEEP_ICONS
|
||
if ((depth > 1) &&
|
||
(depth == DefaultDepth(DISPLAY, pSD->screen)))
|
||
{
|
||
#ifndef NO_CLIP_CENTER
|
||
XCopyArea (DISPLAY, bitmap, iconPixmap, imageGC, src_x, src_y,
|
||
width, height, dest_x, dest_y);
|
||
#else /* NO_CLIP_CENTER */
|
||
XCopyArea (DISPLAY, bitmap, iconPixmap, imageGC, 0, 0,
|
||
width, height, dest_x, dest_y);
|
||
#endif /* NO_CLIP_CENTER */
|
||
}
|
||
else
|
||
#endif /* DISALLOW_DEEP_ICONS */
|
||
#ifndef NO_CLIP_CENTER
|
||
XCopyPlane (DISPLAY, bitmap, iconPixmap, imageGC, src_x, src_y, width,
|
||
height, dest_x, dest_y, 1L);
|
||
#else /* NO_CLIP_CENTER */
|
||
XCopyPlane (DISPLAY, bitmap, iconPixmap, imageGC, 0, 0, width, height,
|
||
dest_x, dest_y, 1L);
|
||
#endif /* NO_CLIP_CENTER */
|
||
|
||
/* free resources */
|
||
XFreeGC (DISPLAY, imageGC);
|
||
|
||
if (pCD)
|
||
{
|
||
/*
|
||
* Shadowing
|
||
*/
|
||
|
||
if (mask && (pPS != NULL))
|
||
{
|
||
topGC = GetHighlightGC (pSD, pPS->ts, pPS->bg,
|
||
pCD->iconImageTopShadowPixmap);
|
||
|
||
botGC = GetHighlightGC (pSD, pPS->bs, pPS->bg,
|
||
pCD->iconImageBottomShadowPixmap);
|
||
}
|
||
else
|
||
{
|
||
topGC = GetHighlightGC (pSD, pCD->iconImageTopShadowColor,
|
||
pCD->iconImageBackground,
|
||
pCD->iconImageTopShadowPixmap);
|
||
|
||
botGC = GetHighlightGC (pSD, pCD->iconImageBottomShadowColor,
|
||
pCD->iconImageBackground,
|
||
pCD->iconImageBottomShadowPixmap);
|
||
}
|
||
|
||
/*
|
||
* CR5208 - Better fix than from OSF!
|
||
* Zero out the rectangle count in our
|
||
* static structures so that BevelRectangle
|
||
* won't extend the RList causing a memory leak.
|
||
* Old fix allocated and freed rectangle structure
|
||
* each time through.
|
||
*/
|
||
top_rects->used = 0; /* reset count */
|
||
bot_rects->used = 0;
|
||
|
||
BevelRectangle (top_rects,
|
||
bot_rects,
|
||
0, 0,
|
||
imageWidth, imageHeight,
|
||
ICON_INTERNAL_SHADOW_WIDTH,
|
||
ICON_INTERNAL_SHADOW_WIDTH,
|
||
ICON_INTERNAL_SHADOW_WIDTH,
|
||
ICON_INTERNAL_SHADOW_WIDTH);
|
||
|
||
XFillRectangles (DISPLAY, iconPixmap, topGC, top_rects->prect,
|
||
top_rects->used);
|
||
XFillRectangles (DISPLAY, iconPixmap, botGC, bot_rects->prect,
|
||
bot_rects->used);
|
||
}
|
||
return (iconPixmap);
|
||
|
||
} /* END OF FUNCTION MakeIconPixmap */
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* Pixmap
|
||
* MakeCachedLabelPixmap (pSD, menuW, bitmapIndex)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Creates and returns a label pixmap.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pSD = pointer to screen data
|
||
* menuW = menu widget (for foreground and background colors)
|
||
* bitmapIndex = bitmap cache index
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Return = label pixmap or NULL.
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* Assumes bitmapIndex is valid.
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
Pixmap MakeCachedLabelPixmap (WmScreenData *pSD, Widget menuW, int bitmapIndex)
|
||
{
|
||
BitmapCache *bitmapc;
|
||
PixmapCache *pixmapc;
|
||
int i;
|
||
Arg args[5];
|
||
Pixel fg, bg;
|
||
Pixmap pixmap = (Pixmap)NULL;
|
||
GC gc;
|
||
XGCValues gcv;
|
||
|
||
if (bitmapIndex < 0)
|
||
{
|
||
return ((Pixmap)NULL);
|
||
}
|
||
bitmapc = &(pSD->bitmapCache[bitmapIndex]);
|
||
|
||
/*
|
||
* Get the foreground and background colors from the menu widget.
|
||
* Search for a label pixmap matching those colors.
|
||
*/
|
||
|
||
i = 0;
|
||
XtSetArg (args[i], XtNforeground, &fg); i++;
|
||
XtSetArg (args[i], XtNbackground, &bg); i++;
|
||
XtGetValues (menuW, (ArgList)args, i);
|
||
|
||
pixmapc = bitmapc->pixmapCache;
|
||
while (pixmapc)
|
||
{
|
||
if ((pixmapc->pixmapType == LABEL_PIXMAP) &&
|
||
(pixmapc->foreground == fg) &&
|
||
(pixmapc->background == bg))
|
||
{
|
||
pixmap = pixmapc->pixmap;
|
||
break;
|
||
}
|
||
pixmapc = pixmapc->next;
|
||
}
|
||
|
||
if (!pixmap)
|
||
/*
|
||
* A matching pixmap was not found in the pixmap cache for this bitmap.
|
||
* Create and save the label pixmap with appropriate colors.
|
||
*/
|
||
{
|
||
/*
|
||
* Create a pixmap of the appropriate size, root, and depth.
|
||
* Only BadAlloc error possible; BadDrawable and BadValue are avoided.
|
||
*/
|
||
|
||
pixmap = XCreatePixmap (DISPLAY, pSD->rootWindow,
|
||
bitmapc->width, bitmapc->height,
|
||
DefaultDepth (DISPLAY, pSD->screen));
|
||
|
||
/*
|
||
* Create a GC and copy the bitmap to the pixmap.
|
||
* Only BadAlloc and BadDrawable errors are possible; others are avoided
|
||
*/
|
||
|
||
gcv.foreground = bg;
|
||
gcv.background = bg;
|
||
gcv.graphics_exposures = False;
|
||
gc = XCreateGC(DISPLAY, pixmap, (GCForeground|GCBackground), &gcv);
|
||
|
||
/*
|
||
* Fill in the background, set the foreground, copy the bitmap to the
|
||
* pixmap, and free the gc.
|
||
*/
|
||
|
||
XFillRectangle (DISPLAY, pixmap, gc, 0, 0,
|
||
bitmapc->width, bitmapc->height);
|
||
XSetForeground (DISPLAY, gc, fg);
|
||
XCopyPlane (DISPLAY, bitmapc->bitmap, pixmap, gc, 0, 0,
|
||
bitmapc->width, bitmapc->height, 0, 0, 1L);
|
||
XFreeGC (DISPLAY, gc);
|
||
|
||
/*
|
||
* If have sufficient memory, save the pixmap info in the pixmapCache.
|
||
*/
|
||
|
||
if ((pixmapc = (PixmapCache *) XtMalloc(sizeof(PixmapCache))) != NULL)
|
||
{
|
||
pixmapc->pixmapType = LABEL_PIXMAP;
|
||
pixmapc->foreground = fg;
|
||
pixmapc->background = bg;
|
||
pixmapc->pixmap = pixmap;
|
||
pixmapc->next = bitmapc->pixmapCache;
|
||
bitmapc->pixmapCache = pixmapc;
|
||
}
|
||
}
|
||
|
||
return (pixmap);
|
||
|
||
} /* END OF FUNCTION MakeCachedLabelPixmap */
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* int
|
||
* GetBitmapIndex (pSD, name)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Retrieve bitmap from cache.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pSD = pointer to screen data
|
||
* name = bitmap file name or NULL pointer
|
||
* bitmapCache[]
|
||
* bitmapCacheSize
|
||
* bitmapCacheCount
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* bitmapCache[]
|
||
* bitmapCacheSize
|
||
* bitmapCacheCount
|
||
* Return = bitmap cache index or -1
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* None
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
#define BITMAP_CACHE_INC 5
|
||
|
||
int GetBitmapIndex (WmScreenData *pSD, char *name, Boolean bReportError)
|
||
{
|
||
char *path;
|
||
BitmapCache *bitmapc;
|
||
unsigned int n;
|
||
int x, y;
|
||
|
||
/*
|
||
* Search a nonempty bitmap cache for a pathname match.
|
||
*/
|
||
path = BitmapPathName (name);
|
||
for (n = 0, bitmapc = pSD->bitmapCache;
|
||
n < pSD->bitmapCacheCount;
|
||
n++, bitmapc++)
|
||
{
|
||
if ((!path && !bitmapc->path) ||
|
||
(path && bitmapc->path &&
|
||
!strcmp (path, bitmapc->path)))
|
||
{
|
||
return (n);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* The bitmap path name was not found in bitmapCache.
|
||
* Find the next BitmapCache entry, creating or enlarging bitmapCache if
|
||
* necessary.
|
||
*/
|
||
if (pSD->bitmapCacheSize == 0)
|
||
/* create */
|
||
{
|
||
pSD->bitmapCacheSize = BITMAP_CACHE_INC;
|
||
pSD->bitmapCache =
|
||
(BitmapCache *) XtMalloc (BITMAP_CACHE_INC * sizeof (BitmapCache));
|
||
}
|
||
else if (pSD->bitmapCacheCount == pSD->bitmapCacheSize)
|
||
/* enlarge */
|
||
{
|
||
pSD->bitmapCacheSize += BITMAP_CACHE_INC;
|
||
pSD->bitmapCache = (BitmapCache *)
|
||
XtRealloc ((char*)pSD->bitmapCache,
|
||
pSD->bitmapCacheSize * sizeof (BitmapCache));
|
||
}
|
||
|
||
if (pSD->bitmapCache == NULL)
|
||
{
|
||
MWarning (((char *)GETMESSAGE(38, 5, "Insufficient memory for bitmap %s\n")), name);
|
||
pSD->bitmapCacheSize = 0;
|
||
pSD->bitmapCacheCount = 0;
|
||
return (-1);
|
||
}
|
||
|
||
bitmapc = &(pSD->bitmapCache[pSD->bitmapCacheCount]);
|
||
|
||
/*
|
||
* Fill the entry with the bitmap info.
|
||
* A NULL path indicates the builtin icon bitmap.
|
||
* Indicate that no pixmapCache exists yet.
|
||
*/
|
||
|
||
if (path)
|
||
{
|
||
if ((bitmapc->path = (String)
|
||
XtMalloc ((unsigned int)(strlen (path) + 1))) == NULL)
|
||
{
|
||
MWarning (((char *)GETMESSAGE(38, 6, "Insufficient memory for bitmap %s\n")), name);
|
||
return (-1);
|
||
}
|
||
strcpy (bitmapc->path, path);
|
||
|
||
if (XReadBitmapFile (DISPLAY, pSD->rootWindow, path,
|
||
&bitmapc->width, &bitmapc->height,
|
||
&bitmapc->bitmap, &x, &y)
|
||
!= BitmapSuccess)
|
||
{
|
||
if (bReportError)
|
||
MWarning (((char *)GETMESSAGE(38, 7, "Unable to read bitmap file %s\n")), path);
|
||
XtFree ((char *)bitmapc->path);
|
||
return (-1);
|
||
}
|
||
|
||
if (bitmapc->width == 0 || bitmapc->height == 0)
|
||
{
|
||
if (bReportError)
|
||
MWarning (((char *)GETMESSAGE(38, 8, "Invalid bitmap file %s\n")), path);
|
||
XtFree ((char *)bitmapc->path);
|
||
return (-1);
|
||
}
|
||
}
|
||
else
|
||
/* builtin icon bitmap */
|
||
{
|
||
bitmapc->path = NULL;
|
||
bitmapc->bitmap = pSD->builtinIconPixmap;
|
||
bitmapc->width = iImage_width;
|
||
bitmapc->height = iImage_height;
|
||
}
|
||
|
||
bitmapc->pixmapCache = NULL;
|
||
|
||
return (pSD->bitmapCacheCount++);
|
||
|
||
} /* END OF FUNCTION GetBitmapIndex */
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* BitmapPathName (string)
|
||
*
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Constructs a bitmap file pathname from the bitmap file name and the
|
||
* bitmapDirectory resource value.
|
||
*
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* string = bitmap file name or NULL
|
||
* wmGD.bitmapDirectory = bitmapDirectory resource value
|
||
* HOME = environment variable for home directory
|
||
* XBMLANGPATH
|
||
* XAPPLRESDIR
|
||
*
|
||
*
|
||
* Outputs:
|
||
* -------
|
||
* Return = string containing the bitmap file pathname or NULL.
|
||
*
|
||
*
|
||
* Comments:
|
||
* --------
|
||
* If the bitmap file does not exist, searches using XBMLANGPATH.
|
||
* Returns NULL path name for a NULL file name.
|
||
*
|
||
*************************************<->***********************************/
|
||
|
||
char *BitmapPathName (char *string)
|
||
{
|
||
static char fileName[MAXWMPATH+1];
|
||
char *retname;
|
||
SubstitutionRec subs[1];
|
||
char *homeDir = XmeGetHomeDirName();
|
||
|
||
if (!string || !*string)
|
||
{
|
||
return (NULL);
|
||
}
|
||
|
||
/*
|
||
* Interpret "~/.." as relative to the user's home directory.
|
||
* Interpret "/.." as an absolute pathname.
|
||
* If the bitmapDirectory resource is nonNULL, interpret path as relative
|
||
* to it.
|
||
* Else, or if bitmapDirectory has no such file, use a XBMLANGPATH lookup.
|
||
*/
|
||
|
||
if ((string[0] == '~') && (string[1] == '/'))
|
||
/*
|
||
* Handle "~/.."
|
||
*/
|
||
{
|
||
snprintf(fileName, MAXWMPATH, "%s%s", homeDir, &(string[1]));
|
||
return (fileName);
|
||
}
|
||
|
||
if (string[0] == '/')
|
||
{
|
||
return(string);
|
||
}
|
||
|
||
if (wmGD.bitmapDirectory && *wmGD.bitmapDirectory)
|
||
/*
|
||
* Relative to nonNULL bitmapDirectory (which may have relative to HOME)
|
||
*/
|
||
{
|
||
if ((wmGD.bitmapDirectory[0] == '~') &&
|
||
(wmGD.bitmapDirectory[1] == '/'))
|
||
{
|
||
strcpy (fileName, homeDir);
|
||
strncat (fileName, &wmGD.bitmapDirectory[1],
|
||
MAXWMPATH - strlen (fileName));
|
||
} else {
|
||
snprintf(fileName, sizeof(fileName), "%s", wmGD.bitmapDirectory);
|
||
}
|
||
strncat (fileName, "/", MAXWMPATH - strlen (fileName));
|
||
strncat (fileName, string, MAXWMPATH - strlen (fileName));
|
||
|
||
/* Test file for existence. */
|
||
|
||
subs[0].substitution = "";
|
||
if ((retname = XtFindFile(fileName, subs, 0,
|
||
(XtFilePredicate) NULL)) != NULL) {
|
||
XtFree(retname);
|
||
return (fileName);
|
||
}
|
||
}
|
||
|
||
/* Fall back on a path search */
|
||
|
||
{
|
||
char *search_path;
|
||
Boolean user_path;
|
||
|
||
search_path = _XmOSInitPath(string, MATCH_PATH, &user_path);
|
||
subs[0].match = user_path ? MATCH_XBM : MATCH_CHAR;
|
||
subs[0].substitution = string;
|
||
retname = XtResolvePathname(DISPLAY, "bitmaps", NULL, NULL,
|
||
search_path, subs, XtNumber(subs),
|
||
(XtFilePredicate)NULL);
|
||
XtFree(search_path);
|
||
|
||
if (!retname)
|
||
return (string);
|
||
|
||
strncpy(fileName, retname, MAXWMPATH);
|
||
XtFree(retname);
|
||
return (fileName);
|
||
}
|
||
|
||
} /* END OF FUNCTION BitmapPathName */
|
||
|
||
/**************************** eof ***************************/
|