#include "XmL.h"
#include <Xm/XmP.h>
#include <Xm/LabelP.h>
#include <Xm/DrawnBP.h>
#include <Xm/MessageB.h>
#include <Xm/Protocols.h>
#include <Xm/AtomMgr.h>
#ifdef MOTIF11
#include <Xm/VendorE.h>
#else
#include <Xm/VendorS.h>
#endif
#include <Xm/BulletinB.h>
#include <Xm/MenuShell.h>
#include <X11/Xft/Xft.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef SUNOS4
int fprintf(
FILE *,
char *, ...);
#endif
static void XmLDrawnBDestroyCB(Widget w, XtPointer clientData, XtPointer);
static void XmLDrawnBDrawCB(Widget, XtPointer, XtPointer);
static void XmLDrawnBDrawStringCB(Widget, XtPointer, XtPointer);
static int XmLDrawCalc(Widget w, Dimension width, Dimension height,
unsigned char alignment, XRectangle *rect, XRectangle *clipRect,
int *x,
int *y);
static void XmLFontGetAverageWidth(XFontStruct *fs,
short *width);
static void XmLMessageBoxResponse(Widget, XtPointer, XtPointer);
static void XmLMessageBoxWMDelete(Widget, XtPointer, XtPointer);
static void XmLSortFunc(
char *lvec,
char *rvec);
struct _XmLArrayRec
{
char _autonumber, _growFast;
int _count, _size;
void **_items;
};
XmLArray
XmLArrayNew(
char autonumber,
char growFast)
{
XmLArray array;
array = (XmLArray)malloc(
sizeof(
struct _XmLArrayRec));
array->_count =
0;
array->_size =
0;
array->_items =
0;
array->_autonumber = autonumber;
array->_growFast = growFast;
return array;
}
void
XmLArrayFree(XmLArray array)
{
if (array->_items)
free((
char *)array->_items);
free((
char *)array);
}
void
XmLArrayAdd(XmLArray array,
int pos,
int count)
{
int i;
void **items;
if (count <
1)
return;
if (pos <
0 || pos > array->_count)
pos = array->_count;
if (array->_count + count >= array->_size)
{
if (array->_growFast)
{
if (!array->_size)
array->_size = count +
256;
else
array->_size = (array->_count + count) *
2;
}
else
array->_size = array->_count + count;
items = (
void **)malloc(
sizeof(
void *) * array->_size);
if (array->_items)
{
for (i =
0; i < array->_count; i++)
items[i] = array->_items[i];
free((
char *)array->_items);
}
array->_items = items;
}
for (i = array->_count + count -
1; i >= pos + count; i--)
{
array->_items[i] = array->_items[i - count];
if (array->_autonumber)
((XmLArrayItem *)array->_items[i])->pos = i;
}
for (i = pos; i < pos + count; i++)
array->_items[i] =
0;
array->_count += count;
}
int
XmLArrayDel(XmLArray array,
int pos,
int count)
{
int i;
if (pos <
0 || pos + count > array->_count)
return -
1;
for (i = pos; i < array->_count - count; i++)
{
array->_items[i] = array->_items[i + count];
if (array->_autonumber)
((XmLArrayItem *)array->_items[i])->pos = i;
}
array->_count -= count;
if (!array->_count)
{
if (array->_items)
free((
char *)array->_items);
array->_items =
0;
array->_size =
0;
}
return 0;
}
int
XmLArraySet(XmLArray array,
int pos,
void *item)
{
if (pos <
0 || pos >= array->_count)
return -
1;
if (array->_items[pos])
fprintf(stderr,
"XmLArraySet: warning: overwriting pointer\n");
array->_items[pos] = item;
if (array->_autonumber)
((XmLArrayItem *)array->_items[pos])->pos = pos;
return 0;
}
void *
XmLArrayGet(XmLArray array,
int pos)
{
if (pos <
0 || pos >= array->_count)
return 0;
return array->_items[pos];
}
int
XmLArrayGetCount(XmLArray array)
{
return array->_count;
}
int
XmLArrayMove(XmLArray array,
int newPos,
int pos,
int count)
{
void **items;
int i;
if (count <=
0)
return -
1;
if (newPos <
0 || newPos + count > array->_count)
return -
1;
if (pos <
0 || pos + count > array->_count)
return -
1;
if (pos == newPos)
return 0;
items = (
void **)malloc(
sizeof(
void *) * count);
for (i =
0; i < count; i++)
items[i] = array->_items[pos + i];
if (newPos < pos)
for (i = pos + count -
1; i >= newPos + count; i--)
{
array->_items[i] = array->_items[i - count];
if (array->_autonumber)
((XmLArrayItem *)array->_items[i])->pos = i;
}
else
for (i = pos; i < newPos; i++)
{
array->_items[i] = array->_items[i + count];
if (array->_autonumber)
((XmLArrayItem *)array->_items[i])->pos = i;
}
for (i =
0; i < count; i++)
{
array->_items[newPos + i] = items[i];
if (array->_autonumber)
((XmLArrayItem *)array->_items[newPos + i])->pos = newPos + i;
}
free((
char *)items);
return 0;
}
int
XmLArrayReorder(XmLArray array,
int *newPositions,
int pos,
int count)
{
int i;
void **items;
if (count <=
0)
return -
1;
if (pos <
0 || pos + count > array->_count)
return -
1;
for (i =
0; i < count; i++)
{
if (newPositions[i] < pos || newPositions[i] >= pos + count)
return -
1;
}
items = (
void **)malloc(
sizeof(
void *) * count);
for (i =
0; i < count; i++)
items[i] = array->_items[newPositions[i]];
for (i =
0; i < count; i++)
{
array->_items[pos + i] = items[i];
if (array->_autonumber)
((XmLArrayItem *)array->_items[pos + i])->pos = pos + i;
}
free((
char *)items);
return 0;
}
int
XmLArraySort(XmLArray array,
XmLArrayCompareFunc compare,
void *userData,
int pos,
int count)
{
int i;
if (pos <
0 || pos + count > array->_count)
return -
1;
XmLSort(&array->_items[pos], count,
sizeof(
void *),
(XmLSortCompareFunc)compare, userData);
if (array->_autonumber)
for (i = pos; i < pos + count; i++)
((XmLArrayItem *)array->_items[i])->pos = i;
return 0;
}
Boolean
XmLCvtStringToUChar(Display *dpy,
char *resname,
XmLStringToUCharMap *map,
XrmValuePtr fromVal,
XrmValuePtr toVal)
{
char *from;
int i, valid;
from = (
char *)fromVal->addr;
valid =
0;
i =
0;
while (map[i].name)
{
if (!strcmp(from, map[i].name))
{
valid =
1;
break;
}
i++;
}
if (!valid)
{
XtDisplayStringConversionWarning(dpy, from, resname);
toVal->size =
0;
toVal->addr =
0;
return False;
}
if (toVal->addr)
{
if (toVal->size <
sizeof(
unsigned char))
{
toVal->size =
sizeof(
unsigned char);
return False;
}
*(
unsigned char *)(toVal->addr) = map[i].value;
}
else
toVal->addr = (
caddr_t)&map[i].value;
toVal->size =
sizeof(
unsigned char);
return True;
}
int
XmLDateDaysInMonth(
int m,
int y)
{
static int d[
12] = {
31,
28,
31,
30,
31,
30,
31,
31,
30,
31,
30,
31};
if (m <
1 || m >
12 || y <
1753 || y >
9999)
return -
1;
if (m ==
2 && (!((y %
4) && (y %
100)) || !(y %
400)))
return 29;
return d[m -
1];
}
int
XmLDateWeekDay(
int m,
int d,
int y)
{
long jd, j1, j2;
if (m <
1 || m >
12 || d <
1 || d > XmLDateDaysInMonth(m, y) ||
y <
1753 || y >
9999)
return -
1;
if (m >
2)
m -=
3;
else
{
m +=
9;
y--;
}
j1 = y /
100;
j2 = y -
100 * j1;
jd = (
146097 * j1) /
4 + (
1461 * j2) /
4 + (
153 * m +
2) /
5 +
1721119 + d;
return (jd +
1) %
7;
}
typedef struct
{
GC gc;
int type;
int dir;
XFontStruct *fontStruct;
} XmLDrawnBData;
void
XmLDrawnButtonSetType(Widget w,
int drawnType,
int drawnDir)
{
XmLDrawnBData *dd;
XmDrawnButtonWidget b;
XmString str;
XmRenderTable rendertable;
XGCValues values;
XtGCMask mask;
Dimension width, height, dim;
Dimension highlightThickness, shadowThickness;
Dimension marginWidth, marginHeight;
Dimension marginTop, marginBottom, marginLeft, marginRight;
if (!XtIsSubclass(w, xmDrawnButtonWidgetClass))
{
XmLWarning(w,
"DrawnButtonSetType() - not an XmDrawnButton");
return;
}
XtVaSetValues(w,
XmNpushButtonEnabled, True,
NULL);
XtRemoveAllCallbacks(w, XmNexposeCallback);
XtRemoveAllCallbacks(w, XmNresizeCallback);
if (drawnType == XmDRAWNB_STRING && drawnDir == XmDRAWNB_RIGHT)
{
XtVaSetValues(w,
XmNlabelType, XmSTRING,
NULL);
return;
}
b = (XmDrawnButtonWidget)w;
dd = (XmLDrawnBData *)malloc(
sizeof(XmLDrawnBData));
dd->type = drawnType;
dd->dir = drawnDir;
dd->gc =
0;
if (dd->type == XmDRAWNB_STRING)
{
XtVaGetValues(w,
XmNlabelString, &str,
XmNrenderTable, &rendertable,
XmNhighlightThickness, &highlightThickness,
XmNshadowThickness, &shadowThickness,
XmNmarginHeight, &marginHeight,
XmNmarginWidth, &marginWidth,
XmNmarginTop, &marginTop,
XmNmarginBottom, &marginBottom,
XmNmarginLeft, &marginLeft,
XmNmarginRight, &marginRight,
NULL);
if (!str && XtName(w))
str = XmStringCreateSimple(XtName(w));
if (!str)
str = XmStringCreateSimple(
"");
XmStringExtent(rendertable, str, &width, &height);
XmStringFree(str);
if (drawnDir == XmDRAWNB_UP || drawnDir == XmDRAWNB_DOWN)
{
dim = width;
width = height;
height = dim;
}
height += (highlightThickness + shadowThickness +
marginHeight) *
2 + marginTop + marginBottom;
width += (highlightThickness + shadowThickness +
marginWidth) *
2 + marginLeft + marginRight;
XtVaSetValues(w,
XmNlabelType, XmPIXMAP,
NULL);
XtVaSetValues(w,
XmNwidth, width,
XmNheight, height,
NULL);
XtAddCallback(w, XmNexposeCallback, XmLDrawnBDrawStringCB,
(XtPointer)dd);
XtAddCallback(w, XmNresizeCallback, XmLDrawnBDrawStringCB,
(XtPointer)dd);
}
else
{
mask = GCForeground;
values.foreground = b->primitive.foreground;
dd->gc = XtGetGC(w, mask, &values);
XtAddCallback(w, XmNexposeCallback, XmLDrawnBDrawCB, (XtPointer)dd);
XtAddCallback(w, XmNresizeCallback, XmLDrawnBDrawCB, (XtPointer)dd);
}
XtAddCallback(w, XmNdestroyCallback, XmLDrawnBDestroyCB, (XtPointer)dd);
}
static void
XmLDrawnBDestroyCB(Widget w,
XtPointer clientData,
XtPointer callData)
{
XmLDrawnBData *dd;
dd = (XmLDrawnBData *)clientData;
if (dd->type == XmDRAWNB_STRING)
{
if (dd->gc)
{
XFreeGC(XtDisplay(w), dd->gc);
XFreeFont(XtDisplay(w), dd->fontStruct);
}
}
else
XtReleaseGC(w, dd->gc);
free((
char *)dd);
}
static void
XmLDrawnBDrawStringCB(Widget w,
XtPointer clientData,
XtPointer callData)
{
XmLDrawnBData *dd;
XmRenderTable rendertable;
XmString str;
XmStringDirection stringDir;
unsigned char drawDir, alignment;
int width, height, xoff, yoff, drawWidth;
Pixel fg;
Dimension highlightThickness;
Dimension shadowThickness, marginWidth, marginHeight;
Dimension marginLeft, marginRight, marginTop, marginBottom;
if (!XtIsRealized(w))
return;
dd = (XmLDrawnBData *)clientData;
XtVaGetValues(w,
XmNlabelString, &str,
NULL);
if (!str && XtName(w))
str = XmStringCreateSimple(XtName(w));
if (!str)
return;
XtVaGetValues(w,
XmNforeground, &fg,
XmNrenderTable, &rendertable,
XmNalignment, &alignment,
XmNhighlightThickness, &highlightThickness,
XmNshadowThickness, &shadowThickness,
XmNmarginWidth, &marginWidth,
XmNmarginHeight, &marginHeight,
XmNmarginLeft, &marginLeft,
XmNmarginRight, &marginRight,
XmNmarginTop, &marginTop,
XmNmarginBottom, &marginBottom,
NULL);
xoff = highlightThickness + shadowThickness + marginLeft + marginWidth;
yoff = highlightThickness + shadowThickness + marginTop + marginHeight;
width = XtWidth(w) - xoff - xoff + marginLeft - marginRight;
height = XtHeight(w) - yoff - yoff + marginTop - marginBottom;
if (XmIsManager(XtParent(w)))
XtVaGetValues(XtParent(w),
XmNstringDirection, &stringDir,
NULL);
else
stringDir = XmSTRING_DIRECTION_L_TO_R;
switch (dd->dir)
{
case XmDRAWNB_LEFT:
drawDir = XmSTRING_LEFT;
break;
case XmDRAWNB_UP:
drawDir = XmSTRING_UP;
break;
case XmDRAWNB_DOWN:
drawDir = XmSTRING_DOWN;
break;
default:
drawDir = XmSTRING_RIGHT;
break;
}
if (drawDir == XmSTRING_LEFT || drawDir == XmSTRING_RIGHT)
drawWidth = width;
else
drawWidth = height;
if (!dd->gc)
{
dd->gc = XCreateGC(XtDisplay(w), XtWindow(w),
0,
NULL);
dd->fontStruct = XLoadQueryFont(XtDisplay(w),
"fixed");
if (!dd->fontStruct)
{
XmLWarning(w,
"DrawnBDrawString() - FATAL can''t load fixed font");
return;
}
XSetFont(XtDisplay(w), dd->gc, dd->fontStruct->fid);
}
XSetForeground(XtDisplay(w), dd->gc, fg);
XmLStringDrawDirection(XtDisplay(w), XtWindow(w), rendertable,
str, dd->gc, xoff, yoff, drawWidth, alignment, stringDir, drawDir);
XmStringFree(str);
}
static void
XmLDrawnBDrawCB(Widget w,
XtPointer clientData,
XtPointer callData)
{
XmLDrawnBData *dd;
XmDrawnButtonWidget b;
Display *dpy;
Window win;
GC gc;
XPoint p[
2][
5];
XSegment seg;
int np[
2];
int i, j, temp;
int md, type, dir;
int avgx, avgy, xoff, yoff, st;
if (!XtIsRealized(w))
return;
dd = (XmLDrawnBData *)clientData;
type = dd->type;
dir = dd->dir;
gc = dd->gc;
b = (XmDrawnButtonWidget)w;
win = XtWindow(w);
dpy = XtDisplay(w);
st = b->primitive.shadow_thickness;
i = st *
2 + b->primitive.highlight_thickness *
2;
md = XtWidth(w) - i;
if (md > ((
int)XtHeight(w) - i))
md = XtHeight(w) - i;
if (md <
4)
return;
xoff = ((
int)XtWidth(w) - md) /
2;
yoff = ((
int)XtHeight(w) - md) /
2;
np[
0] =
0;
np[
1] =
0;
switch (type)
{
case XmDRAWNB_SMALLARROW:
p[
0][
0].x = md /
4;
p[
0][
0].y = md /
4;
p[
0][
1].x = md /
4;
p[
0][
1].y = md - md /
4;
p[
0][
2].x = md - md /
4;
p[
0][
2].y = md /
2;
np[
0] =
3;
break;
case XmDRAWNB_ARROW:
p[
0][
0].x = md /
6;
p[
0][
0].y = md /
6;
p[
0][
1].x = md /
6;
p[
0][
1].y = md - md /
6;
p[
0][
2].x = md - md /
6;
p[
0][
2].y = md /
2;
np[
0] =
3;
break;
case XmDRAWNB_ARROWLINE:
p[
0][
0].x = md /
5;
p[
0][
0].y = md /
5;
p[
0][
1].x = md /
5;
p[
0][
1].y = md - md /
5;
p[
0][
2].x = md - md /
5;
p[
0][
2].y = md /
2;
np[
0] =
3;
p[
1][
0].x = md - md /
5 +
1;
p[
1][
0].y = md /
5;
p[
1][
1].x = md - md /
5 +
1;
p[
1][
1].y = md - md /
5;
p[
1][
2].x = md - md /
10;
p[
1][
2].y = md - md /
5;
p[
1][
3].x = md - md /
10;
p[
1][
3].y = md /
5;
np[
1] =
4;
break;
case XmDRAWNB_DOUBLEARROW:
if (md %
2)
md -=
1;
p[
0][
0].x = md /
10;
p[
0][
0].y = md /
10;
p[
0][
1].x = md /
10;
p[
0][
1].y = md - md /
10;
p[
0][
2].x = md /
2;
p[
0][
2].y = md /
2;
np[
0] =
3;
p[
1][
0].x = md - md /
2;
p[
1][
0].y = md /
10;
p[
1][
1].x = md - md /
2;
p[
1][
1].y = md - md /
10;
p[
1][
2].x = md - md /
10;
p[
1][
2].y = md /
2;
np[
1] =
3;
break;
case XmDRAWNB_SQUARE:
p[
0][
0].x = md /
3;
p[
0][
0].y = md /
3;
p[
0][
1].x = md /
3;
p[
0][
1].y = md - md /
3;
p[
0][
2].x = md - md /
3;
p[
0][
2].y = md - md /
3;
p[
0][
3].x = md - md /
3;
p[
0][
3].y = md /
3;
np[
0] =
4;
break;
case XmDRAWNB_DOUBLEBAR:
p[
0][
0].x = md /
3;
p[
0][
0].y = md /
4;
p[
0][
1].x = md /
3;
p[
0][
1].y = md - md /
4;
p[
0][
2].x = md /
2 - md /
10;
p[
0][
2].y = md - md /
4;
p[
0][
3].x = md /
2 - md /
10;
p[
0][
3].y = md /
4;
np[
0] =
4;
p[
1][
0].x = md - md /
3;
p[
1][
0].y = md /
4;
p[
1][
1].x = md - md /
3;
p[
1][
1].y = md - md /
4;
p[
1][
2].x = md - md /
2 + md /
10;
p[
1][
2].y = md - md /
4;
p[
1][
3].x = md - md /
2 + md /
10;
p[
1][
3].y = md /
4;
np[
1] =
4;
break;
}
for (i =
0; i <
2; i++)
{
avgx =
0;
avgy =
0;
for (j =
0; j < np[i]; j++)
{
switch (dir)
{
case XmDRAWNB_RIGHT:
break;
case XmDRAWNB_LEFT:
p[i][j].x = md - p[i][j].x -
1;
break;
case XmDRAWNB_UP:
temp = p[i][j].x;
p[i][j].x = p[i][j].y;
p[i][j].y = md - temp;
break;
case XmDRAWNB_DOWN:
temp = p[i][j].x;
p[i][j].x = p[i][j].y;
p[i][j].y = temp;
break;
}
p[i][j].x += xoff;
p[i][j].y += yoff;
avgx += p[i][j].x;
avgy += p[i][j].y;
}
if (!np[i])
continue;
avgx /= np[i];
avgy /= np[i];
XFillPolygon(dpy, win, gc, p[i], np[i], Nonconvex, CoordModeOrigin);
p[i][np[i]].x = p[i][
0].x;
p[i][np[i]].y = p[i][
0].y;
for (j =
0; j < np[i]; j++)
{
seg.x1 = p[i][j].x;
seg.y1 = p[i][j].y;
seg.x2 = p[i][j +
1].x;
seg.y2 = p[i][j +
1].y;
if ((seg.x1 <= avgx && seg.x2 <= avgx) ||
(seg.y1 <= avgy && seg.y2 <= avgy))
XDrawSegments(dpy, win,
b->primitive.bottom_shadow_GC, &seg,
1);
else
XDrawSegments(dpy, win,
b->primitive.top_shadow_GC, &seg,
1);
}
}
}
#define XmLDrawNODRAW
0
#define XmLDrawNOCLIP
1
#define XmLDrawCLIPPED
2
static int
XmLDrawCalc(Widget w,
Dimension width,
Dimension height,
unsigned char alignment,
XRectangle *rect,
XRectangle *clipRect,
int *x,
int *y)
{
if (rect->width <=
4 || rect->height <=
4 ||
clipRect->width <
3 || clipRect->height <
3 ||
!width || !height ||
!XtIsRealized(w) ||
XmLRectIntersect(rect, clipRect) == XmLRectOutside)
return XmLDrawNODRAW;
if (alignment == XmALIGNMENT_TOP_LEFT ||
alignment == XmALIGNMENT_LEFT ||
alignment == XmALIGNMENT_BOTTOM_LEFT)
*x = rect->x +
2;
else if (alignment == XmALIGNMENT_TOP ||
alignment == XmALIGNMENT_CENTER ||
alignment == XmALIGNMENT_BOTTOM)
*x = rect->x + ((
int)rect->width - (
int)width) /
2;
else
*x = rect->x + rect->width - width -
2;
if (alignment == XmALIGNMENT_TOP ||
alignment == XmALIGNMENT_TOP_LEFT ||
alignment == XmALIGNMENT_TOP_RIGHT)
*y = rect->y +
2;
else if (alignment == XmALIGNMENT_LEFT ||
alignment == XmALIGNMENT_CENTER ||
alignment == XmALIGNMENT_RIGHT)
*y = rect->y + ((
int)rect->height - (
int)height) /
2;
else
*y = rect->y + rect->height - height -
2;
if (clipRect->x == rect->x &&
clipRect->y == rect->y &&
clipRect->width == rect->width &&
clipRect->height == rect->height &&
(
int)width +
4 <= (
int)clipRect->width &&
(
int)height +
4 <= (
int)clipRect->height)
return XmLDrawNOCLIP;
return XmLDrawCLIPPED;
}
void
XmLDrawToggle(Widget w,
Boolean state,
Dimension size,
unsigned char alignment,
GC gc,
Pixel backgroundColor,
Pixel topColor,
Pixel bottomColor,
Pixel checkColor,
XRectangle *rect,
XRectangle *clipRect)
{
Display *dpy;
Window win;
XPoint point[
5];
int x, y, cx[
3], cy[
4], drawType;
drawType = XmLDrawCalc(w, size, size, alignment, rect, clipRect, &x, &y);
if (size <
3 || drawType == XmLDrawNODRAW)
return;
dpy = XtDisplay(w);
win = XtWindow(w);
if (drawType == XmLDrawCLIPPED)
XSetClipRectangles(dpy, gc,
0,
0, clipRect,
1, Unsorted);
XSetForeground(dpy, gc, backgroundColor);
XFillRectangle(dpy, win, gc, x, y, size, size);
XSetForeground(dpy, gc, topColor);
point[
0].x = x;
point[
0].y = y + size -
1;
point[
1].x = x;
point[
1].y = y;
point[
2].x = x + size -
1;
point[
2].y = y;
XDrawLines(dpy, win, gc, point,
3, CoordModeOrigin);
point[
1].x = x + size -
1;
point[
1].y = y + size -
1;
XSetForeground(dpy, gc, bottomColor);
XDrawLines(dpy, win, gc, point,
3, CoordModeOrigin);
if (state == True)
{
cx[
0] = x +
1;
cx[
1] = x + (((
int)size -
3) /
3) +
1;
cx[
2] = x + size -
2;
cy[
0] = y +
1;
cy[
1] = y + (((
int)size -
3) /
2) +
1;
cy[
2] = y + ((((
int)size -
3) *
2) /
3) +
1;
cy[
3] = y + size -
2;
point[
0].x = cx[
0];
point[
0].y = cy[
1];
point[
1].x = cx[
1];
point[
1].y = cy[
3];
point[
2].x = cx[
2];
point[
2].y = cy[
0];
point[
3].x = cx[
1];
point[
3].y = cy[
2];
point[
4].x = point[
0].x;
point[
4].y = point[
0].y;
XSetForeground(dpy, gc, checkColor);
XFillPolygon(dpy, win, gc, point,
4, Nonconvex, CoordModeOrigin);
XDrawLines(dpy, win, gc, point,
5, CoordModeOrigin);
}
if (drawType == XmLDrawCLIPPED)
XSetClipMask(dpy, gc, None);
}
int
XmLRectIntersect(XRectangle *r1,
XRectangle *r2)
{
if (!r1->width || !r1->height || !r2->width || !r2->height)
return XmLRectOutside;
if (r1->x + (
int)r1->width -
1 < r2->x ||
r1->x > r2->x + (
int)r2->width -
1 ||
r1->y + (
int)r1->height -
1 < r2->y ||
r1->y > r2->y + (
int)r2->height -
1)
return XmLRectOutside;
if (r1->x >= r2->x &&
r1->x + (
int)r1->width <= r2->x + (
int)r2->width &&
r1->y >= r2->y &&
r1->y + (
int)r1->height <= r2->y + (
int)r2->height)
return XmLRectInside;
return XmLRectPartial;
}
XmFontList
XmLFontListCopyDefault(Widget widget)
{
return XmLRenderTableCopyDefault(widget);
}
XmRenderTable
XmLRenderTableCopyDefault(Widget widget)
{
Widget parent;
XmRenderTable renderTable, fl;
renderTable =
0;
parent = XtParent(widget);
while (parent)
{
fl =
0;
if (XmIsVendorShell(parent) || XmIsMenuShell(parent))
XtVaGetValues(parent, XmNdefaultFontList, &fl,
NULL);
else if (XmIsBulletinBoard(parent))
XtVaGetValues(parent, XmNbuttonFontList, &fl,
NULL);
if (fl)
{
renderTable = XmRenderTableCopy(fl,
NULL,
0);
parent =
0;
}
if (parent)
parent = XtParent(parent);
}
if (!renderTable)
{
XmRendition rendition = XmRenditionCreate( widget,
NULL,
NULL,
0 );
renderTable = XmRenderTableAddRenditions(
NULL, &rendition,
1, XmMERGE_REPLACE );
}
return renderTable;
}
void
XmLFontListGetDimensions(
Widget w,
XmFontList fontList,
short *width,
short *height,
Boolean useAverageWidth)
{
XmLRenderTableGetDimensions(
w,
fontList,
width,
height,
useAverageWidth
);
}
static void XmLGetDimensionsOfFontstruct(
XFontStruct *fs,
short *width,
short *height,
Boolean useAverageWidth)
{
if (useAverageWidth == True) {
XmLFontGetAverageWidth(fs, width);
}
else {
*width = fs->max_bounds.width;
}
*height = fs->max_bounds.ascent + fs->max_bounds.descent;
}
void
XmLRenderTableGetDimensions(
Widget w,
XmRenderTable renderTable,
short *width,
short *height,
Boolean useAverageWidth)
{
#if 0
XmStringCharSet charset;
XmFontContext context;
XFontStruct *fs;
#if XmVersion <
2000
typedef struct {
XmFontList nextFontList;
Boolean unused;
} XmFontListContextRec;
typedef struct {
XFontStruct *font;
XmStringCharSet unused;
} XmFontListRec;
XmFontList nextFontList;
#endif
#endif
Display *dpy = XtDisplay(w);
*width =
0;
*height =
0;
XmStringTag* tag_list =
NULL;
int tag_count = XmRenderTableGetTags( renderTable, &tag_list );
int renditionIdx;
XmRendition* renditions = XmRenderTableGetRenditions( renderTable, tag_list, tag_count );
for ( renditionIdx =
0; renditionIdx < tag_count; renditionIdx++ ) {
short w =
0, h =
0;
XmRendition rendition = renditions[renditionIdx];
XmFontType fontType = XmFONT_IS_FONT;
XtPointer font =
NULL;
XftFont* xftFont =
NULL;
Arg arglist[
3];
int argCount =
0;
XtSetArg(arglist[argCount], XmNfontType, &fontType); argCount++;
XtSetArg(arglist[argCount], XmNfont, &font); argCount++;
#ifdef XmNxftFont
XtSetArg(arglist[argCount], XmNxftFont, &xftFont); argCount++;
#endif
XmRenditionRetrieve( rendition, arglist, argCount );
switch(fontType)
{
case XmFONT_IS_FONT:
{
XFontStruct *fs = (XFontStruct*)(font);
if ( ( fs !=
NULL ) && ( fs != (XFontStruct*)XmAS_IS ) ) {
XmLGetDimensionsOfFontstruct(
fs, &w, &h, useAverageWidth
);
}
}
break;
case XmFONT_IS_FONTSET:
{
XFontSet fontSet = (XFontSet)(font);
if ( ( fontSet !=
NULL ) && ( fontSet != (XFontSet)XmAS_IS ) ) {
XFontSetExtents* fontsetExtents =
XExtentsOfFontSet(fontSet);
w = fontsetExtents->max_logical_extent.width;
h = fontsetExtents->max_logical_extent.height;
}
}
break;
#if defined(XmFONT_IS_XFT) || defined(
USE_XFT)
case XmFONT_IS_XFT:
{
if ( ( xftFont !=
NULL ) && ( xftFont != (XftFont*)XmAS_IS ) ) {
w = xftFont->max_advance_width;
h = xftFont->ascent + xftFont->descent;
if ( useAverageWidth ) {
const char* testString =
"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const size_t testStringLen = strlen(testString);
XGlyphInfo extents;
XftTextExtentsUtf8 (
dpy,
xftFont,
(
const FcChar8*)testString,
testStringLen,
&extents
);
w = extents.xOff / testStringLen;
}
}
}
break;
#endif
}
if (*height < h) {
*height = h;
}
if (*width < w) {
*width = w;
}
}
for ( renditionIdx =
0; renditionIdx < tag_count; renditionIdx++ ) {
XtFree(tag_list[renditionIdx]);
}
XtFree( (XtPointer)tag_list );
for ( renditionIdx =
0; renditionIdx < tag_count; renditionIdx++ ) {
XmRenditionFree( renditions[renditionIdx] );
}
XtFree( (XtPointer)renditions );
#if 0
if (XmFontListInitFontContext(&context, renderTable))
{
while (
1)
{
#if XmVersion <
2000
nextFontList = ((XmFontListContextRec *)context)->nextFontList;
if (!nextFontList)
break;
if (!((XmFontListRec *)nextFontList)->font)
break;
#endif
if (XmFontListGetNextFont(context, &charset, &fs) == False)
break;
XtFree(charset);
if (useAverageWidth == True)
XmLFontGetAverageWidth(fs, &w);
else
w = fs->max_bounds.width;
h = fs->max_bounds.ascent + fs->max_bounds.descent;
if (*height < h)
*height = h;
if (*width < w)
*width = w;
}
XmFontListFreeFontContext(context);
}
#endif
}
static void
XmLFontGetAverageWidth(XFontStruct *fs,
short *width)
{
long aw, n;
int r, c, mm, i;
XCharStruct *cs;
n =
0;
aw =
0;
mm = fs->max_char_or_byte2 - fs->min_char_or_byte2 +
1;
for (r = fs->min_byte1; r <= fs->max_byte1; r++)
for (c = fs->min_char_or_byte2; c <= fs->max_char_or_byte2; c++)
{
if (!fs->per_char)
continue;
i = ((r - fs->min_byte1) * mm) + (c - fs->min_char_or_byte2);
cs = &fs->per_char[i];
if (!cs->width)
continue;
aw += cs->width;
n++;
}
if (n)
aw = aw / n;
else
aw = fs->min_bounds.width;
*width = (
short)aw;
}
int _XmLKey;
void XmLInitialize(
void)
{
static int first =
1;
if (!first)
return;
first =
0;
#ifdef XmLEVAL
fprintf(stderr,
"XmL: This is an evalation version of the Microline\n");
fprintf(stderr,
"XmL: Widget Library. Some features are disabled.\n");
#endif
#ifdef XmLJAVA
if (_XmLKey !=
444)
{
fprintf(stderr,
"XmL: Error: This version of the library will only");
fprintf(stderr,
"XmL: work with JAVA.\n");
exit(
0);
}
#endif
}
int
XmLMessageBox(Widget w,
char *string,
Boolean okOnly)
{
int status =
0;
Widget dialog, shell;
Arg args[
3];
XtAppContext context;
XmString str, titleStr;
String shellTitle;
Atom
WM_DELETE_WINDOW;
str = XmStringCreateLtoR(string, XmSTRING_DEFAULT_CHARSET);
XtSetArg(args[
0], XmNmessageString, str);
XtSetArg(args[
1], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL);
shell = XmLShellOfWidget(w);
if (shell)
XtVaGetValues(shell, XmNtitle, &shellTitle,
NULL);
if (shell && shellTitle)
titleStr = XmStringCreateLtoR(shellTitle,
XmSTRING_DEFAULT_CHARSET);
else
titleStr = XmStringCreateSimple(
"Notice");
XtSetArg(args[
2], XmNdialogTitle, titleStr);
if (okOnly == True)
dialog = XmCreateMessageDialog(XtParent(w),
"popup", args,
3);
else
dialog = XmCreateQuestionDialog(XtParent(w),
"popup", args,
3);
WM_DELETE_WINDOW = XmInternAtom(XtDisplay(w),
"WM_DELETE_WINDOW",
False);
XmAddWMProtocolCallback(shell,
WM_DELETE_WINDOW, XmLMessageBoxWMDelete,
(
caddr_t)&status);
XmStringFree(str);
XmStringFree(titleStr);
XtAddCallback(dialog, XmNokCallback, XmLMessageBoxResponse,
(XtPointer)&status);
if (okOnly == True)
{
XtUnmanageChild(XmMessageBoxGetChild(dialog,
XmDIALOG_CANCEL_BUTTON));
XtUnmanageChild(XmMessageBoxGetChild(dialog,
XmDIALOG_HELP_BUTTON));
}
else
{
XtAddCallback(dialog, XmNcancelCallback, XmLMessageBoxResponse,
(XtPointer)&status);
XtAddCallback(dialog, XmNhelpCallback, XmLMessageBoxResponse,
(XtPointer)&status);
}
XtManageChild(dialog);
context = XtWidgetToApplicationContext(w);
while (!status || XtAppPending(context))
XtAppProcessEvent(context, XtIMAll);
XtDestroyWidget(dialog);
return status;
}
static void
XmLMessageBoxWMDelete(Widget w,
XtPointer clientData,
XtPointer callData)
{
int *status = (
int *)clientData;
*status =
1;
}
static void
XmLMessageBoxResponse(Widget w,
XtPointer clientData,
XtPointer callData)
{
int *status = (
int *)clientData;
XmAnyCallbackStruct *reason;
reason = (XmAnyCallbackStruct *)callData;
switch (reason->reason)
{
case XmCR_OK:
*status =
1;
break;
case XmCR_CANCEL:
*status =
2;
break;
case XmCR_HELP:
*status =
3;
break;
}
}
void
XmLPixmapDraw(Widget w,
Pixmap pixmap,
Pixmap pixmask,
int pixmapWidth,
int pixmapHeight,
unsigned char alignment,
GC gc,
XRectangle *rect,
XRectangle *clipRect)
{
Display *dpy;
Window win;
int px, py, x, y, width, height, drawType;
if (pixmap == XmUNSPECIFIED_PIXMAP)
return;
dpy = XtDisplay(w);
win = XtWindow(w);
width = pixmapWidth;
height = pixmapHeight;
if (!width || !height)
{
alignment = XmALIGNMENT_TOP_LEFT;
width = clipRect->width -
4;
height = clipRect->height -
4;
}
drawType = XmLDrawCalc(w, width, height, alignment,
rect, clipRect, &x, &y);
if (drawType == XmLDrawNODRAW)
return;
px =
0;
py =
0;
if (clipRect->y > y && clipRect->y < y + height -
1)
{
py = clipRect->y - y;
y += py;
height -= py;
}
if (clipRect->y + (
int)clipRect->height -
1 >= y &&
clipRect->y + (
int)clipRect->height -
1 <= y + height -
1)
height = clipRect->y + clipRect->height - y;
if (clipRect->x > x && clipRect->x < x + width -
1)
{
px = clipRect->x - x;
x += px;
width -= px;
}
if (clipRect->x + (
int)clipRect->width -
1 >= x &&
clipRect->x + (
int)clipRect->width -
1 <= x + width -
1)
width = clipRect->x + clipRect->width - x;
if (pixmask != XmUNSPECIFIED_PIXMAP)
{
XSetClipMask(dpy, gc, pixmask);
XSetClipOrigin(dpy, gc, x - px, y - py);
}
XSetGraphicsExposures(dpy, gc, False);
XCopyArea(dpy, pixmap, win, gc, px, py, width, height, x, y);
XSetGraphicsExposures(dpy, gc, True);
if (pixmask != XmUNSPECIFIED_PIXMAP)
{
XSetClipMask(dpy, gc, None);
XSetClipOrigin(dpy, gc,
0,
0);
}
}
Widget
XmLShellOfWidget(Widget w)
{
while(
1)
{
if (!w)
return 0;
if (XtIsSubclass(w, shellWidgetClass))
return w;
w = XtParent(w);
}
}
static XmLSortCompareFunc XmLSortCompare;
static int XmLSortEleSize;
static void *XmLSortUserData;
void
XmLSort(
void *base,
int numItems,
unsigned int itemSize,
XmLSortCompareFunc compare,
void *userData)
{
XmLSortCompareFunc oldCompare;
int oldEleSize;
void *oldUserData;
char *lvec, *rvec;
if (numItems <
2)
return;
oldCompare = XmLSortCompare;
oldEleSize = XmLSortEleSize;
oldUserData = XmLSortUserData;
XmLSortCompare = compare;
XmLSortEleSize = itemSize;
XmLSortUserData = userData;
lvec = (
char *)base;
rvec = lvec + (numItems -
1) * itemSize;
XmLSortFunc(lvec, rvec);
XmLSortCompare = oldCompare;
XmLSortEleSize = oldEleSize;
XmLSortUserData = oldUserData;
}
#define SWAP(p1, p2) \
{ \
if (p1 != p2) \
{ \
int zi; \
char zc; \
for (zi =
0; zi < XmLSortEleSize; zi++) \
{ \
zc = (p1)[zi]; \
(p1)[zi] = (p2)[zi]; \
(p2)[zi] = zc; \
} \
}\
}
static void
XmLSortFunc(
char *lvec,
char *rvec)
{
int i;
char *nlvec, *nrvec, *pvec;
start:
i = (*XmLSortCompare)(XmLSortUserData, lvec, rvec);
if (rvec == lvec + XmLSortEleSize)
{
if (i >
0)
SWAP(lvec, rvec)
return;
}
pvec = lvec + ((rvec - lvec) / (XmLSortEleSize *
2)) * XmLSortEleSize;
if (i <
0)
{
i = (*XmLSortCompare)(XmLSortUserData, lvec, pvec);
if (i >
0)
pvec = lvec;
else if (i ==
0)
pvec = rvec;
}
else if (i >
0)
{
i = (*XmLSortCompare)(XmLSortUserData, rvec, pvec);
if (i >
0)
pvec = rvec;
else if (i ==
0)
pvec = lvec;
}
else
{
pvec = lvec + XmLSortEleSize;
while (
1)
{
i = (*XmLSortCompare)(XmLSortUserData, lvec, pvec);
if (i <
0)
break;
else if (i >
0)
{
pvec = lvec;
break;
}
if (pvec == rvec)
return;
pvec += XmLSortEleSize;
}
}
nlvec = lvec;
nrvec = rvec;
while (
1)
{
if (pvec == nrvec)
pvec = nlvec;
else if (pvec == nlvec)
pvec = nrvec;
SWAP(nrvec, nlvec)
while ((*XmLSortCompare)(XmLSortUserData, nlvec, pvec) <
0)
nlvec += XmLSortEleSize;
while ((*XmLSortCompare)(XmLSortUserData, nrvec, pvec) >=
0)
nrvec -= XmLSortEleSize;
if (nlvec > nrvec)
break;
}
if (lvec < nlvec - XmLSortEleSize)
XmLSortFunc(lvec, nlvec - XmLSortEleSize);
if (nlvec < rvec)
{
lvec = nlvec;
goto start;
}
}
void
XmLStringDraw(Widget w,
XmString string,
XmStringDirection stringDir,
XmRenderTable renderTable,
unsigned char alignment,
GC gc,
XRectangle *rect,
XRectangle *clipRect)
{
Display *dpy;
Window win;
Dimension width, height;
int x, y, drawType;
unsigned char strAlignment;
if (!string)
return;
dpy = XtDisplay(w);
win = XtWindow(w);
XmStringExtent(renderTable, string, &width, &height);
drawType = XmLDrawCalc(w, width, height, alignment,
rect, clipRect, &x, &y);
if (drawType == XmLDrawNODRAW)
return;
x = rect->x +
2;
if (alignment == XmALIGNMENT_LEFT ||
alignment == XmALIGNMENT_TOP_LEFT ||
alignment == XmALIGNMENT_BOTTOM_LEFT)
strAlignment = XmALIGNMENT_BEGINNING;
else if (alignment == XmALIGNMENT_CENTER ||
alignment == XmALIGNMENT_TOP ||
alignment == XmALIGNMENT_BOTTOM)
if (width <= rect->width -
4)
strAlignment = XmALIGNMENT_CENTER;
else
strAlignment = XmALIGNMENT_BEGINNING;
else
strAlignment = XmALIGNMENT_END;
if (drawType == XmLDrawCLIPPED)
XSetClipRectangles(dpy, gc,
0,
0, clipRect,
1, Unsorted);
XmStringDraw(dpy, win, renderTable, string, gc,
x, y, rect->width -
4, strAlignment, stringDir, clipRect);
if (drawType == XmLDrawCLIPPED)
XSetClipMask(dpy, gc, None);
}
void
XmLStringDrawDirection(Display *dpy,
Window win,
XmRenderTable rendertable,
XmString string,
GC gc,
int x,
int y,
Dimension width,
unsigned char alignment,
unsigned char layout_direction,
unsigned char drawing_direction)
{
Screen *screen;
XFontStruct *fontStruct;
XImage *sourceImage, *destImage;
Pixmap pixmap;
GC pixmapGC;
int destWidth, destHeight;
int stringWidth, stringHeight;
int i, j, bytesPerLine;
Dimension dW, dH;
char *data;
screen = DefaultScreenOfDisplay(dpy);
XmStringExtent(rendertable, string, &dW, &dH);
stringWidth = (
int)dW;
stringHeight = (
int)dH;
if (!stringWidth || !stringHeight)
return;
pixmap = XCreatePixmap(dpy, win, stringWidth, stringHeight,
1);
pixmapGC = XCreateGC(dpy, pixmap,
0,
NULL);
fontStruct = XLoadQueryFont(dpy,
"fixed");
if (!fontStruct)
{
fprintf(stderr,
"XmLStringDrawDirection: error - ");
fprintf(stderr,
"can''t load fixed font\n");
return;
}
XSetFont(dpy, pixmapGC, fontStruct->fid);
XSetBackground(dpy, pixmapGC,
0L);
XSetForeground(dpy, pixmapGC,
0L);
XFillRectangle(dpy, pixmap, pixmapGC,
0,
0, stringWidth, stringHeight);
XSetForeground(dpy, pixmapGC,
1L);
XmStringDraw(dpy, pixmap, rendertable, string, pixmapGC,
0,
0, stringWidth,
XmALIGNMENT_BEGINNING, layout_direction,
0);
XFreeFont(dpy, fontStruct);
sourceImage = XGetImage(dpy, pixmap,
0,
0, stringWidth, stringHeight,
1, XYPixmap);
XFreePixmap(dpy, pixmap);
if (drawing_direction == XmSTRING_UP || drawing_direction == XmSTRING_DOWN)
{
destWidth = stringHeight;
destHeight = stringWidth;
}
else
{
destWidth = stringWidth;
destHeight = stringHeight;
}
bytesPerLine = (destWidth -
1) /
8 +
1;
data = (
char *)malloc(bytesPerLine * destHeight);
destImage = XCreateImage(dpy, DefaultVisualOfScreen(screen),
1, XYBitmap,
0, data, destWidth, destHeight,
8,
0);
for (i =
0; i < stringWidth; i++)
for (j =
0; j < stringHeight; j++)
{
if (drawing_direction == XmSTRING_UP)
XPutPixel(destImage, j, i,
XGetPixel(sourceImage, stringWidth - i -
1, j));
else if (drawing_direction == XmSTRING_DOWN)
XPutPixel(destImage, stringHeight - j -
1, stringWidth - i -
1,
XGetPixel(sourceImage, stringWidth - i -
1, j));
else if (drawing_direction == XmSTRING_LEFT)
XPutPixel(destImage, i, stringHeight - j -
1,
XGetPixel(sourceImage, stringWidth - i -
1, j));
else
XPutPixel(destImage, i, j,
XGetPixel(sourceImage, i, j));
}
XDestroyImage(sourceImage);
pixmap = XCreatePixmap(dpy, win, destWidth, destHeight,
1);
XPutImage(dpy, pixmap, pixmapGC, destImage,
0,
0,
0,
0,
destWidth, destHeight);
XDestroyImage(destImage);
XFreeGC(dpy, pixmapGC);
if (drawing_direction == XmSTRING_UP || drawing_direction == XmSTRING_DOWN)
{
if (alignment == XmALIGNMENT_BEGINNING)
;
else if (alignment == XmALIGNMENT_CENTER)
y += width /
2 - stringWidth /
2;
else if (alignment == XmALIGNMENT_END)
y += (
int)width - stringWidth;
}
else
{
if (alignment == XmALIGNMENT_BEGINNING)
;
else if (alignment == XmALIGNMENT_CENTER)
x += width /
2 - stringWidth /
2;
else if (alignment == XmALIGNMENT_END)
x += (
int)width - stringWidth;
}
XSetStipple(dpy, gc, pixmap);
XSetFillStyle(dpy, gc, FillStippled);
XSetTSOrigin(dpy, gc, x % destWidth, y % destHeight);
XFillRectangle(dpy, win, gc, x, y, destWidth, destHeight);
XFreePixmap(dpy, pixmap);
XSetFillStyle(dpy, gc, FillSolid);
}
void
XmLWarning(Widget w,
char *msg)
{
XtAppContext app;
char s[
512], *cname, *name;
WidgetClass c;
app = XtWidgetToApplicationContext(w);
name = XtName(w);
if (!name)
name =
"[No Name]";
c = XtClass(w);
cname = c->core_class.class_name;
if (!cname)
cname =
"[No Class]";
sprintf(s,
"%s: %s: %s\n", cname, name, msg);
XtAppWarning(app, s);
}