diff options
author | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
---|---|---|
committer | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
commit | f4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch) | |
tree | 2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/lib/dpstk | |
parent | a840692edc9c6d19cd7c057f68e39c7d95eb767d (diff) | |
download | nx-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')
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, ¤tShared); + 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}; |