#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>
#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
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
};
#ifndef SAMPLER_DEFAULT_SIZE_LIST_COUNT
#define SAMPLER_DEFAULT_SIZE_LIST_COUNT 10
#endif
#ifndef SAMPLER_DEFAULT_SIZE
#define SAMPLER_DEFAULT_SIZE 24.0
#endif
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},
};
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 = {
{
(WidgetClass) &xmManagerClassRec,
"FontSampler",
sizeof(FontSamplerRec),
ClassInitialize,
ClassPartInitialize,
False,
Initialize,
NULL,
XtInheritRealize,
actions,
XtNumber(actions),
resources,
XtNumber(resources),
NULLQUARK,
True,
XtExposeCompressMultiple,
True,
False,
Destroy,
Resize,
NULL,
SetValues,
NULL,
XtInheritSetValuesAlmost,
NULL,
NULL,
XtVersion,
NULL,
NULL,
XtInheritQueryGeometry,
NULL,
NULL,
},
{
GeometryManager,
ChangeManaged,
XtInheritInsertChild,
XtInheritDeleteChild,
NULL,
},
{
NULL,
0,
0,
NULL,
NULL,
NULL,
NULL,
},
{
XtInheritTranslations,
NULL,
0,
NULL,
0,
XmInheritParentProcess,
NULL,
},
{
Cancel,
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);
}
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;
}
}
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);
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);
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);
}
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;
}
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);
}
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;
}
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);
}
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);
}
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);
}
}
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);
}
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, "");
}
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;
}
static Boolean changingSize = False;
static void TextVerify(Widget widget, XtPointer clientData, XtPointer callData)
{
int i;
XmTextVerifyPtr v = (XmTextVerifyPtr) callData;
char ch, *cp;
int decimalPoints = 0;
if (changingSize) return;
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;
}
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);
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);
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);
}
static void Initialize(
Widget request, Widget new,
ArgList args,
Cardinal *num_args)
{
FontSamplerWidget sampler = (FontSamplerWidget) new;
if (sampler->sampler.fsb == NULL) {
XtAppErrorMsg(XtWidgetToApplicationContext(new),
"initializeFontSampler", "noFontSelectionBox",
"FontSelectionBoxError",
"No font selection box given to font sampler",
(String *) NULL, (Cardinal *) NULL);
}
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;
}
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;
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) {
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;
}
static Boolean MatchRoman(String name, FilterRec *filter)
{
FilterRec *f;
char *ch, **search, *start;
int len;
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);
}
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;
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 (anyset && !foundone) return False;
if (anyset && foundone) allmatch = True;
}
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);
}
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;
}
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