/* Copyright 2001-2003 by Norbert Freudemann, David Frese */ #include "xlib.h" #define scx_extract_gc_function(x) S48_EXTRACT_ENUM(x, "scx-gc-function") #define scx_extract_line_style(x) S48_EXTRACT_ENUM(x, "scx-line-style") #define scx_extract_cap_style(x) S48_EXTRACT_ENUM(x, "scx-cap-style") #define scx_extract_join_style(x) S48_EXTRACT_ENUM(x, "scx-join-style") #define scx_extract_fill_style(x) S48_EXTRACT_ENUM(x, "scx-fill-style") #define scx_extract_fill_rule(x) S48_EXTRACT_ENUM(x, "scx-fill-rule") #define scx_extract_subwindow_mode(x) S48_EXTRACT_ENUM(x, "scx-subwindow-mode") #define scx_extract_arc_mode(x) S48_EXTRACT_ENUM(x, "scx-arc-mode") #define scx_enter_gc_function(x) S48_ENTER_ENUM(x, "scx-gc-functions") #define scx_enter_line_style(x) S48_ENTER_ENUM(x, "scx-line-styles") #define scx_enter_cap_style(x) S48_ENTER_ENUM(x, "scx-cap-styles") #define scx_enter_join_style(x) S48_ENTER_ENUM(x, "scx-join-styles") #define scx_enter_fill_style(x) S48_ENTER_ENUM(x, "scx-fill-styles") #define scx_enter_fill_rule(x) S48_ENTER_ENUM(x, "scx-fill-rules") #define scx_enter_subwindow_mode(x) S48_ENTER_ENUM(x, "scx-subwindow-modes") #define scx_enter_arc_mode(x) S48_ENTER_ENUM(x, "scx-arc-modes") #define scx_extract_gc_value_set(x) S48_EXTRACT_ENUM_SET(x, "scx-gc-value-set") #define scx_enter_gc_value_set(x) s48_enter_enum_set(x, "scx-gc-value-set") s48_value scx_enter_charstruct(XCharStruct* cs) { s48_value res = s48_make_record(s48_get_imported_binding("scx-char-struct")); S48_DECLARE_GC_PROTECT(1); S48_GC_PROTECT_1(res); S48_RECORD_SET(res, 0, s48_enter_fixnum(cs->lbearing)); S48_RECORD_SET(res, 1, s48_enter_fixnum(cs->rbearing)); S48_RECORD_SET(res, 2, s48_enter_fixnum(cs->width)); S48_RECORD_SET(res, 3, s48_enter_fixnum(cs->ascent)); S48_RECORD_SET(res, 4, s48_enter_fixnum(cs->descent)); S48_RECORD_SET(res, 5, s48_enter_integer(cs->attributes)); S48_GC_UNPROTECT(); return res; } s48_value scx_enter_fontstruct(XFontStruct* fs) { int i; s48_value plist = S48_NULL, t = S48_NULL; s48_value res = s48_make_record(s48_get_imported_binding("scx-font-struct")); S48_DECLARE_GC_PROTECT(3); S48_GC_PROTECT_3(res, plist, t); S48_RECORD_SET(res, 0, S48_ENTER_POINTER(fs)); S48_RECORD_SET(res, 1, scx_enter_font(fs->fid)); S48_RECORD_SET(res, 2, scx_enter_font_direction(fs->direction)); S48_RECORD_SET(res, 3, s48_enter_integer(fs->min_char_or_byte2)); S48_RECORD_SET(res, 4, s48_enter_integer(fs->max_char_or_byte2)); S48_RECORD_SET(res, 5, s48_enter_integer(fs->min_byte1)); S48_RECORD_SET(res, 6, s48_enter_integer(fs->max_byte1)); S48_RECORD_SET(res, 7, S48_ENTER_BOOLEAN(fs->all_chars_exist)); S48_RECORD_SET(res, 8, s48_enter_integer(fs->default_char)); for (i = fs->n_properties-1; i >= 0; i--) { t = s48_cons(scx_enter_atom(fs->properties[i].name), s48_enter_integer(fs->properties[i].card32)); plist = s48_cons(t, plist); } S48_RECORD_SET(res, 9, plist); S48_RECORD_SET(res, 10, scx_enter_charstruct(&fs->min_bounds)); S48_RECORD_SET(res, 11, scx_enter_charstruct(&fs->max_bounds)); { int count; if ((fs->min_byte1 == 0) && (fs->max_byte1 == 0)) count = (fs->max_char_or_byte2 - fs->min_char_or_byte2); else count = (fs->max_char_or_byte2 - fs->min_char_or_byte2) * 256 - fs->min_byte1 + fs->max_byte1; t = s48_make_vector(count, S48_FALSE); for (i = 0; i < count; i++) S48_VECTOR_SET(t, i, scx_enter_charstruct(&fs->per_char[i])); S48_RECORD_SET(res, 12, t); } S48_RECORD_SET(res, 13, s48_enter_integer(fs->ascent)); S48_RECORD_SET(res, 14, s48_enter_integer(fs->descent)); S48_GC_UNPROTECT(); return res; } s48_value scx_enter_gc(GC gc) { s48_value v = s48_make_record(scx_gc); S48_DECLARE_GC_PROTECT(1); S48_GC_PROTECT_1(v); S48_RECORD_SET(v, 0, S48_ENTER_POINTER(gc)); S48_GC_UNPROTECT(); return v; } unsigned long scx_extract_gc_value_alist(s48_value values, XGCValues* GCV) { unsigned long mask = 0; while (values != S48_NULL) { int mv = scx_extract_gc_value(S48_CAR(S48_CAR(values))); s48_value v = S48_CDR(S48_CAR(values)); values = S48_CDR(values); mask = mask | (1L << mv); switch (1L << mv) { case GCFunction: GCV->function = scx_extract_gc_function(v); break; case GCPlaneMask: GCV->plane_mask = scx_extract_pixel(v); break; case GCForeground: GCV->foreground = scx_extract_pixel(v); break; case GCBackground: GCV->background = scx_extract_pixel(v); break; case GCLineWidth: GCV->line_width = s48_extract_integer(v); break; case GCLineStyle: GCV->line_style = scx_extract_line_style(v); break; case GCCapStyle: GCV->cap_style = scx_extract_cap_style(v); break; case GCJoinStyle: GCV->join_style = scx_extract_join_style(v); break; case GCFillStyle: GCV->fill_style = scx_extract_fill_style(v); break; case GCFillRule: GCV->fill_rule = scx_extract_fill_rule(v); break; case GCTile: GCV->tile = scx_extract_pixmap(v); break; case GCStipple: GCV->stipple = scx_extract_pixmap(v); break; case GCTileStipXOrigin: GCV->ts_x_origin = s48_extract_integer(v); break; case GCTileStipYOrigin: GCV->ts_y_origin = s48_extract_integer(v); break; case GCFont: GCV->font = scx_extract_font(v); break; case GCSubwindowMode: GCV->subwindow_mode = scx_extract_subwindow_mode(v); break; case GCGraphicsExposures: GCV->graphics_exposures = S48_EXTRACT_BOOLEAN(v); break; case GCClipXOrigin: GCV->clip_x_origin = s48_extract_integer(v); break; case GCClipYOrigin: GCV->clip_y_origin = s48_extract_integer(v); break; case GCClipMask: GCV->clip_mask = scx_extract_pixmap(v); break; case GCDashOffset: GCV->dash_offset = s48_extract_integer(v); break; case GCDashList: GCV->dashes = (char)s48_extract_integer(v); break; case GCArcMode: GCV->arc_mode = scx_extract_arc_mode(v); break; } } return mask; } static s48_value scx_enter_gc_value_alist(s48_value values, XGCValues* GCV) { S48_DECLARE_GC_PROTECT(1); s48_value res = S48_NULL; s48_value v = S48_FALSE; S48_GC_PROTECT_3(res, v, values); while (values != S48_NULL) { int mv = scx_extract_gc_value(S48_CAR(values)); switch (1L << mv) { case GCFunction: v = scx_extract_gc_function(GCV->function); break; case GCPlaneMask: v = scx_enter_pixel(GCV->plane_mask); break; case GCForeground: v = scx_enter_pixel(GCV->foreground); break; case GCBackground: v = scx_enter_pixel(GCV->background); break; case GCLineWidth: v = s48_enter_integer(GCV->line_width); break; case GCLineStyle: v = scx_enter_line_style(GCV->line_style); break; case GCCapStyle: v = scx_enter_cap_style(GCV->cap_style); break; case GCJoinStyle: v = scx_enter_join_style(GCV->join_style); break; case GCFillStyle: v = scx_enter_fill_style(GCV->fill_style); break; case GCFillRule: v = scx_enter_fill_rule(GCV->fill_rule); break; case GCTile: v = scx_enter_pixmap(GCV->tile); break; case GCStipple: v = scx_enter_pixmap(GCV->stipple); break; case GCTileStipXOrigin: v = s48_enter_integer(GCV->ts_x_origin); break; case GCTileStipYOrigin: v = s48_enter_integer(GCV->ts_y_origin); break; case GCFont: v = scx_enter_font(GCV->font); break; case GCSubwindowMode: v = scx_enter_subwindow_mode(GCV->subwindow_mode); break; case GCGraphicsExposures: v = S48_ENTER_BOOLEAN(GCV->graphics_exposures); break; case GCClipXOrigin: v = s48_enter_integer(GCV->clip_x_origin); break; case GCClipYOrigin: v = s48_enter_integer(GCV->clip_y_origin); break; case GCClipMask: v = scx_enter_pixmap(GCV->clip_mask); break; case GCDashOffset: v = s48_enter_integer(GCV->dash_offset); break; case GCDashList: v = s48_enter_integer(GCV->dashes); break; case GCArcMode: v = scx_enter_arc_mode(GCV->arc_mode); break; } v = s48_cons(S48_CAR(values), v); res = s48_cons(v, res); values = S48_CDR(values); } S48_GC_UNPROTECT(); return res; } s48_value scx_Create_Gc(s48_value display, s48_value drawable, s48_value values) { XGCValues GCV; unsigned long mask = scx_extract_gc_value_alist(values, &GCV); GC gc = XCreateGC(scx_extract_display(display), scx_extract_drawable(drawable), mask, &GCV); return scx_enter_gc(gc); } s48_value scx_Copy_Gc(s48_value display, s48_value source, s48_value mask, s48_value dest) { XCopyGC(scx_extract_display(display), scx_extract_gc(source), scx_extract_gc_value_set(mask), scx_extract_gc(dest)); return S48_UNSPECIFIC; } s48_value scx_Change_Gc(s48_value display, s48_value gc, s48_value values) { XGCValues GCV; unsigned long mask = scx_extract_gc_value_alist(values, &GCV); XChangeGC(scx_extract_display(display), scx_extract_gc(gc), mask, &GCV); return S48_UNSPECIFIC; } #define ValidGCValuesBits \ (GCFunction | GCPlaneMask | GCForeground | GCBackground | GCLineWidth |\ GCLineStyle | GCCapStyle | GCJoinStyle | GCFillStyle | GCFillRule |\ GCTile | GCStipple | GCTileStipXOrigin | GCTileStipYOrigin | GCFont |\ GCSubwindowMode | GCGraphicsExposures | GCClipXOrigin | GCClipYOrigin |\ GCDashOffset | GCArcMode) s48_value scx_Get_Gc_Values(s48_value display, s48_value gc, s48_value values) { unsigned long mask = 0; XGCValues GCV; for (; values != S48_NULL; values = S48_CDR(values)) mask |= (1L << scx_extract_gc_value(S48_CAR(values))); if (!XGetGCValues(scx_extract_display(display), scx_extract_gc(gc), mask, &GCV)) return S48_FALSE; else return scx_enter_gc_value_alist(values, &GCV); } s48_value scx_Free_Gc(s48_value display, s48_value gc) { XFreeGC(scx_extract_display(display), scx_extract_gc(gc)); return S48_UNSPECIFIC; } s48_value scx_GContext_From_Gc(s48_value gc) { return scx_enter_gcontext(XGContextFromGC(scx_extract_gc(gc))); } s48_value scx_Set_Dashes(s48_value display, s48_value gc, s48_value dashoffset, s48_value dashlist) { int i, n = s48_list_length(dashlist); char dl[n]; for (i = 0; i < n; i++) { dl[i] = s48_extract_integer(S48_CAR(dashlist)); dashlist = S48_CDR(dashlist); } XSetDashes(scx_extract_display(display), scx_extract_gc(gc), s48_extract_integer(dashoffset), dl, n); return S48_UNSPECIFIC; } #define scx_extract_rectangle_ordering(x) \ S48_EXTRACT_ENUM(x, "scx-rectangle-ordering") s48_value scx_Set_Clip_Rectangles(s48_value display, s48_value gc, s48_value x_origin, s48_value y_origin, s48_value rects, s48_value ordering) { //TODO int i, n = s48_list_length(rects); XRectangle crects[n]; for (i = 0; i < n; i++) { s48_value r = S48_CAR(rects); crects[i].x = s48_extract_integer(S48_CAR(r)); r = S48_CDR(r); crects[i].y = s48_extract_integer(S48_CAR(r)); r = S48_CDR(r); crects[i].width = s48_extract_integer(S48_CAR(r)); r = S48_CDR(r); crects[i].height = s48_extract_integer(S48_CAR(r)); r = S48_CDR(r); rects = S48_CDR(rects); } XSetClipRectangles(scx_extract_display(display), scx_extract_gc(gc), s48_extract_integer(x_origin), s48_extract_integer(y_origin), crects, n, scx_extract_rectangle_ordering(ordering)); return S48_UNSPECIFIC; } s48_value scx_Query_Best_Size(s48_value screen, s48_value class, s48_value width, s48_value height) { unsigned int rw, rh; Screen* s = scx_extract_screen(screen); if (!XQueryBestSize(s->display, s48_extract_integer(class), s->root, (int)s48_extract_integer(width), (int)s48_extract_integer(height), &rw, &rh)) return S48_FALSE; else return s48_cons(s48_enter_fixnum(rw), s48_enter_fixnum(rh)); } void scx_init_gcontext(void) { S48_EXPORT_FUNCTION(scx_Create_Gc); S48_EXPORT_FUNCTION(scx_Copy_Gc); S48_EXPORT_FUNCTION(scx_Change_Gc); S48_EXPORT_FUNCTION(scx_Get_Gc_Values); S48_EXPORT_FUNCTION(scx_Free_Gc); S48_EXPORT_FUNCTION(scx_GContext_From_Gc); S48_EXPORT_FUNCTION(scx_Set_Dashes); S48_EXPORT_FUNCTION(scx_Set_Clip_Rectangles); S48_EXPORT_FUNCTION(scx_Query_Best_Size); }