aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/lib/dpstk/FontSample.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/lib/dpstk/FontSample.c')
-rw-r--r--nx-X11/lib/dpstk/FontSample.c1814
1 files changed, 1814 insertions, 0 deletions
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 */