aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/lib/dpstk
diff options
context:
space:
mode:
authorReinhard Tartler <siretart@tauware.de>2011-10-10 17:43:39 +0200
committerReinhard Tartler <siretart@tauware.de>2011-10-10 17:43:39 +0200
commitf4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch)
tree2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/lib/dpstk
parenta840692edc9c6d19cd7c057f68e39c7d95eb767d (diff)
downloadnx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.gz
nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.bz2
nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.zip
Imported nx-X11-3.1.0-1.tar.gznx-X11/3.1.0-1
Summary: Imported nx-X11-3.1.0-1.tar.gz Keywords: Imported nx-X11-3.1.0-1.tar.gz into Git repository
Diffstat (limited to 'nx-X11/lib/dpstk')
-rw-r--r--nx-X11/lib/dpstk/CSBwraps.psw343
-rw-r--r--nx-X11/lib/dpstk/ColorSB.c3388
-rw-r--r--nx-X11/lib/dpstk/ColorSelect.ad162
-rw-r--r--nx-X11/lib/dpstk/DPSScrollW.c3500
-rw-r--r--nx-X11/lib/dpstk/DSWwraps.psw75
-rw-r--r--nx-X11/lib/dpstk/FSBwraps.psw491
-rw-r--r--nx-X11/lib/dpstk/FontCreato.c1610
-rw-r--r--nx-X11/lib/dpstk/FontSB.c4884
-rw-r--r--nx-X11/lib/dpstk/FontSBI.h57
-rw-r--r--nx-X11/lib/dpstk/FontSample.c1814
-rw-r--r--nx-X11/lib/dpstk/FontSelect.ad415
-rw-r--r--nx-X11/lib/dpstk/Imakefile91
-rw-r--r--nx-X11/lib/dpstk/XDPSpreview.c636
-rw-r--r--nx-X11/lib/dpstk/XDPSpwraps.psw97
-rw-r--r--nx-X11/lib/dpstk/XDPSshare.c727
-rw-r--r--nx-X11/lib/dpstk/XDPSswraps.psw110
-rw-r--r--nx-X11/lib/dpstk/XDPSuserpath.c240
-rw-r--r--nx-X11/lib/dpstk/dpsXcommonI.h73
-rw-r--r--nx-X11/lib/dpstk/dpstk-def.cpp65
-rw-r--r--nx-X11/lib/dpstk/eyedrop16.xbm8
-rw-r--r--nx-X11/lib/dpstk/eyedrop32.xbm16
-rw-r--r--nx-X11/lib/dpstk/eyedropmask16.xbm8
-rw-r--r--nx-X11/lib/dpstk/eyedropmask32.xbm16
-rw-r--r--nx-X11/lib/dpstk/heyedrop.xbm7
-rw-r--r--nx-X11/lib/dpstk/square.xbm8
-rw-r--r--nx-X11/lib/dpstk/squaremask.xbm6
26 files changed, 18847 insertions, 0 deletions
diff --git a/nx-X11/lib/dpstk/CSBwraps.psw b/nx-X11/lib/dpstk/CSBwraps.psw
new file mode 100644
index 000000000..02a2041ee
--- /dev/null
+++ b/nx-X11/lib/dpstk/CSBwraps.psw
@@ -0,0 +1,343 @@
+/*
+ * CSBwraps.psw
+ *
+ * (c) Copyright 1993-1994 Adobe Systems Incorporated.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sublicense this software
+ * and its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notices appear in all copies and that
+ * both those copyright notices and this permission notice appear in
+ * supporting documentation and that the name of Adobe Systems Incorporated
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. No trademark license
+ * to use the Adobe trademarks is hereby granted. If the Adobe trademark
+ * "Display PostScript"(tm) is used to describe this software, its
+ * functionality or for any other purpose, such use shall be limited to a
+ * statement that this software works in conjunction with the Display
+ * PostScript system. Proper trademark attribution to reflect Adobe's
+ * ownership of the trademark shall be given whenever any such reference to
+ * the Display PostScript system is made.
+ *
+ * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
+ * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
+ * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
+ * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
+ * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
+ *
+ * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+ * Incorporated which may be registered in certain jurisdictions
+ *
+ * Author: Adobe Systems Incorporated
+ */
+
+defineps _DPSCColormapMatch(DPSContext ctxt; int colormap | boolean *match)
+ currentXgcdrawablecolor % gc draw x y [....colormap...]
+ 10 get colormap eq match % gc draw x y
+ pop pop pop pop
+endps
+
+defineps _DPSCTriangle(DPSContext ctxt; double h, w)
+ newpath
+ 0 0 moveto
+ w 0 rlineto
+ 0 h rlineto
+ closepath
+ fill
+endps
+
+defineps _DPSCShowFillMe(DPSContext ctxt; char *str)
+ /Helvetica-Bold 12 selectfont
+ 2 5 moveto
+ 0 setgray
+ (str) show
+endps
+
+defineps _DPSCShowMessage(DPSContext ctxt; char *str)
+ 1 setgray
+ 0 0 1000 1000 rectfill
+ /Helvetica-Bold 12 selectfont
+ 10 2 moveto
+ 0 setgray
+ (str) show
+endps
+
+defineps _DPSCRGBBlend(DPSContext ctxt; double x, y, width, height;
+ char *function; int steps)
+ gsave
+ x y translate
+ width steps div
+ 0 1 steps 1 sub {
+ steps div (function) cvx exec setrgbcolor
+ dup 0 0 3 -1 roll height rectfill
+ dup 0 translate
+ } for
+ pop
+ grestore
+endps
+
+defineps _DPSCHSBBlend(DPSContext ctxt; double x, y, width, height;
+ char *function; int steps)
+ gsave
+ x y translate
+ width steps div
+ 0 1 steps 1 sub {
+ steps div (function) cvx exec sethsbcolor
+ dup 0 0 3 -1 roll height rectfill
+ dup 0 translate
+ } for
+ pop
+ grestore
+endps
+
+defineps _DPSCCMYKBlend(DPSContext ctxt; double x, y, width, height;
+ char *function; int steps)
+ gsave
+ x y translate
+ width steps div
+ 0 1 steps 1 sub {
+ steps div (function) cvx exec setcmykcolor
+ dup 0 0 3 -1 roll height rectfill
+ dup 0 translate
+ } for
+ pop
+ grestore
+endps
+
+defineps _DPSCGrayBlend(DPSContext ctxt; double x, y, width, height;
+ char *function; int steps)
+ gsave
+ x y translate
+ width steps div
+ 0 1 steps 1 sub {
+ steps div (function) cvx exec setgray
+ dup 0 0 3 -1 roll height rectfill
+ dup 0 translate
+ } for
+ pop
+ grestore
+endps
+
+defineps _DPSCGetInvCTM(DPSContext ctxt; | float invctm[6])
+ matrix currentmatrix matrix invertmatrix invctm
+endps
+
+defineps _DPSCDoRGBColorPalette(DPSContext ctxt; char *func;
+ double red, green, blue; double width, height;
+ int steps | boolean *success)
+ mark {
+ gsave
+ 0 0 translate
+ width steps div
+ 0 1 steps 1 sub {
+ steps div red green blue 4 -1 roll func setrgbcolor
+ dup 0 0 3 -1 roll height rectfill
+ dup 0 translate
+ } for
+ pop
+ grestore
+ } stopped not success cleartomark
+endps
+
+defineps _DPSCDoCMYKColorPalette(DPSContext ctxt; char *func;
+ double cyan, magenta, yellow, black;
+ double width, height;
+ int steps | boolean *success)
+ mark {
+ gsave
+ 0 0 translate
+ width steps div
+ 0 1 steps 1 sub {
+ steps div cyan magenta yellow black 5 -1 roll func setcmykcolor
+ dup 0 0 3 -1 roll height rectfill
+ dup 0 translate
+ } for
+ pop
+ grestore
+ } stopped not success cleartomark
+endps
+
+defineps _DPSCDoHSBColorPalette(DPSContext ctxt; char *func;
+ double hue, sat, bright;
+ double width, height;
+ int steps | boolean *success)
+ mark {
+ gsave
+ 0 0 translate
+ width steps div
+ 0 1 steps 1 sub {
+ steps div hue sat bright 4 -1 roll func sethsbcolor
+ dup 0 0 3 -1 roll height rectfill
+ dup 0 translate
+ } for
+ pop
+ grestore
+ } stopped not success cleartomark
+endps
+
+defineps _DPSCDoGrayColorPalette(DPSContext ctxt; char *func;
+ double gray; double width, height;
+ int steps | boolean *success)
+ mark {
+ gsave
+ 0 0 translate
+ width steps div
+ 0 1 steps 1 sub {
+ steps div gray exch func setgray
+ dup 0 0 3 -1 roll height rectfill
+ dup 0 translate
+ } for
+ pop
+ grestore
+ } stopped not success cleartomark
+endps
+
+
+defineps _DPSCDoRGBPalette(DPSContext ctxt; char *func;
+ double width, height;
+ int steps | boolean *success)
+ mark {
+ gsave
+ 0 0 translate
+ width steps div
+ 0 1 steps 1 sub {
+ steps div func setrgbcolor
+ dup 0 0 3 -1 roll height rectfill
+ dup 0 translate
+ } for
+ pop
+ grestore
+ } stopped not success cleartomark
+endps
+
+defineps _DPSCDoCMYKPalette(DPSContext ctxt; char *func;
+ double width, height;
+ int steps | boolean *success)
+ mark {
+ gsave
+ 0 0 translate
+ width steps div
+ 0 1 steps 1 sub {
+ steps div func setcmykcolor
+ dup 0 0 3 -1 roll height rectfill
+ dup 0 translate
+ } for
+ pop
+ grestore
+ } stopped not success cleartomark
+endps
+
+defineps _DPSCDoHSBPalette(DPSContext ctxt; char *func;
+ double width, height;
+ int steps | boolean *success)
+ mark {
+ gsave
+ 0 0 translate
+ width steps div
+ 0 1 steps 1 sub {
+ steps div func sethsbcolor
+ dup 0 0 3 -1 roll height rectfill
+ dup 0 translate
+ } for
+ pop
+ grestore
+ } stopped not success cleartomark
+endps
+
+defineps _DPSCDoGrayPalette(DPSContext ctxt; char *func;
+ double width, height;
+ int steps | boolean *success)
+ mark {
+ gsave
+ 0 0 translate
+ width steps div
+ 0 1 steps 1 sub {
+ steps div func setgray
+ dup 0 0 3 -1 roll height rectfill
+ dup 0 translate
+ } for
+ pop
+ grestore
+ } stopped not success cleartomark
+endps
+
+defineps _DPSCQueryRGBColorPalette(DPSContext ctxt; char *func;
+ double pct, red, green, blue; |
+ float *redOut, *greenOut, *blueOut;
+ boolean *success)
+ mark {
+ red green blue pct func
+ } stopped dup not success {0 0 0} if
+ blueOut greenOut redOut cleartomark
+endps
+
+defineps _DPSCQueryCMYKColorPalette(DPSContext ctxt; char *func;
+ double pct, cyan, magenta, yellow, black; |
+ float *cyanOut, *magentaOut, *yellowOut,
+ *blackOut; boolean *success)
+ mark {
+ cyan magenta yellow black pct func
+ } stopped dup not success {0 0 0 0} if
+ blackOut yellowOut magentaOut cyanOut cleartomark
+endps
+
+defineps _DPSCQueryHSBColorPalette(DPSContext ctxt; char *func;
+ double pct, hue, sat, bright; |
+ float *hueOut, *satOut, *brightOut;
+ boolean *success)
+ mark {
+ hue sat bright pct func
+ } stopped dup not success {0 0 0} if
+ brightOut satOut hueOut cleartomark
+endps
+
+defineps _DPSCQueryGrayColorPalette(DPSContext ctxt; char *func;
+ double pct, gray; |
+ float *grayOut; boolean *success)
+ mark {
+ gray pct func
+ } stopped dup not success {0} if
+ grayOut cleartomark
+endps
+
+
+defineps _DPSCQueryRGBPalette(DPSContext ctxt; char *func; double pct; |
+ float *redOut, *greenOut, *blueOut;
+ boolean *success)
+ mark {
+ pct func
+ } stopped dup not success {0 0 0} if
+ blueOut greenOut redOut cleartomark
+endps
+
+defineps _DPSCQueryCMYKPalette(DPSContext ctxt; char *func; double pct; |
+ float *cyanOut, *magentaOut, *yellowOut,
+ *blackOut; boolean *success)
+ mark {
+ pct func
+ } stopped dup not success {0 0 0 0} if
+ blackOut yellowOut magentaOut cyanOut cleartomark
+endps
+
+defineps _DPSCQueryHSBPalette(DPSContext ctxt; char *func; double pct; |
+ float *hueOut, *satOut, *brightOut;
+ boolean *success)
+ mark {
+ pct func
+ } stopped dup not success {0 0 0} if
+ brightOut satOut hueOut cleartomark
+endps
+
+defineps _DPSCQueryGrayPalette(DPSContext ctxt; char *func; double pct; |
+ float *grayOut; boolean *success)
+ mark {
+ pct func
+ } stopped dup not success {0} if
+ grayOut cleartomark
+endps
+
diff --git a/nx-X11/lib/dpstk/ColorSB.c b/nx-X11/lib/dpstk/ColorSB.c
new file mode 100644
index 000000000..d2d71088e
--- /dev/null
+++ b/nx-X11/lib/dpstk/ColorSB.c
@@ -0,0 +1,3388 @@
+/*
+ * ColorSB.c
+ *
+ * (c) Copyright 1993-1994 Adobe Systems Incorporated.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sublicense this software
+ * and its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notices appear in all copies and that
+ * both those copyright notices and this permission notice appear in
+ * supporting documentation and that the name of Adobe Systems Incorporated
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. No trademark license
+ * to use the Adobe trademarks is hereby granted. If the Adobe trademark
+ * "Display PostScript"(tm) is used to describe this software, its
+ * functionality or for any other purpose, such use shall be limited to a
+ * statement that this software works in conjunction with the Display
+ * PostScript system. Proper trademark attribution to reflect Adobe's
+ * ownership of the trademark shall be given whenever any such reference to
+ * the Display PostScript system is made.
+ *
+ * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
+ * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
+ * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
+ * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
+ * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
+ *
+ * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+ * Incorporated which may be registered in certain jurisdictions
+ *
+ * Author: Adobe Systems Incorporated
+ */
+/* $XFree86$ */
+
+#ifndef X_NOT_POSIX
+#include <unistd.h>
+#endif
+
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <X11/ShellP.h>
+#include <stdlib.h>
+#include <Xm/Xm.h>
+
+/* There are no words to describe how I feel about having to do this */
+
+#if XmVersion > 1001
+#include <Xm/ManagerP.h>
+#else
+#include <Xm/XmP.h>
+#endif
+
+#include <Xm/Form.h>
+#include <Xm/Label.h>
+#include <Xm/LabelG.h>
+#include <Xm/PushB.h>
+#include <Xm/PushBG.h>
+#include <Xm/SeparatoG.h>
+#include <Xm/DrawingA.h>
+#include <Xm/Scale.h>
+#include <Xm/RowColumn.h>
+#include <Xm/Frame.h>
+#include <Xm/MessageB.h>
+
+#include <DPS/dpsXclient.h>
+#include "dpsXcommonI.h"
+#include <DPS/dpsXshare.h>
+#include "eyedrop16.xbm"
+#include "eyedropmask16.xbm"
+#include "eyedrop32.xbm"
+#include "eyedropmask32.xbm"
+#include "heyedrop.xbm"
+#include "square.xbm"
+#include "squaremask.xbm"
+#include "CSBwraps.h"
+#include <math.h>
+#include <stdio.h>
+#include <pwd.h>
+#include <DPS/ColorSBP.h>
+
+#define PATH_BUF_SIZE 1024
+
+/* Turn a string into a compound string */
+#define CS(str, w) CreateSharedCS(str, w)
+
+#undef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#undef MAX
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define TO_PCT(val) ((int) (val * 100.0 + 0.5))
+#define TO_X(color) ((color) * 65535)
+
+#define Offset(field) XtOffsetOf(ColorSelectionBoxRec, csb.field)
+
+static XtResource resources[] = {
+ {XtNcontext, XtCContext, XtRDPSContext, sizeof(DPSContext),
+ Offset(context), XtRDPSContext, (XtPointer) NULL},
+ {XtNrgbLabels, XtCRgbLabels, XtRString, sizeof(String),
+ Offset(rgb_labels), XtRString, (XtPointer) "R:G:B"},
+ {XtNcmykLabels, XtCCmykLabels, XtRString, sizeof(String),
+ Offset(cmyk_labels), XtRString, (XtPointer) "C:M:Y:K"},
+ {XtNhsbLabels, XtCHsbLabels, XtRString, sizeof(String),
+ Offset(hsb_labels), XtRString, (XtPointer) "H:S:B"},
+ {XtNgrayLabels, XtCGrayLabels, XtRString, sizeof(String),
+ Offset(gray_labels), XtRString, (XtPointer) "Gray"},
+ {XtNcellSize, XtCCellSize, XtRDimension, sizeof(Dimension),
+ Offset(cell_size), XtRImmediate, (XtPointer) 15},
+ {XtNnumCells, XtCNumCells, XtRShort, sizeof(short),
+ Offset(num_cells), XtRImmediate, (XtPointer) 30},
+ {XtNfillMe, XtCFillMe, XtRString, sizeof(String),
+ Offset(fill_me), XtRString, (XtPointer) "Fill me with colors"},
+ {XtNcurrentSpace, XtCCurrentSpace, XtRColorSpace, sizeof(CSBColorSpace),
+ Offset(current_space), XtRImmediate, (XtPointer) CSBSpaceHSB},
+ {XtNcurrentRendering, XtCCurrentRendering, XtRRenderingType,
+ sizeof(CSBRenderingType), Offset(current_rendering),
+ XtRImmediate, (XtPointer) CSBDisplayDPS},
+ {XtNcurrentPalette, XtCCurrentPalette, XtRShort, sizeof(short),
+ Offset(current_palette), XtRImmediate, (XtPointer) 0},
+ {XtNbrokenPaletteLabel, XtCBrokenPaletteLabel, XtRString,
+ sizeof(String), Offset(broken_palette_label),
+ XtRString, (XtPointer) "(broken)"},
+ {XtNbrokenPaletteMessage, XtCBrokenPaletteMessage, XtRString,
+ sizeof(String), Offset(broken_palette_message),
+ XtRString, (XtPointer) "The current palette contains an error"},
+
+ {XtNpalette0Label, XtCPaletteLabel, XtRString, sizeof(String),
+ Offset(palette_label[0]), XtRString, (XtPointer) NULL},
+ {XtNpalette0Space, XtCPaletteSpace, XtRColorSpace, sizeof(CSBColorSpace),
+ Offset(palette_space[0]), XtRImmediate, (XtPointer) CSBSpaceRGB},
+ {XtNpalette0ColorDependent, XtCPaletteColorDependent,
+ XtRBoolean, sizeof(Boolean),
+ Offset(palette_color_dependent[0]), XtRImmediate, (XtPointer) False},
+ {XtNpalette0Function, XtCPaletteFunction, XtRString, sizeof(String),
+ Offset(palette_function[0]), XtRImmediate, (XtPointer) NULL},
+
+ {XtNpalette1Label, XtCPaletteLabel, XtRString, sizeof(String),
+ Offset(palette_label[1]), XtRString, (XtPointer) NULL},
+ {XtNpalette1Space, XtCPaletteSpace, XtRColorSpace, sizeof(CSBColorSpace),
+ Offset(palette_space[1]), XtRImmediate, (XtPointer) CSBSpaceRGB},
+ {XtNpalette1ColorDependent, XtCPaletteColorDependent,
+ XtRBoolean, sizeof(Boolean),
+ Offset(palette_color_dependent[1]), XtRImmediate, (XtPointer) False},
+ {XtNpalette1Function, XtCPaletteFunction, XtRString, sizeof(String),
+ Offset(palette_function[1]), XtRImmediate, (XtPointer) NULL},
+
+ {XtNpalette2Label, XtCPaletteLabel, XtRString, sizeof(String),
+ Offset(palette_label[2]), XtRString, (XtPointer) NULL},
+ {XtNpalette2Space, XtCPaletteSpace, XtRColorSpace, sizeof(CSBColorSpace),
+ Offset(palette_space[2]), XtRImmediate, (XtPointer) CSBSpaceRGB},
+ {XtNpalette2ColorDependent, XtCPaletteColorDependent,
+ XtRBoolean, sizeof(Boolean),
+ Offset(palette_color_dependent[2]), XtRImmediate, (XtPointer) False},
+ {XtNpalette2Function, XtCPaletteFunction, XtRString, sizeof(String),
+ Offset(palette_function[2]), XtRImmediate, (XtPointer) NULL},
+
+ {XtNpalette3Label, XtCPaletteLabel, XtRString, sizeof(String),
+ Offset(palette_label[3]), XtRString, (XtPointer) NULL},
+ {XtNpalette3Space, XtCPaletteSpace, XtRColorSpace, sizeof(CSBColorSpace),
+ Offset(palette_space[3]), XtRImmediate, (XtPointer) CSBSpaceRGB},
+ {XtNpalette3ColorDependent, XtCPaletteColorDependent,
+ XtRBoolean, sizeof(Boolean),
+ Offset(palette_color_dependent[3]), XtRImmediate, (XtPointer) False},
+ {XtNpalette3Function, XtCPaletteFunction, XtRString, sizeof(String),
+ Offset(palette_function[3]), XtRImmediate, (XtPointer) NULL},
+
+ {XtNpalette4Label, XtCPaletteLabel, XtRString, sizeof(String),
+ Offset(palette_label[4]), XtRString, (XtPointer) NULL},
+ {XtNpalette4Space, XtCPaletteSpace, XtRColorSpace, sizeof(CSBColorSpace),
+ Offset(palette_space[4]), XtRImmediate, (XtPointer) CSBSpaceRGB},
+ {XtNpalette4ColorDependent, XtCPaletteColorDependent,
+ XtRBoolean, sizeof(Boolean),
+ Offset(palette_color_dependent[4]), XtRImmediate, (XtPointer) False},
+ {XtNpalette4Function, XtCPaletteFunction, XtRString, sizeof(String),
+ Offset(palette_function[4]), XtRImmediate, (XtPointer) NULL},
+
+ {XtNpalette5Label, XtCPaletteLabel, XtRString, sizeof(String),
+ Offset(palette_label[5]), XtRString, (XtPointer) NULL},
+ {XtNpalette5Space, XtCPaletteSpace, XtRColorSpace, sizeof(CSBColorSpace),
+ Offset(palette_space[5]), XtRImmediate, (XtPointer) CSBSpaceRGB},
+ {XtNpalette5ColorDependent, XtCPaletteColorDependent,
+ XtRBoolean, sizeof(Boolean),
+ Offset(palette_color_dependent[5]), XtRImmediate, (XtPointer) False},
+ {XtNpalette5Function, XtCPaletteFunction, XtRString, sizeof(String),
+ Offset(palette_function[5]), XtRImmediate, (XtPointer) NULL},
+
+ {XtNpalette6Label, XtCPaletteLabel, XtRString, sizeof(String),
+ Offset(palette_label[6]), XtRString, (XtPointer) NULL},
+ {XtNpalette6Space, XtCPaletteSpace, XtRColorSpace, sizeof(CSBColorSpace),
+ Offset(palette_space[6]), XtRImmediate, (XtPointer) CSBSpaceRGB},
+ {XtNpalette6ColorDependent, XtCPaletteColorDependent,
+ XtRBoolean, sizeof(Boolean),
+ Offset(palette_color_dependent[6]), XtRImmediate, (XtPointer) False},
+ {XtNpalette6Function, XtCPaletteFunction, XtRString, sizeof(String),
+ Offset(palette_function[6]), XtRImmediate, (XtPointer) NULL},
+
+ {XtNpalette7Label, XtCPaletteLabel, XtRString, sizeof(String),
+ Offset(palette_label[7]), XtRString, (XtPointer) NULL},
+ {XtNpalette7Space, XtCPaletteSpace, XtRColorSpace, sizeof(CSBColorSpace),
+ Offset(palette_space[7]), XtRImmediate, (XtPointer) CSBSpaceRGB},
+ {XtNpalette7ColorDependent, XtCPaletteColorDependent,
+ XtRBoolean, sizeof(Boolean),
+ Offset(palette_color_dependent[7]), XtRImmediate, (XtPointer) False},
+ {XtNpalette7Function, XtCPaletteFunction, XtRString, sizeof(String),
+ Offset(palette_function[7]), XtRImmediate, (XtPointer) NULL},
+
+ {XtNpalette8Label, XtCPaletteLabel, XtRString, sizeof(String),
+ Offset(palette_label[8]), XtRString, (XtPointer) NULL},
+ {XtNpalette8Space, XtCPaletteSpace, XtRColorSpace, sizeof(CSBColorSpace),
+ Offset(palette_space[8]), XtRImmediate, (XtPointer) CSBSpaceRGB},
+ {XtNpalette8ColorDependent, XtCPaletteColorDependent,
+ XtRBoolean, sizeof(Boolean),
+ Offset(palette_color_dependent[8]), XtRImmediate, (XtPointer) False},
+ {XtNpalette8Function, XtCPaletteFunction, XtRString, sizeof(String),
+ Offset(palette_function[8]), XtRImmediate, (XtPointer) NULL},
+
+ {XtNpalette9Label, XtCPaletteLabel, XtRString, sizeof(String),
+ Offset(palette_label[9]), XtRString, (XtPointer) NULL},
+ {XtNpalette9Space, XtCPaletteSpace, XtRColorSpace, sizeof(CSBColorSpace),
+ Offset(palette_space[9]), XtRImmediate, (XtPointer) CSBSpaceRGB},
+ {XtNpalette9ColorDependent, XtCPaletteColorDependent,
+ XtRBoolean, sizeof(Boolean),
+ Offset(palette_color_dependent[9]), XtRImmediate, (XtPointer) False},
+ {XtNpalette9Function, XtCPaletteFunction, XtRString, sizeof(String),
+ Offset(palette_function[9]), XtRImmediate, (XtPointer) NULL},
+
+ {XtNokCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
+ Offset(ok_callback), XtRCallback, (XtPointer) NULL},
+ {XtNapplyCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
+ Offset(apply_callback), XtRCallback, (XtPointer) NULL},
+ {XtNresetCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
+ Offset(reset_callback), XtRCallback, (XtPointer) NULL},
+ {XtNcancelCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
+ Offset(cancel_callback), XtRCallback, (XtPointer) NULL},
+ {XtNvalueChangedCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
+ Offset(value_changed_callback), XtRCallback, (XtPointer) NULL}
+};
+
+static Boolean SetColor (Widget w, CSBColorSpace space, double c1, double c2, double c3, double c4, Bool setSpace);
+static Boolean SetValues (Widget old, Widget req, Widget new, ArgList args, Cardinal *num_args);
+static XtGeometryResult GeometryManager (Widget w, XtWidgetGeometry *desired, XtWidgetGeometry *allowed);
+static void ChangeLabel (Widget label, double n);
+static void ChangeManaged (Widget w);
+static void ClassInitialize (void);
+static void ClassPartInitialize (WidgetClass widget_class);
+static void CreateChildren (ColorSelectionBoxWidget csb);
+static void Destroy (Widget widget);
+static void DrawDock (ColorSelectionBoxWidget csb);
+static void DrawPalette (ColorSelectionBoxWidget csb);
+static void FillPatch (ColorSelectionBoxWidget csb);
+static void GetColor (Widget w, CSBColorSpace space, float *c1, float *c2, float *c3, float *c4);
+static void Initialize (Widget request, Widget new, ArgList args, Cardinal *num_args);
+static void InitializeDock (ColorSelectionBoxWidget csb);
+static void Realize (Widget w, XtValueMask *mask, XSetWindowAttributes *attr);
+static void Resize (Widget widget);
+static void SaveDockContents (ColorSelectionBoxWidget csb);
+static void SetBackground (ColorSelectionBoxWidget csb);
+static void SetCMYKValues (ColorSelectionBoxWidget csb);
+static void SetColorSpace (ColorSelectionBoxWidget csb);
+static void SetGrayValues (ColorSelectionBoxWidget csb);
+static void SetHSBValues (ColorSelectionBoxWidget csb);
+static void SetRGBValues (ColorSelectionBoxWidget csb);
+static void SetRendering (ColorSelectionBoxWidget csb);
+static void SetSliders (ColorSelectionBoxWidget csb);
+static void UpdateColorSpaces (ColorSelectionBoxWidget csb, CSBColorSpace masterSpace);
+
+static void DockPress (Widget w, XtPointer data, XEvent *event, Boolean *goOn);
+static void EyedropPointer (Widget w, XtPointer data, XEvent *event, Boolean *goOn);
+static void FormResize (Widget w, XtPointer data, XEvent *event, Boolean *goOn);
+static void PalettePress (Widget w, XtPointer data, XEvent *event, Boolean *goOn);
+static void PatchPress (Widget w, XtPointer data, XEvent *event, Boolean *goOn);
+static void PatchRelease (Widget w, XtPointer data, XEvent *event, Boolean *goOn);
+
+static void ApplyCallback (Widget w, XtPointer clientData, XtPointer callData);
+static void DoEyedropCallback (Widget w, XtPointer clientData, XtPointer callData);
+static void DrawDockCallback (Widget w, XtPointer clientData, XtPointer callData);
+static void DrawPaletteCallback (Widget w, XtPointer clientData, XtPointer callData);
+static void FillPatchCallback (Widget w, XtPointer clientData, XtPointer callData);
+static void OKCallback (Widget w, XtPointer clientData, XtPointer callData);
+static void SetCMYKCallback (Widget w, XtPointer clientData, XtPointer callData);
+static void SetGrayCallback (Widget w, XtPointer clientData, XtPointer callData);
+static void SetHSBCallback (Widget w, XtPointer clientData, XtPointer callData);
+static void SetRGBCallback (Widget w, XtPointer clientData, XtPointer callData);
+static void Slider1Callback (Widget w, XtPointer clientData, XtPointer callData);
+static void Slider2Callback (Widget w, XtPointer clientData, XtPointer callData);
+static void Slider3Callback (Widget w, XtPointer clientData, XtPointer callData);
+static void Slider4Callback (Widget w, XtPointer clientData, XtPointer callData);
+
+ColorSelectionBoxClassRec colorSelectionBoxClassRec = {
+ /* Core class part */
+ {
+ /* superclass */ (WidgetClass) &xmManagerClassRec,
+ /* class_name */ "ColorSelectionBox",
+ /* widget_size */ sizeof(ColorSelectionBoxRec),
+ /* class_initialize */ ClassInitialize,
+ /* class_part_initialize */ ClassPartInitialize,
+ /* class_inited */ False,
+ /* initialize */ Initialize,
+ /* initialize_hook */ NULL,
+ /* realize */ Realize,
+ /* actions */ NULL,
+ /* num_actions */ 0,
+ /* resources */ resources,
+ /* num_resources */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ True,
+ /* compress_exposure */ XtExposeCompressMultiple,
+ /* compress_enterleave */ True,
+ /* visible_interest */ False,
+ /* destroy */ Destroy,
+ /* resize */ Resize,
+ /* expose */ NULL,
+ /* set_values */ SetValues,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* callback offsets */ NULL,
+ /* tm_table */ NULL,
+ /* query_geometry */ XtInheritQueryGeometry,
+ /* display_accelerator */ NULL,
+ /* extension */ NULL,
+ },
+ /* Composite class part */
+ {
+ /* geometry_manager */ GeometryManager,
+ /* change_managed */ ChangeManaged,
+ /* insert_child */ XtInheritInsertChild,
+ /* delete_child */ XtInheritDeleteChild,
+ /* extension */ NULL,
+ },
+ /* Constraint class part */
+ {
+ /* resources */ NULL,
+ /* num_resources */ 0,
+ /* constraint_size */ 0,
+ /* initialize */ NULL,
+ /* destroy */ NULL,
+ /* set_values */ NULL,
+ /* extension */ NULL,
+ },
+ /* Manager class part */
+ {
+ /* translations */ XtInheritTranslations,
+ /* syn_resources */ NULL,
+ /* num_syn_resources */ 0,
+ /* syn_constraint_resources */ NULL,
+ /* num_syn_constraint_resources */ 0,
+ /* parent_process */ XmInheritParentProcess,
+ /* extension */ NULL,
+ },
+ /* ColorSelectionBox class part */
+ {
+ /* set_color */ SetColor,
+ /* get_color */ GetColor,
+ /* extension */ NULL,
+ }
+};
+
+WidgetClass colorSelectionBoxWidgetClass =
+ (WidgetClass) &colorSelectionBoxClassRec;
+
+static XmString CreateSharedCS(String str, Widget w)
+{
+ XrmValue src, dst;
+ XmString result;
+
+ src.addr = str;
+ src.size = strlen(str);
+
+ dst.addr = (caddr_t) &result;
+ dst.size = sizeof(result);
+
+ if (XtConvertAndStore(w, XtRString, &src, XmRXmString, &dst)) {
+ return result;
+ } else return NULL;
+}
+
+static Boolean LowerCase(String from, String to, int size)
+{
+ register char ch;
+ register int i;
+
+ for (i = 0; i < size; i++) {
+ ch = from[i];
+ if (ch >= 'A' && ch <= 'Z') to[i] = ch - 'A' + 'a';
+ else to[i] = ch;
+ if (ch == '\0') return False;
+ }
+ return TRUE;
+}
+
+/* ARGSUSED */
+
+static Boolean CvtStringToColorSpace(
+ Display *dpy,
+ XrmValuePtr args,
+ Cardinal *num_args,
+ XrmValuePtr from,
+ XrmValuePtr to,
+ XtPointer *data)
+{
+#define LOWER_SIZE 5
+ char lower[LOWER_SIZE]; /* Lower cased string value */
+ Boolean badConvert;
+ static CSBColorSpace c;
+
+ if (*num_args != 0) { /* Check for correct number */
+ XtAppErrorMsg(XtDisplayToApplicationContext(dpy),
+ "cvtStringToColorSpace", "wrongParameters",
+ "XtToolkitError",
+ "String to colorspace conversion needs no extra arguments",
+ (String *) NULL, (Cardinal *) NULL);
+ }
+
+ /* Lower case the value */
+ badConvert = LowerCase(from->addr, lower, LOWER_SIZE);
+
+ /* Try to convert if a short enough string specified */
+ if (!badConvert) {
+ if (strcmp(lower, "rgb") == 0) c = CSBSpaceRGB;
+ else if (strcmp(lower, "cmyk") == 0) c = CSBSpaceCMYK;
+ else if (strcmp(lower, "hsb") == 0) c = CSBSpaceHSB;
+ else if (strcmp(lower, "gray") == 0) c = CSBSpaceGray;
+ else if (strcmp(lower, "grey") == 0) c = CSBSpaceGray;
+ else badConvert = True;
+ }
+
+ /* String too long or unknown value -- issue warning */
+ if (badConvert) {
+ XtDisplayStringConversionWarning(dpy, from->addr, "ColorSpace");
+ } else {
+ if (to->addr == NULL) to->addr = (caddr_t) &c;
+
+ else if (to->size < sizeof(CSBColorSpace)) badConvert = TRUE;
+ else *(CSBColorSpace *) to->addr = c;
+
+ to->size = sizeof(CSBColorSpace);
+ }
+ return !badConvert;
+#undef LOWER_SIZE
+}
+
+/* ARGSUSED */
+
+static Boolean CvtStringToRenderingType(
+ Display *dpy,
+ XrmValuePtr args,
+ Cardinal *num_args,
+ XrmValuePtr from,
+ XrmValuePtr to,
+ XtPointer *data)
+{
+#define LOWER_SIZE 5
+ char lower[LOWER_SIZE]; /* Lower cased string value */
+ Boolean badConvert;
+ static CSBRenderingType c;
+
+ if (*num_args != 0) { /* Check for correct number */
+ XtAppErrorMsg(XtDisplayToApplicationContext(dpy),
+ "cvtStringToRenderingType", "wrongParameters",
+ "XtToolkitError",
+ "String to rendering type conversion needs no extra arguments",
+ (String *) NULL, (Cardinal *) NULL);
+ }
+
+ /* Lower case the value */
+ badConvert = LowerCase(from->addr, lower, LOWER_SIZE);
+
+ /* Try to convert if a short enough string specified */
+ if (!badConvert) {
+ if (strcmp(lower, "x") == 0) c = CSBDisplayX;
+ else if (strcmp(lower, "dps") == 0) c = CSBDisplayDPS;
+ else if (strcmp(lower, "both") == 0) c = CSBDisplayBoth;
+ else badConvert = True;
+ }
+
+ /* String too long or unknown value -- issue warning */
+ if (badConvert) {
+ XtDisplayStringConversionWarning(dpy, from->addr, "RenderingType");
+ } else {
+ if (to->addr == NULL) to->addr = (caddr_t) &c;
+
+ else if (to->size < sizeof(CSBRenderingType)) badConvert = TRUE;
+ else *(CSBRenderingType *) to->addr = c;
+
+ to->size = sizeof(CSBRenderingType);
+ }
+ return !badConvert;
+#undef LOWER_SIZE
+}
+
+static void ClassInitialize(void)
+{
+ /* Register converters */
+
+ XtSetTypeConverter(XtRString, XtRColorSpace,
+ CvtStringToColorSpace, (XtConvertArgList) NULL, 0,
+ XtCacheAll, (XtDestructor) NULL);
+ XtSetTypeConverter(XtRString, XtRRenderingType,
+ CvtStringToRenderingType, (XtConvertArgList) NULL, 0,
+ XtCacheAll, (XtDestructor) NULL);
+}
+
+/* ARGSUSED */
+
+static void ClassPartInitialize(WidgetClass widget_class)
+{
+ register ColorSelectionBoxWidgetClass wc =
+ (ColorSelectionBoxWidgetClass) widget_class;
+ ColorSelectionBoxWidgetClass super =
+ (ColorSelectionBoxWidgetClass) wc->core_class.superclass;
+
+ if (wc->csb_class.set_color == InheritSetColor) {
+ wc->csb_class.set_color = super->csb_class.set_color;
+ }
+ if (wc->csb_class.get_color == InheritGetColor) {
+ wc->csb_class.get_color = super->csb_class.get_color;
+ }
+}
+
+static void ToUserSpace(
+ ColorSelectionBoxWidget csb,
+ int xWidth, int xHeight,
+ float *uWidth, float *uHeight)
+{
+ register float *i = csb->csb.itransform;
+
+ *uWidth = i[0] * xWidth - i[2] * xHeight + i[4];
+ *uHeight= i[1] * xWidth - i[3] * xHeight + i[5];
+}
+
+static void ColorizeRGB(ColorSelectionBoxWidget csb)
+{
+ Dimension height, width;
+ int depth, steps;
+ float w, h;
+
+ XtVaGetValues(csb->csb.slider_child[0], XtNwidth, &width,
+ XtNheight, &height,
+ XtNdepth, &depth, NULL);
+
+ if (csb->csb.red_pixmap != None && width != csb->csb.rgb_slider_width) {
+ XFreePixmap(XtDisplay(csb), csb->csb.red_pixmap);
+ XFreePixmap(XtDisplay(csb), csb->csb.green_pixmap);
+ XFreePixmap(XtDisplay(csb), csb->csb.blue_pixmap);
+ csb->csb.red_pixmap = None;
+ }
+
+ if (csb->csb.red_pixmap == None) {
+ csb->csb.rgb_slider_width = width;
+ if (csb->csb.visual_class == TrueColor) steps = width / 2;
+ else steps = width / 4;
+
+ ToUserSpace(csb, width, height, &w, &h);
+
+ csb->csb.red_pixmap = XCreatePixmap(XtDisplay(csb), XtWindow(csb),
+ width, height, depth);
+
+ XDPSSetContextGState(csb->csb.context, csb->csb.base_gstate);
+ XDPSSetContextDrawable(csb->csb.context, csb->csb.red_pixmap, height);
+
+ _DPSCRGBBlend(csb->csb.context, 0.0, 0.0, w, h, "0 0", steps);
+
+ csb->csb.green_pixmap = XCreatePixmap(XtDisplay(csb), XtWindow(csb),
+ width, height, depth);
+
+ XDPSSetContextDrawable(csb->csb.context,
+ csb->csb.green_pixmap, height);
+
+ _DPSCRGBBlend(csb->csb.context, 0.0, 0.0, w, h, "0 exch 0", steps);
+
+ csb->csb.blue_pixmap = XCreatePixmap(XtDisplay(csb), XtWindow(csb),
+ width, height, depth);
+
+ XDPSSetContextDrawable(csb->csb.context, csb->csb.blue_pixmap, height);
+
+ _DPSCRGBBlend(csb->csb.context,
+ 0.0, 0.0, w, h, "0 0 3 -1 roll", steps);
+
+ DPSWaitContext(csb->csb.context);
+ }
+
+ XtVaSetValues(csb->csb.slider_child[0],
+ XtNbackgroundPixmap, csb->csb.red_pixmap, NULL);
+ XtVaSetValues(csb->csb.slider_child[1],
+ XtNbackgroundPixmap, csb->csb.green_pixmap, NULL);
+ XtVaSetValues(csb->csb.slider_child[2],
+ XtNbackgroundPixmap, csb->csb.blue_pixmap, NULL);
+}
+
+static void ColorizeCMYK(ColorSelectionBoxWidget csb)
+{
+ Dimension height, width;
+ int depth, steps;
+ float w, h;
+
+ XtVaGetValues(csb->csb.slider_child[0], XtNwidth, &width,
+ XtNheight, &height,
+ XtNdepth, &depth, NULL);
+
+ if (csb->csb.cyan_pixmap != None && width != csb->csb.cmyk_slider_width) {
+ XFreePixmap(XtDisplay(csb), csb->csb.cyan_pixmap);
+ XFreePixmap(XtDisplay(csb), csb->csb.magenta_pixmap);
+ XFreePixmap(XtDisplay(csb), csb->csb.yellow_pixmap);
+ XFreePixmap(XtDisplay(csb), csb->csb.black_pixmap);
+ csb->csb.cyan_pixmap = None;
+ }
+
+ if (csb->csb.cyan_pixmap == None) {
+ csb->csb.cmyk_slider_width = width;
+ if (csb->csb.visual_class == TrueColor) steps = width / 2;
+ else steps = width / 4;
+
+ ToUserSpace(csb, width, height, &w, &h);
+
+ csb->csb.cyan_pixmap = XCreatePixmap(XtDisplay(csb), XtWindow(csb),
+ width, height, depth);
+
+ XDPSSetContextGState(csb->csb.context, csb->csb.base_gstate);
+ XDPSSetContextDrawable(csb->csb.context, csb->csb.cyan_pixmap, height);
+
+ _DPSCCMYKBlend(csb->csb.context, 0.0, 0.0, w, h, "0 0 0", steps);
+
+ csb->csb.magenta_pixmap = XCreatePixmap(XtDisplay(csb), XtWindow(csb),
+ width, height, depth);
+
+ XDPSSetContextDrawable(csb->csb.context, csb->csb.magenta_pixmap,
+ height);
+
+ _DPSCCMYKBlend(csb->csb.context, 0.0, 0.0, w, h, "0 exch 0 0", steps);
+
+ csb->csb.yellow_pixmap = XCreatePixmap(XtDisplay(csb), XtWindow(csb),
+ width, height, depth);
+
+ XDPSSetContextDrawable(csb->csb.context, csb->csb.yellow_pixmap,
+ height);
+
+ _DPSCCMYKBlend(csb->csb.context, 0.0, 0.0, w, h, "0 0 3 -1 roll 0",
+ steps);
+
+ csb->csb.black_pixmap = XCreatePixmap(XtDisplay(csb), XtWindow(csb),
+ width, height, depth);
+
+ XDPSSetContextDrawable(csb->csb.context, csb->csb.black_pixmap,
+ height);
+
+ _DPSCCMYKBlend(csb->csb.context, 0.0, 0.0, w, h, "0 0 0 4 -1 roll",
+ steps);
+
+ DPSWaitContext(csb->csb.context);
+ }
+
+ XtVaSetValues(csb->csb.slider_child[0], XtNbackgroundPixmap,
+ csb->csb.cyan_pixmap, NULL);
+ XtVaSetValues(csb->csb.slider_child[1], XtNbackgroundPixmap,
+ csb->csb.magenta_pixmap, NULL);
+ XtVaSetValues(csb->csb.slider_child[2], XtNbackgroundPixmap,
+ csb->csb.yellow_pixmap, NULL);
+ XtVaSetValues(csb->csb.slider_child[3], XtNbackgroundPixmap,
+ csb->csb.black_pixmap, NULL);
+}
+
+static void ColorizeHSB(ColorSelectionBoxWidget csb)
+{
+ Dimension height, width;
+ int depth, steps;
+ float w, h;
+
+ XtVaGetValues(csb->csb.slider_child[0], XtNwidth, &width,
+ XtNheight, &height,
+ XtNdepth, &depth, NULL);
+
+ if (csb->csb.hue_pixmap != None && width != csb->csb.hsb_slider_width) {
+ XFreePixmap(XtDisplay(csb), csb->csb.hue_pixmap);
+ XFreePixmap(XtDisplay(csb), csb->csb.sat_pixmap);
+ XFreePixmap(XtDisplay(csb), csb->csb.bright_pixmap);
+ csb->csb.hue_pixmap = None;
+ }
+
+ if (csb->csb.hue_pixmap == None) {
+ csb->csb.hsb_slider_width = width;
+ if (csb->csb.visual_class == TrueColor) steps = width / 2;
+ else steps = width / 4;
+
+ ToUserSpace(csb, width, height, &w, &h);
+
+ csb->csb.hue_pixmap = XCreatePixmap(XtDisplay(csb), XtWindow(csb),
+ width, height, depth);
+
+ XDPSSetContextGState(csb->csb.context, csb->csb.base_gstate);
+ XDPSSetContextDrawable(csb->csb.context, csb->csb.hue_pixmap, height);
+
+ _DPSCHSBBlend(csb->csb.context, 0.0, 0.0, w, h, "1 1", steps);
+
+ csb->csb.sat_pixmap = XCreatePixmap(XtDisplay(csb), XtWindow(csb),
+ width, height, depth);
+
+ XDPSSetContextDrawable(csb->csb.context, csb->csb.sat_pixmap, height);
+
+ _DPSCHSBBlend(csb->csb.context, 0.0, 0.0, w, h, "0 exch 1", steps);
+
+ csb->csb.bright_pixmap = XCreatePixmap(XtDisplay(csb), XtWindow(csb),
+ width, height, depth);
+
+ XDPSSetContextDrawable(csb->csb.context, csb->csb.bright_pixmap,
+ height);
+
+ _DPSCHSBBlend(csb->csb.context, 0.0, 0.0, w, h, "0 1 3 -1 roll",
+ steps);
+
+ DPSWaitContext(csb->csb.context);
+ }
+
+ XtVaSetValues(csb->csb.slider_child[0], XtNbackgroundPixmap,
+ csb->csb.hue_pixmap, NULL);
+ XtVaSetValues(csb->csb.slider_child[1], XtNbackgroundPixmap,
+ csb->csb.sat_pixmap, NULL);
+ XtVaSetValues(csb->csb.slider_child[2], XtNbackgroundPixmap,
+ csb->csb.bright_pixmap, NULL);
+}
+
+static void ColorizeGray(ColorSelectionBoxWidget csb)
+{
+ Dimension height, width;
+ int depth, steps;
+ float w, h;
+
+ XtVaGetValues(csb->csb.slider_child[0], XtNwidth, &width,
+ XtNheight, &height,
+ XtNdepth, &depth, NULL);
+
+ if (csb->csb.gray_pixmap != None && width != csb->csb.gray_slider_width) {
+ XFreePixmap(XtDisplay(csb), csb->csb.gray_pixmap);
+ csb->csb.gray_pixmap = None;
+ }
+
+ if (csb->csb.gray_pixmap == None) {
+ csb->csb.gray_slider_width = width;
+ if (csb->csb.visual_class == TrueColor) steps = width / 2;
+ else steps = width / 4;
+
+ ToUserSpace(csb, width, height, &w, &h);
+
+ csb->csb.gray_pixmap = XCreatePixmap(XtDisplay(csb), XtWindow(csb),
+ width, height, depth);
+
+ XDPSSetContextGState(csb->csb.context, csb->csb.base_gstate);
+ XDPSSetContextDrawable(csb->csb.context, csb->csb.gray_pixmap, height);
+
+ _DPSCGrayBlend(csb->csb.context, 0.0, 0.0, w, h, " ", steps);
+
+ DPSWaitContext(csb->csb.context);
+ }
+
+ XtVaSetValues(csb->csb.slider_child[0], XtNbackgroundPixmap,
+ csb->csb.gray_pixmap, NULL);
+}
+
+static void ColorizeSliders(ColorSelectionBoxWidget csb)
+{
+ if (!XtIsRealized(csb)) return;
+
+ switch (csb->csb.current_space) {
+ case CSBSpaceRGB:
+ ColorizeRGB(csb);
+ break;
+ case CSBSpaceCMYK:
+ ColorizeCMYK(csb);
+ break;
+ case CSBSpaceHSB:
+ ColorizeHSB(csb);
+ break;
+ case CSBSpaceGray:
+ ColorizeGray(csb);
+ break;
+ }
+}
+
+/* ARGSUSED */
+
+static void FormResize(
+ Widget w,
+ XtPointer data,
+ XEvent *event,
+ Boolean *goOn)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) data;
+
+ if (event->type != ConfigureNotify && event->type != MapNotify) return;
+
+ csb->csb.rgb_slider_width = csb->csb.cmyk_slider_width =
+ csb->csb.hsb_slider_width = csb->csb.gray_slider_width = 0;
+ csb->csb.palette_pixmap_valid = False;
+ if (csb->csb.patch_gstate != 0) {
+ XDPSFreeContextGState(csb->csb.context, csb->csb.patch_gstate);
+ csb->csb.patch_gstate = 0;
+ }
+ if (csb->csb.dock_gstate != 0) {
+ XDPSFreeContextGState(csb->csb.context, csb->csb.dock_gstate);
+ csb->csb.dock_gstate = 0;
+ }
+ ColorizeSliders(csb);
+ DrawPalette(csb);
+ if (XtIsRealized(csb->csb.patch_child)) {
+ XClearArea(XtDisplay(csb), XtWindow(csb->csb.patch_child),
+ 0, 0, 1000, 1000, True);
+ }
+}
+
+static void FillCallbackRec(
+ ColorSelectionBoxWidget csb,
+ CSBCallbackRec *rec)
+{
+ rec->current_space = csb->csb.current_space;
+ rec->red = csb->csb.current_color.red;
+ rec->green = csb->csb.current_color.green;
+ rec->blue = csb->csb.current_color.blue;
+ rec->cyan = csb->csb.current_color.cyan;
+ rec->magenta = csb->csb.current_color.magenta;
+ rec->yellow = csb->csb.current_color.yellow;
+ rec->black = csb->csb.current_color.black;
+ rec->hue = csb->csb.current_color.hue;
+ rec->saturation = csb->csb.current_color.saturation;
+ rec->brightness = csb->csb.current_color.brightness;
+ rec->gray = csb->csb.current_color.gray;
+}
+
+/* ARGSUSED */
+
+static void OKCallback(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) clientData;
+ CSBCallbackRec rec;
+
+ csb->csb.save_color = csb->csb.current_color;
+ FillCallbackRec(csb, &rec);
+ rec.reason = CSBOK;
+ XtCallCallbackList((Widget) csb, csb->csb.ok_callback, (XtPointer) &rec);
+ if (XtIsShell(XtParent(csb))) XtPopdown(XtParent(csb));
+
+ SaveDockContents(csb);
+}
+
+/* ARGSUSED */
+
+static void ApplyCallback(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) clientData;
+ CSBCallbackRec rec;
+
+ csb->csb.save_color = csb->csb.current_color;
+ FillCallbackRec(csb, &rec);
+ rec.reason = CSBApply;
+ XtCallCallbackList((Widget) csb, csb->csb.apply_callback,
+ (XtPointer) &rec);
+
+ SaveDockContents(csb);
+}
+
+/* ARGSUSED */
+
+static void ResetCallback(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) clientData;
+ CSBCallbackRec rec;
+
+ csb->csb.current_color = csb->csb.save_color;
+ FillPatch(csb);
+ SetSliders(csb);
+ FillCallbackRec(csb, &rec);
+ rec.reason = CSBReset;
+ XtCallCallbackList((Widget) csb, csb->csb.reset_callback,
+ (XtPointer) &rec);
+}
+
+/* ARGSUSED */
+
+static void CancelCallback(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) clientData;
+ CSBCallbackRec rec;
+
+ csb->csb.current_color = csb->csb.save_color;
+ FillPatch(csb);
+ SetSliders(csb);
+ FillCallbackRec(csb, &rec);
+ rec.reason = CSBCancel;
+ XtCallCallbackList((Widget) csb, csb->csb.cancel_callback,
+ (XtPointer) &rec);
+ if (XtIsShell(XtParent(csb))) XtPopdown(XtParent(csb));
+}
+
+/* ARGSUSED */
+
+static void DoValueChangedCallback(ColorSelectionBoxWidget csb)
+{
+ CSBCallbackRec rec;
+
+ FillCallbackRec(csb, &rec);
+ rec.reason = CSBValueChanged;
+ XtCallCallbackList((Widget) csb, csb->csb.value_changed_callback,
+ (XtPointer) &rec);
+}
+
+/* ARGSUSED */
+
+static void ChangeLabelCallback(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ XmScaleCallbackStruct *scaleData = (XmScaleCallbackStruct *) callData;
+
+ ChangeLabel((Widget) clientData, ((float) scaleData->value) / 100.0);
+}
+
+static void ChangeLabel(Widget label, double n)
+{
+ char buf[10];
+
+ sprintf(buf, "%d", TO_PCT(n));
+ XtVaSetValues(label, XmNlabelString, CS(buf, label), NULL);
+}
+
+static void CreateModelMenu(Widget parent, Widget csb)
+{
+ Widget kids[4];
+
+ kids[0] = XmCreatePushButtonGadget(parent, "rgb", (ArgList) NULL, 0);
+ XtAddCallback(kids[0], XmNactivateCallback,
+ SetRGBCallback, (XtPointer) csb);
+ kids[1] = XmCreatePushButtonGadget(parent, "cmyk", (ArgList) NULL, 0);
+ XtAddCallback(kids[1], XmNactivateCallback,
+ SetCMYKCallback, (XtPointer) csb);
+ kids[2] = XmCreatePushButtonGadget(parent, "hsb", (ArgList) NULL, 0);
+ XtAddCallback(kids[2], XmNactivateCallback,
+ SetHSBCallback, (XtPointer) csb);
+ kids[3] = XmCreatePushButtonGadget(parent, "gray", (ArgList) NULL, 0);
+ XtAddCallback(kids[3], XmNactivateCallback,
+ SetGrayCallback, (XtPointer) csb);
+
+ XtManageChildren(kids, 4);
+}
+
+typedef struct {
+ ColorSelectionBoxWidget csb;
+ CSBRenderingType rendering;
+} RenderingRec;
+
+/* ARGSUSED */
+
+static void SetRenderingCallback(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ RenderingRec *r = (RenderingRec *) clientData;
+
+ r->csb->csb.current_rendering = r->rendering;
+ FillPatch(r->csb);
+}
+
+static void CreateDisplayMenu(Widget parent, ColorSelectionBoxWidget csb)
+{
+ Widget kids[3];
+ RenderingRec *r;
+
+ r = XtNew(RenderingRec);
+ r->csb = csb;
+ r->rendering = CSBDisplayDPS;
+ kids[0] = XmCreatePushButtonGadget(parent, "displayDPS",
+ (ArgList) NULL, 0);
+ XtAddCallback(kids[0], XmNactivateCallback,
+ SetRenderingCallback, (XtPointer) r);
+ r = XtNew(RenderingRec);
+ r->csb = csb;
+ r->rendering = CSBDisplayX;
+ kids[1] = XmCreatePushButtonGadget(parent, "displayX", (ArgList) NULL, 0);
+ XtAddCallback(kids[1], XmNactivateCallback,
+ SetRenderingCallback, (XtPointer) r);
+ r = XtNew(RenderingRec);
+ r->csb = csb;
+ r->rendering = CSBDisplayBoth;
+ kids[2] = XmCreatePushButtonGadget(parent, "displayBoth",
+ (ArgList) NULL, 0);
+ XtAddCallback(kids[2], XmNactivateCallback,
+ SetRenderingCallback, (XtPointer) r);
+
+ XtManageChildren(kids, 3);
+}
+
+typedef struct {
+ ColorSelectionBoxWidget csb;
+ int n;
+} PaletteRec;
+
+/* ARGSUSED */
+
+static void SetPaletteCallback(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ PaletteRec *p = (PaletteRec *) clientData;
+
+ if (p->csb->csb.palette_broken[p->n]) return;
+
+ if (p->n != p->csb->csb.current_palette ||
+ p->csb->csb.palette_color_dependent[p->n]) {
+ p->csb->csb.palette_pixmap_valid = False;
+ }
+
+ p->csb->csb.current_palette = p->n;
+ DrawPalette(p->csb);
+}
+
+static void CreatePaletteMenu(Widget parent, ColorSelectionBoxWidget csb)
+{
+ Widget w, managed[PALETTE_MAX];
+ int j, k;
+ char buf[10];
+ PaletteRec *p;
+
+ j = 0;
+
+ for (k = 0; k < PALETTE_MAX; k++) {
+ p = XtNew(PaletteRec);
+ p->csb = csb;
+ p->n = k;
+ sprintf(buf, "palette%d", k);
+ w = XtVaCreateWidget(buf, xmPushButtonGadgetClass, parent, NULL);
+ if (csb->csb.palette_label[k] != NULL) {
+ XtVaSetValues(w, XtVaTypedArg, XmNlabelString,
+ XtRString, csb->csb.palette_label[k],
+ strlen(csb->csb.palette_label[k])+1,
+ NULL);
+ }
+ XtAddCallback(w, XmNactivateCallback,
+ SetPaletteCallback, (XtPointer) p);
+ if (csb->csb.palette_function[k] != NULL) managed[j++] = w;
+ }
+
+ if (j != 0) XtManageChildren(managed, j);
+}
+
+static void CreateChildren(ColorSelectionBoxWidget csb)
+{
+ int i;
+ Arg args[20];
+ Widget form, menu, button, w, dock_frame, palette_frame;
+ Pixel fg, bg;
+ int depth;
+ Pixmap eyedrop;
+
+ i = 0;
+ XtSetArg(args[i], XmNresizePolicy, XmRESIZE_NONE); i++;
+ form = XtCreateManagedWidget("panel", xmFormWidgetClass,
+ (Widget) csb, args, i);
+ csb->csb.form_child = form;
+ XtAddEventHandler(form, StructureNotifyMask, False, FormResize,
+ (XtPointer) csb);
+
+ i = 0;
+ menu = XmCreatePulldownMenu(form, "modelMenu", args, i);
+ CreateModelMenu(menu, (Widget) csb);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNsubMenuId, menu); i++;
+ csb->csb.model_option_menu_child =
+ XmCreateOptionMenu(form, "modelOptionMenu",
+ args, i);
+ XtManageChild(csb->csb.model_option_menu_child);
+
+ XtVaGetValues(form, XtNbackground, &bg, XmNforeground, &fg,
+ XtNdepth, &depth, NULL);
+ eyedrop = XCreatePixmapFromBitmapData(XtDisplay(csb),
+ RootWindowOfScreen(XtScreen(csb)),
+ (char *) heyedrop_bits,
+ heyedrop_width, heyedrop_height,
+ fg, bg, depth);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, csb->csb.model_option_menu_child); i++;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, csb->csb.model_option_menu_child); i++;
+ XtSetArg(args[i], XmNlabelPixmap, eyedrop); i++;
+ button = XtCreateManagedWidget("eyedropButton", xmPushButtonWidgetClass,
+ form, args, i);
+ XtAddCallback(button, XmNactivateCallback,
+ DoEyedropCallback, (XtPointer) csb);
+ XtInsertRawEventHandler(button, PointerMotionMask | ButtonReleaseMask,
+ False, EyedropPointer, (XtPointer) csb,
+ XtListHead);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, csb->csb.model_option_menu_child); i++;
+ csb->csb.label_child[0] =
+ XtCreateManagedWidget("label1", xmLabelWidgetClass, form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, csb->csb.model_option_menu_child); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_POSITION); i++;
+ csb->csb.value_child[0] =
+ XtCreateManagedWidget("value1", xmLabelWidgetClass, form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, csb->csb.label_child[0]); i++;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, csb->csb.model_option_menu_child); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNrightWidget, csb->csb.value_child[0]); i++;
+ csb->csb.slider_child[0] =
+ XtCreateManagedWidget("slider1", xmScaleWidgetClass,
+ form, args, i);
+ XtAddCallback(csb->csb.slider_child[0], XmNvalueChangedCallback,
+ ChangeLabelCallback, (XtPointer) csb->csb.value_child[0]);
+ XtAddCallback(csb->csb.slider_child[0], XmNdragCallback,
+ ChangeLabelCallback, (XtPointer) csb->csb.value_child[0]);
+ XtAddCallback(csb->csb.slider_child[0], XmNvalueChangedCallback,
+ Slider1Callback, (XtPointer) csb);
+ XtAddCallback(csb->csb.slider_child[0], XmNdragCallback,
+ Slider1Callback, (XtPointer) csb);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, csb->csb.slider_child[0]); i++;
+ csb->csb.label_child[1] =
+ XtCreateManagedWidget("label2", xmLabelWidgetClass, form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, csb->csb.slider_child[0]); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNrightWidget, csb->csb.value_child[0]); i++;
+ csb->csb.value_child[1] =
+ XtCreateManagedWidget("value2", xmLabelWidgetClass, form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, csb->csb.slider_child[0]); i++;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, csb->csb.slider_child[0]); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNrightWidget, csb->csb.slider_child[0]); i++;
+ csb->csb.slider_child[1] =
+ XtCreateManagedWidget("slider2", xmScaleWidgetClass,
+ form, args, i);
+ XtAddCallback(csb->csb.slider_child[1], XmNvalueChangedCallback,
+ ChangeLabelCallback, (XtPointer) csb->csb.value_child[1]);
+ XtAddCallback(csb->csb.slider_child[1], XmNdragCallback,
+ ChangeLabelCallback, (XtPointer) csb->csb.value_child[1]);
+ XtAddCallback(csb->csb.slider_child[1], XmNvalueChangedCallback,
+ Slider2Callback, (XtPointer) csb);
+ XtAddCallback(csb->csb.slider_child[1], XmNdragCallback,
+ Slider2Callback, (XtPointer) csb);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, csb->csb.slider_child[1]); i++;
+ csb->csb.label_child[2] =
+ XtCreateManagedWidget("label3", xmLabelWidgetClass, form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, csb->csb.slider_child[1]); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNrightWidget, csb->csb.value_child[0]); i++;
+ csb->csb.value_child[2] =
+ XtCreateManagedWidget("value3", xmLabelWidgetClass, form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, csb->csb.slider_child[0]); i++;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, csb->csb.slider_child[1]); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNrightWidget, csb->csb.slider_child[0]); i++;
+ csb->csb.slider_child[2] =
+ XtCreateManagedWidget("slider3", xmScaleWidgetClass,
+ form, args, i);
+ XtAddCallback(csb->csb.slider_child[2], XmNvalueChangedCallback,
+ ChangeLabelCallback, (XtPointer) csb->csb.value_child[2]);
+ XtAddCallback(csb->csb.slider_child[2], XmNdragCallback,
+ ChangeLabelCallback, (XtPointer) csb->csb.value_child[2]);
+ XtAddCallback(csb->csb.slider_child[2], XmNvalueChangedCallback,
+ Slider3Callback, (XtPointer) csb);
+ XtAddCallback(csb->csb.slider_child[2], XmNdragCallback,
+ Slider3Callback, (XtPointer) csb);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, csb->csb.slider_child[2]); i++;
+ csb->csb.label_child[3] =
+ XtCreateManagedWidget("label4", xmLabelWidgetClass, form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, csb->csb.slider_child[2]); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNrightWidget, csb->csb.value_child[0]); i++;
+ csb->csb.value_child[3] =
+ XtCreateManagedWidget("value4", xmLabelWidgetClass, form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, csb->csb.slider_child[0]); i++;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, csb->csb.slider_child[2]); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNrightWidget, csb->csb.slider_child[0]); i++;
+ csb->csb.slider_child[3] =
+ XtCreateManagedWidget("slider4", xmScaleWidgetClass,
+ form, args, i);
+ XtAddCallback(csb->csb.slider_child[3], XmNvalueChangedCallback,
+ ChangeLabelCallback, (XtPointer) csb->csb.value_child[3]);
+ XtAddCallback(csb->csb.slider_child[3], XmNdragCallback,
+ ChangeLabelCallback, (XtPointer) csb->csb.value_child[3]);
+ XtAddCallback(csb->csb.slider_child[3], XmNvalueChangedCallback,
+ Slider4Callback, (XtPointer) csb);
+ XtAddCallback(csb->csb.slider_child[3], XmNdragCallback,
+ Slider4Callback, (XtPointer) csb);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
+ button = XtCreateManagedWidget("okButton", xmPushButtonWidgetClass,
+ form, args, i);
+ XtAddCallback(button, XmNactivateCallback, OKCallback, (XtPointer) csb);
+
+ i = 0;
+ XtSetArg(args[i], XmNdefaultButton, button); i++;
+ XtSetValues(form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, button); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
+ button = XtCreateManagedWidget("applyButton", xmPushButtonWidgetClass,
+ form, args, i);
+
+ XtAddCallback(button, XmNactivateCallback, ApplyCallback, (XtPointer) csb);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, button); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
+ button = XtCreateManagedWidget("resetButton", xmPushButtonWidgetClass,
+ form, args, i);
+ XtAddCallback(button, XmNactivateCallback, ResetCallback, (XtPointer) csb);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, button); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
+ button = XtCreateManagedWidget("cancelButton", xmPushButtonWidgetClass,
+ form, args, i);
+ XtAddCallback(button, XmNactivateCallback,
+ CancelCallback, (XtPointer) csb);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, button); i++;
+ w = XtCreateManagedWidget("separator", xmSeparatorGadgetClass,
+ form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, w); i++;
+ palette_frame = XtCreateManagedWidget("paletteFrame", xmFrameWidgetClass,
+ form, args, i);
+
+ i = 0;
+ csb->csb.palette_child =
+ XtCreateManagedWidget("palette", xmDrawingAreaWidgetClass,
+ palette_frame, args, i);
+ XtAddCallback(csb->csb.palette_child, XmNexposeCallback,
+ DrawPaletteCallback, (XtPointer) csb);
+ XtAddEventHandler(csb->csb.palette_child, ButtonPressMask, False,
+ PalettePress, (XtPointer) csb);
+
+ i = 0;
+ menu = XmCreatePulldownMenu(form, "paletteMenu", args, i);
+ CreatePaletteMenu(menu, csb);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, palette_frame); i++;
+ XtSetArg(args[i], XmNsubMenuId, menu); i++;
+ csb->csb.palette_option_menu_child =
+ XmCreateOptionMenu(form, "paletteOptionMenu",
+ args, i);
+ XtManageChild(csb->csb.palette_option_menu_child);
+
+ i = 0;
+ menu = XmCreatePulldownMenu(form, "displayMenu", args, i);
+ CreateDisplayMenu(menu, csb);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_POSITION); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNsubMenuId, menu); i++;
+ csb->csb.display_option_menu_child =
+ XmCreateOptionMenu(form, "displayOptionMenu",
+ args, i);
+ XtManageChild(csb->csb.display_option_menu_child);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, csb->csb.display_option_menu_child);i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, palette_frame); i++;
+ dock_frame = XtCreateManagedWidget("dockFrame", xmFrameWidgetClass,
+ form, args, i);
+
+ i = 0;
+ csb->csb.dock_child =
+ XtCreateManagedWidget("dock", xmDrawingAreaWidgetClass,
+ dock_frame, args, i);
+ XtAddCallback(csb->csb.dock_child, XmNexposeCallback,
+ DrawDockCallback, (XtPointer) csb);
+ XtAddEventHandler(csb->csb.dock_child, ButtonPressMask, False, DockPress,
+ (XtPointer) csb);
+
+ {
+ Dimension height;
+ int q;
+
+ XtVaGetValues(csb->csb.dock_child, XtNheight, &height, NULL);
+ if (height < csb->csb.cell_size) height = csb->csb.cell_size;
+ else if (height % csb->csb.cell_size != 0) {
+ q = height / csb->csb.cell_size;
+ height = csb->csb.cell_size * q;
+ }
+ XtVaSetValues(csb->csb.dock_child, XtNheight, height, NULL);
+ }
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, dock_frame); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, csb->csb.display_option_menu_child);i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, dock_frame); i++;
+ w = XtCreateManagedWidget("patchFrame", xmFrameWidgetClass,
+ form, args, i);
+
+ i = 0;
+ csb->csb.patch_child =
+ XtCreateManagedWidget("patch", xmDrawingAreaWidgetClass,
+ w, args, i);
+ XtAddCallback(csb->csb.patch_child, XmNexposeCallback,
+ FillPatchCallback, (XtPointer) csb);
+ XtAddRawEventHandler(csb->csb.patch_child, ButtonPressMask,
+ False, PatchPress, (XtPointer) csb);
+ XtAddRawEventHandler(csb->csb.patch_child, ButtonReleaseMask,
+ False, PatchRelease, (XtPointer) csb);
+}
+
+static void NoBackgroundPixel(ColorSelectionBoxWidget csb)
+{
+ Widget w, message;
+
+ csb->csb.no_background = True;
+ w = XtNameToWidget((Widget) csb, "*displayX");
+ XtSetSensitive(w, False);
+ w = XtNameToWidget((Widget) csb, "*displayBoth");
+ XtSetSensitive(w, False);
+ w = XtNameToWidget((Widget) csb, "*displayDPS");
+ XtVaSetValues(csb->csb.display_option_menu_child, XmNmenuHistory, w, NULL);
+
+ message = XmCreateInformationDialog(csb->csb.form_child,
+ "noBackgroundMessage",
+ (ArgList) NULL, 0);
+ w = XmMessageBoxGetChild(message, XmDIALOG_CANCEL_BUTTON);
+ XtUnmanageChild(w);
+ w = XmMessageBoxGetChild(message, XmDIALOG_HELP_BUTTON);
+ XtUnmanageChild(w);
+
+ XtManageChild(message);
+}
+
+/* labelString is changed by this */
+
+static void ParseLabels(String labelString, String labels[4], int n)
+{
+ register char *ch;
+ int i;
+
+ ch = labelString;
+ for (i = 0; i < n; i++) {
+ labels[i] = ch;
+ while (*ch != ':' && *ch != '\0') ch++;
+ *ch++ = '\0';
+ }
+
+ for (i = n; i < 4; i++) labels[i] = NULL;
+}
+
+static void SetLabels(ColorSelectionBoxWidget csb, String *labels)
+{
+ Widget w = (Widget) csb;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (labels[i] != NULL) {
+ XtVaSetValues(csb->csb.label_child[i],
+ XmNlabelString, CS(labels[i], w), NULL);
+ }
+ }
+}
+
+static void MapChildren(Widget *children, int n)
+{
+ XtManageChildren(children, n);
+}
+
+static void UnmapChildren(Widget *children, int n)
+{
+ XtUnmanageChildren(children, n);
+}
+
+static void SetSliders(ColorSelectionBoxWidget csb)
+{
+ switch(csb->csb.current_space) {
+ case CSBSpaceRGB: SetRGBValues(csb); break;
+ case CSBSpaceCMYK: SetCMYKValues(csb); break;
+ case CSBSpaceHSB: SetHSBValues(csb); break;
+ case CSBSpaceGray: SetGrayValues(csb); break;
+ }
+}
+
+static void SetRGBValues(ColorSelectionBoxWidget csb)
+{
+ XmScaleSetValue(csb->csb.slider_child[0],
+ TO_PCT(csb->csb.current_color.red));
+ XmScaleSetValue(csb->csb.slider_child[1],
+ TO_PCT(csb->csb.current_color.green));
+ XmScaleSetValue(csb->csb.slider_child[2],
+ TO_PCT(csb->csb.current_color.blue));
+ ChangeLabel(csb->csb.value_child[0], csb->csb.current_color.red);
+ ChangeLabel(csb->csb.value_child[1], csb->csb.current_color.green);
+ ChangeLabel(csb->csb.value_child[2], csb->csb.current_color.blue);
+}
+
+/* ARGSUSED */
+
+static void SetRGBCallback(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) clientData;
+ Widget rgb;
+ Widget children[6];
+ String labels[4];
+ int i, j;
+
+ csb->csb.current_space = CSBSpaceRGB;
+
+ ParseLabels(csb->csb.rgb_labels, labels, 3);
+
+ rgb = XtNameToWidget((Widget) csb, "*rgb");
+
+ XtVaSetValues(csb->csb.model_option_menu_child, XmNmenuHistory, rgb, NULL);
+
+ SetLabels(csb, labels);
+
+ SetRGBValues(csb);
+
+ j = 0;
+ for (i = 1; i < 3; i++) {
+ children[j++] = csb->csb.label_child[i];
+ children[j++] = csb->csb.slider_child[i];
+ children[j++] = csb->csb.value_child[i];
+ }
+
+ MapChildren(children, 6);
+
+ children[0] = csb->csb.label_child[3];
+ children[1] = csb->csb.slider_child[3];
+ children[2] = csb->csb.value_child[3];
+
+ UnmapChildren(children, 3);
+
+ ColorizeSliders(csb);
+ FillPatch(csb);
+}
+
+static void SetCMYKValues(ColorSelectionBoxWidget csb)
+{
+ XmScaleSetValue(csb->csb.slider_child[0],
+ TO_PCT(csb->csb.current_color.cyan));
+ XmScaleSetValue(csb->csb.slider_child[1],
+ TO_PCT(csb->csb.current_color.magenta));
+ XmScaleSetValue(csb->csb.slider_child[2],
+ TO_PCT(csb->csb.current_color.yellow));
+ XmScaleSetValue(csb->csb.slider_child[3],
+ TO_PCT(csb->csb.current_color.black));
+ ChangeLabel(csb->csb.value_child[0], csb->csb.current_color.cyan);
+ ChangeLabel(csb->csb.value_child[1], csb->csb.current_color.magenta);
+ ChangeLabel(csb->csb.value_child[2], csb->csb.current_color.yellow);
+ ChangeLabel(csb->csb.value_child[3], csb->csb.current_color.black);
+}
+
+/* ARGSUSED */
+
+static void SetCMYKCallback(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) clientData;
+ Widget cmyk;
+ Widget children[9];
+ String labels[4];
+ int i, j;
+
+ csb->csb.current_space = CSBSpaceCMYK;
+
+ ParseLabels(csb->csb.cmyk_labels, labels, 4);
+
+ cmyk = XtNameToWidget((Widget) csb, "*cmyk");
+
+ XtVaSetValues(csb->csb.model_option_menu_child,
+ XmNmenuHistory, cmyk, NULL);
+
+ SetLabels(csb, labels);
+
+ SetCMYKValues(csb);
+
+ j = 0;
+ for (i = 1; i < 4; i++) {
+ children[j++] = csb->csb.label_child[i];
+ children[j++] = csb->csb.slider_child[i];
+ children[j++] = csb->csb.value_child[i];
+ }
+
+ MapChildren(children, 9);
+
+ ColorizeSliders(csb);
+ FillPatch(csb);
+}
+
+static void SetHSBValues(ColorSelectionBoxWidget csb)
+{
+ XmScaleSetValue(csb->csb.slider_child[0],
+ TO_PCT(csb->csb.current_color.hue));
+ XmScaleSetValue(csb->csb.slider_child[1],
+ TO_PCT(csb->csb.current_color.saturation));
+ XmScaleSetValue(csb->csb.slider_child[2],
+ TO_PCT(csb->csb.current_color.brightness));
+ ChangeLabel(csb->csb.value_child[0], csb->csb.current_color.hue);
+ ChangeLabel(csb->csb.value_child[1], csb->csb.current_color.saturation);
+ ChangeLabel(csb->csb.value_child[2], csb->csb.current_color.brightness);
+}
+
+/* ARGSUSED */
+
+static void SetHSBCallback(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) clientData;
+ Widget hsb;
+ Widget children[6];
+ String labels[4];
+ int i, j;
+
+ csb->csb.current_space = CSBSpaceHSB;
+
+ ParseLabels(csb->csb.hsb_labels, labels, 3);
+
+ hsb = XtNameToWidget((Widget) csb, "*hsb");
+
+ XtVaSetValues(csb->csb.model_option_menu_child, XmNmenuHistory, hsb, NULL);
+
+ SetLabels(csb, labels);
+
+ SetHSBValues(csb);
+
+ j = 0;
+ for (i = 1; i < 3; i++) {
+ children[j++] = csb->csb.label_child[i];
+ children[j++] = csb->csb.slider_child[i];
+ children[j++] = csb->csb.value_child[i];
+ }
+
+ MapChildren(children, 6);
+
+ children[0] = csb->csb.label_child[3];
+ children[1] = csb->csb.slider_child[3];
+ children[2] = csb->csb.value_child[3];
+
+ UnmapChildren(children, 3);
+
+ ColorizeSliders(csb);
+ FillPatch(csb);
+}
+
+static void SetGrayValues(ColorSelectionBoxWidget csb)
+{
+ XmScaleSetValue(csb->csb.slider_child[0],
+ TO_PCT(csb->csb.current_color.gray));
+ ChangeLabel(csb->csb.value_child[0], csb->csb.current_color.gray);
+}
+
+/* ARGSUSED */
+
+static void SetGrayCallback(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) clientData;
+ Widget gray;
+ Widget children[9];
+ String labels[4];
+ int i, j;
+
+ csb->csb.current_space = CSBSpaceGray;
+
+ gray = XtNameToWidget((Widget) csb, "*gray");
+
+ XtVaSetValues(csb->csb.model_option_menu_child, XmNmenuHistory, gray, NULL);
+
+ labels[0] = csb->csb.gray_labels;
+ labels[1] = labels[2] = labels[3] = NULL;
+ SetLabels(csb, labels);
+
+ SetGrayValues(csb);
+
+ j = 0;
+ for (i = 1; i < 4; i++) {
+ children[j++] = csb->csb.label_child[i];
+ children[j++] = csb->csb.slider_child[i];
+ children[j++] = csb->csb.value_child[i];
+ }
+
+ UnmapChildren(children, 9);
+
+ ColorizeSliders(csb);
+ FillPatch(csb);
+}
+
+static void RGBToCMYK(ColorSelectionBoxWidget csb)
+{
+ csb->csb.current_color.cyan = 1.0 - csb->csb.current_color.red;
+ csb->csb.current_color.magenta = 1.0 - csb->csb.current_color.green;
+ csb->csb.current_color.yellow = 1.0 - csb->csb.current_color.blue;
+ csb->csb.current_color.black = 0.0;
+}
+
+static void RGBToGray(ColorSelectionBoxWidget csb)
+{
+ csb->csb.current_color.gray = .3 * csb->csb.current_color.red +
+ .59 * csb->csb.current_color.green +
+ .11 * csb->csb.current_color.blue;
+}
+
+static void HSBToRGB(ColorSelectionBoxWidget csb)
+{
+ double r, g, bl;
+ double h, s, b;
+ double f, m, n, k;
+ int i;
+
+ if (csb->csb.current_color.saturation == 0) {
+ r = g = bl = csb->csb.current_color.brightness;
+ } else {
+ h = csb->csb.current_color.hue;
+ s = csb->csb.current_color.saturation;
+ b = csb->csb.current_color.brightness;
+
+ h = 6.0 * h;
+ if (h >= 6.0) h = 0.0;
+ i = (int) h;
+ f = h - (double)i;
+ m = b * (1.0 - s);
+ n = b * (1.0 - (s * f));
+ k = b * (1.0 - (s * (1.0 - f)));
+
+ switch(i) {
+ default:
+ case 0: r = b; g = k; bl = m; break;
+ case 1: r = n; g = b; bl = m; break;
+ case 2: r = m; g = b; bl = k; break;
+ case 3: r = m; g = n; bl = b; break;
+ case 4: r = k; g = m; bl = b; break;
+ case 5: r = b; g = m; bl = n; break;
+ }
+ }
+
+ csb->csb.current_color.red = r;
+ csb->csb.current_color.green = g;
+ csb->csb.current_color.blue = bl;
+}
+
+static void RGBToHSB(ColorSelectionBoxWidget csb)
+{
+ double hue, sat, value;
+ double diff, x, r, g, b;
+ double red, green, blue;
+
+ red = csb->csb.current_color.red;
+ green = csb->csb.current_color.green;
+ blue = csb->csb.current_color.blue;
+
+ hue = sat = 0.0;
+ value = x = red;
+ if (green > value) value = green; else x = green;
+ if (blue > value) value = blue;
+ if (blue < x) x = blue;
+
+ if (value != 0.0) {
+ diff = value - x;
+ if (diff != 0.0) {
+ sat = diff / value;
+ r = (value - red) / diff;
+ g = (value - green) / diff;
+ b = (value - blue) / diff;
+ if (red == value) hue = (green == x) ? 5.0 + b : 1.0 - g;
+ else if (green == value) hue = (blue == x) ? 1.0 + r : 3.0 - b;
+ else hue = (red == x) ? 3.0 + g : 5.0 - r;
+ hue /= 6.0; if (hue >= 1.0 || hue <= 0.0) hue = 0.0;
+ }
+ }
+ csb->csb.current_color.hue = hue;
+ csb->csb.current_color.saturation = sat;
+ csb->csb.current_color.brightness = value;
+}
+
+static void UpdateColorSpaces(
+ ColorSelectionBoxWidget csb,
+ CSBColorSpace masterSpace)
+{
+ switch (masterSpace) {
+ case CSBSpaceRGB:
+ RGBToCMYK(csb);
+ RGBToHSB(csb);
+ RGBToGray(csb);
+ break;
+
+ case CSBSpaceCMYK:
+ csb->csb.current_color.red =
+ 1.0 - MIN(1.0, csb->csb.current_color.cyan +
+ csb->csb.current_color.black);
+ csb->csb.current_color.green =
+ 1.0 - MIN(1.0, csb->csb.current_color.magenta +
+ csb->csb.current_color.black);
+ csb->csb.current_color.blue =
+ 1.0 - MIN(1.0, csb->csb.current_color.yellow +
+ csb->csb.current_color.black);
+ RGBToHSB(csb);
+ RGBToGray(csb);
+ break;
+
+ case CSBSpaceHSB:
+ HSBToRGB(csb);
+ RGBToCMYK(csb);
+ RGBToGray(csb);
+ break;
+
+ case CSBSpaceGray:
+ csb->csb.current_color.red = csb->csb.current_color.green =
+ csb->csb.current_color.blue = csb->csb.current_color.gray;
+
+ csb->csb.current_color.hue =
+ csb->csb.current_color.saturation = 0.0;
+ csb->csb.current_color.brightness = csb->csb.current_color.gray;
+
+ csb->csb.current_color.cyan = csb->csb.current_color.magenta =
+ csb->csb.current_color.yellow = 0.0;
+ csb->csb.current_color.black = 1.0 - csb->csb.current_color.gray;
+ break;
+ }
+}
+
+/* ARGSUSED */
+
+static void Slider1Callback(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) clientData;
+ XmScaleCallbackStruct *scaleData = (XmScaleCallbackStruct *) callData;
+
+ switch(csb->csb.current_space) {
+ case CSBSpaceRGB:
+ csb->csb.current_color.red = scaleData->value / 100.0;
+ break;
+ case CSBSpaceCMYK:
+ csb->csb.current_color.cyan = scaleData->value / 100.0;
+ break;
+ case CSBSpaceHSB:
+ csb->csb.current_color.hue = scaleData->value / 100.0;
+ break;
+ case CSBSpaceGray:
+ csb->csb.current_color.gray = scaleData->value / 100.0;
+ break;
+ }
+
+ UpdateColorSpaces(csb, csb->csb.current_space);
+ DoValueChangedCallback(csb);
+ FillPatch(csb);
+}
+
+/* ARGSUSED */
+
+static void Slider2Callback(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) clientData;
+ XmScaleCallbackStruct *scaleData = (XmScaleCallbackStruct *) callData;
+
+ switch(csb->csb.current_space) {
+ case CSBSpaceRGB:
+ csb->csb.current_color.green = scaleData->value / 100.0;
+ break;
+ case CSBSpaceCMYK:
+ csb->csb.current_color.magenta = scaleData->value / 100.0;
+ break;
+ case CSBSpaceHSB:
+ csb->csb.current_color.saturation = scaleData->value / 100.0;
+ break;
+ case CSBSpaceGray:
+ break;
+ }
+
+ UpdateColorSpaces(csb, csb->csb.current_space);
+ DoValueChangedCallback(csb);
+ FillPatch(csb);
+}
+
+/* ARGSUSED */
+
+static void Slider3Callback(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) clientData;
+ XmScaleCallbackStruct *scaleData = (XmScaleCallbackStruct *) callData;
+
+ switch(csb->csb.current_space) {
+ case CSBSpaceRGB:
+ csb->csb.current_color.blue = scaleData->value / 100.0;
+ break;
+ case CSBSpaceCMYK:
+ csb->csb.current_color.yellow = scaleData->value / 100.0;
+ break;
+ case CSBSpaceHSB:
+ csb->csb.current_color.brightness = scaleData->value / 100.0;
+ break;
+ case CSBSpaceGray:
+ break;
+ }
+
+ UpdateColorSpaces(csb, csb->csb.current_space);
+ DoValueChangedCallback(csb);
+ FillPatch(csb);
+}
+
+/* ARGSUSED */
+
+static void Slider4Callback(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) clientData;
+ XmScaleCallbackStruct *scaleData = (XmScaleCallbackStruct *) callData;
+
+ csb->csb.current_color.black = scaleData->value / 100.0;
+
+ UpdateColorSpaces(csb, csb->csb.current_space);
+ DoValueChangedCallback(csb);
+ FillPatch(csb);
+}
+
+static void FillPatch(ColorSelectionBoxWidget csb)
+{
+ Colormap c;
+ XColor xc;
+ Widget patch = csb->csb.patch_child;
+
+ if (!XtIsRealized(csb->csb.patch_child)) return;
+
+ if (csb->csb.no_background) {
+ XClearArea(XtDisplay(patch), XtWindow(patch), 0, 0, 1000, 1000, True);
+ return;
+ }
+
+ /* All we have to do is set the background; the expose event will
+ do the rest */
+
+ XtVaGetValues(patch, XtNcolormap, (XtPointer) &c, NULL);
+
+ if (csb->csb.current_space == CSBSpaceGray) {
+ xc.red = xc.green = xc.blue = TO_X(csb->csb.current_color.gray);
+ } else {
+ xc.red = TO_X(csb->csb.current_color.red);
+ xc.green = TO_X(csb->csb.current_color.green);
+ xc.blue = TO_X(csb->csb.current_color.blue);
+ }
+
+ if (csb->csb.static_visual) {
+ (void) XAllocColor(XtDisplay(patch), c, &xc);
+ csb->csb.background = xc.pixel;
+ XtVaSetValues(patch, XtNbackground, csb->csb.background, NULL);
+ } else {
+ xc.pixel = csb->csb.background;
+ xc.flags = DoRed | DoGreen | DoBlue;
+ XStoreColor(XtDisplay(patch), c, &xc);
+ }
+
+ XClearArea(XtDisplay(patch), XtWindow(patch), 0, 0, 1000, 1000, True);
+}
+
+/* ARGSUSED */
+
+static void FillPatchCallback(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) clientData;
+ Dimension height, width;
+ float fh, fw;
+
+ if (csb->csb.current_rendering != CSBDisplayX) {
+ XtVaGetValues(w, XtNheight, &height, XtNwidth, &width, NULL);
+ if (csb->csb.patch_gstate == 0) {
+ XDPSSetContextGState(csb->csb.context, csb->csb.base_gstate);
+ XDPSSetContextDrawable(csb->csb.context, XtWindow(w), height);
+ (void) XDPSCaptureContextGState(csb->csb.context,
+ &csb->csb.patch_gstate);
+ } else XDPSSetContextGState(csb->csb.context, csb->csb.patch_gstate);
+
+ switch (csb->csb.current_space) {
+ case CSBSpaceRGB:
+ DPSsetrgbcolor(csb->csb.context, csb->csb.current_color.red,
+ csb->csb.current_color.green,
+ csb->csb.current_color.blue);
+ break;
+ case CSBSpaceCMYK:
+ DPSsetcmykcolor(csb->csb.context, csb->csb.current_color.cyan,
+ csb->csb.current_color.magenta,
+ csb->csb.current_color.yellow,
+ csb->csb.current_color.black);
+ break;
+ case CSBSpaceHSB:
+ DPSsethsbcolor(csb->csb.context, csb->csb.current_color.hue,
+ csb->csb.current_color.saturation,
+ csb->csb.current_color.brightness);
+ break;
+ case CSBSpaceGray:
+ DPSsetgray(csb->csb.context, csb->csb.current_color.gray);
+ break;
+ }
+ }
+
+ switch (csb->csb.current_rendering) {
+ case CSBDisplayDPS:
+ DPSrectfill(csb->csb.context, 0.0, 0.0, 1000.0, 1000.0);
+ break;
+ case CSBDisplayX:
+ break;
+ case CSBDisplayBoth:
+ ToUserSpace(csb, width, height, &fw, &fh);
+ _DPSCTriangle(csb->csb.context, fh, fw);
+ break;
+ }
+}
+
+/* The following function Copyright 1987, 1988 by Digital Equipment
+Corporation, Maynard, Massachusetts, and the Massachusetts Institute of
+Technology, Cambridge, Massachusetts. */
+
+static String GetRootDirName(String buf)
+{
+#ifndef X_NOT_POSIX
+ uid_t uid;
+#else
+ int uid;
+ extern int getuid();
+#ifndef SYSV386
+ extern struct passwd *getpwuid(), *getpwnam();
+#endif
+#endif
+ struct passwd *pw;
+ static char *ptr = NULL;
+
+ if (ptr == NULL) {
+ if (!(ptr = getenv("HOME"))) {
+ if ((ptr = getenv("USER")) != 0) {
+ pw = getpwnam(ptr);
+ } else {
+ uid = getuid();
+ pw = getpwuid(uid);
+ }
+ if (pw) ptr = pw->pw_dir;
+ else {
+ ptr = NULL;
+ *buf = '\0';
+ }
+ }
+ }
+
+ if (ptr)
+ (void) strcpy(buf, ptr);
+
+ buf += strlen(buf);
+ *buf = '/';
+ buf++;
+ *buf = '\0';
+ return buf;
+}
+
+static void AllocateDock(ColorSelectionBoxWidget csb)
+{
+ int entry;
+
+ csb->csb.dock_cyan = (float *) XtCalloc(csb->csb.num_cells, sizeof(float));
+ csb->csb.dock_magenta =
+ (float *) XtCalloc(csb->csb.num_cells, sizeof(float));
+ csb->csb.dock_yellow =
+ (float *) XtCalloc(csb->csb.num_cells, sizeof(float));
+ csb->csb.dock_black =
+ (float *) XtCalloc(csb->csb.num_cells, sizeof(float));
+ csb->csb.dock_used =
+ (Boolean *) XtCalloc(csb->csb.num_cells, sizeof(Boolean));
+
+ for (entry = 0; entry < csb->csb.num_cells; entry++) {
+ csb->csb.dock_used[entry] = 0;
+ }
+}
+
+static void InitializeDock(ColorSelectionBoxWidget csb)
+{
+ String dockEnv;
+ char homeDir[PATH_BUF_SIZE];
+ FILE *dockFile = NULL;
+ char fileName[PATH_BUF_SIZE];
+#define BUF 256
+ char buf[BUF+1];
+ int entry;
+ float cyan, magenta, yellow, black;
+#define CHECK(v) ((v) > 1.0 ? 1.0 : ((v) < 0.0 ? 0.0 : (v)))
+
+ AllocateDock(csb);
+ csb->csb.dock_changed = False;
+
+ dockEnv = getenv("DPSCPICKRC");
+
+ if (dockEnv != NULL) dockFile = fopen(dockEnv, "r");
+
+ if (dockFile == NULL) {
+ (void) GetRootDirName(homeDir);
+
+ if (dockFile == NULL) {
+ sprintf(fileName, "%s/.dpscpickrc", homeDir);
+ dockFile = fopen(fileName, "r");
+
+ if (dockFile == NULL) return;
+ }
+ }
+
+ while (1) {
+ if (fgets(buf, BUF, dockFile) == NULL) {
+ fclose(dockFile);
+ return;
+ }
+ if (sscanf(buf, "%d %f %f %f %f",
+ &entry, &cyan, &magenta, &yellow, &black) == 5) {
+ if (entry <= csb->csb.num_cells) {
+ csb->csb.dock_cyan[entry] = CHECK(cyan);
+ csb->csb.dock_magenta[entry] = CHECK(magenta);
+ csb->csb.dock_yellow[entry] = CHECK(yellow);
+ csb->csb.dock_black[entry] = CHECK(black);
+ csb->csb.dock_used[entry] = True;
+ }
+ }
+ }
+
+#undef BUF
+#undef CHECK
+}
+
+static void SaveDockContents(ColorSelectionBoxWidget csb)
+{
+ String dockEnv;
+ char homeDir[PATH_BUF_SIZE];
+ FILE *dockFile = NULL;
+ char fileName[PATH_BUF_SIZE];
+ int i;
+
+ if (!csb->csb.dock_changed) return;
+
+ dockEnv = getenv("DPSCPICKRC");
+
+ if (dockEnv != NULL) dockFile = fopen(dockEnv, "w");
+
+ if (dockFile == NULL) {
+ (void) GetRootDirName(homeDir);
+
+ if (dockFile == NULL) {
+ sprintf(fileName, "%s/.dpscpickrc", homeDir);
+ dockFile = fopen(fileName, "w");
+
+ if (dockFile == NULL) return;
+ }
+ }
+
+ for (i = 0; i < csb->csb.num_cells; i++) {
+ if (!csb->csb.dock_used[i]) continue;
+ fprintf(dockFile, "%d %g %g %g %g\n", i, csb->csb.dock_cyan[i],
+ csb->csb.dock_magenta[i], csb->csb.dock_yellow[i],
+ csb->csb.dock_black[i]);
+ }
+ fclose(dockFile);
+ csb->csb.dock_changed = False;
+}
+
+/* ARGSUSED */
+
+static void DrawDockCallback(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) clientData;
+
+ XClearArea(XtDisplay(csb), XtWindow(csb->csb.dock_child),
+ 0, 0, 1000, 1000, False);
+ DrawDock(csb);
+}
+
+static void DrawDock(ColorSelectionBoxWidget csb)
+{
+ Dimension height;
+ float w, h;
+ int lines;
+ int i, row, col;
+ Boolean didAny = False;
+
+ XtVaGetValues(csb->csb.dock_child, XtNheight, &height, NULL);
+
+ lines = height / csb->csb.cell_size;
+
+ if (csb->csb.dock_gstate == 0) {
+ XDPSSetContextGState(csb->csb.context, csb->csb.base_gstate);
+ XDPSSetContextDrawable(csb->csb.context,
+ XtWindow(csb->csb.dock_child), height);
+ (void) XDPSCaptureContextGState(csb->csb.context,
+ &csb->csb.dock_gstate);
+ } else XDPSSetContextGState(csb->csb.context, csb->csb.dock_gstate);
+
+ ToUserSpace(csb, csb->csb.cell_size, csb->csb.cell_size, &w, &h);
+
+ for (i = 0; i < csb->csb.num_cells; i++) {
+ if (!csb->csb.dock_used[i]) continue;
+ row = (lines - 1) - (i % lines);
+ col = i / lines;
+
+ DPSsetcmykcolor(csb->csb.context, csb->csb.dock_cyan[i],
+ csb->csb.dock_magenta[i], csb->csb.dock_yellow[i],
+ csb->csb.dock_black[i]);
+
+ DPSrectfill(csb->csb.context,
+ (float) (col * w), (float) (row * h), w, h);
+ didAny = True;
+ }
+ if (!didAny) _DPSCShowFillMe(csb->csb.context, csb->csb.fill_me);
+}
+
+static void StoreColorInDock(
+ ColorSelectionBoxWidget csb,
+ int x_offset,
+ int y_offset,
+ Dimension dockHeight)
+{
+ int i, lines, row, col;
+
+ lines = dockHeight / csb->csb.cell_size;
+
+ row = y_offset / (int) csb->csb.cell_size;
+ col = x_offset / (int) csb->csb.cell_size;
+ i = col * lines + row;
+
+ if (i >= csb->csb.num_cells) i = csb->csb.num_cells;
+ csb->csb.dock_cyan[i] = csb->csb.current_color.cyan;
+ csb->csb.dock_magenta[i] = csb->csb.current_color.magenta;
+ csb->csb.dock_yellow[i] = csb->csb.current_color.yellow;
+ csb->csb.dock_black[i] = csb->csb.current_color.black;
+ csb->csb.dock_used[i] = True;
+ csb->csb.dock_changed = True;
+ DrawDock(csb);
+}
+
+/* ARGSUSED */
+
+static void DockPress(
+ Widget w,
+ XtPointer data,
+ XEvent *event,
+ Boolean *goOn)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) data;
+ Dimension height;
+ int i, lines, row, col;
+
+ XtVaGetValues(csb->csb.dock_child, XtNheight, &height, NULL);
+
+ lines = height / csb->csb.cell_size;
+
+ row = event->xbutton.y / (int) csb->csb.cell_size;
+ col = event->xbutton.x / (int) csb->csb.cell_size;
+ i = col * lines + row;
+ if (i >= csb->csb.num_cells) i = csb->csb.num_cells;
+
+ if (!csb->csb.dock_used[i]) return;
+
+ csb->csb.current_color.cyan = csb->csb.dock_cyan[i];
+ csb->csb.current_color.magenta = csb->csb.dock_magenta[i];
+ csb->csb.current_color.yellow = csb->csb.dock_yellow[i];
+ csb->csb.current_color.black = csb->csb.dock_black[i];
+ UpdateColorSpaces(csb, CSBSpaceCMYK);
+ DoValueChangedCallback(csb);
+ FillPatch(csb);
+ SetSliders(csb);
+}
+
+static void InitializePalettes(ColorSelectionBoxWidget csb)
+{
+ int k;
+
+ for (k = 0; k < PALETTE_MAX; k++) {
+ if (csb->csb.palette_function[k] != NULL) {
+ DPSPrintf(csb->csb.context,
+ "/palette%dfunc%d { %s } bind def\n", k, (int) csb,
+ csb->csb.palette_function[k]);
+ }
+ csb->csb.palette_broken[k] = False;
+ }
+}
+
+static void InvalidatePalette(ColorSelectionBoxWidget csb)
+{
+ int len;
+ char *buf;
+ Widget w;
+ register int i = csb->csb.current_palette;
+
+ len = strlen(csb->csb.palette_label[i]) +
+ strlen(csb->csb.broken_palette_label) + 2;
+ len = MAX(len, 11);
+ buf = (char *) XtMalloc(len);
+
+ csb->csb.palette_broken[i] = True;
+ sprintf(buf, "*palette%d", csb->csb.current_palette);
+ w = XtNameToWidget((Widget) csb, buf);
+ if (w != NULL) XtSetSensitive(w, False);
+ sprintf(buf, "%s %s", csb->csb.palette_label[i],
+ csb->csb.broken_palette_label);
+ len = strlen(buf);
+ XtVaSetValues(w, XtVaTypedArg, XmNlabelString, XtRString, buf, len, NULL);
+}
+
+static void DoPalette(
+ ColorSelectionBoxWidget csb,
+ Dimension pixelWidth,
+ float w,
+ float h)
+{
+ char whichFunc[25];
+ int steps;
+ int success;
+
+ sprintf(whichFunc, "palette%dfunc%d", csb->csb.current_palette, (int) csb);
+ if (csb->csb.visual_class == TrueColor) steps = pixelWidth / 2;
+ else steps = pixelWidth / 4;
+
+ if (csb->csb.palette_color_dependent[csb->csb.current_palette]) {
+ switch (csb->csb.palette_space[csb->csb.current_palette]) {
+ case CSBSpaceRGB:
+ _DPSCDoRGBColorPalette(csb->csb.context, whichFunc,
+ csb->csb.current_color.red,
+ csb->csb.current_color.green,
+ csb->csb.current_color.blue,
+ w, h, steps, &success);
+ break;
+ case CSBSpaceCMYK:
+ _DPSCDoCMYKColorPalette(csb->csb.context, whichFunc,
+ csb->csb.current_color.cyan,
+ csb->csb.current_color.magenta,
+ csb->csb.current_color.yellow,
+ csb->csb.current_color.black,
+ w, h, steps, &success);
+ break;
+ case CSBSpaceHSB:
+ _DPSCDoHSBColorPalette(csb->csb.context, whichFunc,
+ csb->csb.current_color.hue,
+ csb->csb.current_color.saturation,
+ csb->csb.current_color.brightness,
+ w, h, steps, &success);
+ break;
+ case CSBSpaceGray:
+ _DPSCDoGrayColorPalette(csb->csb.context, whichFunc,
+ csb->csb.current_color.gray,
+ w, h, steps, &success);
+ break;
+ }
+ } else {
+ switch (csb->csb.palette_space[csb->csb.current_palette]) {
+ case CSBSpaceRGB:
+ _DPSCDoRGBPalette(csb->csb.context, whichFunc, w, h,
+ steps, &success);
+ break;
+ case CSBSpaceCMYK:
+ _DPSCDoCMYKPalette(csb->csb.context, whichFunc, w, h,
+ steps, &success);
+ break;
+ case CSBSpaceHSB:
+ _DPSCDoHSBPalette(csb->csb.context, whichFunc, w, h,
+ steps, &success);
+ break;
+ case CSBSpaceGray:
+ _DPSCDoGrayPalette(csb->csb.context, whichFunc, w, h,
+ steps, &success);
+ break;
+ }
+ }
+ if (!success) {
+ InvalidatePalette(csb);
+ _DPSCShowMessage(csb->csb.context, csb->csb.broken_palette_message);
+ }
+}
+
+static void DrawPalette(ColorSelectionBoxWidget csb)
+{
+ DrawPaletteCallback(csb->csb.palette_child,
+ (XtPointer) csb, (XtPointer) NULL);
+}
+
+/* ARGSUSED */
+
+static void DrawPaletteCallback(
+ Widget wid,
+ XtPointer clientData, XtPointer callData)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) clientData;
+ Dimension width, height;
+ Pixmap palette_pixmap;
+ int depth;
+ float w, h;
+
+ if (csb->csb.palette_broken[csb->csb.current_palette]) return;
+ if (!csb->csb.palette_pixmap_valid) {
+ XtVaGetValues(csb->csb.palette_child,
+ XtNwidth, &width, XtNheight, &height,
+ XtNdepth, &depth, NULL);
+
+ ToUserSpace(csb, width, height, &w, &h);
+
+ palette_pixmap =
+ XCreatePixmap(XtDisplay(csb), XtWindow(csb->csb.palette_child),
+ width, height, depth);
+
+ XDPSSetContextGState(csb->csb.context, csb->csb.base_gstate);
+ XDPSSetContextDrawable(csb->csb.context, palette_pixmap, height);
+
+ DoPalette(csb, width, w, h);
+ csb->csb.palette_color = csb->csb.current_color;
+ DPSWaitContext(csb->csb.context);
+ XtVaSetValues(csb->csb.palette_child,
+ XtNbackgroundPixmap, palette_pixmap, NULL);
+ XFreePixmap(XtDisplay(csb), palette_pixmap);
+ csb->csb.palette_pixmap_valid = True;
+ }
+}
+
+/* ARGSUSED */
+
+static void PalettePress(
+ Widget w,
+ XtPointer data,
+ XEvent *event,
+ Boolean *goOn)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) data;
+ Dimension width;
+ float pct;
+ char whichFunc[25];
+ int success;
+ float f1, f2, f3, f4;
+
+ if (csb->csb.palette_broken[csb->csb.current_palette]) return;
+
+ sprintf(whichFunc, "palette%dfunc%d", csb->csb.current_palette, (int) csb);
+
+ XtVaGetValues(csb->csb.palette_child, XtNwidth, &width, NULL);
+
+ pct = ((float) event->xbutton.x) / ((float) width);
+
+ if (csb->csb.palette_color_dependent[csb->csb.current_palette]) {
+ switch (csb->csb.palette_space[csb->csb.current_palette]) {
+ case CSBSpaceRGB:
+ _DPSCQueryRGBColorPalette(csb->csb.context, whichFunc, pct,
+ csb->csb.palette_color.red,
+ csb->csb.palette_color.green,
+ csb->csb.palette_color.blue,
+ &f1, &f2, &f3, &success);
+ if (success) {
+ csb->csb.current_color.red = f1;
+ csb->csb.current_color.green = f2;
+ csb->csb.current_color.blue = f3;
+ }
+ break;
+ case CSBSpaceCMYK:
+ _DPSCQueryCMYKColorPalette(csb->csb.context, whichFunc, pct,
+ csb->csb.palette_color.cyan,
+ csb->csb.palette_color.magenta,
+ csb->csb.palette_color.yellow,
+ csb->csb.palette_color.black,
+ &f1, &f2, &f3, &f4, &success);
+ if (success) {
+ csb->csb.current_color.cyan = f1;
+ csb->csb.current_color.magenta = f2;
+ csb->csb.current_color.yellow = f3;
+ csb->csb.current_color.black = f4;
+ }
+ break;
+ case CSBSpaceHSB:
+ _DPSCQueryHSBColorPalette(csb->csb.context, whichFunc, pct,
+ csb->csb.palette_color.hue,
+ csb->csb.palette_color.saturation,
+ csb->csb.palette_color.brightness,
+ &f1, &f2, &f3, &success);
+ if (success) {
+ csb->csb.current_color.hue = f1;
+ csb->csb.current_color.saturation = f2;
+ csb->csb.current_color.brightness = f3;
+ }
+ break;
+ case CSBSpaceGray:
+ _DPSCQueryGrayColorPalette(csb->csb.context, whichFunc, pct,
+ csb->csb.palette_color.gray,
+ &f1, &success);
+ if (success) csb->csb.current_color.gray = f1;
+ break;
+ }
+ } else {
+ switch (csb->csb.palette_space[csb->csb.current_palette]) {
+ case CSBSpaceRGB:
+ _DPSCQueryRGBPalette(csb->csb.context, whichFunc, pct,
+ &f1, &f2, &f3, &success);
+ if (success) {
+ csb->csb.current_color.red = f1;
+ csb->csb.current_color.green = f2;
+ csb->csb.current_color.blue = f3;
+ }
+ break;
+ case CSBSpaceCMYK:
+ _DPSCQueryCMYKPalette(csb->csb.context, whichFunc, pct,
+ &f1, &f2, &f3, &f4, &success);
+ if (success) {
+ csb->csb.current_color.cyan = f1;
+ csb->csb.current_color.magenta = f2;
+ csb->csb.current_color.yellow = f3;
+ csb->csb.current_color.black = f4;
+ }
+ break;
+ case CSBSpaceHSB:
+ _DPSCQueryHSBPalette(csb->csb.context, whichFunc, pct,
+ &f1, &f2, &f3, &success);
+ if (success) {
+ csb->csb.current_color.hue = f1;
+ csb->csb.current_color.saturation = f2;
+ csb->csb.current_color.brightness = f3;
+ }
+ break;
+ case CSBSpaceGray:
+ _DPSCQueryGrayPalette(csb->csb.context, whichFunc, pct,
+ &f1, &success);
+ if (success) csb->csb.current_color.gray = f1;
+ break;
+ }
+ }
+ if (!success) InvalidatePalette(csb);
+ else {
+ UpdateColorSpaces(csb,
+ csb->csb.palette_space[csb->csb.current_palette]);
+ DoValueChangedCallback(csb);
+ FillPatch(csb);
+ SetSliders(csb);
+ }
+}
+
+/* ARGSUSED */
+
+static void DoEyedropCallback(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) clientData;
+ Pixmap eyedropBitmap, eyedropMaskBitmap;
+ XColor black, fg;
+ Display *dpy;
+ unsigned int x, y;
+ XEvent ev;
+
+ dpy = XtDisplay(w);
+
+ black.red = 0;
+ black.green = 0;
+ black.blue = 0;
+
+ fg.red = 65535;
+ fg.green = 65535;
+ fg.blue = 65535;
+
+ if (csb->csb.eyedrop == None) {
+ XQueryBestCursor(dpy, XtWindow(w), 32, 32,
+ &x, &y);
+
+ if (x >= 32 && y >= 32) {
+ eyedropBitmap =
+ XCreateBitmapFromData(dpy, XtWindow(w),
+ (char *) eyedrop32_bits,
+ eyedrop32_width, eyedrop32_height);
+
+ eyedropMaskBitmap =
+ XCreateBitmapFromData(dpy, XtWindow(w),
+ (char *) eyedropmask32_bits,
+ eyedropmask32_width,
+ eyedropmask32_height);
+
+ csb->csb.eyedrop =
+ XCreatePixmapCursor(dpy, eyedropBitmap,
+ eyedropMaskBitmap,
+ &fg, &black,
+ eyedrop32_x_hot, eyedrop32_y_hot);
+ } else {
+ eyedropBitmap =
+ XCreateBitmapFromData(dpy, XtWindow(w),
+ (char *) eyedrop16_bits,
+ eyedrop16_width, eyedrop16_height);
+
+ eyedropMaskBitmap =
+ XCreateBitmapFromData(dpy, XtWindow(w),
+ (char *) eyedropmask16_bits,
+ eyedropmask16_width,
+ eyedropmask16_height);
+
+ csb->csb.eyedrop =
+ XCreatePixmapCursor(dpy, eyedropBitmap,
+ eyedropMaskBitmap,
+ &fg, &black,
+ eyedrop16_x_hot, eyedrop16_y_hot);
+ }
+ } else {
+ XRecolorCursor(dpy, csb->csb.eyedrop, &fg, &black);
+ }
+
+ (void) XtGrabPointer(w, False,
+ PointerMotionMask | PointerMotionHintMask |
+ ButtonReleaseMask,
+ GrabModeAsync, GrabModeAsync,
+ None, csb->csb.eyedrop,
+ XtLastTimestampProcessed(dpy));
+ csb->csb.eyedrop_grabbed = True;
+
+ ev.type = 0;
+ EyedropPointer(w, (XtPointer) csb, &ev, (Boolean *) NULL);
+}
+
+/* ARGSUSED */
+
+static void EyedropPointer(
+ Widget w,
+ XtPointer data,
+ XEvent *event,
+ Boolean *goOn)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) data;
+ XColor fg, black;
+ Window root, child, stop, old_child = None;
+ int root_x, root_y, x, y;
+ unsigned int mask;
+ XWindowAttributes att;
+ XImage *image;
+ Pixel pixel;
+ Colormap colormap = 0;
+ Display *dpy = XtDisplay(w);
+
+ if (!csb->csb.eyedrop_grabbed) return;
+
+ if (event->type == ButtonPress || event->type == ButtonRelease) {
+ root = event->xbutton.root;
+ root_x = event->xbutton.x_root;
+ root_y = event->xbutton.y_root;
+
+ XTranslateCoordinates(dpy, root, root, root_x, root_y, &x, &y, &child);
+
+ } else {
+ XQueryPointer(dpy, RootWindowOfScreen(XtScreen(w)),
+ &root, &child, &root_x, &root_y, &x, &y, &mask);
+ }
+
+ if (child == None) child = root;
+ else {
+ stop = child;
+
+ while (stop != None) {
+ XTranslateCoordinates(dpy, root, stop, x, y, &x, &y, &child);
+ root = stop;
+ if (child != None && XGetWindowAttributes(dpy, child, &att) &&
+ att.class != InputOutput) break;
+ stop = child;
+ }
+ child = root;
+ }
+
+ if (child != old_child) {
+ XGetWindowAttributes(dpy, child, &att);
+ colormap = att.colormap;
+ old_child = child;
+ }
+
+ image = XGetImage(dpy, child, x, y, 1, 1, AllPlanes, XYPixmap);
+
+ pixel = XGetPixel(image, 0, 0);
+
+ XDestroyImage(image);
+ fg.pixel = pixel;
+ XQueryColors(dpy, colormap, &fg, 1);
+
+ black.red = 0;
+ black.green = 0;
+ black.blue = 0;
+
+ XRecolorCursor(dpy, csb->csb.eyedrop, &fg, &black);
+
+ if (event->type == ButtonRelease) {
+ XtUngrabPointer(w, XtLastTimestampProcessed(dpy));
+ csb->csb.eyedrop_grabbed = False;
+
+ csb->csb.current_color.red = (float) fg.red / 65535.0;
+ csb->csb.current_color.green = (float) fg.green / 65535.0;
+ csb->csb.current_color.blue = (float) fg.blue / 65535.0;
+ UpdateColorSpaces(csb, CSBSpaceRGB);
+ DoValueChangedCallback(csb);
+ FillPatch(csb);
+ SetSliders(csb);
+ }
+}
+
+/* ARGSUSED */
+
+static void PatchPress(
+ Widget w,
+ XtPointer data,
+ XEvent *event,
+ Boolean *goOn)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) data;
+ Pixmap squareBitmap, squareMaskBitmap;
+ XColor black, fg;
+ Display *dpy;
+
+ dpy = XtDisplay(w);
+
+ black.red = 0;
+ black.green = 0;
+ black.blue = 0;
+
+ fg.red = TO_X(csb->csb.current_color.red);
+ fg.green = TO_X(csb->csb.current_color.green);
+ fg.blue = TO_X(csb->csb.current_color.blue);
+
+ if (csb->csb.square == None) {
+ squareBitmap =
+ XCreateBitmapFromData(dpy, XtWindow(w), (char *) square_bits,
+ square_width, square_height);
+
+ squareMaskBitmap =
+ XCreateBitmapFromData(dpy, XtWindow(w),
+ (char *) squaremask_bits,
+ squaremask_width, squaremask_height);
+
+ csb->csb.square =
+ XCreatePixmapCursor(dpy, squareBitmap, squareMaskBitmap,
+ &fg, &black, square_x_hot, square_y_hot);
+ } else {
+ XRecolorCursor(dpy, csb->csb.square, &fg, &black);
+ }
+
+ (void) XtGrabPointer(w, False, ButtonReleaseMask,
+ GrabModeAsync, GrabModeAsync,
+ None, csb->csb.square, XtLastTimestampProcessed(dpy));
+}
+
+/* ARGSUSED */
+
+static void PatchRelease(
+ Widget w,
+ XtPointer data,
+ XEvent *event,
+ Boolean *goOn)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) data;
+ Dimension width, height;
+ Position left, top;
+
+ XtUngrabPointer(w, XtLastTimestampProcessed(XtDisplay(w)));
+ XFlush(XtDisplay(w));
+
+ XtVaGetValues(csb->csb.dock_child, XtNwidth, &width,
+ XtNheight, &height, NULL);
+
+ XtTranslateCoords(csb->csb.dock_child, (Position) 0, (Position) 0,
+ &left, &top);
+
+ if ((int) event->xbutton.x_root >= left &&
+ (int) event->xbutton.x_root <= left + (int) width &&
+ (int) event->xbutton.y_root >= top &&
+ (int) event->xbutton.y_root <= top + (int) height) {
+ StoreColorInDock(csb, event->xbutton.x_root - left,
+ event->xbutton.y_root - top, height);
+ }
+}
+
+static void GetVisualInfo(
+ ColorSelectionBoxWidget csb,
+ Visual **visual)
+{
+ Widget w = (Widget) csb;
+ XVisualInfo *vip, viproto;
+ int n;
+ XWindowAttributes xwa;
+
+ XGetWindowAttributes(XtDisplay(w), XtWindow(w), &xwa);
+
+ *visual = viproto.visual = xwa.visual;
+ viproto.visualid = XVisualIDFromVisual(xwa.visual);
+ vip = XGetVisualInfo(XtDisplay(w), VisualIDMask, &viproto, &n);
+
+ if (n != 1) {
+ csb->csb.static_visual = False; /* Actually we have no idea, but... */
+ csb->csb.visual_class = PseudoColor;
+ } else {
+ csb->csb.visual_class = vip->class;
+ csb->csb.static_visual = (vip->class == StaticGray ||
+ vip->class == TrueColor ||
+ vip->class == StaticColor);
+ }
+
+ if (n > 0) XFree((char *) vip);
+}
+
+static void SetBackground(ColorSelectionBoxWidget csb)
+{
+ Colormap c;
+ XColor xc;
+ int status;
+ unsigned long pix;
+ unsigned long mask;
+
+ XtVaGetValues(csb->csb.patch_child, XtNcolormap, (XtPointer) &c, NULL);
+
+ if (csb->csb.current_space == CSBSpaceGray) {
+ xc.red = xc.green = xc.blue = TO_X(csb->csb.current_color.gray);
+ } else {
+ xc.red = TO_X(csb->csb.current_color.red);
+ xc.green = TO_X(csb->csb.current_color.green);
+ xc.blue = TO_X(csb->csb.current_color.blue);
+ }
+
+ if (csb->csb.static_visual) {
+ status = XAllocColor(XtDisplay(csb), c, &xc);
+ if (status == 0) NoBackgroundPixel(csb);
+ else {
+ csb->csb.background = xc.pixel;
+ XtVaSetValues(csb->csb.patch_child,
+ XtNbackground, csb->csb.background, NULL);
+ }
+
+ } else {
+ if (csb->csb.visual_class == DirectColor) {
+ status = XAllocColorPlanes(XtDisplay(csb), c,
+ False, &pix, 1, 0, 0, 0,
+ &mask, &mask, &mask);
+ } else {
+ status = XAllocColorCells(XtDisplay(csb), c,
+ False, (unsigned long *) NULL, 0,
+ &pix, 1);
+ }
+
+ if (status == 0) NoBackgroundPixel(csb);
+ else {
+ xc.pixel = pix;
+ xc.flags = DoRed | DoGreen | DoBlue;
+ XStoreColor(XtDisplay(csb), c, &xc);
+
+ csb->csb.background = xc.pixel;
+ XtVaSetValues(csb->csb.patch_child,
+ XtNbackground, csb->csb.background, NULL);
+ }
+ }
+}
+
+/* ARGSUSED */
+
+static void Initialize(
+ Widget request, Widget new,
+ ArgList args,
+ Cardinal *num_args)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) new;
+ Bool inited;
+ int i;
+
+ if (csb->csb.rgb_labels != NULL) {
+ csb->csb.rgb_labels = XtNewString(csb->csb.rgb_labels);
+ }
+ if (csb->csb.cmyk_labels != NULL) {
+ csb->csb.cmyk_labels = XtNewString(csb->csb.cmyk_labels);
+ }
+ if (csb->csb.hsb_labels != NULL) {
+ csb->csb.hsb_labels = XtNewString(csb->csb.hsb_labels);
+ }
+ if (csb->csb.gray_labels != NULL) {
+ csb->csb.gray_labels = XtNewString(csb->csb.gray_labels);
+ }
+ if (csb->csb.fill_me != NULL) {
+ csb->csb.fill_me = XtNewString(csb->csb.fill_me);
+ }
+ if (csb->csb.broken_palette_label != NULL) {
+ csb->csb.broken_palette_label =
+ XtNewString(csb->csb.broken_palette_label);
+ }
+ if (csb->csb.broken_palette_message != NULL) {
+ csb->csb.broken_palette_message =
+ XtNewString(csb->csb.broken_palette_message);
+ }
+
+ for (i = 0; i < PALETTE_MAX; i++) {
+ if (csb->csb.palette_function[i] != NULL) {
+ csb->csb.palette_function[i] =
+ XtNewString(csb->csb.palette_function[i]);
+ }
+ }
+
+ if (csb->csb.num_cells <= 0) csb->csb.num_cells = 1;
+
+ /* Get the context */
+
+ if (csb->csb.context == NULL) {
+ csb->csb.context = XDPSGetSharedContext(XtDisplay(csb));
+ }
+
+ if (_XDPSTestComponentInitialized(csb->csb.context,
+ dps_init_bit_csb, &inited) ==
+ dps_status_unregistered_context) {
+ XDPSRegisterContext(csb->csb.context, False);
+ }
+
+ if (!inited) {
+ (void) _XDPSSetComponentInitialized(csb->csb.context,
+ dps_init_bit_csb);
+ InitializePalettes(csb);
+ }
+
+ if (csb->csb.current_palette < 0 ||
+ csb->csb.current_palette > PALETTE_MAX ||
+ csb->csb.palette_function[csb->csb.current_palette] == NULL) {
+ csb->csb.current_palette = 0;
+ }
+
+ /* Initialize non-resource fields */
+
+ CreateChildren(csb);
+ csb->csb.no_background = False;
+ csb->csb.patch_gstate = csb->csb.dock_gstate = 0;
+ csb->csb.red_pixmap = csb->csb.green_pixmap = csb->csb.blue_pixmap =
+ csb->csb.cyan_pixmap = csb->csb.magenta_pixmap =
+ csb->csb.yellow_pixmap = csb->csb.black_pixmap =
+ csb->csb.hue_pixmap = csb->csb.sat_pixmap =
+ csb->csb.bright_pixmap = csb->csb.gray_pixmap = None;
+
+ csb->csb.square = csb->csb.eyedrop = None;
+ csb->csb.eyedrop_grabbed = False;
+
+ for (i = 0; i < PALETTE_MAX; i++) csb->csb.palette_broken[i] = False;
+ csb->csb.palette_pixmap_valid = False;
+
+ csb->csb.current_color.hue = 0.0;
+ csb->csb.current_color.saturation = 1.0;
+ csb->csb.current_color.brightness = 1.0;
+ UpdateColorSpaces(csb, CSBSpaceHSB);
+ csb->csb.save_color = csb->csb.current_color;
+ SetSliders(csb);
+
+ InitializeDock(csb);
+ SetColorSpace(csb);
+ SetRendering(csb);
+}
+
+static void Destroy(Widget widget)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) widget;
+ Display *dpy = XtDisplay(csb);
+ int i;
+
+ /* Lots of stuff to destroy! */
+
+ if (csb->csb.patch_gstate != 0) {
+ XDPSFreeContextGState(csb->csb.context, csb->csb.patch_gstate);
+ }
+ if (csb->csb.dock_gstate != 0) {
+ XDPSFreeContextGState(csb->csb.context, csb->csb.dock_gstate);
+ }
+ if (csb->csb.base_gstate != 0) {
+ XDPSFreeContextGState(csb->csb.context, csb->csb.base_gstate);
+ }
+
+ if (csb->csb.rgb_labels != NULL) XtFree(csb->csb.rgb_labels);
+ if (csb->csb.cmyk_labels != NULL) XtFree(csb->csb.cmyk_labels);
+ if (csb->csb.hsb_labels != NULL) XtFree(csb->csb.hsb_labels);
+ if (csb->csb.gray_labels != NULL) XtFree(csb->csb.gray_labels);
+ if (csb->csb.fill_me != NULL) XtFree(csb->csb.fill_me);
+ if (csb->csb.broken_palette_message != NULL) {
+ XtFree(csb->csb.broken_palette_message);
+ }
+ if (csb->csb.broken_palette_label != NULL) {
+ XtFree(csb->csb.broken_palette_label);
+ }
+
+ XtFree((XtPointer) csb->csb.dock_cyan);
+ XtFree((XtPointer) csb->csb.dock_magenta);
+ XtFree((XtPointer) csb->csb.dock_yellow);
+ XtFree((XtPointer) csb->csb.dock_black);
+ XtFree((XtPointer) csb->csb.dock_used);
+
+ for (i = 0; i < PALETTE_MAX; i++) {
+ if (csb->csb.palette_function[i] != NULL) {
+ XtFree(csb->csb.palette_function[i]);
+ }
+ }
+
+ if (csb->csb.eyedrop != None) XFreeCursor(dpy, csb->csb.eyedrop);
+ if (csb->csb.square != None) XFreeCursor(dpy, csb->csb.square);
+
+ if (csb->csb.red_pixmap != None) XFreePixmap(dpy, csb->csb.red_pixmap);
+ if (csb->csb.green_pixmap != None) XFreePixmap(dpy, csb->csb.green_pixmap);
+ if (csb->csb.blue_pixmap != None) XFreePixmap(dpy, csb->csb.blue_pixmap);
+ if (csb->csb.cyan_pixmap != None) XFreePixmap(dpy, csb->csb.cyan_pixmap);
+ if (csb->csb.magenta_pixmap != None)
+ XFreePixmap(dpy, csb->csb.magenta_pixmap);
+ if (csb->csb.yellow_pixmap != None)
+ XFreePixmap(dpy, csb->csb.yellow_pixmap);
+ if (csb->csb.black_pixmap != None) XFreePixmap(dpy, csb->csb.black_pixmap);
+ if (csb->csb.hue_pixmap != None) XFreePixmap(dpy, csb->csb.hue_pixmap);
+ if (csb->csb.sat_pixmap != None) XFreePixmap(dpy, csb->csb.sat_pixmap);
+ if (csb->csb.bright_pixmap != None)
+ XFreePixmap(dpy, csb->csb.bright_pixmap);
+ if (csb->csb.gray_pixmap != None) XFreePixmap(dpy, csb->csb.gray_pixmap);
+}
+
+static void ChangeManaged(Widget w)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) w;
+
+ w->core.width = csb->composite.children[0]->core.width;
+ w->core.height = csb->composite.children[0]->core.height;
+}
+
+/* ARGSUSED */
+
+static XtGeometryResult GeometryManager(
+ Widget w,
+ XtWidgetGeometry *desired, XtWidgetGeometry *allowed)
+{
+#define WANTS(flag) (desired->request_mode & flag)
+
+ if (WANTS(XtCWQueryOnly)) return XtGeometryYes;
+
+ if (WANTS(CWWidth)) w->core.width = desired->width;
+ if (WANTS(CWHeight)) w->core.height = desired->height;
+ if (WANTS(CWX)) w->core.x = desired->x;
+ if (WANTS(CWY)) w->core.y = desired->y;
+ if (WANTS(CWBorderWidth)) {
+ w->core.border_width = desired->border_width;
+ }
+
+ return XtGeometryYes;
+#undef WANTS
+}
+
+static void SetColorSpace(ColorSelectionBoxWidget csb)
+{
+ switch(csb->csb.current_space) {
+ case CSBSpaceRGB:
+ SetRGBCallback((Widget) csb, (XtPointer) csb, (XtPointer) NULL);
+ break;
+
+ case CSBSpaceCMYK:
+ SetCMYKCallback((Widget) csb, (XtPointer) csb, (XtPointer) NULL);
+ break;
+
+ case CSBSpaceHSB:
+ SetHSBCallback((Widget) csb, (XtPointer) csb, (XtPointer) NULL);
+ break;
+
+ case CSBSpaceGray:
+ SetGrayCallback((Widget) csb, (XtPointer) csb, (XtPointer) NULL);
+ break;
+ }
+}
+
+static void SetRendering(ColorSelectionBoxWidget csb)
+{
+ Widget w;
+
+ switch(csb->csb.current_rendering) {
+ default:
+ case CSBDisplayDPS:
+ w = XtNameToWidget((Widget) csb, "*displayDPS");
+ break;
+ case CSBDisplayX:
+ w = XtNameToWidget((Widget) csb, "*displayX");
+ break;
+ case CSBDisplayBoth:
+ w = XtNameToWidget((Widget) csb, "*displayBoth");
+ break;
+ }
+ XtVaSetValues(csb->csb.display_option_menu_child, XmNmenuHistory, w, NULL);
+ if (XtIsRealized(csb->csb.patch_child)) {
+ XClearArea(XtDisplay(csb), XtWindow(csb->csb.patch_child),
+ 0, 0, 1000, 1000, True);
+ }
+}
+
+static void SetPalette(ColorSelectionBoxWidget csb)
+{
+ Widget w;
+ char buf[10];
+
+ sprintf(buf, "*palette%d", csb->csb.current_palette);
+ w = XtNameToWidget((Widget) csb, buf);
+
+ XtVaSetValues(csb->csb.palette_option_menu_child, XmNmenuHistory, w, NULL);
+
+ csb->csb.palette_pixmap_valid = False;
+ DrawPalette(csb);
+}
+
+static void SetBaseGState(
+ ColorSelectionBoxWidget csb,
+ Visual *visual)
+{
+ XStandardColormap colorCube, grayRamp;
+ int match;
+
+ /* If the context's colormap matches the widget's colormap, assume that
+ everything is already set up right in the color cube department. This
+ allows an application to supply us with a custom color cube by
+ installing it in the context before calling us */
+
+ _DPSCColormapMatch(csb->csb.context, csb->core.colormap, &match);
+
+ if (match) {
+ XDPSSetContextParameters(csb->csb.context, XtScreen(csb),
+ csb->core.depth, XtWindow(csb),
+ csb->core.height, NULL, NULL,
+ XDPSContextScreenDepth | XDPSContextDrawable);
+ } else {
+ grayRamp.colormap = colorCube.colormap = csb->core.colormap;
+
+ XDPSCreateStandardColormaps(XtDisplay(csb), XtWindow(csb), visual,
+ 0, 0, 0, 0, &colorCube, &grayRamp, False);
+
+ XDPSSetContextParameters(csb->csb.context, XtScreen(csb),
+ csb->core.depth, XtWindow(csb),
+ csb->core.height,
+ (XDPSStandardColormap *) &colorCube,
+ (XDPSStandardColormap *) &grayRamp,
+ XDPSContextScreenDepth | XDPSContextDrawable |
+ XDPSContextRGBMap | XDPSContextGrayMap);
+ }
+
+ XDPSCaptureContextGState(csb->csb.context, &csb->csb.base_gstate);
+}
+
+/* ARGSUSED */
+
+static Boolean SetValues(
+ Widget old, Widget req, Widget new,
+ ArgList args,
+ Cardinal *num_args)
+{
+ ColorSelectionBoxWidget oldcsb = (ColorSelectionBoxWidget) old;
+ ColorSelectionBoxWidget newcsb = (ColorSelectionBoxWidget) new;
+ Bool inited;
+ char buf[10];
+ Widget w = 0;
+ int i;
+
+#define NE(field) newcsb->csb.field != oldcsb->csb.field
+
+ if (NE(rgb_labels)) {
+ XtFree(oldcsb->csb.rgb_labels);
+ newcsb->csb.rgb_labels = XtNewString(newcsb->csb.rgb_labels);
+ }
+ if (NE(cmyk_labels)) {
+ XtFree(oldcsb->csb.cmyk_labels);
+ newcsb->csb.cmyk_labels = XtNewString(newcsb->csb.cmyk_labels);
+ }
+ if (NE(hsb_labels)) {
+ XtFree(oldcsb->csb.hsb_labels);
+ newcsb->csb.hsb_labels = XtNewString(newcsb->csb.hsb_labels);
+ }
+ if (NE(gray_labels)) {
+ XtFree(oldcsb->csb.gray_labels);
+ newcsb->csb.gray_labels = XtNewString(newcsb->csb.gray_labels);
+ }
+
+ if (NE(context)) {
+ if (newcsb->csb.context == NULL) {
+ newcsb->csb.context = XDPSGetSharedContext(XtDisplay(newcsb));
+ }
+ if (_XDPSTestComponentInitialized(newcsb->csb.context,
+ dps_init_bit_csb, &inited) ==
+ dps_status_unregistered_context) {
+ XDPSRegisterContext(newcsb->csb.context, False);
+ }
+ if (!inited) {
+ (void) _XDPSSetComponentInitialized(newcsb->csb.context,
+ dps_init_bit_csb);
+ InitializePalettes(newcsb);
+ }
+ newcsb->csb.patch_gstate = newcsb->csb.dock_gstate = 0;
+ XDPSFreeContextGState(newcsb->csb.context, newcsb->csb.patch_gstate);
+ XDPSFreeContextGState(newcsb->csb.context, newcsb->csb.dock_gstate);
+ if (XtIsRealized(newcsb)) {
+ XWindowAttributes xwa;
+
+ XGetWindowAttributes(XtDisplay(newcsb), XtWindow(newcsb), &xwa);
+ SetBaseGState(newcsb, xwa.visual);
+ }
+ }
+
+ if (NE(fill_me)) {
+ XtFree(oldcsb->csb.fill_me);
+ newcsb->csb.fill_me = XtNewString(newcsb->csb.fill_me);
+ }
+
+ if (NE(broken_palette_label)) {
+ XtFree(oldcsb->csb.broken_palette_label);
+ newcsb->csb.broken_palette_label =
+ XtNewString(newcsb->csb.broken_palette_label);
+ }
+
+ if (NE(broken_palette_message)) {
+ XtFree(oldcsb->csb.broken_palette_message);
+ newcsb->csb.broken_palette_message =
+ XtNewString(newcsb->csb.broken_palette_message);
+ }
+
+ if (newcsb->csb.num_cells <= 0) newcsb->csb.num_cells = 1;
+ if (NE(num_cells)) {
+ int i, min;
+
+ AllocateDock(newcsb);
+ min = MIN(newcsb->csb.num_cells, oldcsb->csb.num_cells);
+ for (i = 0; i < min; i++) {
+ newcsb->csb.dock_cyan[i] = oldcsb->csb.dock_cyan[i];
+ newcsb->csb.dock_magenta[i] = oldcsb->csb.dock_magenta[i];
+ newcsb->csb.dock_yellow[i] = oldcsb->csb.dock_yellow[i];
+ newcsb->csb.dock_black[i] = oldcsb->csb.dock_black[i];
+ newcsb->csb.dock_used[i] = oldcsb->csb.dock_used[i];
+ }
+ XtFree((XtPointer) oldcsb->csb.dock_cyan);
+ XtFree((XtPointer) oldcsb->csb.dock_magenta);
+ XtFree((XtPointer) oldcsb->csb.dock_yellow);
+ XtFree((XtPointer) oldcsb->csb.dock_black);
+ XtFree((XtPointer) oldcsb->csb.dock_used);
+ }
+
+ for (i = 0; i < PALETTE_MAX; i++) {
+ if (NE(palette_function[i]) || NE(palette_label[i])) {
+ sprintf(buf, "*palette%d", i);
+ w = XtNameToWidget((Widget) newcsb, buf);
+ }
+ if (NE(palette_function[i])) {
+ if (newcsb->csb.palette_function[i] != NULL) {
+ DPSPrintf(newcsb->csb.context,
+ "/palette%dfunc%d { %s } bind def\n", i,
+ (int) newcsb, newcsb->csb.palette_function[i]);
+ /* Assume the best... */
+ newcsb->csb.palette_broken[i] = False;
+ XtManageChild(w);
+ } else {
+ XtUnmanageChild(w);
+ if (newcsb->csb.current_palette == i) {
+ newcsb->csb.current_palette = -1;
+ }
+ }
+ }
+ if (NE(palette_label[i]) || NE(palette_function[i])) {
+ XtSetSensitive(w, True);
+ XtVaSetValues(w, XtVaTypedArg, XmNlabelString, XtRString,
+ newcsb->csb.palette_label[i],
+ strlen(newcsb->csb.palette_label[i])+1, NULL);
+ }
+ }
+
+ if (NE(current_palette)) {
+ if (newcsb->csb.current_palette < 0 ||
+ newcsb->csb.current_palette > PALETTE_MAX ||
+ newcsb->csb.palette_function[newcsb->csb.current_palette] == NULL ||
+ newcsb->csb.palette_broken[newcsb->csb.current_palette]) {
+ newcsb->csb.current_palette = 0;
+ }
+ }
+ if (NE(current_palette) ||
+ NE(palette_function[newcsb->csb.current_palette])) SetPalette(newcsb);
+
+ if ((NE(cell_size) || NE(fill_me)) &&
+ XtIsRealized(newcsb->csb.dock_child)) {
+ XClearArea(XtDisplay(newcsb), XtWindow(newcsb->csb.dock_child),
+ 0, 0, 1000, 1000, True);
+ }
+
+ if (NE(current_space)) SetColorSpace(newcsb);
+ if (NE(current_rendering)) SetRendering(newcsb);
+
+ return False;
+#undef NE
+}
+
+static void Realize(
+ Widget w,
+ XtValueMask *mask,
+ XSetWindowAttributes *attr)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) w;
+ Visual *v;
+
+ (*colorSelectionBoxClassRec.core_class.superclass->core_class.realize)
+ (w, mask, attr);
+
+ GetVisualInfo(csb, &v);
+ SetBackground(csb);
+ SetBaseGState(csb, v);
+ _DPSCGetInvCTM(csb->csb.context, csb->csb.itransform);
+}
+
+static void Resize(Widget widget)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) widget;
+
+ XtResizeWidget(csb->csb.form_child, csb->core.width, csb->core.height, 0);
+}
+
+static Boolean SetColor(
+ Widget w,
+ CSBColorSpace space,
+ double c1, double c2, double c3, double c4,
+ Bool setSpace)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) w;
+#define CHECK(c) if ((c) > 1.0 || (c) < 0.0) return False;
+
+ CHECK(c1);
+ switch (space) {
+ case CSBSpaceRGB:
+ CHECK(c2);
+ CHECK(c3);
+ csb->csb.current_color.red = c1;
+ csb->csb.current_color.green = c2;
+ csb->csb.current_color.blue = c3;
+ break;
+ case CSBSpaceCMYK:
+ CHECK(c2);
+ CHECK(c3);
+ CHECK(c4);
+ csb->csb.current_color.cyan = c1;
+ csb->csb.current_color.magenta = c2;
+ csb->csb.current_color.yellow = c3;
+ csb->csb.current_color.black = c4;
+ break;
+ case CSBSpaceHSB:
+ CHECK(c2);
+ CHECK(c3);
+ csb->csb.current_color.hue = c1;
+ csb->csb.current_color.saturation = c2;
+ csb->csb.current_color.brightness = c3;
+ break;
+ case CSBSpaceGray:
+ csb->csb.current_color.gray = c1;
+ break;
+ }
+ UpdateColorSpaces(csb, space);
+ csb->csb.save_color = csb->csb.current_color;
+ DoValueChangedCallback(csb);
+ FillPatch(csb);
+ SetSliders(csb);
+ if (setSpace) XtVaSetValues(w, XtNcurrentSpace, space, NULL);
+ return True;
+#undef CHECK
+}
+
+Boolean CSBSetColor(
+ Widget w,
+ CSBColorSpace space,
+ double c1, double c2, double c3, double c4,
+ Bool setSpace)
+{
+ XtCheckSubclass(w, colorSelectionBoxWidgetClass, NULL);
+
+ return (*((ColorSelectionBoxWidgetClass) XtClass(w))->
+ csb_class.set_color) (w, space, c1, c2, c3, c4, setSpace);
+}
+
+static void GetColor(
+ Widget w,
+ CSBColorSpace space,
+ float *c1, float *c2, float *c3, float *c4)
+{
+ ColorSelectionBoxWidget csb = (ColorSelectionBoxWidget) w;
+
+ switch (space) {
+ case CSBSpaceRGB:
+ *c1 = csb->csb.current_color.red;
+ *c2 = csb->csb.current_color.green;
+ *c3 = csb->csb.current_color.blue;
+ break;
+ case CSBSpaceCMYK:
+ *c1 = csb->csb.current_color.cyan;
+ *c2 = csb->csb.current_color.magenta;
+ *c3 = csb->csb.current_color.yellow;
+ *c4 = csb->csb.current_color.black;
+ break;
+ case CSBSpaceHSB:
+ *c1 = csb->csb.current_color.hue;
+ *c2 = csb->csb.current_color.saturation;
+ *c3 = csb->csb.current_color.brightness;
+ break;
+ case CSBSpaceGray:
+ *c1 = csb->csb.current_color.gray;
+ break;
+ }
+}
+
+void CSBGetColor(
+ Widget w,
+ CSBColorSpace space,
+ float *c1, float *c2, float *c3, float *c4)
+{
+ XtCheckSubclass(w, colorSelectionBoxWidgetClass, NULL);
+
+ (*((ColorSelectionBoxWidgetClass) XtClass(w))->
+ csb_class.get_color) (w, space, c1, c2, c3, c4);
+}
diff --git a/nx-X11/lib/dpstk/ColorSelect.ad b/nx-X11/lib/dpstk/ColorSelect.ad
new file mode 100644
index 000000000..8c3baa8c6
--- /dev/null
+++ b/nx-X11/lib/dpstk/ColorSelect.ad
@@ -0,0 +1,162 @@
+! ColorSelect
+!
+! (c) Copyright 1991-1994 Adobe Systems Incorporated.
+! All rights reserved.
+!
+! Permission to use, copy, modify, distribute, and sublicense this software
+! and its documentation for any purpose and without fee is hereby granted,
+! provided that the above copyright notices appear in all copies and that
+! both those copyright notices and this permission notice appear in
+! supporting documentation and that the name of Adobe Systems Incorporated
+! not be used in advertising or publicity pertaining to distribution of the
+! software without specific, written prior permission. No trademark license
+! to use the Adobe trademarks is hereby granted. If the Adobe trademark
+! "Display PostScript"(tm) is used to describe this software, its
+! functionality or for any other purpose, such use shall be limited to a
+! statement that this software works in conjunction with the Display
+! PostScript system. Proper trademark attribution to reflect Adobe's
+! ownership of the trademark shall be given whenever any such reference to
+! the Display PostScript system is made.
+!
+! ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
+! ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
+! ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+! IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+! NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
+! TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
+! DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
+! NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
+! CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
+! PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
+!
+! Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+! Incorporated which may be registered in certain jurisdictions
+!
+! Author: Adobe Systems Incorporated
+!
+! Resource file for Color Picker
+!
+! This resource file must be merged into the resource file for
+! any application that uses the Color Picker
+!
+!
+*ColorSelectionBox*fontList: -adobe-helvetica-bold-r-normal--*-120-*-*-*-*-iso8859-1
+*ColorSelectionBox*XmPushButton.marginLeft: 5
+*ColorSelectionBox*XmPushButton.marginRight: 5
+*ColorSelectionBox*XmScale.orientation: horizontal
+*ColorSelectionBox*XmScale.highlightThickness: 0
+
+*ColorSelectionBox*panel.width: 350
+*ColorSelectionBox*panel.height: 250
+
+*ColorSelectionBox*panel.horizontalSpacing: 5
+*ColorSelectionBox*panel.verticalSpacing: 5
+*ColorSelectionBox*panel.shadowThickness: 0
+
+*ColorSelectionBox*okButton.labelString: OK
+*ColorSelectionBox*applyButton.labelString: Apply
+*ColorSelectionBox*resetButton.labelString: Reset
+*ColorSelectionBox*cancelButton.labelString: Cancel
+
+*ColorSelectionBox*XmScale.topOffset: 8
+*ColorSelectionBox*slider2.leftOffset: 0
+*ColorSelectionBox*slider2.rightOffset: 0
+*ColorSelectionBox*slider3.leftOffset: 0
+*ColorSelectionBox*slider3.rightOffset: 0
+*ColorSelectionBox*slider4.leftOffset: 0
+*ColorSelectionBox*slider4.rightOffset: 0
+
+*ColorSelectionBox*displayX.labelString: X Rendering
+*ColorSelectionBox*displayDPS.labelString: DPS Rendering
+*ColorSelectionBox*displayBoth.labelString: Both
+
+*ColorSelectionBox*noBackgroundMessage.messageString: Unable to allocate solid color\n\
+for color patch. Patch can only be\n\
+displayed using DPS rendering.
+*ColorSelectionBox*noBackgroundMessage.dialogTitle: Color Picker Alert
+
+*ColorSelectionBox*rgb.labelString: RGB
+*ColorSelectionBox*cmyk.labelString: CMYK
+*ColorSelectionBox*hsb.labelString: HSB
+*ColorSelectionBox*gray.labelString: Gray
+
+*ColorSelectionBox*value1.rightPosition: 60
+*ColorSelectionBox*value2.rightOffset:0
+*ColorSelectionBox*value3.rightOffset:0
+*ColorSelectionBox*value4.rightOffset:0
+
+*ColorSelectionBox*label1.alignment: alignment_end
+*ColorSelectionBox*label2.alignment: alignment_end
+*ColorSelectionBox*label3.alignment: alignment_end
+*ColorSelectionBox*label4.alignment: alignment_end
+
+*ColorSelectionBox*value1.recomputeSize: false
+*ColorSelectionBox*value2.recomputeSize: false
+*ColorSelectionBox*value3.recomputeSize: false
+*ColorSelectionBox*value4.recomputeSize: false
+*ColorSelectionBox*value1.width: 20
+*ColorSelectionBox*value2.width: 20
+*ColorSelectionBox*value3.width: 20
+*ColorSelectionBox*value4.width: 20
+*ColorSelectionBox*value1.labelString: 0
+*ColorSelectionBox*value2.labelString: 0
+*ColorSelectionBox*value3.labelString: 0
+*ColorSelectionBox*value4.labelString: 0
+
+*ColorSelectionBox*displayOptionMenu.leftPosition: 60
+*ColorSelectionBox*displayOptionMenu.labelString:
+*ColorSelectionBox*modelOptionMenu.labelString:
+*ColorSelectionBox*modelOptionMenu.leftOffset: 10
+*ColorSelectionBox*paletteOptionMenu.labelString:
+*ColorSelectionBox*paletteOptionMenu.leftOffset: 10
+
+*ColorSelectionBox*eyedropButton.topOffset: -3
+*ColorSelectionBox*eyedropButton.labelType: pixmap
+*ColorSelectionBox*eyedropButton.marginLeft: 2
+*ColorSelectionBox*eyedropButton.marginRight: 2
+*ColorSelectionBox*paletteFrame.shadowType: shadow_in
+*ColorSelectionBox*palette.height: 15
+
+*ColorSelectionBox*dockFrame.leftOffset: 12
+*ColorSelectionBox*dockFrame.shadowType: shadow_in
+
+*ColorSelectionBox*dock.height: 30
+
+*ColorSelectionBox*patchFrame.leftOffset: 0
+*ColorSelectionBox*patchFrame.shadowType: shadow_in
+*ColorSelectionBox*patchFrame.bottomOffset: 0
+*ColorSelectionBox*patch.shadowThickness: 0
+
+*ColorSelectionBox*palette0Label: Full Spectrum
+*ColorSelectionBox*palette0Space: HSB
+*ColorSelectionBox*palette0ColorDependent: False
+*ColorSelectionBox*palette0Function: 1 1
+
+*ColorSelectionBox*palette1Label: NarrowSpectrum
+*ColorSelectionBox*palette1Space: HSB
+*ColorSelectionBox*palette1ColorDependent: True
+*ColorSelectionBox*palette1Function: .5 sub .3 mul \
+ 4 -1 roll add \
+ dup 0.0 lt {1.0 add} if \
+ dup 1.0 gt {1.0 sub} if \
+ 3 1 roll
+
+*ColorSelectionBox*palette2Label: Shades
+*ColorSelectionBox*palette2Space: HSB
+*ColorSelectionBox*palette2ColorDependent: True
+*ColorSelectionBox*palette2Function: exch pop
+
+*ColorSelectionBox*palette3Label: Pastels
+*ColorSelectionBox*palette3Space: HSB
+*ColorSelectionBox*palette3ColorDependent: True
+*ColorSelectionBox*palette3Function: 3 -1 roll pop exch
+
+*ColorSelectionBox*palette4Label:Black to White
+*ColorSelectionBox*palette4Space: HSB
+*ColorSelectionBox*palette4ColorDependent: True
+*ColorSelectionBox*palette4Function: dup .5 lt {2 mul 3 1 roll pop pop 1 exch} {.5 sub 2 mul 1 sub neg 3 1 roll pop pop 1} ifelse
+
+*ColorSelectionBox*palette5Label: Grays
+*ColorSelectionBox*palette5Space: Gray
+*ColorSelectionBox*palette5ColorDependent: False
+*ColorSelectionBox*palette5Function:
diff --git a/nx-X11/lib/dpstk/DPSScrollW.c b/nx-X11/lib/dpstk/DPSScrollW.c
new file mode 100644
index 000000000..9c2f7e005
--- /dev/null
+++ b/nx-X11/lib/dpstk/DPSScrollW.c
@@ -0,0 +1,3500 @@
+ /*
+ * DPSScrollW.c
+ *
+ * (c) Copyright 1993-1994 Adobe Systems Incorporated.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sublicense this software
+ * and its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notices appear in all copies and that
+ * both those copyright notices and this permission notice appear in
+ * supporting documentation and that the name of Adobe Systems Incorporated
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. No trademark license
+ * to use the Adobe trademarks is hereby granted. If the Adobe trademark
+ * "Display PostScript"(tm) is used to describe this software, its
+ * functionality or for any other purpose, such use shall be limited to a
+ * statement that this software works in conjunction with the Display
+ * PostScript system. Proper trademark attribution to reflect Adobe's
+ * ownership of the trademark shall be given whenever any such reference to
+ * the Display PostScript system is made.
+ *
+ * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
+ * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
+ * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
+ * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
+ * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
+ *
+ * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+ * Incorporated which may be registered in certain jurisdictions
+ *
+ * Author: Adobe Systems Incorporated
+ */
+/* $XFree86$ */
+
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <X11/ShellP.h>
+#include <X11/Xproto.h>
+#include <stdlib.h>
+#include <Xm/Xm.h>
+
+/* There are no words to describe how I feel about having to do this */
+
+#if XmVersion > 1001
+#include <Xm/ManagerP.h>
+#else
+#include <Xm/XmP.h>
+#endif
+
+#include <Xm/DrawingA.h>
+#include <Xm/ScrolledW.h>
+#include <Xm/ScrollBar.h>
+
+#include <DPS/dpsXclient.h>
+#include "dpsXcommonI.h"
+#include <DPS/dpsXshare.h>
+#include "DSWwraps.h"
+#include <stdio.h>
+#include <DPS/DPSScrollWP.h>
+
+#undef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#undef MAX
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#undef ABS
+#define ABS(x) ((x) >= 0 ? (x) : -(x))
+#undef CEIL
+#define CEIL(x) ((int) ((float)((int)(x)) == (x) ? (x) : (x) + 1))
+
+/* Define macros to get rectangle entries. All rectangles are stored as
+ x, y, width, height. NOTE: ONLY FOR USER SPACE RECTANGLES, NOT X
+ RECTANGLES!!!! */
+
+#define LEFT(r) ((r)[0])
+#define RIGHT(r) ((r)[0] + (r)[2])
+#define BOTTOM(r) ((r)[1])
+#define TOP(r) ((r)[1] + (r)[3])
+#define WIDTH(r) ((r)[2])
+#define HEIGHT(r) ((r)[3])
+
+/* This is used in converting bounding boxes into user space to ensure
+ that we don't end up slopping over into another pixel */
+
+#define DELTA .001
+
+#define Offset(field) XtOffsetOf(DPSScrolledWindowRec, sw.field)
+
+static float initScale = 1.0;
+
+static XtResource resources[] = {
+ {XtNcontext, XtCContext, XtRDPSContext, sizeof(DPSContext),
+ Offset(context), XtRImmediate, (XtPointer) NULL},
+ {XtNareaWidth, XtCAreaWidth, XtRInt, sizeof(int),
+ Offset(area_width), XtRImmediate, (XtPointer) ((int) (8.5*72))},
+ {XtNareaHeight, XtCAreaHeight, XtRInt, sizeof(int),
+ Offset(area_height), XtRImmediate, (XtPointer) (11*72)},
+ {XtNscale, XtCScale, XtRFloat, sizeof(float),
+ Offset(scale), XtRFloat, (XtPointer) &initScale},
+ {XtNctm, XtCCtm, XtRFloatArray, sizeof(float *),
+ Offset(ctm_ptr), XtRImmediate, (XtPointer) NULL},
+ {XtNinvCtm, XtCInvCtm, XtRFloatArray, sizeof(float *),
+ Offset(inv_ctm_ptr), XtRImmediate, (XtPointer) NULL},
+ {XtNuseBackingPixmap, XtCUseBackingPixmap, XtRBoolean, sizeof(Boolean),
+ Offset(use_backing_pixmap), XtRImmediate, (XtPointer) True},
+ {XtNuseFeedbackPixmap, XtCUseFeedbackPixmap, XtRBoolean, sizeof(Boolean),
+ Offset(use_feedback_pixmap), XtRImmediate, (XtPointer) True},
+ {XtNbackingPixmap, XtCBackingPixmap, XtRPixmap, sizeof(Pixmap),
+ Offset(backing_pixmap), XtRImmediate, (XtPointer) None},
+ {XtNfeedbackPixmap, XtCFeedbackPixmap, XtRPixmap, sizeof(Pixmap),
+ Offset(feedback_pixmap), XtRImmediate, (XtPointer) None},
+ {XtNdocumentSizePixmaps, XtCDocumentSizePixmaps,
+ XtRBoolean, sizeof(Boolean),
+ Offset(document_size_pixmaps), XtRImmediate, (XtPointer) False},
+ {XtNwindowGState, XtCWindowGState, XtRDPSGState, sizeof(DPSGState),
+ Offset(window_gstate), XtRImmediate, (XtPointer) 0},
+ {XtNbackingGState, XtCBackingGState, XtRDPSGState, sizeof(DPSGState),
+ Offset(backing_gstate), XtRImmediate, (XtPointer) 0},
+ {XtNfeedbackGState, XtCFeedbackGState, XtRDPSGState, sizeof(DPSGState),
+ Offset(feedback_gstate), XtRImmediate, (XtPointer) 0},
+ {XtNdirtyAreas, XtCDirtyAreas, XtRFloatArray, sizeof(float *),
+ Offset(dirty_areas), XtRImmediate, (XtPointer) NULL},
+ {XtNnumDirtyAreas, XtCNumDirtyAreas, XtRShort, sizeof(short),
+ Offset(num_dirty_areas), XtRImmediate, (XtPointer) 0},
+ {XtNpixmapLimit, XtCPixmapLimit, XtRInt, sizeof(int),
+ Offset(pixmap_limit), XtRImmediate, (XtPointer) -1},
+ {XtNabsolutePixmapLimit, XtCAbsolutePixmapLimit, XtRInt, sizeof(int),
+ Offset(absolute_pixmap_limit), XtRImmediate, (XtPointer) 0},
+ {XtNwatchProgress, XtCWatchProgress, XtRBoolean, sizeof(Boolean),
+ Offset(watch_progress), XtRImmediate, (XtPointer) False},
+ {XtNwatchProgressDelay, XtCWatchProgressDelay, XtRInt, sizeof(int),
+ Offset(watch_progress_delay), XtRImmediate, (XtPointer) 1000},
+ {XtNminimalDrawing, XtCMinimalDrawing, XtRBoolean, sizeof(Boolean),
+ Offset(minimal_drawing), XtRImmediate, (XtPointer) False},
+ {XtNapplicationScrolling, XtCApplicationScrolling,
+ XtRBoolean, sizeof(Boolean),
+ Offset(application_scrolling), XtRImmediate, (XtPointer) False},
+ {XtNsetupCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
+ Offset(setup_callback), XtRCallback, (XtPointer) NULL},
+ {XtNexposeCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
+ Offset(expose_callback), XtRCallback, (XtPointer) NULL},
+ {XtNbackgroundCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
+ Offset(background_callback), XtRCallback, (XtPointer) NULL},
+ {XtNfeedbackCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
+ Offset(feedback_callback), XtRCallback, (XtPointer) NULL},
+ {XtNresizeCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
+ Offset(resize_callback), XtRCallback, (XtPointer) NULL},
+};
+
+static Boolean GiveFeedbackPixmap(Widget w, Pixmap p, int width, int height, int depth, Screen *screen);
+static Boolean SetValues(Widget old, Widget req, Widget new, ArgList args, Cardinal *num_args);
+static Boolean TakeFeedbackPixmap(Widget w, Pixmap *p, int *width, int *height, int *depth, Screen **screen);
+static XtGeometryResult GeometryManager(Widget w, XtWidgetGeometry *desired, XtWidgetGeometry *allowed);
+static XtGeometryResult QueryGeometry(Widget w, XtWidgetGeometry *desired, XtWidgetGeometry *allowed);
+static void AbortPendingDrawing(Widget w);
+static void AddExposureToPending(DPSScrolledWindowWidget dsw, XExposeEvent *ev);
+static void AddRectsToDirtyArea(DPSScrolledWindowWidget dsw, float *newRect, int n);
+static void AddRectsToPending(DPSScrolledWindowWidget dsw, int *newRect, int n);
+static void AddToDirtyArea(Widget w, float *rect, long n);
+static void AddUserSpaceRectsToPending(DPSScrolledWindowWidget dsw, float *newRect, int n);
+static void CallFeedbackCallback(DPSScrolledWindowWidget dsw, float *r, int n);
+static void CheckFeedbackPixmap(DPSScrolledWindowWidget dsw);
+static void ClassPartInitialize(WidgetClass widget_class);
+static void ConvertPSToX(Widget w, double psX, double psY, int *xX, int *xY);
+static void ConvertToOrigPS(DPSScrolledWindowWidget dsw, int xX, int xY, float *psX, float *psY);
+static void ConvertToPS(DPSScrolledWindowWidget dsw, float xX, float xY, float *psX, float *psY);
+static void ConvertToX(DPSScrolledWindowWidget dsw, float psX, float psY, int *xX, int *xY);
+static void ConvertXToPS(Widget w, long xX, long xY, float *psX, float *psY);
+static void CopyRectsToCurrentDrawing(DPSScrolledWindowWidget dsw, float *newRect, int n);
+static void CopyRectsToDirtyArea(DPSScrolledWindowWidget dsw, float *newRect, int n);
+static void CopyToFeedbackPixmap(DPSScrolledWindowWidget dsw, float *rects, int n);
+static void Destroy(Widget widget);
+static void DrawingAreaExpose(Widget w, XtPointer clientData, XtPointer callData);
+static void DrawingAreaGraphicsExpose(Widget w, XtPointer clientData, XEvent *event, Boolean *goOn);
+static void EndFeedbackDrawing(Widget w, int restore);
+static void FinishDrawing(DPSScrolledWindowWidget dsw);
+static void FinishPendingDrawing(Widget w);
+static void GetDrawingInfo(Widget w, DSWDrawableType *type, Drawable *drawable, DPSGState *gstate, DPSContext *context);
+static void GetScrollInfo(Widget w, int *h_value, int *h_size, int *h_max, int *v_value, int *v_size, int *v_max);
+static void HScrollCallback(Widget w, XtPointer clientData, XtPointer callData);
+static void Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args);
+static void Realize(Widget w, XtValueMask *mask, XSetWindowAttributes *attr);
+static void Resize(Widget w);
+static void ScrollBy(Widget w, long dx, long dy);
+static void ScrollMoved(DPSScrolledWindowWidget dsw);
+static void ScrollPoint(Widget w, double psX, double psY, long xX, long xY);
+static void ScrollTo(Widget w, long x, long y);
+static void SetFeedbackDirtyArea(Widget w, float *rects, int count, XtPointer continue_feedback_data);
+static void SetScale(Widget w, double scale, long fixedX, long fixedY);
+static void SetScaleAndScroll(Widget w, double scale, double psX, double psY, long xX, long xY);
+static void StartFeedbackDrawing(Widget w, XtPointer start_feedback_data);
+static void UpdateDrawing(Widget w, float *rects, int count);
+static void VScrollCallback(Widget w, XtPointer clientData, XtPointer callData);
+
+DPSScrolledWindowClassRec dpsScrolledWindowClassRec = {
+ /* Core class part */
+ {
+ /* superclass */ (WidgetClass) &xmManagerClassRec,
+ /* class_name */ "DPSScrolledWindow",
+ /* widget_size */ sizeof(DPSScrolledWindowRec),
+ /* class_initialize */ NULL,
+ /* class_part_initialize */ ClassPartInitialize,
+ /* class_inited */ False,
+ /* initialize */ Initialize,
+ /* initialize_hook */ NULL,
+ /* realize */ Realize,
+ /* actions */ NULL,
+ /* num_actions */ 0,
+ /* resources */ resources,
+ /* num_resources */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ True,
+ /* compress_exposure */ XtExposeCompressMultiple,
+ /* compress_enterleave */ True,
+ /* visible_interest */ False,
+ /* destroy */ Destroy,
+ /* resize */ Resize,
+ /* expose */ NULL,
+ /* set_values */ SetValues,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* callback offsets */ NULL,
+ /* tm_table */ NULL,
+ /* query_geometry */ QueryGeometry,
+ /* display_accelerator */ NULL,
+ /* extension */ NULL,
+ },
+ /* Composite class part */
+ {
+ /* geometry_manager */ GeometryManager,
+ /* change_managed */ NULL,
+ /* insert_child */ XtInheritInsertChild,
+ /* delete_child */ XtInheritDeleteChild,
+ /* extension */ NULL,
+ },
+ /* Constraint class part */
+ {
+ /* resources */ NULL,
+ /* num_resources */ 0,
+ /* constraint_size */ 0,
+ /* initialize */ NULL,
+ /* destroy */ NULL,
+ /* set_values */ NULL,
+ /* extension */ NULL,
+ },
+ /* Manager class part */
+ {
+ /* translations */ XtInheritTranslations,
+ /* syn_resources */ NULL,
+ /* num_syn_resources */ 0,
+ /* syn_constraint_resources */ NULL,
+ /* num_syn_constraint_resources */ 0,
+ /* parent_process */ XmInheritParentProcess,
+ /* extension */ NULL,
+ },
+ /* DPSScrolledWindow class part */
+ {
+ /* set_scale */ SetScale,
+ /* scroll_point */ ScrollPoint,
+ /* scroll_by */ ScrollBy,
+ /* scroll_to */ ScrollTo,
+ /* set_scale_and_scroll */ SetScaleAndScroll,
+ /* convert_x_to_ps */ ConvertXToPS,
+ /* convert_ps_to_x */ ConvertPSToX,
+ /* add_to_dirty_area */ AddToDirtyArea,
+ /* take_feedback_pixmap */ TakeFeedbackPixmap,
+ /* give_feedback_pixmap */ GiveFeedbackPixmap,
+ /* start_feedback_drawing */ StartFeedbackDrawing,
+ /* end_feedback_drawing */ EndFeedbackDrawing,
+ /* set_feedback_dirty_area */ SetFeedbackDirtyArea,
+ /* finish_pending_drawing */ FinishPendingDrawing,
+ /* abort_pending_drawing */ AbortPendingDrawing,
+ /* get_drawing_info */ GetDrawingInfo,
+ /* update_drawing */ UpdateDrawing,
+ /* get_scroll_info */ GetScrollInfo,
+ /* extension */ NULL,
+ }
+};
+
+WidgetClass dpsScrolledWindowWidgetClass =
+ (WidgetClass) &dpsScrolledWindowClassRec;
+
+/***** UTILITY FUNCTIONS *****/
+
+static void PrintRectList(float *r, short num_r)
+{
+ int i;
+
+ for (i = 0; i < num_r; i++) {
+ printf("Rectangle %d: ", i);
+ printf("X %g Y %g W %g H %g\n", r[0], r[1], r[2], r[3]);
+ r += 4;
+ }
+}
+
+/* Make sure the list pointed to by r can hold n more rectangles. Always
+ grow by at least min_grow */
+
+static void GrowRectList(
+ float **r,
+ short *r_size,
+ short num_r,
+ int n, int min_grow)
+{
+ if (*r_size < num_r + n) {
+ if (min_grow > 1 && num_r + n - *r_size < min_grow) {
+ *r_size += min_grow;
+ } else *r_size = num_r + n;
+ *r = (float *) XtRealloc((char *) *r, *r_size * 4 * sizeof(float));
+ }
+}
+
+static void GrowIntRectList(
+ int **r,
+ short *r_size,
+ short num_r,
+ int n, int min_grow)
+{
+ if (*r_size < num_r + n) {
+ if (min_grow > 1 && num_r + n - *r_size < min_grow) {
+ *r_size += min_grow;
+ } else *r_size = num_r + n;
+ *r = (int *) XtRealloc((char *) *r, *r_size * 4 * sizeof(int));
+ }
+}
+
+static Boolean Intersects(float *r1, float *r2)
+{
+ if (RIGHT(r1) <= LEFT(r2)) return False;
+ if (RIGHT(r2) <= LEFT(r1)) return False;
+ if (TOP(r1) <= BOTTOM(r2)) return False;
+ if (TOP(r2) <= BOTTOM(r1)) return False;
+
+ return True;
+}
+
+/* Subtract sub from src, putting result into dst. Return rectangle count */
+
+static int Subtract(float *src, float *sub, float *dst)
+{
+ int n = 0;
+
+ /* If bottom of sub is greater than bottom of src, there's a
+ rectangle across the bottom */
+ if (BOTTOM(sub) > BOTTOM(src)) {
+ LEFT(dst) = LEFT(src);
+ BOTTOM(dst) = BOTTOM(src);
+ WIDTH(dst) = WIDTH(src);
+ HEIGHT(dst) = BOTTOM(sub) - BOTTOM(src);
+ n++;
+ dst += 4;
+ }
+
+ /* If left of sub is greater than left of src, there's a left rectangle. */
+ if (LEFT(sub) > LEFT(src)) {
+ LEFT(dst) = LEFT(src);
+ BOTTOM(dst) = MAX(BOTTOM(src), BOTTOM(sub));
+ WIDTH(dst) = LEFT(sub) - LEFT(src);
+ HEIGHT(dst) = MIN(TOP(src), TOP(sub)) - BOTTOM(dst);
+ n++;
+ dst += 4;
+ }
+
+ /* If right of sub is less than right of src, there's a right rect */
+ if (RIGHT(sub) < RIGHT(src)) {
+ LEFT(dst) = RIGHT(sub);
+ BOTTOM(dst) = MAX(BOTTOM(src), BOTTOM(sub));
+ WIDTH(dst) = RIGHT(src) - RIGHT(sub);
+ HEIGHT(dst) = MIN(TOP(src), TOP(sub)) - BOTTOM(dst);
+ n++;
+ dst += 4;
+ }
+
+ /* If top of sub is less than top of src, there's a top rectangle */
+ if (TOP(sub) < TOP(src)) {
+ LEFT(dst) = LEFT(src);
+ BOTTOM(dst) = TOP(sub);
+ WIDTH(dst) = WIDTH(src);
+ HEIGHT(dst) = TOP(src) - TOP(sub);
+ n++;
+ dst += 4;
+ }
+
+ return n;
+}
+
+static void Copy(float *src, float *dst)
+{
+ LEFT(dst) = LEFT(src);
+ BOTTOM(dst) = BOTTOM(src);
+ WIDTH(dst) = WIDTH(src);
+ HEIGHT(dst) = HEIGHT(src);
+}
+
+static void Intersection(float *r1, float *r2, float *dst)
+{
+ LEFT(dst) = MAX(LEFT(r1), LEFT(r2));
+ BOTTOM(dst) = MAX(BOTTOM(r1), BOTTOM(r2));
+ WIDTH(dst) = MIN(RIGHT(r1), RIGHT(r2)) - LEFT(dst);
+ HEIGHT(dst) = MIN(TOP(r1), TOP(r2)) - BOTTOM(dst);
+}
+
+/* These are used by the SubtractRects and IntersectRects procedures */
+
+static float *rbuf = NULL;
+static short rbuf_size = 0;
+#define GROW_BUF 10
+
+/* Replace the rectangle list in src with src minus sub */
+
+static void SubtractRects(
+ float **src,
+ short *src_size,
+ short *num_src,
+ float *sub,
+ int num_sub)
+{
+ short num_rbuf;
+ float *r;
+ int i;
+
+ /* Go through, subtracting the first sub rectangle from each src
+ rectangle. Put the result in the internal buffer, then copy this
+ list to the src. Repeat for each sub rectangle. */
+
+ while (num_sub > 0) {
+ num_rbuf = 0;
+ for (r = *src, i = 0; i < *num_src; r += 4, i++) {
+ if (Intersects(r, sub)) {
+ /* Subtract sub from r, putting result into rbuf. First
+ make sure there are at least 4 spaces in the buffer */
+ GrowRectList(&rbuf, &rbuf_size, num_rbuf, 4, GROW_BUF);
+
+ /* Do the subtraction */
+ num_rbuf += Subtract(r, sub, rbuf + (num_rbuf*4));
+ } else {
+ /* Copy r into buffer */
+ GrowRectList(&rbuf, &rbuf_size, num_rbuf, 1, GROW_BUF);
+ Copy(r, rbuf + (num_rbuf*4));
+ num_rbuf++;
+ }
+ }
+
+ /* Copy buffered rectangles back into src */
+ GrowRectList(src, src_size, 0, num_rbuf, 1);
+ for (i = 0; i < num_rbuf * 4; i++) (*src)[i] = rbuf[i];
+ *num_src = num_rbuf;
+
+ /* Check if we've taken everything away */
+ if (*num_src == 0) return;
+
+ /* Skip on to the next sub rectangle */
+ num_sub--;
+ sub += 4;
+ }
+}
+
+/* Replace list r1 with the intersection of r1 and r2 */
+
+static void IntersectRects(
+ float **r1,
+ short *r1_size,
+ short *num_r1,
+ float *r2,
+ int num_r2)
+{
+ short num_rbuf = 0;
+ float *r;
+ int i;
+
+ /* Fairly straightforward. Intersect each rectangle in r1 with each
+ rectangle in r2, then copy the results to r1 */
+
+ while (num_r2 > 0) {
+ for (r = *r1, i = 0; i < *num_r1; r += 4, i++) {
+ if (Intersects(r, r2)) {
+ GrowRectList(&rbuf, &rbuf_size, num_rbuf, 1, GROW_BUF);
+ Intersection(r, r2, rbuf + (num_rbuf*4));
+ num_rbuf++;
+ }
+ }
+ num_r2--;
+ r2 += 4;
+ }
+
+ /* Copy intersection rectangles back into r1 */
+ GrowRectList(r1, r1_size, 0, num_rbuf, 1);
+ for (i = 0; i < num_rbuf * 4; i++) (*r1)[i] = rbuf[i];
+ *num_r1 = num_rbuf;
+}
+
+static void SimplifyRects(float *rect, short *num)
+{
+ int i, j, k;
+ float *r, *r1;
+
+ i = 0;
+ while (i < *num) {
+ r = rect + (i * 4);
+ if (WIDTH(r) == 0 || HEIGHT(r) == 0) {
+ for (k = 4*(i+1); k < *num * 4; k++) rect[k-4] = rect[k];
+ (*num)--;
+ goto LOOPEND;
+ }
+ j = i+1;
+ while (j < *num) {
+ r1 = rect + (j * 4);
+ if (TOP(r1) <= TOP(r) && BOTTOM(r1) >= BOTTOM(r) &&
+ LEFT(r1) >= LEFT(r) && RIGHT(r1) <= RIGHT(r)) {
+ for (k = 4*(j+1); k < *num * 4; k++) rect[k-4] = rect[k];
+ (*num)--;
+ } else if (TOP(r) <= TOP(r1) && BOTTOM(r) >= BOTTOM(r1) &&
+ LEFT(r) >= LEFT(r1) && RIGHT(r) <= RIGHT(r1)) {
+ for (k = 4*(i+1); k < *num * 4; k++) rect[k-4] = rect[k];
+ (*num)--;
+ goto LOOPEND;
+ } else j++;
+ }
+ i++;
+LOOPEND:;
+ }
+}
+
+static void ComputeOffsets(DPSScrolledWindowWidget dsw, int *dx, int *dy)
+{
+ if (dsw->sw.doing_feedback && dsw->sw.feedback_pixmap != None) {
+ *dx = *dy = 0;
+ } else {
+ if (dsw->sw.pixmap_width == dsw->sw.drawing_area->core.width) *dx = 0;
+ else *dx = -dsw->sw.origin_x;
+ if (dsw->sw.pixmap_height == dsw->sw.drawing_area->core.height) *dy = 0;
+ else *dy = CEIL(dsw->sw.drawing_height) - dsw->sw.origin_y;
+ }
+}
+
+static void ClassPartInitialize(WidgetClass widget_class)
+{
+ register DPSScrolledWindowWidgetClass wc =
+ (DPSScrolledWindowWidgetClass) widget_class;
+ DPSScrolledWindowWidgetClass super =
+ (DPSScrolledWindowWidgetClass) wc->core_class.superclass;
+
+ if (wc->sw_class.set_scale == InheritSetScale) {
+ wc->sw_class.set_scale = super->sw_class.set_scale;
+ }
+ if (wc->sw_class.scroll_point == InheritScrollPoint) {
+ wc->sw_class.scroll_point = super->sw_class.scroll_point;
+ }
+ if (wc->sw_class.scroll_by == InheritScrollBy) {
+ wc->sw_class.scroll_by = super->sw_class.scroll_by;
+ }
+ if (wc->sw_class.scroll_to == InheritScrollTo) {
+ wc->sw_class.scroll_to = super->sw_class.scroll_to;
+ }
+ if (wc->sw_class.set_scale_and_scroll == InheritSetScaleAndScroll) {
+ wc->sw_class.set_scale_and_scroll =
+ super->sw_class.set_scale_and_scroll;
+ }
+ if (wc->sw_class.convert_x_to_ps == InheritConvertXToPS) {
+ wc->sw_class.convert_x_to_ps = super->sw_class.convert_x_to_ps;
+ }
+ if (wc->sw_class.convert_ps_to_x == InheritConvertPSToX) {
+ wc->sw_class.convert_ps_to_x = super->sw_class.convert_ps_to_x;
+ }
+ if (wc->sw_class.add_to_dirty_area == InheritAddToDirtyArea) {
+ wc->sw_class.add_to_dirty_area = super->sw_class.add_to_dirty_area;
+ }
+ if (wc->sw_class.take_feedback_pixmap == InheritTakeFeedbackPixmap) {
+ wc->sw_class.take_feedback_pixmap =
+ super->sw_class.take_feedback_pixmap;
+ }
+ if (wc->sw_class.give_feedback_pixmap == InheritGiveFeedbackPixmap) {
+ wc->sw_class.give_feedback_pixmap =
+ super->sw_class.give_feedback_pixmap;
+ }
+ if (wc->sw_class.start_feedback_drawing == InheritStartFeedbackDrawing) {
+ wc->sw_class.start_feedback_drawing =
+ super->sw_class.start_feedback_drawing;
+ }
+ if (wc->sw_class.end_feedback_drawing == InheritEndFeedbackDrawing) {
+ wc->sw_class.end_feedback_drawing =
+ super->sw_class.end_feedback_drawing;
+ }
+ if (wc->sw_class.set_feedback_dirty_area == InheritSetFeedbackDirtyArea) {
+ wc->sw_class.set_feedback_dirty_area =
+ super->sw_class.set_feedback_dirty_area;
+ }
+ if (wc->sw_class.finish_pending_drawing == InheritFinishPendingDrawing) {
+ wc->sw_class.finish_pending_drawing =
+ super->sw_class.finish_pending_drawing;
+ }
+ if (wc->sw_class.abort_pending_drawing == InheritAbortPendingDrawing) {
+ wc->sw_class.abort_pending_drawing =
+ super->sw_class.abort_pending_drawing;
+ }
+ if (wc->sw_class.get_drawing_info == InheritGetDrawingInfo) {
+ wc->sw_class.get_drawing_info = super->sw_class.get_drawing_info;
+ }
+ if (wc->sw_class.update_drawing == InheritUpdateDrawing) {
+ wc->sw_class.update_drawing = super->sw_class.update_drawing;
+ }
+ if (wc->sw_class.get_scroll_info == InheritGetScrollInfo) {
+ wc->sw_class.get_scroll_info = super->sw_class.get_scroll_info;
+ }
+}
+
+static void CreateChildren(DPSScrolledWindowWidget dsw)
+{
+ Widget w;
+
+ w = dsw->sw.scrolled_window =
+ XtVaCreateManagedWidget("scrolledWindow",
+ xmScrolledWindowWidgetClass,
+ (Widget) dsw,
+ XtNwidth, dsw->core.width,
+ XtNheight, dsw->core.height,
+ XmNscrollingPolicy, XmAPPLICATION_DEFINED,
+ NULL);
+
+ dsw->sw.h_scroll =
+ XtVaCreateManagedWidget("horizontalScrollBar",
+ xmScrollBarWidgetClass, w,
+ XmNorientation, XmHORIZONTAL,
+ NULL);
+ XtAddCallback(dsw->sw.h_scroll, XmNvalueChangedCallback, HScrollCallback,
+ (XtPointer) dsw);
+ XtAddCallback(dsw->sw.h_scroll, XmNdragCallback, HScrollCallback,
+ (XtPointer) dsw);
+
+ dsw->sw.v_scroll =
+ XtVaCreateManagedWidget("verticalScrollBar",
+ xmScrollBarWidgetClass, w,
+ XmNorientation, XmVERTICAL,
+ NULL);
+ XtAddCallback(dsw->sw.v_scroll, XmNvalueChangedCallback, VScrollCallback,
+ (XtPointer) dsw);
+ XtAddCallback(dsw->sw.v_scroll, XmNdragCallback, VScrollCallback,
+ (XtPointer) dsw);
+
+
+ dsw->sw.drawing_area =
+ XtVaCreateManagedWidget("drawingArea",
+ xmDrawingAreaWidgetClass, w, NULL);
+ XtAddCallback(dsw->sw.drawing_area, XtNexposeCallback, DrawingAreaExpose,
+ (XtPointer) dsw);
+ XtAddRawEventHandler(dsw->sw.drawing_area, 0, True,
+ DrawingAreaGraphicsExpose, (XtPointer) dsw);
+
+ XmScrolledWindowSetAreas(w, dsw->sw.h_scroll, dsw->sw.v_scroll,
+ dsw->sw.drawing_area);
+}
+
+/* ARGSUSED */
+
+static void Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) new;
+ XGCValues gcVal;
+ Bool inited;
+
+ if (dsw->sw.area_width <= 0) dsw->sw.area_width = 8.5*72;
+ if (dsw->sw.area_height <= 0) dsw->sw.area_height = 11*72;
+ if (dsw->sw.scale <= 0) dsw->sw.scale = 1.0;
+ dsw->sw.ctm_ptr = dsw->sw.ctm;
+ dsw->sw.inv_ctm_ptr = dsw->sw.inv_ctm;
+ dsw->sw.backing_pixmap = None;
+ dsw->sw.feedback_pixmap = None;
+ dsw->sw.window_gstate = 0;
+ dsw->sw.backing_gstate = 0;
+ dsw->sw.feedback_gstate = 0;
+ dsw->sw.scrolling = False;
+ dsw->sw.num_pending_expose = dsw->sw.pending_expose_size = 0;
+ dsw->sw.pending_expose = NULL;
+ dsw->sw.num_pending_dirty = dsw->sw.pending_dirty_size = 0;
+ dsw->sw.pending_dirty = NULL;
+ dsw->sw.num_current_drawing = dsw->sw.current_drawing_size = 0;
+ dsw->sw.current_drawing = NULL;
+ dsw->sw.num_prev_dirty_areas = dsw->sw.prev_dirty_areas_size = 0;
+ dsw->sw.prev_dirty_areas = NULL;
+ dsw->sw.drawing_stage = DSWStart;
+ dsw->sw.work = 0;
+ dsw->sw.big_pixmap = False;
+
+ /* Set the initial dirty area to everything */
+
+ dsw->sw.dirty_areas_size = 0;
+ dsw->sw.dirty_areas = NULL;
+
+ GrowRectList(&dsw->sw.dirty_areas, &dsw->sw.dirty_areas_size, 0, 1, 1);
+ dsw->sw.num_dirty_areas = 1;
+ LEFT(dsw->sw.dirty_areas) = 0.0;
+ BOTTOM(dsw->sw.dirty_areas) = 0.0;
+ WIDTH(dsw->sw.dirty_areas) = dsw->sw.area_width;
+ HEIGHT(dsw->sw.dirty_areas) = dsw->sw.area_height;
+
+ /* Make the scratch list have at least one element */
+
+ dsw->sw.num_scratch = dsw->sw.scratch_size = 0;
+ dsw->sw.scratch = NULL;
+ GrowRectList(&dsw->sw.scratch, &dsw->sw.scratch_size, 0, 1, 1);
+
+ /* Get the context */
+
+ if (dsw->sw.context == NULL) {
+ dsw->sw.context = XDPSGetSharedContext(XtDisplay(dsw));
+ }
+
+ /* Watch progress only works with pass-through event dispatching */
+
+ if (dsw->sw.watch_progress &&
+ XDPSSetEventDelivery(XtDisplay(dsw), dps_event_query) !=
+ dps_event_pass_through) dsw->sw.watch_progress = False;
+
+ if (_XDPSTestComponentInitialized(dsw->sw.context,
+ dps_init_bit_dsw, &inited) ==
+ dps_status_unregistered_context) {
+ XDPSRegisterContext(dsw->sw.context, False);
+ }
+
+ dsw->sw.use_saved_scroll = False;
+ dsw->sw.context_inited = False;
+ dsw->sw.doing_feedback = False;
+ dsw->sw.feedback_displayed = False;
+
+ CreateChildren(dsw);
+
+ dsw->sw.ge_gc = XtGetGC(dsw->sw.drawing_area, 0, (XGCValues *) NULL);
+
+ gcVal.graphics_exposures = False;
+ dsw->sw.no_ge_gc = XtGetGC(dsw->sw.drawing_area, GCGraphicsExposures,
+ &gcVal);
+}
+
+static void Destroy(Widget widget)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) widget;
+
+ if (dsw->sw.backing_pixmap != None) {
+ XFreePixmap(XtDisplay(dsw), dsw->sw.backing_pixmap);
+ }
+ if (dsw->sw.feedback_pixmap != None) {
+ XFreePixmap(XtDisplay(dsw), dsw->sw.feedback_pixmap);
+ }
+
+ if (dsw->sw.window_gstate != 0) {
+ XDPSFreeContextGState(dsw->sw.context, dsw->sw.window_gstate);
+ }
+ if (dsw->sw.backing_gstate != 0) {
+ XDPSFreeContextGState(dsw->sw.context, dsw->sw.backing_gstate);
+ }
+ if (dsw->sw.feedback_gstate != 0) {
+ XDPSFreeContextGState(dsw->sw.context, dsw->sw.feedback_gstate);
+ }
+
+ if (dsw->sw.pending_expose != NULL) {
+ XtFree((char *) dsw->sw.pending_expose);
+ }
+ if (dsw->sw.current_drawing != NULL) {
+ XtFree((char *) dsw->sw.current_drawing);
+ }
+ if (dsw->sw.prev_dirty_areas != NULL) {
+ XtFree((char *) dsw->sw.prev_dirty_areas);
+ }
+ if (dsw->sw.dirty_areas != NULL) XtFree((char *) dsw->sw.dirty_areas);
+ if (dsw->sw.pending_dirty != NULL) XtFree((char *) dsw->sw.pending_dirty);
+ if (dsw->sw.scratch != NULL) XtFree((char *) dsw->sw.scratch);
+
+ XtReleaseGC(widget, dsw->sw.ge_gc);
+ XtReleaseGC(widget, dsw->sw.no_ge_gc);
+}
+
+static void SetOriginAndGetTransform(DPSScrolledWindowWidget dsw)
+{
+ float psX, psY;
+
+ ConvertToOrigPS(dsw, dsw->sw.origin_x, dsw->sw.origin_y, &psX, &psY);
+ _DPSSWSetMatrixAndGetTransform(dsw->sw.context, psX, psY, dsw->sw.scale,
+ dsw->sw.origin_x, dsw->sw.origin_y,
+ dsw->sw.ctm, dsw->sw.inv_ctm,
+ &dsw->sw.x_offset, &dsw->sw.y_offset);
+}
+
+static void SetPixmapOrigin(DPSScrolledWindowWidget dsw)
+{
+ float psX, psY;
+
+ ConvertToOrigPS(dsw, dsw->sw.origin_x, dsw->sw.origin_y, &psX, &psY);
+ _DPSSWSetMatrix(dsw->sw.context, psX, psY, dsw->sw.scale,
+ dsw->sw.origin_x, dsw->sw.origin_y);
+}
+
+static void SetPixmapOffset(DPSScrolledWindowWidget dsw)
+{
+ int ox, oy;
+
+ if (dsw->sw.pixmap_width <= (int) dsw->sw.drawing_area->core.width) ox = 0;
+ else ox = -dsw->sw.origin_x;
+ if (dsw->sw.pixmap_height <= (int) dsw->sw.drawing_area->core.height) {
+ oy = dsw->sw.drawing_area->core.height;
+ } else oy = dsw->sw.pixmap_height - dsw->sw.origin_y +
+ dsw->sw.drawing_area->core.height;
+
+ DPSsetXoffset(dsw->sw.context, ox, oy);
+}
+
+static Boolean pixmapError;
+static int (*oldHandler)(Display *, XErrorEvent *);
+
+static int PixmapHandler(Display *dpy, XErrorEvent *error)
+{
+ if (error->error_code == BadAlloc &&
+ error->request_code == X_CreatePixmap) {
+ pixmapError = True;
+ return 0;
+ } else return (*oldHandler) (dpy, error);
+}
+
+static Pixmap AllocPixmap(DPSScrolledWindowWidget dsw, unsigned w, unsigned h)
+{
+ Pixmap p;
+ unsigned int dBytes;
+ Widget wid = dsw->sw.drawing_area;
+ unsigned area = (w * h);
+
+ if (dsw->sw.pixmap_limit > 0) {
+ if (area > (unsigned)dsw->sw.pixmap_limit) return None;
+ } else if (dsw->sw.pixmap_limit < 0
+ && area > (unsigned)(dsw->sw.unscaled_width * dsw->sw.unscaled_height)
+ && area > (unsigned)(wid->core.width * wid->core.height)) return None;
+
+ if (dsw->sw.absolute_pixmap_limit > 0) {
+ dBytes = (wid->core.depth + 7) / 8; /* Convert into bytes */
+ if (area * dBytes > (unsigned)dsw->sw.absolute_pixmap_limit * 1024) {
+ return None;
+ }
+ }
+
+ XSync(XtDisplay(dsw), False);
+ oldHandler = XSetErrorHandler(PixmapHandler);
+ pixmapError = False;
+ p = XCreatePixmap(XtDisplay(dsw), XtWindow(dsw->sw.drawing_area), w, h,
+ wid->core.depth);
+ XSync(XtDisplay(dsw), False);
+ (void) XSetErrorHandler(oldHandler);
+ if (pixmapError) return None;
+ else return p;
+}
+
+static void CreateBackingPixmap(DPSScrolledWindowWidget dsw)
+{
+ Pixmap p;
+
+ if (dsw->sw.document_size_pixmaps) {
+ dsw->sw.pixmap_width =
+ MAX(CEIL(dsw->sw.drawing_width),
+ (int) dsw->sw.drawing_area->core.width);
+ dsw->sw.pixmap_height =
+ MAX(CEIL(dsw->sw.drawing_height),
+ (int) dsw->sw.drawing_area->core.height);
+
+ p = dsw->sw.backing_pixmap =
+ AllocPixmap(dsw, dsw->sw.pixmap_width, dsw->sw.pixmap_height);
+ if (p != None) {
+ dsw->sw.big_pixmap =
+ dsw->sw.pixmap_width >
+ (int) dsw->sw.drawing_area->core.width ||
+ dsw->sw.pixmap_height >
+ (int) dsw->sw.drawing_area->core.height;
+ return;
+ }
+ }
+ dsw->sw.big_pixmap = False;
+ dsw->sw.pixmap_width = dsw->sw.drawing_area->core.width;
+ dsw->sw.pixmap_height = dsw->sw.drawing_area->core.height;
+ p = dsw->sw.backing_pixmap =
+ AllocPixmap(dsw, dsw->sw.pixmap_width, dsw->sw.pixmap_height);
+ if (p == None) dsw->sw.pixmap_width = dsw->sw.pixmap_height = 0;
+}
+
+static void FreeBackingPixmap(DPSScrolledWindowWidget dsw)
+{
+ if (dsw->sw.backing_pixmap == None) return;
+ XFreePixmap(XtDisplay(dsw), dsw->sw.backing_pixmap);
+ dsw->sw.backing_pixmap = None;
+ dsw->sw.big_pixmap = False;
+ dsw->sw.pixmap_width = dsw->sw.pixmap_height = 0;
+ XDPSFreeContextGState(dsw->sw.context, dsw->sw.backing_gstate);
+}
+
+static void SetDrawingAreaPosition(
+ DPSScrolledWindowWidget dsw,
+ float ix,
+ float iy,
+ int vx,
+ int vy,
+ Boolean setOrigin)
+{
+ int xoff, yoff;
+ int hSize, vSize;
+ float scrollX, scrollY;
+
+ /* Convert ix, iy into X units */
+
+ ix *= dsw->sw.drawing_width / dsw->sw.area_width;
+ iy *= dsw->sw.drawing_height / dsw->sw.area_height;
+
+ if ((int)dsw->sw.drawing_area->core.width >= CEIL(dsw->sw.drawing_width)) {
+ /* The scaled width is narrower than the view window, so
+ center the picture and set scroll bar to be unscrollable */
+
+ xoff = ((int) dsw->sw.drawing_area->core.width -
+ CEIL(dsw->sw.drawing_width))
+ / 2.0;
+ scrollX = 0;
+ hSize = CEIL(dsw->sw.drawing_width);
+ } else {
+ /* The scaled width is larger than the view window, so
+ turn on the scroll bar, and set up its maximum and
+ slider size. Do this by converting the image offset into X
+ coordinates and subtracting the view offset */
+
+ scrollX = ix - vx;
+ scrollX = MAX(scrollX, 0);
+ scrollX = MIN(scrollX, CEIL(dsw->sw.drawing_width) -
+ (int) dsw->sw.drawing_area->core.width);
+ hSize = dsw->sw.drawing_area->core.width;
+ xoff = -(int) (scrollX + 0.5);
+ }
+
+ /* Now do the same thing for the height. We want to compute the offset
+ relative to the lower left corner, but X coordinates are relative
+ to the upper left, so the drawing height must be added in. Also, since
+ the coordinates go in the other direction, the view offset must be
+ added, not subtracted. */
+
+ if ((int) dsw->sw.drawing_area->core.height >=
+ CEIL(dsw->sw.drawing_height)) {
+ yoff = ((int) dsw->sw.drawing_area->core.height -
+ CEIL(dsw->sw.drawing_height)) / 2.0;
+ scrollY = CEIL(dsw->sw.drawing_height) -
+ (int) dsw->sw.drawing_area->core.height;
+ vSize = CEIL(dsw->sw.drawing_height);
+ } else {
+ scrollY = iy + vy - (int) dsw->sw.drawing_area->core.height;
+ scrollY = MAX(scrollY, 0);
+ scrollY = MIN(scrollY, CEIL(dsw->sw.drawing_height) -
+ (int) dsw->sw.drawing_area->core.height);
+ vSize = dsw->sw.drawing_area->core.height;
+ yoff = -(int) (scrollY + 0.5);
+ }
+
+ /* Update the scrollbars */
+ dsw->sw.scroll_x = (int) (scrollX + 0.5);
+ dsw->sw.scroll_y = (int) (CEIL(dsw->sw.drawing_height) -
+ (int) dsw->sw.drawing_area->core.height -
+ scrollY + 0.5);
+
+ yoff = dsw->sw.drawing_area->core.height - yoff;
+
+ dsw->sw.scroll_h_value = dsw->sw.scroll_x;
+ dsw->sw.scroll_h_size = hSize;
+ dsw->sw.scroll_h_max = CEIL(dsw->sw.drawing_width);
+ dsw->sw.scroll_v_value = dsw->sw.scroll_y;
+ dsw->sw.scroll_v_size = vSize;
+ dsw->sw.scroll_v_max = CEIL(dsw->sw.drawing_height);
+
+ if (!dsw->sw.application_scrolling) {
+ XtVaSetValues(dsw->sw.h_scroll, XmNmaximum, dsw->sw.scroll_h_max,
+ XmNvalue, dsw->sw.scroll_x, XmNsliderSize, hSize, NULL);
+ XtVaSetValues(dsw->sw.v_scroll, XmNmaximum, dsw->sw.scroll_v_max,
+ XmNvalue, dsw->sw.scroll_y, XmNsliderSize, vSize, NULL);
+ }
+
+ if (setOrigin) {
+ /* Set the origin in the X window to reflect the new location */
+ dsw->sw.origin_x = xoff;
+ dsw->sw.origin_y = yoff;
+ }
+}
+
+static void DrawBackground(
+ DPSScrolledWindowWidget dsw,
+ DSWDrawableType which)
+{
+ DSWExposeCallbackRec e;
+
+ e.type = which;
+ e.directions = DSWFinish;
+ e.results = DSWUndefined;
+ e.first = True;
+ e.background = True;
+ if (which == DSWBackingPixmap) {
+ e.drawable = dsw->sw.backing_pixmap;
+ e.gstate = dsw->sw.backing_gstate;
+ } else if (which == DSWFeedbackPixmap) {
+ e.drawable = dsw->sw.feedback_pixmap;
+ e.gstate = dsw->sw.feedback_gstate;
+ } else {
+ e.drawable = XtWindow(dsw->sw.drawing_area);
+ e.gstate = dsw->sw.window_gstate;
+ }
+ e.context = dsw->sw.context;
+
+ SimplifyRects(dsw->sw.current_drawing, &dsw->sw.num_current_drawing);
+
+ XDPSSetContextGState(dsw->sw.context, e.gstate);
+ _DPSSWSetRectViewClip(dsw->sw.context, dsw->sw.current_drawing,
+ dsw->sw.num_current_drawing * 4);
+
+ e.rects = dsw->sw.current_drawing;
+ e.rect_count = dsw->sw.num_current_drawing;
+
+ do {
+ XtCallCallbackList((Widget) dsw, dsw->sw.background_callback,
+ (XtPointer) &e);
+ if (e.results == DSWUndefined) {
+ if (XtHasCallbacks((Widget) dsw, XtNbackgroundCallback) !=
+ XtCallbackHasNone) {
+ XtAppWarningMsg(XtWidgetToApplicationContext((Widget) dsw),
+ "returnError", "backgroundCallback",
+ "DPSScrollError",
+ "Background callback did not set result field",
+ (String *) NULL, (Cardinal *) NULL);
+ }
+ e.results = DSWFinished;
+ }
+ } while (e.results != DSWFinished);
+
+
+ DPSinitviewclip(dsw->sw.context);
+}
+
+static void ClipToDrawingSize(
+ DPSScrolledWindowWidget dsw,
+ DSWDrawableType which)
+{
+ int i;
+ float r[4];
+
+ if (CEIL(dsw->sw.drawing_width) >= (int) dsw->sw.drawing_area->core.width &&
+ CEIL(dsw->sw.drawing_height) >= (int) dsw->sw.drawing_area->core.height) return;
+
+ /* Copy current drawing area to scratch */
+
+ GrowRectList(&dsw->sw.scratch, &dsw->sw.scratch_size, 0,
+ dsw->sw.num_current_drawing, 1);
+ dsw->sw.num_scratch = dsw->sw.num_current_drawing;
+ for (i = 0; i < dsw->sw.num_current_drawing * 4; i++) {
+ dsw->sw.scratch[i] = dsw->sw.current_drawing[i];
+ }
+
+ /* Construct a rectangle of the drawing area */
+
+ ConvertToPS(dsw, dsw->sw.origin_x + DELTA, dsw->sw.origin_y - DELTA,
+ r, r+1);
+ ConvertToPS(dsw, dsw->sw.origin_x + CEIL(dsw->sw.drawing_width) - DELTA,
+ dsw->sw.origin_y - CEIL(dsw->sw.drawing_height) + DELTA,
+ r+2, r+3);
+ r[2] -= r[0];
+ r[3] -= r[1];
+
+ /* Subtract the area of the drawing from the current drawing list */
+
+ SubtractRects(&dsw->sw.current_drawing, &dsw->sw.current_drawing_size,
+ &dsw->sw.num_current_drawing, r, 1);
+
+ if (dsw->sw.num_current_drawing != 0) {
+ DrawBackground(dsw, which);
+ /* Now intersect the rectangle with the current drawing area */
+ IntersectRects(&dsw->sw.scratch, &dsw->sw.scratch_size,
+ &dsw->sw.num_scratch, r, 1);
+ /* If nothing left, we won't be drawing anything more, so
+ synchronize. Otherwise wait until we're done drawing */
+ if (dsw->sw.num_scratch == 0) DPSWaitContext(dsw->sw.context);
+ }
+
+ /* Copy scratch back into the current drawing list */
+ GrowRectList(&dsw->sw.current_drawing, &dsw->sw.current_drawing_size, 0,
+ dsw->sw.num_scratch, 1);
+ dsw->sw.num_current_drawing = dsw->sw.num_scratch;
+ for (i = 0; i < dsw->sw.num_scratch * 4; i++) {
+ dsw->sw.current_drawing[i] = dsw->sw.scratch[i];
+ }
+}
+
+static DSWResults ClipAndDraw(
+ DPSScrolledWindowWidget dsw,
+ DSWDrawableType which,
+ DSWDirections howMuch,
+ Boolean first)
+{
+ DSWExposeCallbackRec e;
+
+ e.type = which;
+ e.directions = howMuch;
+ e.results = DSWUndefined;
+ e.first = first;
+ e.background = False;
+ if (which == DSWBackingPixmap) {
+ e.drawable = dsw->sw.backing_pixmap;
+ e.gstate = dsw->sw.backing_gstate;
+ } else if (which == DSWFeedbackPixmap) {
+ e.drawable = dsw->sw.feedback_pixmap;
+ e.gstate = dsw->sw.feedback_gstate;
+ } else {
+ e.drawable = XtWindow(dsw->sw.drawing_area);
+ e.gstate = dsw->sw.window_gstate;
+ }
+ e.context = dsw->sw.context;
+
+ if (first) {
+ XDPSSetContextGState(dsw->sw.context, e.gstate);
+ if (howMuch != DSWAbort) {
+ ClipToDrawingSize(dsw, which);
+ SimplifyRects(dsw->sw.current_drawing,
+ &dsw->sw.num_current_drawing);
+ if (dsw->sw.num_current_drawing == 0) return DSWFinished;
+ _DPSSWSetRectViewClip(dsw->sw.context, dsw->sw.current_drawing,
+ dsw->sw.num_current_drawing * 4);
+ }
+ }
+
+ e.rects = dsw->sw.current_drawing;
+ e.rect_count = dsw->sw.num_current_drawing;
+
+ do {
+ XtCallCallbackList((Widget) dsw, dsw->sw.expose_callback,
+ (XtPointer) &e);
+ if (e.results == DSWUndefined) {
+ if (XtHasCallbacks((Widget) dsw,
+ XtNexposeCallback) != XtCallbackHasNone) {
+ XtAppWarningMsg(XtWidgetToApplicationContext((Widget) dsw),
+ "returnError", "exposeCallback",
+ "DPSScrollError",
+ "Expose callback did not set result field",
+ (String *) NULL, (Cardinal *) NULL);
+ }
+ e.results = DSWFinished;
+ }
+ } while ((e.results != DSWFinished && howMuch == DSWFinish) ||
+ (e.results != DSWFinished && e.results != DSWAborted &&
+ howMuch == DSWAbortOrFinish) ||
+ (e.results != DSWAborted && howMuch == DSWAbort));
+
+ if (e.results == DSWFinished) {
+ DPSinitviewclip(dsw->sw.context);
+ DPSWaitContext(dsw->sw.context);
+ }
+ return e.results;
+}
+
+static void SplitExposeEvent(
+ DPSScrolledWindowWidget dsw,
+ XExposeEvent *ev)
+{
+ float *r;
+ float llx, lly, urx, ury;
+ int xr[4];
+ int i;
+ int dx, dy;
+
+ ComputeOffsets(dsw, &dx, &dy);
+
+ /* Put the expose event into the scratch list */
+ dsw->sw.num_scratch = 1;
+ r = dsw->sw.scratch;
+ ConvertToPS(dsw, ev->x + DELTA, ev->y + ev->height - DELTA, &llx, &lly);
+ ConvertToPS(dsw, ev->x + ev->width - DELTA, ev->y + DELTA, &urx, &ury);
+ LEFT(r) = llx;
+ BOTTOM(r) = lly;
+ WIDTH(r) = urx - llx;
+ HEIGHT(r) = ury - lly;
+
+ /* Subtract the dirty area from the exposed area and copy the resulting
+ area to the window */
+ SubtractRects(&dsw->sw.scratch, &dsw->sw.scratch_size,
+ &dsw->sw.num_scratch,
+ dsw->sw.dirty_areas, dsw->sw.num_dirty_areas);
+ for (i = 0; i < dsw->sw.num_scratch; i++) {
+ r = dsw->sw.scratch + 4*i;
+ ConvertToX(dsw, LEFT(r), TOP(r), xr, xr+1);
+ ConvertToX(dsw, RIGHT(r), BOTTOM(r), xr+2, xr+3);
+ xr[2] -= xr[0];
+ xr[3] -= xr[1];
+ XCopyArea(XtDisplay(dsw), dsw->sw.backing_pixmap,
+ XtWindow(dsw->sw.drawing_area), dsw->sw.no_ge_gc,
+ xr[0] + dx, xr[1] + dy, xr[2], xr[3], xr[0], xr[1]);
+ }
+
+ /* Now do it again, but intersect the exposed area with the dirty area
+ and add the intersection to the pending list */
+
+ dsw->sw.num_scratch = 1;
+ r = dsw->sw.scratch;
+ LEFT(r) = llx;
+ BOTTOM(r) = lly;
+ WIDTH(r) = urx - llx;
+ HEIGHT(r) = ury - lly;
+ IntersectRects(&dsw->sw.scratch, &dsw->sw.scratch_size,
+ &dsw->sw.num_scratch,
+ dsw->sw.dirty_areas, dsw->sw.num_dirty_areas);
+ AddUserSpaceRectsToPending(dsw, dsw->sw.scratch, dsw->sw.num_scratch);
+}
+
+/* ARGSUSED */
+
+static Bool CheckWatchProgressEvent(
+ Display *dpy,
+ XEvent *e,
+ char *arg)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) arg;
+
+ return (e->xany.window == dsw->sw.backing_pixmap &&
+ (e->type == GraphicsExpose || e->type == NoExpose)) ||
+ (e->xany.window == XtWindow(dsw->sw.drawing_area) &&
+ e->type == Expose);
+}
+
+static void CopyWindowToBackingPixmap(
+ DPSScrolledWindowWidget dsw)
+{
+ int llx, lly, urx, ury;
+ XEvent e;
+ XExposeEvent *ev = (XExposeEvent *) &e;
+ int i;
+ float *r;
+ int copies = 0;
+ int dx, dy;
+
+ ComputeOffsets(dsw, &dx, &dy);
+
+ for (i = 0; i < dsw->sw.num_dirty_areas; i++) {
+ r = dsw->sw.dirty_areas + i*4;
+ ConvertToX(dsw, LEFT(r), BOTTOM(r), &llx, &lly);
+ ConvertToX(dsw, RIGHT(r), TOP(r), &urx, &ury);
+ XCopyArea(XtDisplay(dsw), XtWindow(dsw->sw.drawing_area),
+ dsw->sw.backing_pixmap, dsw->sw.ge_gc,
+ llx, ury, urx-llx, lly-ury, llx + dx, ury + dy);
+ copies++;
+ }
+
+ /* Unfortunately the Intrinsics won't let us get ahold of the the
+ GraphicsExpose events for the pixmap, so we have to wait and
+ get them the old fashioned way. Yuck. */
+
+ while (copies > 0) {
+ XIfEvent(XtDisplay(dsw), &e, CheckWatchProgressEvent,
+ (char *) dsw);
+ if (e.type == Expose) {
+ SplitExposeEvent(dsw, ev);
+ continue;
+ } else if (e.type == GraphicsExpose) {
+ ev->x -= dx;
+ ev->y -= dy;
+ AddExposureToPending(dsw, ev);
+ if (ev->count == 0) copies--;
+ } else copies--; /* NoExpose */
+ }
+ CopyRectsToCurrentDrawing(dsw, dsw->sw.pending_dirty,
+ dsw->sw.num_pending_dirty);
+
+ dsw->sw.num_pending_dirty = 0;
+ dsw->sw.num_pending_expose = 0;
+ if (dsw->sw.num_current_drawing == 0) {
+ dsw->sw.drawing_stage = DSWDone;
+ dsw->sw.num_dirty_areas = 0;
+ } else {
+ /* The dirty area is now the intersection of the old dirty area and
+ the newly-created current drawing list */
+ IntersectRects(&dsw->sw.dirty_areas, &dsw->sw.dirty_areas_size,
+ &dsw->sw.num_dirty_areas,
+ dsw->sw.current_drawing, dsw->sw.num_current_drawing);
+ }
+}
+
+/* Subtract the window area from the dirty area, and make the
+ result be the new current drawing list */
+
+static void SetCurrentDrawingToBackground(
+ DPSScrolledWindowWidget dsw)
+{
+ int i;
+ float r[4];
+
+ ConvertToPS(dsw, 0 + DELTA, dsw->sw.drawing_area->core.height - DELTA,
+ r, r+1);
+ ConvertToPS(dsw, dsw->sw.drawing_area->core.width - DELTA, 0 + DELTA,
+ r+2, r+3);
+ r[2] -= r[0];
+ r[3] -= r[1];
+
+ SubtractRects(&dsw->sw.dirty_areas, &dsw->sw.dirty_areas_size,
+ &dsw->sw.num_dirty_areas, r, 1);
+
+ GrowRectList(&dsw->sw.current_drawing, &dsw->sw.current_drawing_size,
+ 0, dsw->sw.num_dirty_areas, 1);
+ for (i = 0; i < 4 * dsw->sw.num_dirty_areas; i++) {
+ dsw->sw.current_drawing[i] = dsw->sw.dirty_areas[i];
+ }
+ dsw->sw.num_current_drawing = dsw->sw.num_dirty_areas;
+}
+
+static void CopyPendingExpose(DPSScrolledWindowWidget dsw)
+{
+ int dx, dy;
+ int i;
+ int *r;
+
+ ComputeOffsets(dsw, &dx, &dy);
+
+ for (i = 0; i < dsw->sw.num_pending_expose; i++) {
+ r = dsw->sw.pending_expose + 4*i;
+ XCopyArea(XtDisplay(dsw), dsw->sw.backing_pixmap,
+ XtWindow(dsw->sw.drawing_area),
+ dsw->sw.no_ge_gc,
+ LEFT(r) + dx, BOTTOM(r) + dy, WIDTH(r), HEIGHT(r),
+ LEFT(r), BOTTOM(r));
+ }
+ dsw->sw.num_pending_expose = dsw->sw.num_pending_dirty = 0;
+}
+
+static void UpdateWindowFromBackingPixmap(
+ DPSScrolledWindowWidget dsw,
+ float *rects,
+ int n)
+{
+ int dx, dy;
+ int llx, lly, urx, ury;
+ int i;
+ float *r;
+
+ ComputeOffsets(dsw, &dx, &dy);
+
+ for (i = 0; i < n; i++) {
+ r = rects + 4*i;
+ ConvertToX(dsw, LEFT(r), BOTTOM(r), &llx, &lly);
+ ConvertToX(dsw, RIGHT(r), TOP(r), &urx, &ury);
+
+ XCopyArea(XtDisplay(dsw), dsw->sw.backing_pixmap,
+ XtWindow(dsw->sw.drawing_area),
+ dsw->sw.no_ge_gc,
+ llx+dx-1, ury+dy-1, urx-llx+2, lly-ury+2, llx-1, ury-1);
+ }
+}
+
+static void UpdateWindowFromFeedbackPixmap(
+ DPSScrolledWindowWidget dsw,
+ float *rects,
+ int n)
+{
+ int llx, lly, urx, ury;
+ int i;
+ float *r;
+
+ for (i = 0; i < n; i++) {
+ r = rects + (i * 4);
+ ConvertToX(dsw, LEFT(r), BOTTOM(r), &llx, &lly);
+ ConvertToX(dsw, RIGHT(r), TOP(r), &urx, &ury);
+
+ XCopyArea(XtDisplay(dsw), dsw->sw.feedback_pixmap,
+ XtWindow(dsw->sw.drawing_area), dsw->sw.no_ge_gc,
+ llx-1, ury-1, urx-llx+2, lly-ury+2, llx-1, ury-1);
+ }
+}
+
+/* This is the heart of the drawing code; it does one piece of drawing.
+ It can be called either directly or as a work procedure */
+
+static Boolean DoDrawing(XtPointer clientData)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) clientData;
+ DSWResults results;
+ DSWDrawableType which;
+
+ if (dsw->sw.drawing_stage == DSWStart && dsw->sw.watch_progress &&
+ dsw->sw.backing_pixmap != None && dsw->sw.num_current_drawing == 0) {
+ dsw->sw.drawing_stage = DSWDrewVisible;
+ CopyWindowToBackingPixmap(dsw);
+ }
+
+ switch (dsw->sw.drawing_stage) {
+ case DSWStart:
+ case DSWDrawingVisible:
+ if (dsw->sw.watch_progress || dsw->sw.backing_pixmap == None) {
+ which = DSWWindow;
+ } else which = DSWBackingPixmap;
+ results = ClipAndDraw(dsw, which, DSWDrawSome,
+ (dsw->sw.drawing_stage == DSWStart));
+ if (results == DSWFinished) {
+ if (dsw->sw.watch_progress && dsw->sw.backing_pixmap != None) {
+ dsw->sw.drawing_stage = DSWDrewVisible;
+ CopyWindowToBackingPixmap(dsw);
+ } else {
+ if (dsw->sw.minimal_drawing && dsw->sw.big_pixmap) {
+ dsw->sw.drawing_stage = DSWDrewVisible;
+ SetCurrentDrawingToBackground(dsw);
+ } else {
+ dsw->sw.drawing_stage = DSWDone;
+ dsw->sw.num_dirty_areas = 0;
+ }
+ if (dsw->sw.num_pending_expose != 0 &&
+ dsw->sw.backing_pixmap != None) {
+ CopyPendingExpose(dsw);
+ }
+ }
+ } else dsw->sw.drawing_stage = DSWDrawingVisible;
+ break;
+
+ case DSWDrewVisible:
+ case DSWDrawingBackground:
+ results = ClipAndDraw(dsw, DSWBackingPixmap, DSWDrawSome,
+ (dsw->sw.drawing_stage == DSWDrewVisible));
+ if (results == DSWFinished) {
+ dsw->sw.drawing_stage = DSWDone;
+ dsw->sw.num_dirty_areas = 0;
+ }
+ else dsw->sw.drawing_stage = DSWDrawingBackground;
+ break;
+
+ case DSWDone:
+ break;
+ }
+
+ if (dsw->sw.drawing_stage == DSWDone && dsw->sw.num_pending_dirty != 0) {
+ CopyRectsToCurrentDrawing(dsw, dsw->sw.pending_dirty,
+ dsw->sw.num_pending_dirty);
+ CopyRectsToDirtyArea(dsw, dsw->sw.pending_dirty,
+ dsw->sw.num_pending_dirty);
+ dsw->sw.num_pending_dirty = 0;
+ dsw->sw.num_pending_expose = 0;
+ dsw->sw.drawing_stage = DSWStart;
+ }
+
+ if (dsw->sw.drawing_stage == DSWDone) {
+ dsw->sw.work = 0;
+ if (dsw->sw.watch_progress) {
+ /* Some of the background drawing may have been to areas that
+ are visible */
+ UpdateWindowFromBackingPixmap(dsw, dsw->sw.current_drawing,
+ dsw->sw.num_current_drawing);
+ }
+ dsw->sw.num_current_drawing = 0;
+ if (dsw->sw.scrolling) {
+ dsw->sw.scrolling = False;
+ ScrollMoved(dsw);
+ }
+ return True;
+ } else return False;
+}
+
+static void StartDrawing(DPSScrolledWindowWidget dsw)
+{
+ float r[4];
+
+ CopyRectsToCurrentDrawing(dsw, dsw->sw.dirty_areas,
+ dsw->sw.num_dirty_areas);
+
+ if (dsw->sw.watch_progress || dsw->sw.backing_pixmap == None) {
+ /* Intersect the current drawing area with the pending dirty area
+ (The pending dirty area represents the window exposures that
+ have happened so far) */
+ IntersectRects(&dsw->sw.current_drawing, &dsw->sw.current_drawing_size,
+ &dsw->sw.num_current_drawing,
+ dsw->sw.pending_dirty, dsw->sw.num_pending_dirty);
+ dsw->sw.num_pending_dirty = dsw->sw.num_pending_expose = 0;
+ } else {
+ if (!dsw->sw.big_pixmap || dsw->sw.minimal_drawing) {
+ /* Intersect the current drawing area to the window to start */
+ ConvertToPS(dsw, 0 + DELTA,
+ dsw->sw.drawing_area->core.height - DELTA, r, r+1);
+ ConvertToPS(dsw, dsw->sw.drawing_area->core.width - DELTA,
+ 0 + DELTA, r+2, r+3);
+ r[2] -= r[0];
+ r[3] -= r[1];
+ IntersectRects(&dsw->sw.current_drawing,
+ &dsw->sw.current_drawing_size,
+ &dsw->sw.num_current_drawing, r, 1);
+ }
+ }
+
+ if (dsw->sw.num_current_drawing == 0 && !dsw->sw.watch_progress) {
+ dsw->sw.drawing_stage = DSWFinished;
+ dsw->sw.num_dirty_areas = 0;
+ return;
+ }
+
+ dsw->sw.drawing_stage = DSWStart;
+ if (!DoDrawing((XtPointer) dsw)) {
+ dsw->sw.work =
+ XtAppAddWorkProc(XtWidgetToApplicationContext((Widget) dsw),
+ DoDrawing, (XtPointer) dsw);
+ }
+}
+
+static void RedisplaySliver(DPSScrolledWindowWidget dsw, int deltaX, int deltaY)
+{
+ float r[8];
+ int xr[8];
+ int n;
+ int xllx, xlly, xurx, xury;
+ float llx, lly, urx, ury;
+
+ /* If one of the deltas is 0, then the area to update is just a
+ single rectangle. */
+ if (deltaX == 0 || deltaY == 0) {
+ if (deltaX == 0) {
+ /* Just a single horizontal rectangle */
+
+ xllx = 0;
+ xurx = dsw->sw.drawing_area->core.width;
+ if (deltaY > 0) {
+ xlly = dsw->sw.drawing_area->core.height;
+ xury = dsw->sw.drawing_area->core.height - deltaY;
+ } else {
+ xlly = -deltaY;
+ xury = 0;
+ }
+
+ } else if (deltaY == 0) {
+ /* Just a single vertical rectangle */
+ xlly = dsw->sw.drawing_area->core.height;
+ xury = 0;
+ if (deltaX > 0) {
+ xllx = dsw->sw.drawing_area->core.width - deltaX;
+ xurx = dsw->sw.drawing_area->core.width;
+ } else {
+ xllx = 0;
+ xurx = -deltaX;
+ }
+ }
+ /* Convert the rectangle into PS coordinates */
+ ConvertToPS(dsw, xllx + DELTA, xlly - DELTA, &llx, &lly);
+ ConvertToPS(dsw, xurx - DELTA, xury + DELTA, &urx, &ury);
+ r[0] = llx;
+ r[1] = lly;
+ r[2] = urx - llx;
+ r[3] = ury - lly;
+ xr[0] = xllx;
+ xr[1] = xury;
+ xr[2] = xurx - xllx;
+ xr[3] = xlly - xury;
+ n = 1;
+
+ } else {
+ /* Scrolling in both directions, so there are two rectangles.
+ It's easiest to do if we let them overlap; fortunately that is
+ legal! First do the horizontal rectangle. */
+ xllx = 0;
+ xurx = dsw->sw.drawing_area->core.width;
+ if (deltaY > 0) {
+ xlly = dsw->sw.drawing_area->core.height;
+ xury = dsw->sw.drawing_area->core.height - deltaY;
+ } else {
+ xlly = -deltaY;
+ xury = 0;
+ }
+ ConvertToPS(dsw, xllx + DELTA, xlly - DELTA, &llx, &lly);
+ ConvertToPS(dsw, xurx - DELTA, xury + DELTA, &urx, &ury);
+
+ /* Store in point array */
+ r[0] = llx;
+ r[1] = lly;
+ r[2] = urx - llx;
+ r[3] = ury - lly;
+ xr[0] = xllx;
+ xr[1] = xury;
+ xr[2] = xurx - xllx;
+ xr[3] = xlly - xury;
+
+ /* Now do vertical rectangle and store in point array */
+ xlly = dsw->sw.drawing_area->core.height;
+ xury = 0;
+ if (deltaX > 0) {
+ xllx = dsw->sw.drawing_area->core.width - deltaX;
+ xurx = dsw->sw.drawing_area->core.width;
+ } else {
+ xllx = 0;
+ xurx = -deltaX;
+ }
+ ConvertToPS(dsw, xllx + DELTA, xlly - DELTA, &llx, &lly);
+ ConvertToPS(dsw, xurx - DELTA, xury + DELTA, &urx, &ury);
+ r[4] = llx;
+ r[5] = lly;
+ r[6] = urx - llx;
+ r[7] = ury - lly;
+ xr[4] = xllx;
+ xr[5] = xury;
+ xr[6] = xurx - xllx;
+ xr[7] = xlly - xury;
+ n = 2;
+ }
+
+ AddRectsToDirtyArea(dsw, r, n);
+ AddRectsToPending(dsw, xr, n);
+ StartDrawing(dsw);
+}
+
+static void SetUpInitialPixmap(DPSScrolledWindowWidget dsw)
+{
+ float *r = dsw->sw.dirty_areas;
+ int llx, lly, urx, ury;
+
+ CreateBackingPixmap(dsw);
+ if (dsw->sw.backing_pixmap != None) {
+ XDPSSetContextDrawable(dsw->sw.context, dsw->sw.backing_pixmap,
+ dsw->sw.pixmap_height);
+
+ SetPixmapOffset(dsw);
+ SetPixmapOrigin(dsw);
+ XDPSCaptureContextGState(dsw->sw.context, &dsw->sw.backing_gstate);
+
+ if (dsw->sw.pixmap_width != CEIL(dsw->sw.drawing_width) ||
+ dsw->sw.pixmap_height != CEIL(dsw->sw.drawing_height)) {
+
+ /* Make the dirty area match the window */
+ if (dsw->sw.pixmap_width > (int)dsw->sw.drawing_area->core.width) {
+ llx = dsw->sw.origin_x;
+ urx = llx + CEIL(dsw->sw.drawing_width);
+ } else {
+ llx = 0;
+ urx = dsw->sw.drawing_area->core.width;
+ }
+ if (dsw->sw.pixmap_height >
+ (int) dsw->sw.drawing_area->core.height) {
+ lly = dsw->sw.origin_y;
+ ury = dsw->sw.origin_y - CEIL(dsw->sw.drawing_height);
+ } else {
+ lly = dsw->sw.drawing_area->core.height;
+ ury = 0;
+ }
+ ConvertToPS(dsw, llx + DELTA, lly - DELTA, r, r+1);
+ ConvertToPS(dsw, urx - DELTA, ury + DELTA, r+2, r+3);
+ r[2] -= r[0];
+ r[3] -= r[1];
+ dsw->sw.num_dirty_areas = 1;
+ }
+ if (dsw->sw.doing_feedback) {
+ CopyRectsToCurrentDrawing(dsw, dsw->sw.dirty_areas,
+ dsw->sw.num_dirty_areas);
+ FinishDrawing(dsw);
+ } else if (!dsw->sw.watch_progress) StartDrawing(dsw);
+ }
+}
+
+/* ARGSUSED */
+
+static void TimerStart(XtPointer clientData, XtIntervalId *id)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) clientData;
+
+ if (dsw->sw.drawing_stage == DSWStart) StartDrawing(dsw);
+}
+
+static void SetUpInitialInformation(DPSScrolledWindowWidget dsw)
+{
+ int i;
+ float llx, lly, urx, ury;
+ float xScale, yScale;
+ XExposeEvent ev;
+ XStandardColormap colorCube, grayRamp;
+ int match;
+
+ /* If the context's colormap matches the widget's colormap, assume that
+ everything is already set up right in the color cube department. This
+ allows an application to supply us with a custom color cube by
+ installing it in the context before calling us */
+
+ _DPSSWColormapMatch(dsw->sw.context,
+ dsw->sw.drawing_area->core.colormap, &match);
+
+ if (match) {
+ XDPSSetContextParameters(dsw->sw.context, XtScreen(dsw),
+ dsw->sw.drawing_area->core.depth,
+ XtWindow(dsw->sw.drawing_area),
+ dsw->sw.drawing_area->core.height, NULL, NULL,
+ XDPSContextScreenDepth | XDPSContextDrawable);
+ } else {
+ grayRamp.colormap = colorCube.colormap =
+ dsw->sw.drawing_area->core.colormap;
+
+ XDPSCreateStandardColormaps(XtDisplay(dsw), XtWindow(dsw),
+ (Visual *) NULL, 0, 0, 0, 0,
+ &colorCube, &grayRamp, False);
+
+ XDPSSetContextParameters(dsw->sw.context, XtScreen(dsw),
+ dsw->sw.drawing_area->core.depth,
+ XtWindow(dsw->sw.drawing_area),
+ dsw->sw.drawing_area->core.height,
+ (XDPSStandardColormap *) &colorCube,
+ (XDPSStandardColormap *) &grayRamp,
+ XDPSContextScreenDepth | XDPSContextDrawable |
+ XDPSContextRGBMap | XDPSContextGrayMap);
+ }
+
+ DPSinitgraphics(dsw->sw.context);
+ _DPSSWGetTransform(dsw->sw.context, dsw->sw.ctm, dsw->sw.orig_inv_ctm);
+ dsw->sw.x_offset = 0;
+ dsw->sw.y_offset = dsw->sw.drawing_area->core.height;
+ for (i = 0; i < 6; i++) dsw->sw.inv_ctm[i] = dsw->sw.orig_inv_ctm[i];
+
+ ConvertToPS(dsw, 0.0, 100.0, &llx, &lly);
+ ConvertToPS(dsw, 100.0, 0.0, &urx, &ury);
+ xScale = ABS(100.0 / (urx - llx));
+ yScale = ABS(100.0 / (ury - lly));
+
+ if (dsw->sw.scale != 1.0) {
+ DPSscale(dsw->sw.context, dsw->sw.scale, dsw->sw.scale);
+ _DPSSWGetTransform(dsw->sw.context, dsw->sw.ctm, dsw->sw.inv_ctm);
+ }
+
+ dsw->sw.drawing_width = dsw->sw.area_width * xScale * dsw->sw.scale;
+ dsw->sw.drawing_height = dsw->sw.area_height * yScale * dsw->sw.scale;
+
+ dsw->sw.unscaled_width = dsw->sw.drawing_width / dsw->sw.scale + 1;
+ dsw->sw.unscaled_height = dsw->sw.drawing_height / dsw->sw.scale + 1;
+
+ if (!dsw->sw.use_saved_scroll) {
+ dsw->sw.scroll_pic_x = dsw->sw.area_width / 2;
+ dsw->sw.scroll_pic_y = dsw->sw.area_height / 2;
+ dsw->sw.scroll_win_x = dsw->sw.drawing_area->core.width / 2;
+ dsw->sw.scroll_win_y = dsw->sw.drawing_area->core.height / 2;
+ }
+
+ SetDrawingAreaPosition(dsw, dsw->sw.scroll_pic_x, dsw->sw.scroll_pic_y,
+ dsw->sw.scroll_win_x, dsw->sw.scroll_win_y, True);
+ SetOriginAndGetTransform(dsw);
+ XDPSCaptureContextGState(dsw->sw.context, &dsw->sw.window_gstate);
+
+ dsw->sw.drawing_stage = DSWStart;
+
+ if (dsw->sw.use_backing_pixmap) SetUpInitialPixmap(dsw);
+
+ if (dsw->sw.doing_feedback) return;
+
+ if (dsw->sw.watch_progress || dsw->sw.backing_pixmap == None) {
+ /* If watching progress or no pixmap, clear the window to ensure
+ that things get started */
+ XClearArea(XtDisplay(dsw), XtWindow(dsw->sw.drawing_area),
+ 0, 0, 0, 0, True);
+ XSync(XtDisplay(dsw), False);
+ if (dsw->sw.watch_progress && dsw->sw.watch_progress_delay > 0) {
+ /* Set a timer so that we start drawing if nothing is visible */
+ (void) XtAppAddTimeOut(XtWidgetToApplicationContext((Widget) dsw),
+ dsw->sw.watch_progress_delay,
+ TimerStart, (XtPointer) dsw);
+ }
+ } else {
+ /* Put a synthetic expose event in the pending queue */
+ ev.x = ev.y = 0;
+ ev.width = dsw->sw.drawing_area->core.width;
+ ev.height = dsw->sw.drawing_area->core.height;
+ SplitExposeEvent(dsw, &ev);
+ }
+}
+
+static void Realize(
+ Widget w,
+ XtValueMask *mask,
+ XSetWindowAttributes *attr)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
+ DSWSetupCallbackRec setup;
+
+ /* Let my parent do all the hard work */
+ (*dpsScrolledWindowClassRec.core_class.superclass->core_class.realize)
+ (w, mask, attr);
+
+ /* We delay calling the setup callback so that the caller can use
+ XtAddCallback to add it */
+ setup.context = dsw->sw.context;
+ XtCallCallbackList((Widget) dsw, dsw->sw.setup_callback,
+ (XtPointer) &setup);
+
+ /* Now, explicitly realize my children */
+ XtRealizeWidget(dsw->sw.scrolled_window);
+
+ /* Et voila, now we have windows! */
+ SetUpInitialInformation(dsw);
+}
+
+static void AbortOrFinish(DPSScrolledWindowWidget dsw)
+{
+ DSWResults results;
+ DSWDrawableType which;
+
+ if (dsw->sw.work != 0) {
+ XtRemoveWorkProc(dsw->sw.work);
+ dsw->sw.work = 0;
+ }
+
+ switch (dsw->sw.drawing_stage) {
+ case DSWStart:
+ return;
+ /* break; */
+
+ case DSWDrawingVisible:
+ if (dsw->sw.watch_progress || dsw->sw.backing_pixmap == None) {
+ which = DSWWindow;
+ } else which = DSWBackingPixmap;
+ results = ClipAndDraw(dsw, which, DSWAbortOrFinish, False);
+ if (results == DSWAborted) {
+ dsw->sw.drawing_stage = DSWStart;
+ if (dsw->sw.backing_pixmap == None || dsw->sw.watch_progress) {
+ /* Add the current drawing area back into the pending
+ expose area */
+ AddUserSpaceRectsToPending(dsw, dsw->sw.current_drawing,
+ dsw->sw.num_current_drawing);
+ }
+ return;
+ }
+ if (dsw->sw.watch_progress && dsw->sw.backing_pixmap != None) {
+ dsw->sw.drawing_stage = DSWDrewVisible;
+ CopyWindowToBackingPixmap(dsw);
+ if (dsw->sw.num_current_drawing != 0) {
+ results = ClipAndDraw(dsw, DSWBackingPixmap,
+ DSWAbortOrFinish, True);
+ }
+ if (results == DSWAborted) {
+ dsw->sw.drawing_stage = DSWStart;
+ return;
+ }
+ } else {
+ if (dsw->sw.backing_pixmap != None) {
+ if (dsw->sw.num_pending_expose != 0) {
+ CopyPendingExpose(dsw);
+ }
+
+ if (dsw->sw.minimal_drawing && dsw->sw.big_pixmap) {
+ dsw->sw.drawing_stage = DSWDrewVisible;
+ SetCurrentDrawingToBackground(dsw);
+ results = ClipAndDraw(dsw, which,
+ DSWAbortOrFinish, True);
+ if (results == DSWAborted) {
+ dsw->sw.drawing_stage = DSWStart;
+ return;
+ }
+ }
+ }
+ }
+ break;
+
+ case DSWDrewVisible:
+ case DSWDrawingBackground:
+ results = ClipAndDraw(dsw, DSWBackingPixmap, DSWAbortOrFinish,
+ (dsw->sw.drawing_stage == DSWDrewVisible));
+ if (results == DSWAborted) {
+ dsw->sw.drawing_stage = DSWStart;
+ return;
+ }
+ break;
+
+ case DSWDone:
+ break;
+ }
+
+ dsw->sw.drawing_stage = DSWDone;
+ dsw->sw.num_dirty_areas = 0;
+ return;
+}
+
+static void AbortDrawing(DPSScrolledWindowWidget dsw)
+{
+ DSWDrawableType which;
+
+ if (dsw->sw.work != 0) {
+ XtRemoveWorkProc(dsw->sw.work);
+ dsw->sw.work = 0;
+ }
+
+ switch (dsw->sw.drawing_stage) {
+ case DSWStart:
+ case DSWDone:
+ case DSWDrewVisible:
+ break;
+
+ case DSWDrawingVisible:
+ if (dsw->sw.watch_progress || dsw->sw.backing_pixmap == None) {
+ which = DSWWindow;
+ } else which = DSWBackingPixmap;
+ (void) ClipAndDraw(dsw, which, DSWAbort, False);
+ break;
+
+ case DSWDrawingBackground:
+ (void) ClipAndDraw(dsw, DSWBackingPixmap, DSWAbort, False);
+ break;
+
+ }
+
+ dsw->sw.num_pending_expose = dsw->sw.num_pending_dirty = 0;
+}
+
+static void FinishDrawing(DPSScrolledWindowWidget dsw)
+{
+ DSWDrawableType which;
+
+ if (dsw->sw.work != 0) {
+ XtRemoveWorkProc(dsw->sw.work);
+ dsw->sw.work = 0;
+ }
+
+ switch (dsw->sw.drawing_stage) {
+ case DSWStart:
+ case DSWDrawingVisible:
+ if (dsw->sw.watch_progress || dsw->sw.backing_pixmap == None) {
+ which = DSWWindow;
+ } else which = DSWBackingPixmap;
+ if (dsw->sw.drawing_stage == DSWStart) {
+ ClipToDrawingSize(dsw, which);
+ if (dsw->sw.num_current_drawing == 0) return;
+ }
+ (void) ClipAndDraw(dsw, which, DSWFinish,
+ dsw->sw.drawing_stage == DSWStart);
+ if (dsw->sw.watch_progress && dsw->sw.backing_pixmap != None) {
+ dsw->sw.drawing_stage = DSWDrewVisible;
+ CopyWindowToBackingPixmap(dsw);
+ if (dsw->sw.num_current_drawing != 0) {
+ (void) ClipAndDraw(dsw, DSWBackingPixmap, DSWFinish, True);
+ }
+ } else {
+ if (dsw->sw.backing_pixmap != None) {
+ if (dsw->sw.num_pending_expose != 0) {
+ CopyPendingExpose(dsw);
+ }
+
+ if (dsw->sw.minimal_drawing && dsw->sw.big_pixmap) {
+ dsw->sw.drawing_stage = DSWDrewVisible;
+ SetCurrentDrawingToBackground(dsw);
+ (void) ClipAndDraw(dsw, which, DSWFinish, True);
+ }
+ }
+ }
+ break;
+
+ case DSWDrewVisible:
+ case DSWDrawingBackground:
+ (void) ClipAndDraw(dsw, DSWBackingPixmap, DSWFinish,
+ (dsw->sw.drawing_stage == DSWDrewVisible));
+ break;
+
+ case DSWDone:
+ break;
+ }
+
+ dsw->sw.drawing_stage = DSWDone;
+ dsw->sw.num_dirty_areas = 0;
+}
+
+static void DoScroll(
+ DPSScrolledWindowWidget dsw,
+ int deltaX, int deltaY)
+{
+ /* Set the PS origin in the X window to the new settings of
+ the scrollbars */
+ dsw->sw.origin_x -= deltaX;
+ dsw->sw.origin_y -= deltaY;
+
+ /* Update the graphics states for the window and backing pixmap to
+ reflect new origin */
+ (void) XDPSSetContextGState(dsw->sw.context, dsw->sw.window_gstate);
+ SetOriginAndGetTransform(dsw);
+ (void) XDPSUpdateContextGState(dsw->sw.context, dsw->sw.window_gstate);
+
+ if (dsw->sw.backing_pixmap != None && !dsw->sw.big_pixmap) {
+ (void) XDPSSetContextGState(dsw->sw.context, dsw->sw.backing_gstate);
+ SetPixmapOrigin(dsw);
+ (void) XDPSUpdateContextGState(dsw->sw.context,
+ dsw->sw.backing_gstate);
+ }
+
+ /* Update the stored position of the scroll bars */
+ dsw->sw.scroll_x += deltaX;
+ dsw->sw.scroll_y += deltaY;
+}
+
+static void ShiftPendingExpose(
+ DPSScrolledWindowWidget dsw,
+ int deltaX, int deltaY)
+{
+ int i;
+ int *r;
+
+ for (i = 0; i < dsw->sw.num_pending_expose; i++) {
+ r = dsw->sw.pending_expose + 4*i;
+ r[0] -= deltaX;
+ r[1] -= deltaY;
+ }
+}
+
+static void HScrollCallback(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) clientData;
+ XmScrollBarCallbackStruct *sb = (XmScrollBarCallbackStruct *) callData;
+
+ if (!dsw->sw.application_scrolling) {
+ dsw->sw.scroll_h_value = sb->value;
+ ScrollMoved(dsw);
+ }
+}
+
+static void VScrollCallback(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) clientData;
+ XmScrollBarCallbackStruct *sb = (XmScrollBarCallbackStruct *) callData;
+
+ if (!dsw->sw.application_scrolling) {
+ dsw->sw.scroll_v_value = sb->value;
+ ScrollMoved(dsw);
+ }
+}
+
+/* ARGSUSED */
+
+static void ScrollMoved(DPSScrolledWindowWidget dsw)
+{
+ int deltaX, deltaY;
+
+ /* If we haven't started drawing yet, it must be because we're waiting
+ for GraphicsExpose events. Delay scrolling until they come in */
+ if (dsw->sw.scrolling && dsw->sw.drawing_stage == DSWStart) return;
+
+ /* Calculate the delta in the scrolling */
+ deltaX = dsw->sw.scroll_h_value - dsw->sw.scroll_x;
+ deltaY = dsw->sw.scroll_v_value - dsw->sw.scroll_y;
+
+ /* If there is some scrolling to do, then scroll the pixmap and
+ copy the pixmap to the window */
+ if (deltaX == 0 && deltaY == 0) return;
+
+ ShiftPendingExpose(dsw, deltaX, deltaY);
+
+ AbortOrFinish(dsw);
+
+ DoScroll(dsw, deltaX, deltaY);
+
+ if (!dsw->sw.big_pixmap) {
+ /* Copy visible area to new location */
+ if (dsw->sw.backing_pixmap != None) {
+ XCopyArea(XtDisplay(dsw), dsw->sw.backing_pixmap,
+ dsw->sw.backing_pixmap, dsw->sw.no_ge_gc,
+ deltaX, deltaY, dsw->sw.drawing_area->core.width,
+ dsw->sw.drawing_area->core.height, 0, 0);
+ if (!dsw->sw.doing_feedback || dsw->sw.feedback_pixmap == None) {
+ XCopyArea(XtDisplay(dsw), dsw->sw.backing_pixmap,
+ XtWindow(dsw->sw.drawing_area), dsw->sw.no_ge_gc,
+ 0, 0, dsw->sw.drawing_area->core.width,
+ dsw->sw.drawing_area->core.height, 0, 0);
+ }
+ RedisplaySliver(dsw, deltaX, deltaY);
+ } else {
+ if (!dsw->sw.doing_feedback || dsw->sw.feedback_pixmap == None) {
+ XCopyArea(XtDisplay(dsw), XtWindow(dsw->sw.drawing_area),
+ XtWindow(dsw->sw.drawing_area), dsw->sw.ge_gc,
+ deltaX, deltaY, dsw->sw.drawing_area->core.width,
+ dsw->sw.drawing_area->core.height, 0, 0);
+ }
+ if (dsw->sw.doing_feedback) RedisplaySliver(dsw, deltaX, deltaY);
+ else dsw->sw.drawing_stage = DSWStart;
+ }
+ }
+
+ if (dsw->sw.doing_feedback) {
+ float *r;
+
+ FinishDrawing(dsw);
+
+ r = dsw->sw.prev_dirty_areas;
+ ConvertToPS(dsw, 0 + DELTA, dsw->sw.drawing_area->core.height - DELTA,
+ r, r+1);
+ ConvertToPS(dsw, dsw->sw.drawing_area->core.width - DELTA, 0 + DELTA,
+ r+2, r+3);
+ r[2] -= r[0];
+ r[3] -= r[1];
+ dsw->sw.num_prev_dirty_areas = 1;
+
+ if (dsw->sw.feedback_pixmap != None) {
+ XDPSSetContextDrawable(dsw->sw.context, dsw->sw.feedback_pixmap,
+ dsw->sw.drawing_area->core.height);
+ SetPixmapOrigin(dsw);
+ XDPSCaptureContextGState(dsw->sw.context,
+ &dsw->sw.feedback_gstate);
+
+ /* Initialize the feedback pixmap with a copy of the drawing */
+ if (dsw->sw.backing_pixmap != None) {
+ CopyToFeedbackPixmap(dsw, dsw->sw.prev_dirty_areas,
+ dsw->sw.num_prev_dirty_areas);
+ } else {
+ CopyRectsToCurrentDrawing(dsw, dsw->sw.prev_dirty_areas,
+ dsw->sw.num_prev_dirty_areas);
+ (void) ClipAndDraw(dsw, DSWFeedbackPixmap, DSWFinish, True);
+ }
+ if (!dsw->sw.feedback_displayed) {
+ XCopyArea(XtDisplay(dsw), dsw->sw.feedback_pixmap,
+ XtWindow(dsw->sw.drawing_area),
+ dsw->sw.no_ge_gc, 0, 0,
+ dsw->sw.drawing_area->core.width,
+ dsw->sw.drawing_area->core.height, 0, 0);
+ }
+ }
+
+ if (dsw->sw.feedback_displayed) {
+ CallFeedbackCallback(dsw, dsw->sw.prev_dirty_areas,
+ dsw->sw.num_prev_dirty_areas);
+ }
+ if (dsw->sw.feedback_pixmap != None) {
+ UpdateWindowFromFeedbackPixmap(dsw, dsw->sw.prev_dirty_areas,
+ dsw->sw.num_prev_dirty_areas);
+ }
+ dsw->sw.num_pending_dirty = dsw->sw.num_pending_expose = 0;
+
+ } else {
+ if (dsw->sw.backing_pixmap != None &&
+ dsw->sw.drawing_stage == DSWDone) {
+ ComputeOffsets(dsw, &deltaX, &deltaY);
+ if (!dsw->sw.big_pixmap) dsw->sw.scrolling = True;
+
+ XCopyArea(XtDisplay(dsw), dsw->sw.backing_pixmap,
+ XtWindow(dsw->sw.drawing_area), dsw->sw.no_ge_gc,
+ deltaX, deltaY,
+ dsw->sw.drawing_area->core.width,
+ dsw->sw.drawing_area->core.height, 0, 0);
+ } else dsw->sw.scrolling = True;
+ }
+}
+
+static void AddExposureToPending(
+ DPSScrolledWindowWidget dsw,
+ XExposeEvent *ev)
+{
+ float *f;
+ int *i;
+
+ if (dsw->sw.backing_pixmap == None || dsw->sw.watch_progress ||
+ dsw->sw.doing_feedback) {
+ GrowRectList(&dsw->sw.pending_dirty, &dsw->sw.pending_dirty_size,
+ dsw->sw.num_pending_dirty, 1, 1);
+
+ f = dsw->sw.pending_dirty + (dsw->sw.num_pending_dirty * 4);
+ ConvertToPS(dsw, ev->x + DELTA, ev->y + ev->height - DELTA, f, f+1);
+ ConvertToPS(dsw, ev->x + ev->width - DELTA, ev->y + DELTA, f+2, f+3);
+ f[2] -= f[0];
+ f[3] -= f[1];
+ dsw->sw.num_pending_dirty++;
+ }
+
+ GrowIntRectList(&dsw->sw.pending_expose, &dsw->sw.pending_expose_size,
+ dsw->sw.num_pending_expose, 1, 1);
+
+ i = dsw->sw.pending_expose + (dsw->sw.num_pending_expose * 4);
+ i[0] = ev->x;
+ i[1] = ev->y;
+ i[2] = ev->width;
+ i[3] = ev->height;
+ dsw->sw.num_pending_expose++;
+}
+
+static void AddRectsToPending(
+ DPSScrolledWindowWidget dsw,
+ int *newRect,
+ int n)
+{
+ int *r;
+ int i;
+ float *f;
+
+ if (dsw->sw.backing_pixmap == None || dsw->sw.watch_progress) {
+ GrowRectList(&dsw->sw.pending_dirty, &dsw->sw.pending_dirty_size,
+ dsw->sw.num_pending_dirty, n, 1);
+
+ for (i = 0; i < n; i++) {
+ f = dsw->sw.pending_dirty + (dsw->sw.num_pending_dirty * 4);
+ r = newRect + (i * 4);
+ ConvertToPS(dsw, r[0] + DELTA, r[1] + r[3] - DELTA, f, f+1);
+ ConvertToPS(dsw, r[0] + r[2] - DELTA, r[1] + DELTA, f+2, f+3);
+ f[2] -= f[0];
+ f[3] -= f[1];
+ dsw->sw.num_pending_dirty++;
+ }
+ }
+
+ GrowIntRectList(&dsw->sw.pending_expose, &dsw->sw.pending_expose_size,
+ dsw->sw.num_pending_expose, n, 1);
+
+ r = dsw->sw.pending_expose + (dsw->sw.num_pending_expose * 4);
+ for (i = 0; i < 4*n; i++) r[i] = newRect[i];
+ dsw->sw.num_pending_expose += n;
+}
+
+static void AddUserSpaceRectsToPending(
+ DPSScrolledWindowWidget dsw,
+ float *newRect,
+ int n)
+{
+ int *r;
+ int i;
+ float *f;
+
+ if (dsw->sw.backing_pixmap == None || dsw->sw.watch_progress) {
+ GrowRectList(&dsw->sw.pending_dirty, &dsw->sw.pending_dirty_size,
+ dsw->sw.num_pending_dirty, n, 1);
+
+ f = dsw->sw.pending_dirty + (dsw->sw.num_pending_dirty * 4);
+ for (i = 0; i < 4*n; i++) f[i] = newRect[i];
+ dsw->sw.num_pending_dirty += n;
+ }
+
+ GrowIntRectList(&dsw->sw.pending_expose, &dsw->sw.pending_expose_size,
+ dsw->sw.num_pending_expose, n, 1);
+
+ for (i = 0; i < n; i++) {
+ r = dsw->sw.pending_expose + (dsw->sw.num_pending_expose * 4);
+ f = newRect + (i * 4);
+ ConvertToX(dsw, LEFT(f), TOP(f), r, r+1);
+ ConvertToX(dsw, RIGHT(f), BOTTOM(f), r+2, r+3);
+ r[2] -= r[0];
+ r[3] -= r[1];
+ dsw->sw.num_pending_expose++;
+ }
+}
+
+static void CopyRectsToCurrentDrawing(
+ DPSScrolledWindowWidget dsw,
+ float *newRect,
+ int n)
+{
+ float *r;
+ int i;
+
+ GrowRectList(&dsw->sw.current_drawing, &dsw->sw.current_drawing_size,
+ 0, n, 1);
+
+ r = dsw->sw.current_drawing;
+ for (i = 0; i < 4*n; i++) r[i] = newRect[i];
+ dsw->sw.num_current_drawing = n;
+}
+
+static void CopyRectsToDirtyArea(
+ DPSScrolledWindowWidget dsw,
+ float *newRect,
+ int n)
+{
+ float *r;
+ int i;
+
+ GrowRectList(&dsw->sw.dirty_areas, &dsw->sw.dirty_areas_size, 0, n, 1);
+
+ r = dsw->sw.dirty_areas;
+ for (i = 0; i < 4*n; i++) r[i] = newRect[i];
+ dsw->sw.num_dirty_areas = n;
+}
+
+static void AddRectsToDirtyArea(
+ DPSScrolledWindowWidget dsw,
+ float *newRect,
+ int n)
+{
+ float *r;
+ int i;
+
+ GrowRectList(&dsw->sw.dirty_areas, &dsw->sw.dirty_areas_size,
+ dsw->sw.num_dirty_areas, n, 1);
+
+ r = dsw->sw.dirty_areas + (4 * dsw->sw.num_dirty_areas);
+ for (i = 0; i < 4*n; i++) r[i] = newRect[i];
+ dsw->sw.num_dirty_areas += n;
+}
+
+static void CopyRectsToPrevDirtyArea(
+ DPSScrolledWindowWidget dsw,
+ float *newRect,
+ int n)
+{
+ float *r;
+ int i;
+
+ GrowRectList(&dsw->sw.prev_dirty_areas,
+ &dsw->sw.prev_dirty_areas_size, 0, n, 1);
+
+ r = dsw->sw.prev_dirty_areas;
+ for (i = 0; i < 4*n; i++) r[i] = newRect[i];
+ dsw->sw.num_prev_dirty_areas = n;
+}
+
+/* ARGSUSED */
+
+static void DrawingAreaGraphicsExpose(
+ Widget w,
+ XtPointer clientData,
+ XEvent *event,
+ Boolean *goOn)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) clientData;
+ XExposeEvent *ev = (XExposeEvent *) event;
+
+ switch (event->type) {
+ case GraphicsExpose:
+ /* GraphicsExpose occur during unbuffered scrolling */
+ if (dsw->sw.backing_pixmap == None && dsw->sw.scrolling) {
+ /* Unbuffered scrolling case */
+ AddExposureToPending(dsw, ev);
+
+ if (ev->count == 0) {
+ AddRectsToDirtyArea(dsw, dsw->sw.pending_dirty,
+ dsw->sw.num_pending_dirty);
+ StartDrawing(dsw);
+ dsw->sw.num_pending_dirty = dsw->sw.num_pending_expose = 0;
+ }
+ }
+ break;
+ }
+}
+
+static Boolean MoreExposes(Widget w)
+{
+ XEvent event;
+
+ if (XPending(XtDisplay(w)) > 0) {
+ if (XCheckTypedWindowEvent(XtDisplay(w), XtWindow(w),
+ Expose, &event)) {
+ XPutBackEvent(XtDisplay(w), &event);
+ return True;;
+ }
+ }
+ return False;
+}
+
+static void DrawingAreaExpose(
+ Widget w,
+ XtPointer clientData, XtPointer callData)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) clientData;
+ XmDrawingAreaCallbackStruct *d = (XmDrawingAreaCallbackStruct *) callData;
+ XExposeEvent *ev = (XExposeEvent *) d->event;
+ int dx, dy;
+
+ if (dsw->sw.doing_feedback) {
+ if (dsw->sw.feedback_pixmap != None) {
+ XCopyArea(XtDisplay(dsw), dsw->sw.feedback_pixmap,
+ XtWindow(dsw->sw.drawing_area),
+ dsw->sw.no_ge_gc,
+ ev->x, ev->y, ev->width, ev->height, ev->x, ev->y);
+ } else {
+ if (dsw->sw.backing_pixmap != None) {
+ ComputeOffsets(dsw, &dx, &dy);
+
+ XCopyArea(XtDisplay(dsw), dsw->sw.backing_pixmap,
+ XtWindow(dsw->sw.drawing_area),
+ dsw->sw.no_ge_gc, ev->x + dx, ev->y + dy,
+ ev->width, ev->height, ev->x, ev->y);
+ }
+ AddExposureToPending(dsw, ev);
+ if (ev->count != 0 || MoreExposes(w)) return;
+
+ if (dsw->sw.backing_pixmap == None) {
+ CopyRectsToCurrentDrawing(dsw, dsw->sw.pending_dirty,
+ dsw->sw.num_pending_dirty);
+ dsw->sw.drawing_stage = DSWStart;
+ FinishDrawing(dsw);
+ }
+ if (dsw->sw.feedback_displayed) {
+ CallFeedbackCallback(dsw, dsw->sw.pending_dirty,
+ dsw->sw.num_pending_dirty);
+ }
+ dsw->sw.num_pending_dirty = dsw->sw.num_pending_expose = 0;
+ }
+ return;
+ }
+
+ if (dsw->sw.backing_pixmap != None) {
+ if (dsw->sw.drawing_stage == DSWStart && dsw->sw.watch_progress) {
+ SplitExposeEvent(dsw, ev);
+ if (ev->count == 0) {
+ if (MoreExposes(w)) return;
+ StartDrawing(dsw);
+ dsw->sw.num_pending_dirty = dsw->sw.num_pending_expose = 0;
+ }
+ return;
+ }
+
+ if (dsw->sw.drawing_stage < DSWDrewVisible) {
+ SplitExposeEvent(dsw, ev);
+ return;
+ }
+ ComputeOffsets(dsw, &dx, &dy);
+
+ XCopyArea(XtDisplay(dsw), dsw->sw.backing_pixmap,
+ XtWindow(dsw->sw.drawing_area),
+ dsw->sw.no_ge_gc,
+ ev->x + dx, ev->y + dy, ev->width, ev->height, ev->x, ev->y);
+ } else {
+ AddExposureToPending(dsw, ev);
+ if (ev->count == 0) {
+ if (MoreExposes(w)) return;
+ if (dsw->sw.drawing_stage == DSWDone ||
+ dsw->sw.drawing_stage == DSWStart) {
+ CopyRectsToDirtyArea(dsw, dsw->sw.pending_dirty,
+ dsw->sw.num_pending_dirty);
+ StartDrawing(dsw);
+ dsw->sw.num_pending_dirty = dsw->sw.num_pending_expose = 0;
+ }
+ }
+ }
+}
+
+static void Resize(Widget w)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
+ DSWResizeCallbackRec r;
+ float x, y;
+
+ if (XtIsRealized(w)) (void) AbortOrFinish(dsw);
+
+ r.oldw = dsw->sw.scrolled_window->core.width;
+ r.oldh = dsw->sw.scrolled_window->core.height;
+ r.neww = dsw->core.width;
+ r.newh = dsw->core.height;
+ r.x = r.y = 0;
+
+ XtCallCallbackList(w, dsw->sw.resize_callback, (XtPointer) &r);
+
+ if (XtIsRealized(w)) {
+ ConvertToPS(dsw, (float) r.x, (float) r.y, &x, &y);
+ } else if (r.x != 0 || r.y != 0) ScrollBy(w, r.x, r.y);
+
+ XtResizeWidget(dsw->sw.scrolled_window, w->core.width, w->core.height, 0);
+
+ if (!XtIsRealized(w)) return;
+
+ if (dsw->sw.backing_pixmap != None &&
+ dsw->sw.pixmap_width == CEIL(dsw->sw.drawing_width) &&
+ dsw->sw.pixmap_height == CEIL(dsw->sw.drawing_height) &&
+ dsw->sw.pixmap_width >= (int) dsw->sw.drawing_area->core.width &&
+ dsw->sw.pixmap_height >= (int) dsw->sw.drawing_area->core.width) {
+
+ XDPSSetContextGState(dsw->sw.context, dsw->sw.window_gstate);
+ DPSinitclip(dsw->sw.context);
+ DPSinitviewclip(dsw->sw.context);
+ SetDrawingAreaPosition(dsw, x, y, r.x, r.y, True);
+ SetOriginAndGetTransform(dsw);
+ XDPSUpdateContextGState(dsw->sw.context, dsw->sw.window_gstate);
+ XClearArea(XtDisplay(dsw), XtWindow(dsw->sw.drawing_area),
+ 0, 0, 0, 0, True);
+ } else {
+ dsw->sw.use_saved_scroll = True;
+ dsw->sw.scroll_pic_x = x;
+ dsw->sw.scroll_pic_y = y;
+ dsw->sw.scroll_win_x = r.x;
+ dsw->sw.scroll_win_y = r.y;
+
+ if (dsw->sw.backing_pixmap != None) {
+ XFreePixmap(XtDisplay(dsw), dsw->sw.backing_pixmap);
+ XDPSFreeContextGState(dsw->sw.context, dsw->sw.backing_gstate);
+ }
+ dsw->sw.backing_pixmap = None;
+ dsw->sw.big_pixmap = False;
+ dsw->sw.pixmap_width = dsw->sw.pixmap_height = 0;
+
+ dsw->sw.num_dirty_areas = 1;
+ LEFT(dsw->sw.dirty_areas) = 0.0;
+ BOTTOM(dsw->sw.dirty_areas) = 0.0;
+ WIDTH(dsw->sw.dirty_areas) = dsw->sw.area_width;
+ HEIGHT(dsw->sw.dirty_areas) = dsw->sw.area_height;
+
+ SetUpInitialInformation(dsw);
+ }
+
+ if (dsw->sw.doing_feedback) {
+ float *r;
+ int dx, dy;
+
+ CheckFeedbackPixmap(dsw);
+ r = dsw->sw.prev_dirty_areas;
+ ConvertToPS(dsw, 0 + DELTA, dsw->sw.drawing_area->core.height - DELTA,
+ r, r+1);
+ ConvertToPS(dsw, dsw->sw.drawing_area->core.width - DELTA, 0 + DELTA,
+ r+2, r+3);
+ r[2] -= r[0];
+ r[3] -= r[1];
+ dsw->sw.num_prev_dirty_areas = 1;
+
+ if (dsw->sw.feedback_pixmap != None) {
+ /* Initialize the feedback pixmap with a copy of the drawing */
+ if (dsw->sw.backing_pixmap != None) {
+ CopyToFeedbackPixmap(dsw, dsw->sw.prev_dirty_areas,
+ dsw->sw.num_prev_dirty_areas);
+ } else {
+ CopyRectsToCurrentDrawing(dsw, dsw->sw.prev_dirty_areas,
+ dsw->sw.num_prev_dirty_areas);
+ (void) ClipAndDraw(dsw, DSWFeedbackPixmap, DSWFinish, True);
+ }
+ XCopyArea(XtDisplay(dsw), dsw->sw.feedback_pixmap,
+ XtWindow(dsw->sw.drawing_area),
+ dsw->sw.no_ge_gc, 0, 0,
+ dsw->sw.drawing_area->core.width,
+ dsw->sw.drawing_area->core.height, 0, 0);
+ } else {
+ if (dsw->sw.backing_pixmap != None) {
+ ComputeOffsets(dsw, &dx, &dy);
+
+ XCopyArea(XtDisplay(dsw), dsw->sw.backing_pixmap,
+ XtWindow(dsw->sw.drawing_area),
+ dsw->sw.no_ge_gc, dx, dy,
+ dsw->sw.drawing_area->core.width,
+ dsw->sw.drawing_area->core.height, 0, 0);
+ } else {
+ CopyRectsToCurrentDrawing(dsw, dsw->sw.prev_dirty_areas,
+ dsw->sw.num_prev_dirty_areas);
+ dsw->sw.drawing_stage = DSWStart;
+ FinishDrawing(dsw);
+ }
+ }
+ if (dsw->sw.feedback_displayed) {
+ CallFeedbackCallback(dsw, dsw->sw.prev_dirty_areas,
+ dsw->sw.num_prev_dirty_areas);
+ }
+ if (dsw->sw.feedback_pixmap != None) {
+ UpdateWindowFromFeedbackPixmap(dsw, dsw->sw.prev_dirty_areas,
+ dsw->sw.num_prev_dirty_areas);
+ }
+ dsw->sw.num_pending_dirty = dsw->sw.num_pending_expose = 0;
+ }
+}
+
+static void CheckFeedbackPixmap(DPSScrolledWindowWidget dsw)
+{
+ if (dsw->sw.feedback_pixmap != None &&
+ (dsw->sw.feedback_width < (int) dsw->sw.drawing_area->core.width ||
+ dsw->sw.feedback_height < (int) dsw->sw.drawing_area->core.height)) {
+ XFreePixmap(XtDisplay(dsw), dsw->sw.feedback_pixmap);
+ dsw->sw.feedback_pixmap = None;
+ dsw->sw.feedback_width = dsw->sw.feedback_height = 0;
+ }
+ if (dsw->sw.use_feedback_pixmap && dsw->sw.feedback_pixmap == None) {
+ dsw->sw.feedback_pixmap =
+ AllocPixmap(dsw, dsw->sw.drawing_area->core.width,
+ dsw->sw.drawing_area->core.height);
+ if (dsw->sw.feedback_pixmap != None) {
+ dsw->sw.feedback_width = dsw->sw.drawing_area->core.width;
+ dsw->sw.feedback_height = dsw->sw.drawing_area->core.height;
+ }
+ }
+ if (dsw->sw.feedback_pixmap != None) {
+ XDPSSetContextDrawable(dsw->sw.context, dsw->sw.feedback_pixmap,
+ dsw->sw.drawing_area->core.height);
+ SetPixmapOrigin(dsw);
+ XDPSCaptureContextGState(dsw->sw.context, &dsw->sw.feedback_gstate);
+ }
+}
+
+static void UpdateGStates(DPSScrolledWindowWidget dsw)
+{
+ /* Create graphics states for the window and backing pixmap in
+ the new context */
+ XDPSSetContextDrawable(dsw->sw.context, XtWindow(dsw->sw.drawing_area),
+ dsw->sw.drawing_area->core.height);
+ DPSinitgraphics(dsw->sw.context);
+ if (dsw->sw.scale != 1.0) {
+ DPSscale(dsw->sw.context, dsw->sw.scale, dsw->sw.scale);
+ }
+
+ SetOriginAndGetTransform(dsw);
+ (void) XDPSCaptureContextGState(dsw->sw.context, &dsw->sw.window_gstate);
+ if (dsw->sw.backing_pixmap != None) {
+ XDPSSetContextDrawable(dsw->sw.context, dsw->sw.backing_pixmap,
+ dsw->sw.pixmap_height);
+
+ SetPixmapOffset(dsw);
+ SetPixmapOrigin(dsw);
+ XDPSCaptureContextGState(dsw->sw.context, &dsw->sw.backing_gstate);
+ }
+}
+
+static void CheckPixmapSize(DPSScrolledWindowWidget dsw)
+{
+ Boolean freeIt = False;
+ int w = dsw->sw.pixmap_width, h = dsw->sw.pixmap_height;
+ Widget wid = dsw->sw.drawing_area;
+ unsigned int dBytes;
+
+ if (dsw->sw.pixmap_limit > 0) {
+ if (w * h > dsw->sw.pixmap_limit) freeIt = True;
+ } else if (dsw->sw.pixmap_limit < 0 &&
+ w * h > dsw->sw.unscaled_width * dsw->sw.unscaled_height &&
+ w * h > (int) wid->core.width * (int) wid->core.height) {
+ freeIt = True;
+ }
+
+ if (dsw->sw.absolute_pixmap_limit > 0) {
+ dBytes = (wid->core.depth + 7) / 8; /* Convert into bytes */
+ if (w * h * dBytes > (unsigned)dsw->sw.absolute_pixmap_limit * 1024) {
+ freeIt = True;
+ }
+ }
+ if (freeIt) {
+ XFreePixmap(XtDisplay(dsw), dsw->sw.backing_pixmap);
+ dsw->sw.backing_pixmap = None;
+ dsw->sw.big_pixmap = False;
+ dsw->sw.pixmap_width = dsw->sw.pixmap_height = 0;
+ XDPSFreeContextGState(dsw->sw.context, dsw->sw.backing_gstate);
+ }
+}
+
+static void ResizeArea(DPSScrolledWindowWidget dsw)
+{
+ AbortDrawing(dsw);
+
+ /* Make everything dirty */
+ dsw->sw.num_dirty_areas = 1;
+ LEFT(dsw->sw.dirty_areas) = 0.0;
+ BOTTOM(dsw->sw.dirty_areas) = 0.0;
+ WIDTH(dsw->sw.dirty_areas) = dsw->sw.area_width;
+ HEIGHT(dsw->sw.dirty_areas) = dsw->sw.area_height;
+
+ if (dsw->sw.big_pixmap) {
+ XFreePixmap(XtDisplay(dsw), dsw->sw.backing_pixmap);
+ dsw->sw.backing_pixmap = None;
+ dsw->sw.big_pixmap = False;
+ dsw->sw.pixmap_width = dsw->sw.pixmap_height = 0;
+ XDPSFreeContextGState(dsw->sw.context, dsw->sw.backing_gstate);
+ }
+
+ if (!dsw->sw.use_saved_scroll) {
+ /* Keep the upper left in the same place */
+ dsw->sw.scroll_win_x = 0;
+ dsw->sw.scroll_win_y = 0;
+ ConvertToPS(dsw, 0.0, 0.0,
+ &dsw->sw.scroll_pic_x, &dsw->sw.scroll_pic_y);
+ dsw->sw.use_saved_scroll = True;
+ }
+
+ SetUpInitialInformation(dsw);
+}
+
+static void ClearDirtyAreas(DPSScrolledWindowWidget dsw)
+{
+ int i;
+ float *r;
+ int llx, lly, urx, ury;
+
+ for (i = 0; i < dsw->sw.num_dirty_areas; i++) {
+ r = dsw->sw.dirty_areas + (i * 4);
+ ConvertToX(dsw, LEFT(r), BOTTOM(r), &llx, &lly);
+ ConvertToX(dsw, RIGHT(r), TOP(r), &urx, &ury);
+ XClearArea(XtDisplay(dsw), XtWindow(dsw->sw.drawing_area),
+ llx, ury, urx-llx, lly-ury, True);
+ }
+}
+
+static void HandleFeedbackPixmapChange(DPSScrolledWindowWidget dsw)
+{
+ if (!dsw->sw.use_feedback_pixmap) {
+ /* Get rid of one if we have it */
+ if (dsw->sw.feedback_pixmap != None) {
+ XFreePixmap(XtDisplay(dsw), dsw->sw.feedback_pixmap);
+ dsw->sw.feedback_pixmap = None;
+ dsw->sw.feedback_width = dsw->sw.feedback_height = 0;
+ }
+ } else {
+ if (dsw->sw.doing_feedback) {
+ float *r;
+
+ CheckFeedbackPixmap(dsw);
+ if (dsw->sw.feedback_pixmap == None) return;
+
+ r = dsw->sw.prev_dirty_areas;
+ ConvertToPS(dsw, 0 + DELTA,
+ dsw->sw.drawing_area->core.height - DELTA, r, r+1);
+ ConvertToPS(dsw, dsw->sw.drawing_area->core.width - DELTA,
+ 0 + DELTA, r+2, r+3);
+ r[2] -= r[0];
+ r[3] -= r[1];
+ dsw->sw.num_prev_dirty_areas = 1;
+
+ /* Initialize the feedback pixmap with a copy of the drawing */
+ if (dsw->sw.backing_pixmap != None) {
+ CopyToFeedbackPixmap(dsw, dsw->sw.prev_dirty_areas,
+ dsw->sw.num_prev_dirty_areas);
+ } else {
+ CopyRectsToCurrentDrawing(dsw, dsw->sw.prev_dirty_areas,
+ dsw->sw.num_prev_dirty_areas);
+ (void) ClipAndDraw(dsw, DSWFeedbackPixmap, DSWFinish, True);
+ }
+ if (dsw->sw.feedback_displayed) {
+ CallFeedbackCallback(dsw, dsw->sw.prev_dirty_areas,
+ dsw->sw.num_prev_dirty_areas);
+ }
+ }
+ }
+}
+
+/* ARGSUSED */
+
+static Boolean SetValues(
+ Widget old, Widget req, Widget new,
+ ArgList args,
+ Cardinal *num_args)
+{
+ DPSScrolledWindowWidget olddsw = (DPSScrolledWindowWidget) old;
+ DPSScrolledWindowWidget newdsw = (DPSScrolledWindowWidget) new;
+ Bool inited;
+
+#define NE(field) newdsw->sw.field != olddsw->sw.field
+#define DONT_CHANGE(field) \
+ if (NE(field)) newdsw->sw.field = olddsw->sw.field;
+
+ DONT_CHANGE(ctm_ptr);
+ DONT_CHANGE(inv_ctm_ptr);
+ DONT_CHANGE(backing_pixmap);
+ DONT_CHANGE(feedback_pixmap);
+ DONT_CHANGE(window_gstate);
+ DONT_CHANGE(backing_gstate);
+ DONT_CHANGE(feedback_gstate);
+
+ if (NE(context)) {
+ DSWSetupCallbackRec setup;
+
+ if (newdsw->sw.context == NULL) {
+ newdsw->sw.context = XDPSGetSharedContext(XtDisplay(newdsw));
+ }
+ if (_XDPSTestComponentInitialized(newdsw->sw.context,
+ dps_init_bit_dsw, &inited) ==
+ dps_status_unregistered_context) {
+ XDPSRegisterContext(newdsw->sw.context, False);
+ }
+ if (XtIsRealized(newdsw)) {
+ setup.context = newdsw->sw.context;
+ XtCallCallbackList((Widget) newdsw, newdsw->sw.setup_callback,
+ (XtPointer) &setup);
+ }
+ UpdateGStates(newdsw);
+ }
+
+ /* Watch progress only works with pass-through event dispatching */
+
+ if (NE(watch_progress)) {
+ if (newdsw->sw.watch_progress &&
+ XDPSSetEventDelivery(XtDisplay(newdsw), dps_event_query) !=
+ dps_event_pass_through) newdsw->sw.watch_progress = False;
+ }
+
+ if (NE(application_scrolling) && !newdsw->sw.application_scrolling) {
+ XtVaSetValues(newdsw->sw.h_scroll, XmNmaximum, newdsw->sw.scroll_h_max,
+ XmNvalue, newdsw->sw.scroll_h_value,
+ XmNsliderSize, newdsw->sw.scroll_h_size, NULL);
+ XtVaSetValues(newdsw->sw.v_scroll, XmNmaximum, newdsw->sw.scroll_v_max,
+ XmNvalue, newdsw->sw.scroll_v_value,
+ XmNsliderSize, newdsw->sw.scroll_v_size, NULL);
+ }
+
+ if (newdsw->sw.doing_feedback) {
+ DONT_CHANGE(scale);
+ DONT_CHANGE(area_width);
+ DONT_CHANGE(area_height);
+ }
+
+ if (NE(pixmap_limit) || NE(absolute_pixmap_limit)) CheckPixmapSize(newdsw);
+
+ if (NE(area_width) || NE(area_height) || NE(scale)) ResizeArea(newdsw);
+
+ /* It's too confusing to let any of these things change in the middle
+ of drawing */
+
+ if (NE(use_backing_pixmap) || NE(watch_progress) ||
+ NE(minimal_drawing) || NE(document_size_pixmaps)) {
+ Boolean freeIt = False, setUp = False;
+ AbortOrFinish(newdsw);
+ if (NE(use_backing_pixmap)) {
+ if (newdsw->sw.use_backing_pixmap) setUp = True;
+ else freeIt = True;
+ }
+ if (NE(document_size_pixmaps)) {
+ if (newdsw->sw.backing_pixmap != None) freeIt = True;
+ setUp = True;
+ }
+ if (freeIt) FreeBackingPixmap(newdsw);
+ if (setUp) SetUpInitialPixmap(newdsw);
+ }
+
+ if (NE(dirty_areas)) {
+ float *r = newdsw->sw.dirty_areas;
+ int n = newdsw->sw.num_dirty_areas;
+ DONT_CHANGE(dirty_areas);
+ DONT_CHANGE(num_dirty_areas);
+ AbortOrFinish(newdsw);
+ AddRectsToDirtyArea(newdsw, r, n);
+ if (newdsw->sw.watch_progress || newdsw->sw.backing_pixmap == None) {
+ ClearDirtyAreas(newdsw);
+ newdsw->sw.drawing_stage = DSWStart;
+ } else {
+ AddUserSpaceRectsToPending(newdsw, r, n);
+ StartDrawing(newdsw);
+ }
+ }
+
+ if (NE(use_feedback_pixmap)) HandleFeedbackPixmapChange(newdsw);
+
+ return False;
+#undef DONT_CHANGE
+}
+
+static XtGeometryResult GeometryManager(
+ Widget w,
+ XtWidgetGeometry *desired, XtWidgetGeometry *allowed)
+{
+ /* Pass geometry requests up to our parent */
+ return XtMakeGeometryRequest(XtParent(w), desired, allowed);
+}
+
+static XtGeometryResult QueryGeometry(
+ Widget w,
+ XtWidgetGeometry *desired, XtWidgetGeometry *allowed)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
+
+ /* Pass geometry requests down to our child */
+ return XtQueryGeometry(dsw->sw.scrolled_window, desired, allowed);
+}
+
+static void CopyToFeedbackPixmap(
+ DPSScrolledWindowWidget dsw,
+ float *rects,
+ int n)
+{
+ int llx, lly, urx, ury;
+ int dx, dy;
+ int i;
+ float *r;
+
+ ComputeOffsets(dsw, &dx, &dy);
+
+ for (i = 0; i < n; i++) {
+ r = rects + (i * 4);
+ ConvertToX(dsw, LEFT(r), BOTTOM(r), &llx, &lly);
+ ConvertToX(dsw, RIGHT(r), TOP(r), &urx, &ury);
+
+ XCopyArea(XtDisplay(dsw), dsw->sw.backing_pixmap,
+ dsw->sw.feedback_pixmap, dsw->sw.no_ge_gc,
+ llx+dx-1, ury+dy-1, urx-llx+2, lly-ury+2, llx-1, ury-1);
+ }
+}
+
+static void CallFeedbackCallback(
+ DPSScrolledWindowWidget dsw,
+ float *r,
+ int n)
+{
+ DSWFeedbackCallbackRec f;
+
+ f.start_feedback_data = dsw->sw.start_feedback_data;
+ f.continue_feedback_data = dsw->sw.continue_feedback_data;
+ if (dsw->sw.feedback_pixmap == None) {
+ f.type = DSWWindow;
+ f.drawable = XtWindow(dsw->sw.drawing_area);
+ f.gstate = dsw->sw.window_gstate;
+ } else {
+ f.type = DSWFeedbackPixmap;
+ f.drawable = dsw->sw.feedback_pixmap;
+ f.gstate = dsw->sw.feedback_gstate;
+ }
+ f.context = dsw->sw.context;
+ f.dirty_rects = r;
+ f.dirty_count = n;
+
+ XDPSSetContextGState(dsw->sw.context, f.gstate);
+ _DPSSWSetRectViewClip(dsw->sw.context, r, n * 4);
+ XtCallCallbackList((Widget) dsw, dsw->sw.feedback_callback,
+ (XtPointer) &f);
+ DPSWaitContext(dsw->sw.context);
+}
+
+static void SetScale(
+ Widget w,
+ double scale,
+ long fixedX, long fixedY)
+{
+ float psX, psY;
+
+ ConvertToPS((DPSScrolledWindowWidget) w, (float) fixedX, (float) fixedY,
+ &psX, &psY);
+ SetScaleAndScroll(w, scale, psX, psY, fixedX, fixedY);
+}
+
+void DSWSetScale(
+ Widget w,
+ double scale,
+ long fixedX, long fixedY)
+{
+ XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
+
+ (*((DPSScrolledWindowWidgetClass) XtClass(w))->
+ sw_class.set_scale) (w, scale, fixedX, fixedY);
+}
+
+static void ScrollPoint(
+ Widget w,
+ double psX, double psY,
+ long xX, long xY)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
+
+ if (!XtIsRealized(w)) {
+ dsw->sw.use_saved_scroll = True;
+ dsw->sw.scroll_pic_x = psX;
+ dsw->sw.scroll_pic_y = psY;
+ dsw->sw.scroll_win_x = xX;
+ dsw->sw.scroll_win_y = xY;
+ return;
+ } else {
+ SetDrawingAreaPosition(dsw, psX, psY, xX, xY, False);
+ ScrollMoved(dsw);
+ }
+}
+
+void DSWScrollPoint(
+ Widget w,
+ double psX, double psY,
+ long xX, long xY)
+{
+ XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
+
+ (*((DPSScrolledWindowWidgetClass) XtClass(w))->
+ sw_class.scroll_point) (w, psX, psY, xX, xY);
+}
+
+static void ScrollBy(Widget w, long dx, long dy)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
+ int value;
+
+ if (dx == 0 && dy == 0) return;
+
+ if (!XtIsRealized(w) && dsw->sw.use_saved_scroll) {
+ dsw->sw.scroll_win_x += dx;
+ dsw->sw.scroll_win_y += dy;
+ } else {
+ value = dsw->sw.scroll_h_value + dx;
+
+ if (value < 0) value = 0;
+ else if (value > dsw->sw.scroll_h_max - dsw->sw.scroll_h_size) {
+ value = dsw->sw.scroll_h_max - dsw->sw.scroll_h_size;
+ }
+ dsw->sw.scroll_h_value = value;
+
+ if (!dsw->sw.application_scrolling) {
+ XtVaSetValues(dsw->sw.h_scroll, XmNvalue, value, NULL);
+ }
+
+ value = dsw->sw.scroll_v_value + dy;
+
+ if (value < 0) value = 0;
+ else if (value > dsw->sw.scroll_v_max - dsw->sw.scroll_v_size) {
+ value = dsw->sw.scroll_v_max - dsw->sw.scroll_v_size;
+ }
+ dsw->sw.scroll_v_value = value;
+
+ if (!dsw->sw.application_scrolling) {
+ XtVaSetValues(dsw->sw.v_scroll, XmNvalue, value, NULL);
+ }
+
+ ScrollMoved(dsw);
+ }
+}
+
+void DSWScrollBy(Widget w, long dx, long dy)
+{
+ XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
+
+ (*((DPSScrolledWindowWidgetClass) XtClass(w))->
+ sw_class.scroll_by) (w, dx, dy);
+}
+
+static void ScrollTo(Widget w, long x, long y)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
+ int max, size;
+
+ if (XtIsRealized(w)) {
+ if (x < 0) x = 0;
+ else if (x > dsw->sw.scroll_h_max - dsw->sw.scroll_h_size) {
+ x = dsw->sw.scroll_h_max - dsw->sw.scroll_h_size;
+ }
+ dsw->sw.scroll_h_value = x;
+
+ if (y < 0) y = 0;
+ else if (y > dsw->sw.scroll_v_max - dsw->sw.scroll_v_size) {
+ y = dsw->sw.scroll_v_max - dsw->sw.scroll_v_size;
+ }
+ dsw->sw.scroll_v_value = y;
+
+ if (!dsw->sw.application_scrolling) {
+ XtVaSetValues(dsw->sw.h_scroll, XmNvalue, x, NULL);
+ XtVaSetValues(dsw->sw.v_scroll, XmNvalue, y, NULL);
+ }
+
+ ScrollMoved(dsw);
+ }
+}
+
+void DSWScrollTo(Widget w, long x, long y)
+{
+ XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
+
+ (*((DPSScrolledWindowWidgetClass) XtClass(w))->
+ sw_class.scroll_to) (w, x, y);
+}
+
+static void SetScaleAndScroll(
+ Widget w,
+ double scale,
+ double psX, double psY,
+ long xX, long xY)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
+ Arg arg;
+ union {
+ int i;
+ float f;
+ } kludge;
+
+ dsw->sw.use_saved_scroll = True;
+ dsw->sw.scroll_pic_x = psX;
+ dsw->sw.scroll_pic_y = psY;
+ dsw->sw.scroll_win_x = xX;
+ dsw->sw.scroll_win_y = xY;
+
+ kludge.f = scale;
+ arg.name = XtNscale;
+ if (sizeof(float) > sizeof(XtArgVal)) arg.value = (XtArgVal) &kludge.f;
+ else arg.value = (XtArgVal) kludge.i;
+ XtSetValues(w, &arg, 1);
+}
+
+void DSWSetScaleAndScroll(
+ Widget w,
+ double scale,
+ double psX, double psY,
+ long xX, long xY)
+{
+ XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
+
+ (*((DPSScrolledWindowWidgetClass) XtClass(w))->
+ sw_class.set_scale_and_scroll) (w, scale, psX, psY, xX, xY);
+}
+
+static void ConvertXToPS(
+ Widget w,
+ long xX, long xY,
+ float *psX, float *psY)
+{
+ ConvertToPS((DPSScrolledWindowWidget) w, (float) xX, (float) xY, psX, psY);
+}
+
+void DSWConvertXToPS(
+ Widget w,
+ long xX, long xY,
+ float *psX, float *psY)
+{
+ XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
+
+ (*((DPSScrolledWindowWidgetClass) XtClass(w))->
+ sw_class.convert_x_to_ps) (w, xX, xY, psX, psY);
+}
+
+static void ConvertPSToX(
+ Widget w,
+ double psX, double psY,
+ int *xX, int *xY)
+{
+ ConvertToX((DPSScrolledWindowWidget) w, psX, psY, xX, xY);
+}
+
+void DSWConvertPSToX(
+ Widget w,
+ double psX, double psY,
+ int *xX, int *xY)
+{
+ XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
+
+ (*((DPSScrolledWindowWidgetClass) XtClass(w))->
+ sw_class.convert_ps_to_x) (w, psX, psY, xX, xY);
+}
+
+static void AddToDirtyArea(
+ Widget w,
+ float *rect,
+ long n)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
+
+ if (n == 1 && rect[0] == 0 && rect[1] == 0 &&
+ rect[2] == -1 && rect[2] == -1) {
+ rect[2] = dsw->sw.area_width;
+ rect[3] = dsw->sw.area_height;
+ }
+
+ XtVaSetValues(w, XtNdirtyAreas, rect, XtNnumDirtyAreas, n, NULL);
+}
+
+void DSWAddToDirtyArea(
+ Widget w,
+ float *rect,
+ long n)
+{
+ XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
+
+ (*((DPSScrolledWindowWidgetClass) XtClass(w))->
+ sw_class.add_to_dirty_area) (w, rect, n);
+}
+
+static Boolean TakeFeedbackPixmap(
+ Widget w,
+ Pixmap *p,
+ int *width, int *height, int *depth,
+ Screen **screen)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
+
+ if (dsw->sw.doing_feedback) return False;
+
+ *p = dsw->sw.feedback_pixmap;
+ if (*p == None) {
+ *width = *height = *depth;
+ *screen = NULL;
+ return True;
+ }
+
+ *width = dsw->sw.feedback_width;
+ *height = dsw->sw.feedback_height;
+ *depth = dsw->sw.drawing_area->core.depth;
+ *screen = dsw->core.screen;
+
+ dsw->sw.feedback_pixmap = None;
+ dsw->sw.feedback_width = dsw->sw.feedback_height = 0;
+ return True;
+}
+
+Boolean DSWTakeFeedbackPixmap(
+ Widget w,
+ Pixmap *p,
+ int *width, int *height, int *depth,
+ Screen **screen)
+{
+ XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
+
+ return (*((DPSScrolledWindowWidgetClass) XtClass(w))->
+ sw_class.take_feedback_pixmap) (w, p, width, height,
+ depth, screen);
+}
+
+static void StartFeedbackDrawing(
+ Widget w,
+ XtPointer start_feedback_data)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
+ float *r;
+
+ FinishDrawing(dsw);
+ CheckFeedbackPixmap(dsw);
+ if (dsw->sw.feedback_pixmap != None) {
+ /* Initialize the feedback pixmap with a copy of the drawing */
+ GrowRectList(&dsw->sw.prev_dirty_areas, &dsw->sw.prev_dirty_areas_size,
+ 0, 1, 1);
+ r = dsw->sw.prev_dirty_areas;
+ ConvertToPS(dsw, 0 + DELTA, dsw->sw.drawing_area->core.height - DELTA,
+ r, r+1);
+ ConvertToPS(dsw, dsw->sw.drawing_area->core.width - DELTA, 0 + DELTA,
+ r+2, r+3);
+ r[2] -= r[0];
+ r[3] -= r[1];
+ dsw->sw.num_prev_dirty_areas = 1;
+
+ if (dsw->sw.backing_pixmap != None) {
+ CopyToFeedbackPixmap(dsw, dsw->sw.prev_dirty_areas,
+ dsw->sw.num_prev_dirty_areas);
+ } else {
+ CopyRectsToCurrentDrawing(dsw, dsw->sw.prev_dirty_areas,
+ dsw->sw.num_prev_dirty_areas);
+ (void) ClipAndDraw(dsw, DSWFeedbackPixmap, DSWFinish, True);
+ }
+ }
+ dsw->sw.num_prev_dirty_areas = 0;
+ dsw->sw.doing_feedback = True;
+ dsw->sw.start_feedback_data = start_feedback_data;
+}
+
+void DSWStartFeedbackDrawing(
+ Widget w,
+ XtPointer start_feedback_data)
+{
+ XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
+
+ (*((DPSScrolledWindowWidgetClass) XtClass(w))->
+ sw_class.start_feedback_drawing) (w, start_feedback_data);
+}
+
+static void EndFeedbackDrawing(
+ Widget w,
+ int restore)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
+
+ if (restore) {
+ if (dsw->sw.backing_pixmap != None) {
+ UpdateWindowFromBackingPixmap(dsw, dsw->sw.prev_dirty_areas,
+ dsw->sw.num_prev_dirty_areas);
+ } else {
+ CopyRectsToCurrentDrawing(dsw, dsw->sw.prev_dirty_areas,
+ dsw->sw.num_prev_dirty_areas);
+ (void) ClipAndDraw(dsw, DSWWindow, DSWFinish, True);
+ }
+ }
+ if (dsw->sw.feedback_gstate != 0) {
+ XDPSFreeContextGState(dsw->sw.context, dsw->sw.feedback_gstate);
+ }
+ dsw->sw.doing_feedback = dsw->sw.feedback_displayed = False;
+}
+
+void DSWEndFeedbackDrawing(
+ Widget w,
+ Bool restore)
+{
+ XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
+
+ (*((DPSScrolledWindowWidgetClass) XtClass(w))->
+ sw_class.end_feedback_drawing) (w, restore);
+}
+
+static void SetFeedbackDirtyArea(
+ Widget w,
+ float *rects,
+ int count,
+ XtPointer continue_feedback_data)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
+ int i;
+ float *r;
+
+ for (i = 0; i < count; i++) {
+ r = rects + (i * 4);
+ if (WIDTH(r) < 0) {
+ LEFT(r) += WIDTH(r);
+ WIDTH(r) = -WIDTH(r);
+ }
+ if (HEIGHT(r) < 0) {
+ BOTTOM(r) += HEIGHT(r);
+ HEIGHT(r) = -HEIGHT(r);
+ }
+ }
+
+ if (dsw->sw.backing_pixmap != None) {
+ if (dsw->sw.feedback_pixmap != None) {
+ CopyToFeedbackPixmap(dsw, dsw->sw.prev_dirty_areas,
+ dsw->sw.num_prev_dirty_areas);
+ } else {
+ UpdateWindowFromBackingPixmap(dsw, dsw->sw.prev_dirty_areas,
+ dsw->sw.num_prev_dirty_areas);
+ }
+ } else {
+ CopyRectsToCurrentDrawing(dsw, dsw->sw.prev_dirty_areas,
+ dsw->sw.num_prev_dirty_areas);
+ (void) ClipAndDraw(dsw, (dsw->sw.feedback_pixmap == None ?
+ DSWWindow : DSWFeedbackPixmap),
+ DSWFinish, True);
+ }
+ dsw->sw.continue_feedback_data = continue_feedback_data;
+ CallFeedbackCallback(dsw, rects, count);
+
+ if (dsw->sw.feedback_pixmap != None) {
+ CopyRectsToDirtyArea(dsw, dsw->sw.prev_dirty_areas,
+ dsw->sw.num_prev_dirty_areas);
+ AddRectsToDirtyArea(dsw, rects, count);
+ SimplifyRects(dsw->sw.dirty_areas, &dsw->sw.num_dirty_areas);
+ UpdateWindowFromFeedbackPixmap(dsw, dsw->sw.dirty_areas,
+ dsw->sw.num_dirty_areas);
+ dsw->sw.num_dirty_areas = 0;
+ }
+ CopyRectsToPrevDirtyArea(dsw, rects, count);
+ dsw->sw.feedback_displayed = True;
+}
+
+void DSWSetFeedbackDirtyArea(
+ Widget w,
+ float *rects,
+ int count,
+ XtPointer continue_feedback_data)
+{
+ XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
+
+ (*((DPSScrolledWindowWidgetClass) XtClass(w))->
+ sw_class.set_feedback_dirty_area) (w, rects, count,
+ continue_feedback_data);
+}
+
+static void FinishPendingDrawing(Widget w)
+{
+ FinishDrawing((DPSScrolledWindowWidget) w);
+}
+
+void DSWFinishPendingDrawing(Widget w)
+{
+ XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
+
+ (*((DPSScrolledWindowWidgetClass) XtClass(w))->
+ sw_class.finish_pending_drawing) (w);
+}
+
+static void AbortPendingDrawing(Widget w)
+{
+ AbortDrawing((DPSScrolledWindowWidget) w);
+}
+
+void DSWAbortPendingDrawing(Widget w)
+{
+ XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
+
+ (*((DPSScrolledWindowWidgetClass) XtClass(w))->
+ sw_class.abort_pending_drawing) (w);
+}
+
+static void UpdateDrawing(
+ Widget w,
+ float *rects,
+ int count)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
+ int i;
+ float *r;
+ int llx, lly, urx, ury;
+ int dx, dy;
+
+ if (dsw->sw.backing_pixmap == None) {
+ AddToDirtyArea(w, rects, count);
+ return;
+ }
+
+ ComputeOffsets(dsw, &dx, &dy);
+
+ for (i = 0; i < count; i++) {
+ r = rects + (i * 4);
+ ConvertToX(dsw, LEFT(r), BOTTOM(r), &llx, &lly);
+ ConvertToX(dsw, RIGHT(r), TOP(r), &urx, &ury);
+ XCopyArea(XtDisplay(dsw), XtWindow(dsw->sw.drawing_area),
+ dsw->sw.backing_pixmap, dsw->sw.no_ge_gc,
+ llx-1, ury-1, urx-llx+2, lly-ury+2, llx+dx-1, ury+dy-1);
+ }
+}
+
+void DSWUpdateDrawing(
+ Widget w,
+ float *rects,
+ int count)
+{
+ XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
+
+ (*((DPSScrolledWindowWidgetClass) XtClass(w))->
+ sw_class.update_drawing) (w, rects, count);
+}
+
+static void GetScrollInfo(
+ Widget w,
+ int *h_value, int *h_size, int *h_max, int *v_value, int *v_size, int *v_max)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
+
+ if (h_value != NULL) *h_value = dsw->sw.scroll_h_value;
+ if (h_size != NULL) *h_size = dsw->sw.scroll_h_size;
+ if (h_max != NULL) *h_max = dsw->sw.scroll_h_max;
+ if (v_value != NULL) *v_value = dsw->sw.scroll_v_value;
+ if (v_size != NULL) *v_size = dsw->sw.scroll_v_size;
+ if (v_max != NULL) *v_max = dsw->sw.scroll_v_max;
+}
+
+void DSWGetScrollInfo(
+ Widget w,
+ int *h_value, int *h_size, int *h_max, int *v_value, int *v_size, int *v_max)
+{
+ XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
+
+ (*((DPSScrolledWindowWidgetClass) XtClass(w))->
+ sw_class.get_scroll_info) (w, h_value, h_size, h_max,
+ v_value, v_size, v_max);
+}
+
+static void GetDrawingInfo(
+ Widget w,
+ DSWDrawableType *type,
+ Drawable *drawable,
+ DPSGState *gstate,
+ DPSContext *context)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
+
+ if (dsw->sw.backing_pixmap != None) {
+ *type = DSWBackingPixmap;
+ *drawable = dsw->sw.backing_pixmap;
+ *gstate = dsw->sw.backing_gstate;
+ } else {
+ *type = DSWWindow;
+ *drawable = XtWindow(dsw->sw.drawing_area);
+ *gstate = dsw->sw.window_gstate;
+ }
+ *context = dsw->sw.context;
+}
+
+void DSWGetDrawingInfo(
+ Widget w,
+ DSWDrawableType *type,
+ Drawable *drawable,
+ DPSGState *gstate,
+ DPSContext *context)
+{
+ XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
+
+ (*((DPSScrolledWindowWidgetClass) XtClass(w))->
+ sw_class.get_drawing_info) (w, type, drawable, gstate, context);
+}
+
+static Boolean GiveFeedbackPixmap(
+ Widget w,
+ Pixmap p,
+ int width, int height, int depth,
+ Screen *screen)
+{
+ DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
+
+ if ((unsigned) depth != dsw->sw.drawing_area->core.depth
+ || screen != dsw->core.screen
+ || dsw->sw.feedback_pixmap != None) return False;
+
+ dsw->sw.feedback_pixmap = p;
+ dsw->sw.feedback_width = width;
+ dsw->sw.feedback_height = height;
+
+ return True;
+}
+
+Boolean DSWGiveFeedbackPixmap(
+ Widget w,
+ Pixmap p,
+ int width, int height, int depth,
+ Screen *screen)
+{
+ XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
+
+ return (*((DPSScrolledWindowWidgetClass) XtClass(w))->
+ sw_class.give_feedback_pixmap) (w, p, width, height,
+ depth, screen);
+}
+
+static void ConvertToX(
+ DPSScrolledWindowWidget dsw,
+ float psX,
+ float psY,
+ int *xX,
+ int *xY)
+{
+ *xX = dsw->sw.ctm[0] * psX + dsw->sw.ctm[2] * psY + dsw->sw.ctm[4] +
+ dsw->sw.x_offset + 0.5;
+ *xY = dsw->sw.ctm[1] * psX + dsw->sw.ctm[3] * psY + dsw->sw.ctm[5] +
+ dsw->sw.y_offset + 0.5;
+}
+
+static void ConvertToPS(
+ DPSScrolledWindowWidget dsw,
+ float xX, float xY,
+ float *psX, float *psY)
+{
+ xX -= dsw->sw.x_offset;
+ xY -= dsw->sw.y_offset;
+
+ *psX = dsw->sw.inv_ctm[0] * xX + dsw->sw.inv_ctm[2] * xY +
+ dsw->sw.inv_ctm[4];
+ *psY = dsw->sw.inv_ctm[1] * xX + dsw->sw.inv_ctm[3] * xY +
+ dsw->sw.inv_ctm[5];
+}
+
+static void ConvertToOrigPS(
+ DPSScrolledWindowWidget dsw,
+ int xX, int xY,
+ float *psX, float *psY)
+{
+ xX -= dsw->sw.x_offset;
+ xY -= dsw->sw.y_offset;
+
+ *psX = dsw->sw.orig_inv_ctm[0] * xX + dsw->sw.orig_inv_ctm[2] * xY +
+ dsw->sw.orig_inv_ctm[4];
+ *psY = dsw->sw.orig_inv_ctm[1] * xX + dsw->sw.orig_inv_ctm[3] * xY +
+ dsw->sw.orig_inv_ctm[5];
+}
diff --git a/nx-X11/lib/dpstk/DSWwraps.psw b/nx-X11/lib/dpstk/DSWwraps.psw
new file mode 100644
index 000000000..84c4268a4
--- /dev/null
+++ b/nx-X11/lib/dpstk/DSWwraps.psw
@@ -0,0 +1,75 @@
+/*
+ * DSWwraps.psw
+ *
+ * (c) Copyright 1993-1994 Adobe Systems Incorporated.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sublicense this software
+ * and its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notices appear in all copies and that
+ * both those copyright notices and this permission notice appear in
+ * supporting documentation and that the name of Adobe Systems Incorporated
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. No trademark license
+ * to use the Adobe trademarks is hereby granted. If the Adobe trademark
+ * "Display PostScript"(tm) is used to describe this software, its
+ * functionality or for any other purpose, such use shall be limited to a
+ * statement that this software works in conjunction with the Display
+ * PostScript system. Proper trademark attribution to reflect Adobe's
+ * ownership of the trademark shall be given whenever any such reference to
+ * the Display PostScript system is made.
+ *
+ * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
+ * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
+ * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
+ * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
+ * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
+ *
+ * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+ * Incorporated which may be registered in certain jurisdictions
+ *
+ * Author: Adobe Systems Incorporated
+ */
+
+defineps _DPSSWGetTransform(DPSContext ctxt | float ctm[6], invctm[6])
+ matrix currentmatrix dup ctm
+ matrix invertmatrix invctm
+endps
+
+defineps _DPSSWSetMatrixAndGetTransform(DPSContext ctxt;
+ float tx, ty, s; int hx, hy
+ | float ctm[6], invctm[6]; int *xoffset, *yoffset)
+ initmatrix
+ tx ty translate
+ s s scale
+ hx hy sethalftonephase
+ initclip
+ matrix currentmatrix dup ctm
+ matrix invertmatrix invctm
+ currentXoffset yoffset xoffset
+endps
+
+defineps _DPSSWSetMatrix(DPSContext ctxt; float tx, ty, s; int hx, hy)
+ initmatrix
+ tx ty translate
+ s s scale
+ hx hy sethalftonephase
+ initclip
+endps
+
+defineps _DPSSWSetRectViewClip(DPSContext ctxt;
+ float numstring rect[numrect]; int numrect)
+ rect rectviewclip
+endps
+
+defineps _DPSSWColormapMatch(DPSContext ctxt; int colormap | boolean *match)
+ currentXgcdrawablecolor % gc draw x y [....colormap...]
+ 10 get colormap eq match % gc draw x y
+ pop pop pop pop
+endps
+
diff --git a/nx-X11/lib/dpstk/FSBwraps.psw b/nx-X11/lib/dpstk/FSBwraps.psw
new file mode 100644
index 000000000..c36a0d78c
--- /dev/null
+++ b/nx-X11/lib/dpstk/FSBwraps.psw
@@ -0,0 +1,491 @@
+/*
+ * FSBwraps.psw
+ *
+ * (c) Copyright 1991-1994 Adobe Systems Incorporated.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sublicense this software
+ * and its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notices appear in all copies and that
+ * both those copyright notices and this permission notice appear in
+ * supporting documentation and that the name of Adobe Systems Incorporated
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. No trademark license
+ * to use the Adobe trademarks is hereby granted. If the Adobe trademark
+ * "Display PostScript"(tm) is used to describe this software, its
+ * functionality or for any other purpose, such use shall be limited to a
+ * statement that this software works in conjunction with the Display
+ * PostScript system. Proper trademark attribution to reflect Adobe's
+ * ownership of the trademark shall be given whenever any such reference to
+ * the Display PostScript system is made.
+ *
+ * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
+ * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
+ * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
+ * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
+ * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
+ *
+ * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+ * Incorporated which may be registered in certain jurisdictions
+ *
+ * Author: Adobe Systems Incorporated
+ */
+
+defineps _DPSFClearWindow(DPSContext ctxt)
+ 1 setgray
+ 0 0 2000 2000 rectfill
+endps
+
+defineps _DPSFPreviewString(DPSContext ctxt; char *font; float size;
+ char *text; int height | boolean *bogus)
+ mark {
+ /font size selectfont
+ 0 height neg 5 div itransform
+ exch pop 5 exch moveto
+ 0 setgray
+ (text) show
+ } stopped bogus cleartomark
+endps
+
+defineps _DPSFReclip(DPSContext ctxt)
+ initclip
+ initviewclip
+endps
+
+defineps _DPSFUndefineFont(DPSContext ctxt; char *font; boolean oldServer)
+ currentshared true setshared % currentshared
+ {/font undefinefont} stopped % currentshared [font] stopped
+ {
+ false setshared % currentshared font
+ {undefinefont} stopped {
+ pop
+ } if
+ } if
+ setshared
+ oldServer { 2 vmreclaim } if
+endps
+
+defineps _DPSFDefineFontEnumFunctions(DPSContext ctxt)
+ $Adobe$DPS$Lib$Dict begin
+ /GetFontName { % int GetFontName string
+ $Adobe$DPS$Lib$Dict /FontDict get begin
+ dup maxItems div truncate cvi baseArray exch get
+ exch maxItems mod get
+ end
+ } bind def
+
+ % (str) x y SafeBBox left bottom right top
+ /SafeBBox {
+ 3 copy % (str) x y (str) x y
+ newpath
+ moveto % (str) x y (str)
+ {
+ mark exch false charpath flattenpath pathbbox
+ } stopped {
+ cleartomark
+ 3 -1 roll dup length dup % x y (str) len len
+ 1 le {
+ pop
+ % punt; we can't divide it any more
+ 0 0 moveto stringwidth pop % x y wx
+ dup 2 index add exch 3 index add exch
+ } {
+ 2 copy % x y (str) len (str) len
+ 2 idiv % x y (str) len (str) len/2
+ 0 exch % x y (str) len (str) 0 len/2
+ getinterval dup % x y (str) len (s1) (s1)
+ 5 index 5 index % x y (str) len (s1) (s1) x y
+ $Adobe$DPS$Lib$Dict /SafeBBox get exec
+ % x y (str) len (s1) l1 b1 r1 t1
+ 9 4 roll % l1 b1 r1 t1 x y (str) len (s1)
+ stringwidth % ... x y (str) len wx wy
+ 5 -1 roll add exch % ... x (str) len y+wy wx
+ 5 -1 roll add exch % ... (str) len x+wx y+wy
+ 4 2 roll % ... x+wx y+wy (str) len
+ dup 2 idiv % ... x+wx y+wy (str) len len/2
+ exch 2 div ceiling cvi
+ % ... x+wx y+wy (str) len/2 ceil(len/2)
+ getinterval % ... x+wx y+wy (s2)
+ 3 1 roll % ... (s2) x+wx y+wy
+ $Adobe$DPS$Lib$Dict /SafeBBox get exec
+ % l1 b1 r1 t1 l2 b2 r2 t2
+ 5 -1 roll 2 copy % l1 b1 r1 l2 b2 r2 t2 t1 t2 t1
+ gt {pop} {exch pop} ifelse % l1 b1 r1 l2 b2 r2 t
+ 7 1 roll % t l1 b1 r1 l2 b2 r2
+ 4 -1 roll 2 copy % t l1 b1 l2 b2 r2 r1 r2 r1
+ gt {pop} {exch pop} ifelse % t l1 b1 l2 b2 r
+ 6 1 roll % r t l1 b1 l2 b2
+ 3 -1 roll 2 copy % r t l1 l2 b2 b1 b2 b1
+ lt {pop} {exch pop} ifelse % r t l1 l2 b
+ 5 1 roll % b r t l1 l2
+ 2 copy % b r t l1 l2 l1 l2
+ lt {pop} {exch pop} ifelse % b r t l
+ 4 1 roll % l b r t
+ } ifelse
+ } { % mark (str) x y l b r t
+ 8 -4 roll pop pop pop pop
+ } ifelse
+ } bind def
+ /DownloadPS {
+ $Adobe$DPS$Lib$Dict /downloadSuccess false put
+ (%stdin) (r) file
+ cvx stopped
+ pop % always true
+ % Flush until you get the magic line
+ {
+ {currentfile 256 string readline} stopped
+ pop % don't care stopped result
+ pop % don't care readline bool result
+(Magic end of data line \)\)\)\)\)\)\)\)\)\) 99#2 2#99 <xyz> // 7gsad,32h4ghNmndFgj2)
+ eq
+ {exit} if
+ } loop
+ } bind def
+ end
+endps
+
+defineps _DPSFEnumFonts(DPSContext ctxt | int *count; int *totalLength)
+ $Adobe$DPS$Lib$Dict begin
+ /FontDict 5 dict def
+ FontDict begin
+ /currentItem 0 def
+ /maxItems 100 def
+ /maxArrays 20 def % This is the max index, not the array size!
+ /baseArray maxArrays 1 add array def
+ /currentArray 0 def
+ baseArray 0 maxItems array put
+ end
+
+ /AddFontName { % string AddFontName success
+ $Adobe$DPS$Lib$Dict /FontDict get begin
+ 1 { % provides enclosing loop for exit
+ currentItem maxItems eq
+ {
+ currentArray maxArrays eq {pop false exit} if
+ /currentArray currentArray 1 add def
+ baseArray currentArray maxItems array put
+ /currentItem 0 def
+ } if
+ dup length string copy
+ baseArray currentArray get currentItem 3 -1 roll put
+ /currentItem currentItem 1 add def
+ true
+ } repeat % provides enclosing loop for exit
+ end
+ } bind def
+
+ 3 dict begin
+ /$listString 256 string def
+ /countFonts 0 def
+ /totalLen 0 def
+
+ % Enumerate SharedFontDirectory
+ SharedFontDirectory { % forall
+ pop % /fontname
+ $listString cvs % (fontname)
+ dup AddFontName % (name) success
+ {
+ /countFonts countFonts 1 add def
+ length 1 add totalLen add /totalLen exch def
+ } {
+ pop
+ } ifelse
+ } forall
+
+ % Enumerate %font% storage device, if available.
+ /filenameforall where { % if
+ pop
+ (%font%*) { % filenameforall
+ % Check if name is something we really believe
+ % is a font. Leave either "false" or "(name) true"
+ % on stack
+
+ % Discard filenames containing "."
+ (.) search { % if
+ pop pop pop null false
+ } { % else
+ dup % (%font%name) (%font%name)
+ (%font%) anchorsearch { % if
+ % (%font%name) (name) (%font%)
+ pop exch pop % (name)
+ dup AddFontName % (name) success
+ } { % else
+ pop null false
+ } ifelse
+ } ifelse
+
+ % Stack is either "<something> false" or "(name) true"
+ {
+ /countFonts countFonts 1 add def
+ length 1 add totalLen add /totalLen exch def
+ } {
+ pop
+ } ifelse
+ } $listString filenameforall
+ } if
+ totalLen totalLength countFonts count
+ end
+ end
+
+ $Adobe$DPS$Lib$Dict /AddFontName undef
+endps
+
+defineps _DPSFGetAllFontNames(DPSContext ctxt; int fontCount; int arrLen |
+ char fontNames[arrLen])
+ $Adobe$DPS$Lib$Dict begin
+ FontDict begin
+ 0 1 fontCount 1 sub {
+ GetFontName fontNames
+ ( ) fontNames
+ } for
+ end
+ end
+endps
+
+defineps _DPSFGetFontInfo(DPSContext ctxt; int fontNum; boolean oldServer |
+ char *familyName; char *fullName; char *weight;
+ boolean *blendedFont, *undefineIt, *bogus)
+ fontNum $Adobe$DPS$Lib$Dict /GetFontName get exec
+
+ dup dup % fontname fontname fontname
+ SharedFontDirectory exch known % fontname fontname known
+ dup undefineIt exch % fontname known fontname
+ % (leave fontname and known on stack
+ % for the duration of this call
+ % even though I don't list them in
+ % the comments)
+ { % stopped
+ findfont dup % fontdir fontdir
+ /FontInfo known { % fontdir bool
+ /FontInfo get dup dup % fontinfo fontinfo fontinfo
+ /FamilyName known { % fontinfo fontinfo bool
+ /FamilyName get % fontinfo (familyname)
+ } {
+ pop ()
+ } ifelse
+ exch dup dup % (familyname) fontinfo fontinfo fontinfo
+ /FullName known { % (familyname) fontinfo fontinfo bool
+ /FullName get % (familyname) fontinfo (fullname)
+ } {
+ pop ()
+ } ifelse
+ exch dup dup % (familyname) (fullname) fontinfo*3
+ /Weight known { % (familyname) (fullname) fontinfo*2 bool
+ /Weight get % (familyname) (fullname) fontinfo (weight)
+ } {
+ pop (Medium)
+ } ifelse
+ exch % (familyname) (fullname) (weight) fontinfo
+ /BlendAxisTypes known % (familyname) (fullname) (weight) blendedFont
+
+ dup blendedFont % (familyname) (fullname) (weight) blendedFont
+ } {
+ pop () () ()
+ false false blendedFont
+ } ifelse % (familyname) (fullname) (weight) blendedFont
+ false bogus
+
+ } stopped {
+ () () ()
+ false false blendedFont
+ true bogus
+ } if
+
+ 4 1 roll % blendedFont (familyname) (fullname) (weight)
+ weight fullName familyName
+ % fontname known is still on the stack so...
+ % fontname known blendedFont
+
+ % if blendedFont (the bool on the stack) is true, don't undefine things
+ % just yet since we'll be coming back quite soon for more stuff
+
+ not and { % undefine font if we just defined
+ % it to get this information
+ currentshared true setshared
+ exch % currentshared fontname
+ {undefinefont} stopped % currentshared [fontname] stopped
+ {
+ false setshared % currentshared fontname
+
+ {undefinefont} stopped {
+ pop
+ } if
+ } if
+ setshared
+
+ oldServer {2 vmreclaim} if
+ } {
+ pop
+ } ifelse
+endps
+
+defineps _DPSFFreeFontInfo(DPSContext ctxt)
+ $Adobe$DPS$Lib$Dict /FontDict undef
+ $Adobe$DPS$Lib$Dict /GetFontName undef
+ 1 vmreclaim
+endps
+
+defineps _DPSFIsFontResident(DPSContext ctxt; char *name; | boolean *resident)
+ SharedFontDirectory /name known {
+ true resident
+ } {
+ /buf (name) length 6 add string def
+ buf 0 (%font%) putinterval
+ buf 6 (name) putinterval
+ buf status dup resident { pop pop pop pop } if
+ } ifelse
+endps
+
+defineps _DPSFGetBlendedFontInfo(DPSContext ctxt; int fontNum;
+ boolean undefineIt; boolean oldServer |
+ int *axes; int *designs;
+ char axisNames[256];
+ float blendPos[64]; int breakCount[4];
+ int blendBreak[48]; float blendBreakValue[48];
+ boolean *bogus)
+
+ fontNum $Adobe$DPS$Lib$Dict /GetFontName get exec
+ $Adobe$DPS$Lib$Dict /stringbuf 256 string put
+ dup % duplicate fontname; we'll need it later
+
+ findfont /FontInfo get dup % fontinfo fontinfo
+ /BlendAxisTypes get % fontinfo array
+ dup length axes % fontinfo array
+ { % Concatenate all the names into axisNames
+ $Adobe$DPS$Lib$Dict /stringbuf get cvs
+ axisNames
+ ( ) axisNames
+ } forall
+ dup dup % fontinfo fontinfo fontinfo
+ /BlendDesignPositions known { % fontinfo fontinfo known
+ /BlendDesignPositions get % fontinfo array
+ dup length designs % fontinfo array
+ { % enumerate the subarrays
+ {
+ blendPos
+ } forall
+ } forall
+ false
+ } {
+ pop true
+ } ifelse % fontinfo bool
+ exch dup % bool fontinfo fontinfo
+ /BlendDesignMap known { % bool fontinfo known
+ /BlendDesignMap get % bool array
+ {
+ dup length % bool subarray len
+ breakCount % bool subarray len
+ {
+ aload pop % bool break breakvalue
+ blendBreakValue
+ blendBreak
+ } forall
+ } forall
+ false
+ } {
+ pop true
+ } ifelse % bool bool
+
+ or bogus
+
+ undefineIt { % undefine font if we just defined
+ % it to get this information
+ currentshared true setshared
+ exch % currentshared fontname
+ {undefinefont} stopped % currentshared [fontname] stopped
+ {
+ false setshared % currentshared fontname
+
+ {undefinefont} stopped {
+ pop
+ } if
+ } if
+ setshared
+ oldServer { 2 vmreclaim } if
+ } {
+ pop
+ } ifelse
+ $Adobe$DPS$Lib$Dict /stringbuf undef
+endps
+
+defineps _DPSFShowText(DPSContext ctxt; char *text; char *font; float size;
+ int x, y | boolean *bogus)
+ mark {
+ /font size selectfont
+ x y moveto
+ (text) show
+ } stopped dup bogus cleartomark
+endps
+
+defineps _DPSFShowTextAndGetDimensions(DPSContext ctxt;
+ char *text; char *font; float size;
+ int x, y |
+ float *width, *left, *right,
+ *top, *bottom)
+ mark {
+ /font size selectfont
+ x y moveto
+ (text) show
+ (text) stringwidth pop width
+ (text) x y $Adobe$DPS$Lib$Dict /SafeBBox get exec
+ } stopped {0 0 0 0} if
+ top right bottom left
+ cleartomark
+endps
+
+defineps _DPSFGetTextDimensions(DPSContext ctxt;
+ char *text; char *font; float size;
+ float x, y |
+ float *width, *height,
+ *left, *right, *top, *bottom;
+ boolean *bogus)
+ mark {
+ /font size selectfont
+ (text) stringwidth height width
+
+ (text) x y $Adobe$DPS$Lib$Dict /SafeBBox get exec
+ } stopped dup bogus {0 0 0 0} if
+ top right bottom left
+ cleartomark
+endps
+
+defineps _DPSFGetCTM(DPSContext ctx | float ctm[6], invctm[6])
+ matrix currentmatrix dup ctm matrix invertmatrix invctm
+endps
+
+defineps _DPSFSetUpMM(DPSContext ctxt; char *font, *str; float size;
+ int height; float p[n]; int n | boolean *bogus)
+ userdict /fontDefined known {
+ /tempfont undefinefont
+ } if
+ mark {
+ /tempfont /font findfont p makeblendedfont definefont
+ size scalefont setfont
+ 0 height neg 5 div itransform
+ exch pop 5 exch moveto
+ (str) stringwidth pop pop
+ /fontDefined true def
+ } stopped bogus cleartomark
+endps
+
+defineps _DPSFDrawMM(DPSContext ctxt; char *str; int height)
+ 0 height neg 5 div itransform
+ exch pop 5 exch moveto
+ (str) show
+endps
+
+defineps _DPSFPrepareToDownload(DPSContext ctxt; boolean makeShared |
+ boolean *currShared)
+ $Adobe$DPS$Lib$Dict /DownloadPS get
+ currentshared currShared makeShared setshared
+endps
+
+defineps _DPSFFinishDownload(DPSContext ctxt; boolean shared | boolean *ok)
+ shared setshared
+ $Adobe$DPS$Lib$Dict /downloadSuccess get ok
+endps
diff --git a/nx-X11/lib/dpstk/FontCreato.c b/nx-X11/lib/dpstk/FontCreato.c
new file mode 100644
index 000000000..5164665cc
--- /dev/null
+++ b/nx-X11/lib/dpstk/FontCreato.c
@@ -0,0 +1,1610 @@
+/*
+ * FontCreato.c
+ *
+ * (c) Copyright 1992-1994 Adobe Systems Incorporated.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sublicense this software
+ * and its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notices appear in all copies and that
+ * both those copyright notices and this permission notice appear in
+ * supporting documentation and that the name of Adobe Systems Incorporated
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. No trademark license
+ * to use the Adobe trademarks is hereby granted. If the Adobe trademark
+ * "Display PostScript"(tm) is used to describe this software, its
+ * functionality or for any other purpose, such use shall be limited to a
+ * statement that this software works in conjunction with the Display
+ * PostScript system. Proper trademark attribution to reflect Adobe's
+ * ownership of the trademark shall be given whenever any such reference to
+ * the Display PostScript system is made.
+ *
+ * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
+ * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
+ * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
+ * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
+ * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
+ *
+ * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+ * Incorporated which may be registered in certain jurisdictions
+ *
+ * Author: Adobe Systems Incorporated
+ */
+/* $XFree86$ */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <X11/ShellP.h>
+#include <Xm/Xm.h>
+
+/* There are no words to describe how I feel about having to do this */
+
+#if XmVersion > 1001
+#include <Xm/ManagerP.h>
+#else
+#include <Xm/XmP.h>
+#endif
+
+#include <Xm/Form.h>
+#include <Xm/LabelG.h>
+#include <Xm/PushBG.h>
+#include <Xm/DrawingA.h>
+#include <Xm/Scale.h>
+#include <Xm/MessageB.h>
+#include <Xm/TextF.h>
+#include <Xm/PanedW.h>
+#include <Xm/List.h>
+#include <Xm/SeparatoG.h>
+#include <Xm/ToggleBG.h>
+#include <Xm/RowColumn.h>
+#include <DPS/dpsXclient.h>
+#include <DPS/dpsXshare.h>
+#include <DPS/FontSBP.h>
+#include <DPS/FontCreatP.h>
+#include <stdlib.h>
+#include <math.h>
+#include "FontSBI.h"
+#include "FSBwraps.h"
+
+/* Turn a string into a compound string */
+#define UnsharedCS(str) XmStringCreate(str, XmSTRING_DEFAULT_CHARSET)
+#define CS(str, w) _FSBCreateSharedCS(str, w)
+static XmString CSempty;
+static char *opticalSize = NULL;
+
+#define Canonical(str) XrmQuarkToString(XrmStringToQuark(str))
+
+static float defaultSizeList[] = {
+#ifndef CREATOR_DEFAULT_SIZE_LIST
+ 8, 10, 12, 14, 16, 18, 24, 36, 48, 72
+#else
+ CREATOR_DEFAULT_SIZE_LIST
+#endif /* CREATOR_DEFAULT_SIZE_LIST */
+};
+
+#ifndef CREATOR_DEFAULT_SIZE_LIST_COUNT
+#define CREATOR_DEFAULT_SIZE_LIST_COUNT 10
+#endif /* CREATOR_DEFAULT_SIZE_LIST_COUNT */
+
+#define Offset(field) XtOffsetOf(FontCreatorRec, creator.field)
+
+static XtResource resources[] = {
+ {XtNsizes, XtCSizes, XtRFloatList, sizeof(float*),
+ Offset(sizes), XtRImmediate, (XtPointer) defaultSizeList},
+ {XtNsizeCount, XtCSizeCount, XtRInt, sizeof(int),
+ Offset(size_count), XtRImmediate,
+ (XtPointer) CREATOR_DEFAULT_SIZE_LIST_COUNT},
+ {XtNdismissCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
+ Offset(dismiss_callback), XtRCallback, (XtPointer) NULL},
+ {XtNfontSelectionBox, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(fsb), XtRWidget, (XtPointer) NULL},
+};
+
+/* Forward declarations */
+
+static Boolean SetValues(Widget old, Widget req, Widget new, ArgList args, Cardinal *num_args);
+static XtGeometryResult GeometryManager(Widget w, XtWidgetGeometry *desired, XtWidgetGeometry *allowed);
+static void ChangeManaged(Widget w);
+static void ClassInitialize(void);
+static void Destroy(Widget widget);
+static void Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args);
+static void Resize(Widget widget);
+
+FontCreatorClassRec fontCreatorClassRec = {
+ /* Core class part */
+ {
+ /* superclass */ (WidgetClass) &xmManagerClassRec,
+ /* class_name */ "FontCreator",
+ /* widget_size */ sizeof(FontCreatorRec),
+ /* class_initialize */ ClassInitialize,
+ /* class_part_initialize */ NULL,
+ /* class_inited */ FALSE,
+ /* initialize */ Initialize,
+ /* initialize_hook */ NULL,
+ /* realize */ XtInheritRealize,
+ /* actions */ NULL,
+ /* num_actions */ 0,
+ /* resources */ resources,
+ /* num_resources */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ TRUE,
+ /* compress_exposure */ XtExposeCompressMultiple,
+ /* compress_enterleave */ TRUE,
+ /* visible_interest */ FALSE,
+ /* destroy */ Destroy,
+ /* resize */ Resize,
+ /* expose */ NULL,
+ /* set_values */ SetValues,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* callback offsets */ NULL,
+ /* tm_table */ NULL,
+ /* query_geometry */ XtInheritQueryGeometry,
+ /* display_accelerator */ NULL,
+ /* extension */ NULL,
+ },
+ /* Composite class part */
+ {
+ /* geometry_manager */ GeometryManager,
+ /* change_managed */ ChangeManaged,
+ /* insert_child */ XtInheritInsertChild,
+ /* delete_child */ XtInheritDeleteChild,
+ /* extension */ NULL,
+ },
+ /* Constraint class part */
+ {
+ /* resources */ NULL,
+ /* num_resources */ 0,
+ /* constraint_size */ 0,
+ /* initialize */ NULL,
+ /* destroy */ NULL,
+ /* set_values */ NULL,
+ /* extension */ NULL,
+ },
+ /* Manager class part */
+ {
+ /* translations */ XtInheritTranslations,
+ /* syn_resources */ NULL,
+ /* num_syn_resources */ 0,
+ /* syn_constraint_resources */ NULL,
+ /* num_syn_constraint_resources */ 0,
+ /* parent_process */ XmInheritParentProcess,
+ /* extension */ NULL,
+ },
+ /* FontCreator class part */
+ {
+ /* extension */ NULL,
+ }
+};
+
+WidgetClass fontCreatorWidgetClass =
+ (WidgetClass) &fontCreatorClassRec;
+
+static void ClassInitialize(void)
+{
+ XtInitializeWidgetClass(fontSelectionBoxWidgetClass);
+
+ CSempty = UnsharedCS("");
+ opticalSize = Canonical("OpticalSize");
+}
+
+/* ARGSUSED */
+
+static void ResizePreview(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ Dimension height;
+ Cardinal depth;
+ FontCreatorWidget fc = (FontCreatorWidget) clientData;
+
+ if (!XtIsRealized(widget) || fc->creator.gstate == 0) return;
+
+ XtVaGetValues(widget, XmNheight, &height,
+ XmNdepth, &depth, NULL);
+
+ XDPSSetContextGState(fc->creator.fsb->fsb.context, fc->creator.gstate);
+
+ XDPSSetContextParameters(fc->creator.fsb->fsb.context, XtScreen(widget),
+ depth, XtWindow(widget), height,
+ (XDPSStandardColormap *) NULL,
+ (XDPSStandardColormap *) NULL,
+ XDPSContextScreenDepth | XDPSContextDrawable);
+
+ _DPSFReclip(fc->creator.fsb->fsb.context);
+
+ XDPSUpdateContextGState(fc->creator.fsb->fsb.context, fc->creator.gstate);
+}
+
+static void DrawMM(FontCreatorWidget fc)
+{
+ int i, j;
+ String str;
+ float p[MAX_AXES];
+ float b[MAX_BLENDS];
+ int val;
+ float size;
+ char *chSize;
+ DPSContext context;
+ Dimension hgt;
+ BlendDataRec *bd = fc->creator.font->blend_data;
+ float total;
+ int bogusFont;
+
+ str = XmTextFieldGetString(fc->creator.display_text_child);
+
+ for (i = 0; i < bd->num_axes; i++) {
+ XtVaGetValues(fc->creator.axis_scale_child[i], XmNvalue, &val, NULL);
+ p[i] = _FSBNormalize(val, bd, i);
+ }
+
+ XtVaGetValues(fc->creator.preview_child, XtNheight, &hgt, NULL);
+ context = fc->creator.fsb->fsb.context;
+ if (fc->creator.gstate == 0) {
+ XDPSSetContextDrawable(context,
+ XtWindow(fc->creator.preview_child), hgt);
+ XDPSCaptureContextGState(context, &fc->creator.gstate);
+ } else XDPSSetContextGState(context, fc->creator.gstate);
+
+ /* Force b[0] to be 1 - total(b[1..n]) to avoid round-off error */
+
+ total = 0.0;
+ for (i = 1; i < bd->num_designs; i++) {
+ b[i] = 1.0;
+ for (j = 0; j < bd->num_axes; j++) {
+ if (bd->design_positions[i*bd->num_axes + j] == 1.0) b[i] *= p[j];
+ else b[i] *= 1.0 - p[j];
+ }
+ total += b[i];
+ }
+ b[0] = 1.0 - total;
+
+ XtVaGetValues(fc->creator.size_text_field_child,
+ XmNvalue, &chSize, NULL);
+
+ if (chSize == NULL || *chSize == '\0') return;
+ size = atof(chSize);
+
+ _DPSFSetUpMM(context, fc->creator.font->font_name,
+ str, size, hgt, b, bd->num_designs, &bogusFont);
+ DPSWaitContext(context);
+ XClearWindow(XtDisplay(fc->creator.preview_child),
+ XtWindow(fc->creator.preview_child));
+ _DPSFDrawMM(context, str, hgt);
+}
+
+/* ARGSUSED */
+
+static void DrawMMCallback(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ FontCreatorWidget fc = (FontCreatorWidget) clientData;
+
+ DrawMM(fc);
+}
+
+/* ARGSUSED */
+
+static void ExposeCallback(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ FontCreatorWidget fc = (FontCreatorWidget) clientData;
+ XmDrawingAreaCallbackStruct *dac =
+ (XmDrawingAreaCallbackStruct *) callData;
+
+ if (!fc->creator.preview_fixed) {
+ XSetWindowAttributes att;
+ att.bit_gravity = ForgetGravity;
+ XChangeWindowAttributes(XtDisplay(fc),
+ XtWindow(fc->creator.preview_child),
+ CWBitGravity, &att);
+ fc->creator.preview_fixed = TRUE;
+ }
+
+ if (dac != NULL && dac->event->type == Expose &&
+ dac->event->xexpose.count != 0) return;
+
+ DrawMM(fc);
+}
+
+static void SetUpBlendList(FontCreatorWidget fc)
+{
+ XmString *CSblends;
+ int count, i;
+ BlendRec *b;
+ char buf[256];
+ FontRec *f = fc->creator.font;
+
+ sprintf(buf, "%s Blends", f->face_name);
+ XtVaSetValues(fc->creator.blend_label_child,
+ XtVaTypedArg, XmNlabelString, XtRString,
+ buf, strlen(buf)+1,
+ NULL);
+
+ if (f->blend_count == 0) {
+ count = 1;
+ CSblends = &CSempty;
+
+ } else {
+ count = f->blend_count;
+ CSblends = (XmString *) XtCalloc(count, sizeof(XmString));
+
+ for (i = 0, b = f->blend_data->blends; i < f->blend_count;
+ i++, b = b->next) {
+ CSblends[i] = b->CS_blend_name;
+ }
+ }
+
+ XtVaSetValues(fc->creator.blend_scrolled_list_child, XmNitemCount, count,
+ XmNitems, CSblends, NULL);
+
+ if (f->blend_count != 0) XtFree((XtPointer) CSblends);
+}
+
+static void CalcCarryValues(FontCreatorWidget fc, FontRec *oldf, int *carry_values)
+{
+ FontRec *f = fc->creator.font;
+ BlendDataRec *bd = f->blend_data, *oldbd = oldf->blend_data;
+ int i, j;
+
+ for (i = 0; i < bd->num_axes; i++) {
+ carry_values[i] = -1;
+ for (j = 0; j < oldbd->num_axes; j++) {
+ if (bd->name[i] == oldbd->name[j]) {
+ XmScaleGetValue(fc->creator.axis_scale_child[j],
+ carry_values+i);
+ break;
+ }
+ }
+ }
+}
+
+static void SetUpAxisLabels(FontCreatorWidget fc, FontRec *oldf, int *carry_values)
+{
+ int i;
+ char buf[20];
+ XmString cs;
+ BlendDataRec *bd = fc->creator.font->blend_data, *oldbd = 0;
+ char *value;
+
+ if (oldf != NULL) oldbd = oldf->blend_data;
+
+ for (i = 0; i < bd->num_axes; i++) {
+ if (oldf == NULL || i >= oldbd->num_axes ||
+ oldbd->name[i] != bd->name[i]) {
+ cs = UnsharedCS(bd->name[i]);
+ XtVaSetValues(fc->creator.axis_label_child[i],
+ XmNlabelString, cs, NULL);
+ XmStringFree(cs);
+ }
+ if (oldf == NULL || i >= oldbd->num_axes ||
+ oldbd->min[i] != bd->min[i]) {
+ sprintf(buf, "%d", bd->min[i]);
+ cs = UnsharedCS(buf);
+ XtVaSetValues(fc->creator.axis_min_label_child[i],
+ XmNlabelString, cs, NULL);
+ XmStringFree(cs);
+ }
+ if (oldf == NULL || i >= oldbd->num_axes ||
+ oldbd->max[i] != bd->max[i]) {
+ sprintf(buf, "%d", bd->max[i]);
+ cs = UnsharedCS(buf);
+ XtVaSetValues(fc->creator.axis_max_label_child[i],
+ XmNlabelString, cs, NULL);
+ XmStringFree(cs);
+ }
+ if (oldf == NULL || carry_values[i] == -1) {
+ if (bd->name[i] == opticalSize &&
+ XmToggleButtonGadgetGetState(
+ fc->creator.follow_size_toggle_child)) {
+ XtVaGetValues(fc->creator.fsb->fsb.size_text_field_child,
+ XmNvalue, &value, NULL);
+ if (value == NULL || *value == '\0') {
+ carry_values[i] = bd->min[i];
+ } else carry_values[i] = atof(value) + 0.5;
+ } else carry_values[i] = bd->min[i];
+ }
+ if (carry_values[i] < bd->min[i]) carry_values[i] = bd->min[i];
+ else if (carry_values[i] > bd->max[i]) carry_values[i] = bd->max[i];
+ XtVaSetValues(fc->creator.axis_scale_child[i],
+ XmNminimum, bd->min[i], XmNmaximum, bd->max[i],
+ XmNvalue, carry_values[i], NULL);
+ }
+}
+
+static void ManageAxes(FontCreatorWidget fc)
+{
+ Widget w[5*MAX_AXES];
+ int i, j;
+ int diff;
+
+ diff = fc->creator.managed_axes - fc->creator.font->blend_data->num_axes;
+
+ if (diff == 0) return;
+
+ if (diff < 0) {
+ for (i = fc->creator.managed_axes, j=0; j < -diff * 5; i++, j+=5) {
+ w[j] = fc->creator.axis_label_child[i];
+ w[j+1] = fc->creator.axis_scale_child[i];
+ w[j+2] = fc->creator.axis_value_text_child[i];
+ w[j+3] = fc->creator.axis_min_label_child[i];
+ w[j+4] = fc->creator.axis_max_label_child[i];
+ }
+ XtManageChildren(w, -diff * 5);
+ } else {
+ for (i = fc->creator.font->blend_data->num_axes, j=0; j < diff * 5;
+ i++, j+=5) {
+ w[j] = fc->creator.axis_label_child[i];
+ w[j+1] = fc->creator.axis_scale_child[i];
+ w[j+2] = fc->creator.axis_value_text_child[i];
+ w[j+3] = fc->creator.axis_min_label_child[i];
+ w[j+4] = fc->creator.axis_max_label_child[i];
+ }
+ XtUnmanageChildren(w, diff * 5);
+ }
+ fc->creator.managed_axes = fc->creator.font->blend_data->num_axes;
+}
+
+static void SetScaleValues(FontCreatorWidget fc)
+{
+ int val;
+ char buf[32];
+ int i, axes;
+
+ axes = fc->creator.font->blend_data->num_axes;
+
+ for (i = 0; i < axes; i++) {
+ XmScaleGetValue(fc->creator.axis_scale_child[i], &val);
+ sprintf(buf, "%d", val);
+ XmTextFieldSetString(fc->creator.axis_value_text_child[i], buf);
+ }
+}
+
+static void SetUpAxes(FontCreatorWidget fc, FontRec *oldf)
+{
+ int carry_values[MAX_AXES];
+
+ if (oldf != NULL) CalcCarryValues(fc, oldf, carry_values);
+ SetUpAxisLabels(fc, oldf, carry_values);
+ SetScaleValues(fc);
+ ManageAxes(fc);
+}
+
+/* ARGSUSED */
+
+static void FaceSelect(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ XmListCallbackStruct *listCB = (XmListCallbackStruct *) callData;
+ FontCreatorWidget fc = (FontCreatorWidget) clientData;
+ FontRec *f, *oldf = fc->creator.font;
+ int i;
+
+ i = 0;
+ f = fc->creator.family->fonts;
+ while (f != NULL) {
+ if (f->blend_data != NULL) i++;
+ if (i == listCB->item_position) break;
+ f = f->next;
+ }
+
+ if (f == NULL) return;
+ if (!_FSBDownloadFontIfNecessary(f, fc->creator.fsb)) {
+ _FSBFlushFont(fc->creator.fsb, f);
+ return;
+ }
+ if (fc->creator.font != NULL) fc->creator.font->in_font_creator = False;
+ fc->creator.font = f;
+ f->in_font_creator = True;
+ SetUpBlendList(fc);
+ SetUpAxes(fc, oldf);
+
+ DrawMM(fc);
+}
+
+static void HandleSelectedBlend(FontCreatorWidget fc, int n)
+{
+ BlendDataRec *bd = fc->creator.font->blend_data;
+ BlendRec *b;
+ int i;
+ int value;
+ char buf[32];
+
+ b = bd->blends;
+ /* List uses 1-based addressing!! */
+ for (i = 1; i < n; i++) b = b->next;
+
+ XmTextFieldSetString(fc->creator.name_text_child, b->blend_name);
+
+ for (i = 0; i < bd->num_axes; i++) {
+ value = _FSBUnnormalize(b->data[i], bd, i);
+ XmScaleSetValue(fc->creator.axis_scale_child[i], value);
+ sprintf(buf, "%d", value);
+ XmTextFieldSetString(fc->creator.axis_value_text_child[i], buf);
+ }
+}
+
+/* ARGSUSED */
+
+static void BlendSelect(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ XmListCallbackStruct *listCB = (XmListCallbackStruct *) callData;
+ FontCreatorWidget fc = (FontCreatorWidget) clientData;
+
+ if (fc->creator.font->blend_count == 0) return;
+
+ HandleSelectedBlend(fc, listCB->item_position);
+
+ DrawMM(fc);
+}
+
+/* ARGSUSED */
+
+static void SetValue(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ XmScaleCallbackStruct *scaleData = (XmScaleCallbackStruct *) callData;
+ Widget text = (Widget) clientData;
+ char buf[32];
+
+ sprintf(buf, "%d", scaleData->value);
+ XmTextFieldSetString(text, buf);
+}
+
+/* ARGSUSED */
+
+static void SetScale(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ Widget scale = (Widget) clientData;
+ char *value;
+ int val, min, max;
+ char buf[32];
+
+ value = XmTextFieldGetString(widget);
+ val = atoi(value);
+ XtVaGetValues(scale, XmNminimum, &min, XmNmaximum, &max, NULL);
+ if (val < min) val = min;
+ if (val > max) val = max;
+ XmScaleSetValue(scale, val);
+
+ /* Handle range and illegal characters this way...*/
+
+ sprintf(buf, "%d", val);
+ XmTextFieldSetString(widget, buf);
+}
+
+/* ARGSUSED */
+
+static void DeleteMessage(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ XtDestroyWidget(widget);
+}
+
+static void PutUpDialog(FontCreatorWidget fc, char *name)
+{
+ Widget message, w;
+
+ message = XmCreateInformationDialog((Widget) fc, name, (ArgList) NULL, 0);
+ w = XmMessageBoxGetChild(message, XmDIALOG_CANCEL_BUTTON);
+ XtUnmanageChild(w);
+ w = XmMessageBoxGetChild(message, XmDIALOG_HELP_BUTTON);
+ XtUnmanageChild(w);
+ XtAddCallback(message, XmNokCallback, DeleteMessage, (XtPointer) NULL);
+
+ XtManageChild(message);
+}
+
+static void NoName(FontCreatorWidget fc)
+{
+ PutUpDialog(fc, "noNameMessage");
+}
+
+static void UsedName(FontCreatorWidget fc)
+{
+ PutUpDialog(fc, "usedNameMessage");
+}
+
+static void SomeUsedName(FontCreatorWidget fc)
+{
+ PutUpDialog(fc, "someUsedNameMessage");
+}
+
+static void NoSuchName(FontCreatorWidget fc)
+{
+ PutUpDialog(fc, "noSuchNameMessage");
+}
+
+static Boolean DoAdd(FontCreatorWidget fc, FontRec *f, String name)
+{
+ char *spaceName;
+ BlendRec *b, *newb, **last;
+ BlendDataRec *bd = f->blend_data;
+ int val[MAX_AXES], i;
+
+ for (b = bd->blends; b != NULL; b = b->next) {
+ if (strcmp(name, b->blend_name) == 0) return True;
+ }
+
+ newb = (BlendRec *) XtMalloc(sizeof(BlendRec));
+ newb->blend_name = Canonical(name);
+ newb->CS_blend_name = CS(newb->blend_name, (Widget) fc);
+
+ spaceName = (char *) XtMalloc(strlen(name) + 4);
+ spaceName[0] = spaceName[1] = spaceName[2] = ' ';
+ strcpy(spaceName+3, name);
+ newb->CS_space_blend_name = CS(spaceName, (Widget) fc);
+ XtFree((XtPointer) spaceName);
+
+ for (i = 0; i < bd->num_axes; i++) {
+ XtVaGetValues(fc->creator.axis_scale_child[i],
+ XmNvalue, val+i, NULL);
+ newb->data[i] = _FSBNormalize(val[i], bd, i);
+ }
+ for (/**/; i < MAX_AXES; i++) newb->data[i] = 0.0;
+
+ newb->font_name = _FSBGenFontName(f->font_name, val, bd);
+
+ f->blend_count++;
+ fc->creator.family->blend_count++;
+
+ last = &bd->blends;
+ for (b = bd->blends; b != NULL; b = b->next) {
+ if (strcmp(name, b->blend_name) < 0) break;
+ last = &b->next;
+ }
+ newb->next = b;
+ *last = newb;
+
+ SetUpBlendList(fc);
+ _FSBSetUpFaceList(fc->creator.fsb, False);
+ return False;
+}
+
+/* ARGSUSED */
+
+static void AddCallback(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ FontCreatorWidget fc = (FontCreatorWidget) clientData;
+ char *value;
+ FontRec *f;
+ Boolean failures = False;
+ BlendDataRec *bd = fc->creator.font->blend_data;
+ int i;
+
+ value = XmTextFieldGetString(fc->creator.name_text_child);
+
+ if (value == NULL || *value == '\0') {
+ NoName(fc);
+ return;
+ }
+
+ if (XmToggleButtonGadgetGetState(fc->creator.do_all_toggle_child)) {
+ for (f = fc->creator.family->fonts; f != NULL; f = f->next) {
+ if (f->blend_data != NULL &&
+ f->blend_data->num_axes == bd->num_axes) {
+ for (i = 0; i < bd->num_axes; i++) {
+ if (f->blend_data->name[i] != bd->name[i]) break;
+ }
+ if (i == bd->num_axes) failures |= DoAdd(fc, f, value);
+ }
+ }
+ if (failures) SomeUsedName(fc);
+ } else if (DoAdd(fc, fc->creator.font, value)) UsedName(fc);
+}
+
+static Boolean DoReplace(FontCreatorWidget fc, FontRec *f, String name)
+{
+ BlendDataRec *bd = f->blend_data;
+ BlendRec *b;
+ int val[MAX_AXES], i;
+
+ name = Canonical(name);
+ for (b = bd->blends; b != NULL; b = b->next) {
+ if (name == b->blend_name) {
+ for (i = 0; i < bd->num_axes; i++) {
+ XtVaGetValues(fc->creator.axis_scale_child[i],
+ XmNvalue, val+i, NULL);
+ b->data[i] = _FSBNormalize(val[i], bd, i);
+ }
+ b->font_name = _FSBGenFontName(f->font_name, val, bd);
+ if (fc->creator.fsb->fsb.currently_selected_blend == b) {
+ _FSBSetUpFaceList(fc->creator.fsb, True);
+ }
+ return False;
+ }
+ }
+ return True;
+}
+
+/* ARGSUSED */
+
+static void ReplaceCallback(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ FontCreatorWidget fc = (FontCreatorWidget) clientData;
+ char *value;
+ FontRec *f;
+ Boolean failures = True;
+ BlendDataRec *bd = fc->creator.font->blend_data;
+ int i;
+
+ value = XmTextFieldGetString(fc->creator.name_text_child);
+
+ if (value == NULL || *value == '\0') {
+ NoName(fc);
+ return;
+ }
+
+ if (XmToggleButtonGadgetGetState(fc->creator.do_all_toggle_child)) {
+ for (f = fc->creator.family->fonts; f != NULL; f = f->next) {
+ if (f->blend_data != NULL &&
+ f->blend_data->num_axes == bd->num_axes) {
+ for (i = 0; i < bd->num_axes; i++) {
+ if (f->blend_data->name[i] != bd->name[i]) break;
+ }
+ if (i == bd->num_axes) failures &= DoReplace(fc, f, value);
+ }
+ }
+ if (failures) NoSuchName(fc);
+ } else if (DoReplace(fc, fc->creator.font, value)) NoSuchName(fc);
+}
+
+static Boolean DoDelete(FontCreatorWidget fc, FontRec *f, String name)
+{
+ BlendDataRec *bd = f->blend_data;
+ BlendRec *b, *oldb;
+ Boolean current = FALSE;
+
+ name = Canonical(name);
+ for (b = bd->blends, oldb = NULL; b != NULL; oldb = b, b = b->next) {
+ if (name == b->blend_name) {
+ if (oldb == NULL) bd->blends = b->next;
+ else oldb->next = b->next;
+ if (fc->creator.fsb->fsb.currently_selected_blend == b) {
+ fc->creator.fsb->fsb.currently_selected_blend = NULL;
+ current = TRUE;
+ }
+ XtFree((XtPointer) b);
+ f->blend_count--;
+ fc->creator.family->blend_count--;
+ SetUpBlendList(fc);
+ _FSBSetUpFaceList(fc->creator.fsb, current);
+ return False;
+ }
+ }
+ return True;
+}
+
+/* ARGSUSED */
+
+static void DeleteCallback(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ FontCreatorWidget fc = (FontCreatorWidget) clientData;
+ char *value;
+ FontRec *f;
+ Boolean failures = True;
+
+ value = XmTextFieldGetString(fc->creator.name_text_child);
+
+ if (value == NULL || *value == '\0') {
+ NoName(fc);
+ return;
+ }
+
+ if (XmToggleButtonGadgetGetState(fc->creator.do_all_toggle_child)) {
+ for (f = fc->creator.family->fonts; f != NULL; f = f->next) {
+ if (f->blend_data != NULL) {
+ failures &= DoDelete(fc, f, value);
+ }
+ }
+ if (failures) NoSuchName(fc);
+ } else if (DoDelete(fc, fc->creator.font, value)) NoSuchName(fc);
+}
+
+/* ARGSUSED */
+
+static void UnmanageOptions(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ FontCreatorWidget fc = (FontCreatorWidget) clientData;
+
+ XtUnmanageChild(fc->creator.option_box);
+}
+
+/* ARGSUSED */
+
+static void ShowOptions(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ FontCreatorWidget fc = (FontCreatorWidget) clientData;
+
+ XtManageChild(fc->creator.option_box);
+}
+
+/* ARGSUSED */
+
+static void GenerateCallback(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ FontCreatorWidget fc = (FontCreatorWidget) clientData;
+ BlendDataRec *bd = fc->creator.font->blend_data;
+ int i, val[MAX_AXES];
+ char nameBuf[256];
+ char *ch;
+
+ for (i = 0; i < bd->num_axes; i++) {
+ XtVaGetValues(fc->creator.axis_scale_child[i],
+ XmNvalue, val+i, NULL);
+ }
+
+ ch = nameBuf;
+
+ for (i = 0; i < bd->num_axes - 1; i++) {
+ sprintf(ch, "%d ", val[i]);
+ ch = ch + strlen(ch);
+ }
+
+ sprintf(ch, "%d", val[bd->num_axes - 1]);
+
+ XmTextFieldSetString(fc->creator.name_text_child, nameBuf);
+}
+
+/* ARGSUSED */
+
+static void DismissCallback(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ FontCreatorWidget fc = (FontCreatorWidget) clientData;
+
+ if (XtIsShell(XtParent(fc))) XtPopdown(XtParent(fc));
+ XtCallCallbackList(widget, fc->creator.dismiss_callback, (XtPointer) NULL);
+}
+
+/* ARGSUSED */
+
+static void SizeChanged(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ String value;
+ FontCreatorWidget fc = (FontCreatorWidget) clientData;
+ int size;
+ FontRec *f = fc->creator.font;
+ BlendDataRec *bd;
+ int i;
+ char buf[32];
+
+ if (f == NULL || f->blend_data == NULL) return;
+
+ /* See if we have an optical size scale */
+ bd = f->blend_data;
+
+ for (i = 0; i < bd->num_axes; i++) {
+ if (bd->name[i] == opticalSize) break;
+ }
+ if (i == bd->num_axes) return;
+
+ if (!XmToggleButtonGadgetGetState(fc->creator.follow_size_toggle_child)) {
+ return;
+ }
+
+ XtVaGetValues(widget, XmNvalue, &value, NULL);
+
+ if (value == NULL || *value == '\0') return;
+ size = atof(value) + 0.5;
+ sprintf(buf, "%d", size);
+ XmTextFieldSetString(fc->creator.axis_value_text_child[i], buf);
+
+ SetScale(fc->creator.axis_value_text_child[i],
+ (XtPointer) fc->creator.axis_scale_child[i], (XtPointer) NULL);
+ DrawMM(fc);
+}
+
+/* There's a problem; sometimes the change has already been made in the field,
+ and sometimes it hasn't. The times when it has seem to correspond to
+ making changes with the size option menu, so we use this disgusting
+ global flag to notice when this happens. We also use this to tell whether
+ or not the change is coming from internal to the widget or as a result
+ of user interaction. */
+
+static Boolean changingSize = False;
+
+/* ARGSUSED */
+
+static void SizeSelect(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ String value;
+ Widget option;
+ FontCreatorWidget fc = (FontCreatorWidget) clientData;
+ char *ch;
+
+ XtVaGetValues(widget, XmNvalue, &value, NULL);
+
+ if (value == NULL) option = fc->creator.other_size;
+ else {
+ for (ch = value; *ch != '\0'; ch++) if (*ch == '.') *ch = '-';
+
+ option = XtNameToWidget(fc->creator.size_menu, value);
+ if (option == NULL) option = fc->creator.other_size;
+ }
+
+ XtVaSetValues(fc->creator.size_option_menu_child,
+ XmNmenuHistory, option, NULL);
+}
+
+/* ARGSUSED */
+
+static void TextVerify(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ XmTextVerifyPtr v = (XmTextVerifyPtr) callData;
+ char ch, *cp;
+ int decimalPoints = 0;
+ int i;
+
+ if (changingSize) return; /* We know what we're doing; allow it */
+
+ /* Should probably look at format field, but seems to contain garbage */
+
+ if (v->text->length == 0) return;
+
+ for (i = 0; i < v->text->length; i++) {
+ ch = v->text->ptr[i];
+ if (ch == '.') decimalPoints++;
+ else if (!isdigit(ch)) {
+ v->doit = False;
+ return;
+ }
+ }
+
+ if (decimalPoints > 1) {
+ v->doit = False;
+ return;
+ }
+
+ XtVaGetValues(widget, XmNvalue, &cp, NULL);
+
+ for (/**/; *cp != '\0'; cp++) {
+ if (*cp == '.') decimalPoints++;
+ }
+
+ if (decimalPoints > 1) v->doit = False;
+}
+
+/* ARGSUSED */
+
+static void SetSize(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ char buf[20];
+ char *ch;
+ FontCreatorWidget fc = (FontCreatorWidget) clientData;
+
+ strcpy(buf, XtName(widget));
+ for (ch = buf; *ch != '\0'; ch++) if (*ch == '-') *ch++ = '.';
+
+ changingSize = True;
+ XtVaSetValues(fc->creator.size_text_field_child, XmNvalue, buf, NULL);
+ changingSize = False;
+}
+
+/* This makes sure the selected item is visible */
+
+static void ListSelectPos(Widget w, int pos, Boolean notify)
+{
+ int topPos, items, visible;
+
+ XmListSelectPos(w, pos, notify);
+
+ XtVaGetValues(w, XmNtopItemPosition, &topPos,
+ XmNvisibleItemCount, &visible,
+ XmNitemCount, &items, NULL);
+
+ if (pos >= topPos && pos < topPos + visible) return;
+ topPos = pos - (visible-1)/2;
+ if (topPos + visible > items) topPos = items - visible + 1;
+ if (topPos < 1) topPos = 1;
+
+ XtVaSetValues(w, XmNtopItemPosition, topPos, NULL);
+}
+
+static void CreateSizeMenu(
+ FontCreatorWidget fc,
+ Boolean destroyOldChildren)
+{
+ Arg args[20];
+ int i, j;
+ Widget *sizes;
+ char buf[20];
+ Widget *children;
+ Cardinal num_children;
+ XmString csName;
+ char *ch;
+
+ if (destroyOldChildren) {
+ XtVaGetValues(fc->creator.size_menu, XtNchildren, &children,
+ XtNnumChildren, &num_children, NULL);
+
+ /* Don't destroy first child ("other") */
+ for (j = 1; (Cardinal)j < num_children; j++) XtDestroyWidget(children[j]);
+
+ sizes = (Widget *) XtMalloc((fc->creator.size_count+1) *
+ sizeof(Widget));
+ sizes[0] = children[0];
+ } else {
+ sizes = (Widget *) XtMalloc((fc->creator.size_count+1) *
+ sizeof(Widget));
+ i = 0;
+ fc->creator.other_size = sizes[0] =
+ XtCreateManagedWidget("other", xmPushButtonGadgetClass,
+ fc->creator.size_menu, args, i);
+ }
+
+ for (j = 0; j < fc->creator.size_count; j++) {
+ (void) sprintf(buf, "%g", fc->creator.sizes[j]);
+ csName = UnsharedCS(buf);
+ for (ch = buf; *ch != '\0'; ch++) if (*ch == '.') *ch = '-';
+ i = 0;
+ XtSetArg(args[i], XmNlabelString, csName); i++;
+ sizes[j+1] =
+ XmCreatePushButtonGadget(fc->creator.size_menu, buf, args, i);
+ XmStringFree(csName);
+ XtAddCallback(sizes[j+1], XmNactivateCallback,
+ SetSize, (XtPointer) fc);
+ XtAddCallback(sizes[j+1], XmNactivateCallback,
+ DrawMMCallback, (XtPointer) fc);
+ }
+ XtManageChildren(sizes, j+1);
+ XtFree((char *) sizes);
+}
+
+static void CreateChildren(FontCreatorWidget fc)
+{
+ Arg args[20];
+ int i, j;
+ Widget form, prev, w, label, sep, button;
+ char buf[20];
+
+ i = 0;
+ fc->creator.pane_child =
+ XtCreateManagedWidget("pane", xmPanedWindowWidgetClass,
+ (Widget) fc, args, i);
+
+ i = 0;
+ fc->creator.preview_child =
+ XtCreateManagedWidget("preview", xmDrawingAreaWidgetClass,
+ fc->creator.pane_child, args, i);
+ XtAddCallback(fc->creator.preview_child, XmNexposeCallback,
+ ExposeCallback, (XtPointer) fc);
+ XtAddCallback(fc->creator.preview_child, XmNresizeCallback,
+ ResizePreview, (XtPointer) fc);
+
+ i = 0;
+ form = XtCreateManagedWidget("panel", xmFormWidgetClass,
+ fc->creator.pane_child, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
+ button = XtCreateManagedWidget("deleteButton", xmPushButtonGadgetClass,
+ form, args, i);
+ XtAddCallback(button, XmNactivateCallback, DeleteCallback, (XtPointer) fc);
+
+ i = 0;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNrightWidget, button); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
+ button = XtCreateManagedWidget("replaceButton", xmPushButtonGadgetClass,
+ form, args, i);
+ XtAddCallback(button, XmNactivateCallback,
+ ReplaceCallback, (XtPointer) fc);
+
+ i = 0;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNrightWidget, button); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
+ button = XtCreateManagedWidget("addButton", xmPushButtonGadgetClass,
+ form, args, i);
+ XtAddCallback(button, XmNactivateCallback, AddCallback, (XtPointer) fc);
+
+ i = 0;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNrightWidget, button); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
+ fc->creator.generate_button_child =
+ XtCreateManagedWidget("generateButton", xmPushButtonGadgetClass,
+ form, args, i);
+ XtAddCallback(fc->creator.generate_button_child, XmNactivateCallback,
+ GenerateCallback, (XtPointer) fc);
+
+ i = 0;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNrightWidget, fc->creator.generate_button_child);i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
+ button = XtCreateManagedWidget("optionsButton", xmPushButtonGadgetClass,
+ form, args, i);
+ XtAddCallback(button, XmNactivateCallback, ShowOptions, (XtPointer) fc);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
+ button = XtCreateManagedWidget("dismissButton", xmPushButtonGadgetClass,
+ form, args, i);
+ XtAddCallback(button, XmNactivateCallback,
+ DismissCallback, (XtPointer) fc);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, button); i++;
+ sep = XtCreateManagedWidget("separator", xmSeparatorGadgetClass,
+ form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_POSITION); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, sep); i++;
+ label = XtCreateManagedWidget("sizeLabel", xmLabelGadgetClass,
+ form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_POSITION); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, label); i++;
+ fc->creator.size_text_field_child =
+ XtCreateManagedWidget("sizeTextField", xmTextFieldWidgetClass,
+ form, args, i);
+ XtAddCallback(fc->creator.size_text_field_child, XmNvalueChangedCallback,
+ SizeSelect, (XtPointer) fc);
+ XtAddCallback(fc->creator.size_text_field_child, XmNmodifyVerifyCallback,
+ TextVerify, (XtPointer) fc);
+ XtAddCallback(fc->creator.size_text_field_child, XmNactivateCallback,
+ DrawMMCallback, (XtPointer) fc);
+
+ i = 0;
+ fc->creator.size_menu = XmCreatePulldownMenu(form, "sizeMenu", args, i);
+
+ CreateSizeMenu(fc, FALSE);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, fc->creator.size_text_field_child);i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, label); i++;
+ XtSetArg(args[i], XmNsubMenuId, fc->creator.size_menu); i++;
+ fc->creator.size_option_menu_child =
+ XmCreateOptionMenu(form, "sizeOptionMenu", args, i);
+ XtManageChild(fc->creator.size_option_menu_child);
+
+ SizeSelect(fc->creator.size_text_field_child, (XtPointer) fc,
+ (XtPointer) NULL);
+
+ i = 0;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, sep); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_POSITION); i++;
+ fc->creator.name_text_child =
+ XtCreateManagedWidget("nameText", xmTextFieldWidgetClass,
+ form, args, i);
+ XtAddCallback(fc->creator.name_text_child, XmNactivateCallback,
+ AddCallback, (XtPointer) fc);
+
+ i = 0;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, fc->creator.name_text_child); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_POSITION); i++;
+ label = XtCreateManagedWidget("nameLabel", xmLabelGadgetClass,
+ form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_POSITION); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
+ label = XtCreateManagedWidget("faceLabel",xmLabelGadgetClass,
+ form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNitemCount, 1); i++;
+ XtSetArg(args[i], XmNitems, &CSempty); i++;
+ fc->creator.face_scrolled_list_child =
+ XmCreateScrolledList(form, "faceList", args, i);
+ XtAddCallback(fc->creator.face_scrolled_list_child,
+ XmNbrowseSelectionCallback, FaceSelect, (XtPointer) fc);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, label); i++;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_POSITION); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_POSITION); i++;
+ XtSetValues(XtParent(fc->creator.face_scrolled_list_child), args, i);
+ XtManageChild(fc->creator.face_scrolled_list_child);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_POSITION); i++;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_POSITION); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
+ fc->creator.blend_label_child =
+ XtCreateManagedWidget("blendLabel",xmLabelGadgetClass,
+ form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNitemCount, 1); i++;
+ XtSetArg(args[i], XmNitems, &CSempty); i++;
+ fc->creator.blend_scrolled_list_child =
+ XmCreateScrolledList(form, "blendList", args, i);
+ XtAddCallback(fc->creator.blend_scrolled_list_child,
+ XmNbrowseSelectionCallback, BlendSelect, (XtPointer) fc);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, fc->creator.blend_label_child); i++;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_POSITION); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, fc->creator.name_text_child); i++;
+ XtSetValues(XtParent(fc->creator.blend_scrolled_list_child), args, i);
+ XtManageChild(fc->creator.blend_scrolled_list_child);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_POSITION); i++;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget,
+ XtParent(fc->creator.face_scrolled_list_child)); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_POSITION); i++;
+ fc->creator.display_text_child =
+ XtCreateManagedWidget("displayText", xmTextFieldWidgetClass,
+ form, args, i);
+ XtAddCallback(fc->creator.display_text_child, XmNactivateCallback,
+ DrawMMCallback, (XtPointer) fc);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, fc->creator.display_text_child); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_POSITION); i++;
+ label = XtCreateManagedWidget("displayTextLabel", xmLabelGadgetClass,
+ form, args, i);
+
+ prev = fc->creator.display_text_child;
+
+ for (j = 0; j < 4; j++) {
+ i = 0;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_POSITION); i++;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, prev); i++;
+ sprintf(buf, "axisValue%d", j+1);
+ fc->creator.axis_value_text_child[j] =
+ XtCreateWidget(buf, xmTextFieldWidgetClass, form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_POSITION); i++;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget,
+ fc->creator.axis_value_text_child[j]); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNrightWidget,
+ fc->creator.axis_value_text_child[j]); i++;
+ sprintf(buf, "axisScale%d", j+1);
+ fc->creator.axis_scale_child[j] =
+ XtCreateWidget(buf, xmScaleWidgetClass, form, args, i);
+ XtAddCallback(fc->creator.axis_scale_child[j],
+ XmNvalueChangedCallback, DrawMMCallback, (XtPointer) fc);
+ XtAddCallback(fc->creator.axis_scale_child[j],
+ XmNdragCallback, DrawMMCallback, (XtPointer) fc);
+ XtAddCallback(fc->creator.axis_scale_child[j],
+ XmNvalueChangedCallback, SetValue,
+ (XtPointer) fc->creator.axis_value_text_child[j]);
+ XtAddCallback(fc->creator.axis_scale_child[j],
+ XmNdragCallback, SetValue,
+ (XtPointer) fc->creator.axis_value_text_child[j]);
+ XtAddCallback(fc->creator.axis_value_text_child[j],
+ XmNactivateCallback, SetScale,
+ (XtPointer) fc->creator.axis_scale_child[j]);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget,
+ fc->creator.axis_scale_child[j]); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET);i++;
+ XtSetArg(args[i], XmNrightWidget,
+ fc->creator.axis_scale_child[j]); i++;
+ sprintf(buf, "axisMax%d", j+1);
+ fc->creator.axis_max_label_child[j] =
+ XtCreateWidget(buf, xmLabelGadgetClass, form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget,
+ fc->creator.axis_scale_child[j]); i++;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget,
+ fc->creator.axis_scale_child[j]); i++;
+ sprintf(buf, "axisMin%d", j+1);
+ fc->creator.axis_min_label_child[j] =
+ XtCreateWidget(buf, xmLabelGadgetClass, form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget,
+ fc->creator.axis_value_text_child[j]); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_POSITION); i++;
+ sprintf(buf, "axisLabel%d", j+1);
+ fc->creator.axis_label_child[j] =
+ XtCreateWidget(buf, xmLabelGadgetClass, form, args, i);
+
+ prev = fc->creator.axis_value_text_child[j];
+ }
+
+ /* Create the options box so we have the toggles */
+
+ fc->creator.option_box = XmCreateFormDialog((Widget) fc, "optionBox",
+ (Arg *) NULL, 0);
+ w = XtCreateManagedWidget("filterBox", xmRowColumnWidgetClass,
+ fc->creator.option_box, (Arg *) NULL, 0);
+ fc->creator.do_all_toggle_child =
+ XtCreateManagedWidget("doAllToggle", xmToggleButtonGadgetClass,
+ w, (Arg *) NULL, 0);
+ fc->creator.follow_size_toggle_child =
+ XtCreateManagedWidget("followSizeToggle",
+ xmToggleButtonGadgetClass,
+ w, (Arg *) NULL, 0);
+ button = XtCreateManagedWidget("dismissOptionButton",
+ xmPushButtonGadgetClass,
+ w, (Arg *) NULL, 0);
+ XtAddCallback(button, XmNactivateCallback,
+ UnmanageOptions, (XtPointer) fc);
+}
+
+/* ARGSUSED */
+
+static void Initialize(
+ Widget request, Widget new,
+ ArgList args,
+ Cardinal *num_args)
+{
+ FontCreatorWidget fc = (FontCreatorWidget) new;
+
+ /* Must have a fsb */
+
+ if (fc->creator.fsb == NULL) {
+ XtAppErrorMsg(XtWidgetToApplicationContext(new),
+ "initializeFontCreator", "noFontSelectionBox",
+ "FontSelectionBoxError",
+ "No font selection box given to font creator",
+ (String *) NULL, (Cardinal *) NULL);
+ }
+
+ /* Verify size list */
+
+ if (fc->creator.size_count > 0 && fc->creator.sizes == NULL) {
+ XtAppWarningMsg(XtWidgetToApplicationContext(new),
+ "initializeFontCreator", "sizeMismatch",
+ "FontSelectionBoxError",
+ "Size count specified but no sizes present",
+ (String *) NULL, (Cardinal *) NULL);
+ fc->creator.size_count = 0;
+ }
+
+ if (fc->creator.size_count < 0) {
+ XtAppWarningMsg(XtWidgetToApplicationContext(new),
+ "initializeFontCreator", "negativeSize",
+ "FontSelectionBoxError",
+ "Size count should not be negative",
+ (String *) NULL, (Cardinal *) NULL);
+ fc->creator.size_count = 0;
+ }
+
+ fc->creator.gstate = 0;
+ fc->creator.family = NULL;
+ fc->creator.font = NULL;
+ fc->creator.managed_axes = 0;
+ fc->creator.preview_fixed = False;
+ fc->creator.option_box = NULL;
+
+ CreateChildren(fc);
+ XtAddCallback(fc->creator.fsb->fsb.size_text_field_child,
+ XmNvalueChangedCallback, SizeChanged, (XtPointer) fc);
+}
+
+static void SelectBlend(FontCreatorWidget fc, BlendRec *cur_b)
+{
+ int i, cur = 0;
+ BlendRec *b;
+ int *selectList, selectCount;
+
+ if (cur_b == NULL) {
+ if (!XmListGetSelectedPos(fc->creator.blend_scrolled_list_child,
+ &selectList, &selectCount)) return;
+ if (selectCount == 0 || *selectList < 1) return;
+ cur = *selectList;
+ XtFree((XtPointer) selectList);
+ } else {
+ for (i = 0, b = fc->creator.font->blend_data->blends;
+ i < fc->creator.font->blend_count; i++, b = b->next) {
+ if (b == cur_b) {
+ cur = i+1;
+ break;
+ }
+ }
+ }
+ ListSelectPos(fc->creator.blend_scrolled_list_child, cur, FALSE);
+ HandleSelectedBlend(fc, cur);
+}
+
+void _FSBSetCreatorFamily(Widget w, FontFamilyRec *ff)
+{
+ FontCreatorWidget fc = (FontCreatorWidget) w;
+ int i, count = 0, cur = 1;
+ FontRec *newf = NULL, *f, *oldf = fc->creator.font;
+ XmString *CSfaces;
+
+ if (ff != fc->creator.family) {
+ fc->creator.family = ff;
+
+ CSfaces = (XmString *) XtCalloc(ff->font_count, sizeof(XmString));
+
+ for (i = 0, f = ff->fonts; i < ff->font_count; i++, f = f->next) {
+ if (f->blend_data == NULL) continue;
+
+ if (newf == NULL) newf = f;
+ CSfaces[count] = f->CS_face_name;
+ count++;
+ if (f == fc->creator.fsb->fsb.currently_selected_face) {
+ cur = count;
+ newf = f;
+ }
+ }
+
+ XtVaSetValues(fc->creator.face_scrolled_list_child,
+ XmNitemCount, count, XmNitems, CSfaces, NULL);
+
+ XtFree((XtPointer) CSfaces);
+
+ } else {
+ for (i = 0, f = ff->fonts; i < ff->font_count; i++, f = f->next) {
+ if (f->blend_data == NULL) continue;
+ count++;
+ if (newf == NULL) newf = f;
+ if (f == fc->creator.fsb->fsb.currently_selected_face) {
+ cur = count;
+ newf = f;
+ break;
+ }
+ }
+ }
+
+ if (fc->creator.font != NULL) fc->creator.font->in_font_creator = False;
+ fc->creator.font = newf;
+ newf->in_font_creator = True;
+ ListSelectPos(fc->creator.face_scrolled_list_child, cur, FALSE);
+ SetUpBlendList(fc);
+ SetUpAxes(fc, oldf);
+ if (fc->creator.fsb->fsb.currently_selected_blend != 0) {
+ SelectBlend(fc, fc->creator.fsb->fsb.currently_selected_blend);
+ } else {
+ SelectBlend(fc, NULL);
+ }
+ SetScaleValues(fc);
+ XmTextFieldSetString(fc->creator.display_text_child, ff->family_name);
+ DrawMM(fc);
+}
+
+static void Destroy(Widget widget)
+{
+ FontCreatorWidget fc = (FontCreatorWidget) widget;
+
+ if (fc->creator.gstate != 0) {
+ XDPSFreeContextGState(fc->creator.fsb->fsb.context,
+ fc->creator.gstate);
+ }
+}
+
+static void Resize(Widget widget)
+{
+ FontCreatorWidget fc = (FontCreatorWidget) widget;
+
+ XtResizeWidget(fc->creator.pane_child, fc->core.width, fc->core.height, 0);
+}
+
+/* ARGSUSED */
+
+static Boolean SetValues(
+ Widget old, Widget req, Widget new,
+ ArgList args,
+ Cardinal *num_args)
+{
+ FontCreatorWidget oldfc = (FontCreatorWidget) old;
+ FontCreatorWidget newfc = (FontCreatorWidget) new;
+
+#define NE(field) newfc->creator.field != oldfc->creator.field
+
+ if (NE(fsb)) newfc->creator.fsb = oldfc->creator.fsb;
+
+ if (newfc->creator.size_count > 0 && newfc->creator.sizes == NULL) {
+ XtAppWarningMsg(XtWidgetToApplicationContext(new),
+ "setValuesFontCreator", "sizeMismatch",
+ "FontSelectionBoxError",
+ "Size count specified but no sizes present",
+ (String *) NULL, (Cardinal *) NULL);
+ newfc->creator.size_count = 0;
+ }
+
+ if (newfc->creator.size_count < 0) {
+ XtAppWarningMsg(XtWidgetToApplicationContext(new),
+ "setValuesFontCreator", "negativeSize",
+ "FontSelectionBoxError",
+ "Size count should not be negative",
+ (String *) NULL, (Cardinal *) NULL);
+ newfc->creator.size_count = 0;
+ }
+
+ if (NE(sizes)) CreateSizeMenu(newfc, TRUE);
+#undef NE
+ return False;
+}
+
+/* ARGSUSED */
+
+static XtGeometryResult GeometryManager(
+ Widget w,
+ XtWidgetGeometry *desired, XtWidgetGeometry *allowed)
+{
+#define WANTS(flag) (desired->request_mode & flag)
+
+ if (WANTS(XtCWQueryOnly)) return XtGeometryYes;
+
+ if (WANTS(CWWidth)) w->core.width = desired->width;
+ if (WANTS(CWHeight)) w->core.height = desired->height;
+ if (WANTS(CWX)) w->core.x = desired->x;
+ if (WANTS(CWY)) w->core.y = desired->y;
+ if (WANTS(CWBorderWidth)) {
+ w->core.border_width = desired->border_width;
+ }
+
+ return XtGeometryYes;
+#undef WANTS
+}
+
+static void ChangeManaged(Widget w)
+{
+ FontCreatorWidget fc = (FontCreatorWidget) w;
+
+ w->core.width = fc->composite.children[0]->core.width;
+ w->core.height = fc->composite.children[0]->core.height;
+}
diff --git a/nx-X11/lib/dpstk/FontSB.c b/nx-X11/lib/dpstk/FontSB.c
new file mode 100644
index 000000000..a529f3af0
--- /dev/null
+++ b/nx-X11/lib/dpstk/FontSB.c
@@ -0,0 +1,4884 @@
+/*
+ * FontSB.c
+ *
+ * (c) Copyright 1991-1994 Adobe Systems Incorporated.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sublicense this software
+ * and its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notices appear in all copies and that
+ * both those copyright notices and this permission notice appear in
+ * supporting documentation and that the name of Adobe Systems Incorporated
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. No trademark license
+ * to use the Adobe trademarks is hereby granted. If the Adobe trademark
+ * "Display PostScript"(tm) is used to describe this software, its
+ * functionality or for any other purpose, such use shall be limited to a
+ * statement that this software works in conjunction with the Display
+ * PostScript system. Proper trademark attribution to reflect Adobe's
+ * ownership of the trademark shall be given whenever any such reference to
+ * the Display PostScript system is made.
+ *
+ * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
+ * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
+ * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
+ * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
+ * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
+ *
+ * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+ * Incorporated which may be registered in certain jurisdictions
+ *
+ * Author: Adobe Systems Incorporated
+ */
+/* $XFree86$ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <math.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <Xm/Xm.h>
+
+/* There are no words to describe how I feel about having to do this */
+
+#if XmVersion > 1001
+#include <Xm/ManagerP.h>
+#else
+#include <Xm/XmP.h>
+#endif
+
+#include <Xm/Form.h>
+#include <Xm/List.h>
+#include <Xm/Label.h>
+#include <Xm/LabelG.h>
+#include <Xm/PushB.h>
+#include <Xm/PanedW.h>
+#include <Xm/PushBG.h>
+#include <Xm/SeparatoG.h>
+#include <Xm/TextF.h>
+#include <Xm/RowColumn.h>
+#include <Xm/DrawingA.h>
+#include <Xm/MessageB.h>
+#include <DPS/dpsXclient.h>
+#include "dpsXcommonI.h"
+#include <DPS/dpsXcommon.h>
+#include <DPS/dpsXshare.h>
+#include <DPS/PSres.h>
+#include <DPS/FontSBP.h>
+#include "FSBwraps.h"
+#include "FontSBI.h"
+#include <DPS/FontSample.h>
+#include <DPS/FontCreato.h>
+#include <pwd.h>
+
+#define PATH_BUF_SIZE 1024
+
+/* Turn a string into a compound string */
+#define UnsharedCS(str) XmStringCreate(str, XmSTRING_DEFAULT_CHARSET)
+#define CS(str, w) _FSBCreateSharedCS(str, w)
+static XmString CSempty;
+
+/* Create a canonical representation of a string, and as a side effect
+ make sure the string is in permanent storage. This implementation may
+ not work under all Xlibs */
+
+#define Canonical(str) XrmQuarkToString(XrmStringToQuark(str))
+
+static float defaultSizeList[] = {
+#ifndef DEFAULT_SIZE_LIST
+ 8, 10, 12, 14, 16, 18, 24, 36, 48, 72
+#else
+ DEFAULT_SIZE_LIST
+#endif /* DEFAULT_SIZE_LIST */
+};
+
+#ifndef DEFAULT_SIZE_LIST_COUNT
+#define DEFAULT_SIZE_LIST_COUNT 10
+#endif /* DEFAULT_SIZE_LIST_COUNT */
+
+#ifndef DEFAULT_SIZE
+static float default_size = 12.0;
+#else
+static float default_size = DEFAULT_SIZE
+#endif /* DEFAULT_SIZE */
+
+#ifndef DEFAULT_RESOURCE_PATH
+#define DEFAULT_RESOURCE_PATH NULL
+#endif /* DEFAULT_RESOURCE_PATH */
+
+#ifndef DEFAULT_MAX_PENDING
+#define DEFAULT_MAX_PENDING 10
+#endif /* DEFAULT_MAX_PENDING */
+
+#define Offset(field) XtOffsetOf(FontSelectionBoxRec, fsb.field)
+
+static XtResource resources[] = {
+ {XtNcontext, XtCContext, XtRDPSContext, sizeof(DPSContext),
+ Offset(context), XtRDPSContext, (XtPointer) NULL},
+ {XtNpreviewString, XtCPreviewString, XtRString, sizeof(String),
+ Offset(preview_string), XtRString, (XtPointer) NULL},
+ {XtNsizes, XtCSizes, XtRFloatList, sizeof(float*),
+ Offset(sizes), XtRImmediate, (XtPointer) defaultSizeList},
+ {XtNsizeCount, XtCSizeCount, XtRInt, sizeof(int),
+ Offset(size_count), XtRImmediate, (XtPointer) DEFAULT_SIZE_LIST_COUNT},
+ {XtNdefaultResourcePath, XtCDefaultResourcePath, XtRString, sizeof(String),
+ Offset(default_resource_path), XtRImmediate,
+ (XtPointer) DEFAULT_RESOURCE_PATH},
+ {XtNresourcePathOverride, XtCResourcePathOverride,
+ XtRString, sizeof(String),
+ Offset(resource_path_override), XtRString, (XtPointer) NULL},
+ {XtNuseFontName, XtCUseFontName, XtRBoolean, sizeof(Boolean),
+ Offset(use_font_name), XtRImmediate, (XtPointer) True},
+ {XtNfontName, XtCFontName, XtRString, sizeof(String),
+ Offset(font_name), XtRString, (XtPointer) NULL},
+ {XtNfontFamily, XtCFontFamily, XtRString, sizeof(String),
+ Offset(font_family), XtRString, (XtPointer) NULL},
+ {XtNfontFace, XtCFontFace, XtRString, sizeof(String),
+ Offset(font_face), XtRString, (XtPointer) NULL},
+ {XtNfontBlend, XtCFontBlend, XtRString, sizeof(String),
+ Offset(font_blend), XtRString, (XtPointer) NULL},
+ {XtNfontSize, XtCFontSize, XtRFloat, sizeof(String),
+ Offset(font_size), XtRFloat, (XtPointer) &default_size},
+ {XtNfontNameMultiple, XtCFontNameMultiple, XtRBoolean, sizeof(Boolean),
+ Offset(font_name_multiple), XtRImmediate, (XtPointer) False},
+ {XtNfontFamilyMultiple, XtCFontFamilyMultiple, XtRBoolean, sizeof(Boolean),
+ Offset(font_family_multiple), XtRImmediate, (XtPointer) False},
+ {XtNfontFaceMultiple, XtCFontFaceMultiple, XtRBoolean, sizeof(Boolean),
+ Offset(font_face_multiple), XtRImmediate, (XtPointer) False},
+ {XtNfontSizeMultiple, XtCFontSizeMultiple, XtRBoolean, sizeof(Boolean),
+ Offset(font_size_multiple), XtRImmediate, (XtPointer) False},
+ {XtNgetServerFonts, XtCGetServerFonts, XtRBoolean, sizeof(Boolean),
+ Offset(get_server_fonts), XtRImmediate, (XtPointer) True},
+ {XtNgetAFM, XtCGetAFM, XtRBoolean, sizeof(Boolean),
+ Offset(get_afm), XtRImmediate, (XtPointer) False},
+ {XtNautoPreview, XtCAutoPreview, XtRBoolean, sizeof(Boolean),
+ Offset(auto_preview), XtRImmediate, (XtPointer) True},
+ {XtNpreviewOnChange, XtCPreviewOnChange, XtRBoolean, sizeof(Boolean),
+ Offset(preview_on_change), XtRImmediate, (XtPointer) True},
+ {XtNundefUnusedFonts, XtCUndefUnusedFonts, XtRBoolean, sizeof(Boolean),
+ Offset(undef_unused_fonts), XtRImmediate, (XtPointer) True},
+ {XtNmaxPendingDeletes, XtCMaxPendingDeletes, XtRCardinal, sizeof(Cardinal),
+ Offset(max_pending_deletes), XtRImmediate,
+ (XtPointer) DEFAULT_MAX_PENDING},
+ {XtNmakeFontsShared, XtCMakeFontsShared, XtRBoolean, sizeof(Boolean),
+ Offset(make_fonts_shared), XtRImmediate, (XtPointer) True},
+ {XtNshowSampler, XtCShowSampler, XtRBoolean, sizeof(Boolean),
+ Offset(show_sampler), XtRImmediate, (XtPointer) False},
+ {XtNshowSamplerButton, XtCShowSamplerButton, XtRBoolean, sizeof(Boolean),
+ Offset(show_sampler_button), XtRImmediate, (XtPointer) True},
+ {XtNtypographicSort, XtCTypographicSort, XtRBoolean, sizeof(Boolean),
+ Offset(typographic_sort), XtRImmediate, (XtPointer) True},
+
+ {XtNokCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
+ Offset(ok_callback), XtRCallback, (XtPointer) NULL},
+ {XtNapplyCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
+ Offset(apply_callback), XtRCallback, (XtPointer) NULL},
+ {XtNresetCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
+ Offset(reset_callback), XtRCallback, (XtPointer) NULL},
+ {XtNcancelCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
+ Offset(cancel_callback), XtRCallback, (XtPointer) NULL},
+ {XtNvalidateCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
+ Offset(validate_callback), XtRCallback, (XtPointer) NULL},
+ {XtNfaceSelectCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
+ Offset(face_select_callback), XtRCallback, (XtPointer) NULL},
+ {XtNcreateSamplerCallback, XtCCallback, XtRCallback,
+ sizeof(XtCallbackList), Offset(create_sampler_callback),
+ XtRCallback, (XtPointer) NULL},
+ {XtNcreateCreatorCallback, XtCCallback, XtRCallback,
+ sizeof(XtCallbackList), Offset(create_creator_callback),
+ XtRCallback, (XtPointer) NULL},
+ {XtNvalueChangedCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
+ Offset(value_changed_callback), XtRCallback, (XtPointer) NULL},
+
+ {XtNpaneChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(pane_child), XtRWidget, (XtPointer) NULL},
+ {XtNpreviewChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(preview_child), XtRWidget, (XtPointer) NULL},
+ {XtNpanelChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(panel_child), XtRWidget, (XtPointer) NULL},
+ {XtNfamilyLabelChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(family_label_child), XtRWidget, (XtPointer) NULL},
+ {XtNfamilyMultipleLabelChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(family_multiple_label_child), XtRWidget, (XtPointer) NULL},
+ {XtNfamilyScrolledListChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(family_scrolled_list_child), XtRWidget, (XtPointer) NULL},
+ {XtNfaceLabelChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(face_label_child), XtRWidget, (XtPointer) NULL},
+ {XtNfaceMultipleLabelChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(face_multiple_label_child), XtRWidget, (XtPointer) NULL},
+ {XtNfaceScrolledListChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(face_scrolled_list_child), XtRWidget, (XtPointer) NULL},
+ {XtNsizeLabelChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(size_label_child), XtRWidget, (XtPointer) NULL},
+ {XtNsizeTextFieldChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(size_text_field_child), XtRWidget, (XtPointer) NULL},
+ {XtNsizeOptionMenuChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(size_option_menu_child), XtRWidget, (XtPointer) NULL},
+ {XtNsizeMultipleLabelChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(size_multiple_label_child), XtRWidget, (XtPointer) NULL},
+ {XtNpreviewButtonChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(preview_button_child), XtRWidget, (XtPointer) NULL},
+ {XtNsamplerButtonChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(sampler_button_child), XtRWidget, (XtPointer) NULL},
+ {XtNseparatorChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(separator_child), XtRWidget, (XtPointer) NULL},
+ {XtNokButtonChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(ok_button_child), XtRWidget, (XtPointer) NULL},
+ {XtNapplyButtonChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(apply_button_child), XtRWidget, (XtPointer) NULL},
+ {XtNresetButtonChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(reset_button_child), XtRWidget, (XtPointer) NULL},
+ {XtNcancelButtonChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(cancel_button_child), XtRWidget, (XtPointer) NULL},
+ {XtNmultipleMasterButtonChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(multiple_master_button_child), XtRWidget, (XtPointer) NULL}
+};
+
+/* Forward declarations */
+
+static Boolean ChangeBlends(Widget w, String base_name, String blend_name, FSBBlendAction action, int *axis_values, float *axis_percents);
+static Boolean DownloadFontName(Widget w, String name);
+static Boolean MatchFontFace(Widget w, String old_face, String new_family, String *new_face);
+static Boolean SetValues(Widget old, Widget req, Widget new, ArgList args, Cardinal *num_args);
+static Boolean Verify(FontSelectionBoxWidget fsb, FSBValidateCallbackRec *cb, String afm, Boolean doIt);
+static String FindAFM(Widget w, String name);
+static String FindFontFile(Widget w, String name);
+static XtGeometryResult GeometryManager(Widget w, XtWidgetGeometry *desired, XtWidgetGeometry *allowed);
+static void ChangeManaged(Widget w);
+static void ClassInitialize(void);
+static void ClassPartInitialize(WidgetClass widget_class);
+static void Destroy(Widget widget);
+static void DisplayFontFamilies(FontSelectionBoxWidget fsb);
+static void FontFamilyFaceBlendToName(Widget w, String family, String face, String blend, String *font_name);
+static void FontFamilyFaceToName(Widget w, String family, String face, String *font_name);
+static void FontNameToFamilyFace(Widget w, String font_name, String *family, String *face);
+static void FontNameToFamilyFaceBlend(Widget w, String font_name, String *family, String *face, String *blend);
+static void FreeFontRec(FontRec *f);
+static void GetBlendInfo(Widget w, String name, int *num_axes_return, int *num_designs_return, String **axis_names_return, float **blend_positions_return, int **blend_map_count_return, int **blend_design_coords_return, float **blend_normalized_coords_return);
+static void GetBlendList(Widget w, String name, int *count_return, String **blend_return, String **font_name_return, float **axis_values_return);
+static void GetFaceList(Widget w, String family, int *count, String **face_list, String **font_list);
+static void GetFamilyList(Widget w, int *count, String **list);
+static void GetTextDimensions(Widget w, String text, String font, double size, double x, double y, float *dx, float *dy, float *left, float *right, float *top, float *bottom);
+static void Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args);
+static void ReadBlends(FontSelectionBoxWidget fsb);
+static void RefreshFontList(Widget w);
+static void Resize(Widget widget);
+static void SetFontFamilyFace(Widget w, String family, String face, Bool family_multiple, Bool face_multiple);
+static void SetFontFamilyFaceBlend(Widget w, String family, String face, String blend, Bool family_multiple, Bool face_multiple);
+static void SetFontName(Widget w, String name, Bool name_multiple);
+static void SetFontSize(Widget w, double size, Bool size_multiple);
+static void SetUpCurrentSelections(FontSelectionBoxWidget fsb);
+static void UndefUnusedFonts(Widget w);
+static void WriteBlends(FontSelectionBoxWidget fsb);
+
+FontSelectionBoxClassRec fontSelectionBoxClassRec = {
+ /* Core class part */
+ {
+ /* superclass */ (WidgetClass) &xmManagerClassRec,
+ /* class_name */ "FontSelectionBox",
+ /* widget_size */ sizeof(FontSelectionBoxRec),
+ /* class_initialize */ ClassInitialize,
+ /* class_part_initialize */ ClassPartInitialize,
+ /* class_inited */ False,
+ /* initialize */ Initialize,
+ /* initialize_hook */ NULL,
+ /* realize */ XtInheritRealize,
+ /* actions */ NULL,
+ /* num_actions */ 0,
+ /* resources */ resources,
+ /* num_resources */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ True,
+ /* compress_exposure */ XtExposeCompressMultiple,
+ /* compress_enterleave */ True,
+ /* visible_interest */ False,
+ /* destroy */ Destroy,
+ /* resize */ Resize,
+ /* expose */ NULL,
+ /* set_values */ SetValues,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* callback offsets */ NULL,
+ /* tm_table */ NULL,
+ /* query_geometry */ XtInheritQueryGeometry,
+ /* display_accelerator */ NULL,
+ /* extension */ NULL,
+ },
+ /* Composite class part */
+ {
+ /* geometry_manager */ GeometryManager,
+ /* change_managed */ ChangeManaged,
+ /* insert_child */ XtInheritInsertChild,
+ /* delete_child */ XtInheritDeleteChild,
+ /* extension */ NULL,
+ },
+ /* Constraint class part */
+ {
+ /* resources */ NULL,
+ /* num_resources */ 0,
+ /* constraint_size */ 0,
+ /* initialize */ NULL,
+ /* destroy */ NULL,
+ /* set_values */ NULL,
+ /* extension */ NULL,
+ },
+ /* Manager class part */
+ {
+ /* translations */ XtInheritTranslations,
+ /* syn_resources */ NULL,
+ /* num_syn_resources */ 0,
+ /* syn_constraint_resources */ NULL,
+ /* num_syn_constraint_resources */ 0,
+ /* parent_process */ XmInheritParentProcess,
+ /* extension */ NULL,
+ },
+ /* FontSelectionBox class part */
+ {
+ /* set_font_name */ SetFontName,
+ /* set_font_family_face */ SetFontFamilyFace,
+ /* set_font_size */ SetFontSize,
+ /* refresh_font_list */ RefreshFontList,
+ /* get_family_list */ GetFamilyList,
+ /* get_face_list */ GetFaceList,
+ /* undef_unused_fonts */ UndefUnusedFonts,
+ /* download_font_name */ DownloadFontName,
+ /* match_font_face */ MatchFontFace,
+ /* font_name_to_family_face */ FontNameToFamilyFace,
+ /* font_family_face_to_name */ FontFamilyFaceToName,
+ /* find_afm */ FindAFM,
+ /* find_font_file */ FindFontFile,
+ /* get_text_dimensions */ GetTextDimensions,
+ /* set_font_family_face_blend */ SetFontFamilyFaceBlend,
+ /* font_name_to_family_face_blend */ FontNameToFamilyFaceBlend,
+ /* font_family_face_blend_to_name */ FontFamilyFaceBlendToName,
+ /* get_blend_list */ GetBlendList,
+ /* get_blend_info */ GetBlendInfo,
+ /* change_blends */ ChangeBlends,
+ /* extension */ NULL,
+ }
+};
+
+WidgetClass fontSelectionBoxWidgetClass =
+ (WidgetClass) &fontSelectionBoxClassRec;
+
+/* ARGSUSED */
+
+static Boolean CvtStringToFloatList(
+ Display *dpy,
+ XrmValuePtr args,
+ Cardinal *num_args,
+ XrmValuePtr from,
+ XrmValuePtr to,
+ XtPointer *data)
+{
+ register int i, count = 1;
+ register char *ch, *start = from->addr;
+ static float *list;
+ char save;
+
+ if (*num_args != 0) { /* Check for correct number */
+ XtAppErrorMsg(XtDisplayToApplicationContext(dpy),
+ "cvtStringToFloatList", "wrongParameters",
+ "XtToolkitError",
+ "String to integer list conversion needs no extra arguments",
+ (String *) NULL, (Cardinal *) NULL);
+ }
+
+ if (to->addr != NULL && to->size < sizeof(int *)) {
+ to->size = sizeof(int *);
+ return False;
+ }
+ if (start == NULL || *start == '\0') list = NULL;
+ else {
+ for (ch = start; *ch != '\0'; ch++) { /* Count floats */
+ if (!isdigit(*ch) && *ch != '.' && *ch != ',') {
+ XtDisplayStringConversionWarning(dpy, from->addr, "FloatList");
+ return False;
+ }
+ if (*ch == ',') count++;
+ }
+ list = (float *) XtCalloc(count+1, sizeof(float));
+
+ for (i = 0; i < count; i++) {
+ for (ch = start; *ch != ',' && *ch != '\0'; ch++) {}
+ save = *ch;
+ *ch = '\0';
+ list[i] = atof(start);
+ *ch = save;
+ start = ch + 1;
+ }
+ }
+ if (to->addr == NULL) to->addr = (caddr_t) &list;
+ else *(float **) to->addr = list;
+ to->size = sizeof(int *);
+ return True;
+}
+
+/* ARGSUSED */
+
+static void FloatListDestructor(
+ XtAppContext app,
+ XrmValuePtr to,
+ XtPointer converter_data,
+ XrmValuePtr args,
+ Cardinal *num_args)
+{
+ float *list = (float *) to->addr;
+
+ if (list == NULL) return;
+ XtFree((XtPointer) list);
+}
+
+XmString _FSBCreateSharedCS(String str, Widget w)
+{
+ XrmValue src, dst;
+ XmString result;
+
+ src.addr = str;
+ src.size = strlen(str);
+
+ dst.addr = (caddr_t) &result;
+ dst.size = sizeof(result);
+
+ if (XtConvertAndStore(w, XtRString, &src, XmRXmString, &dst)) {
+ return result;
+ } else return NULL;
+}
+
+static Boolean ScanFloat(char *src, float *f, char **past)
+{
+ char buf[20], *ch;
+ int countDecimals;
+
+ ch = buf;
+ countDecimals = 0;
+ while (*src == '.' || isdigit(*src)) {
+ if (*src == '.') {
+ if (countDecimals) return False;
+ else countDecimals++;
+ }
+ *ch++ = *src++;
+ }
+ if (ch == buf) return False;
+ *ch++ = '\0';
+ *f = atof(buf);
+ *past = src;
+ return True;
+}
+
+static Boolean ScanInt(char *src, int *i, char **past)
+{
+ char buf[20], *ch;
+
+ ch = buf;
+ while (isdigit(*src)) *ch++ = *src++;
+ if (ch == buf) return False;
+ *ch++ = '\0';
+ *i = atoi(buf);
+ *past = src;
+ return True;
+}
+
+static void ClassInitialize(void)
+{
+ /* Register a converter for string to int list */
+
+ XtSetTypeConverter(XtRString, XtRFloatList,
+ CvtStringToFloatList, (XtConvertArgList) NULL, 0,
+ XtCacheAll | XtCacheRefCount, FloatListDestructor);
+
+ CSempty = UnsharedCS("");
+}
+
+static void ClassPartInitialize(WidgetClass widget_class)
+{
+ register FontSelectionBoxWidgetClass wc =
+ (FontSelectionBoxWidgetClass) widget_class;
+ FontSelectionBoxWidgetClass super =
+ (FontSelectionBoxWidgetClass) wc->core_class.superclass;
+
+ if (wc->fsb_class.set_font_name == InheritSetFontName) {
+ wc->fsb_class.set_font_name = super->fsb_class.set_font_name;
+ }
+ if (wc->fsb_class.set_font_family_face == InheritSetFontFamilyFace) {
+ wc->fsb_class.set_font_family_face =
+ super->fsb_class.set_font_family_face;
+ }
+ if (wc->fsb_class.set_font_size == InheritSetFontSize) {
+ wc->fsb_class.set_font_size = super->fsb_class.set_font_size;
+ }
+ if (wc->fsb_class.refresh_font_list == InheritRefreshFontList) {
+ wc->fsb_class.refresh_font_list = super->fsb_class.refresh_font_list;
+ }
+ if (wc->fsb_class.get_family_list == InheritGetFamilyList) {
+ wc->fsb_class.get_family_list = super->fsb_class.get_family_list;
+ }
+ if (wc->fsb_class.get_face_list == InheritGetFaceList) {
+ wc->fsb_class.get_face_list = super->fsb_class.get_face_list;
+ }
+ if (wc->fsb_class.undef_unused_fonts == InheritUndefUnusedFonts) {
+ wc->fsb_class.undef_unused_fonts = super->fsb_class.undef_unused_fonts;
+ }
+ if (wc->fsb_class.download_font_name == InheritDownloadFontName) {
+ wc->fsb_class.download_font_name = super->fsb_class.download_font_name;
+ }
+ if (wc->fsb_class.match_font_face == InheritMatchFontFace) {
+ wc->fsb_class.match_font_face = super->fsb_class.match_font_face;
+ }
+ if (wc->fsb_class.font_name_to_family_face ==
+ InheritFontNameToFamilyFace) {
+ wc->fsb_class.font_name_to_family_face =
+ super->fsb_class.font_name_to_family_face;
+ }
+ if (wc->fsb_class.font_family_face_to_name ==
+ InheritFontFamilyFaceToName) {
+ wc->fsb_class.font_family_face_to_name =
+ super->fsb_class.font_family_face_to_name;
+ }
+ if (wc->fsb_class.find_afm == InheritFindAFM) {
+ wc->fsb_class.find_afm = super->fsb_class.find_afm;
+ }
+ if (wc->fsb_class.find_font_file == InheritFindFontFile) {
+ wc->fsb_class.find_font_file = super->fsb_class.find_font_file;
+ }
+ if (wc->fsb_class.get_text_dimensions == InheritGetTextDimensions) {
+ wc->fsb_class.get_text_dimensions =
+ super->fsb_class.get_text_dimensions;
+ }
+ if (wc->fsb_class.set_font_family_face_blend ==
+ InheritSetFontFamilyFaceBlend) {
+ wc->fsb_class.set_font_family_face_blend =
+ super->fsb_class.set_font_family_face_blend;
+ }
+ if (wc->fsb_class.font_name_to_family_face_blend ==
+ InheritFontNameToFamilyFaceBlend) {
+ wc->fsb_class.font_name_to_family_face_blend =
+ super->fsb_class.font_name_to_family_face_blend;
+ }
+ if (wc->fsb_class.font_family_face_blend_to_name ==
+ InheritFontFamilyFaceBlendToName) {
+ wc->fsb_class.font_family_face_blend_to_name =
+ super->fsb_class.font_family_face_blend_to_name;
+ }
+ if (wc->fsb_class.get_blend_list == InheritGetBlendList) {
+ wc->fsb_class.get_blend_list =
+ super->fsb_class.get_blend_list;
+ }
+ if (wc->fsb_class.get_blend_info == InheritGetBlendInfo) {
+ wc->fsb_class.get_blend_info =
+ super->fsb_class.get_blend_info;
+ }
+ if (wc->fsb_class.change_blends == InheritChangeBlends) {
+ wc->fsb_class.change_blends =
+ super->fsb_class.change_blends;
+ }
+}
+
+static String bugFamilies[] = {
+ "Berkeley", "CaslonFiveForty", "CaslonThree", "GaramondThree",
+ "Music", "TimesTen", NULL
+};
+
+static String fixedFamilies[] = {
+ "ITC Berkeley Oldstyle", "Caslon 540", "Caslon 3", "Garamond 3",
+ "Sonata", "Times 10", NULL
+};
+
+static String missingFoundries[] = {
+ "Berthold ", "ITC ", "Linotype ", NULL
+};
+
+static int missingFoundryLen[] = {
+ 9, 4, 9, 0
+};
+
+/* I wish we didn't have to do this! */
+
+static void MungeFontNames(
+ String name, String family, String fullname, String weight,
+ String *familyReturn, String *fullnameReturn, String *faceReturn)
+{
+ register char *src, *dst, prev;
+ char buf[256];
+ int digits = 0;
+ int i, diff;
+ static Bool inited = False;
+ static String FetteFrakturDfr, LinotextDfr;
+
+ /* Don't make bugFamilies canonical; we'd have to make the initial
+ family canonical to do anything with it and there's no point in that */
+
+ if (!inited) {
+ for (i = 0; fixedFamilies[i] != NULL; i++) {
+ fixedFamilies[i] = Canonical(fixedFamilies[i]);
+ }
+ FetteFrakturDfr = Canonical("FetteFraktur-Dfr");
+ LinotextDfr = Canonical("Linotext-Dfr");
+ inited = True;
+ }
+
+ /* Copy the fullname into buf, enforcing one space between words.
+ Eliminate leading digits and spaces, ignore asterisks, if the
+ full name ends with 5 digits strip them, and replace periods that
+ aren't followed by a space with a space. If leading digits are
+ followed by " pt " skip that too. */
+
+ dst = buf;
+ prev = ' ';
+ src = fullname;
+ while (isdigit(*src)) src++;
+ while (*src == ' ' || *src == '\t') src++;
+ if (strncmp(src, "pt ", 3) == 0) src += 3;
+ else if (strncmp(src, "pt. ", 4) == 0) src += 4;
+
+ while (*src != '\0') {
+ if (*src == '*') {
+ src++;
+ continue;
+ }
+
+ if (*src == '.') {
+ if (*(src+1) != ' ') {
+ prev = *dst++ = ' ';
+ } else prev = *dst++ = '.';
+ src++;
+ continue;
+ }
+
+ if (isdigit(*src)) digits++;
+ else digits = 0;
+
+ if (isupper(*src)) {
+ if (prev != ' ' && (islower(*(src+1)) || islower(prev))) {
+ *dst++ = ' ';
+ prev = *dst++ = *src++;
+ } else prev = *dst++ = *src++;
+
+ } else if (*src == ' ' || *src == '\t') {
+ if (prev == ' ') {
+ src++;
+ continue;
+ }
+ prev = *dst++ = ' ';
+ src++;
+
+ } else prev = *dst++ = *src++;
+ }
+
+ if (digits == 5) {
+ dst -= 5;
+ }
+ if (dst > buf && *(dst-1) == ' ') dst--;
+
+ *dst = '\0';
+
+ /* Stupid Fette Fraktur */
+
+ if (name == FetteFrakturDfr) {
+ strcat(buf, " Black Dfr");
+ } else if (name == LinotextDfr) {
+ strcat(buf, " Dfr");
+ }
+
+ if (strncmp(fullname, "pt ", 3) == 0) {
+ src = buf + 2;
+ while (*++src != '\0') *(src-3) = *src;
+ *(src-3) = '\0';
+ }
+ *fullnameReturn = XtNewString(buf);
+
+ /* From here on fullname should not be used */
+
+ /* Done with the full name; now onto the family */
+
+ for (i = 0; bugFamilies[i] != NULL; i++) {
+ diff = strcmp(family, bugFamilies[i]);
+ if (diff < 0) break;
+ if (diff == 0) {
+ *familyReturn = fixedFamilies[i];
+ goto FAMILY_DONE;
+ }
+ }
+
+ /* Copy the family into buf, enforcing one space between words */
+
+ dst = buf;
+ prev = ' ';
+ src = family;
+
+ while (*src != '\0') {
+ if (isupper(*src)) {
+ if (prev != ' ' && (islower(*(src+1)) || islower(prev))) {
+ *dst++ = ' ';
+ prev = *dst++ = *src++;
+ } else prev = *dst++ = *src++;
+
+ } else if (*src == ' ' || *src == '\t') {
+ if (prev == ' ') {
+ src++;
+ continue;
+ }
+ prev = *dst++ = ' ';
+ src++;
+
+ } else prev = *dst++ = *src++;
+ }
+
+ if (dst > buf && *(dst-1) == ' ') dst--;
+ *dst = '\0';
+
+ /* Compensate for fonts with foundries in the full name but not the
+ family name by adding to the family name */
+
+ for (i = 0; missingFoundries[i] != NULL; i++) {
+ diff = strncmp(*fullnameReturn, missingFoundries[i],
+ missingFoundryLen[i]);
+ if (diff > 0) continue;
+ if (diff == 0 && strncmp(buf, missingFoundries[i],
+ missingFoundryLen[i] != 0)) {
+ while (dst >= buf) {
+ *(dst+missingFoundryLen[i]) = *dst;
+ dst--;
+ }
+ strncpy(buf, missingFoundries[i], missingFoundryLen[i]);
+ }
+ break;
+ }
+
+ /* From here on dst no longer points to the end of the buffer */
+
+ /* Stupid Helvetica Rounded! */
+
+ if (strncmp(*fullnameReturn, "Helvetica Rounded ", 18) == 0) {
+ strcat(buf, " Rounded");
+ }
+
+ *familyReturn = Canonical(buf);
+
+ /* From here on family should not be used */
+
+FAMILY_DONE:
+
+ /* Now to find the face in all this */
+
+ src = *fullnameReturn;
+ dst = *familyReturn;
+ while (*dst == *src && *dst != '\0') {
+ src++;
+ dst++;
+ }
+ if (*src == ' ') src++;
+
+ if (*src != '\0') *faceReturn = Canonical(src);
+ else if (*weight != '\0') {
+ /* Handle Multiple Master fonts */
+ if (strcmp(weight, "All") == 0) *faceReturn = Canonical("Roman");
+ else {
+ if (islower(weight[0])) weight[0] = toupper(weight[0]);
+ *faceReturn = Canonical(weight);
+ }
+ } else *faceReturn = Canonical("Medium");
+}
+
+static String strip[] = {
+ "Adobe ", "Bauer ", "Berthold ", "ITC ", "Linotype ",
+ "New ", "Simoncini ", "Stempel ", NULL};
+
+static int striplen[] = {6, 6, 9, 4, 9, 4, 10, 8, 0};
+
+#define STEMPELINDEX 7
+
+static Boolean CreateSortKey(String family, String key)
+{
+ char newkey[256];
+ int len = strlen(family);
+ register int i, diff;
+
+ if (family[len-2] == 'P' && family[len-1] == 'i') {
+ key[0] = 'P';
+ key[1] = 'i';
+ key[2] = ' ';
+ strcpy(key+3, family);
+ key[len] = '\0';
+ return True;
+ }
+
+ for (i = 0; strip[i] != NULL; i++) {
+ diff = strncmp(family, strip[i], striplen[i]);
+ if (diff < 0) break;
+ if (diff == 0) {
+ if (i == STEMPELINDEX) {
+ if (strcmp(family, "Stempel Schneidler") == 0) break;
+ }
+ strcpy(key, family + striplen[i]);
+ key[len - striplen[i]] = ' ';
+ strcpy(key + len - striplen[i] + 1, strip[i]);
+ key[len] = '\0';
+ if (CreateSortKey(key, newkey)) strcpy(key, newkey);
+ return True;
+ }
+ }
+ strcpy(key, family);
+ return False;
+}
+
+#define SKIP_SPACE(buf) while (*buf == ' ' || *buf == '\t') buf++;
+
+static int CountAxes(char *buf)
+{
+ int count = 0;
+
+ while (*buf != '\0') {
+ SKIP_SPACE(buf)
+ if (*buf != '/') return 0;
+ buf++;
+ count++;
+ if (*buf == ' ' || *buf == '\t' || *buf == '\0') return 0;
+ while (*buf != ' ' && *buf != '\t' && *buf != '\0') buf++;
+ }
+ return count;
+}
+
+static Boolean ParseBlendPositions(
+ char *buf,
+ float *blendPos,
+ int *axes, int *designs)
+{
+ int i, j = 0;
+ float f;
+
+ *designs = 0;
+
+ while (*buf != '\0') {
+ SKIP_SPACE(buf)
+ if (*buf++ != '[') return True;
+
+ /* Now there should be *axes positive floats, separated by space */
+ SKIP_SPACE(buf)
+ for (i = 0; i < *axes; i++) {
+ if (!ScanFloat(buf, &f, &buf)) return True;
+ blendPos[j++] = f;
+ SKIP_SPACE(buf)
+ }
+ if (*buf++ != ']') return True;
+ (*designs)++;
+ }
+ return False;
+}
+
+static Boolean ParseBlendMap(
+ char *buf,
+ int *breakCount,
+ int *blendBreak,
+ float *blendBreakValue,
+ int *axes)
+{
+ int i, j = 0;
+ int n;
+ float f;
+
+ /* OK. What we expect to see here is *axes arrays. Each one contains at
+ least 2 and no more than 12 subarrays, each of which contains 2 values,
+ an int and a float */
+
+ for (i = 0; i < *axes; i++) {
+
+ breakCount[i] = 0;
+
+ SKIP_SPACE(buf)
+ if (*buf++ != '[') return True;
+ SKIP_SPACE(buf)
+
+ while (*buf == '[') {
+ buf++;
+ SKIP_SPACE(buf)
+ /* Now there should be an integer */
+ if (!ScanInt(buf, &n, &buf)) return True;
+ blendBreak[j] = n;
+
+ SKIP_SPACE(buf)
+
+ /* Now there should be a float */
+ if (!ScanFloat(buf, &f, &buf)) return True;
+ blendBreakValue[j++] = f;
+ SKIP_SPACE(buf)
+
+ /* Nothing more in the array */
+ if (*buf++ != ']') return True;
+ SKIP_SPACE(buf)
+
+ breakCount[i]++;
+ if (breakCount[i] == 12 && *buf != ']') return True;
+ }
+ if (*buf++ != ']') return True;
+ }
+ SKIP_SPACE(buf)
+ if (*buf != '\0') return True;
+ return False;
+}
+
+static Boolean ParseAxisNames(
+ int axes,
+ char *buf,
+ char *names[])
+{
+ int i = 0;
+
+ /* We expect to see axes names, each optionally preceded with a / and
+ separated by space */
+
+ while (*buf != '\0') {
+ SKIP_SPACE(buf)
+ if (*buf == '/') buf++;
+ names[i] = buf;
+ while (*buf != ' ' && *buf != '\t' && *buf != '\0') buf++;
+ if (buf != names[i]) i++;
+ if (*buf != '\0') *buf++ = '\0';
+ if (i >= axes) return True;
+ }
+ return False;
+}
+#undef SKIP_SPACE
+
+static void GetPSFontInfo(
+ FontSelectionBoxWidget fsb,
+ char *name,
+ int *axes,
+ int *designs,
+ char *axisNames,
+ float *blendPos,
+ int *breakCount,
+ int *blendBreak,
+ float *blendBreakValue)
+{
+ int entries;
+ char **names, **data;
+
+ entries = ListPSResourceFiles(fsb->fsb.resource_path_override,
+ fsb->fsb.default_resource_path,
+ "FontAxes", name,
+ &names, &data);
+ if (entries < 1) {
+ *axes = 0;
+ return;
+ }
+ *axes = CountAxes(data[0]);
+ if (*axes == 0) return;
+ strcpy(axisNames, data[0]);
+
+ entries = ListPSResourceFiles(fsb->fsb.resource_path_override,
+ fsb->fsb.default_resource_path,
+ "FontBlendMap", name,
+ &names, &data);
+ if (entries < 1) {
+ *axes = 0;
+ return;
+ }
+ if (ParseBlendMap(data[0], breakCount,
+ blendBreak, blendBreakValue, axes)) {
+ *axes = 0;
+ return;
+ }
+
+ entries = ListPSResourceFiles(fsb->fsb.resource_path_override,
+ fsb->fsb.default_resource_path,
+ "FontBlendPositions", name,
+ &names, &data);
+ if (entries < 1) {
+ *axes = 0;
+ return;
+ }
+ if (ParseBlendPositions(data[0], blendPos, axes, designs)) {
+ *axes = 0;
+ return;
+ }
+}
+
+static void AddFontRecord(
+ FontSelectionBoxWidget fsb,
+ int serverNum,
+ String name, String family, String fullname, String weight,
+ Boolean resident)
+{
+ FontFamilyRec *ff;
+ FontRec *f;
+ String familyReturn, fullnameReturn, faceReturn;
+ char axisNameBuf[256];
+ char *axisName[MAX_AXES];
+ int blendedFont, undefineIt, brokenFont;
+ int axes, designs, breakCount[MAX_AXES],
+ blendBreak[12 * MAX_AXES];
+ float blendBreakValue[12 * MAX_AXES], blendPos[MAX_AXES * MAX_BLENDS];
+ char key[256];
+ int i, j, k, n;
+
+ name = Canonical(name);
+
+ /* First see if it's there already */
+
+ for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
+ for (f = ff->fonts; f != NULL; f = f->next) {
+ if (f->font_name == name) {
+ if (!f->resident && resident) f->resident = True;
+ return;
+ }
+ }
+ }
+
+ /* We believe that names gotten from PS resource files have been
+ pre-munged, so no need to do it again */
+
+ if (resident) {
+ /* Have to get the info from the server */
+ _DPSFGetFontInfo(fsb->fsb.context, serverNum, fsb->fsb.old_server,
+ family, fullname,
+ weight, &blendedFont, &undefineIt, &brokenFont);
+
+ if (brokenFont) return;
+
+ /* Deal with fonts that don't have useful information */
+
+ if (family[0] == '\0') {
+ if (fullname[0] == '\0') {
+ strcpy(family, name);
+ strcpy(fullname, name);
+ } else strcpy(family, fullname);
+ } else if (fullname[0] == '\0') strcpy(fullname, family);
+
+ MungeFontNames(name, family, fullname, weight,
+ &familyReturn, &fullnameReturn, &faceReturn);
+ if (blendedFont) {
+ _DPSFGetBlendedFontInfo(fsb->fsb.context, serverNum,
+ undefineIt, fsb->fsb.old_server,
+ &axes, &designs, axisNameBuf,
+ blendPos, breakCount, blendBreak,
+ blendBreakValue, &brokenFont);
+ if (brokenFont) axes = 0;
+ } else axes = 0;
+
+ } else {
+ familyReturn = Canonical(family);
+ fullnameReturn = XtNewString(fullname);
+ faceReturn = Canonical(weight);
+ GetPSFontInfo(fsb, name, &axes, &designs, axisNameBuf, blendPos,
+ breakCount, blendBreak, blendBreakValue);
+ }
+
+ /* We didn't get an exact match, go for family match */
+
+ for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
+ if (ff->family_name == familyReturn) break;
+ }
+
+ if (ff == NULL) {
+ ff = (FontFamilyRec *) XtMalloc(sizeof(FontFamilyRec));
+ ff->next = fsb->fsb.known_families;
+ ff->family_name = familyReturn;
+ ff->fonts = NULL;
+ ff->font_count = 0;
+ ff->blend_count = 0;
+ if (fsb->fsb.typographic_sort) {
+ (void) CreateSortKey(familyReturn, key);
+ ff->sort_key = XtNewString(key);
+ } else ff->sort_key = ff->family_name;
+ fsb->fsb.known_families = ff;
+ fsb->fsb.family_count++;
+ }
+
+ f = (FontRec *) XtMalloc(sizeof(FontRec));
+ f->next = ff->fonts;
+ f->font_name = name;
+ f->full_name = fullnameReturn;
+ f->resident = resident;
+ f->temp_resident = False;
+ f->in_font_creator = False;
+ f->pending_delete_next = NULL;
+ f->face_name = faceReturn;
+ f->CS_face_name = CS(f->face_name, (Widget) fsb);
+ f->blend_count = 0;
+
+ if (axes != 0 && ParseAxisNames(axes, axisNameBuf, axisName)) {
+ BlendDataRec *b;
+
+ f->blend_data = b = XtNew(BlendDataRec);
+ b->num_axes = axes;
+ b->num_designs = designs;
+ k = 0;
+
+ for (i = 0; i < axes; i++) {
+ b->internal_points[i] = breakCount[i] - 2;
+ if (b->internal_points[i] <= 0) {
+ b->internal_break[i] = NULL;
+ b->internal_value[i] = NULL;
+ b->internal_points[i] = 0;
+ } else {
+ b->internal_break[i] = (int *)
+ XtMalloc(b->internal_points[i] * sizeof(int));
+ b->internal_value[i] = (float *)
+ XtMalloc(b->internal_points[i] * sizeof(float));
+ }
+
+ n = 0;
+ for (j = 0; j < breakCount[i]; j++) {
+ if (blendBreakValue[k] == 0.0) b->min[i] = blendBreak[k];
+ else if (blendBreakValue[k] == 1.0) b->max[i] = blendBreak[k];
+ else {
+ b->internal_break[i][n] = blendBreak[k];
+ b->internal_value[i][n++] = blendBreakValue[k];
+ }
+ k++;
+ }
+ b->name[i] = Canonical(axisName[i]);
+ }
+
+ b->design_positions =
+ (float *) XtMalloc(axes * designs * sizeof(float));
+ for (i = 0; i < axes * designs; i++) {
+ b->design_positions[i] = blendPos[i];
+ }
+ b->blends = NULL;
+ } else f->blend_data = NULL;
+
+ ff->fonts = f;
+ ff->font_count++;
+}
+
+static void SortFontNames(FontFamilyRec *ff)
+{
+ FontRec *f, *highest, **prev, **highestPrev;
+ FontRec *newFontList = NULL;
+
+ while (ff->fonts != NULL) {
+ prev = highestPrev = &ff->fonts;
+ highest = ff->fonts;
+
+ for (f = ff->fonts->next; f != NULL; f = f->next) {
+ prev = &(*prev)->next;
+ if (strcmp(f->face_name, highest->face_name) > 0) {
+ highest = f;
+ highestPrev = prev;
+ }
+ }
+
+ *highestPrev = highest->next;
+ highest->next = newFontList;
+ newFontList = highest;
+ }
+ ff->fonts = newFontList;
+}
+
+static void SortFontFamilies(FontSelectionBoxWidget fsb)
+{
+ FontFamilyRec *ff, *highest, **prev, **highestPrev;
+ FontFamilyRec *newFamilyList = NULL;
+
+ while (fsb->fsb.known_families != NULL) {
+ prev = highestPrev = &fsb->fsb.known_families;
+ highest = fsb->fsb.known_families;
+
+ for (ff = fsb->fsb.known_families->next; ff != NULL; ff = ff->next) {
+ prev = &(*prev)->next;
+ if (strcmp(ff->sort_key, highest->sort_key) > 0) {
+ highest = ff;
+ highestPrev = prev;
+ }
+ }
+
+ *highestPrev = highest->next;
+ highest->next = newFamilyList;
+ newFamilyList = highest;
+ SortFontNames(highest);
+ if (fsb->fsb.typographic_sort) XtFree(highest->sort_key);
+ highest->sort_key = NULL;
+ }
+ fsb->fsb.known_families = newFamilyList;
+}
+
+static void AddFamily(
+ FontSelectionBoxWidget fsb,
+ char *family, char *fonts, char *weight, char *fullname, char *name)
+{
+ int j;
+ char *ch;
+
+ ch = fonts;
+ while (*ch != '\0') {
+ j = 0;
+ while (1) {
+ if (*ch == '\\' && (*(ch+1) == '\\' || *(ch+1) == ',')) {
+ ch++;
+ weight[j++] = *ch++;
+ } else if (*ch == '\0' || *ch == ',') {
+ weight[j] = '\0';
+ break;
+ } else weight[j++] = *ch++;
+ }
+ if (*ch == ',') {
+ j = 0;
+ ch++;
+ while (1) {
+ if (*ch == '\\' && (*(ch+1) == '\\' || *(ch+1) == ',')) {
+ ch++;
+ name[j++] = *ch++;
+ } else if (*ch == '\0' || *ch == ',') {
+ name[j] = '\0';
+ break;
+ } else name[j++] = *ch++;
+ }
+ strcpy(fullname, family);
+ strcat(fullname, " ");
+ strcat(fullname, weight);
+ AddFontRecord(fsb, 0, name, family, fullname, weight, False);
+ if (*ch == ',') ch++;
+ }
+ }
+}
+
+static void GetFontNames(FontSelectionBoxWidget fsb)
+{
+ int i;
+ char name[256], family[256], fullname[256], weight[256];
+ char *buffer, *ch, *start;
+ int fontCount, totalLength;
+ char **loadableFamilies = NULL, **loadableFamilyFonts = NULL;
+
+ fsb->fsb.family_count = 0;
+
+ fontCount = ListPSResourceFiles(fsb->fsb.resource_path_override,
+ fsb->fsb.default_resource_path,
+ PSResFontFamily, NULL,
+ &loadableFamilies, &loadableFamilyFonts);
+ for (i = 0; i < fontCount; i++) {
+ AddFamily(fsb, loadableFamilies[i], loadableFamilyFonts[i],
+ weight, fullname, name);
+ }
+
+ XtFree((XtPointer) loadableFamilies);
+ XtFree((XtPointer) loadableFamilyFonts);
+ FreePSResourceStorage(False);
+
+ if (fsb->fsb.get_server_fonts) {
+ _DPSFEnumFonts(fsb->fsb.context, &fontCount, &totalLength);
+
+ buffer = XtMalloc(totalLength);
+ _DPSFGetAllFontNames(fsb->fsb.context, fontCount, totalLength, buffer);
+ ch = start = buffer;
+ for (i = 0; i < fontCount; i++) {
+ while (*ch != ' ') ch++;
+ *ch = '\0';
+ AddFontRecord(fsb, i, start, family, fullname, weight, True);
+ start = ch+1;
+ }
+ XtFree(buffer);
+ }
+
+ _DPSFFreeFontInfo(fsb->fsb.context);
+ SortFontFamilies(fsb);
+ ReadBlends(fsb);
+}
+
+static void SensitizeReset(FontSelectionBoxWidget fsb)
+{
+ XtSetSensitive(fsb->fsb.reset_button_child, True);
+}
+
+static void DesensitizeReset(FontSelectionBoxWidget fsb)
+{
+ XtSetSensitive(fsb->fsb.reset_button_child, False);
+}
+
+static void ManageFamilyMultiple(FontSelectionBoxWidget fsb)
+{
+ XtManageChild(fsb->fsb.family_multiple_label_child);
+
+ XtVaSetValues(XtParent(fsb->fsb.family_scrolled_list_child),
+ XmNtopWidget, fsb->fsb.family_multiple_label_child, NULL);
+}
+
+static void ManageFaceMultiple(FontSelectionBoxWidget fsb)
+{
+ XtManageChild(fsb->fsb.face_multiple_label_child);
+
+ XtVaSetValues(XtParent(fsb->fsb.face_scrolled_list_child),
+ XmNtopWidget, fsb->fsb.face_multiple_label_child, NULL);
+}
+
+static void ManageMultipleMaster(FontSelectionBoxWidget fsb)
+{
+ XtManageChild(fsb->fsb.multiple_master_button_child);
+
+ XtVaSetValues(XtParent(fsb->fsb.face_scrolled_list_child),
+ XmNbottomWidget, fsb->fsb.multiple_master_button_child,
+ NULL);
+}
+
+static void ManageSizeMultiple(FontSelectionBoxWidget fsb)
+{
+ XtManageChild(fsb->fsb.size_multiple_label_child);
+}
+
+static void UnmanageFamilyMultiple(FontSelectionBoxWidget fsb)
+{
+ XtVaSetValues(XtParent(fsb->fsb.family_scrolled_list_child),
+ XmNtopWidget, fsb->fsb.family_label_child, NULL);
+
+ XtUnmanageChild(fsb->fsb.family_multiple_label_child);
+}
+
+static void UnmanageFaceMultiple(FontSelectionBoxWidget fsb)
+{
+ XtVaSetValues(XtParent(fsb->fsb.face_scrolled_list_child),
+ XmNtopWidget, fsb->fsb.face_label_child, NULL);
+
+ XtUnmanageChild(fsb->fsb.face_multiple_label_child);
+}
+
+static void UnmanageMultipleMaster(FontSelectionBoxWidget fsb)
+{
+ XtUnmanageChild(fsb->fsb.multiple_master_button_child);
+
+ XtVaSetValues(XtParent(fsb->fsb.face_scrolled_list_child),
+ XmNbottomWidget, fsb->fsb.size_text_field_child, NULL);
+}
+
+static void UnmanageSizeMultiple(FontSelectionBoxWidget fsb)
+{
+ XtUnmanageChild(fsb->fsb.size_multiple_label_child);
+}
+
+/* Callbacks for subwidgets */
+
+static Boolean DownloadFont(
+ FontSelectionBoxWidget fsb,
+ String name,
+ DPSContext ctxt,
+ Boolean make_shared)
+{
+ int count;
+ char **names, **files;
+ FILE *f;
+#define BUFLEN 256
+ char buf[BUFLEN];
+ static char eobuf[] = "\n$Adobe$DPS$Lib$Dict /downloadSuccess true put\n\
+stop\n\
+Magic end of data line )))))))))) 99#2 2#99 <xyz> // 7gsad,32h4ghNmndFgj2\n";
+ int currentShared, ok;
+
+ /* Assume context is correct */
+
+ count = ListPSResourceFiles(fsb->fsb.resource_path_override,
+ fsb->fsb.default_resource_path,
+ PSResFontOutline, name,
+ &names, &files);
+ if (count == 0) return False;
+
+ f = fopen(files[0], "r");
+ if (f == NULL) return False;
+
+ /* A bug in 1006.9 and earlier servers prevents the more robust
+ downloading method from working reliably. */
+
+ if (fsb->fsb.old_server) {
+ DPSPrintf(ctxt, "\ncurrentshared %s setshared\n",
+ (make_shared ? "true" : "false"));
+ while (fgets(buf, BUFLEN, f) != NULL) {
+ DPSWritePostScript(ctxt, buf, strlen(buf));
+ }
+ DPSWritePostScript(ctxt, "\nsetshared\n", 11);
+ ok = True;
+
+ } else {
+ _DPSFPrepareToDownload(ctxt, make_shared, &currentShared);
+ DPSWriteData(ctxt, "\nexec\n", 6);
+
+ while (fgets(buf, BUFLEN, f) != NULL) {
+ DPSWriteData(ctxt, buf, strlen(buf));
+ }
+
+ /* This marks the end of the data stream */
+ DPSWriteData(ctxt, eobuf, strlen(eobuf));
+
+ /* Check the results of the download by getting the error status */
+ _DPSFFinishDownload(ctxt, currentShared, &ok);
+ }
+
+ fclose (f);
+ free(names);
+ free(files);
+ return ok;
+
+#undef BUFLEN
+}
+
+static void UndefSomeUnusedFonts(
+ FontSelectionBoxWidget fsb,
+ Boolean all)
+{
+ FontRec *f, *nextf, **start;
+ int i;
+
+ if (!all
+ && (Cardinal)fsb->fsb.pending_delete_count < fsb->fsb.max_pending_deletes) {
+ return;
+ }
+
+ if (all) start = &fsb->fsb.pending_delete_font;
+ else {
+ /* Skip to the end of the ones we're keeping */
+ f = fsb->fsb.pending_delete_font;
+ for (i = 1; f != NULL && (Cardinal)i < fsb->fsb.max_pending_deletes; i++) {
+ f = f->pending_delete_next;
+ }
+ if (f == NULL) return;
+ start = &f->pending_delete_next;
+ }
+
+ for (f = *start; f != NULL; f = nextf) {
+ nextf = f->pending_delete_next;
+ if (f == fsb->fsb.currently_previewed) {
+ start = &f->pending_delete_next;
+ continue;
+ }
+ *start = nextf;
+ if (!f->resident && !f->in_font_creator) {
+ _DPSFUndefineFont(fsb->fsb.context, f->font_name,
+ fsb->fsb.old_server);
+ }
+ f->temp_resident = False;
+ fsb->fsb.pending_delete_count--;
+ f->pending_delete_next = NULL;
+ }
+}
+
+static void UndefUnusedFonts(Widget w)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
+
+ UndefSomeUnusedFonts(fsb, True);
+}
+
+Boolean _FSBDownloadFontIfNecessary(
+ FontRec *f,
+ FontSelectionBoxWidget fsb)
+{
+ Boolean shared;
+
+ if (!f->resident && !f->temp_resident) {
+
+ shared = fsb->fsb.make_fonts_shared && !fsb->fsb.undef_unused_fonts;
+ if (!fsb->fsb.get_server_fonts) {
+ int resident;
+ /* This font might already be there, so check before downloading */
+ _DPSFIsFontResident(fsb->fsb.context, f->font_name, &resident);
+ if (resident) {
+ f->resident = True;
+ return True;
+ }
+ }
+ if (!DownloadFont(fsb, f->font_name, fsb->fsb.context, shared)) {
+ _FSBFlushFont(fsb, f);
+ return False;
+ }
+ if (shared) f->resident = True;
+ else f->temp_resident = True;
+
+ if (f->pending_delete_next == NULL && fsb->fsb.undef_unused_fonts) {
+ f->pending_delete_next = fsb->fsb.pending_delete_font;
+ fsb->fsb.pending_delete_font = f;
+ fsb->fsb.pending_delete_count++;
+ UndefSomeUnusedFonts(fsb, False);
+ }
+ }
+ return True;
+}
+
+static void DoPreview(
+ FontSelectionBoxWidget fsb,
+ Boolean override)
+{
+ int i, n;
+ int *selectList, selectCount;
+ float size;
+ FontFamilyRec *ff = fsb->fsb.known_families;
+ FontRec *f;
+ BlendRec *b;
+ char *chSize, *fontName;
+ Dimension height;
+ Cardinal depth;
+ int bogusFont;
+
+ if (!XtIsRealized(fsb)) return;
+
+ XtVaGetValues(fsb->fsb.preview_child, XmNheight, &height,
+ XmNdepth, &depth, NULL);
+
+ if (fsb->fsb.gstate == 0) {
+ XDPSSetContextParameters(fsb->fsb.context, XtScreen(fsb), depth,
+ XtWindow(fsb->fsb.preview_child), height,
+ (XDPSStandardColormap *) NULL,
+ (XDPSStandardColormap *) NULL,
+ XDPSContextScreenDepth | XDPSContextDrawable |
+ XDPSContextRGBMap | XDPSContextGrayMap);
+ XDPSCaptureContextGState(fsb->fsb.context, &fsb->fsb.gstate);
+ } else XDPSSetContextGState(fsb->fsb.context, fsb->fsb.gstate);
+
+ _DPSFClearWindow(fsb->fsb.context);
+
+ if (override) {
+ if (fsb->fsb.current_family_multiple ||
+ fsb->fsb.current_face_multiple ||
+ fsb->fsb.current_size_multiple) return;
+ f = fsb->fsb.currently_previewed;
+ size = fsb->fsb.currently_previewed_size;
+ b = fsb->fsb.currently_previewed_blend;
+ }
+
+ if (!override || f == NULL || size == 0.0) {
+ if (!XmListGetSelectedPos(fsb->fsb.family_scrolled_list_child,
+ &selectList, &selectCount)) return;
+ if (selectCount == 0 ||
+ *selectList < 1 || *selectList > fsb->fsb.family_count) return;
+
+ for (i = 1; i < *selectList; i++) ff = ff->next;
+
+ XtFree((XtPointer) selectList);
+
+ if (!XmListGetSelectedPos(fsb->fsb.face_scrolled_list_child,
+ &selectList, &selectCount)) return;
+ if (selectCount == 0 ||
+ *selectList < 1 ||
+ *selectList > ff->font_count + ff->blend_count) return;
+
+ f = ff->fonts;
+ n = 0;
+ while (1) {
+ n += f->blend_count + 1;
+ if (n >= *selectList) {
+ n -= f->blend_count;
+ if (n == *selectList) b = NULL;
+ else for (b = f->blend_data->blends;
+ n < *selectList - 1; b = b->next) n++;
+ break;
+ }
+ f = f->next;
+ }
+
+ XtFree((XtPointer) selectList);
+
+ XtVaGetValues(fsb->fsb.size_text_field_child,
+ XmNvalue, &chSize, NULL);
+
+ if (chSize == NULL || *chSize == '\0') return;
+ size = atof(chSize);
+ }
+
+ if (size <= 0.0) return;
+
+ fsb->fsb.currently_previewed = f;
+ fsb->fsb.currently_previewed_blend = b;
+ fsb->fsb.currently_previewed_size = size;
+
+ if (!_FSBDownloadFontIfNecessary(f, fsb)) return;
+
+ if (b == NULL) fontName = f->font_name;
+ else fontName = b->font_name;
+
+ if (fsb->fsb.preview_string == NULL) {
+ _DPSFPreviewString(fsb->fsb.context, fontName, size,
+ f->full_name, height, &bogusFont);
+ } else _DPSFPreviewString(fsb->fsb.context, fontName, size,
+ fsb->fsb.preview_string, height, &bogusFont);
+ if (bogusFont) {
+ _FSBBogusFont(fsb, f);
+ }
+}
+
+static void DoValueChangedCallback(FontSelectionBoxWidget fsb)
+{
+ String afm = NULL;
+ FSBValidateCallbackRec cb;
+
+ if (fsb->fsb.get_afm) {
+ if (fsb->fsb.currently_selected_face == NULL) afm = NULL;
+ else afm = FindAFM((Widget) fsb,
+ fsb->fsb.currently_selected_face->font_name);
+ }
+
+ (void) Verify(fsb, &cb, afm, False);
+ cb.reason = FSBValueChanged;
+
+ XtCallCallbackList((Widget) fsb, fsb->fsb.value_changed_callback, &cb);
+}
+
+static void ValueChanged(FontSelectionBoxWidget fsb)
+{
+ if (fsb->fsb.auto_preview) DoPreview(fsb, False);
+ DoValueChangedCallback(fsb);
+}
+
+/* ARGSUSED */
+
+static void PreviewText(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
+ XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) callData;
+
+ if (!fsb->fsb.preview_fixed) {
+ XSetWindowAttributes att;
+ att.bit_gravity = ForgetGravity;
+ XChangeWindowAttributes(XtDisplay(fsb),
+ XtWindow(fsb->fsb.preview_child),
+ CWBitGravity, &att);
+ fsb->fsb.preview_fixed = True;
+ }
+
+ if (cb != NULL && cb->event->type == Expose &&
+ cb->event->xexpose.count != 0) return;
+
+ DoPreview(fsb, True);
+}
+
+/* ARGSUSED */
+
+static void PreviewCallback(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
+
+ DoPreview(fsb, False);
+}
+
+/* ARGSUSED */
+
+static void DismissSamplerCallback(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
+
+ fsb->fsb.show_sampler = False;
+}
+
+static void ShowSampler(FontSelectionBoxWidget fsb)
+{
+ int i;
+ Arg args[2];
+ Widget s;
+
+ if (fsb->fsb.sampler == NULL) {
+ FSBCreateSamplerCallbackRec cs;
+
+ cs.sampler_shell = NULL;
+
+ XtCallCallbackList((Widget) fsb, fsb->fsb.create_sampler_callback,
+ (XtPointer) &cs);
+
+ if (cs.sampler_shell == NULL || cs.sampler == NULL) {
+ fsb->fsb.sampler =
+ XtCreatePopupShell("samplerShell",
+ transientShellWidgetClass,
+ (Widget) fsb, (ArgList) NULL, 0);
+ i = 0;
+ XtSetArg(args[i], XtNfontSelectionBox, fsb); i++;
+ s = XtCreateManagedWidget("sampler", fontSamplerWidgetClass,
+ fsb->fsb.sampler, args, i);
+ XtAddCallback(s, XtNdismissCallback,
+ DismissSamplerCallback, (XtPointer) fsb);
+ } else {
+ fsb->fsb.sampler = cs.sampler_shell;
+ XtAddCallback(cs.sampler, XtNdismissCallback,
+ DismissSamplerCallback, (XtPointer) fsb);
+ }
+ }
+ XtPopup(fsb->fsb.sampler, XtGrabNone);
+ XRaiseWindow(XtDisplay(fsb->fsb.sampler), XtWindow(fsb->fsb.sampler));
+ fsb->fsb.show_sampler = True;
+}
+
+static void ShowCreator(FontSelectionBoxWidget fsb)
+{
+ int i;
+ Arg args[2];
+ FSBCreateCreatorCallbackRec cc;
+
+ if (fsb->fsb.creator == NULL) {
+
+ cc.creator_shell = NULL;
+
+ XtCallCallbackList((Widget) fsb, fsb->fsb.create_creator_callback,
+ (XtPointer) &cc);
+
+ if (cc.creator_shell == NULL || cc.creator == NULL) {
+ cc.creator_shell =
+ XtCreatePopupShell("creatorShell",
+ transientShellWidgetClass,
+ (Widget) fsb, (ArgList) NULL, 0);
+ i = 0;
+ XtSetArg(args[i], XtNfontSelectionBox, fsb); i++;
+ cc.creator =
+ XtCreateManagedWidget("creator", fontCreatorWidgetClass,
+ cc.creator_shell, args, i);
+ }
+ fsb->fsb.creator_shell = cc.creator_shell;
+ fsb->fsb.creator = cc.creator;
+ }
+
+ XtPopup(fsb->fsb.creator_shell, XtGrabNone);
+ XRaiseWindow(XtDisplay(fsb->fsb.creator_shell),
+ XtWindow(fsb->fsb.creator_shell));
+
+ _FSBSetCreatorFamily(fsb->fsb.creator, fsb->fsb.currently_selected_family);
+}
+
+/* ARGSUSED */
+
+static void ShowCreatorCallback(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
+
+ ShowCreator(fsb);
+}
+
+/* ARGSUSED */
+
+static void ShowSamplerCallback(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
+
+ ShowSampler(fsb);
+}
+
+/* ARGSUSED */
+
+static void PreviewDoubleClick(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
+
+ DoPreview(fsb, False);
+}
+
+/* ARGSUSED */
+
+static void ResizePreview(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ Dimension height;
+ Cardinal depth;
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
+
+ if (!XtIsRealized(widget) || fsb->fsb.gstate == 0) return;
+
+ XtVaGetValues(widget, XmNheight, &height, XmNdepth, &depth, NULL);
+
+ XDPSSetContextGState(fsb->fsb.context, fsb->fsb.gstate);
+
+ XDPSSetContextParameters(fsb->fsb.context, XtScreen(widget), depth,
+ XtWindow(widget), height,
+ (XDPSStandardColormap *) NULL,
+ (XDPSStandardColormap *) NULL,
+ XDPSContextScreenDepth | XDPSContextDrawable);
+
+ _DPSFReclip(fsb->fsb.context);
+
+ XDPSUpdateContextGState(fsb->fsb.context, fsb->fsb.gstate);
+}
+
+static String FindAFMRecursive(
+ Widget w,
+ String name,
+ Boolean recur)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
+ int count;
+ char **names, **files;
+ String ret, ch;
+
+ if (name == NULL) return NULL;
+
+ count = ListPSResourceFiles(fsb->fsb.resource_path_override,
+ fsb->fsb.default_resource_path,
+ PSResFontAFM,
+ name,
+ &names, &files);
+
+ if (count == 0 && recur) {
+ for (ch = name; *ch != '_' && *ch != '\0'; ch++) {}
+ if (*ch == '\0') return NULL;
+ *ch = '\0';
+ ret = FindAFMRecursive(w, name, False);
+ *ch = '_';
+ return ret;
+ }
+
+ if (count == 0) return NULL;
+ ret = files[0];
+ free(names);
+ free(files);
+ return ret;
+}
+
+static String FindAFM(Widget w, String name)
+{
+ return FindAFMRecursive(w, name, True);
+}
+
+static String FindFontFileRecursive(
+ Widget w,
+ String name,
+ Boolean recur)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
+ int count;
+ char **names, **files;
+ String ret, ch;
+
+ if (name == NULL) return NULL;
+
+ count = ListPSResourceFiles(fsb->fsb.resource_path_override,
+ fsb->fsb.default_resource_path,
+ PSResFontOutline,
+ name,
+ &names, &files);
+
+ if (count == 0 && recur) {
+ for (ch = name; *ch != '_' && *ch != '\0'; ch++) {}
+ if (*ch == '\0') return NULL;
+ *ch = '\0';
+ ret = FindFontFileRecursive(w, name, False);
+ *ch = '_';
+ return ret;
+ }
+
+ if (count == 0) return NULL;
+ ret = files[0];
+ free(names);
+ free(files);
+ return ret;
+}
+
+static String FindFontFile(Widget w, String name)
+{
+ return FindFontFileRecursive(w, name, True);
+}
+
+static Boolean Verify(
+ FontSelectionBoxWidget fsb,
+ FSBValidateCallbackRec *cb,
+ String afm,
+ Boolean doIt)
+{
+ char *chSize;
+ int i;
+
+ if (fsb->fsb.current_family_multiple) {
+ cb->family = NULL;
+ cb->family_selection = FSBMultiple;
+ } else if (fsb->fsb.currently_selected_family == NULL) {
+ cb->family = NULL;
+ cb->family_selection = FSBNone;
+ } else {
+ cb->family = fsb->fsb.currently_selected_family->family_name;
+ cb->family_selection = FSBOne;
+ }
+
+ if (fsb->fsb.current_face_multiple) {
+ cb->face = NULL;
+ cb->face_selection = FSBMultiple;
+ } else if (fsb->fsb.currently_selected_face == NULL) {
+ cb->face = NULL;
+ cb->face_selection = FSBNone;
+ } else {
+ cb->face = fsb->fsb.currently_selected_face->face_name;
+ cb->face_selection = FSBOne;
+ }
+
+ if (cb->family_selection == FSBMultiple ||
+ cb->face_selection == FSBMultiple) {
+ cb->name = NULL;
+ cb->name_selection = FSBMultiple;
+ } else if (fsb->fsb.currently_selected_face == NULL) {
+ cb->name = NULL;
+ cb->name_selection = FSBNone;
+ } else {
+ if (fsb->fsb.currently_selected_blend != NULL) {
+ cb->name = fsb->fsb.currently_selected_blend->font_name;
+ } else cb->name = fsb->fsb.currently_selected_face->font_name;
+ cb->name_selection = FSBOne;
+ }
+
+ if (fsb->fsb.current_size_multiple) {
+ cb->size = 0.0;
+ cb->size_selection = FSBMultiple;
+ } else {
+ XtVaGetValues(fsb->fsb.size_text_field_child, XmNvalue, &chSize, NULL);
+
+ if (chSize == NULL || *chSize == '\0') {
+ cb->size = 0.0;
+ cb->size_selection = FSBNone;
+ } else {
+ cb->size = atof(chSize);
+ cb->size_selection = FSBOne;
+ }
+ }
+
+ cb->afm_filename = afm;
+ cb->afm_present = (afm != NULL);
+ cb->doit = True;
+
+ if (fsb->fsb.currently_selected_blend == NULL) {
+ cb->blend = cb->base_name = NULL;
+ for (i = 0; i < MAX_AXES; i++) cb->axis_percent[i] = 0.0;
+ } else {
+ cb->blend = fsb->fsb.currently_selected_blend->blend_name;
+ cb->base_name = fsb->fsb.currently_selected_face->font_name;
+ for (i = 0; i < MAX_AXES; i++) {
+ cb->axis_percent[i] = fsb->fsb.currently_selected_blend->data[i];
+ }
+ }
+
+ if (doIt) XtCallCallbackList((Widget) fsb, fsb->fsb.validate_callback, cb);
+ return cb->doit;
+}
+
+static Boolean VerifyAndCallback(
+ FontSelectionBoxWidget fsb,
+ FSBCallbackReason reason,
+ XtCallbackList callback)
+{
+ String afm = NULL;
+ FSBValidateCallbackRec cb;
+ FontRec *fsave, *face;
+
+ if (fsb->fsb.get_afm) {
+ if (fsb->fsb.currently_selected_face == NULL) afm = NULL;
+ else afm = FindAFM((Widget) fsb,
+ fsb->fsb.currently_selected_face->font_name);
+ }
+
+ DoPreview(fsb, False);
+
+ cb.reason = reason;
+ if (!Verify(fsb, &cb, afm, True)) return False;
+
+ fsb->fsb.font_family_multiple = fsb->fsb.current_family_multiple;
+ if (!fsb->fsb.font_family_multiple &&
+ fsb->fsb.currently_selected_family != NULL) {
+ fsb->fsb.font_family =
+ fsb->fsb.currently_selected_family->family_name;
+ } else fsb->fsb.font_family = NULL;
+
+ fsb->fsb.font_face_multiple = fsb->fsb.current_face_multiple;
+ if (!fsb->fsb.font_face_multiple &&
+ fsb->fsb.currently_selected_face != NULL) {
+ fsb->fsb.font_face = fsb->fsb.currently_selected_face->face_name;
+ } else fsb->fsb.font_face = NULL;
+
+ fsb->fsb.font_name_multiple =
+ fsb->fsb.font_family_multiple || fsb->fsb.font_face_multiple;
+ if (!fsb->fsb.font_name_multiple &&
+ fsb->fsb.currently_selected_face != NULL) {
+ fsb->fsb.font_name = fsb->fsb.currently_selected_face->font_name;
+ } else fsb->fsb.font_name = NULL;
+
+ fsb->fsb.font_size_multiple = fsb->fsb.current_size_multiple;
+ if (!fsb->fsb.font_size_multiple) {
+ fsb->fsb.font_size = cb.size;
+ }
+
+ if (fsb->fsb.currently_selected_blend != NULL) {
+ fsb->fsb.font_blend = fsb->fsb.currently_selected_blend->blend_name;
+ } else fsb->fsb.font_blend = NULL;
+
+ if (fsb->fsb.undef_unused_fonts) {
+ fsave = fsb->fsb.currently_previewed;
+ if (fsb->fsb.make_fonts_shared) {
+ fsb->fsb.currently_previewed = NULL;
+ }
+ UndefUnusedFonts((Widget)fsb);
+ fsb->fsb.currently_previewed = fsave;
+ face = fsb->fsb.currently_selected_face;
+ if (face != NULL && !face->resident) {
+ face->resident = True;
+ if (fsb->fsb.make_fonts_shared) {
+ (void) DownloadFont(fsb, face->font_name,
+ fsb->fsb.context, True);
+ /* If making it shared, be sure to synchronize with
+ the caller who might be using a different context */
+ DPSWaitContext(fsb->fsb.context);
+ }
+ }
+ }
+
+ XtCallCallbackList((Widget) fsb, callback, &cb);
+ return True;
+}
+
+/* ARGSUSED */
+
+static void OKCallback(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
+
+ if (!VerifyAndCallback(fsb, FSBOK, fsb->fsb.ok_callback)) return;
+ if (XtIsShell(XtParent(fsb))) XtPopdown(XtParent(fsb));
+ WriteBlends(fsb);
+ DesensitizeReset(fsb);
+ if (fsb->fsb.show_sampler) XtPopdown(fsb->fsb.sampler);
+}
+
+/* ARGSUSED */
+
+static void ApplyCallback(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
+
+ (void) VerifyAndCallback(fsb, FSBApply, fsb->fsb.apply_callback);
+ WriteBlends(fsb);
+ DesensitizeReset(fsb);
+}
+
+static void ResetFSB(
+ FontSelectionBoxWidget fsb,
+ FSBCallbackReason reason)
+{
+ FSBCallbackRec cb;
+ int i;
+
+ fsb->fsb.currently_previewed = NULL;
+ fsb->fsb.currently_previewed_size = fsb->fsb.currently_selected_size = 0.0;
+ SetUpCurrentSelections(fsb);
+ if (fsb->fsb.undef_unused_fonts) UndefUnusedFonts((Widget)fsb);
+
+ cb.reason = reason;
+ if (fsb->fsb.font_family_multiple) {
+ cb.family = NULL;
+ cb.family_selection = FSBMultiple;
+ } else if (fsb->fsb.font_family == NULL) {
+ cb.family = NULL;
+ cb.family_selection = FSBNone;
+ } else {
+ cb.family = fsb->fsb.font_family;
+ cb.family_selection = FSBOne;
+ }
+
+ if (fsb->fsb.font_face_multiple) {
+ cb.face = NULL;
+ cb.face_selection = FSBMultiple;
+ } else if (fsb->fsb.font_face == NULL) {
+ cb.face = NULL;
+ cb.face_selection = FSBNone;
+ } else {
+ cb.face = fsb->fsb.font_face;
+ cb.face_selection = FSBOne;
+ }
+
+ if (cb.family_selection == FSBMultiple ||
+ cb.face_selection == FSBMultiple) {
+ cb.name = NULL;
+ cb.name_selection = FSBMultiple;
+ } else if (fsb->fsb.font_face == NULL) {
+ cb.name = NULL;
+ cb.name_selection = FSBNone;
+ } else {
+ cb.name = fsb->fsb.font_name;
+ cb.name_selection = FSBOne;
+ }
+
+ if (fsb->fsb.font_size_multiple) {
+ cb.size = 0.0;
+ cb.size_selection = FSBMultiple;
+ } else {
+ cb.size = fsb->fsb.font_size;
+ cb.size_selection = FSBOne;
+ }
+
+ cb.afm_filename = NULL;
+ cb.afm_present = False;
+
+ cb.blend = fsb->fsb.font_blend;
+ if (cb.blend == NULL || fsb->fsb.currently_selected_blend == NULL) {
+ cb.base_name = NULL;
+ for (i = 0; i < MAX_AXES; i++) cb.axis_percent[i] = 0;
+ } else {
+ cb.base_name = fsb->fsb.currently_selected_face->font_name;
+ for (i = 0; i < MAX_AXES; i++) {
+ cb.axis_percent[i] = fsb->fsb.currently_selected_blend->data[i];
+ }
+ }
+
+ if (reason == FSBReset) {
+ XtCallCallbackList((Widget) fsb, fsb->fsb.reset_callback, &cb);
+ } else XtCallCallbackList((Widget) fsb, fsb->fsb.cancel_callback, &cb);
+}
+
+/* ARGSUSED */
+
+static void ResetCallback(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
+
+ ResetFSB(fsb, FSBReset);
+ DesensitizeReset(fsb);
+}
+
+/* ARGSUSED */
+
+static void CancelCallback(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
+
+ ResetFSB(fsb, FSBCancel);
+ if (XtIsShell(XtParent(fsb))) XtPopdown(XtParent(fsb));
+ DesensitizeReset(fsb);
+ if (fsb->fsb.show_sampler) XtPopdown(fsb->fsb.sampler);
+}
+
+/* There's a problem; sometimes the change has already been made in the field,
+ and sometimes it hasn't. The times when it has seem to correspond to
+ making changes with the size option menu, so we use this disgusting
+ global flag to notice when this happens. We also use this to tell whether
+ or not the change is coming from internal to the widget or as a result
+ of user interaction. */
+
+static Boolean changingSize = False;
+
+/* ARGSUSED */
+
+static void SizeSelect(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ String value;
+ Widget option;
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
+ char *ch;
+
+ XtVaGetValues(widget, XmNvalue, &value, NULL);
+
+ if (value == NULL) option = fsb->fsb.other_size;
+ else {
+ if (value[0] != '\0' && fsb->fsb.current_size_multiple) {
+ fsb->fsb.current_size_multiple = False;
+ UnmanageSizeMultiple(fsb);
+ }
+ for (ch = value; *ch != '\0'; ch++) if (*ch == '.') *ch = '-';
+
+ option = XtNameToWidget(fsb->fsb.size_menu, value);
+ if (option == NULL) option = fsb->fsb.other_size;
+ }
+
+ XtVaSetValues(fsb->fsb.size_option_menu_child,
+ XmNmenuHistory, option, NULL);
+
+ if (value != NULL && value[0] != '\0') {
+ fsb->fsb.currently_selected_size = atof(value);
+ } else fsb->fsb.currently_selected_size = 0.0;
+
+ if (!changingSize) SensitizeReset(fsb);
+ fsb->fsb.current_size_multiple = False;
+}
+
+/* ARGSUSED */
+
+static void TextVerify(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ int i;
+ XmTextVerifyPtr v = (XmTextVerifyPtr) callData;
+ char ch, *cp;
+ int decimalPoints = 0;
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
+
+ if (changingSize) return; /* We know what we're doing; allow it */
+
+ /* Should probably look at format field, but seems to contain garbage */
+
+ if (v->text->length == 0) return;
+
+ if (v->text->length == 1) {
+ ch = v->text->ptr[0];
+ if (ch == 'p' || ch == 'P') {
+ XtCallCallbacks(fsb->fsb.preview_button_child,
+ XmNactivateCallback, NULL);
+ v->doit = False;
+ return;
+ }
+ }
+
+ for (i = 0; i < v->text->length; i++) {
+ ch = v->text->ptr[i];
+ if (ch == '.') decimalPoints++;
+ else if (!isdigit(ch)) {
+ v->doit = False;
+ return;
+ }
+ }
+
+ if (decimalPoints > 1) {
+ v->doit = False;
+ return;
+ }
+
+ XtVaGetValues(widget, XmNvalue, &cp, NULL);
+
+ for (/**/; *cp != '\0'; cp++) {
+ if (*cp == '.') decimalPoints++;
+ }
+
+ if (decimalPoints > 1) v->doit = False;
+}
+
+/* ARGSUSED */
+
+static void SetSize(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ char buf[20];
+ char *ch;
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
+
+ if (fsb->fsb.current_size_multiple) {
+ fsb->fsb.current_size_multiple = False;
+ UnmanageSizeMultiple(fsb);
+ }
+
+ strcpy(buf, XtName(widget));
+ for (ch = buf; *ch != '\0'; ch++) if (*ch == '-') *ch++ = '.';
+
+ changingSize = True;
+ XtVaSetValues(fsb->fsb.size_text_field_child, XmNvalue, buf, NULL);
+ changingSize = False;
+
+ SensitizeReset(fsb);
+ ValueChanged(fsb);
+}
+
+/* This makes sure the selected item is visible */
+
+static void ListSelectPos(
+ Widget w,
+ int pos,
+ Boolean notify)
+{
+ int topPos, items, visible;
+
+ XmListSelectPos(w, pos, notify);
+
+ XtVaGetValues(w, XmNtopItemPosition, &topPos,
+ XmNvisibleItemCount, &visible, XmNitemCount, &items, NULL);
+
+ if (pos >= topPos && pos < topPos + visible) return;
+ topPos = pos - (visible-1)/2;
+ if (topPos + visible > items) topPos = items - visible + 1;
+ if (topPos < 1) topPos = 1;
+
+ XtVaSetValues(w, XmNtopItemPosition, topPos, NULL);
+}
+
+/* The following function Copyright 1987, 1988 by Digital Equipment
+Corporation, Maynard, Massachusetts, and the Massachusetts Institute of
+Technology, Cambridge, Massachusetts. */
+
+static String GetRootDirName(String buf)
+{
+#ifndef X_NOT_POSIX
+ uid_t uid;
+#else
+ int uid;
+ extern int getuid();
+#ifndef SYSV386
+ extern struct passwd *getpwuid(), *getpwnam();
+#endif
+#endif
+ struct passwd *pw;
+ static char *ptr = NULL;
+
+ if (ptr == NULL) {
+ if (!(ptr = getenv("HOME"))) {
+ if ((ptr = getenv("USER")) != NULL) pw = getpwnam(ptr);
+ else {
+ uid = getuid();
+ pw = getpwuid(uid);
+ }
+ if (pw) ptr = pw->pw_dir;
+ else {
+ ptr = NULL;
+ *buf = '\0';
+ }
+ }
+ }
+
+ if (ptr)
+ (void) strcpy(buf, ptr);
+
+ buf += strlen(buf);
+ *buf = '/';
+ buf++;
+ *buf = '\0';
+ return buf;
+}
+
+static void WriteBlendLine(
+ FILE *f,
+ String family, String face, String blend, String name,
+ int axes,
+ float *p)
+{
+ register char *ch;
+ int i;
+
+ ch = family;
+ while (*ch != '\0') {
+ if (*ch == ',' || *ch == '\\') (void) putc('\\', f);
+ (void) putc(*ch++, f);
+ }
+ putc(',', f);
+ ch = face;
+ while (*ch != '\0') {
+ if (*ch == ',' || *ch == '\\') (void) putc('\\', f);
+ (void) putc(*ch++, f);
+ }
+ putc(',', f);
+ ch = blend;
+ while (*ch != '\0') {
+ if (*ch == ',' || *ch == '\\') (void) putc('\\', f);
+ (void) putc(*ch++, f);
+ }
+ (void) putc(',', f);
+ ch = name;
+ while (*ch != '\0') {
+ if (*ch == ',' || *ch == '\\') (void) putc('\\', f);
+ (void) putc(*ch++, f);
+ }
+ for (i = 0; i < axes; i++) fprintf(f, ",%f", p[i]);
+ (void) putc('\n', f);
+}
+
+static void WriteBlends(FontSelectionBoxWidget fsb)
+{
+ FontFamilyRec *ff;
+ FontRec *f;
+ BlendRec *b;
+ String blendEnv;
+ char homeDir[PATH_BUF_SIZE];
+ FILE *blendFile = NULL;
+ char fileName[PATH_BUF_SIZE];
+
+ if (!fsb->fsb.blends_changed) return;
+
+ blendEnv = getenv("DPSFONTRC");
+
+ if (blendEnv != NULL) blendFile = fopen(blendEnv, "w");
+
+ if (blendFile == NULL) {
+ (void) GetRootDirName(homeDir);
+ sprintf(fileName, "%s/.dpsfontrc", homeDir);
+ blendFile = fopen(fileName, "w");
+
+ if (blendFile == NULL) return;
+ }
+
+ for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
+ for (f = ff->fonts; f != NULL; f = f->next) {
+ if (f->blend_data != NULL) {
+ for (b = f->blend_data->blends; b != NULL; b = b->next) {
+ WriteBlendLine(blendFile, ff->family_name, f->face_name,
+ b->blend_name, b->font_name,
+ f->blend_data->num_axes, b->data);
+ }
+ }
+ }
+ }
+
+ fclose(blendFile);
+ fsb->fsb.blends_changed = False;
+}
+
+static Boolean ParseBlendLine(
+ String buf, String family, String face, String blend, String name,
+ float *p)
+{
+ char *src, *dst;
+ int i;
+ float f;
+
+ src = buf;
+ dst = family;
+ while (*src != ',' && *src != '\0') {
+ if (*src == '\\') src++;
+ if (*src == '\0') return False;
+ *dst++ = *src++;
+ }
+ if (*src == '\0') return False;
+ *dst = '\0';
+ src++;
+ dst = face;
+ while (*src != ',' && *src != '\0') {
+ if (*src == '\\') src++;
+ if (*src == '\0') return False;
+ *dst++ = *src++;
+ }
+ if (*src == '\0') return False;
+ *dst = '\0';
+ src++;
+ dst = blend;
+ while (*src != ',' && *src != '\0') {
+ if (*src == '\\') src++;
+ if (*src == '\0') return False;
+ *dst++ = *src++;
+ }
+ if (*src == '\0') return False;
+ *dst = '\0';
+ src++;
+ dst = name;
+ while (*src != ',' && *src != '\0') {
+ if (*src == '\\') src++;
+ if (*src == '\0') return False;
+ *dst++ = *src++;
+ }
+ if (*src == '\0') return False;
+ *dst = '\0';
+ for (i = 0; i < MAX_AXES; i++) {
+ src++;
+ if (!ScanFloat(src, &f, &src)) {
+ for (/**/; i < MAX_AXES; i++) p[i] = 0;
+ return True;;
+ }
+ else p[i] = f;
+ }
+ return True;
+}
+
+static void ReadBlends(FontSelectionBoxWidget fsb)
+{
+ String blendEnv;
+ char homeDir[PATH_BUF_SIZE];
+ FILE *blendFile = NULL;
+ char fileName[PATH_BUF_SIZE];
+#define BUF 256
+ char buf[BUF+1], family[BUF+1], face[BUF+1], blend[BUF+1], name[BUF+1];
+ char *cfamily, *cface;
+ float p[MAX_AXES];
+ FontRec *f;
+ FontFamilyRec *ff = 0;
+ BlendRec *b, *newb, **lastb;
+ char *spaceBlend;
+ char *lastFamily = NULL;
+ int cmp, i;
+
+ blendEnv = getenv("DPSFONTRC");
+
+ if (blendEnv != NULL) blendFile = fopen(blendEnv, "r");
+
+ if (blendFile == NULL) {
+ (void) GetRootDirName(homeDir);
+ sprintf(fileName, "%s/.dpsfontrc", homeDir);
+ blendFile = fopen(fileName, "r");
+
+ if (blendFile == NULL) return;
+ }
+
+ while (1) {
+ if (fgets(buf, BUF, blendFile) == NULL) {
+ fclose(blendFile);
+ return;
+ }
+ if (ParseBlendLine(buf, family, face, blend, name, p)) {
+ cfamily = Canonical(family);
+ if (cfamily != lastFamily) {
+ for (ff = fsb->fsb.known_families;
+ ff != NULL && ff->family_name != cfamily;
+ ff = ff->next) {}
+ }
+ if (ff == NULL) continue;
+ lastFamily = cfamily;
+ cface = Canonical(face);
+ for (f = ff->fonts; f != NULL && f->face_name != cface;
+ f = f->next) {}
+ /* If the blend data is NULL, we have a blend line for a font
+ that we don't believe is a MM font. Ignore it */
+ if (f != NULL && f->blend_data != NULL) {
+ lastb = &f->blend_data->blends;
+ cmp = -1;
+ for (b = f->blend_data->blends; b != NULL; b = b->next) {
+ cmp = strcmp(blend, b->blend_name);
+ if (cmp < 0) break;
+ lastb = &b->next;
+ }
+ if (cmp != 0) {
+ newb = XtNew(BlendRec);
+ newb->blend_name = Canonical(blend);
+ newb->CS_blend_name = CS(newb->blend_name, (Widget) fsb);
+
+ spaceBlend = (char *) XtMalloc(strlen(blend) + 4);
+ spaceBlend[0] = spaceBlend[1] = spaceBlend[2] = ' ';
+ strcpy(spaceBlend+3, blend);
+ newb->CS_space_blend_name = CS(spaceBlend, (Widget) fsb);
+ XtFree((XtPointer) spaceBlend);
+
+ for (i = 0; i < MAX_AXES; i++) newb->data[i] = p[i];
+ newb->font_name = Canonical(name);
+
+ f->blend_count++;
+ ff->blend_count++;
+
+ newb->next = b;
+ *lastb = newb;
+ }
+ }
+ }
+ }
+}
+
+static void SetUpFaceList(
+ FontSelectionBoxWidget fsb,
+ FontFamilyRec *ff)
+{
+ FontRec *f;
+ BlendRec *b;
+ XmString *CSfaces;
+ Boolean multiple = False;
+ int i;
+
+ for (f = ff->fonts; f != NULL; f = f->next) {
+ if (f->blend_data != NULL) {
+ multiple = True;
+ break;
+ }
+ }
+ if (multiple) ManageMultipleMaster(fsb);
+ else UnmanageMultipleMaster(fsb);
+
+ CSfaces = (XmString *) XtCalloc(ff->font_count + ff->blend_count,
+ sizeof(XmString));
+
+ i = 0;
+ for (f = ff->fonts; f != NULL; f = f->next) {
+ CSfaces[i++] = f->CS_face_name;
+ if (f->blend_data != NULL) {
+ for (b = f->blend_data->blends; b != NULL; b = b->next) {
+ CSfaces[i++] = b->CS_space_blend_name;
+ }
+ }
+ }
+
+ XtVaSetValues(fsb->fsb.face_scrolled_list_child,
+ XmNitemCount, ff->font_count + ff->blend_count,
+ XmNitems, CSfaces, NULL);
+ XtFree((XtPointer) CSfaces);
+}
+
+/* ARGSUSED */
+
+static void DeleteMessage(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ XtDestroyWidget(widget);
+}
+
+static void FlushFont(
+ FontSelectionBoxWidget fsb,
+ FontRec *font)
+{
+ FontRec *f = 0, *f1;
+ FontFamilyRec *ff, *ff1;
+ Boolean previewedFamily = False;
+
+ for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
+ for (f = ff->fonts; f != NULL; f = f->next) {
+ if (f == font) goto FOUND_BOGUS;
+ }
+ }
+
+FOUND_BOGUS:
+ if (f != NULL) {
+ for (f1 = ff->fonts; f1 != NULL; f1 = f1->next) {
+ if (f1 == fsb->fsb.currently_previewed) {
+ previewedFamily = True;
+ break;
+ }
+ }
+
+ if (ff->fonts == f) {
+ ff->fonts = f->next;
+ } else {
+ for (f1 = ff->fonts; f1 != NULL && f1->next != f; f1 = f1->next) {}
+ if (f1 != NULL) f1->next = f->next;
+ }
+
+ ff->font_count--;
+ ff->blend_count -= f->blend_count;
+
+ if (f == fsb->fsb.currently_selected_face) {
+ fsb->fsb.currently_selected_face = NULL;
+ fsb->fsb.currently_selected_blend = NULL;
+ }
+
+ if (previewedFamily) SetUpFaceList(fsb, ff);
+
+ if (f == fsb->fsb.currently_previewed) {
+ fsb->fsb.currently_previewed = NULL;
+ fsb->fsb.currently_previewed_blend = NULL;
+ ValueChanged(fsb);
+ }
+
+ /* We do not free the FontRec or FontFamilyRec. In the long
+ run we don't expect to leak much storage this way, since we
+ shouldn't have many bogus fonts, and invalidating every
+ reference here, in the sampler, and in the creator isn't
+ worth the small storage waste. */
+
+ if (ff->fonts == NULL) {
+ if (fsb->fsb.known_families == ff) {
+ fsb->fsb.known_families = ff->next;
+ } else {
+ for (ff1 = fsb->fsb.known_families;
+ ff1 != NULL && ff1->next != ff; ff1 = ff1->next) {}
+ if (ff1 != NULL) ff1->next = ff->next;
+ }
+
+ fsb->fsb.family_count--;
+
+ if (ff == fsb->fsb.currently_selected_family) {
+ fsb->fsb.currently_selected_family = NULL;
+ }
+
+ DisplayFontFamilies(fsb);
+ }
+ }
+}
+
+void _FSBFlushFont(
+ FontSelectionBoxWidget fsb,
+ FontRec *font)
+{
+ if (font == fsb->fsb.currently_previewed) _FSBBogusFont(fsb, font);
+ else FlushFont(fsb, font);
+}
+
+void _FSBBogusFont(
+ FontSelectionBoxWidget fsb,
+ FontRec *font)
+{
+ Widget message, w;
+
+ message = XmCreateInformationDialog((Widget) fsb, "invalidFontMessage",
+ (ArgList) NULL, 0);
+ w = XmMessageBoxGetChild(message, XmDIALOG_CANCEL_BUTTON);
+ XtUnmanageChild(w);
+ w = XmMessageBoxGetChild(message, XmDIALOG_HELP_BUTTON);
+ XtUnmanageChild(w);
+ XtAddCallback(message, XmNokCallback, DeleteMessage, (XtPointer) NULL);
+
+ XtManageChild(message);
+
+ /* Now get this blasted thing out of here */
+ FlushFont(fsb, font);
+}
+
+void _FSBSetUpFaceList(
+ FontSelectionBoxWidget fsb,
+ Bool redisplay)
+{
+ FontRec *f;
+ BlendRec *b;
+ int i;
+
+ SetUpFaceList(fsb, fsb->fsb.currently_selected_family);
+
+ f = fsb->fsb.currently_selected_family->fonts;
+ i = 1;
+ while (f != NULL) {
+ if (f == fsb->fsb.currently_selected_face) {
+ if (f->blend_data != NULL) {
+ b = f->blend_data->blends;
+ if (fsb->fsb.currently_selected_blend != NULL) {
+ i++;
+ while (b != NULL &&
+ b != fsb->fsb.currently_selected_blend) {
+ i++;
+ b = b->next;
+ }
+ }
+ }
+ break;
+ } else {
+ i += f->blend_count+1;
+ f = f->next;
+ }
+ }
+
+ ListSelectPos(fsb->fsb.face_scrolled_list_child, i, False);
+ if (redisplay) ValueChanged(fsb);
+ fsb->fsb.blends_changed = True;
+}
+
+static String categories[][6] = {
+ {"Regular", "Roman", "Medium", "Book", "Light", NULL},
+ {"Italic", "Slanted", "Oblique", NULL},
+ {"Demi", "Semibold", "Heavy", "Bold", NULL},
+ {NULL},
+};
+
+#define NORMALINDEX 0][0
+#define ITALICINDEX 1][0
+#define BOLDINDEX 2][3
+#define DEMIINDEX 2][0
+#define LIGHTINDEX 0][4
+#define BOOKINDEX 0][3
+
+static String extraNormalFaces[] = {"Demi", "Semibold", NULL};
+
+static int MatchFaceName(
+ FSBFaceSelectCallbackRec *rec,
+ Boolean *gaveUp)
+{
+ int i, j, k, face;
+#define PIECEMAX 10
+ String pieces[PIECEMAX];
+ int numPieces;
+ int pass;
+ char *ch, *start, *compare;
+ char save;
+ static Boolean categoriesInited = False;
+ static char *canonicalBold, *canonicalLight, *canonicalBook;
+
+ *gaveUp = False;
+
+ if (!categoriesInited) {
+ for (i = 0; categories[i][0] != NULL; i++) {
+ for (j = 0; categories[i][j] != NULL; j++) {
+ categories[i][j] = Canonical(categories[i][j]);
+ }
+ }
+ for (i = 0; extraNormalFaces[i] != NULL; i++) {
+ extraNormalFaces[i] = Canonical(extraNormalFaces[i]);
+ }
+ canonicalBold = categories[BOLDINDEX];
+ canonicalLight = categories[LIGHTINDEX];
+ canonicalBook = categories[BOOKINDEX];
+ categoriesInited = True;
+ }
+
+ if (rec->current_face == NULL || rec->current_face[0] == '\0') {
+ goto GIVE_UP;
+ }
+
+ /* First check for an exact match */
+
+ for (i = 0; i < rec->num_available_faces; i++) {
+ if (rec->available_faces[i] == rec->current_face) return i;
+ }
+
+ /* Try some category matching. We make two passes; in the first pass
+ we remove "Bold" from the "Demi" family and "Light" and "Book" from
+ the "Regular" family; in the second pass we include them. We ignore
+ leading digits in the face name. */
+
+ categories[BOLDINDEX] = categories[LIGHTINDEX] =
+ categories[BOOKINDEX] = NULL;
+
+ i = 0;
+ ch = rec->current_face;
+ while (*ch == ' ' || isdigit(*ch)) ch++;
+ start = ch;
+
+ while (1) {
+ while (*ch != ' ' && *ch != '\0') ch++;
+ save = *ch;
+ *ch = '\0';
+ compare = Canonical(start);
+ for (j = 0; categories[j][0] != NULL; j++) {
+ for (k = 0; categories[j][k] != NULL; k++) {
+ if (compare == categories[j][k]) {
+ pieces[i++] = categories[j][0];
+ goto FOUND_PIECE;
+ }
+ }
+ }
+ pieces[i++] = compare; /* A unique piece */
+FOUND_PIECE:
+ *ch = save;
+ while (*ch == ' ') ch++;
+ if (*ch == '\0') break;
+ if (i >= PIECEMAX) goto GIVE_UP;
+ start = ch;
+ }
+ numPieces = i;
+ if (numPieces == 0) goto GIVE_UP;
+
+ /* Special case starting with the italic category */
+
+ if (pieces[0] == categories[ITALICINDEX] && numPieces < PIECEMAX-1) {
+ for (i = numPieces; i > 0; i--) pieces[i] = pieces[i-1];
+ pieces[0] = categories[NORMALINDEX];
+ numPieces++;
+ }
+
+ for (pass = 0; pass < 2; pass++) {
+ if (pass == 1) {
+ categories[BOLDINDEX] = canonicalBold;
+ categories[LIGHTINDEX] = canonicalLight;
+ categories[BOOKINDEX] = canonicalBook;
+ for (i = 0; i < numPieces; i++) {
+ if (pieces[i] == canonicalBold) {
+ pieces[i] = categories[DEMIINDEX];
+ } else if (pieces[i] == canonicalLight) {
+ pieces[i] = categories[NORMALINDEX];
+ } else if (pieces[i] == canonicalBook) {
+ pieces[i] = categories[NORMALINDEX];
+ }
+ }
+ }
+
+ /* Now match against each face */
+
+ for (face = 0; face < rec->num_available_faces; face++) {
+ i = 0;
+ ch = rec->available_faces[face];
+ while (*ch == ' ' || isdigit(*ch)) ch++;
+ start = ch;
+
+ while (1) {
+ while (*ch != ' ' && *ch != '\0') ch++;
+ save = *ch;
+ *ch = '\0';
+ compare = Canonical(start);
+ for (j = 0; categories[j][0] != NULL; j++) {
+ for (k = 0; categories[j][k] != NULL; k++) {
+ if (compare == categories[j][k]) {
+ compare = categories[j][0];
+ goto MATCH;
+ }
+ }
+ }
+ MATCH:
+ /* Special case matching the italic category again */
+
+ if (i == 0 && compare == categories[ITALICINDEX] &&
+ pieces[0] == categories[NORMALINDEX] &&
+ numPieces > 1 &&
+ pieces[1] == categories[ITALICINDEX]) i = 1;
+
+ if (pieces[i] != compare) {
+ *ch = save;
+ goto NEXT_FACE;
+ } else i++;
+
+ *ch = save;
+ while (*ch == ' ') ch++;
+ if (*ch == '\0') break;
+ if (i >= numPieces) goto NEXT_FACE;
+ start = ch;
+ }
+ if (i == numPieces) return face; /* Found a match! */
+ NEXT_FACE:
+ ;
+ }
+ }
+
+ /* Couldn't find a match. Look for a "normal face". Make sure "Light"
+ and "Book" are installed. Again, ignore leading spaces. */
+GIVE_UP:
+ *gaveUp = True;
+ categories[LIGHTINDEX] = canonicalLight;
+ categories[BOOKINDEX] = canonicalBook;
+
+ for (i = 0; categories[0][i] != NULL; i++) {
+ for (face = 0; face < rec->num_available_faces; face++) {
+ compare = rec->available_faces[face];
+ while (*compare == ' ' || isdigit(*compare)) compare++;
+ if (compare != rec->available_faces[face]) {
+ compare = Canonical(compare);
+ }
+ if (categories[0][i] == compare) return face;
+ }
+ }
+
+ for (i = 0; extraNormalFaces[i] != NULL; i++) {
+ for (face = 0; face < rec->num_available_faces; face++) {
+ compare = rec->available_faces[face];
+ while (*compare == ' ' || isdigit(*compare)) compare++;
+ if (compare != rec->available_faces[face]) {
+ compare = Canonical(compare);
+ }
+ if (extraNormalFaces[i] == compare) return face;
+ }
+ }
+
+ /* Oh, well. Use the first one */
+ return 0;
+}
+
+static void GetInitialFace(
+ FontSelectionBoxWidget fsb,
+ FontFamilyRec *ff)
+{
+ FSBFaceSelectCallbackRec rec;
+ String *faces;
+ int i, j;
+ FontRec *f;
+ Boolean junk;
+
+ faces = (String *) XtMalloc(ff->font_count * sizeof(String));
+ i = 0;
+ for (f = ff->fonts; f != NULL; f = f->next) faces[i++] = f->face_name;
+
+ rec.available_faces = faces;
+ rec.num_available_faces = ff->font_count;
+
+ if (fsb->fsb.currently_selected_face != NULL) {
+ rec.current_face = fsb->fsb.currently_selected_face->face_name;
+ } else rec.current_face = fsb->fsb.font_face;
+
+ rec.new_face = NULL;
+
+ XtCallCallbackList((Widget) fsb, fsb->fsb.face_select_callback, &rec);
+ if (rec.new_face != NULL) {
+ for (i = 0; i < ff->font_count; i++) {
+ if (rec.new_face == faces[i]) break;
+ }
+ }
+ if (rec.new_face == NULL || i >= ff->font_count) {
+ i = MatchFaceName(&rec, &junk);
+ }
+ XtFree((XtPointer) faces);
+
+ j = 0;
+ for (f = ff->fonts; i != 0; f= f->next) {
+ j += f->blend_count + 1;
+ i--;
+ }
+
+ ListSelectPos(fsb->fsb.face_scrolled_list_child, j+1, False);
+ fsb->fsb.currently_selected_face = f;
+ fsb->fsb.currently_selected_blend = NULL;
+}
+
+/* ARGSUSED */
+
+static void FamilySelect(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ XmListCallbackStruct *listCB = (XmListCallbackStruct *) callData;
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
+ FontFamilyRec *ff = fsb->fsb.known_families;
+ int i;
+
+ if (fsb->fsb.current_family_multiple) {
+ fsb->fsb.current_family_multiple = False;
+ UnmanageFamilyMultiple(fsb);
+ }
+
+ /* List uses 1-based addressing!! */
+ for (i = 1; i < listCB->item_position; i++) ff = ff->next;
+
+ fsb->fsb.currently_selected_family = ff;
+
+ SensitizeReset(fsb);
+ SetUpFaceList(fsb, ff);
+ if (!fsb->fsb.current_face_multiple) GetInitialFace(fsb, ff);
+ ValueChanged(fsb);
+}
+
+/* ARGSUSED */
+
+static void FaceSelect(
+ Widget widget,
+ XtPointer clientData, XtPointer callData)
+{
+ XmListCallbackStruct *listCB = (XmListCallbackStruct *) callData;
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) clientData;
+ FontRec *f;
+ BlendRec *b;
+ int n;
+
+ if (fsb->fsb.currently_selected_family == NULL) return;
+ f = fsb->fsb.currently_selected_family->fonts;
+
+ if (fsb->fsb.current_face_multiple) {
+ fsb->fsb.current_face_multiple = False;
+ UnmanageFaceMultiple(fsb);
+ }
+
+ /* List uses 1-based addressing!! */
+ n = 0;
+ while (1) {
+ n += f->blend_count + 1;
+ if (n >= listCB->item_position) {
+ n -= f->blend_count;
+ if (n == listCB->item_position) b = NULL;
+ else for (b = f->blend_data->blends; n < listCB->item_position - 1;
+ b = b->next) n++;
+ break;
+ }
+ f = f->next;
+ }
+
+ fsb->fsb.currently_selected_face = f;
+ fsb->fsb.currently_selected_blend = b;
+
+ SensitizeReset(fsb);
+ ValueChanged(fsb);
+}
+
+static void CreateSizeMenu(
+ FontSelectionBoxWidget fsb,
+ Boolean destroyOldChildren)
+{
+ Arg args[20];
+ int i, j;
+ Widget *sizes;
+ char buf[20];
+ Widget *children;
+ Cardinal num_children;
+ XmString csName;
+ char *ch;
+
+ if (destroyOldChildren) {
+ XtVaGetValues(fsb->fsb.size_menu, XtNchildren, &children,
+ XtNnumChildren, &num_children, NULL);
+
+ /* Don't destroy first child ("other") */
+ for (j = 1; (Cardinal)j < num_children; j++) XtDestroyWidget(children[j]);
+
+ sizes = (Widget *) XtMalloc((fsb->fsb.size_count+1) * sizeof(Widget));
+ sizes[0] = children[0];
+ } else {
+ i = 0;
+ sizes = (Widget *) XtMalloc((fsb->fsb.size_count+1) * sizeof(Widget));
+ fsb->fsb.other_size = sizes[0] =
+ XtCreateManagedWidget("other", xmPushButtonGadgetClass,
+ fsb->fsb.size_menu, args, i);
+ }
+
+ for (j = 0; j < fsb->fsb.size_count; j++) {
+ (void) sprintf(buf, "%g", fsb->fsb.sizes[j]);
+ csName = UnsharedCS(buf);
+ for (ch = buf; *ch != '\0'; ch++) if (*ch == '.') *ch = '-';
+ i = 0;
+ XtSetArg(args[i], XmNlabelString, csName); i++;
+ sizes[j+1] =
+ XmCreatePushButtonGadget(fsb->fsb.size_menu, buf, args, i);
+ XmStringFree(csName);
+ XtAddCallback(sizes[j+1], XmNactivateCallback,
+ SetSize, (XtPointer) fsb);
+ }
+ XtManageChildren(sizes, j+1);
+ XtFree((char *) sizes);
+}
+
+static void CreateChildren(FontSelectionBoxWidget fsb)
+{
+ Arg args[20];
+ int i;
+ Widget form;
+
+ i = 0;
+ fsb->fsb.pane_child =
+ XtCreateManagedWidget("pane", xmPanedWindowWidgetClass,
+ (Widget) fsb, args, i);
+
+ i = 0;
+ fsb->fsb.preview_child =
+ XtCreateManagedWidget("preview", xmDrawingAreaWidgetClass,
+ fsb->fsb.pane_child, args, i);
+ XtAddCallback(fsb->fsb.preview_child, XmNexposeCallback,
+ PreviewText, (XtPointer) fsb);
+ XtAddCallback(fsb->fsb.preview_child, XmNresizeCallback,
+ ResizePreview, (XtPointer) fsb);
+
+ i = 0;
+ form = XtCreateManagedWidget("panel", xmFormWidgetClass,
+ fsb->fsb.pane_child, args, i);
+ fsb->fsb.panel_child = form;
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
+ fsb->fsb.ok_button_child =
+ XtCreateManagedWidget("okButton", xmPushButtonWidgetClass,
+ form, args, i);
+ XtAddCallback(fsb->fsb.ok_button_child, XmNactivateCallback,
+ OKCallback, (XtPointer) fsb);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget,fsb->fsb.ok_button_child ); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
+ fsb->fsb.apply_button_child =
+ XtCreateManagedWidget("applyButton", xmPushButtonWidgetClass,
+ form, args, i);
+ XtAddCallback(fsb->fsb.apply_button_child, XmNactivateCallback,
+ ApplyCallback, (XtPointer) fsb);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget,fsb->fsb.apply_button_child ); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
+ fsb->fsb.reset_button_child =
+ XtCreateManagedWidget("resetButton", xmPushButtonWidgetClass,
+ form, args, i);
+ XtAddCallback(fsb->fsb.reset_button_child, XmNactivateCallback,
+ ResetCallback, (XtPointer) fsb);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget,fsb->fsb.reset_button_child ); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
+ fsb->fsb.cancel_button_child =
+ XtCreateManagedWidget("cancelButton", xmPushButtonWidgetClass,
+ form, args, i);
+ XtAddCallback(fsb->fsb.cancel_button_child, XmNactivateCallback,
+ CancelCallback, (XtPointer) fsb);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, fsb->fsb.ok_button_child); i++;
+ fsb->fsb.separator_child =
+ XtCreateManagedWidget("separator", xmSeparatorGadgetClass,
+ form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, fsb->fsb.separator_child); i++;
+ fsb->fsb.size_label_child =
+ XtCreateManagedWidget("sizeLabel", xmLabelWidgetClass,
+ form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, fsb->fsb.size_label_child); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, fsb->fsb.size_label_child); i++;
+ fsb->fsb.size_text_field_child =
+ XtCreateManagedWidget("sizeTextField", xmTextFieldWidgetClass,
+ form, args, i);
+ XtAddCallback(fsb->fsb.size_text_field_child, XmNvalueChangedCallback,
+ SizeSelect, (XtPointer) fsb);
+ XtAddCallback(fsb->fsb.size_text_field_child, XmNmodifyVerifyCallback,
+ TextVerify, (XtPointer) fsb);
+
+ i = 0;
+ fsb->fsb.size_menu = XmCreatePulldownMenu(form, "sizeMenu", args, i);
+
+ CreateSizeMenu(fsb, False);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, fsb->fsb.size_text_field_child); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, fsb->fsb.size_label_child); i++;
+ XtSetArg(args[i], XmNsubMenuId, fsb->fsb.size_menu); i++;
+ fsb->fsb.size_option_menu_child =
+ XmCreateOptionMenu(form, "sizeOptionMenu", args, i);
+ XtManageChild(fsb->fsb.size_option_menu_child);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, fsb->fsb.size_option_menu_child); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, fsb->fsb.separator_child); i++;
+ fsb->fsb.size_multiple_label_child =
+ XtCreateWidget("sizeMultipleLabel", xmLabelWidgetClass,
+ form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, fsb->fsb.size_label_child); i++;
+ fsb->fsb.preview_button_child =
+ XtCreateManagedWidget("previewButton", xmPushButtonWidgetClass,
+ form, args, i);
+ XtAddCallback(fsb->fsb.preview_button_child, XmNactivateCallback,
+ PreviewCallback, (XtPointer) fsb);
+
+ i = 0;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNrightWidget, fsb->fsb.preview_button_child); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, fsb->fsb.preview_button_child); i++;
+ fsb->fsb.sampler_button_child =
+ XtCreateWidget("samplerButton", xmPushButtonWidgetClass,
+ form, args, i);
+ if (fsb->fsb.show_sampler_button) {
+ XtManageChild(fsb->fsb.sampler_button_child);
+ }
+ XtAddCallback(fsb->fsb.sampler_button_child, XmNactivateCallback,
+ ShowSamplerCallback, (XtPointer) fsb);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_POSITION); i++;
+ XtSetArg(args[i], XmNrightPosition, 50); i++;
+ fsb->fsb.family_label_child =
+ XtCreateManagedWidget("familyLabel", xmLabelGadgetClass,
+ form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_POSITION); i++;
+ XtSetArg(args[i], XmNleftPosition, 50); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
+ fsb->fsb.face_label_child =
+ XtCreateManagedWidget("faceLabel", xmLabelGadgetClass,
+ form, args, i);
+
+ /* The next two must be widgets in order to be reversed in color */
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, fsb->fsb.family_label_child); i++;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_POSITION); i++;
+ XtSetArg(args[i], XmNrightPosition, 50); i++;
+ fsb->fsb.family_multiple_label_child =
+ XtCreateWidget("familyMultipleLabel", xmLabelWidgetClass,
+ form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, fsb->fsb.face_label_child); i++;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_POSITION); i++;
+ XtSetArg(args[i], XmNleftPosition, 50); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
+ fsb->fsb.face_multiple_label_child =
+ XtCreateWidget("faceMultipleLabel", xmLabelWidgetClass,
+ form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNitemCount, 1); i++;
+ XtSetArg(args[i], XmNitems, &CSempty); i++;
+ fsb->fsb.family_scrolled_list_child =
+ XmCreateScrolledList(form, "familyScrolledList", args, i);
+ XtAddCallback(fsb->fsb.family_scrolled_list_child,
+ XmNbrowseSelectionCallback, FamilySelect, (XtPointer) fsb);
+ XtAddCallback(fsb->fsb.family_scrolled_list_child,
+ XmNdefaultActionCallback,
+ PreviewDoubleClick, (XtPointer) fsb);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, fsb->fsb.family_label_child); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, fsb->fsb.size_text_field_child); i++;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_POSITION); i++;
+ XtSetArg(args[i], XmNrightPosition, 50); i++;
+ XtSetValues(XtParent(fsb->fsb.family_scrolled_list_child), args, i);
+ XtManageChild(fsb->fsb.family_scrolled_list_child);
+
+ i = 0;
+ XtSetArg(args[i], XmNitemCount, 1); i++;
+ XtSetArg(args[i], XmNitems, &CSempty); i++;
+ fsb->fsb.face_scrolled_list_child =
+ XmCreateScrolledList(form, "faceScrolledList", args, i);
+ XtAddCallback(fsb->fsb.face_scrolled_list_child,
+ XmNbrowseSelectionCallback, FaceSelect, (XtPointer) fsb);
+ XtAddCallback(fsb->fsb.face_scrolled_list_child,
+ XmNdefaultActionCallback, PreviewDoubleClick,
+ (XtPointer) fsb);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, fsb->fsb.face_label_child); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, fsb->fsb.size_text_field_child); i++;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_POSITION); i++;
+ XtSetArg(args[i], XmNleftPosition, 50); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
+ XtSetValues(XtParent(fsb->fsb.face_scrolled_list_child), args, i);
+ XtManageChild(fsb->fsb.face_scrolled_list_child);
+
+ i = 0;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, fsb->fsb.size_text_field_child); i++;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_POSITION); i++;
+ XtSetArg(args[i], XmNleftPosition, 50); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
+ fsb->fsb.multiple_master_button_child =
+ XtCreateWidget("multipleMasterButton", xmPushButtonWidgetClass,
+ form, args, i);
+ XtAddCallback(fsb->fsb.multiple_master_button_child, XmNactivateCallback,
+ ShowCreatorCallback, (XtPointer) fsb);
+
+ i = 0;
+ XtSetArg(args[i], XmNdefaultButton, fsb->fsb.ok_button_child); i++;
+ XtSetValues(form, args, i);
+}
+
+static void DisplayFontFamilies(FontSelectionBoxWidget fsb)
+{
+ FontFamilyRec *ff;
+ XmString *CSlist, *str;
+
+ CSlist = (XmString *) XtMalloc(fsb->fsb.family_count * sizeof(XmString));
+ str = CSlist;
+ for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
+ *str++ = UnsharedCS(ff->family_name);
+ }
+
+ XtVaSetValues(fsb->fsb.family_scrolled_list_child,
+ XmNitemCount, fsb->fsb.family_count,
+ XmNitems, CSlist, NULL);
+
+ /* The list makes a copy, so we can delete the list */
+ XtFree((char *) CSlist);
+}
+
+static void SetUpCurrentFontFromName(FontSelectionBoxWidget fsb)
+{
+ FontFamilyRec *ff;
+ FontRec *f;
+ BlendRec *b;
+ int i, j;
+
+ fsb->fsb.currently_selected_face = NULL;
+ fsb->fsb.currently_selected_family = NULL;
+ fsb->fsb.currently_selected_blend = NULL;
+
+ if (fsb->fsb.font_name_multiple || fsb->fsb.font_name == NULL) {
+ fsb->fsb.font_name = NULL;
+ fsb->fsb.font_family = NULL;
+ fsb->fsb.font_blend = NULL;
+ fsb->fsb.font_face = NULL;
+ if (fsb->fsb.font_name_multiple) {
+ fsb->fsb.current_family_multiple = True;
+ fsb->fsb.current_face_multiple = True;
+ ManageFamilyMultiple(fsb);
+ ManageFaceMultiple(fsb);
+ }
+ XmListDeselectAllItems(fsb->fsb.family_scrolled_list_child);
+ XmListDeselectAllItems(fsb->fsb.face_scrolled_list_child);
+ XmListDeleteAllItems(fsb->fsb.face_scrolled_list_child);
+ XmListAddItem(fsb->fsb.face_scrolled_list_child, CSempty, 1);
+ return;
+ }
+
+ if (!fsb->fsb.font_name_multiple) {
+ fsb->fsb.current_family_multiple = False;
+ fsb->fsb.current_face_multiple = False;
+ UnmanageFamilyMultiple(fsb);
+ UnmanageFaceMultiple(fsb);
+ }
+
+ fsb->fsb.font_name = Canonical(fsb->fsb.font_name);
+ i = 1;
+ for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
+ j = 1;
+ for (f = ff->fonts; f != NULL; f = f->next) {
+ if (f->font_name == fsb->fsb.font_name) {
+ fsb->fsb.font_family = ff->family_name;
+ fsb->fsb.font_face = f->face_name;
+ SetUpFaceList(fsb, ff);
+ ListSelectPos(fsb->fsb.family_scrolled_list_child, i, False);
+ ListSelectPos(fsb->fsb.face_scrolled_list_child, j, False);
+ fsb->fsb.currently_selected_face = f;
+ fsb->fsb.currently_selected_family = ff;
+ fsb->fsb.currently_selected_blend = NULL;
+ return;
+ }
+ j++;
+ if (f->blend_data != NULL && f->blend_data->blends != NULL) {
+ for (b = f->blend_data->blends; b != NULL; b = b->next) {
+ if (b->font_name == fsb->fsb.font_name) {
+ fsb->fsb.font_family = ff->family_name;
+ fsb->fsb.font_face = f->face_name;
+ SetUpFaceList(fsb, ff);
+ ListSelectPos(fsb->fsb.family_scrolled_list_child, i,
+ False);
+ ListSelectPos(fsb->fsb.face_scrolled_list_child, j,
+ False);
+ fsb->fsb.currently_selected_face = f;
+ fsb->fsb.currently_selected_family = ff;
+ fsb->fsb.currently_selected_blend = b;
+ return;
+ }
+ j++;
+ }
+ }
+
+ }
+ i++;
+ }
+
+ /* Didn't find it! */
+ fsb->fsb.font_name = NULL;
+ fsb->fsb.font_family = NULL;
+ fsb->fsb.font_face = NULL;
+ fsb->fsb.font_blend = NULL;
+ XmListDeselectAllItems(fsb->fsb.family_scrolled_list_child);
+ XmListDeselectAllItems(fsb->fsb.face_scrolled_list_child);
+ XmListDeleteAllItems(fsb->fsb.face_scrolled_list_child);
+ XmListAddItem(fsb->fsb.face_scrolled_list_child, CSempty, 1);
+}
+
+static void SetUpCurrentFontFromFamilyFace(FontSelectionBoxWidget fsb)
+{
+ FontFamilyRec *ff;
+ FontRec *f;
+ BlendRec *b;
+ int i;
+
+ fsb->fsb.currently_selected_face = NULL;
+ fsb->fsb.currently_selected_family = NULL;
+ fsb->fsb.currently_selected_blend = NULL;
+
+ if (fsb->fsb.font_family_multiple) {
+ fsb->fsb.font_family = NULL;
+ fsb->fsb.current_family_multiple = True;
+ ManageFamilyMultiple(fsb);
+ } else {
+ fsb->fsb.current_family_multiple = False;
+ UnmanageFamilyMultiple(fsb);
+ }
+
+ if (fsb->fsb.font_face_multiple) {
+ fsb->fsb.font_face = NULL;
+ fsb->fsb.current_face_multiple = True;
+ ManageFaceMultiple(fsb);
+ } else {
+ fsb->fsb.current_face_multiple = False;
+ UnmanageFaceMultiple(fsb);
+ }
+
+ fsb->fsb.font_name_multiple =
+ fsb->fsb.font_family_multiple || fsb->fsb.font_face_multiple;
+
+ if (fsb->fsb.font_family != NULL) {
+ fsb->fsb.font_family = Canonical(fsb->fsb.font_family);
+ i = 1;
+ for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
+ if (fsb->fsb.font_family == ff->family_name) {
+ ListSelectPos(fsb->fsb.family_scrolled_list_child, i, False);
+ fsb->fsb.currently_selected_family = ff;
+ SetUpFaceList(fsb, ff);
+ break;
+ }
+ i++;
+ }
+ if (ff == NULL) fsb->fsb.font_family = NULL;
+ }
+
+ if (fsb->fsb.font_family == NULL) {
+ fsb->fsb.font_face = NULL;
+ fsb->fsb.font_blend = NULL;
+ fsb->fsb.font_name = NULL;
+ XmListDeselectAllItems(fsb->fsb.family_scrolled_list_child);
+ XmListDeselectAllItems(fsb->fsb.face_scrolled_list_child);
+ XmListDeleteAllItems(fsb->fsb.face_scrolled_list_child);
+ XmListAddItem(fsb->fsb.face_scrolled_list_child, CSempty, 1);
+ return;
+ }
+
+ if (fsb->fsb.font_face != NULL) {
+ fsb->fsb.font_face = Canonical(fsb->fsb.font_face);
+
+ i = 1;
+ for (f = ff->fonts; f != NULL; f = f->next) {
+ if (fsb->fsb.font_face == f->face_name) {
+ fsb->fsb.currently_selected_face = f;
+ if (fsb->fsb.font_blend != NULL) {
+ fsb->fsb.font_blend = Canonical(fsb->fsb.font_blend);
+ for (b = f->blend_data->blends; b != NULL; b = b->next) {
+ i++;
+ if (b->blend_name == fsb->fsb.font_blend) {
+ fsb->fsb.currently_selected_blend = b;
+ break;
+ }
+ }
+ if (b == NULL) {
+ fsb->fsb.font_blend = NULL;
+ i -= f->blend_count;
+ }
+ }
+ ListSelectPos(fsb->fsb.face_scrolled_list_child, i, False);
+ break;
+ }
+ i += f->blend_count + 1;
+ }
+ if (f == NULL) fsb->fsb.font_face = NULL;
+ } else {
+ f = NULL;
+ XmListDeselectAllItems(fsb->fsb.face_scrolled_list_child);
+ }
+
+ if (f == NULL && !fsb->fsb.font_face_multiple) GetInitialFace(fsb, ff);
+}
+
+static void SetUpCurrentFont(FontSelectionBoxWidget fsb)
+{
+ if (fsb->fsb.use_font_name) SetUpCurrentFontFromName(fsb);
+ else SetUpCurrentFontFromFamilyFace(fsb);
+}
+
+static void SetUpCurrentSize(FontSelectionBoxWidget fsb)
+{
+ char buf[20];
+
+ if (fsb->fsb.font_size_multiple) {
+ changingSize = True;
+ XtVaSetValues(fsb->fsb.size_text_field_child, XmNvalue, "", NULL);
+ changingSize = False;
+ fsb->fsb.current_size_multiple = True;
+ ManageSizeMultiple(fsb);
+ return;
+ } else UnmanageSizeMultiple(fsb);
+
+ if (fsb->fsb.currently_selected_size == 0.0) {
+ sprintf(buf, "%g", fsb->fsb.font_size);
+ } else sprintf(buf, "%g", fsb->fsb.currently_selected_size);
+
+ changingSize = True;
+ XtVaSetValues(fsb->fsb.size_text_field_child, XmNvalue, buf, NULL);
+ changingSize = False;
+}
+
+static void SetUpCurrentSelections(FontSelectionBoxWidget fsb)
+{
+ SetUpCurrentFont(fsb);
+ SetUpCurrentSize(fsb);
+ if (fsb->fsb.preview_on_change) DoPreview(fsb, False);
+ DoValueChangedCallback(fsb);
+}
+
+/* ARGSUSED */
+
+static void Initialize(
+ Widget request, Widget new,
+ ArgList args,
+ Cardinal *num_args)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) new;
+ Bool inited;
+ char version[20];
+
+ /* Verify size list */
+
+ if (fsb->fsb.size_count > 0 && fsb->fsb.sizes == NULL) {
+ XtAppWarningMsg(XtWidgetToApplicationContext(new),
+ "initializeFontBox", "sizeMismatch",
+ "FontSelectionBoxError",
+ "Size count specified but no sizes present",
+ (String *) NULL, (Cardinal *) NULL);
+ fsb->fsb.size_count = 0;
+ }
+
+ if (fsb->fsb.size_count < 0) {
+ XtAppWarningMsg(XtWidgetToApplicationContext(new),
+ "initializeFontBox", "negativeSize",
+ "FontSelectionBoxError",
+ "Size count should not be negative",
+ (String *) NULL, (Cardinal *) NULL);
+ fsb->fsb.size_count = 0;
+ }
+
+ if (fsb->fsb.max_pending_deletes <= 0) {
+ XtAppWarningMsg(XtWidgetToApplicationContext(new),
+ "initializeFontBox", "nonPositivePendingDelete",
+ "FontSelectionBoxError",
+ "Pending delete max must be positive",
+ (String *) NULL, (Cardinal *) NULL);
+ fsb->fsb.max_pending_deletes = 1;
+ }
+
+ /* Copy strings. SetUpCurrentSelection will copy the font strings */
+
+ if (fsb->fsb.preview_string != NULL) {
+ fsb->fsb.preview_string = XtNewString(fsb->fsb.preview_string);
+ }
+ if (fsb->fsb.default_resource_path != NULL) {
+ fsb->fsb.default_resource_path =
+ XtNewString(fsb->fsb.default_resource_path);
+ }
+ if (fsb->fsb.resource_path_override != NULL) {
+ fsb->fsb.resource_path_override =
+ XtNewString(fsb->fsb.resource_path_override);
+ }
+
+ /* Get the context */
+
+ if (fsb->fsb.context == NULL) {
+ fsb->fsb.context = XDPSGetSharedContext(XtDisplay(fsb));
+ }
+
+ if (_XDPSTestComponentInitialized(fsb->fsb.context,
+ dps_init_bit_fsb, &inited) ==
+ dps_status_unregistered_context) {
+ XDPSRegisterContext(fsb->fsb.context, False);
+ }
+
+ if (!inited) {
+ (void) _XDPSSetComponentInitialized(fsb->fsb.context,
+ dps_init_bit_fsb);
+ _DPSFDefineFontEnumFunctions(fsb->fsb.context);
+ }
+
+ DPSversion(fsb->fsb.context, 20, version);
+ fsb->fsb.old_server = (atof(version) < 1007);
+
+ /* Initialize non-resource fields */
+
+ fsb->fsb.gstate = 0;
+ fsb->fsb.sampler = fsb->fsb.creator = NULL;
+ fsb->fsb.known_families = NULL;
+ fsb->fsb.family_count = 0;
+ fsb->fsb.currently_previewed = NULL;
+ fsb->fsb.currently_selected_face = NULL;
+ fsb->fsb.currently_selected_family = NULL;
+ fsb->fsb.currently_previewed_blend = NULL;
+ fsb->fsb.currently_selected_blend = NULL;
+ fsb->fsb.currently_previewed_size = 0.0;
+ fsb->fsb.currently_selected_size = 0.0;
+ fsb->fsb.pending_delete_count = 0;
+ fsb->fsb.pending_delete_font = NULL;
+ fsb->fsb.preview_fixed = False;
+ fsb->fsb.current_family_multiple = False;
+ fsb->fsb.current_face_multiple = False;
+ fsb->fsb.current_size_multiple = False;
+ fsb->fsb.blends_changed = False;
+
+ GetFontNames(fsb);
+ CreateChildren(fsb);
+
+ DisplayFontFamilies(fsb);
+ SetUpCurrentSelections(fsb);
+ DesensitizeReset(fsb);
+ if (fsb->fsb.show_sampler) ShowSampler(fsb);
+}
+
+static void FreeFontRec(FontRec *f)
+{
+ BlendDataRec *bd;
+ BlendRec *b, *next_b;
+
+ if (f->blend_data != NULL) {
+ bd = f->blend_data;
+ for (b = bd->blends; b != NULL; b = next_b) {
+ next_b = b->next;
+ XtFree((char *) b);
+ }
+ XtFree((char *) bd->internal_break);
+ XtFree((char *) bd->internal_value);
+ XtFree((char *) bd->design_positions);
+ XtFree((char *) bd);
+ }
+ XtFree(f->full_name);
+}
+
+static void FreeFontLists(
+ FontSelectionBoxWidget fsb)
+{
+ FontFamilyRec *ff, *next_ff;
+ FontRec *f, *next_f;
+
+ /* font_name, face_name, family_name, and blend_name are canonical
+ strings and so should not be freed. The face and blend compound
+ strings were gotten from converters and so should likewise remain. */
+
+ for (ff = fsb->fsb.known_families; ff != NULL; ff = next_ff) {
+ for (f = ff->fonts; f != NULL; f = next_f) {
+ FreeFontRec(f);
+ next_f = f->next;
+ XtFree((char *) f);
+ }
+ next_ff = ff->next;
+ XtFree((char *) ff);
+ }
+ fsb->fsb.known_families = NULL;
+}
+
+static void Destroy(Widget widget)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) widget;
+
+ /* Lots of stuff to destroy! */
+
+ if (fsb->fsb.gstate != 0) XDPSFreeContextGState(fsb->fsb.context,
+ fsb->fsb.gstate);
+ if (fsb->fsb.preview_string != NULL) XtFree(fsb->fsb.preview_string);
+ if (fsb->fsb.default_resource_path != NULL) {
+ XtFree(fsb->fsb.default_resource_path);
+ }
+ if (fsb->fsb.resource_path_override != NULL) {
+ XtFree(fsb->fsb.resource_path_override);
+ }
+
+ FreeFontLists(fsb);
+}
+
+static void Resize(Widget widget)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) widget;
+
+ XtResizeWidget(fsb->fsb.pane_child, fsb->core.width, fsb->core.height, 0);
+}
+
+/* ARGSUSED */
+
+static Boolean SetValues(
+ Widget old, Widget req, Widget new,
+ ArgList args,
+ Cardinal *num_args)
+{
+ FontSelectionBoxWidget oldfsb = (FontSelectionBoxWidget) old;
+ FontSelectionBoxWidget newfsb = (FontSelectionBoxWidget) new;
+ Boolean refreshLists = False, setSelection = False, do_preview = False;
+ Bool inited;
+
+#define NE(field) newfsb->fsb.field != oldfsb->fsb.field
+#define DONT_CHANGE(field) \
+ if (NE(field)) newfsb->fsb.field = oldfsb->fsb.field;
+
+ DONT_CHANGE(typographic_sort);
+ DONT_CHANGE(pane_child);
+ DONT_CHANGE(preview_child);
+ DONT_CHANGE(panel_child);
+ DONT_CHANGE(family_label_child);
+ DONT_CHANGE(family_multiple_label_child);
+ DONT_CHANGE(family_scrolled_list_child);
+ DONT_CHANGE(face_label_child);
+ DONT_CHANGE(face_multiple_label_child);
+ DONT_CHANGE(face_scrolled_list_child);
+ DONT_CHANGE(size_label_child);
+ DONT_CHANGE(size_text_field_child);
+ DONT_CHANGE(size_option_menu_child);
+ DONT_CHANGE(preview_button_child);
+ DONT_CHANGE(sampler_button_child);
+ DONT_CHANGE(separator_child);
+ DONT_CHANGE(ok_button_child);
+ DONT_CHANGE(apply_button_child);
+ DONT_CHANGE(reset_button_child);
+ DONT_CHANGE(cancel_button_child);
+#undef DONT_CHANGE
+
+ if (newfsb->fsb.size_count > 0 && newfsb->fsb.sizes == NULL) {
+ XtAppWarningMsg(XtWidgetToApplicationContext(new),
+ "setValuesFontBox", "sizeMismatch",
+ "FontSelectionBoxError",
+ "Size count specified but no sizes present",
+ (String *) NULL, (Cardinal *) NULL);
+ newfsb->fsb.size_count = 0;
+ }
+
+ if (newfsb->fsb.size_count < 0) {
+ XtAppWarningMsg(XtWidgetToApplicationContext(new),
+ "setValuesFontBox", "negativeSize",
+ "FontSelectionBoxError",
+ "Size count should not be negative",
+ (String *) NULL, (Cardinal *) NULL);
+ newfsb->fsb.size_count = 0;
+ }
+
+ if (newfsb->fsb.max_pending_deletes <= 0) {
+ XtAppWarningMsg(XtWidgetToApplicationContext(new),
+ "setValuesFontBox", "nonPositivePendingDelete",
+ "FontSelectionBoxError",
+ "Pending delete max must be positive",
+ (String *) NULL, (Cardinal *) NULL);
+ newfsb->fsb.max_pending_deletes = 1;
+ }
+
+ if (NE(preview_string)) {
+ XtFree(oldfsb->fsb.preview_string);
+ newfsb->fsb.preview_string = XtNewString(newfsb->fsb.preview_string);
+ do_preview = True;
+ }
+
+ if (NE(default_resource_path)) {
+ XtFree(oldfsb->fsb.default_resource_path);
+ newfsb->fsb.default_resource_path =
+ XtNewString(newfsb->fsb.default_resource_path);
+ refreshLists = True;
+ }
+
+ if (NE(resource_path_override)) {
+ XtFree(oldfsb->fsb.resource_path_override);
+ newfsb->fsb.resource_path_override =
+ XtNewString(newfsb->fsb.resource_path_override);
+ refreshLists = True;
+ }
+
+ if (newfsb->fsb.undef_unused_fonts) UndefSomeUnusedFonts(newfsb, False);
+
+ if (NE(context)) {
+ if (newfsb->fsb.context == NULL) {
+ newfsb->fsb.context = XDPSGetSharedContext(XtDisplay(newfsb));
+ }
+ if (_XDPSTestComponentInitialized(newfsb->fsb.context,
+ dps_init_bit_fsb, &inited) ==
+ dps_status_unregistered_context) {
+ XDPSRegisterContext(newfsb->fsb.context, False);
+ }
+ if (!inited) {
+ (void) _XDPSSetComponentInitialized(newfsb->fsb.context,
+ dps_init_bit_fsb);
+ _DPSFDefineFontEnumFunctions(newfsb->fsb.context);
+ }
+ }
+
+ if (refreshLists) {
+ UndefUnusedFonts((Widget)newfsb);
+ newfsb->fsb.pending_delete_font = NULL;
+ newfsb->fsb.pending_delete_count = 0;
+ FreeFontLists(newfsb);
+ GetFontNames(newfsb);
+ DisplayFontFamilies(newfsb);
+ setSelection = True;
+ }
+
+ if (NE(sizes)) {
+ CreateSizeMenu(newfsb, True);
+ setSelection = True;
+ }
+
+ if (NE(show_sampler)) {
+ if (newfsb->fsb.show_sampler) ShowSampler(newfsb);
+ else XtPopdown(newfsb->fsb.sampler);
+ }
+
+ if (NE(show_sampler_button)) {
+ if (newfsb->fsb.show_sampler_button) {
+ XtManageChild(newfsb->fsb.sampler_button_child);
+ } else XtUnmanageChild(newfsb->fsb.sampler_button_child);
+ }
+
+ if (NE(font_size)) newfsb->fsb.currently_selected_size = 0.0;
+
+ if (NE(use_font_name) || NE(font_name) || NE(font_family) ||
+ NE(font_face) || NE(font_size) || NE(font_name_multiple) ||
+ NE(font_family_multiple) || NE(font_face_multiple) ||
+ NE(font_size_multiple) || NE(font_blend)) setSelection = True;
+
+ if (setSelection) SetUpCurrentSelections(newfsb);
+ else if (do_preview && newfsb->fsb.preview_on_change) {
+ DoPreview(newfsb, False);
+ }
+
+ if ((NE(font_name) || NE(font_size)) &&
+ XtIsSensitive(newfsb->fsb.reset_button_child)) {
+
+ if ((newfsb->fsb.font_size_multiple ||
+ newfsb->fsb.font_size == newfsb->fsb.currently_selected_size) &&
+ (newfsb->fsb.font_name_multiple ||
+ newfsb->fsb.currently_selected_face == NULL ||
+ newfsb->fsb.font_name ==
+ newfsb->fsb.currently_selected_face->font_name)) {
+ DesensitizeReset(newfsb);
+ }
+ }
+
+ return False;
+#undef NE
+}
+
+/* ARGSUSED */
+
+static XtGeometryResult GeometryManager(
+ Widget w,
+ XtWidgetGeometry *desired, XtWidgetGeometry *allowed)
+{
+#define WANTS(flag) (desired->request_mode & flag)
+
+ if (WANTS(XtCWQueryOnly)) return XtGeometryYes;
+
+ if (WANTS(CWWidth)) w->core.width = desired->width;
+ if (WANTS(CWHeight)) w->core.height = desired->height;
+ if (WANTS(CWX)) w->core.x = desired->x;
+ if (WANTS(CWY)) w->core.y = desired->y;
+ if (WANTS(CWBorderWidth)) {
+ w->core.border_width = desired->border_width;
+ }
+
+ return XtGeometryYes;
+#undef WANTS
+}
+
+static void ChangeManaged(Widget w)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
+
+ w->core.width = fsb->composite.children[0]->core.width;
+ w->core.height = fsb->composite.children[0]->core.height;
+}
+
+static void SetFontName(
+ Widget w,
+ String name,
+ Bool name_multiple)
+{
+ XtVaSetValues(w, XtNfontName, name, XtNuseFontName, True,
+ XtNfontNameMultiple, name_multiple, NULL);
+}
+
+void FSBSetFontName(
+ Widget w,
+ String name,
+ Bool name_multiple)
+{
+ XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
+
+ (*((FontSelectionBoxWidgetClass) XtClass(w))->fsb_class.set_font_name)
+ (w, name, name_multiple);
+}
+
+static void SetFontFamilyFace(
+ Widget w,
+ String family, String face,
+ Bool family_multiple, Bool face_multiple)
+{
+ XtVaSetValues(w, XtNfontFamily, family, XtNfontFace, face,
+ XtNuseFontName, False,
+ XtNfontFamilyMultiple, family_multiple,
+ XtNfontFaceMultiple, face_multiple, NULL);
+}
+
+void FSBSetFontFamilyFace(
+ Widget w,
+ String family, String face,
+ Bool family_multiple, Bool face_multiple)
+{
+ XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
+
+ (*((FontSelectionBoxWidgetClass)
+ XtClass(w))->fsb_class.set_font_family_face)
+ (w, family, face, family_multiple, face_multiple);
+}
+
+static void SetFontSize(
+ Widget w,
+ double size,
+ Bool size_multiple)
+{
+ int i;
+ Arg args[2];
+
+ union {
+ int i;
+ float f;
+ } kludge;
+
+ kludge.f = size;
+
+ i = 0;
+ if (sizeof(float) > sizeof(XtArgVal)) {
+ XtSetArg(args[i], XtNfontSize, &kludge.f); i++;
+ } else XtSetArg(args[i], XtNfontSize, kludge.i); i++;
+ XtSetArg(args[i], XtNfontSizeMultiple, size_multiple); i++;
+ XtSetValues(w, args, i);
+}
+
+void FSBSetFontSize(
+ Widget w,
+ double size,
+ Bool size_multiple)
+{
+ XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
+
+ (*((FontSelectionBoxWidgetClass) XtClass(w))->fsb_class.set_font_size)
+ (w, size, size_multiple);
+}
+
+static void RefreshFontList(Widget w)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
+
+ UndefUnusedFonts((Widget)fsb);
+ fsb->fsb.pending_delete_font = NULL;
+ fsb->fsb.pending_delete_count = 0;
+ FreeFontLists(fsb);
+ FreePSResourceStorage(True);
+ GetFontNames(fsb);
+ DisplayFontFamilies(fsb);
+ SetUpCurrentSelections(fsb);
+}
+
+void FSBRefreshFontList(
+ Widget w)
+{
+ XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
+
+ (*((FontSelectionBoxWidgetClass)
+ XtClass(w))->fsb_class.refresh_font_list) (w);
+}
+
+static void GetFamilyList(
+ Widget w,
+ int *count,
+ String **list)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
+ String *buf;
+ FontFamilyRec *ff;
+
+ *count = fsb->fsb.family_count;
+ *list = buf = (String *) XtMalloc(*count * sizeof(String));
+
+ for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
+ *buf++ = ff->family_name;
+ }
+}
+
+void FSBGetFamilyList(
+ Widget w,
+ int *count,
+ String **list)
+{
+ XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
+
+ (*((FontSelectionBoxWidgetClass)
+ XtClass(w))->fsb_class.get_family_list) (w, count, list);
+}
+
+static void GetFaceList(
+ Widget w,
+ String family,
+ int *count,
+ String **face_list, String **font_list)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
+ String *buf1, *buf2;
+ FontFamilyRec *ff;
+ FontRec *f;
+
+ family = Canonical(family);
+ for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
+ if (ff->family_name == family) break;
+ }
+
+ if (ff == NULL) {
+ *count = 0;
+ *face_list = *font_list = NULL;
+ return;
+ }
+
+ *count = ff->font_count;
+ *face_list = buf1 = (String *) XtMalloc(*count * sizeof(String));
+ *font_list = buf2 = (String *) XtMalloc(*count * sizeof(String));
+
+ for (f = ff->fonts; f != NULL; f = f->next) {
+ *buf1++ = f->face_name;
+ *buf2++ = f->font_name;
+ }
+}
+
+void FSBGetFaceList(
+ Widget w,
+ String family,
+ int *count_return,
+ String **face_list, String **font_list)
+{
+ XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
+
+ (*((FontSelectionBoxWidgetClass)
+ XtClass(w))->fsb_class.get_face_list) (w, family, count_return,
+ face_list, font_list);
+}
+
+void FSBUndefineUnusedFonts(
+ Widget w)
+{
+ XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
+
+ (*((FontSelectionBoxWidgetClass)
+ XtClass(w))->fsb_class.undef_unused_fonts) (w);
+}
+
+static Boolean DownloadFontName(Widget w, String name)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
+ FontFamilyRec *ff;
+ FontRec *f;
+ Boolean ret;
+
+ name = Canonical(name);
+ for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
+ for (f = ff->fonts; f != NULL; f = f->next) {
+ if (f->font_name == name) {
+ if (!fsb->fsb.get_server_fonts) {
+ int resident;
+ _DPSFIsFontResident(fsb->fsb.context, f->font_name,
+ &resident);
+ if (resident) f->resident = True;
+ }
+ if (f->resident) return True;
+ else {
+ ret = DownloadFont(fsb, name, fsb->fsb.context,
+ fsb->fsb.make_fonts_shared);
+ if (fsb->fsb.make_fonts_shared && ret) f->resident = True;
+ return ret;
+ }
+ }
+ }
+ }
+
+ return DownloadFont(fsb, name, fsb->fsb.context,
+ fsb->fsb.make_fonts_shared);
+}
+
+Boolean FSBDownloadFontName(
+ Widget w,
+ String name)
+{
+ XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
+
+ if (name == NULL) return False;
+ return (*((FontSelectionBoxWidgetClass)
+ XtClass(w))->fsb_class.download_font_name) (w, name);
+}
+
+static Boolean MatchFontFace(
+ Widget w,
+ String old_face, String new_family,
+ String *new_face)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
+ FSBFaceSelectCallbackRec rec;
+ String *faces;
+ int i;
+ FontFamilyRec *ff;
+ FontRec *f;
+ Boolean retVal;
+
+ new_family = Canonical(new_family);
+ old_face = Canonical(old_face);
+ for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
+ if (ff->family_name == new_family) break;
+ }
+ if (ff == NULL) {
+ *new_face = NULL;
+ return False;
+ }
+
+ faces = (String *) XtMalloc(ff->font_count * sizeof(String));
+ i = 0;
+ for (f = ff->fonts; f != NULL; f = f->next) faces[i++] = f->face_name;
+
+ rec.available_faces = faces;
+ rec.num_available_faces = ff->font_count;
+ rec.current_face = old_face;
+ rec.new_face = NULL;
+
+ i = MatchFaceName(&rec, &retVal);
+ *new_face = faces[i];
+ XtFree((XtPointer) faces);
+ return !retVal;
+}
+
+Boolean FSBMatchFontFace(
+ Widget w,
+ String old_face, String new_family,
+ String *new_face)
+{
+ XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
+
+ return (*((FontSelectionBoxWidgetClass)
+ XtClass(w))->fsb_class.match_font_face) (w, old_face,
+ new_family, new_face);
+}
+
+static void FontNameToFamilyFaceBlend(
+ Widget w,
+ String font_name,
+ String *family, String *face, String *blend)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
+ FontFamilyRec *ff;
+ FontRec *f;
+ BlendRec *b;
+
+ font_name = Canonical(font_name);
+ for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
+ for (f = ff->fonts; f != NULL; f = f->next) {
+ if (f->font_name == font_name) {
+ *family = ff->family_name;
+ *face = f->face_name;
+ *blend = NULL;
+ return;
+ }
+ if (f->blend_data != NULL) {
+ for (b = f->blend_data->blends; b != NULL; b = b->next) {
+ if (b->font_name == font_name) {
+ *family = ff->family_name;
+ *face = f->face_name;
+ *blend = b->blend_name;
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ *family = NULL;
+ *face = NULL;
+ *blend = NULL;
+}
+
+static void FontNameToFamilyFace(
+ Widget w,
+ String font_name,
+ String *family, String *face)
+{
+ String blend;
+
+ FontNameToFamilyFaceBlend(w, font_name, family, face, &blend);
+}
+
+void FSBFontNameToFamilyFace(
+ Widget w,
+ String font_name,
+ String *family, String *face)
+{
+ XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
+
+ (*((FontSelectionBoxWidgetClass)
+ XtClass(w))->fsb_class.font_name_to_family_face) (w, font_name,
+ family, face);
+}
+
+static void FontFamilyFaceBlendToName(
+ Widget w,
+ String family, String face, String blend,
+ String *font_name)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
+ FontFamilyRec *ff;
+ FontRec *f;
+ BlendRec *b;
+
+ family = Canonical(family);
+ for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
+ if (ff->family_name == family) break;
+ }
+ if (ff == NULL) {
+ *font_name = NULL;
+ return;
+ }
+
+ face = Canonical(face);
+ for (f = ff->fonts; f != NULL; f = f->next) {
+ if (f->face_name == face) break;
+ }
+ if (f == NULL) {
+ *font_name = NULL;
+ return;
+ }
+
+ if (blend == NULL) {
+ *font_name = f->font_name;
+ return;
+ }
+ if (f->blend_data == NULL) {
+ *font_name = NULL;
+ return;
+ }
+
+ blend = Canonical(blend);
+ for (b = f->blend_data->blends; b != NULL; b = b->next) {
+ if (b->blend_name == blend) {
+ *font_name = b->font_name;
+ return;
+ }
+ }
+ *font_name = NULL;
+}
+
+static void FontFamilyFaceToName(
+ Widget w,
+ String family, String face,
+ String *font_name)
+{
+ FontFamilyFaceBlendToName(w, family, face, NULL, font_name);
+}
+
+void FSBFontFamilyFaceToName(
+ Widget w,
+ String family, String face,
+ String *font_name)
+{
+ XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
+
+ (*((FontSelectionBoxWidgetClass)
+ XtClass(w))->fsb_class.font_family_face_to_name) (w, family, face,
+ font_name);
+}
+
+String FSBFindAFM(
+ Widget w,
+ String font_name)
+{
+ XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
+
+ return (*((FontSelectionBoxWidgetClass) XtClass(w))->
+ fsb_class.find_afm) (w, font_name);
+}
+
+String FSBFindFontFile(
+ Widget w,
+ String font_name)
+{
+ XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
+
+ return (*((FontSelectionBoxWidgetClass) XtClass(w))->
+ fsb_class.find_font_file) (w, font_name);
+}
+
+static void GetTextDimensions(
+ Widget w,
+ String text, String font,
+ double size, double x, double y,
+ float *dx, float *dy, float *left, float *right, float *top, float *bottom)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
+ int bogusFont;
+
+ _DPSFGetTextDimensions(fsb->fsb.context, text, font, size, x, y,
+ dx, dy, left, right, top, bottom, &bogusFont);
+}
+
+void FSBGetTextDimensions(
+ Widget w,
+ String text, String font,
+ double size, double x, double y,
+ float *dx, float *dy, float *left, float *right, float *top, float *bottom)
+{
+ XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
+
+ (*((FontSelectionBoxWidgetClass) XtClass(w))->
+ fsb_class.get_text_dimensions) (w, text, font, size, x, y,
+ dx, dy, left, right, top, bottom);
+}
+
+static void SetFontFamilyFaceBlend(
+ Widget w,
+ String family,
+ String face,
+ String blend,
+ Bool family_multiple,
+ Bool face_multiple)
+{
+ XtVaSetValues(w, XtNfontFamily, family, XtNfontFace, face,
+ XtNfontBlend, blend, XtNuseFontName, False,
+ XtNfontFamilyMultiple, family_multiple,
+ XtNfontFaceMultiple, face_multiple, NULL);
+}
+
+void FSBSetFontFamilyFaceBlend(
+ Widget w,
+ String font_family,
+ String font_face,
+ String font_blend,
+ Bool font_family_multiple,
+ Bool font_face_multiple)
+{
+ XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
+
+ (*((FontSelectionBoxWidgetClass) XtClass(w))->
+ fsb_class.set_font_family_face_blend) (w, font_family, font_face,
+ font_blend,
+ font_family_multiple,
+ font_face_multiple);
+}
+
+void FSBFontNameToFamilyFaceBlend(
+ Widget w,
+ String font_name,
+ String *family,
+ String *face,
+ String *blend)
+{
+ XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
+
+ (*((FontSelectionBoxWidgetClass) XtClass(w))->
+ fsb_class.font_name_to_family_face_blend) (w, font_name, family,
+ face, blend);
+}
+
+void FSBFontFamilyFaceBlendToName(
+ Widget w,
+ String family,
+ String face,
+ String blend,
+ String *font_name)
+{
+ XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
+
+ (*((FontSelectionBoxWidgetClass) XtClass(w))->
+ fsb_class.font_family_face_blend_to_name) (w, family, face,
+ blend, font_name);
+}
+
+static void GetBlendList(
+ Widget w,
+ String name,
+ int *count_return,
+ String **blend_return,
+ String **font_name_return,
+ float **axis_values_return)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
+ String *buf1, *buf2;
+ float *buf3;
+ FontFamilyRec *ff;
+ FontRec *f;
+ BlendRec *b;
+ int i;
+
+ name = Canonical(name);
+ for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
+ for (f = ff->fonts; f != NULL; f = f->next) {
+ if (f->font_name == name) break;
+ }
+ }
+
+ if (ff == NULL || f == NULL || f->blend_data == NULL) {
+ *count_return = 0;
+ *blend_return = *font_name_return = NULL;
+ *axis_values_return = NULL;
+ return;
+ }
+
+ *count_return = f->blend_count;
+ *blend_return = buf1 = (String *) XtMalloc(*count_return * sizeof(String));
+ *font_name_return = buf2 =
+ (String *) XtMalloc(*count_return * sizeof(String));
+ *axis_values_return = buf3 =
+ (float *) XtMalloc(*count_return * MAX_AXES * sizeof(float));
+
+
+ for (b = f->blend_data->blends; b != NULL; b = b->next) {
+ *buf1++ = b->blend_name;
+ *buf2++ = b->font_name;
+ for (i = 0; i < MAX_AXES; i++) *buf3++ = b->data[i];
+ }
+}
+
+void FSBGetBlendList(
+ Widget w,
+ String name,
+ int *count_return,
+ String **blend_return,
+ String **font_name_return,
+ float **axis_values_return)
+{
+ XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
+
+ (*((FontSelectionBoxWidgetClass) XtClass(w))->
+ fsb_class.get_blend_list) (w, name, count_return, blend_return,
+ font_name_return, axis_values_return);
+}
+
+static void GetBlendInfo(
+ Widget w,
+ String name,
+ int *num_axes_return,
+ int *num_designs_return,
+ String **axis_names_return,
+ float **blend_positions_return,
+ int **blend_map_count_return,
+ int **blend_design_coords_return,
+ float **blend_normalized_coords_return)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
+ FontFamilyRec *ff;
+ FontRec *f;
+ BlendDataRec *bd;
+ int i, j;
+ float *fbuf;
+ int *ibuf;
+ String *sbuf;
+ int coords;
+
+ name = Canonical(name);
+ if (fsb->fsb.currently_selected_face->font_name == name) {
+ bd = fsb->fsb.currently_selected_face->blend_data;
+ } else {
+
+ for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
+ for (f = ff->fonts; f != NULL; f = f->next) {
+ if (f->font_name == name) goto FOUND_IT;
+ }
+ }
+ *num_axes_return = *num_designs_return = 0;
+ *axis_names_return = NULL;
+ *blend_positions_return = *blend_normalized_coords_return = NULL;
+ *blend_map_count_return = *blend_design_coords_return = NULL;
+ return;
+
+FOUND_IT:
+ bd = f->blend_data;
+ }
+
+ *num_axes_return = bd->num_axes;
+ *num_designs_return = bd->num_designs;
+
+ *axis_names_return = sbuf =
+ (String *) XtMalloc(bd->num_axes * sizeof(String));
+ *blend_map_count_return = ibuf =
+ (int *) XtMalloc(bd->num_axes * sizeof(int));
+ coords = 0;
+ for (i = 0; i < bd->num_axes; i++) {
+ *sbuf++ = bd->name[i];
+ *ibuf++ = bd->internal_points[i] + 2;
+ coords += bd->internal_points[i] + 2;
+ }
+
+ *blend_positions_return = fbuf =
+ (float *) XtMalloc(bd->num_axes * bd->num_designs * sizeof(float));
+ for (i = 0; i < bd->num_axes * bd->num_designs; i++) {
+ *fbuf++ = bd->design_positions[i];
+ }
+
+ *blend_design_coords_return = ibuf =
+ (int *) XtMalloc(coords * sizeof(int));
+ *blend_normalized_coords_return = fbuf =
+ (float *) XtMalloc(coords * sizeof(float));
+
+ for (i = 0; i < bd->num_axes; i++) {
+ *ibuf++ = bd->min[i];
+ *fbuf++ = 0.0;
+ for (j = 0; j < bd->internal_points[i]; j++) {
+ *ibuf++ = bd->internal_break[i][j];
+ *fbuf++ = bd->internal_value[i][j];
+ }
+ *ibuf++ = bd->max[i];
+ *fbuf++ = 1.0;
+ }
+}
+
+void FSBGetBlendInfo(
+ Widget w,
+ String name,
+ int *num_axes_return,
+ int *num_designs_return,
+ String **axis_names_return,
+ float **blend_positions_return,
+ int **blend_map_count_return,
+ int **blend_design_coords_return,
+ float **blend_normalized_coords_return)
+{
+ XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
+
+ (*((FontSelectionBoxWidgetClass) XtClass(w))->
+ fsb_class.get_blend_info) (w, name, num_axes_return,
+ num_designs_return, axis_names_return,
+ blend_positions_return,
+ blend_map_count_return,
+ blend_design_coords_return,
+ blend_normalized_coords_return);
+}
+
+static Boolean ChangeBlends(
+ Widget w,
+ String base_name,
+ String blend_name,
+ FSBBlendAction action,
+ int *axis_values,
+ float *axis_percents)
+{
+ FontSelectionBoxWidget fsb = (FontSelectionBoxWidget) w;
+ FontFamilyRec *ff;
+ FontRec *f;
+ BlendRec *b = NULL, *newb, **lastb;
+ BlendDataRec *bd;
+ String spaceBlend;
+ int val[4];
+ float pct[4];
+ int i;
+
+ base_name = Canonical(base_name);
+ blend_name = Canonical(blend_name);
+
+ for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
+ for (f = ff->fonts; f != NULL; f = f->next) {
+ if (f->font_name == base_name) {
+ if ((bd = f->blend_data) == NULL) return False;
+
+ for (b = f->blend_data->blends; b != NULL; b = b->next) {
+ if (b->blend_name == blend_name) break;
+ }
+ goto FOUND_BASE;
+ }
+ }
+ }
+ return False;
+
+FOUND_BASE:
+ if (action != FSBDeleteBlend) {
+ if (axis_values != NULL) {
+ for (i = 0; i < bd->num_axes; i++) {
+ val[i] = axis_values[i];
+ pct[i] = _FSBNormalize(val[i], bd, i);
+ }
+ for (/**/; i < 4; i++) pct[i] = 0.0;
+ } else {
+ if (axis_percents == NULL) return False;
+ for (i = 0; i < bd->num_axes; i++) {
+ pct[i] = axis_percents[i];
+ val[i] = _FSBUnnormalize(pct[i], bd, i);
+ }
+ for (/**/; i < 4; i++) pct[i] = 0.0;
+ }
+ }
+
+ switch (action) {
+ case FSBAddBlend:
+ if (b != NULL) return False;
+ newb = XtNew(BlendRec);
+ newb->blend_name = blend_name;
+ newb->CS_blend_name = CS(blend_name, (Widget) fsb);
+
+ spaceBlend = (char *) XtMalloc(strlen(blend_name) + 4);
+ spaceBlend[0] = spaceBlend[1] = spaceBlend[2] = ' ';
+ strcpy(spaceBlend+3, blend_name);
+ newb->CS_space_blend_name = CS(spaceBlend, (Widget) fsb);
+ XtFree((XtPointer) spaceBlend);
+
+ for (i = 0; i < MAX_AXES; i++) newb->data[i] = pct[i];
+ newb->font_name = _FSBGenFontName(base_name, val, bd);
+
+ f->blend_count++;
+ ff->blend_count++;
+
+ lastb = &bd->blends;
+ for (b = bd->blends; b != NULL; b = b->next) {
+ if (strcmp(blend_name, b->blend_name) < 0) break;
+ lastb = &b->next;
+ }
+
+ newb->next = b;
+ *lastb = newb;
+ break;
+
+ case FSBReplaceBlend:
+ if (b == NULL) return False;
+
+ for (i = 0; i < MAX_AXES; i++) b->data[i] = pct[i];
+ b->font_name = _FSBGenFontName(base_name, val, bd);
+ if (b == fsb->fsb.currently_previewed_blend) DoPreview(fsb, False);
+
+ break;
+
+ case FSBDeleteBlend:
+ if (b == NULL) return False;
+
+ if (bd->blends == b) {
+ bd->blends = b->next;
+ } else {
+ for (newb = bd->blends; newb->next != b; newb = newb->next) {}
+ newb->next = b->next;
+ }
+
+ f->blend_count--;
+ ff->blend_count--;
+
+ /* Don't actually delete the blend record, in case it's displayed
+ in the sampler. */
+ break;
+ }
+ if (f->in_font_creator) _FSBSetCreatorFamily(fsb->fsb.creator, ff);
+ if (ff == fsb->fsb.currently_selected_family) SetUpFaceList(fsb, ff);
+ fsb->fsb.blends_changed = True;
+ WriteBlends(fsb);
+ return True;
+}
+
+Boolean FSBChangeBlends(
+ Widget w,
+ String base_name,
+ String blend_name,
+ FSBBlendAction action,
+ int *axis_values,
+ float *axis_percents)
+{
+ XtCheckSubclass(w, fontSelectionBoxWidgetClass, NULL);
+
+ return (*((FontSelectionBoxWidgetClass) XtClass(w))->
+ fsb_class.change_blends) (w, base_name, blend_name, action,
+ axis_values, axis_percents);
+}
+
+void _FSBSetCurrentFont(
+ FontSelectionBoxWidget fsb,
+ String name)
+{
+ FontFamilyRec *ff;
+ FontRec *f;
+ BlendRec *b;
+ int i, j;
+
+ fsb->fsb.current_family_multiple = False;
+ fsb->fsb.current_face_multiple = False;
+ UnmanageFamilyMultiple(fsb);
+ UnmanageFaceMultiple(fsb);
+
+ name = Canonical(name);
+ i = 1;
+ for (ff = fsb->fsb.known_families; ff != NULL; ff = ff->next) {
+ j = 1;
+ for (f = ff->fonts; f != NULL; f = f->next) {
+ if (f->font_name == name) {
+ b = NULL;
+ goto FOUND_NAME;
+ }
+ j++;
+ if (f->blend_data != NULL && f->blend_data->blends != NULL) {
+ for (b = f->blend_data->blends; b != NULL; b = b->next) {
+ if (b->font_name == name) {
+ goto FOUND_NAME;
+ }
+ j++;
+ }
+ }
+
+ }
+ i++;
+ }
+ return;
+FOUND_NAME:
+ SetUpFaceList(fsb, ff);
+ ListSelectPos(fsb->fsb.family_scrolled_list_child, i, False);
+ ListSelectPos(fsb->fsb.face_scrolled_list_child, j, False);
+ fsb->fsb.currently_selected_face = f;
+ fsb->fsb.currently_selected_family = ff;
+ fsb->fsb.currently_selected_blend = b;
+ SensitizeReset(fsb);
+ DoPreview(fsb, False);
+}
+
+float _FSBNormalize(
+ int val,
+ BlendDataRec *bd,
+ int i)
+{
+ int j;
+ int lessBreak, moreBreak;
+ float lessValue, moreValue;
+
+ if (bd->internal_points[i] == 0) {
+ return ((float) (val - bd->min[i])) /
+ ((float) (bd->max[i] - bd->min[i]));
+ }
+
+ /* Find the largest breakpoint less than val and the smallest one greater
+ than it */
+
+ lessBreak = bd->min[i];
+ lessValue = 0.0;
+ moreBreak = bd->max[i];
+ moreValue = 1.0;
+
+ for (j = 0; j < bd->internal_points[i]; j++) {
+ if (bd->internal_break[i][j] > lessBreak &&
+ bd->internal_break[i][j] <= val) {
+ lessBreak = bd->internal_break[i][j];
+ lessValue = bd->internal_value[i][j];
+ }
+ if (bd->internal_break[i][j] < moreBreak &&
+ bd->internal_break[i][j] >= val) {
+ moreBreak = bd->internal_break[i][j];
+ moreValue = bd->internal_value[i][j];
+ }
+ }
+
+ if (moreBreak == lessBreak) return moreValue;
+
+ return lessValue + (moreValue - lessValue) *
+ ((float) (val - lessBreak)) / ((float) (moreBreak - lessBreak));
+}
+
+int _FSBUnnormalize(val, bd, i)
+ float val;
+ BlendDataRec *bd;
+ int i;
+{
+ int j;
+ int lessBreak, moreBreak;
+ float lessValue, moreValue;
+
+ if (bd->internal_points[i] == 0) {
+ return val * (bd->max[i] - bd->min[i]) + bd->min[i] + 0.5;
+ }
+
+ /* Find the largest breakpoint less than val and the smallest one greater
+ than it */
+
+ lessBreak = bd->min[i];
+ lessValue = 0.0;
+ moreBreak = bd->max[i];
+ moreValue = 1.0;
+
+ for (j = 0; j < bd->internal_points[i]; j++) {
+ if (bd->internal_value[i][j] > lessValue &&
+ bd->internal_value[i][j] <= val) {
+ lessBreak = bd->internal_break[i][j];
+ lessValue = bd->internal_value[i][j];
+ }
+ if (bd->internal_value[i][j] < moreBreak &&
+ bd->internal_value[i][j] >= val) {
+ moreBreak = bd->internal_break[i][j];
+ moreValue = bd->internal_value[i][j];
+ }
+ }
+
+ if (moreBreak == lessBreak) return moreBreak;
+
+ return ((float) (val - lessValue)) / ((float) (moreValue - lessValue)) *
+ (moreBreak - lessBreak) + lessBreak + 0.5;
+}
+
+String _FSBGenFontName(
+ String name,
+ int *val,
+ BlendDataRec *bd)
+{
+ char nameBuf[256];
+ int i;
+ char *ch;
+
+ strcpy(nameBuf, name);
+ ch = nameBuf + strlen(nameBuf);
+
+ for (i = 0; i < bd->num_axes; i++) {
+ sprintf(ch, "_%d_%s", val[i], bd->name[i]);
+ ch = ch + strlen(ch);
+ }
+
+ return Canonical(nameBuf);
+}
diff --git a/nx-X11/lib/dpstk/FontSBI.h b/nx-X11/lib/dpstk/FontSBI.h
new file mode 100644
index 000000000..87d59df40
--- /dev/null
+++ b/nx-X11/lib/dpstk/FontSBI.h
@@ -0,0 +1,57 @@
+/*
+ * FontSBI.h
+ *
+ * (c) Copyright 1991-1994 Adobe Systems Incorporated.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sublicense this software
+ * and its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notices appear in all copies and that
+ * both those copyright notices and this permission notice appear in
+ * supporting documentation and that the name of Adobe Systems Incorporated
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. No trademark license
+ * to use the Adobe trademarks is hereby granted. If the Adobe trademark
+ * "Display PostScript"(tm) is used to describe this software, its
+ * functionality or for any other purpose, such use shall be limited to a
+ * statement that this software works in conjunction with the Display
+ * PostScript system. Proper trademark attribution to reflect Adobe's
+ * ownership of the trademark shall be given whenever any such reference to
+ * the Display PostScript system is made.
+ *
+ * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
+ * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
+ * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
+ * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
+ * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
+ *
+ * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+ * Incorporated which may be registered in certain jurisdictions
+ *
+ * Author: Adobe Systems Incorporated
+ */
+/* $XFree86$ */
+
+#ifndef _FontSelectionBoxI_H
+#define _FontSelectionBoxI_H
+
+extern Widget _FSBCreateFontSampler(FontSelectionBoxWidget fsb);
+extern Boolean _FSBDownloadFontIfNecessary(FontRec *f,
+ FontSelectionBoxWidget fsb);
+extern XmString _FSBCreateSharedCS(String str, Widget w);
+extern void _FSBSetCreatorFamily(Widget w, FontFamilyRec *ff);
+extern void _FSBSetUpFaceList(FontSelectionBoxWidget fsb, Bool redisplay);
+extern void _FSBBogusFont(FontSelectionBoxWidget fsb, FontRec *f);
+extern void _FSBFlushFont(FontSelectionBoxWidget fsb, FontRec *f);
+extern void _FSBSetCurrentFont(FontSelectionBoxWidget fsb, String name);
+extern float _FSBNormalize(int val, BlendDataRec *bd, int i);
+extern int _FSBUnnormalize(double val, BlendDataRec *bd, int i);
+extern String _FSBGenFontName(String name, int *val, BlendDataRec *bd);
+
+#endif /* _FontSelectionBoxI_H */
+/* DON'T ADD ANYTHING AFTER THIS #endif */
diff --git a/nx-X11/lib/dpstk/FontSample.c b/nx-X11/lib/dpstk/FontSample.c
new file mode 100644
index 000000000..9bccdf30d
--- /dev/null
+++ b/nx-X11/lib/dpstk/FontSample.c
@@ -0,0 +1,1814 @@
+/*
+ * FontSample.c
+ *
+ * (c) Copyright 1991-1994 Adobe Systems Incorporated.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sublicense this software
+ * and its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notices appear in all copies and that
+ * both those copyright notices and this permission notice appear in
+ * supporting documentation and that the name of Adobe Systems Incorporated
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. No trademark license
+ * to use the Adobe trademarks is hereby granted. If the Adobe trademark
+ * "Display PostScript"(tm) is used to describe this software, its
+ * functionality or for any other purpose, such use shall be limited to a
+ * statement that this software works in conjunction with the Display
+ * PostScript system. Proper trademark attribution to reflect Adobe's
+ * ownership of the trademark shall be given whenever any such reference to
+ * the Display PostScript system is made.
+ *
+ * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
+ * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
+ * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
+ * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
+ * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
+ *
+ * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+ * Incorporated which may be registered in certain jurisdictions
+ *
+ * Author: Adobe Systems Incorporated
+ */
+/* $XFree86$ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <X11/Xos.h>
+#include <stdlib.h>
+#include <math.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <Xm/Xm.h>
+
+/* There are no words to describe how I feel about having to do this */
+
+#if XmVersion > 1001
+#include <Xm/ManagerP.h>
+#else
+#include <Xm/XmP.h>
+#endif
+
+#include <Xm/Form.h>
+#include <Xm/List.h>
+#include <Xm/Label.h>
+#include <Xm/LabelG.h>
+#include <Xm/PushB.h>
+#include <Xm/PanedW.h>
+#include <Xm/PushBG.h>
+#include <Xm/SeparatoG.h>
+#include <Xm/TextF.h>
+#include <Xm/RowColumn.h>
+#include <Xm/DrawingA.h>
+#include <Xm/ScrolledW.h>
+#include <Xm/ToggleBG.h>
+#include <Xm/Frame.h>
+#include <Xm/RowColumn.h>
+#include <DPS/dpsXclient.h>
+#include <DPS/dpsops.h>
+#include <DPS/dpsXcommon.h>
+#include <DPS/dpsXshare.h>
+#include <DPS/FontSBP.h>
+#include "FSBwraps.h"
+#include "FontSBI.h"
+#include <DPS/FontSamplP.h>
+
+#if 0
+/* This is not in Xos.h for some reason */
+char *strstr();
+#endif
+
+#undef MAX
+#define MAX(x,y) ((x) > (y) ? (x) : (y))
+
+#define UnsharedCS(str) XmStringCreate(str, XmSTRING_DEFAULT_CHARSET)
+
+static float defaultSizeList[] = {
+#ifndef SAMPLER_DEFAULT_SIZE_LIST
+ 8, 10, 12, 14, 16, 18, 24, 36, 48, 72
+#else
+ SAMPLER_DEFAULT_SIZE_LIST
+#endif /* DEFAULT_SIZE_LIST */
+};
+
+#ifndef SAMPLER_DEFAULT_SIZE_LIST_COUNT
+#define SAMPLER_DEFAULT_SIZE_LIST_COUNT 10
+#endif /* DEFAULT_SIZE_LIST_COUNT */
+
+#ifndef SAMPLER_DEFAULT_SIZE
+#define SAMPLER_DEFAULT_SIZE 24.0
+#endif /* SAMPLER_DEFAULT_SIZE */
+
+static Boolean DisplayAllWorkProc(XtPointer client_data);
+static Boolean DisplaySelectedWorkProc(XtPointer client_data);
+static Boolean DisplaySelectedFamilyWorkProc(XtPointer client_data);
+static Boolean DisplayFilteredWorkProc(XtPointer client_data);
+
+#define Offset(field) XtOffsetOf(FontSamplerRec, sampler.field)
+
+static XtResource resources[] = {
+ {XtNsizes, XtCSizes, XtRFloatList, sizeof(float*),
+ Offset(sizes), XtRImmediate, (XtPointer) defaultSizeList},
+ {XtNsizeCount, XtCSizeCount, XtRInt, sizeof(int),
+ Offset(size_count), XtRImmediate,
+ (XtPointer) SAMPLER_DEFAULT_SIZE_LIST_COUNT},
+ {XtNdismissCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
+ Offset(dismiss_callback), XtRCallback, (XtPointer) NULL},
+ {XtNfontSelectionBox, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(fsb), XtRWidget, (XtPointer) NULL},
+ {XtNminimumWidth, XtCMinimumWidth, XtRDimension, sizeof(Dimension),
+ Offset(minimum_width), XtRImmediate, (XtPointer) 100},
+ {XtNminimumHeight, XtCMinimumHeight, XtRDimension, sizeof(Dimension),
+ Offset(minimum_height), XtRImmediate, (XtPointer) 100},
+ {XtNnoRoomMessage, XtCMessage, XmRXmString, sizeof(XmString),
+ Offset(no_room_message), XtRString,
+ "Current size is too large or panel is too small"},
+ {XtNnoFontMessage, XtCMessage, XmRXmString, sizeof(XmString),
+ Offset(no_font_message), XtRString,
+ "There are no fonts!"},
+ {XtNnoSelectedFontMessage, XtCMessage, XmRXmString, sizeof(XmString),
+ Offset(no_selected_font_message), XtRString,
+ "No font is currently selected"},
+ {XtNnoSelectedFamilyMessage, XtCMessage, XmRXmString, sizeof(XmString),
+ Offset(no_selected_family_message), XtRString,
+ "No family is currently selected"},
+ {XtNnoFamilyFontMessage, XtCMessage, XmRXmString, sizeof(XmString),
+ Offset(no_family_font_message), XtRString,
+ "Selected family has no fonts!"},
+ {XtNnoMatchMessage, XtCMessage, XmRXmString, sizeof(XmString),
+ Offset(no_match_message), XtRString,
+ "No fonts match filters"},
+ {XtNpanelChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(panel_child), XtRImmediate, (XtPointer) NULL},
+ {XtNareaChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(area_child), XtRImmediate, (XtPointer) NULL},
+ {XtNtextChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(text_child), XtRImmediate, (XtPointer) NULL},
+ {XtNfontLabelChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(font_label_child), XtRImmediate, (XtPointer) NULL},
+ {XtNscrolledWindowChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(scrolled_window_child), XtRImmediate, (XtPointer) NULL},
+ {XtNdisplayButtonChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(display_button_child), XtRImmediate, (XtPointer) NULL},
+ {XtNdismissButtonChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(dismiss_button_child), XtRImmediate, (XtPointer) NULL},
+ {XtNstopButtonChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(stop_button_child), XtRImmediate, (XtPointer) NULL},
+ {XtNclearButtonChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(clear_button_child), XtRImmediate, (XtPointer) NULL},
+ {XtNradioFrameChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(radio_frame_child), XtRImmediate, (XtPointer) NULL},
+ {XtNradioBoxChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(radio_box_child), XtRImmediate, (XtPointer) NULL},
+ {XtNallToggleChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(all_toggle_child), XtRImmediate, (XtPointer) NULL},
+ {XtNselectedToggleChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(selected_toggle_child), XtRImmediate, (XtPointer) NULL},
+ {XtNselectedFamilyToggleChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(selected_family_toggle_child), XtRImmediate, (XtPointer) NULL},
+ {XtNfilterToggleChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(filter_toggle_child), XtRImmediate, (XtPointer) NULL},
+ {XtNfilterTextChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(filter_text_child), XtRImmediate, (XtPointer) NULL},
+ {XtNfilterBoxChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(filter_box_child), XtRImmediate, (XtPointer) NULL},
+ {XtNfilterFrameChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(filter_frame_child), XtRImmediate, (XtPointer) NULL},
+ {XtNsizeLabelChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(size_label_child), XtRWidget, (XtPointer) NULL},
+ {XtNsizeTextFieldChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(size_text_field_child), XtRWidget, (XtPointer) NULL},
+ {XtNsizeOptionMenuChild, XtCReadOnly, XtRWidget, sizeof(Widget),
+ Offset(size_option_menu_child), XtRWidget, (XtPointer) NULL},
+};
+
+/* Forward declarations */
+
+static Boolean SetValues(Widget old, Widget req, Widget new, ArgList args, Cardinal *num_args);
+static XtGeometryResult GeometryManager(Widget w, XtWidgetGeometry *desired, XtWidgetGeometry *allowed);
+static void Cancel(Widget w);
+static void ChangeManaged(Widget w);
+static void ClassInitialize(void);
+static void ClassPartInitialize(WidgetClass widget_class);
+static void ClickAction(Widget widget, XEvent *event, String *params, Cardinal *num_params);
+static void Destroy(Widget widget);
+static void Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args);
+static void Resize(Widget widget);
+
+static XtActionsRec actions[] = {
+ {"FSBClickAction", ClickAction}
+};
+
+FontSamplerClassRec fontSamplerClassRec = {
+ /* Core class part */
+ {
+ /* superclass */ (WidgetClass) &xmManagerClassRec,
+ /* class_name */ "FontSampler",
+ /* widget_size */ sizeof(FontSamplerRec),
+ /* class_initialize */ ClassInitialize,
+ /* class_part_initialize */ ClassPartInitialize,
+ /* class_inited */ False,
+ /* initialize */ Initialize,
+ /* initialize_hook */ NULL,
+ /* realize */ XtInheritRealize,
+ /* actions */ actions,
+ /* num_actions */ XtNumber(actions),
+ /* resources */ resources,
+ /* num_resources */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ True,
+ /* compress_exposure */ XtExposeCompressMultiple,
+ /* compress_enterleave */ True,
+ /* visible_interest */ False,
+ /* destroy */ Destroy,
+ /* resize */ Resize,
+ /* expose */ NULL,
+ /* set_values */ SetValues,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* callback offsets */ NULL,
+ /* tm_table */ NULL,
+ /* query_geometry */ XtInheritQueryGeometry,
+ /* display_accelerator */ NULL,
+ /* extension */ NULL,
+ },
+ /* Composite class part */
+ {
+ /* geometry_manager */ GeometryManager,
+ /* change_managed */ ChangeManaged,
+ /* insert_child */ XtInheritInsertChild,
+ /* delete_child */ XtInheritDeleteChild,
+ /* extension */ NULL,
+ },
+ /* Constraint class part */
+ {
+ /* resources */ NULL,
+ /* num_resources */ 0,
+ /* constraint_size */ 0,
+ /* initialize */ NULL,
+ /* destroy */ NULL,
+ /* set_values */ NULL,
+ /* extension */ NULL,
+ },
+ /* Manager class part */
+ {
+ /* translations */ XtInheritTranslations,
+ /* syn_resources */ NULL,
+ /* num_syn_resources */ 0,
+ /* syn_constraint_resources */ NULL,
+ /* num_syn_constraint_resources */ 0,
+ /* parent_process */ XmInheritParentProcess,
+ /* extension */ NULL,
+ },
+ /* FontSampler class part */
+ {
+ /* cancel */ Cancel,
+ /* extension */ NULL,
+ }
+};
+
+WidgetClass fontSamplerWidgetClass =
+ (WidgetClass) &fontSamplerClassRec;
+
+struct _FilterRec;
+
+typedef Boolean (*MatchProc)(String name, struct _FilterRec *filter);
+
+typedef struct _FilterRec {
+ char *name;
+ char *particles[9];
+ MatchProc special;
+} FilterRec;
+
+static Boolean MatchRoman(String name, FilterRec *filter);
+static Boolean MatchMedium(String name, FilterRec *filter);
+static Boolean MatchBlack(String name, FilterRec *filter);
+
+FilterRec filters[] = {
+ {"roman", {"Roman", NULL}, MatchRoman},
+ {"italic", {"Italic", "Kursiv", "Oblique", "Slanted", NULL}},
+ {"symbol", {"Pi", "Symbol", "Logo", "Math", "Ornaments",
+ "Carta", "Sonata", "Dingbats", NULL}},
+ {"display", {"Display", "Titling", NULL}},
+ {"alternate", {"Alternate", NULL}},
+ {"expert", {"Expert", NULL}},
+ {"oldstyle", {"Oldstyle Figures", "Old Style Figures",
+ "Expert", NULL}},
+ {"smallcaps", {"Small Caps", NULL}},
+ {"swash", {"Swash", NULL}},
+ {"script", {"Script", NULL}},
+ {"separator1", { NULL}},
+ {"condensed", {"Condensed", "Compressed", "Narrow", NULL}},
+ {"extended", {"Extended", NULL}},
+ {"separator2", { NULL}},
+ {"light", {"Light", "Thin", NULL}},
+ {"book", {"Book", NULL}},
+ {"medium", {"Medium", "Normal", "Regular",
+ "Roman", NULL}, MatchMedium},
+ {"demi", {"Demi", "Semi", "Demibold", "Semibold", NULL}},
+ {"bold", {"Bold", NULL}},
+ {"black", {"Black", "Heavy", "Poster", "Scal",
+ "Ultra", NULL}, MatchBlack},
+ {"separator3", { NULL}},
+ { NULL, { NULL}}
+};
+
+#define ITALIC_FILTER 1
+#define SYMBOL_FILTER 2
+#define TYPE_FILTERS 0
+#define WIDTH_FILTERS 11
+#define WEIGHT_FILTERS 14
+
+static int class_indices[] = {TYPE_FILTERS, WIDTH_FILTERS, WEIGHT_FILTERS, -1};
+
+static void ShowLabel(FontSamplerWidget s, XmString string)
+{
+ XtVaSetValues(s->sampler.font_label_child, XmNlabelString, string, NULL);
+}
+
+static void UnhighlightFont(FontSamplerWidget s)
+{
+ DisplayedFontRec *d = s->sampler.highlighted_font;
+
+ XCopyArea(XtDisplay(s->sampler.area_child), s->sampler.pixmap,
+ XtWindow(s->sampler.area_child),
+ s->sampler.gc, d->l-1, d->t-1, d->r - d->l + 2, d->b - d->t + 2,
+ d->l-1, d->t-1);
+}
+
+static void HighlightFont(FontSamplerWidget s)
+{
+ DisplayedFontRec *d = s->sampler.highlighted_font;
+ FontRec *f = d->font;
+ BlendRec *b = d->blend;
+ String fontName;
+ int bogusFont;
+
+ if (b == NULL) fontName = f->font_name;
+ else fontName = b->font_name;
+
+ (void) _FSBDownloadFontIfNecessary(d->font, s->sampler.fsb);
+
+ XDPSSetContextGState(s->sampler.fsb->fsb.context, s->sampler.gstate);
+ DPSsetrgbcolor(s->sampler.fsb->fsb.context, 1.0, 0.0, 0.0);
+ _DPSFShowText(s->sampler.fsb->fsb.context, d->text->str,
+ fontName, d->text->size, d->x, d->y, &bogusFont);
+}
+
+/* ARGSUSED */
+
+static void ClickAction(
+ Widget widget,
+ XEvent *event,
+ String *params,
+ Cardinal *num_params)
+{
+ XButtonEvent *b = (XButtonEvent *) event;
+ DisplayedFontRec *f;
+ FontSamplerWidget s =
+ (FontSamplerWidget) XtParent(XtParent(XtParent(XtParent(widget))));
+ XmString CSname;
+ char buf[512];
+
+ if (event->type != ButtonPress) return;
+
+ if (s->sampler.current_display_info == NULL) return;
+
+ f = s->sampler.current_display_info->shown_fonts;
+
+ while (f != NULL &&
+ (b->x < f->l || b->y < f->t || b->x > f->r || b->y > f->b)) {
+ f = f->next;
+ }
+
+ if (f != NULL) {
+ if (s->sampler.highlighted_font == f) return;
+ if (s->sampler.highlighted_font != NULL) UnhighlightFont(s);
+ s->sampler.highlighted_font = f;
+ HighlightFont(s);
+ if (f->blend == NULL) CSname = UnsharedCS(f->font->full_name);
+ else {
+ sprintf(buf, "%s %s", f->font->full_name, f->blend->blend_name);
+ CSname = UnsharedCS(buf);
+ }
+ ShowLabel(s, CSname);
+ XmStringFree(CSname);
+ if (f->blend == NULL) {
+ _FSBSetCurrentFont(s->sampler.fsb, f->font->font_name);
+ } else {
+ _FSBSetCurrentFont(s->sampler.fsb, f->blend->font_name);
+ }
+ }
+}
+
+static void UpdateDisplayedFontRecs(
+ DisplayRecord *info,
+ Position newHeight,
+ Position oldHeight,
+ Position newWidth)
+{
+ float *m = info->sampler->sampler.invctm;
+ float h, w;
+ Position oldInfoHeight = info->height;
+ DisplayedFontRec *f;
+
+ info->window_height = newHeight;
+ h = newHeight;
+ w = newWidth;
+
+ info->width = (int) (m[0] * w - m[2] * h + m[4]);
+ info->height = (int) (m[1] * w - m[3] * h + m[5]);
+
+ info->y += info->height - oldInfoHeight;
+
+ for (f = info->shown_fonts; f != NULL; f = f->next) {
+ f->y += info->height - oldInfoHeight;
+ }
+}
+
+/* ARGSUSED */
+
+static void ResizeEventHandler(
+ Widget widget,
+ XtPointer clientData,
+ XEvent *event,
+ Boolean *continueToDispatch)
+{
+ Dimension clip_width, clip_height, new_width, new_height,
+ area_width, area_height;
+ int depth;
+ FontSamplerWidget s = (FontSamplerWidget) clientData;
+ Pixmap p;
+
+ if (event->type != ConfigureNotify) return;
+
+ XtVaGetValues(s->sampler.clip_widget, XtNwidth, &clip_width,
+ XtNheight, &clip_height, NULL);
+ XtVaGetValues(s->sampler.area_child, XtNwidth, &area_width,
+ XtNheight, &area_height, XtNdepth, &depth, NULL);
+
+ /* Trying to make it fit exactly causes looooping... */
+
+ new_width = clip_width-2;
+ new_height = clip_height-2;
+
+ if (clip_width < s->sampler.minimum_width) {
+ new_width = s->sampler.minimum_width;
+ }
+ if (clip_height < s->sampler.minimum_height) {
+ new_height = s->sampler.minimum_height;
+ }
+
+ if (new_height != area_height || new_width != area_width) {
+ XtVaSetValues(s->sampler.area_child, XtNwidth, new_width,
+ XtNheight, new_height, NULL);
+
+ p = XCreatePixmap(XtDisplay(s->sampler.area_child),
+ RootWindowOfScreen(XtScreen(s->sampler.area_child)),
+ new_width, new_height, depth);
+
+ if (s->sampler.gstate != 0) {
+ XDPSSetContextGState(s->sampler.fsb->fsb.context,
+ s->sampler.gstate);
+ XDPSSetContextParameters(s->sampler.fsb->fsb.context,
+ XtScreen(s->sampler.area_child), depth,
+ XtWindow(s->sampler.area_child),
+ new_height,
+ (XDPSStandardColormap *) NULL,
+ (XDPSStandardColormap *) NULL,
+ XDPSContextScreenDepth | XDPSContextDrawable |
+ XDPSContextRGBMap | XDPSContextGrayMap);
+ _DPSFReclip(s->sampler.fsb->fsb.context);
+ _DPSFGetCTM(s->sampler.fsb->fsb.context,
+ s->sampler.ctm, s->sampler.invctm);
+ XDPSUpdateContextGState(s->sampler.fsb->fsb.context,
+ s->sampler.gstate);
+ XDPSSetContextGState(s->sampler.fsb->fsb.context,
+ s->sampler.pixmap_gstate);
+ XDPSSetContextParameters(s->sampler.fsb->fsb.context,
+ (Screen *) NULL, 0,
+ p, new_height,
+ (XDPSStandardColormap *) NULL,
+ (XDPSStandardColormap *) NULL,
+ XDPSContextDrawable);
+ XDPSUpdateContextGState(s->sampler.fsb->fsb.context,
+ s->sampler.pixmap_gstate);
+
+ _DPSFClearWindow(s->sampler.fsb->fsb.context);
+ /* La di dah */
+ DPSWaitContext(s->sampler.fsb->fsb.context);
+ XCopyArea(XtDisplay(s), s->sampler.pixmap, p,
+ s->sampler.gc, 0, 0, new_width, new_height, 0, 0);
+ }
+ XFreePixmap(XtDisplay(s), s->sampler.pixmap);
+ s->sampler.pixmap = p;
+ UpdateDisplayedFontRecs(s->sampler.current_display_info,
+ new_height, area_height, new_width);
+ }
+}
+
+static void ClassInitialize(void)
+{
+ XtInitializeWidgetClass(fontSelectionBoxWidgetClass);
+}
+
+static void ClassPartInitialize(WidgetClass widget_class)
+{
+ register FontSamplerWidgetClass wc =
+ (FontSamplerWidgetClass) widget_class;
+ FontSamplerWidgetClass super =
+ (FontSamplerWidgetClass) wc->core_class.superclass;
+
+ if (wc->sampler_class.cancel == InheritCancel) {
+ wc->sampler_class.cancel = super->sampler_class.cancel;
+ }
+}
+
+static void FreeDisplayInfo(DisplayRecord *info)
+{
+ DisplayedFontRec *f;
+ DisplayedTextRec *t;
+
+ if (info == NULL) return;
+
+ XtVaSetValues(info->sampler->sampler.font_label_child,
+ XtVaTypedArg, XmNlabelString, XtRString,
+ " ", 2, NULL);
+
+ while ((f = info->shown_fonts) != NULL) {
+ info->shown_fonts = f->next;
+ XtFree((char *) f);
+ }
+
+ while ((t = info->text_list) != NULL) {
+ info->text_list = t->next;
+ XtFree((char *) t->str);
+ XtFree((char *) t);
+ }
+
+ XtFree((char *) info);
+}
+
+static Boolean IsSet(Widget widget)
+{
+ return XmToggleButtonGadgetGetState(widget);
+}
+
+/* ARGSUSED */
+
+static void DisplayCallback(Widget widget, XtPointer clientData, XtPointer callData)
+{
+ XtAppContext app;
+ float h, w;
+ DisplayRecord *info;
+ FontSamplerWidget s = (FontSamplerWidget) clientData;
+ float *m;
+ char *value;
+ DisplayedTextRec *t;
+
+ if (s->sampler.current_display_proc != None) {
+ XtRemoveWorkProc(s->sampler.current_display_proc);
+ }
+ FreeDisplayInfo(s->sampler.current_display_info);
+ s->sampler.highlighted_font = NULL;
+
+ app = XtDisplayToApplicationContext(XtDisplay(widget));
+
+ info = s->sampler.current_display_info =
+ (DisplayRecord *) XtNew(DisplayRecord);
+
+ XtVaGetValues(s->sampler.area_child,
+ XtNwidth, &info->width,
+ XtNheight, &info->window_height,
+ XtNdepth, &info->depth,
+ NULL);
+
+ if (s->sampler.gstate == 0) {
+ XDPSSetContextParameters(s->sampler.fsb->fsb.context,
+ XtScreen(s->sampler.area_child), info->depth,
+ XtWindow(s->sampler.area_child),
+ info->window_height,
+ (XDPSStandardColormap *) NULL,
+ (XDPSStandardColormap *) NULL,
+ XDPSContextScreenDepth | XDPSContextDrawable |
+ XDPSContextRGBMap | XDPSContextGrayMap);
+ DPSsetgray(s->sampler.fsb->fsb.context, 0.0);
+ XDPSCaptureContextGState(s->sampler.fsb->fsb.context,
+ &s->sampler.gstate);
+ _DPSFGetCTM(s->sampler.fsb->fsb.context,
+ s->sampler.ctm, s->sampler.invctm);
+ XDPSSetContextParameters(s->sampler.fsb->fsb.context,
+ (Screen *) NULL, 0,
+ s->sampler.pixmap, info->window_height,
+ (XDPSStandardColormap *) NULL,
+ (XDPSStandardColormap *) NULL,
+ XDPSContextDrawable);
+ DPSsetgray(s->sampler.fsb->fsb.context, 0.0);
+ XDPSCaptureContextGState(s->sampler.fsb->fsb.context,
+ &s->sampler.pixmap_gstate);
+ }
+
+ h = info->window_height;
+ w = info->width;
+
+ m = s->sampler.invctm;
+
+ info->width = (int) (m[0] * w - m[2] * h + m[4]);
+ info->height = (int) (m[1] * w - m[3] * h + m[5]);
+ info->sampler = s;
+ info->inited = info->any_shown = False;
+ info->column_width = 0;
+ info->x = 5;
+ info->y = info->height;
+ info->shown_fonts = NULL;
+
+ t = info->text_list = XtNew(DisplayedTextRec);
+ t->next = NULL;
+ value = XmTextFieldGetString(s->sampler.text_child);
+ t->str = XtNewString(value);
+
+ value = XmTextFieldGetString(s->sampler.size_text_field_child);
+
+ if (value == NULL || *value == '\0') t->size = SAMPLER_DEFAULT_SIZE;
+ else {
+ t->size = atof(value);
+ if (t->size <= 0) t->size = SAMPLER_DEFAULT_SIZE;
+ }
+
+ s->sampler.displaying = True;
+
+ XDPSSetContextGState(s->sampler.fsb->fsb.context, s->sampler.gstate);
+ _DPSFClearWindow(s->sampler.fsb->fsb.context);
+ XDPSSetContextGState(s->sampler.fsb->fsb.context,
+ s->sampler.pixmap_gstate);
+ _DPSFClearWindow(s->sampler.fsb->fsb.context);
+
+ XtSetSensitive(s->sampler.stop_button_child, True);
+
+ if (IsSet(s->sampler.all_toggle_child)) {
+ s->sampler.current_display_proc =
+ XtAppAddWorkProc(app, DisplayAllWorkProc,
+ (XtPointer) info);
+ } else if (IsSet(s->sampler.selected_toggle_child)) {
+ s->sampler.current_display_proc =
+ XtAppAddWorkProc(app, DisplaySelectedWorkProc,
+ (XtPointer) info);
+ } else if (IsSet(s->sampler.selected_family_toggle_child)) {
+ s->sampler.current_display_proc =
+ XtAppAddWorkProc(app, DisplaySelectedFamilyWorkProc,
+ (XtPointer) info);
+ } else if (IsSet(s->sampler.filter_toggle_child)) {
+ s->sampler.current_display_proc =
+ XtAppAddWorkProc(app, DisplayFilteredWorkProc,
+ (XtPointer) info);
+ }
+}
+
+static void FinishUpDisplaying(FontSamplerWidget s)
+{
+ XtSetSensitive(s->sampler.stop_button_child, False);
+ s->sampler.current_display_proc = None;
+}
+
+/* ARGSUSED */
+
+static void FilterCallback(Widget widget, XtPointer clientData, XtPointer callData)
+{
+ FontSamplerWidget s = (FontSamplerWidget) clientData;
+
+ s->sampler.filters_changed = True;
+
+ if (IsSet(s->sampler.filter_toggle_child)) return;
+
+ XmToggleButtonGadgetSetState(s->sampler.filter_toggle_child, True, True);
+
+ XmToggleButtonGadgetSetState(s->sampler.all_toggle_child, False, False);
+ XmToggleButtonGadgetSetState(s->sampler.selected_toggle_child,
+ False, False);
+ XmToggleButtonGadgetSetState(s->sampler.selected_family_toggle_child,
+ False, False);
+}
+
+/* ARGSUSED */
+
+static void TextCallback(Widget widget, XtPointer clientData, XtPointer callData)
+{
+ FontSamplerWidget s = (FontSamplerWidget) clientData;
+ DisplayedTextRec *t;
+ char *value;
+
+ if (!s->sampler.displaying) return;
+
+ t = XtNew(DisplayedTextRec);
+
+ value = XmTextFieldGetString(s->sampler.text_child);
+ t->str = XtNewString(value);
+ t->size = s->sampler.current_display_info->text_list->size;
+ t->next = s->sampler.current_display_info->text_list;
+ s->sampler.current_display_info->text_list = t;
+}
+
+/* ARGSUSED */
+
+static void StopCallback(Widget widget, XtPointer clientData, XtPointer callData)
+{
+ FontSamplerWidget s = (FontSamplerWidget) clientData;
+
+ if (s->sampler.current_display_proc == None) return;
+
+ XtRemoveWorkProc(s->sampler.current_display_proc);
+ FinishUpDisplaying(s);
+}
+
+/* ARGSUSED */
+
+static void DismissCallback(Widget widget, XtPointer clientData, XtPointer callData)
+{
+ FontSamplerWidget s = (FontSamplerWidget) clientData;
+
+ if (XtIsShell(XtParent(s))) XtPopdown(XtParent(s));
+
+ if (s->sampler.current_display_proc != None) {
+ XtRemoveWorkProc(s->sampler.current_display_proc);
+ }
+ FinishUpDisplaying(s);
+
+ XtCallCallbackList(widget, s->sampler.dismiss_callback, (XtPointer) NULL);
+}
+
+/* ARGSUSED */
+
+static void PopdownCallback(Widget widget, XtPointer clientData, XtPointer callData)
+{
+ FontSamplerWidget s =
+ (FontSamplerWidget)
+ (((CompositeWidget) widget)->composite.children[0]);
+
+ if (s->sampler.current_display_proc != None) {
+ XtRemoveWorkProc(s->sampler.current_display_proc);
+ }
+}
+
+/* ARGSUSED */
+
+static void ExposeCallback(Widget widget, XtPointer clientData, XtPointer callData)
+{
+ XmDrawingAreaCallbackStruct *da = (XmDrawingAreaCallbackStruct *) callData;
+ XExposeEvent *ev = (XExposeEvent *) da->event;
+ FontSamplerWidget s = (FontSamplerWidget) clientData;
+
+ if (ev->type != Expose || !s->sampler.displaying) return;
+
+ XCopyArea(XtDisplay(widget), s->sampler.pixmap, XtWindow(widget),
+ s->sampler.gc, ev->x, ev->y, ev->width, ev->height,
+ ev->x, ev->y);
+ if (s->sampler.highlighted_font != NULL) HighlightFont(s);
+}
+
+/* ARGSUSED */
+
+static void ClearCallback(Widget widget, XtPointer clientData, XtPointer callData)
+{
+ int j;
+ FontSamplerWidget s = (FontSamplerWidget) clientData;
+
+ for (j = 0; filters[j].name != NULL; j++) {
+ if (filters[j].particles[0] != NULL) {
+ XmToggleButtonGadgetSetState(s->sampler.filter_widgets[j],
+ False, False);
+ }
+ }
+
+ XmTextFieldSetString(s->sampler.filter_text_child, "");
+}
+
+/* ARGSUSED */
+
+static void SizeSelect(Widget widget, XtPointer clientData, XtPointer callData)
+{
+ FontSamplerWidget s = (FontSamplerWidget) clientData;
+ String value;
+ Widget option;
+ char *ch;
+ DisplayedTextRec *t;
+
+ value = XmTextFieldGetString(widget);
+
+ if (value == NULL) option = s->sampler.other_size;
+ else {
+ for (ch = value; *ch != '\0'; ch++) if (*ch == '.') *ch = '-';
+
+ option = XtNameToWidget(s->sampler.size_menu, value);
+ if (option == NULL) option = s->sampler.other_size;
+ }
+
+ XtVaSetValues(s->sampler.size_option_menu_child,
+ XmNmenuHistory, option, NULL);
+
+ if (!s->sampler.displaying) return;
+
+ t = XtNew(DisplayedTextRec);
+
+ t->str = XtNewString(s->sampler.current_display_info->text_list->str);
+ if (value == NULL || *value == '\0') t->size = SAMPLER_DEFAULT_SIZE;
+ else {
+ t->size = atof(value);
+ if (t->size <= 0) t->size = SAMPLER_DEFAULT_SIZE;
+ }
+ t->next = s->sampler.current_display_info->text_list;
+ s->sampler.current_display_info->text_list = t;
+}
+
+/* There's a problem; sometimes the change has already been made in the field,
+ and sometimes it hasn't. The times when it has seem to correspond to
+ making changes with the size option menu, so we use this disgusting
+ global flag to notice when this happens. */
+
+static Boolean changingSize = False;
+
+/* ARGSUSED */
+
+static void TextVerify(Widget widget, XtPointer clientData, XtPointer callData)
+{
+ int i;
+ XmTextVerifyPtr v = (XmTextVerifyPtr) callData;
+ char ch, *cp;
+ int decimalPoints = 0;
+
+ if (changingSize) return; /* We know what we're doing; allow it */
+
+ /* Should probably look at format field, but seems to contain garbage */
+
+ if (v->text->length == 0) return;
+
+ for (i = 0; i < v->text->length; i++) {
+ ch = v->text->ptr[i];
+ if (ch == '.') decimalPoints++;
+ else if (!isdigit(ch)) {
+ v->doit = False;
+ return;
+ }
+ }
+
+ if (decimalPoints > 1) {
+ v->doit = False;
+ return;
+ }
+
+ cp = XmTextFieldGetString(widget);
+
+ for (/**/; *cp != '\0'; cp++) {
+ if (*cp == '.') decimalPoints++;
+ }
+
+ if (decimalPoints > 1) v->doit = False;
+}
+
+/* ARGSUSED */
+
+static void SetSize(Widget widget, XtPointer clientData, XtPointer callData)
+{
+ char buf[20], *ch;
+ FontSamplerWidget s = (FontSamplerWidget) clientData;
+
+ strcpy(buf, XtName(widget));
+ for (ch = buf; *ch != '\0'; ch++) if (*ch == '-') *ch++ = '.';
+
+ changingSize = True;
+ XmTextFieldSetString(s->sampler.size_text_field_child, buf);
+ changingSize = False;
+}
+
+static void CreateSizeMenu(FontSamplerWidget s, Boolean destroyOldChildren)
+{
+ Arg args[20];
+ int i, j;
+ Widget *sizes;
+ char buf[20];
+ Widget *children;
+ Cardinal num_children;
+ XmString csName;
+ char *ch;
+
+ if (destroyOldChildren) {
+ XtVaGetValues(s->sampler.size_menu, XtNchildren, &children,
+ XtNnumChildren, &num_children, NULL);
+
+ /* Don't destroy first child ("other") */
+ for (j = 1; (Cardinal)j < num_children; j++) XtDestroyWidget(children[j]);
+
+ sizes = (Widget *) XtMalloc((s->sampler.size_count+1) *
+ sizeof(Widget));
+ sizes[0] = children[0];
+ } else {
+ i = 0;
+ sizes = (Widget *) XtMalloc((s->sampler.size_count+1) *
+ sizeof(Widget));
+ s->sampler.other_size = sizes[0] =
+ XtCreateManagedWidget("other", xmPushButtonGadgetClass,
+ s->sampler.size_menu, args, i);
+ }
+
+ for (j = 0; j < s->sampler.size_count; j++) {
+ (void) sprintf(buf, "%g", s->sampler.sizes[j]);
+ csName = UnsharedCS(buf);
+ for (ch = buf; *ch != '\0'; ch++) if (*ch == '.') *ch = '-';
+ i = 0;
+ XtSetArg(args[i], XmNlabelString, csName); i++;
+ sizes[j+1] =
+ XmCreatePushButtonGadget(s->sampler.size_menu, buf, args, i);
+ XmStringFree(csName);
+ XtAddCallback(sizes[j+1], XmNactivateCallback, SetSize, (XtPointer) s);
+ }
+ XtManageChildren(sizes, j+1);
+ XtFree((char *) sizes);
+}
+
+static void CreateFilters(FontSamplerWidget s)
+{
+ FilterRec *f;
+ int i;
+
+ s->sampler.filter_widgets =
+ (Widget *) XtCalloc(XtNumber(filters)-1, sizeof(Widget));
+
+ s->sampler.filter_flags =
+ (Boolean *) XtCalloc(XtNumber(filters)-1, sizeof(Boolean));
+
+ for (i = 0; filters[i].name != NULL; i++) {
+ f = filters+i;
+ if (f->particles[0] == NULL) {
+ s->sampler.filter_widgets[i] =
+ XtCreateManagedWidget(f->name, xmSeparatorGadgetClass,
+ s->sampler.filter_box_child,
+ (ArgList) NULL, 0);
+ } else {
+ s->sampler.filter_widgets[i] =
+ XtCreateManagedWidget(f->name, xmToggleButtonGadgetClass,
+ s->sampler.filter_box_child,
+ (ArgList) NULL, 0);
+ XtAddCallback(s->sampler.filter_widgets[i],
+ XmNvalueChangedCallback,
+ FilterCallback, (XtPointer) s);
+ }
+ }
+}
+
+static void CreateChildren(FontSamplerWidget s)
+{
+ Arg args[20];
+ int i;
+ Widget form;
+ Dimension area_width, area_height;
+ int depth;
+ Widget w, rowcol;
+
+ form = s->sampler.panel_child =
+ XtCreateManagedWidget("panel", xmFormWidgetClass,
+ (Widget) s, (ArgList) NULL, 0);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
+ s->sampler.display_button_child =
+ XtCreateManagedWidget("displayButton", xmPushButtonWidgetClass,
+ form, args, i);
+ XtAddCallback(s->sampler.display_button_child, XmNactivateCallback,
+ DisplayCallback, (XtPointer) s);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, s->sampler.display_button_child); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XtNsensitive, False); i++;
+ s->sampler.stop_button_child =
+ XtCreateManagedWidget("stopButton", xmPushButtonWidgetClass,
+ form, args, i);
+ XtAddCallback(s->sampler.stop_button_child, XmNactivateCallback,
+ StopCallback, (XtPointer) s);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, s->sampler.stop_button_child); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
+ s->sampler.dismiss_button_child =
+ XtCreateManagedWidget("dismissButton", xmPushButtonWidgetClass,
+ form, args, i);
+ XtAddCallback(s->sampler.dismiss_button_child, XmNactivateCallback,
+ DismissCallback, (XtPointer) s);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, s->sampler.dismiss_button_child); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
+ s->sampler.size_label_child =
+ XtCreateManagedWidget("sizeLabel", xmLabelWidgetClass,
+ form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, s->sampler.size_label_child); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, s->sampler.size_label_child); i++;
+ s->sampler.size_text_field_child =
+ XtCreateManagedWidget("sizeTextField",
+ xmTextFieldWidgetClass,
+ form, args, i);
+ XtAddCallback(s->sampler.size_text_field_child, XmNvalueChangedCallback,
+ SizeSelect, (XtPointer) s);
+ XtAddCallback(s->sampler.size_text_field_child, XmNmodifyVerifyCallback,
+ TextVerify, (XtPointer) NULL);
+
+ i = 0;
+ s->sampler.size_menu = XmCreatePulldownMenu(form, "sizeMenu", args, i);
+
+ CreateSizeMenu(s, False);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, s->sampler.size_text_field_child); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, s->sampler.size_label_child); i++;
+ XtSetArg(args[i], XmNsubMenuId, s->sampler.size_menu); i++;
+ s->sampler.size_option_menu_child =
+ XmCreateOptionMenu(form, "sizeOptionMenu", args, i);
+ XtManageChild(s->sampler.size_option_menu_child);
+
+ SizeSelect(s->sampler.size_text_field_child, (XtPointer) s,
+ (XtPointer) NULL);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_FORM); i++;
+ rowcol = XtCreateManagedWidget("rowColumn", xmRowColumnWidgetClass,
+ form, args, i);
+
+ i = 0;
+ s->sampler.radio_frame_child =
+ XtCreateManagedWidget("radioFrame", xmFrameWidgetClass,
+ rowcol, args, i);
+
+ i = 0;
+ s->sampler.radio_box_child = XmCreateRadioBox(s->sampler.radio_frame_child,
+ "radioBox", args, i);
+ XtManageChild(s->sampler.radio_box_child);
+
+ i = 0;
+ s->sampler.all_toggle_child =
+ XtCreateManagedWidget("allToggle", xmToggleButtonGadgetClass,
+ s->sampler.radio_box_child, args, i);
+
+ i = 0;
+ s->sampler.selected_toggle_child =
+ XtCreateManagedWidget("selectedToggle", xmToggleButtonGadgetClass,
+ s->sampler.radio_box_child, args, i);
+
+ i = 0;
+ s->sampler.selected_family_toggle_child =
+ XtCreateManagedWidget("selectedFamilyToggle",
+ xmToggleButtonGadgetClass,
+ s->sampler.radio_box_child, args, i);
+
+ i = 0;
+ s->sampler.filter_toggle_child =
+ XtCreateManagedWidget("filterToggle",
+ xmToggleButtonGadgetClass,
+ s->sampler.radio_box_child, args, i);
+
+ i = 0;
+ s->sampler.filter_frame_child =
+ XtCreateManagedWidget("filterFrame", xmFrameWidgetClass,
+ rowcol, args, i);
+
+ i = 0;
+ s->sampler.filter_box_child =
+ XtCreateManagedWidget("filterBox", xmRowColumnWidgetClass,
+ s->sampler.filter_frame_child, args, i);
+
+ CreateFilters(s);
+
+ i = 0;
+ s->sampler.filter_text_child =
+ XtCreateManagedWidget("filterText", xmTextFieldWidgetClass,
+ s->sampler.filter_box_child, args, i);
+ XtAddCallback(s->sampler.filter_text_child,
+ XmNvalueChangedCallback,
+ FilterCallback, (XtPointer) s);
+
+ i = 0;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, rowcol); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNrightWidget, rowcol); i++;
+ s->sampler.clear_button_child =
+ XtCreateManagedWidget("clearButton", xmPushButtonWidgetClass,
+ form, args, i);
+ XtAddCallback(s->sampler.clear_button_child, XmNactivateCallback,
+ ClearCallback, (XtPointer) s);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNrightWidget, rowcol); i++;
+ s->sampler.text_child =
+ XtCreateManagedWidget("text", xmTextFieldWidgetClass,
+ form, args, i);
+ XtAddCallback(s->sampler.text_child,
+ XmNvalueChangedCallback,
+ TextCallback, (XtPointer) s);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, s->sampler.text_child); i++;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNleftWidget, s->sampler.text_child); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); i++;
+ XtSetArg(args[i], XmNrightWidget, s->sampler.text_child); i++;
+ s->sampler.font_label_child =
+ XtCreateManagedWidget("fontLabel", xmLabelGadgetClass,
+ form, args, i);
+
+ i = 0;
+ XtSetArg(args[i], XmNtopAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNtopWidget, s->sampler.font_label_child); i++;
+ XtSetArg(args[i], XmNleftAttachment, XmATTACH_FORM); i++;
+ XtSetArg(args[i], XmNrightAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNrightWidget, rowcol); i++;
+ XtSetArg(args[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
+ XtSetArg(args[i], XmNbottomWidget, s->sampler.display_button_child);i++;
+ XtSetArg(args[i], XmNscrollingPolicy, XmAUTOMATIC); i++;
+ s->sampler.scrolled_window_child =
+ XtCreateManagedWidget("scrolledWindow",
+ xmScrolledWindowWidgetClass,
+ form, args, i);
+ i = 0;
+ s->sampler.area_child =
+ XtCreateManagedWidget("area", xmDrawingAreaWidgetClass,
+ s->sampler.scrolled_window_child, args, i);
+ XtAddCallback(s->sampler.area_child, XmNexposeCallback,
+ ExposeCallback, (XtPointer) s);
+
+ XtVaGetValues(s->sampler.scrolled_window_child,
+ XmNclipWindow, &s->sampler.clip_widget,
+ NULL);
+
+ /* I would like to use translations for this, but Motif overwrites the
+ clip window's translation. Grr... */
+
+ XtAddEventHandler(s->sampler.clip_widget, StructureNotifyMask, False,
+ ResizeEventHandler, (XtPointer) s);
+
+ XtVaSetValues(s->sampler.scrolled_window_child,
+ XmNworkWindow, s->sampler.area_child, NULL);
+
+ XtVaGetValues(s->sampler.area_child,
+ XtNheight, &area_height,
+ XtNwidth, &area_width,
+ XtNdepth, &depth,
+ NULL);
+
+ if (area_height < s->sampler.minimum_height ||
+ area_width < s->sampler.minimum_width) {
+ area_height = MAX(area_height, s->sampler.minimum_height);
+ area_width = MAX(area_width, s->sampler.minimum_width);
+
+ XtVaSetValues(s->sampler.area_child, XtNwidth, area_width,
+ XtNheight, area_height, NULL);
+ }
+
+ s->sampler.pixmap =
+ XCreatePixmap(XtDisplay(s->sampler.area_child),
+ RootWindowOfScreen(XtScreen(s->sampler.area_child)),
+ area_width, area_height, depth);
+
+ XtVaSetValues(form, XmNdefaultButton, s->sampler.display_button_child,
+ NULL);
+
+ s->sampler.gc = XtGetGC(s->sampler.area_child, 0, (XGCValues *) NULL);
+
+ for (w = XtParent(s); !XtIsShell(w); w = XtParent(w)) {}
+ XtAddCallback(w, XtNpopdownCallback, PopdownCallback, (XtPointer) NULL);
+}
+
+/* ARGSUSED */
+
+static void Initialize(
+ Widget request, Widget new,
+ ArgList args,
+ Cardinal *num_args)
+{
+ FontSamplerWidget sampler = (FontSamplerWidget) new;
+
+ /* Must have a fsb */
+
+ if (sampler->sampler.fsb == NULL) {
+ XtAppErrorMsg(XtWidgetToApplicationContext(new),
+ "initializeFontSampler", "noFontSelectionBox",
+ "FontSelectionBoxError",
+ "No font selection box given to font sampler",
+ (String *) NULL, (Cardinal *) NULL);
+ }
+
+ /* Verify size list */
+
+ if (sampler->sampler.size_count > 0 && sampler->sampler.sizes == NULL) {
+ XtAppWarningMsg(XtWidgetToApplicationContext(new),
+ "initializeFontSampler", "sizeMismatch",
+ "FontSelectionBoxError",
+ "Size count specified but no sizes present",
+ (String *) NULL, (Cardinal *) NULL);
+ sampler->sampler.size_count = 0;
+ }
+
+ if (sampler->sampler.size_count < 0) {
+ XtAppWarningMsg(XtWidgetToApplicationContext(new),
+ "initializeFontSampler", "negativeSize",
+ "FontSelectionBoxError",
+ "Size count should not be negative",
+ (String *) NULL, (Cardinal *) NULL);
+ sampler->sampler.size_count = 0;
+ }
+
+ /* Initialize non-resource fields */
+
+ sampler->sampler.displaying = False;
+ sampler->sampler.current_display_proc = None;
+ sampler->sampler.current_display_info = NULL;
+ sampler->sampler.gstate = sampler->sampler.pixmap_gstate = 0;
+
+ CreateChildren(sampler);
+}
+
+static void AdvanceInfoToNextFont(DisplayRecord *info)
+{
+ if (info->current_font->blend_data != NULL) {
+ if (info->current_blend == NULL) {
+ info->current_blend = info->current_font->blend_data->blends;
+ } else info->current_blend = info->current_blend->next;
+ if (info->current_blend == NULL) {
+ info->current_font = info->current_font->next;
+ }
+ } else info->current_font = info->current_font->next;
+
+ if (info->current_font == NULL) {
+ info->current_family = info->current_family->next;
+ if (info->current_family != NULL) {
+ info->current_font = info->current_family->fonts;
+ }
+ }
+}
+
+static Boolean ShowFont(DisplayRecord *info)
+{
+ float width, left, right, top, bottom;
+ FontRec *f = info->current_font;
+ BlendRec *b = info->current_blend;
+ DisplayedFontRec *d;
+ FontSamplerWidget s = info->sampler;
+ float *m;
+ DisplayedTextRec *t = info->text_list;
+ String fontName;
+ int bogusFont;
+ int oldx, oldy;
+
+ if (f == NULL) return True;
+
+ oldx = info->x;
+ oldy = info->y;
+
+ info->y -= t->size * 5 / 4;
+
+ if (info->y < 0) {
+ if (info->column_width == 0) return False;
+ info->y = info->height - (t->size * 5 / 4);
+ info->x += info->column_width + (t->size / 4);
+ if (info->x > (int) info->width) return False;
+ info->column_width = 0;
+ }
+
+ if (!_FSBDownloadFontIfNecessary(f, s->sampler.fsb)) {
+ AdvanceInfoToNextFont(info);
+ return True;
+ }
+
+ if (b == NULL) fontName = f->font_name;
+ else fontName = b->font_name;
+
+ /* Do ...AndGetDimensions on the pixmap to make sure that it's synced.
+ That way we can reliably do an XCopyArea without first doing a
+ WaitContext. */
+
+ XDPSSetContextGState(s->sampler.fsb->fsb.context, s->sampler.gstate);
+ _DPSFShowText(s->sampler.fsb->fsb.context, t->str, fontName,
+ t->size, info->x, info->y, &bogusFont);
+
+ AdvanceInfoToNextFont(info);
+
+ if (bogusFont) {
+ info->x = oldx;
+ info->y = oldy;
+
+ XCopyArea(XtDisplay(s), s->sampler.pixmap,
+ XtWindow(s->sampler.area_child),
+ s->sampler.gc, 0, 0, info->width, info->height, 0, 0);
+
+ if (info->current_font == f) {
+ /* Must be the same font, different blend */
+ info->current_font = info->current_font->next;
+
+ if (info->current_font == NULL) {
+ info->current_family = info->current_family->next;
+ if (info->current_family != NULL) {
+ info->current_font = info->current_family->fonts;
+ }
+ }
+ }
+
+ _FSBFlushFont(s->sampler.fsb, f);
+ return True;
+ }
+
+ XDPSSetContextGState(s->sampler.fsb->fsb.context,
+ s->sampler.pixmap_gstate);
+ _DPSFShowTextAndGetDimensions(s->sampler.fsb->fsb.context,
+ t->str, fontName,
+ t->size, info->x, info->y,
+ &width, &left, &right, &top, &bottom);
+
+ width = ceil(width);
+
+ if (width > (int) info->column_width) info->column_width = (int) width;
+
+ d = XtNew(DisplayedFontRec);
+
+ m = s->sampler.ctm;
+
+ d->l = (int) (m[0] * left + m[2] * top + m[4]);
+ d->r = (int) ceil(m[0] * right + m[2] * bottom + m[4]);
+ d->t = (int) ceil(m[1] * left + m[3] * top + m[5] + info->window_height);
+ d->b = (int) (m[1] * right + m[3] * bottom + m[5] + info->window_height);
+ d->x = info->x;
+ d->y = info->y;
+ d->font = f;
+ d->blend = b;
+ d->text = info->text_list;
+ d->next = info->shown_fonts;
+ info->shown_fonts = d;
+
+ return True;
+}
+
+static Boolean DisplayAllWorkProc(XtPointer client_data)
+{
+ DisplayRecord *info = (DisplayRecord *) client_data;
+ FontSamplerWidget s = info->sampler;
+
+ if (!info->inited) {
+ info->inited = True;
+ info->current_family = s->sampler.fsb->fsb.known_families;
+ info->current_font = info->current_family->fonts;
+ info->current_blend = NULL;
+ }
+
+ if (!ShowFont(info)) {
+ if (!info->any_shown) ShowLabel(s, s->sampler.no_room_message);
+ FinishUpDisplaying(s);
+ return True;
+ }
+
+ info->any_shown = True;
+ if (info->current_family == NULL) {
+ if (!info->any_shown) ShowLabel(s, s->sampler.no_font_message);
+ FinishUpDisplaying(s);
+ return True;
+ }
+ return False;
+}
+
+static Boolean DisplaySelectedWorkProc(XtPointer client_data)
+{
+ DisplayRecord *info = (DisplayRecord *) client_data;
+ FontSamplerWidget s = info->sampler;
+
+ info->current_family = s->sampler.fsb->fsb.currently_selected_family;
+ info->current_font = s->sampler.fsb->fsb.currently_selected_face;
+ info->current_blend = s->sampler.fsb->fsb.currently_selected_blend;
+
+ if (info->current_font != NULL) {
+ if (!ShowFont(info)) ShowLabel(s, s->sampler.no_room_message);
+ } else ShowLabel(s, s->sampler.no_selected_font_message);
+
+ FinishUpDisplaying(s);
+ return True;
+}
+
+static Boolean DisplaySelectedFamilyWorkProc(XtPointer client_data)
+{
+ DisplayRecord *info = (DisplayRecord *) client_data;
+ FontSamplerWidget s = info->sampler;
+ FontFamilyRec *currentFamily;
+
+ if (!info->inited) {
+ info->inited = True;
+ info->current_family = s->sampler.fsb->fsb.currently_selected_family;
+ if (info->current_family != NULL) {
+ info->current_font = info->current_family->fonts;
+ info->current_blend = NULL;
+ } else {
+ ShowLabel(s, s->sampler.no_selected_family_message);
+ FinishUpDisplaying(s);
+ return True;
+ }
+ }
+
+ currentFamily = info->current_family;
+
+ if (!ShowFont(info)) {
+ if (!info->any_shown) ShowLabel(s, s->sampler.no_room_message);
+ FinishUpDisplaying(s);
+ return True;
+ }
+
+ info->any_shown = True;
+ if (info->current_family != currentFamily) {
+ if (!info->any_shown) ShowLabel(s, s->sampler.no_family_font_message);
+ FinishUpDisplaying(s);
+ return True;
+ }
+ return False;
+}
+
+/* ARGSUSED */
+
+static Boolean MatchRoman(String name, FilterRec *filter)
+{
+ FilterRec *f;
+ char *ch, **search, *start;
+ int len;
+
+ /* Roman means not italic and not symbol */
+
+ for (f = filters + ITALIC_FILTER; f <= filters + SYMBOL_FILTER; f++) {
+ for (search = f->particles; *search != NULL; search++) {
+ start = name;
+ do {
+ ch = strstr(start, *search);
+ if (ch != NULL) {
+ len = strlen(*search);
+ if (ch[len] == ' ' || ch[len] == '\0') return False;
+ else start = ch+1;
+ }
+ } while (ch != NULL);
+ }
+ }
+ return True;
+}
+
+static Boolean MatchMedium(String name, FilterRec *filter)
+{
+ FilterRec *f;
+ char *ch, **search, *start;
+ int len;
+
+ for (search = filter->particles; *search != NULL; search++) {
+ start = name;
+ do {
+ ch = strstr(start, *search);
+ if (ch != NULL) {
+ len = strlen(*search);
+ if (ch[len] == ' ' || ch[len] == '\0') return True;
+ else start = ch+1;
+ }
+ } while (ch != NULL);
+ }
+
+ /* Also match anything that has none of the other weight particles */
+
+ for (f = filters + WEIGHT_FILTERS; f->name != NULL; f++) {
+ if (f == filter) continue;
+ for (search = f->particles; *search != NULL; search++) {
+ start = name;
+ do {
+ ch = strstr(start, *search);
+ if (ch != NULL) {
+ len = strlen(*search);
+ if (ch[len] == ' ' || ch[len] == '\0') return False;
+ else start = ch+1;
+ }
+ } while (ch != NULL);
+ }
+ }
+ return True;
+}
+
+static Boolean MatchBlack(String name, FilterRec *filter)
+{
+ char *ch, **search, *start;
+ int len;
+ Boolean ultra;
+
+ for (search = filter->particles; *search != NULL; search++) {
+ ultra = (strcmp(*search, "Ultra") == 0);
+ start = name;
+ do {
+ ch = strstr(start, *search);
+ if (ch != NULL) {
+ len = strlen(*search);
+ if (ch[len] == '\0') return True;
+ if (ch[len] == ' ') {
+ if (!ultra) return True;
+ /* Only match "Ultra" if not followed by "Compressed" or
+ "Light". We'd also like to add "Condensed" to this
+ list, but some fonts use "Ultra Condensed" to mean
+ "Ultra & Condensed" while others use it to mean "Very
+ much Condensed". Sigh... */
+ start = ch+len+1;
+ if (strncmp(start, "Compressed", 10) != 0 &&
+ strncmp(start, "Light", 5) != 0) return True;
+ else start = ch+1;
+ }
+ else start = ch+1;
+ }
+ } while (ch != NULL);
+ }
+ return False;
+}
+
+static void UpdateFilters(FontSamplerWidget s)
+{
+ int i;
+
+ for (i = 0; filters[i].name != NULL; i++) {
+ if (filters[i].particles[0] != NULL) {
+ s->sampler.filter_flags[i] = IsSet(s->sampler.filter_widgets[i]);
+ }
+ }
+
+ s->sampler.filter_text =
+ XmTextFieldGetString(s->sampler.filter_text_child);
+}
+
+static Boolean FontMatchesFilters(
+ FontRec *font,
+ BlendRec *blend,
+ FontSamplerWidget s)
+{
+ int *cl, i;
+ FilterRec *f;
+ char *ch, **search, *start;
+ int len;
+ Boolean anyset, foundone, allmatch;
+ char *name;
+ char buf[512];
+
+ if (blend != NULL) {
+ sprintf(buf, "%s %s", font->full_name, blend->blend_name);
+ name = buf;
+ } else name = font->full_name;
+
+ allmatch = False;
+ if (s->sampler.filters_changed) UpdateFilters(s);
+
+ for (cl = class_indices; *cl != -1; cl++) {
+ anyset = foundone = False;
+ for (i = *cl;
+ filters[i].particles[0] != NULL && filters[i].name != NULL; i++) {
+
+ f = filters+i;
+
+ if (!s->sampler.filter_flags[i]) continue;
+ anyset = True;
+
+ if (f->special != NULL) {
+ if ((*f->special)(name, f)) {
+ foundone = True;
+ goto NEXT_CLASS;
+ }
+ continue;
+ }
+
+ for (search = f->particles; *search != NULL; search++) {
+ start = name;
+ do {
+ ch = strstr(start, *search);
+ if (ch != NULL) {
+ len = strlen(*search);
+ if (ch[len] == ' ' || ch[len] == '\0') {
+ foundone = True;
+ goto NEXT_CLASS;
+ }
+ else start = ch+1;
+ }
+ } while (ch != NULL);
+ }
+ }
+NEXT_CLASS: ;
+ /* If there were any filters set in this class, but we didn't match,
+ return False */
+ if (anyset && !foundone) return False;
+ if (anyset && foundone) allmatch = True;
+ }
+
+ /* Now check against the text field */
+
+ if (s->sampler.filter_text == NULL || s->sampler.filter_text[0] == '\0') {
+ return allmatch;
+ }
+
+ ch = strstr(name, s->sampler.filter_text);
+
+ return (ch != NULL);
+}
+
+static Boolean DisplayFilteredWorkProc(XtPointer client_data)
+{
+ DisplayRecord *info = (DisplayRecord *) client_data;
+ FontSamplerWidget s = info->sampler;
+
+ if (!info->inited) {
+ info->inited = True;
+ info->current_family = s->sampler.fsb->fsb.known_families;
+ info->current_font = info->current_family->fonts;
+ info->current_blend = NULL;
+ s->sampler.filters_changed = True;
+ }
+
+ if (FontMatchesFilters(info->current_font, info->current_blend, s)) {
+ if (!ShowFont(info)) {
+ if (!info->any_shown) ShowLabel(s, s->sampler.no_room_message);
+ FinishUpDisplaying(s);
+ return True;
+ }
+ info->any_shown = True;
+ } else AdvanceInfoToNextFont(info);
+
+ if (info->current_font == NULL) {
+ if (!info->any_shown) ShowLabel(s, s->sampler.no_match_message);
+ FinishUpDisplaying(s);
+ return True;
+ }
+ return False;
+}
+
+static void Destroy(Widget widget)
+{
+ FontSamplerWidget s = (FontSamplerWidget) widget;
+
+ if (s->sampler.gstate != 0) {
+ XDPSFreeContextGState(s->sampler.fsb->fsb.context,
+ s->sampler.pixmap_gstate);
+ XDPSFreeContextGState(s->sampler.fsb->fsb.context, s->sampler.gstate);
+ }
+ XtReleaseGC(widget, s->sampler.gc);
+ XFreePixmap(XtDisplay(widget), s->sampler.pixmap);
+ if (s->sampler.current_display_proc != None) {
+ XtRemoveWorkProc(s->sampler.current_display_proc);
+ }
+ if (s->sampler.current_display_info != NULL) {
+ FreeDisplayInfo(s->sampler.current_display_info);
+ }
+ XtFree((char *) s->sampler.filter_widgets);
+ XtFree((char *) s->sampler.filter_flags);
+}
+
+static void Resize(Widget widget)
+{
+ FontSamplerWidget s = (FontSamplerWidget) widget;
+
+ XtResizeWidget(s->sampler.panel_child, s->core.width, s->core.height, 0);
+}
+
+/* ARGSUSED */
+
+static XtGeometryResult GeometryManager(
+ Widget w,
+ XtWidgetGeometry *desired, XtWidgetGeometry *allowed)
+{
+#define WANTS(flag) (desired->request_mode & flag)
+
+ if (WANTS(XtCWQueryOnly)) return XtGeometryYes;
+
+ if (WANTS(CWWidth)) w->core.width = desired->width;
+ if (WANTS(CWHeight)) w->core.height = desired->height;
+ if (WANTS(CWX)) w->core.x = desired->x;
+ if (WANTS(CWY)) w->core.y = desired->y;
+ if (WANTS(CWBorderWidth)) {
+ w->core.border_width = desired->border_width;
+ }
+
+ return XtGeometryYes;
+#undef WANTS
+}
+
+static void ChangeManaged(Widget w)
+{
+ FontSamplerWidget s = (FontSamplerWidget) w;
+
+ w->core.width = s->composite.children[0]->core.width;
+ w->core.height = s->composite.children[0]->core.height;
+}
+
+/* ARGSUSED */
+
+static Boolean SetValues(
+ Widget old, Widget req, Widget new,
+ ArgList args,
+ Cardinal *num_args)
+{
+ FontSamplerWidget olds = (FontSamplerWidget) old;
+ FontSamplerWidget news = (FontSamplerWidget) new;
+
+#define NE(field) news->sampler.field != olds->sampler.field
+#define DONT_CHANGE(field) \
+ if (NE(field)) news->sampler.field = olds->sampler.field;
+
+ DONT_CHANGE(panel_child);
+ DONT_CHANGE(area_child);
+ DONT_CHANGE(text_child);
+ DONT_CHANGE(font_label_child);
+ DONT_CHANGE(scrolled_window_child);
+ DONT_CHANGE(display_button_child);
+ DONT_CHANGE(dismiss_button_child);
+ DONT_CHANGE(stop_button_child);
+ DONT_CHANGE(clear_button_child);
+ DONT_CHANGE(radio_frame_child);
+ DONT_CHANGE(radio_box_child);
+ DONT_CHANGE(all_toggle_child);
+ DONT_CHANGE(selected_toggle_child);
+ DONT_CHANGE(selected_family_toggle_child);
+ DONT_CHANGE(filter_toggle_child);
+ DONT_CHANGE(filter_box_child);
+ DONT_CHANGE(filter_frame_child);
+ DONT_CHANGE(size_option_menu_child);
+ DONT_CHANGE(size_text_field_child);
+ DONT_CHANGE(size_label_child);
+ DONT_CHANGE(fsb);
+#undef DONT_CHANGE
+
+ if (news->sampler.size_count > 0 && news->sampler.sizes == NULL) {
+ XtAppWarningMsg(XtWidgetToApplicationContext(new),
+ "setValuesFontSampler", "sizeMismatch",
+ "FontSelectionBoxError",
+ "Size count specified but no sizes present",
+ (String *) NULL, (Cardinal *) NULL);
+ news->sampler.size_count = 0;
+ }
+
+ if (news->sampler.size_count < 0) {
+ XtAppWarningMsg(XtWidgetToApplicationContext(new),
+ "setValuesFontSampler", "negativeSize",
+ "FontSelectionBoxError",
+ "Size count should not be negative",
+ (String *) NULL, (Cardinal *) NULL);
+ news->sampler.size_count = 0;
+ }
+
+ if (NE(sizes)) CreateSizeMenu(news, True);
+
+ return False;
+#undef NE
+}
+
+static void Cancel(Widget w)
+{
+ FontSamplerWidget s = (FontSamplerWidget) w;
+
+ if (s->sampler.current_display_proc != None) {
+ XtRemoveWorkProc(s->sampler.current_display_proc);
+ }
+}
+
+void FSBCancelSampler(Widget w)
+{
+ XtCheckSubclass(w, fontSamplerWidgetClass, NULL);
+
+ (*((FontSamplerWidgetClass) XtClass(w))->sampler_class.cancel) (w);
+}
+
+#ifdef NO_STRSTR_AVAILABLE
+String strstr(String s1, String s2)
+{
+ register int len1, len2;
+
+ len1 = strlen(s1);
+ len2 = strlen(s2);
+
+ while (len1 >= len2) {
+ if (*s1 == *s2) {
+ if (strncmp(s1+1, s2+1, len2-1) == 0) return s1;
+ }
+ len1--;
+ s1++;
+ }
+}
+#endif /* NO_STRSTR_AVAILABLE */
diff --git a/nx-X11/lib/dpstk/FontSelect.ad b/nx-X11/lib/dpstk/FontSelect.ad
new file mode 100644
index 000000000..6d3440a9e
--- /dev/null
+++ b/nx-X11/lib/dpstk/FontSelect.ad
@@ -0,0 +1,415 @@
+! FontSelect
+!
+! (c) Copyright 1991-1994 Adobe Systems Incorporated.
+! All rights reserved.
+!
+! Permission to use, copy, modify, distribute, and sublicense this software
+! and its documentation for any purpose and without fee is hereby granted,
+! provided that the above copyright notices appear in all copies and that
+! both those copyright notices and this permission notice appear in
+! supporting documentation and that the name of Adobe Systems Incorporated
+! not be used in advertising or publicity pertaining to distribution of the
+! software without specific, written prior permission. No trademark license
+! to use the Adobe trademarks is hereby granted. If the Adobe trademark
+! "Display PostScript"(tm) is used to describe this software, its
+! functionality or for any other purpose, such use shall be limited to a
+! statement that this software works in conjunction with the Display
+! PostScript system. Proper trademark attribution to reflect Adobe's
+! ownership of the trademark shall be given whenever any such reference to
+! the Display PostScript system is made.
+!
+! ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
+! ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
+! ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+! IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+! NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
+! TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
+! DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
+! NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
+! CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
+! PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
+!
+! Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+! Incorporated which may be registered in certain jurisdictions
+!
+! Author: Adobe Systems Incorporated
+!
+! Resource file for Font Selection Box
+!
+! This resource file must be merged into the resource file for
+! any application that uses the Font Selection Box
+!
+!
+*FontSelectionBox*fontList: -adobe-helvetica-bold-r-normal--*-120-*-*-*-*-iso8859-1
+*FontSelectionBox*XmPushButton.marginLeft:5
+*FontSelectionBox*XmPushButton.marginRight:5
+
+*FontSelectionBox*preview.background: white
+*FontSelectionBox*preview.height: 40
+
+*FontSelectionBox*panel.width: 397
+*FontSelectionBox*panel.height: 286
+
+*FontSelectionBox*panel.horizontalSpacing: 5
+*FontSelectionBox*panel.verticalSpacing: 2
+
+*FontSelectionBox*okButton.labelString: OK
+
+*FontSelectionBox*applyButton.labelString: Apply
+
+*FontSelectionBox*resetButton.labelString: Reset
+
+*FontSelectionBox*cancelButton.labelString: Cancel
+
+*FontSelectionBox*sizeLabel.labelString: Size:
+*FontSelectionBox*sizeLabel.leftOffset: 10
+*FontSelectionBox*sizeLabel.bottomOffset: 12
+
+*FontSelectionBox*sizeTextField.columns: 4
+*FontSelectionBox*sizeTextField.leftOffset: 2
+*FontSelectionBox*sizeTextField.bottomOffset: -7
+*FontSelectionBox*sizeTextField.value: 12
+*FontSelectionBox*sizeTextField.verifyBell: False
+
+*FontSelectionBox*other.labelString: ...
+
+*FontSelectionBox*sizeOptionMenu.labelString:
+*FontSelectionBox*sizeOptionMenu.bottomOffset: -9
+*FontSelectionBox*sizeOptionMenu.leftOffset: -5
+
+*FontSelectionBox*sizeMultipleLabel.labelString: Multiple
+*FontSelectionBox*sizeMultipleLabel.leftOffset: 0
+*FontSelectionBox*sizeMultipleLabel.bottomOffset: 10
+
+*FontSelectionBox*previewButton.labelString: Preview
+*FontSelectionBox*previewButton.bottomOffset: -11
+*FontSelectionBox*previewButton.rightOffset: 5
+
+*FontSelectionBox*samplerButton.labelString: Sampler...
+*FontSelectionBox*samplerButton.bottomOffset: 0
+*FontSelectionBox*samplerButton.rightOffset: 0
+
+*FontSelectionBox*familyLabel.labelString: Family
+*FontSelectionBox*familyLabel.rightOffset: 7
+*FontSelectionBox*familyLabel.leftOffset: 10
+
+*FontSelectionBox*faceLabel.labelString: Face
+*FontSelectionBox*faceLabel.rightOffset: 10
+*FontSelectionBox*faceLabel.leftOffset: 7
+
+*FontSelectionBox*familyMultipleLabel.labelString: MULTIPLE
+*FontSelectionBox*familyMultipleLabel.background: black
+*FontSelectionBox*familyMultipleLabel.foreground: #729FFF
+*FontSelectionBox*familyMultipleLabel.leftOffset: 10
+*FontSelectionBox*familyMultipleLabel.rightOffset: 7
+*FontSelectionBox*familyMultipleLabel.topOffset: 2
+
+*FontSelectionBox*faceMultipleLabel.labelString: MULTIPLE
+*FontSelectionBox*faceMultipleLabel.background: black
+*FontSelectionBox*faceMultipleLabel.foreground: #729FFF
+*FontSelectionBox*faceMultipleLabel.leftOffset: 7
+*FontSelectionBox*faceMultipleLabel.topOffset: 2
+*FontSelectionBox*faceMultipleLabel.rightOffset: 10
+
+*FontSelectionBox*familyScrolledListSW.leftOffset: 10
+*FontSelectionBox*familyScrolledListSW.topOffset: 2
+*FontSelectionBox*familyScrolledListSW.rightOffset: 7
+
+*FontSelectionBox*faceScrolledListSW.topOffset: 2
+*FontSelectionBox*faceScrolledListSW.leftOffset: 7
+*FontSelectionBox*faceScrolledListSW.rightOffset: 10
+
+*FontSelectionBox*XmList.listSizePolicy: constant
+*FontSelectionBox*XmList.scrollBarDisplayPolicy: as_needed
+
+*FontSelectionBox*multipleMasterButton.labelString: Multiple Master...
+
+*FontSelectionBox*invalidFontMessage.dialogTitle: Font Alert
+*FontSelectionBox*invalidFontMessage.messageString: The selected font contains\n\
+an error and is not usable.
+
+! Font sampler resources
+
+! Keep mwm from deleting this window; it confuses everyone
+*FontSelectionBox*samplerShell.deleteResponse: unmap
+
+*FontSelectionBox*samplerShell.width: 530
+*FontSelectionBox*samplerShell.height: 620
+*FontSelectionBox*samplerShell.title: Font Sampler
+
+*FontSelectionBox*sampler.minimumWidth: 1000
+*FontSelectionBox*sampler.minimumHeight: 400
+
+*FontSelectionBox*sampler*panel.horizontalSpacing: 5
+*FontSelectionBox*sampler*panel.verticalSpacing: 5
+
+*FontSelectionBox*sampler*area.width: 1000
+*FontSelectionBox*sampler*area.height: 476
+*FontSelectionBox*sampler*area.background: white
+*FontSelectionBox*sampler*ScrolledWindowClipWindow.background: white
+
+*FontSelectionBox*sampler*area.translations: #override\n\
+ <ButtonPress> : FSBClickAction()
+
+*FontSelectionBox*sampler*text.value: Abc
+
+*FontSelectionBox*sampler*fontLabel.labelString: \040
+*FontSelectionBox*sampler*fontLabel.recomputeSize: FALSE
+
+*FontSelectionBox*sampler*displayButton.labelString: Display
+*FontSelectionBox*sampler*stopButton.labelString: Stop
+*FontSelectionBox*sampler*dismissButton.labelString: Dismiss
+*FontSelectionBox*sampler*clearButton.labelString: Reset Filters
+
+*FontSelectionBox*sampler*allToggle.labelString: All
+*FontSelectionBox*sampler*allToggle.set: true
+*FontSelectionBox*sampler*selectedToggle.labelString: Selected
+*FontSelectionBox*sampler*selectedFamilyToggle.labelString: Family
+*FontSelectionBox*sampler*filterToggle.labelString: Filter
+
+*FontSelectionBox*sampler*filterText.leftOffset: 0
+*FontSelectionBox*sampler*filterText.columns:10
+*FontSelectionBox*sampler*filterText.marginHeight: 5
+
+*FontSelectionBox*sampler*radioBox*marginHeight: 1
+*FontSelectionBox*sampler*radioBox.spacing: 0
+*FontSelectionBox*sampler*filterBox*XmToggleButtonGadget.marginHeight: 0
+*FontSelectionBox*sampler*filterBox.spacing: 0
+*FontSelectionBox*sampler*filterBox*packing: PACK_TIGHT
+
+*FontSelectionBox*sampler*filterBox*XmSeparatorGadget.height: 8
+
+*FontSelectionBox*sampler*radioBox.width: 129
+*FontSelectionBox*sampler*radioBox.resizeWidth: FALSE
+
+*FontSelectionBox*sampler*roman.labelString: Roman
+*FontSelectionBox*sampler*italic.labelString: Italic
+*FontSelectionBox*sampler*symbol.labelString: Symbol
+*FontSelectionBox*sampler*display.labelString: Display
+*FontSelectionBox*sampler*alternate.labelString: Alternate
+*FontSelectionBox*sampler*expert.labelString: Expert
+*FontSelectionBox*sampler*oldstyle.labelString: Oldstyle Figures
+*FontSelectionBox*sampler*smallcaps.labelString: Small Caps
+*FontSelectionBox*sampler*swash.labelString: Swash
+*FontSelectionBox*sampler*script.labelString: Script
+
+*FontSelectionBox*sampler*condensed.labelString: Condensed
+*FontSelectionBox*sampler*extended.labelString: Extended
+
+*FontSelectionBox*sampler*light.labelString: Light
+*FontSelectionBox*sampler*book.labelString: Book
+*FontSelectionBox*sampler*medium.labelString: Medium
+*FontSelectionBox*sampler*demi.labelString: Demi
+*FontSelectionBox*sampler*bold.labelString: Bold
+*FontSelectionBox*sampler*black.labelString: Black +
+
+*FontSelectionBox*sampler*sizeLabel.labelString: Size:
+*FontSelectionBox*sampler*sizeLabel.bottomOffset: 15
+*FontSelectionBox*sampler*sizeLabel.leftOffset: 0
+
+*FontSelectionBox*sampler*sizeTextField.columns: 4
+*FontSelectionBox*sampler*sizeTextField.leftOffset: 2
+*FontSelectionBox*sampler*sizeTextField.bottomOffset: -7
+*FontSelectionBox*sampler*sizeTextField.value: 24
+*FontSelectionBox*sampler*sizeTextField.verifyBell: False
+
+*FontSelectionBox*sampler*sizeOptionMenu.labelString:
+*FontSelectionBox*sampler*sizeOptionMenu.bottomOffset: -9
+*FontSelectionBox*sampler*sizeOptionMenu.leftOffset: -5
+
+*FontSelectionBox*creatorShell.title: Multiple Master Font Creator
+
+*FontSelectionBox*creatorShell*preview.height: 50
+*FontSelectionBox*creatorShell*preview.leftOffset: 4
+*FontSelectionBox*creatorShell*preview.rightOffset: 4
+*FontSelectionBox*creatorShell*preview.topOffset: 4
+
+*FontSelectionBox*creatorShell*panel.horizontalSpacing: 10
+*FontSelectionBox*creatorShell*panel.verticalSpacing: 5
+*FontSelectionBox*creatorShell*panel.width: 500
+*FontSelectionBox*creatorShell*panel.height: 325
+*FontSelectionBox*creatorShell*panel.marginHeight: 5
+*FontSelectionBox*creatorShell*panel.marginWidth: 5
+
+*FontSelectionBox*creatorShell*displayTextLabel.labelString: String
+*FontSelectionBox*creatorShell*displayTextLabel.rightPosition: 15
+*FontSelectionBox*creatorShell*displayTextLabel.rightOffset: 5
+*FontSelectionBox*creatorShell*displayTextLabel.topOffset: 5
+
+*FontSelectionBox*creatorShell*displayText.leftPosition: 15
+*FontSelectionBox*creatorShell*displayText.rightPosition: 60
+*FontSelectionBox*creatorShell*displayText.rightOffset: 10
+*FontSelectionBox*creatorShell*displayText.topOffset: 0
+
+*FontSelectionBox*creatorShell*axisLabel1.rightPosition: 15
+*FontSelectionBox*creatorShell*axisLabel1.bottomOffset: 0
+*FontSelectionBox*creatorShell*axisLabel1.rightOffset: 5
+*FontSelectionBox*creatorShell*axisLabel1.topOffset: 5
+
+*FontSelectionBox*creatorShell*axisValue1.rightPosition: 60
+*FontSelectionBox*creatorShell*axisValue1.rightOffset: 10
+*FontSelectionBox*creatorShell*axisValue1.columns: 4
+
+*FontSelectionBox*creatorShell*axisScale1.rightOffset: 5
+*FontSelectionBox*creatorShell*axisScale1.leftPosition: 15
+*FontSelectionBox*creatorShell*axisScale1.topOffset: 5
+*FontSelectionBox*creatorShell*axisScale1.decimalPoints: 0
+*FontSelectionBox*creatorShell*axisScale1.orientation: horizontal
+*FontSelectionBox*creatorShell*axisScale1.showValue: false
+
+*FontSelectionBox*creatorShell*axisMin1.topOffset: 0
+*FontSelectionBox*creatorShell*axisMin1.leftOffset: 0
+
+*FontSelectionBox*creatorShell*axisMax1.topOffset: 0
+*FontSelectionBox*creatorShell*axisMax1.rightOffset: 0
+
+*FontSelectionBox*creatorShell*axisLabel2.rightPosition: 15
+*FontSelectionBox*creatorShell*axisLabel2.bottomOffset: 0
+*FontSelectionBox*creatorShell*axisLabel2.rightOffset: 5
+*FontSelectionBox*creatorShell*axisLabel2.topOffset: 5
+
+*FontSelectionBox*creatorShell*axisValue2.rightPosition: 60
+*FontSelectionBox*creatorShell*axisValue2.rightOffset: 10
+*FontSelectionBox*creatorShell*axisValue2.topOffset: 15
+*FontSelectionBox*creatorShell*axisValue2.columns: 4
+
+*FontSelectionBox*creatorShell*axisScale2.rightOffset: 5
+*FontSelectionBox*creatorShell*axisScale2.leftPosition: 15
+*FontSelectionBox*creatorShell*axisScale2.decimalPoints: 0
+*FontSelectionBox*creatorShell*axisScale2.orientation: horizontal
+*FontSelectionBox*creatorShell*axisScale2.showValue: false
+*FontSelectionBox*creatorShell*axisScale2.topOffset: 5
+
+*FontSelectionBox*creatorShell*axisMin2.topOffset: 0
+*FontSelectionBox*creatorShell*axisMin2.leftOffset: 0
+
+*FontSelectionBox*creatorShell*axisMax2.topOffset: 0
+*FontSelectionBox*creatorShell*axisMax2.rightOffset: 0
+
+*FontSelectionBox*creatorShell*axisLabel3.rightPosition: 15
+*FontSelectionBox*creatorShell*axisLabel3.bottomOffset: 0
+*FontSelectionBox*creatorShell*axisLabel3.rightOffset: 5
+*FontSelectionBox*creatorShell*axisLabel3.topOffset: 5
+
+*FontSelectionBox*creatorShell*axisValue3.rightPosition: 60
+*FontSelectionBox*creatorShell*axisValue3.rightOffset: 10
+*FontSelectionBox*creatorShell*axisValue3.topOffset: 15
+*FontSelectionBox*creatorShell*axisValue3.columns: 4
+
+*FontSelectionBox*creatorShell*axisScale3.rightOffset: 5
+*FontSelectionBox*creatorShell*axisScale3.leftPosition: 15
+*FontSelectionBox*creatorShell*axisScale3.decimalPoints: 0
+*FontSelectionBox*creatorShell*axisScale3.orientation: horizontal
+*FontSelectionBox*creatorShell*axisScale3.showValue: false
+*FontSelectionBox*creatorShell*axisScale3.topOffset: 5
+
+*FontSelectionBox*creatorShell*axisMin3.topOffset: 0
+*FontSelectionBox*creatorShell*axisMin3.leftOffset: 0
+
+*FontSelectionBox*creatorShell*axisMax3.topOffset: 0
+*FontSelectionBox*creatorShell*axisMax3.rightOffset: 0
+
+*FontSelectionBox*creatorShell*axisLabel4.rightPosition: 15
+*FontSelectionBox*creatorShell*axisLabel4.bottomOffset: 0
+*FontSelectionBox*creatorShell*axisLabel4.rightOffset: 5
+*FontSelectionBox*creatorShell*axisLabel4.topOffset: 5
+
+*FontSelectionBox*creatorShell*axisValue4.rightPosition: 60
+*FontSelectionBox*creatorShell*axisValue4.rightOffset: 10
+*FontSelectionBox*creatorShell*axisValue4.topOffset: 15
+*FontSelectionBox*creatorShell*axisValue4.columns: 4
+
+*FontSelectionBox*creatorShell*axisScale4.rightOffset: 5
+*FontSelectionBox*creatorShell*axisScale4.leftPosition: 15
+*FontSelectionBox*creatorShell*axisScale4.decimalPoints: 0
+*FontSelectionBox*creatorShell*axisScale4.orientation: horizontal
+*FontSelectionBox*creatorShell*axisScale4.showValue: false
+*FontSelectionBox*creatorShell*axisScale4.topOffset: 5
+
+*FontSelectionBox*creatorShell*axisMin4.topOffset: 0
+*FontSelectionBox*creatorShell*axisMin4.leftOffset: 0
+
+*FontSelectionBox*creatorShell*axisMax4.topOffset: 0
+*FontSelectionBox*creatorShell*axisMax4.rightOffset: 0
+
+*FontSelectionBox*creatorShell*faceLabel.leftPosition: 60
+*FontSelectionBox*creatorShell*faceLabel.leftOffset: 10
+*FontSelectionBox*creatorShell*faceLabel.labelString: Faces
+*FontSelectionBox*creatorShell*faceLabel.topOffset: 0
+
+*FontSelectionBox*creatorShell*faceListSW.leftPosition: 60
+*FontSelectionBox*creatorShell*faceListSW.leftOffset: 10
+*FontSelectionBox*creatorShell*faceListSW.topOffset: 0
+*FontSelectionBox*creatorShell*faceListSW.bottomPosition: 30
+
+*FontSelectionBox*creatorShell*blendLabel.leftPosition: 60
+*FontSelectionBox*creatorShell*blendLabel.leftOffset: 10
+*FontSelectionBox*creatorShell*blendLabel.topPosition: 30
+*FontSelectionBox*creatorShell*blendLabel.topOffset: 8
+*FontSelectionBox*creatorShell*blendLabel.labelString: Blends
+
+*FontSelectionBox*creatorShell*blendListSW.leftPosition: 60
+*FontSelectionBox*creatorShell*blendListSW.leftOffset: 10
+*FontSelectionBox*creatorShell*blendListSW.topOffset: 0
+
+*FontSelectionBox*creatorShell*nameLabel.labelString: Name
+*FontSelectionBox*creatorShell*nameLabel.rightPosition: 60
+*FontSelectionBox*creatorShell*nameLabel.rightOffset:-5
+*FontSelectionBox*creatorShell*nameLabel.bottomOffset: 8
+
+*FontSelectionBox*creatorShell*nameText.leftPosition: 60
+*FontSelectionBox*creatorShell*nameText.leftOffset: 8
+*FontSelectionBox*creatorShell*nameText.rightOffset: 3
+
+*FontSelectionBox*creatorShell*deleteButton.labelString: Delete
+
+*FontSelectionBox*creatorShell*replaceButton.labelString: Replace
+
+*FontSelectionBox*creatorShell*addButton.labelString: Add
+
+*FontSelectionBox*creatorShell*generateButton.labelString: Generate Name
+*FontSelectionBox*creatorShell*generateButton.rightOffset: 20
+
+*FontSelectionBox*creatorShell*optionsButton.labelString: Options...
+
+*FontSelectionBox*creatorShell*dismissButton.labelString: Dismiss
+
+*FontSelectionBox*creatorShell*noNameMessage.messageString: You must enter a\n\
+name in the Name field.
+*FontSelectionBox*creatorShell*noNameMessage.dialogTitle: Font Alert
+
+*FontSelectionBox*creatorShell*usedNameMessage.messageString: That name is already in use;\n\
+pick another or use the Replace button\n\
+to change its definition.
+*FontSelectionBox*creatorShell*usedNameMessage.dialogTitle: Font Alert
+
+*FontSelectionBox*creatorShell*someUsedNameMessage.messageString: That name was already in use in\n\
+some faces; use the Replace button\n\
+to change the definition in all faces.
+*FontSelectionBox*creatorShell*someUsedNameMessage.dialogTitle: Font Alert
+
+*FontSelectionBox*creatorShell*noSuchNameMessage.messageString: That blend does not exist.
+*FontSelectionBox*creatorShell*noSuchNameMessage.dialogTitle: Font Alert
+
+*FontSelectionBox*creatorShell*sizeLabel.labelString: Size
+*FontSelectionBox*creatorShell*sizeLabel.rightPosition: 15
+*FontSelectionBox*creatorShell*sizeLabel.rightOffset: 5
+*FontSelectionBox*creatorShell*sizeLabel.bottomOffset: 12
+
+*FontSelectionBox*creatorShell*sizeTextField.columns: 4
+*FontSelectionBox*creatorShell*sizeTextField.leftPosition: 15
+*FontSelectionBox*creatorShell*sizeTextField.bottomOffset: -7
+*FontSelectionBox*creatorShell*sizeTextField.verifyBell: False
+*FontSelectionBox*sizeTextField.value: 36
+
+*FontSelectionBox*creatorShell*other.labelString: ...
+
+*FontSelectionBox*creatorShell*sizeOptionMenu.labelString:
+*FontSelectionBox*creatorShell*sizeOptionMenu.bottomOffset: -9
+*FontSelectionBox*creatorShell*sizeOptionMenu.leftOffset: -5
+
+*FontSelectionBox*creatorShell*optionBox_popup.title: Font Creator Options
+*FontSelectionBox*creatorShell*doAllToggle.labelString: Apply blend list changes to all faces
+*FontSelectionBox*creatorShell*followSizeToggle.labelString: Reflect font size in OpticalSize axis
+*FontSelectionBox*creatorShell*dismissOptionButton.labelString: Dismiss
+
diff --git a/nx-X11/lib/dpstk/Imakefile b/nx-X11/lib/dpstk/Imakefile
new file mode 100644
index 000000000..323e584f6
--- /dev/null
+++ b/nx-X11/lib/dpstk/Imakefile
@@ -0,0 +1,91 @@
+XCOMM $XFree86: xc/lib/dpstk/Imakefile,v 1.5 2000/05/23 19:32:52 dawes Exp $
+
+#define DoNormalLib NormalLibDpsTk
+#define DoSharedLib SharedLibDpsTk
+#define DoExtraLib SharedLibDpsTk
+#define DoDebugLib DebugLibDpsTk
+#define DoProfileLib ProfileLibDpsTk
+#define LibName dpstk
+#define SoRev SODPSTKREV
+#define LibHeaders NO
+
+#ifdef SharedDPSTKReqs
+REQUIREDLIBS = SharedDPSTKReqs
+#endif
+
+ PSWRAP = PsWrap
+
+#if HasMotif
+INCLUDES = $(MOTIFINCLUDES)
+
+MOTIFSRCS = FSBwraps.c FontSample.c FontSB.c FontCreato.c \
+ CSBwraps.c ColorSB.c DSWwraps.c DPSScrollW.c
+MOTIFOBJS = FSBwraps.o FontSample.o FontSB.o FontCreato.o \
+ CSBwraps.o ColorSB.o DSWwraps.o DPSScrollW.o
+#endif
+
+#ifndef DefaultResourcePath
+#define DefaultResourcePath NULL
+#endif
+RESPATH = DefaultResourcePath
+
+#if NoStrstr
+ DEFINES = -DNO_STRSTR_AVAILABLE -DDEFAULT_RESOURCE_PATH=\"${RESPATH}\"
+#else
+ DEFINES = -DDEFAULT_RESOURCE_PATH=\"${RESPATH}\"
+#endif
+
+
+DERIVED_FILES = FSBwraps.c FSBwraps.h XDPSpwraps.c XDPSpwraps.h \
+ XDPSswraps.c XDPSswraps.h CSBwraps.c CSBwraps.h \
+ DSWwraps.c DSWwraps.h
+
+SRCS = XDPSpwraps.c XDPSswraps.c XDPSshare.c XDPSpreview.c \
+ XDPSuserpath.c
+
+OBJS = XDPSpwraps.o XDPSswraps.o XDPSshare.o XDPSpreview.o \
+ XDPSuserpath.o
+
+#include <Library.tmpl>
+
+.SUFFIXES: .psw
+
+.psw.c :
+ RunProgram(PSWRAP,-o $*.c -a -f $*.h -h $*.h $<)
+
+includes:: $(SRCS)
+
+#if HasMotif
+
+includes:: $(MOTIFSRCS)
+
+#if DoSharedLib
+SharedDepLibraryTarget(dpstkXm,$(SODPSREV),$(MOTIFOBJS),$(MOTIFOBJS) $(MOTIFLIB) $(DPSTKLIB) $(PSRESLIB),.,.)
+InstallSharedLibrary(dpstkXm,$(SODPSREV),$(USRLIBDIR))
+#endif
+#if DoNormalLib
+#if DoSharedLib
+UnsharedLibraryTarget(dpstkXm,$(MOTIFOBJS),unshared,..)
+#else
+NormalLibraryTarget(dpstkXm,$(MOTIFOBJS))
+#endif
+InstallLibrary(dpstkXm,$(USRLIBDIR))
+#endif
+#if DebugLibDps
+DebuggedLibraryTarget(dpstkXm,$(MOTIFOBJS))
+InstallLibrary(dpstkXm_d,$(USRLIBDIR))
+#endif
+#if ProfileLibDps
+ProfiledLibraryTarget(dpstkXm,$(MOTIFOBJS))
+InstallDpsProfiledLibrary(dpstkXm_p,$(USRLIBDIR))
+#endif
+
+InstallAppDefaults(FontSelect)
+InstallAppDefaults(ColorSelect)
+#endif /* HasMotif */
+
+clean ::
+ ${RM} $(DERIVED_FILES) $(MOTIFOBJS)
+
+DependTarget()
+
diff --git a/nx-X11/lib/dpstk/XDPSpreview.c b/nx-X11/lib/dpstk/XDPSpreview.c
new file mode 100644
index 000000000..d36331b71
--- /dev/null
+++ b/nx-X11/lib/dpstk/XDPSpreview.c
@@ -0,0 +1,636 @@
+/*
+ * XDPSpreview.c
+ *
+ * (c) Copyright 1990-1994 Adobe Systems Incorporated.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sublicense this software
+ * and its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notices appear in all copies and that
+ * both those copyright notices and this permission notice appear in
+ * supporting documentation and that the name of Adobe Systems Incorporated
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. No trademark license
+ * to use the Adobe trademarks is hereby granted. If the Adobe trademark
+ * "Display PostScript"(tm) is used to describe this software, its
+ * functionality or for any other purpose, such use shall be limited to a
+ * statement that this software works in conjunction with the Display
+ * PostScript system. Proper trademark attribution to reflect Adobe's
+ * ownership of the trademark shall be given whenever any such reference to
+ * the Display PostScript system is made.
+ *
+ * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
+ * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
+ * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
+ * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
+ * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
+ *
+ * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+ * Incorporated which may be registered in certain jurisdictions
+ *
+ * Author: Adobe Systems Incorporated
+ */
+/* $XFree86$ */
+
+#include <X11/Xlib.h>
+#include <DPS/dpsXclient.h>
+#include <DPS/XDPSlib.h>
+#include <DPS/psops.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef NeXT
+#include <unistd.h>
+#endif
+
+#include <DPS/dpsXshare.h>
+#include <DPS/dpsXpreview.h>
+#include "XDPSpwraps.h"
+#include "dpsXcommonI.h"
+#include <math.h>
+#include <X11/Xos.h>
+
+#if defined(hpux) || defined(AIXV3)
+#define SELECT_TYPE int *
+#else
+#define SELECT_TYPE fd_set *
+#endif
+
+#define BEGINDOCUMENTLEN 15 /* Length of "%%BeginDocument" */
+#define BEGINBINARYLEN 14 /* Length of "%%BeginBinary:" */
+
+static int ParseFileForBBox(FILE *file, XRectangle *bb);
+static void FillPixmapWithGray(
+ Screen *screen,
+ Drawable dest,
+ XRectangle *bbox,
+ int xOffset, int yOffset,
+ double pixelsPerPoint,
+ Bool createMask);
+
+static XDPSRewindFunction rewindFunction = XDPSFileRewindFunc;
+static DPSPointer rewindClientData = NULL;
+static XDPSGetsFunction getsFunction = XDPSFileGetsFunc;
+static DPSPointer getsClientData = NULL;
+
+int XDPSSetFileFunctions(
+ XDPSRewindFunction rewindFunc,
+ DPSPointer rewindData,
+ XDPSGetsFunction getsFunc,
+ DPSPointer getsData)
+{
+ if (rewindFunc != NULL) {
+ rewindFunction = rewindFunc;
+ rewindClientData = rewindData;
+ }
+ if (getsFunc != NULL) {
+ getsFunction = getsFunc;
+ getsClientData = getsData;
+ }
+ return 0;
+}
+
+/* ARGSUSED */
+
+void XDPSFileRewindFunc(FILE *f, DPSPointer data)
+{
+ rewind(f);
+}
+
+/* ARGSUSED */
+
+char *XDPSFileGetsFunc(char *buf, int n, FILE *f, DPSPointer data)
+{
+ return fgets(buf, n, f);
+}
+
+void XDPSEmbeddedEPSFRewindFunc(FILE *f, DPSPointer data)
+{
+ XDPSPosition *p = (XDPSPosition *) data;
+
+ p->nestingLevel = 0;
+ p->continuedLine = False;
+ p->binaryCount = 0;
+
+ if (fseek(f, p->startPos, SEEK_SET) != 0) {
+ (void) fseek(f, 0L, SEEK_END); /* Go to the end */
+ }
+}
+
+static Bool imaging = False;
+
+char *XDPSEmbeddedGetsFunc(char *buf, int n, FILE *f, DPSPointer data)
+{
+ XDPSPosition *p = (XDPSPosition *) data;
+ int count;
+ unsigned len;
+
+ if (fgets(buf, n, f) == NULL) {
+ if (imaging) p->startPos = -1;
+ return NULL;
+ }
+
+ /* If previous call didn't get a whole line, we're somewhere in the
+ middle, so don't check for comments. Also, if we're in the middle of
+ binary data, don't look for comments either. */
+
+ len = strlen(buf);
+
+ if (p->binaryCount != 0) {
+ if (len > p->binaryCount) p->binaryCount = 0;
+ else p->binaryCount -= len;
+
+ } else if (!p->continuedLine) {
+ if (strncmp(buf, "%%BeginDocument", BEGINDOCUMENTLEN) == 0) {
+ p->nestingLevel++;
+
+ } else if (strncmp(buf, "%%BeginBinary:", BEGINBINARYLEN) == 0) {
+ count = sscanf(buf, "%%%%BeginBinary: %lu", &p->binaryCount);
+ if (count != 1) p->binaryCount = 0; /* Malformed comment */
+
+ } else if (strcmp(buf, "%%EndDocument\n") == 0) {
+ if (p->nestingLevel == 0) {
+ if (imaging) p->startPos = ftell(f);
+ return NULL;
+ }
+ else p->nestingLevel--;
+ }
+ }
+
+ if ((int)len == n-1 && buf[n-1] != '\n') p->continuedLine = True;
+ else p->continuedLine = False;
+
+ return buf;
+}
+
+int XDPSCreatePixmapForEPSF(
+ DPSContext context,
+ Screen *screen,
+ FILE *epsf,
+ int depth,
+ double pixelsPerPoint,
+ Pixmap *pixmap,
+ XRectangle *pixelSize,
+ XRectangle *bbox)
+{
+ Pixmap p;
+ int width, height;
+ XRectangle bb;
+
+ if (screen == NULL || depth <= 0 ||
+ pixelsPerPoint <= 0) {
+ return dps_status_illegal_value;
+ }
+
+ if (context == NULL) {
+ context = XDPSGetSharedContext(DisplayOfScreen(screen));
+ }
+
+ (*rewindFunction)(epsf, rewindClientData);
+
+ if (ParseFileForBBox(epsf, &bb) == dps_status_failure) {
+ return dps_status_failure;
+ }
+
+ width = ceil(bb.width * pixelsPerPoint);
+ height = ceil(bb.height * pixelsPerPoint);
+ if (width <= 0 || height <= 0) return dps_status_failure;
+
+ p = XCreatePixmap(DisplayOfScreen(screen), RootWindowOfScreen(screen),
+ width, height, depth);
+
+ if (pixmap != NULL) *pixmap = p;
+ if (pixelSize != NULL) {
+ pixelSize->x = pixelSize->y = 0;
+ pixelSize->width = width;
+ pixelSize->height = height;
+ }
+ if (bbox != NULL) *bbox = bb;
+
+ if (context != NULL) return dps_status_success;
+ else return dps_status_no_extension;
+}
+
+static int ParseFileForBBox(FILE *file, XRectangle *bb)
+{
+#define BBOXLEN 14 /* Length of "%%BoundingBox:" */
+#define BUFLEN 256
+#define ATENDLEN 8 /* Length of "(atend)" plus one byte for \0 */
+ char buf[BUFLEN];
+ char buf2[ATENDLEN];
+ Bool atend = False; /* Found a %%BoundingBox: (atend) */
+ float x, y, r, t;
+ int n;
+ int nestingLevel = 0;
+ unsigned long binaryCount = 0;
+ Bool continuedLine = False;
+ unsigned len;
+
+ while (1) {
+ if ((*getsFunction)(buf, BUFLEN, file, getsClientData) == NULL) {
+ return dps_status_failure;
+ }
+
+ len = strlen(buf);
+
+ /* If in binary data or continued line, ignore everything */
+
+ if (binaryCount != 0) {
+ if (len > binaryCount) binaryCount = 0;
+ else binaryCount -= len;
+
+ } else if (!continuedLine) {
+ if (strncmp(buf, "%%BeginBinary:", BEGINBINARYLEN) == 0) {
+ n = sscanf(buf, "%%%%BeginBinary: %lu", &binaryCount);
+ if (n != 1) binaryCount = 0; /* Malformed comment */
+
+ } else if (strncmp(buf, "%%BeginDocument", BEGINDOCUMENTLEN) == 0) {
+ nestingLevel++;
+
+ } else if (strcmp(buf, "%%EndDocument\n") == 0) {
+ nestingLevel--;
+
+ /* Only check for bounding box comments at nesting level 0 */
+
+ } else if (nestingLevel == 0) {
+
+ /* If we haven't already hit an (atend), the end of the
+ comments is a good place to stop looking for the bbox */
+
+ if (!atend && (strcmp(buf, "%%EndComments\n") == 0 ||
+ strcmp(buf, "%%EndProlog\n") == 0)) {
+ return dps_status_failure;
+ }
+
+ if (strncmp(buf, "%%BoundingBox:", BBOXLEN) == 0) {
+ n = sscanf(buf, "%%%%BoundingBox: %f %f %f %f",
+ &x, &y, &r, &t);
+
+ if (n != 4) {
+ n = sscanf(buf, "%%%%BoundingBox: %7s", buf2);
+
+ if (n == 1 && strcmp(buf2, "(atend)") == 0) {
+ atend = True;
+ } else return dps_status_failure;
+
+ } else {
+ bb->x = (int) x;
+ bb->y = (int) y;
+ bb->width = r - bb->x;
+ if ((float)((int) r) != r) bb->width++;
+ bb->height = t - bb->y;
+ if ((float)((int) t) != t) bb->height++;
+ return dps_status_success;
+ }
+ }
+ }
+ }
+
+ /* See if this line fills the buffer */
+ if (len == BUFLEN-1 && buf[BUFLEN-1] != '\n') continuedLine = True;
+ }
+
+#undef ATENDLEN
+#undef BUFLEN
+#undef BBOXLEN
+}
+
+#define mmPerPoint (25.4/72.0)
+
+double XDPSPixelsPerPoint(Screen *screen)
+{
+ return (float) WidthOfScreen(screen) * mmPerPoint /
+ (float) WidthMMOfScreen(screen);
+}
+
+static int timeStart = 200, maxDoubles = 3;
+
+void XDPSSetImagingTimeout(int timeout, int max)
+{
+ timeStart = timeout;
+ maxDoubles = max;
+}
+
+typedef struct _StatusInfo {
+ DPSContext ctxt;
+ DPSPointer cookie;
+ Bool *doneFlag;
+ unsigned long startReqNum, endReqNum;
+ XDPSStatusProc oldProc;
+ struct _StatusInfo *next, *prev;
+} StatusInfo;
+
+static StatusInfo *StatusList;
+
+static void SetUpStatusVariables(
+ DPSContext context,
+ DPSPointer cookie,
+ Bool *doneFlag,
+ unsigned long startReq,
+ XDPSStatusProc oldProc)
+{
+ StatusInfo *info = (StatusInfo *) malloc(sizeof(StatusInfo));
+
+ info->ctxt = context;
+ info->cookie = cookie;
+ info->doneFlag = doneFlag;
+ info->startReqNum = startReq;
+ info->endReqNum = 0xFFFFFFFF;
+ info->oldProc = oldProc;
+ if (StatusList != NULL) StatusList->prev = info;
+ info->next = StatusList;
+ info->prev = NULL;
+ StatusList = info;
+}
+
+static void SetEndReqNum(
+ DPSContext context,
+ unsigned long endReq)
+{
+ StatusInfo *info = StatusList;
+
+ while (info != NULL && info->ctxt != context) info = info->next;
+ if (info != NULL) info->endReqNum = endReq;
+}
+
+static void HandlePreviewStatus(
+ DPSContext context,
+ int status)
+{
+ unsigned long serial;
+ Display *dpy;
+ StatusInfo *info = StatusList;
+
+ while (info != NULL && info->ctxt != context) info = info->next;
+ if (info == NULL) return;
+
+ (void) XDPSXIDFromContext(&dpy, context);
+ serial = LastKnownRequestProcessed(dpy);
+
+ /* This event is from before our imaging; send to old status proc. */
+ if (serial < info->startReqNum) {
+ (*info->oldProc) (context, status);
+ return;
+ }
+
+ /* This event is from during our imaging; ignore it */
+ if (serial < info->endReqNum) return;
+
+ /* This event is juuuuust right. */
+ if (status == PSFROZEN) *info->doneFlag = True;
+}
+
+static int FinishUp(
+ DPSContext context,
+ DPSPointer cookie)
+{
+ static char restorebuf[] =
+ "\n$Adobe$DPS$Lib$Dict /EPSFsave get restore grestore\n";
+ StatusInfo *info = StatusList;
+ int err;
+
+ /* Check the results of the imaging: Get the error status and restore the
+ context */
+
+ _DPSPCheckForError(context, &err);
+
+ /* Can't do this is a wrap because of restore semantics */
+ DPSWritePostScript(context, restorebuf, strlen(restorebuf));
+
+ (void) XDPSPopContextParameters(cookie);
+
+ /* See if we have an info record and delete it if so */
+ while (info != NULL && info->ctxt != context) info = info->next;
+ if (info != NULL) {
+ if (info == StatusList) StatusList = info->next;
+ else info->prev->next = info->next;
+ if (info->next != NULL) info->next->prev = info->prev;
+ XDPSRegisterStatusProc(context, info->oldProc);
+ free(info);
+ }
+
+ if (err) return dps_status_postscript_error;
+ else return dps_status_success;
+}
+
+int XDPSCheckImagingResults(
+ DPSContext context,
+ Screen *screen)
+{
+ StatusInfo *info = StatusList;
+ int status;
+
+ if (context == NULL) {
+ context = XDPSGetSharedContext(DisplayOfScreen(screen));
+ if (context == NULL) return dps_status_no_extension;
+ }
+
+ while (info != NULL && info->ctxt != context) info = info->next;
+ if (info == NULL) return dps_status_illegal_value;
+
+ status = XDPSGetContextStatus(context);
+ if (status != PSFROZEN) return dps_status_imaging_incomplete;
+
+ XDPSUnfreezeContext(context);
+ return FinishUp(context, info->cookie);
+}
+
+static void msleep(int ms)
+{
+ struct timeval incr;
+
+ incr.tv_sec = ms / 1000;
+ incr.tv_usec = (ms % 1000) * 1000;
+ (void) select (0, (SELECT_TYPE) NULL, (SELECT_TYPE) NULL,
+ (SELECT_TYPE) NULL, &incr);
+}
+
+int XDPSImageFileIntoDrawable(
+ DPSContext context,
+ Screen *screen,
+ Drawable dest,
+ FILE *file,
+ int drawableHeight,
+ int drawableDepth,
+ XRectangle *bbox,
+ int xOffset, int yOffset,
+ double pixelsPerPoint,
+ Bool clear, Bool createMask,
+ Bool waitForCompletion,
+ Bool *doneFlag)
+{
+#define BUFSIZE 256
+#define EXECLEN 6
+ char buf[BUFSIZE];
+ static char eobuf[] = "\n$Adobe$DPS$Lib$Dict /execSuccess true put\n\
+stop\n\
+Magic end of data line )))))))))) 99#2 2#99 <xyz> // 7gsad,32h4ghNmndFgj2\n";
+ XDPSStandardColormap maskMap;
+ XDPSStandardColormap rgbMap;
+ unsigned int flags = 0;
+ int status;
+ Bool inited;
+ DPSPointer cookie;
+ int doublings;
+ int ms;
+ XDPSStatusProc oldProc;
+ unsigned long startReqNum = 0, endReqNum;
+
+ if (screen == NULL || dest == None ||
+ drawableHeight <= 0 || drawableDepth <= 0 ||
+ pixelsPerPoint <= 0) {
+ return dps_status_illegal_value;
+ }
+
+ if (context == NULL) {
+ context = XDPSGetSharedContext(DisplayOfScreen(screen));
+ if (context == NULL) {
+ FillPixmapWithGray(screen, dest, bbox, xOffset, yOffset,
+ pixelsPerPoint,
+ createMask);
+ return dps_status_no_extension;
+ }
+ }
+
+ (*rewindFunction)(file, rewindClientData);
+
+ if (!waitForCompletion) {
+ DPSWaitContext(context);
+ /* Any status events before this point go to old handler */
+ startReqNum = NextRequest(DisplayOfScreen(screen));
+ }
+
+ status = _XDPSTestComponentInitialized(context,
+ dps_init_bit_preview, &inited);
+ if (status != dps_status_success) return status;
+ if (!inited) {
+ (void) _XDPSSetComponentInitialized(context, dps_init_bit_preview);
+ _DPSPDefineExecFunction(context);
+ }
+
+ if (createMask) {
+ if (drawableDepth != 1) return dps_status_illegal_value;
+ maskMap.colormap = None;
+ maskMap.red_max = 1;
+ maskMap.red_mult = -1;
+ maskMap.base_pixel = 1;
+ rgbMap.colormap = None;
+ rgbMap.red_max = rgbMap.green_max = rgbMap.blue_max =
+ rgbMap.red_mult = rgbMap.green_mult = rgbMap.blue_mult =
+ rgbMap.base_pixel = 0;
+ flags = XDPSContextGrayMap | XDPSContextRGBMap;
+ }
+
+ status = XDPSPushContextParameters(context, screen, drawableDepth,
+ dest, drawableHeight,
+ &rgbMap, &maskMap,
+ flags | XDPSContextScreenDepth |
+ XDPSContextDrawable, &cookie);
+
+ if (status != dps_status_success) return status;
+
+ _DPSPSetMatrix(context, xOffset, yOffset, pixelsPerPoint);
+
+ if (clear) _DPSPClearArea(context, (int) bbox->x, (int) bbox->y,
+ (int) bbox->width, (int) bbox->height);
+
+ if (createMask) _DPSPSetMaskTransfer(context);
+
+ /* Prepare to read PostScript code */
+ _DPSPSaveBeforeExec(context, !waitForCompletion);
+ DPSWritePostScript(context, "\nexec\n", EXECLEN);
+
+ imaging = True;
+ while ((*getsFunction)(buf, BUFSIZE, file, getsClientData) != NULL) {
+ DPSWritePostScript(context, buf, strlen(buf));
+ }
+ imaging = False;
+
+ /* This marks the end of the data stream */
+ DPSWritePostScript(context, eobuf, strlen(eobuf));
+
+ if (!waitForCompletion) {
+ *doneFlag = False;
+ oldProc = XDPSRegisterStatusProc(context, HandlePreviewStatus);
+ SetUpStatusVariables(context, cookie, doneFlag, startReqNum, oldProc);
+ XDPSSetStatusMask(context, 0, 0, PSFROZENMASK);
+
+ ms = timeStart;
+
+ /* Check for done until we run out of time */
+ doublings = 0;
+ while (1) {
+ if (XDPSGetContextStatus(context) == PSFROZEN) {
+ waitForCompletion = True;
+ XDPSUnfreezeContext(context);
+ break;
+ }
+ if (doublings >= maxDoubles) break;
+
+ /* Wait a while */
+ msleep(ms);
+ ms *= 2;
+ doublings++;
+ }
+ }
+
+ /* If previous decided imaging is done, it changed waitForCompletion */
+
+ if (waitForCompletion) return FinishUp(context, cookie);
+ else {
+ endReqNum = NextRequest(DisplayOfScreen(screen)) - 1;
+ SetEndReqNum(context, endReqNum);
+ return dps_status_imaging_incomplete;
+ }
+#undef EXECLEN
+#undef BUFSIZE
+}
+
+static void FillPixmapWithGray(
+ Screen *screen,
+ Drawable dest,
+ XRectangle *bbox,
+ int xOffset, int yOffset,
+ double pixelsPerPoint,
+ Bool createMask)
+{
+ int width, height, x, y;
+ GC gc;
+ XGCValues v;
+ static char grayBits[] = {0x01, 0x02};
+ Pixmap grayStipple;
+ Display *dpy = DisplayOfScreen(screen);
+
+ width = ceil(bbox->width * pixelsPerPoint);
+ height = ceil(bbox->height * pixelsPerPoint);
+ x = (bbox->x + xOffset) * pixelsPerPoint;
+ y = (bbox->y + yOffset) * pixelsPerPoint;
+
+ if (createMask) {
+ v.foreground = 1;
+ v.function = GXcopy;
+
+ gc = XCreateGC(dpy, dest, GCForeground | GCFunction, &v);
+ XFillRectangle(dpy, dest, gc, x, y, width, height);
+ XFreeGC(dpy, gc);
+ return;
+ }
+
+ grayStipple = XCreateBitmapFromData(dpy, dest, grayBits, 2, 2);
+
+ v.foreground = BlackPixelOfScreen(screen);
+ v.background = WhitePixelOfScreen(screen);
+ v.function = GXcopy;
+ v.stipple = grayStipple;
+ v.fill_style = FillOpaqueStippled;
+ gc = XCreateGC(dpy, dest, GCForeground | GCBackground | GCFunction |
+ GCStipple | GCFillStyle, &v);
+ XFillRectangle(dpy, dest, gc, x, y, width, height);
+ XFreeGC(dpy, gc);
+ XFreePixmap(dpy, grayStipple);
+}
diff --git a/nx-X11/lib/dpstk/XDPSpwraps.psw b/nx-X11/lib/dpstk/XDPSpwraps.psw
new file mode 100644
index 000000000..b5ff4c4bd
--- /dev/null
+++ b/nx-X11/lib/dpstk/XDPSpwraps.psw
@@ -0,0 +1,97 @@
+/*
+ * XDPSpwraps.psw
+ *
+ * (c) Copyright 1990-1994 Adobe Systems Incorporated.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sublicense this software
+ * and its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notices appear in all copies and that
+ * both those copyright notices and this permission notice appear in
+ * supporting documentation and that the name of Adobe Systems Incorporated
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. No trademark license
+ * to use the Adobe trademarks is hereby granted. If the Adobe trademark
+ * "Display PostScript"(tm) is used to describe this software, its
+ * functionality or for any other purpose, such use shall be limited to a
+ * statement that this software works in conjunction with the Display
+ * PostScript system. Proper trademark attribution to reflect Adobe's
+ * ownership of the trademark shall be given whenever any such reference to
+ * the Display PostScript system is made.
+ *
+ * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
+ * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
+ * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
+ * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
+ * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
+ *
+ * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+ * Incorporated which may be registered in certain jurisdictions
+ *
+ * Author: Adobe Systems Incorporated
+ */
+
+defineps _DPSPSetMatrix(DPSContext ctxt; int xOffset, yOffset;
+ double pixelsPerPoint)
+ gsave
+ initmatrix
+ 1 1 idtransform abs exch abs exch scale
+ % matrix is identity modulo sign
+ pixelsPerPoint dup scale
+ xOffset yOffset translate
+endps
+
+defineps _DPSPClearArea(DPSContext ctxt; int x, y, width, height)
+ 1 setgray
+ x y width height rectfill
+endps
+
+defineps _DPSPSetMaskTransfer(DPSContext ctxt)
+ {pop 0} dup dup dup setcolortransfer
+ {pop 0} settransfer
+endps
+
+defineps _DPSPDefineExecFunction(DPSContext ctxt)
+ $Adobe$DPS$Lib$Dict begin
+ /ExecPS {
+ $Adobe$DPS$Lib$Dict /doclientsync 3 -1 roll put
+ $Adobe$DPS$Lib$Dict /execSuccess false put
+ (%stdin) (r) file
+ cvx stopped
+ pop % always true
+ % Flush until you get the magic line
+ {
+ {currentfile 256 string readline} stopped
+ pop % don't care stopped result
+ pop % don't care readline bool result
+(Magic end of data line \)\)\)\)\)\)\)\)\)\) 99#2 2#99 <xyz> // 7gsad,32h4ghNmndFgj2)
+ eq
+ {exit} if
+ } loop
+ $Adobe$DPS$Lib$Dict /doclientsync get {
+ clientsync
+ } if
+ } def end
+endps
+
+defineps _DPSPSaveBeforeExec(DPSContext ctxt; boolean noWait)
+ $Adobe$DPS$Lib$Dict /EPSFsave save put
+ clear cleardictstack
+ /showpage {} def
+ 0 setgray 0 setlinecap
+ 1 setlinewidth 0 setlinejoin
+ 10 setmiterlimit [] 0 setdash newpath
+ noWait
+ $Adobe$DPS$Lib$Dict /ExecPS get
+endps
+
+defineps _DPSPCheckForError(DPSContext ctxt | boolean *err)
+ $Adobe$DPS$Lib$Dict /execSuccess get not err
+ clear
+ cleardictstack
+endps
diff --git a/nx-X11/lib/dpstk/XDPSshare.c b/nx-X11/lib/dpstk/XDPSshare.c
new file mode 100644
index 000000000..ef146db4e
--- /dev/null
+++ b/nx-X11/lib/dpstk/XDPSshare.c
@@ -0,0 +1,727 @@
+/*
+ * XDPSshare.c
+ *
+ * (c) Copyright 1990-1994 Adobe Systems Incorporated.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sublicense this software
+ * and its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notices appear in all copies and that
+ * both those copyright notices and this permission notice appear in
+ * supporting documentation and that the name of Adobe Systems Incorporated
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. No trademark license
+ * to use the Adobe trademarks is hereby granted. If the Adobe trademark
+ * "Display PostScript"(tm) is used to describe this software, its
+ * functionality or for any other purpose, such use shall be limited to a
+ * statement that this software works in conjunction with the Display
+ * PostScript system. Proper trademark attribution to reflect Adobe's
+ * ownership of the trademark shall be given whenever any such reference to
+ * the Display PostScript system is made.
+ *
+ * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
+ * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
+ * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
+ * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
+ * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
+ *
+ * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+ * Incorporated which may be registered in certain jurisdictions
+ *
+ * Author: Adobe Systems Incorporated
+ */
+/* $XFree86: xc/lib/dpstk/XDPSshare.c,v 1.2 2000/06/07 22:03:01 tsi Exp $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <X11/Xlib.h>
+
+#include <DPS/dpsXclient.h>
+#include <DPS/dpsops.h>
+#include <DPS/XDPSlib.h>
+#include <DPS/dpsXshare.h>
+
+#include "XDPSswraps.h"
+#include "dpsXcommonI.h"
+
+static int extensionId = 0;
+
+/*
+ Alloc...Info allocates an info entry and stores it at the head of the list.
+ Find...Info looks for an info entry and returns NULL if not found.
+ Lookup...Info looks for an info entry and creates one if not found.
+*/
+
+typedef struct _ContextInfoRec {
+ int extensionId;
+ DPSContextExtensionRec next;
+ DPSContext text;
+ Bool enableText;
+ unsigned long initFlags;
+ struct _DisplayInfoRec *displayInfo;
+} ContextInfoRec, *ContextInfo;
+
+typedef enum {ext_yes, ext_no, ext_no_idea} ExtensionStatus;
+
+typedef struct _DisplayInfoRec {
+ Display *display;
+ ExtensionStatus extensionPresent;
+ DPSContext defaultContext;
+ int *depthsForScreen;
+ int **validDepths;
+ GC **gcForDepth;
+ struct _DisplayInfoRec *next;
+} DisplayInfoRec, *DisplayInfo;
+
+/* If a display is in displayList, it means that we have looked to see if
+ the extension exists on the display. If context is not NULL, the
+ display has a default context associated with it. */
+
+static DisplayInfo displayList = NULL;
+
+static DisplayInfo LookupDisplayInfo(Display *display);
+
+static ContextInfo AllocContextInfo(DPSContext context)
+{
+ ContextInfo c = (ContextInfo) calloc(1, sizeof(ContextInfoRec));
+
+ if (extensionId == 0) extensionId = DPSGenerateExtensionRecID();
+
+ c->extensionId = extensionId;
+ DPSAddContextExtensionRec(context, (DPSContextExtensionRec *) c);
+
+ return c;
+}
+
+static ContextInfo FindContextInfo(DPSContext context)
+{
+ if (extensionId == 0) extensionId = DPSGenerateExtensionRecID();
+
+ return (ContextInfo) DPSGetContextExtensionRec(context, extensionId);
+}
+
+static ContextInfo RemoveContextInfo(DPSContext context)
+{
+ return (ContextInfo) DPSRemoveContextExtensionRec(context,
+ extensionId);
+}
+
+/* May only be called for a display in the display list. */
+
+static ContextInfo LookupContext(
+ Display *display,
+ DPSContext context)
+{
+ ContextInfo c = FindContextInfo(context);
+
+ if (c != NULL) return c;
+
+ /* Create one */
+
+ c = AllocContextInfo(context);
+ c->displayInfo = LookupDisplayInfo(display);
+ return c;
+}
+
+static DisplayInfo AllocDisplayInfo(
+ Display *display,
+ DPSContext context)
+{
+ DisplayInfo d = (DisplayInfo) malloc(sizeof(DisplayInfoRec));
+ register int i;
+
+ if (d == NULL) return NULL;
+ d->next = displayList;
+ displayList = d;
+
+ d->display = display;
+ d->defaultContext = context;
+ d->extensionPresent = (context == NULL) ? ext_no_idea : ext_yes;
+
+ d->depthsForScreen = (int *) calloc(ScreenCount(display), sizeof(int));
+ d->validDepths = (int **) calloc(ScreenCount(display), sizeof(int *));
+ d->gcForDepth = (GC **) calloc(ScreenCount(display), sizeof(GC *));
+
+ for (i = 0; i < ScreenCount(display); i++) {
+ d->validDepths[i] = XListDepths(display, i, &d->depthsForScreen[i]);
+ d->gcForDepth[i] = (GC *) calloc(d->depthsForScreen[i], sizeof(GC));
+ }
+
+ return d;
+}
+
+static DisplayInfo FindDisplayInfo(Display *display)
+{
+ DisplayInfo d = displayList;
+
+ while (d != NULL && d->display != display) d = d->next;
+ return d;
+}
+
+static DisplayInfo LookupDisplayInfo(Display *display)
+{
+ DisplayInfo d = FindDisplayInfo(display);
+
+ if (d == NULL) d = AllocDisplayInfo(display, (DPSContext) NULL);
+
+ return d;
+}
+
+int _XDPSSetComponentInitialized(DPSContext context, unsigned long bit)
+{
+ ContextInfo c = FindContextInfo(context);
+
+ if (c == NULL) return dps_status_unregistered_context;
+ c->initFlags |= bit;
+ return dps_status_success;
+}
+
+int _XDPSTestComponentInitialized(
+ DPSContext context,
+ unsigned long bit,
+ Bool *result)
+{
+ ContextInfo c = FindContextInfo(context);
+
+ if (c == NULL) {
+ *result = False;
+ return dps_status_unregistered_context;
+ }
+ *result = ((c->initFlags & bit) != 0);
+ return dps_status_success;
+}
+
+int XDPSSetContextDepth(
+ DPSContext context,
+ Screen *screen,
+ int depth)
+{
+ return XDPSSetContextParameters(context, screen, depth, None, 0,
+ (XDPSStandardColormap *) NULL,
+ (XDPSStandardColormap *) NULL,
+ XDPSContextScreenDepth);
+}
+
+int XDPSSetContextDrawable(
+ DPSContext context,
+ Drawable drawable,
+ int height)
+{
+ if (drawable != None && height <= 0) return dps_status_illegal_value;
+ _DPSSSetContextDrawable(context, drawable, height);
+ return dps_status_success;
+}
+
+int XDPSSetContextRGBMap(
+ DPSContext context,
+ XDPSStandardColormap *map)
+{
+ return XDPSSetContextParameters(context, (Screen *) NULL, 0, None, 0,
+ map, (XDPSStandardColormap *) NULL,
+ XDPSContextRGBMap);
+}
+
+int XDPSSetContextGrayMap(
+ DPSContext context,
+ XDPSStandardColormap *map)
+{
+ return XDPSSetContextParameters(context, (Screen *) NULL, 0, None, 0,
+ map, (XDPSStandardColormap *) NULL,
+ XDPSContextGrayMap);
+}
+
+static GC DisplayInfoSharedGC(DisplayInfo d, Screen *screen, int depth)
+{
+ int s = XScreenNumberOfScreen(screen);
+ register int i;
+ XGCValues v;
+ Pixmap p;
+
+ if (s >= ScreenCount(DisplayOfScreen(screen))) return NULL;
+
+ for (i = 0; i < d->depthsForScreen[s] &&
+ d->validDepths[s][i] != depth; i++) {}
+
+ if (i >= d->depthsForScreen[s]) return NULL;
+
+ if (d->gcForDepth[s][i] == 0) { /* Not "None" -- used calloc */
+ if (depth == DefaultDepthOfScreen(screen)) {
+ d->gcForDepth[s][i] = XCreateGC(d->display,
+ RootWindowOfScreen(screen), 0, &v);
+ } else {
+ p = XCreatePixmap(d->display,
+ RootWindowOfScreen(screen),
+ 1, 1, depth);
+ d->gcForDepth[s][i] = XCreateGC(d->display, p, 0, &v);
+ XFreePixmap(d->display, p);
+ }
+ }
+
+ return d->gcForDepth[s][i];
+}
+
+int XDPSSetContextParameters(
+ DPSContext context,
+ Screen *screen,
+ int depth,
+ Drawable drawable,
+ int height,
+ XDPSStandardColormap *rgbMap,
+ XDPSStandardColormap *grayMap,
+ unsigned int flags)
+{
+ ContextInfo c = FindContextInfo(context);
+ Bool doDepth = False, doDrawable = False, doRGB = False, doGray = False;
+ Colormap map = None;
+ XStandardColormap cmap;
+ GC gc;
+ GContext gctx = None;
+ DisplayInfo d;
+ Display *dpy;
+ int rgb_base_pixel = 0;
+ int red_max = 0;
+ int red_mult = 0;
+ int green_max = 0;
+ int green_mult = 0;
+ int blue_max = 0;
+ int blue_mult = 0;
+ int gray_base_pixel = 0;
+ int gray_max = 0;
+ int gray_mult = 0;
+
+ if (c == NULL) return dps_status_unregistered_context;
+ d = c->displayInfo;
+
+ (void) XDPSXIDFromContext(&dpy, context);
+
+ if (flags & XDPSContextScreenDepth) {
+ doDepth = True;
+
+ if (DisplayOfScreen(screen) != dpy) {
+ return dps_status_illegal_value;
+ }
+
+ gc = DisplayInfoSharedGC(d, screen, depth);
+ if (gc == NULL) return dps_status_illegal_value;
+
+ gctx = XGContextFromGC(gc);
+ }
+
+ if (flags & XDPSContextDrawable) {
+ doDrawable = True;
+ if (drawable != None && height <= 0) return dps_status_illegal_value;
+ }
+
+ if (flags & XDPSContextRGBMap) {
+ doRGB = True;
+ if (rgbMap == NULL) {
+ XDPSGetDefaultColorMaps(dpy, screen, drawable, &cmap,
+ (XStandardColormap *) NULL);
+ rgb_base_pixel = cmap.base_pixel;
+ red_max = cmap.red_max;
+ red_mult = cmap.red_mult;
+ green_max = cmap.green_max;
+ green_mult = cmap.green_mult;
+ blue_max = cmap.blue_max;
+ blue_mult = cmap.blue_mult;
+ map = cmap.colormap;
+ } else {
+ rgb_base_pixel = rgbMap->base_pixel;
+ red_max = rgbMap->red_max;
+ red_mult = rgbMap->red_mult;
+ green_max = rgbMap->green_max;
+ green_mult = rgbMap->green_mult;
+ blue_max = rgbMap->blue_max;
+ blue_mult = rgbMap->blue_mult;
+ map = rgbMap->colormap;
+ }
+ }
+
+ if (flags & XDPSContextGrayMap) {
+ doGray = True;
+ if (grayMap == NULL) {
+ XDPSGetDefaultColorMaps(dpy, screen, drawable,
+ (XStandardColormap *) NULL, &cmap);
+ gray_base_pixel = cmap.base_pixel;
+ gray_max = cmap.red_max;
+ gray_mult = cmap.red_mult;
+ if (doRGB && map != cmap.colormap) {
+ return dps_status_illegal_value;
+ } else map = cmap.colormap;
+ } else {
+ gray_base_pixel = grayMap->base_pixel;
+ gray_max = grayMap->red_max;
+ gray_mult = grayMap->red_mult;
+ if (doRGB && map != grayMap->colormap) {
+ return dps_status_illegal_value;
+ } else map = grayMap->colormap;
+ }
+ }
+
+ if (doDepth || doDrawable || doRGB || doGray) {
+ _DPSSSetContextParameters(context, gctx, drawable, height, map,
+ rgb_base_pixel, red_max, red_mult,
+ green_max, green_mult, blue_max, blue_mult,
+ gray_base_pixel, gray_max, gray_mult,
+ doDepth, doDrawable, doRGB, doGray);
+ }
+ return dps_status_success;
+}
+
+int XDPSPushContextParameters(
+ DPSContext context,
+ Screen *screen,
+ int depth,
+ Drawable drawable,
+ int height,
+ XDPSStandardColormap *rgbMap,
+ XDPSStandardColormap *grayMap,
+ unsigned int flags,
+ DPSPointer *pushCookieReturn)
+{
+ ContextInfo c = FindContextInfo(context);
+ int status;
+
+ if (c == NULL) return dps_status_unregistered_context;
+
+ DPSgsave(context);
+
+ status = XDPSSetContextParameters(context, screen, depth, drawable, height,
+ rgbMap, grayMap, flags);
+
+ *pushCookieReturn = (DPSPointer) context;
+ return status;
+}
+
+int XDPSPopContextParameters(DPSPointer pushCookie)
+{
+ DPSContext context = (DPSContext) pushCookie;
+ ContextInfo c = FindContextInfo(context);
+
+ if (c == NULL) return dps_status_illegal_value;
+
+ DPSgrestore(context);
+
+ return dps_status_success;
+}
+
+int XDPSCaptureContextGState(DPSContext context, DPSGState *gsReturn)
+{
+ *gsReturn = DPSNewUserObjectIndex();
+ /* We want to keep 0 as an unassigned value */
+ if (*gsReturn == 0) *gsReturn = DPSNewUserObjectIndex();
+
+ _DPSSCaptureGState(context, *gsReturn);
+
+ return dps_status_success;
+}
+
+int XDPSUpdateContextGState(DPSContext context, DPSGState gs)
+{
+ _DPSSUpdateGState(context, gs);
+
+ return dps_status_success;
+}
+
+int XDPSFreeContextGState(DPSContext context, DPSGState gs)
+{
+ _DPSSUndefineUserObject(context, gs);
+
+ return dps_status_success;
+}
+
+int XDPSSetContextGState(
+ DPSContext context,
+ DPSGState gs)
+{
+ _DPSSRestoreGState(context, gs);
+
+ return dps_status_success;
+}
+
+int XDPSPushContextGState(
+ DPSContext context,
+ DPSGState gs,
+ DPSPointer *pushCookieReturn)
+{
+ int status;
+
+ DPSgsave(context);
+
+ status = XDPSSetContextGState(context, gs);
+ *pushCookieReturn = (DPSPointer) context;
+ return status;
+}
+
+int XDPSPopContextGState(DPSPointer pushCookie)
+{
+ DPSContext context = (DPSContext) pushCookie;
+
+ DPSgrestore(context);
+ return dps_status_success;
+}
+
+void XDPSRegisterContext(DPSContext context, Bool makeSharedContext)
+{
+ Display *display;
+ Bool inited;
+ ContextInfo c;
+
+ /* Get the display */
+ (void) XDPSXIDFromContext(&display, context);
+
+ if (makeSharedContext) { /* Install as shared ctxt for this display */
+ c = LookupContext(display, context);
+ c->displayInfo->defaultContext = context;
+ } else { /* Just add to the context list */
+ c = LookupContext(display, context);
+ }
+
+ c->displayInfo->extensionPresent = ext_yes;
+
+ (void) _XDPSTestComponentInitialized(context, dps_init_bit_share, &inited);
+ if (!inited) {
+ (void) _XDPSSetComponentInitialized(context, dps_init_bit_share);
+ _DPSSInstallDPSlibDict(context);
+ }
+}
+
+DPSContext XDPSGetSharedContext(Display *display)
+{
+ DisplayInfo d = LookupDisplayInfo(display);
+ ContextInfo c;
+ DPSContext context;
+
+ if (d->extensionPresent == ext_no) return NULL;
+
+ if (d->defaultContext != NULL) context = d->defaultContext;
+ else {
+ context = XDPSCreateSimpleContext(display,
+ None, None, 0, 0,
+ DPSDefaultTextBackstop,
+ DPSDefaultErrorProc, NULL);
+ if (context != NULL) {
+ c = AllocContextInfo(context);
+ d->defaultContext = context;
+ c->displayInfo = d;
+ (void) _XDPSSetComponentInitialized(context, dps_init_bit_share);
+ _DPSSInstallDPSlibDict(context);
+ (void) XDPSSetContextDepth(context,
+ DefaultScreenOfDisplay(display),
+ DefaultDepth(display,
+ DefaultScreen(display)));
+ }
+ }
+
+ if (context == NULL) d->extensionPresent = ext_no;
+ else d->extensionPresent = ext_yes;
+
+ return context;
+}
+
+void XDPSDestroySharedContext(DPSContext context)
+{
+ ContextInfo c = RemoveContextInfo(context);
+
+ if (c == NULL) return;
+
+ if (c->displayInfo->defaultContext == context) {
+ c->displayInfo->defaultContext = NULL;
+ }
+ DPSDestroySpace(DPSSpaceFromContext(context)); /* Also gets context */
+ if (c->text != NULL) DPSDestroySpace(DPSSpaceFromContext(c->text));
+ free((char *) c);
+}
+
+void XDPSUnregisterContext(DPSContext context)
+{
+ ContextInfo c = RemoveContextInfo(context);
+
+ if (c == NULL) return;
+
+ if (c->displayInfo->defaultContext == context) {
+ c->displayInfo->defaultContext = NULL;
+ }
+ if (c->text != NULL) DPSDestroySpace(DPSSpaceFromContext(c->text));
+ free((char *) c);
+}
+
+void XDPSFreeDisplayInfo(Display *display)
+{
+ DisplayInfo *dp = &displayList;
+ DisplayInfo d;
+ register int i, j;
+
+ while (*dp != NULL && (*dp)->display != display) dp = &((*dp)->next);
+
+ if (*dp == NULL) return;
+
+ d = *dp;
+ *dp = d->next; /* remove from list */
+
+ for (i = 0; i < ScreenCount(display); i++) {
+#ifdef NO_XLISTDEPTHS
+ free((char *) d->validDepths[i]);
+#else
+ XFree((char *) d->validDepths[i]);
+#endif
+ for (j = 0; j < d->depthsForScreen[i]; j++) {
+ if (d->gcForDepth[i][j] != 0) {
+ XFreeGC(display, d->gcForDepth[i][j]);
+ }
+ }
+ }
+
+ free((char *) d->depthsForScreen);
+ free((char *) d->validDepths);
+ free((char *) d->gcForDepth);
+ free((char *) d);
+}
+
+int XDPSChainTextContext(DPSContext context, Bool enable)
+{
+ ContextInfo c = FindContextInfo(context);
+
+ if (c == NULL) return dps_status_unregistered_context;
+
+ /* Check if already in desired state */
+
+ if (c->enableText == enable) return dps_status_success;
+
+ if (enable) {
+ if (c->text == NULL) {
+ c->text = DPSCreateTextContext(DPSDefaultTextBackstop,
+ DPSDefaultErrorProc);
+ if (c->text == NULL) return dps_status_no_extension;
+ }
+ DPSChainContext(context, c->text);
+ c->enableText = True;
+ return dps_status_success;
+ }
+
+ /* disabling, currently enabled */
+
+ DPSUnchainContext(c->text);
+ c->enableText = False;
+ return dps_status_success;
+}
+
+Bool XDPSExtensionPresent(Display *display)
+{
+ DisplayInfo d = LookupDisplayInfo(display);
+
+ if (d->extensionPresent != ext_no_idea) {
+ return (d->extensionPresent == ext_yes);
+ }
+
+ /* Check if the extension is present by trying to initialize it */
+
+ if (XDPSLInit(display, (int *) NULL, (char **) NULL) == -1) {
+ d->extensionPresent = ext_no;
+ } else d->extensionPresent = ext_yes;
+
+ return (d->extensionPresent == ext_yes);
+}
+
+int PSDefineAsUserObj(void)
+{
+ return DPSDefineAsUserObj(DPSGetCurrentContext());
+}
+
+void PSRedefineUserObj(int uo)
+{
+ DPSRedefineUserObj(DPSGetCurrentContext(), uo);
+}
+
+void PSUndefineUserObj(int uo)
+{
+ DPSUndefineUserObj(DPSGetCurrentContext(), uo);
+}
+
+int DPSDefineAsUserObj(DPSContext ctxt)
+{
+ int out = DPSNewUserObjectIndex();
+ /* We want to keep 0 as an unassigned value */
+ if (out == 0) out = DPSNewUserObjectIndex();
+
+ _DPSSDefineUserObject(ctxt, out);
+ return out;
+}
+
+void DPSRedefineUserObj(DPSContext ctxt, int uo)
+{
+ _DPSSDefineUserObject(ctxt, uo);
+}
+
+void DPSUndefineUserObj(DPSContext ctxt, int uo)
+{
+ _DPSSUndefineUserObject(ctxt, uo);
+}
+
+int PSReserveUserObjIndices(int number)
+{
+ return DPSReserveUserObjIndices(DPSGetCurrentContext(), number);
+}
+
+int DPSReserveUserObjIndices(DPSContext ctxt, int number)
+{
+ int out = DPSNewUserObjectIndex();
+
+ /* We want to keep 0 as an unassigned value */
+ if (out == 0) out = DPSNewUserObjectIndex();
+
+ number--;
+ while (number-- > 0) (void) DPSNewUserObjectIndex();
+ return out;
+}
+
+void PSReturnUserObjIndices(int start, int number)
+{
+ DPSReturnUserObjIndices(DPSGetCurrentContext(), start, number);
+}
+
+void DPSReturnUserObjIndices(DPSContext ctxt, int start, int number)
+{
+ /* Nothing left any more */
+}
+
+#ifdef NO_XLISTDEPTHS
+/* This function copyright 1989 Massachusetts Institute of Technology */
+
+/*
+ * XListDepths - return info from connection setup
+ */
+int *XListDepths (
+ Display *dpy,
+ int scrnum,
+ int *countp)
+{
+ Screen *scr;
+ int count;
+ int *depths;
+
+ if (scrnum < 0 || scrnum >= dpy->nscreens) return NULL;
+
+ scr = &dpy->screens[scrnum];
+ if ((count = scr->ndepths) > 0) {
+ register Depth *dp;
+ register int i;
+
+ depths = (int *) malloc (count * sizeof(int));
+ if (!depths) return NULL;
+ for (i = 0, dp = scr->depths; i < count; i++, dp++)
+ depths[i] = dp->depth;
+ } else {
+ /* a screen must have a depth */
+ return NULL;
+ }
+ *countp = count;
+ return depths;
+}
+#endif /* NO_XLISTDEPTHS */
diff --git a/nx-X11/lib/dpstk/XDPSswraps.psw b/nx-X11/lib/dpstk/XDPSswraps.psw
new file mode 100644
index 000000000..f878c765a
--- /dev/null
+++ b/nx-X11/lib/dpstk/XDPSswraps.psw
@@ -0,0 +1,110 @@
+/*
+ * XDPSswraps.psw
+ *
+ * (c) Copyright 1990-1994 Adobe Systems Incorporated.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sublicense this software
+ * and its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notices appear in all copies and that
+ * both those copyright notices and this permission notice appear in
+ * supporting documentation and that the name of Adobe Systems Incorporated
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. No trademark license
+ * to use the Adobe trademarks is hereby granted. If the Adobe trademark
+ * "Display PostScript"(tm) is used to describe this software, its
+ * functionality or for any other purpose, such use shall be limited to a
+ * statement that this software works in conjunction with the Display
+ * PostScript system. Proper trademark attribution to reflect Adobe's
+ * ownership of the trademark shall be given whenever any such reference to
+ * the Display PostScript system is made.
+ *
+ * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
+ * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
+ * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
+ * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
+ * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
+ *
+ * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+ * Incorporated which may be registered in certain jurisdictions
+ *
+ * Author: Adobe Systems Incorporated
+ */
+
+defineps _DPSSSetContextParameters(DPSContext ctxt;
+ int gc, drawable, drawableHeight,
+ map, rgbBase, redMax, redMult,
+ greenMax, greenMult, blueMax, blueMult,
+ grayBase, grayMax, grayMult;
+ boolean doGC, doDrawable, doRGB, doGray)
+ $Adobe$DPS$Lib$Dict begin
+ currentXgcdrawablecolor
+ /colorinfo exch def
+
+ doGC {
+ 4 -1 roll pop gc 4 1 roll
+ } if
+
+ doDrawable {
+ pop pop 0 drawableHeight
+ 3 -1 roll pop drawable 3 1 roll
+ } if
+
+ doRGB {
+ colorinfo 3 redMax put
+ colorinfo 4 redMult put
+ colorinfo 5 greenMax put
+ colorinfo 6 greenMult put
+ colorinfo 7 blueMax put
+ colorinfo 8 blueMult put
+ colorinfo 9 rgbBase put
+ colorinfo 10 map put
+ } if
+
+ doGray {
+ colorinfo 0 grayMax put
+ colorinfo 1 grayMult put
+ colorinfo 2 grayBase put
+ colorinfo 10 map put
+ } if
+
+ colorinfo setXgcdrawablecolor
+ end
+endps
+
+defineps _DPSSSetContextDrawable(DPSContext ctxt;
+ int drawable, drawableHeight)
+ currentXgcdrawable
+ pop pop pop drawable 0 drawableHeight
+ setXgcdrawable
+endps
+
+defineps _DPSSInstallDPSlibDict(DPSContext c)
+ userdict /$Adobe$DPS$Lib$Dict 20 dict put
+endps
+
+defineps _DPSSCaptureGState(DPSContext c; int gs)
+ gs gstate defineuserobject
+endps
+
+defineps _DPSSUpdateGState(DPSContext c; userobject gs)
+ gs currentgstate pop
+endps
+
+defineps _DPSSRestoreGState(DPSContext c; userobject gs)
+ gs setgstate
+endps
+
+defineps _DPSSDefineUserObject(DPSContext c; int uo)
+ uo exch defineuserobject
+endps
+
+defineps _DPSSUndefineUserObject(DPSContext c; int uo)
+ uo undefineuserobject
+endps
+
diff --git a/nx-X11/lib/dpstk/XDPSuserpath.c b/nx-X11/lib/dpstk/XDPSuserpath.c
new file mode 100644
index 000000000..251f74574
--- /dev/null
+++ b/nx-X11/lib/dpstk/XDPSuserpath.c
@@ -0,0 +1,240 @@
+/*
+ * XDPSuserpath.c
+ *
+ * (c) Copyright 1990-1994 Adobe Systems Incorporated.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sublicense this software
+ * and its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notices appear in all copies and that
+ * both those copyright notices and this permission notice appear in
+ * supporting documentation and that the name of Adobe Systems Incorporated
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. No trademark license
+ * to use the Adobe trademarks is hereby granted. If the Adobe trademark
+ * "Display PostScript"(tm) is used to describe this software, its
+ * functionality or for any other purpose, such use shall be limited to a
+ * statement that this software works in conjunction with the Display
+ * PostScript system. Proper trademark attribution to reflect Adobe's
+ * ownership of the trademark shall be given whenever any such reference to
+ * the Display PostScript system is made.
+ *
+ * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
+ * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
+ * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
+ * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
+ * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
+ *
+ * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+ * Incorporated which may be registered in certain jurisdictions
+ *
+ * Author: Adobe Systems Incorporated
+ */
+/* $XFree86$ */
+
+#include <DPS/dpsXclient.h>
+#include <DPS/dpsops.h>
+#include <DPS/dpsXuserpath.h>
+
+typedef struct _t_NumStrHeader {
+ unsigned char type;
+ unsigned char representation;
+ unsigned short length;
+} NumStrHeader;
+
+void PSDoUserPath(coords, numCoords, numType, ops, numOps, bbox, action)
+ DPSPointer coords;
+ int numCoords;
+ DPSNumberFormat numType;
+ DPSUserPathOp *ops;
+ int numOps;
+ DPSPointer bbox;
+ DPSUserPathAction action;
+{
+ DPSDoUserPath(DPSGetCurrentContext(), coords, numCoords, numType, ops,
+ numOps, bbox, action);
+}
+
+void DPSDoUserPath(ctxt, coords, numCoords, numType, ops, numOps, bbox, action)
+ DPSContext ctxt;
+ DPSPointer coords;
+ int numCoords;
+ DPSNumberFormat numType;
+ DPSUserPathOp *ops;
+ int numOps;
+ DPSPointer bbox;
+ DPSUserPathAction action;
+{
+ typedef struct {
+ unsigned char tokenType;
+ unsigned char topLevelCount;
+ unsigned short nBytes;
+ DPSBinObjGeneric obj0;
+ DPSBinObjGeneric obj1;
+ DPSBinObjGeneric obj2;
+ DPSBinObjGeneric obj3;
+ } _dpsQ;
+ static _dpsQ _dpsF = {
+ DPS_DEF_TOKENTYPE, 0, 36, /* will fill in topLevelCount later */
+ {DPS_LITERAL|DPS_ARRAY, 0, 2, 16},
+ {DPS_EXEC|DPS_NAME, 0, DPSSYSNAME, 0},
+ {DPS_LITERAL|DPS_STRING, 0, 0, 32}, /* param nums */
+ {DPS_LITERAL|DPS_STRING, 0, 0, 32}, /* param ops */
+ }; /* _dpsQ */
+ register DPSBinObjRec *_dpsP = (DPSBinObjRec *)&_dpsF.obj0;
+ register int _dps_offset = 32;
+ int needBBox, hasUCache, numberSize;
+ DPSUserPathOp setbboxOp;
+ NumStrHeader nsHeader;
+
+ if (numType >= dps_short && numType < dps_float) numberSize = 2;
+ else numberSize = 4;
+
+ hasUCache = (*ops == dps_ucache);
+
+ if (hasUCache) {
+ needBBox = (numOps > 1 && ops[1] != dps_setbbox);
+ } else needBBox = (*ops != dps_setbbox);
+
+ if (needBBox) {
+ numOps += 1;
+ setbboxOp = dps_setbbox;
+ }
+
+ numCoords += 4; /* Account for bbox */
+
+ nsHeader.type = 149; /* Homogeneous Number Array */
+ nsHeader.representation = numType;
+ nsHeader.length = numCoords;
+
+ /* If we're using the send operation, we modify the sequence so that
+ it never gets to the action. This leaves a hole in the sequence,
+ but that's ok. */
+
+ if (action == dps_send) _dpsF.topLevelCount = 1;
+ else _dpsF.topLevelCount = 2;
+
+ _dpsP[1].val.nameVal = action;
+ _dpsP[2].length = (sizeof(NumStrHeader) + numCoords * numberSize);
+ _dpsP[3].length = numOps;
+ _dpsP[3].val.stringVal = _dps_offset;
+ _dps_offset += numOps;
+ _dpsP[2].val.stringVal = _dps_offset;
+ _dps_offset += _dpsP[2].length;
+ _dpsF.nBytes = _dps_offset+4;
+
+ if (needBBox) numOps -= 1;
+
+ numCoords -= 4; /* Unaccount for bbox */
+
+ DPSBinObjSeqWrite(ctxt, (char *) &_dpsF, 36);
+ if (needBBox) {
+ if (hasUCache) {
+ DPSWriteStringChars(ctxt, (char *) ops, 1);
+ ops++; numOps--;
+ }
+ DPSWriteStringChars(ctxt, (char *) &setbboxOp, 1);
+ }
+ DPSWriteStringChars(ctxt, (char *) ops, numOps);
+ DPSWriteStringChars(ctxt, (char *) &nsHeader, sizeof(NumStrHeader));
+ DPSWriteStringChars(ctxt, (char *) bbox, 4 * numberSize);
+ DPSWriteStringChars(ctxt, (char *) coords, numCoords * numberSize);
+}
+
+Bool PSHitUserPath(x, y, radius,
+ coords, numCoords, numType, ops, numOps, bbox, action)
+ double x, y, radius;
+ DPSPointer coords;
+ int numCoords;
+ DPSNumberFormat numType;
+ DPSUserPathOp *ops;
+ int numOps;
+ DPSPointer bbox;
+ DPSUserPathAction action;
+{
+ return DPSHitUserPath(DPSGetCurrentContext(), x, y, radius,
+ coords, numCoords, numType, ops,
+ numOps, bbox, action);
+}
+
+Bool DPSHitUserPath(ctxt, x, y, radius,
+ coords, numCoords, numType, ops, numOps, bbox, action)
+ DPSContext ctxt;
+ double x, y, radius;
+ DPSPointer coords;
+ int numCoords;
+ DPSNumberFormat numType;
+ DPSUserPathOp *ops;
+ int numOps;
+ DPSPointer bbox;
+ DPSUserPathAction action;
+{
+ float aCoords[5];
+ DPSUserPathOp aOps[1];
+ float aBbox[4];
+ int result;
+
+ if (radius != 0.0) {
+ aCoords[0] = x;
+ aCoords[1] = y;
+ aCoords[2] = radius;
+ aCoords[3] = 0.0;
+ aCoords[4] = 360.0;
+ aOps[0] = dps_arc;
+ aBbox[0] = x - radius;
+ aBbox[1] = y - radius;
+ aBbox[2] = x + radius;
+ aBbox[3] = y + radius;
+
+ switch (action) {
+ case dps_infill:
+ case dps_ineofill:
+ case dps_instroke:
+ DPSDoUserPath(ctxt, (DPSPointer) aCoords, 5, dps_float,
+ aOps, 1, (DPSPointer) aBbox, action);
+ break;
+ case dps_inufill:
+ case dps_inueofill:
+ case dps_inustroke:
+ DPSDoUserPath(ctxt, (DPSPointer) aCoords, 5, dps_float,
+ aOps, 1, (DPSPointer) aBbox, dps_send);
+ DPSDoUserPath(ctxt, coords, numCoords, numType, ops,
+ numOps, bbox, action);
+ break;
+ default:
+ return False;
+ }
+ DPSgetboolean(ctxt, &result);
+
+ } else {
+ switch (action) {
+ case dps_infill:
+ DPSinfill(ctxt, x, y, &result);
+ break;
+ case dps_ineofill:
+ DPSineofill(ctxt, x, y, &result);
+ break;
+ case dps_instroke:
+ DPSinstroke(ctxt, x, y, &result);
+ break;
+ case dps_inufill:
+ case dps_inueofill:
+ case dps_inustroke:
+ DPSsendfloat(ctxt, x);
+ DPSsendfloat(ctxt, y);
+ DPSDoUserPath(ctxt, coords, numCoords, numType, ops,
+ numOps, bbox, action);
+ DPSgetboolean(ctxt, &result);
+ break;
+ default:
+ return False;
+ }
+ }
+ return result;
+}
+
diff --git a/nx-X11/lib/dpstk/dpsXcommonI.h b/nx-X11/lib/dpstk/dpsXcommonI.h
new file mode 100644
index 000000000..2e91dc629
--- /dev/null
+++ b/nx-X11/lib/dpstk/dpsXcommonI.h
@@ -0,0 +1,73 @@
+/*
+ * dpsXcommonI.h
+ *
+ * (c) Copyright 1990-1994 Adobe Systems Incorporated.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sublicense this software
+ * and its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notices appear in all copies and that
+ * both those copyright notices and this permission notice appear in
+ * supporting documentation and that the name of Adobe Systems Incorporated
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. No trademark license
+ * to use the Adobe trademarks is hereby granted. If the Adobe trademark
+ * "Display PostScript"(tm) is used to describe this software, its
+ * functionality or for any other purpose, such use shall be limited to a
+ * statement that this software works in conjunction with the Display
+ * PostScript system. Proper trademark attribution to reflect Adobe's
+ * ownership of the trademark shall be given whenever any such reference to
+ * the Display PostScript system is made.
+ *
+ * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
+ * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
+ * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
+ * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
+ * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
+ *
+ * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+ * Incorporated which may be registered in certain jurisdictions
+ *
+ * Author: Adobe Systems Incorporated
+ */
+
+#ifndef DPS_X_COMMON_I_H
+#define DPS_X_COMMON_I_H
+
+#define dps_init_bit_share (1<<0)
+#define dps_init_bit_preview (1<<1)
+#define dps_init_bit_fsb (1<<2)
+#define dps_init_bit_csb (1<<3)
+#define dps_init_bit_dsw (1<<4)
+
+#ifdef _NO_PROTO
+
+extern int _XDPSSetComponentInitialized();
+
+extern int _XDPSTestComponentInitialized();
+
+#else /* _NO_PROTO */
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+extern int _XDPSSetComponentInitialized(DPSContext context,
+ unsigned long componentBit);
+
+extern int _XDPSTestComponentInitialized(DPSContext context,
+ unsigned long componentBit,
+ Bool *result);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* _NO_PROTO */
+
+#endif /* DPS_X_COMMON_I_H */
diff --git a/nx-X11/lib/dpstk/dpstk-def.cpp b/nx-X11/lib/dpstk/dpstk-def.cpp
new file mode 100644
index 000000000..ada432c37
--- /dev/null
+++ b/nx-X11/lib/dpstk/dpstk-def.cpp
@@ -0,0 +1,65 @@
+LIBRARY DPSTK
+VERSION LIBRARY_VERSION
+EXPORTS
+_DPSPCheckForError
+_DPSPClearArea
+_DPSPDefineExecFunction
+_DPSPSaveBeforeExec
+_DPSPSetMaskTransfer
+_DPSPSetMatrix
+_DPSSCaptureGState
+_DPSSDefineUserObject
+_DPSSInstallDPSlibDict
+_DPSSRestoreGState
+_DPSSSetContextDrawable
+_DPSSSetContextParameters
+_DPSSUndefineUserObject
+_DPSSUpdateGState
+DPSDefineAsUserObj
+DPSRedefineUserObj
+DPSReserveUserObjIndices
+DPSReturnUserObjIndices
+DPSUndefineUserObj
+PSDefineAsUserObj
+PSRedefineUserObj
+PSReserveUserObjIndices
+PSReturnUserObjIndices
+PSUndefineUserObj
+XDPSCaptureContextGState
+XDPSChainTextContext
+XDPSDestroySharedContext
+XDPSExtensionPresent
+XDPSFreeContextGState
+XDPSFreeDisplayInfo
+XDPSGetSharedContext
+XDPSPopContextGState
+XDPSPopContextParameters
+XDPSPushContextGState
+XDPSPushContextParameters
+XDPSRegisterContext
+XDPSSetContextDepth
+XDPSSetContextDrawable
+XDPSSetContextGState
+XDPSSetContextGrayMap
+XDPSSetContextParameters
+XDPSSetContextRGBMap
+XDPSUnregisterContext
+XDPSUpdateContextGState
+_XDPSSetComponentInitialized
+_XDPSTestComponentInitialized
+XDPSCheckImagingResults
+XDPSCreatePixmapForEPSF
+XDPSEmbeddedEPSFRewindFunc
+XDPSEmbeddedGetsFunc
+XDPSFileGetsFunc
+XDPSFileRewindFunc
+XDPSImageFileIntoDrawable
+XDPSPixelsPerPoint
+XDPSSetFileFunctions
+XDPSSetImagingTimeout
+DPSDoUserPath
+DPSHitUserPath
+PSDoUserPath
+PSHitUserPath
+
+/* $XFree86$ */
diff --git a/nx-X11/lib/dpstk/eyedrop16.xbm b/nx-X11/lib/dpstk/eyedrop16.xbm
new file mode 100644
index 000000000..2f5a772d7
--- /dev/null
+++ b/nx-X11/lib/dpstk/eyedrop16.xbm
@@ -0,0 +1,8 @@
+#define eyedrop16_width 16
+#define eyedrop16_height 16
+#define eyedrop16_x_hot 0
+#define eyedrop16_y_hot 13
+static unsigned char eyedrop16_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x03,
+ 0xc0, 0x07, 0xe0, 0x0f, 0xf0, 0x07, 0xf8, 0x03, 0xf8, 0x01, 0xf8, 0x00,
+ 0x7c, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x00};
diff --git a/nx-X11/lib/dpstk/eyedrop32.xbm b/nx-X11/lib/dpstk/eyedrop32.xbm
new file mode 100644
index 000000000..5bc98a02c
--- /dev/null
+++ b/nx-X11/lib/dpstk/eyedrop32.xbm
@@ -0,0 +1,16 @@
+#define eyedrop32_width 32
+#define eyedrop32_height 32
+#define eyedrop32_x_hot 0
+#define eyedrop32_y_hot 29
+static unsigned char eyedrop32_bits[] = {
+ 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, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xe0, 0x07, 0x00,
+ 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xfc, 0x07, 0x00,
+ 0x00, 0xfe, 0x03, 0x00, 0x00, 0xff, 0x01, 0x00, 0x80, 0xff, 0x00, 0x00,
+ 0xc0, 0x7f, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00,
+ 0xf8, 0x0f, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0xf8, 0x03, 0x00, 0x00,
+ 0xf8, 0x01, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/nx-X11/lib/dpstk/eyedropmask16.xbm b/nx-X11/lib/dpstk/eyedropmask16.xbm
new file mode 100644
index 000000000..e1a696dd6
--- /dev/null
+++ b/nx-X11/lib/dpstk/eyedropmask16.xbm
@@ -0,0 +1,8 @@
+#define eyedropmask16_width 16
+#define eyedropmask16_height 16
+#define eyedropmask16_x_hot 0
+#define eyedropmask16_y_hot 13
+static unsigned char eyedropmask16_bits[] = {
+ 0x00, 0x7c, 0x00, 0xfe, 0x80, 0xff, 0x00, 0xff, 0x80, 0xff, 0xc0, 0xff,
+ 0xe0, 0x7f, 0xf0, 0x3f, 0xf8, 0x2f, 0xfc, 0x07, 0xfc, 0x03, 0xfc, 0x01,
+ 0xfe, 0x00, 0x7f, 0x00, 0x0e, 0x00, 0x04, 0x00};
diff --git a/nx-X11/lib/dpstk/eyedropmask32.xbm b/nx-X11/lib/dpstk/eyedropmask32.xbm
new file mode 100644
index 000000000..8e12f00e7
--- /dev/null
+++ b/nx-X11/lib/dpstk/eyedropmask32.xbm
@@ -0,0 +1,16 @@
+#define eyedropmask32_width 32
+#define eyedropmask32_height 32
+#define eyedropmask32_x_hot 0
+#define eyedropmask32_y_hot 29
+static unsigned char eyedropmask32_bits[] = {
+ 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00, 0xf0, 0x7f,
+ 0x00, 0x00, 0xf8, 0xff, 0x00, 0x00, 0xfc, 0xff, 0x00, 0x00, 0xfe, 0xff,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0xc0, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff,
+ 0x00, 0xc0, 0xff, 0x7f, 0x00, 0x80, 0xff, 0x7f, 0x00, 0xc0, 0xff, 0x3f,
+ 0x00, 0xe0, 0xff, 0x1f, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0xf8, 0xff, 0x07,
+ 0x00, 0xfc, 0xff, 0x03, 0x00, 0xfe, 0xff, 0x01, 0x00, 0xff, 0xdf, 0x01,
+ 0x80, 0xff, 0x8f, 0x00, 0xc0, 0xff, 0x07, 0x00, 0xe0, 0xff, 0x03, 0x00,
+ 0xf0, 0xff, 0x01, 0x00, 0xf8, 0xff, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00,
+ 0xfc, 0x3f, 0x00, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00,
+ 0xfc, 0x07, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00};
diff --git a/nx-X11/lib/dpstk/heyedrop.xbm b/nx-X11/lib/dpstk/heyedrop.xbm
new file mode 100644
index 000000000..ea51ae599
--- /dev/null
+++ b/nx-X11/lib/dpstk/heyedrop.xbm
@@ -0,0 +1,7 @@
+#define heyedrop_width 32
+#define heyedrop_height 12
+static unsigned char heyedrop_bits[] = {
+ 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xf8, 0x3f, 0xe0, 0xff, 0xff, 0x7f,
+ 0x38, 0x00, 0xf8, 0xff, 0x0f, 0x00, 0xf8, 0xff, 0x00, 0x00, 0xf8, 0xff,
+ 0x00, 0x00, 0xf8, 0xff, 0x0f, 0x00, 0xf8, 0xff, 0x38, 0x00, 0xf8, 0xff,
+ 0xe0, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0x08, 0x00};
diff --git a/nx-X11/lib/dpstk/square.xbm b/nx-X11/lib/dpstk/square.xbm
new file mode 100644
index 000000000..d05789431
--- /dev/null
+++ b/nx-X11/lib/dpstk/square.xbm
@@ -0,0 +1,8 @@
+#define square_width 16
+#define square_height 16
+#define square_x_hot 6
+#define square_y_hot 6
+static unsigned char square_bits[] = {
+ 0x00, 0x00, 0xfe, 0x0f, 0xfe, 0x0f, 0xfe, 0x0f, 0xfe, 0x0f, 0xfe, 0x0f,
+ 0xfe, 0x0f, 0xfe, 0x0f, 0xfe, 0x0f, 0xfe, 0x0f, 0xfe, 0x0f, 0xfe, 0x0f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/nx-X11/lib/dpstk/squaremask.xbm b/nx-X11/lib/dpstk/squaremask.xbm
new file mode 100644
index 000000000..ea2e0d96b
--- /dev/null
+++ b/nx-X11/lib/dpstk/squaremask.xbm
@@ -0,0 +1,6 @@
+#define squaremask_width 16
+#define squaremask_height 16
+static unsigned char squaremask_bits[] = {
+ 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f,
+ 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f,
+ 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};