>From 7a83f54d65856e6df4df2dd45788aa176b36045c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=B6rnquist?= Date: Mon, 29 Apr 2019 09:08:49 +0200 Subject: [PATCH 1/7] Rename xlib.c => guile-xlib.c, create guile-xlib.h. This slightly restructures the project into being more of a library, even in C space. --- Makefile.am | 4 +- configure.ac | 5 +- xlib.c => guile-xlib.c | 229 ++--------------------------------------- guile-xlib.h | 228 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 239 insertions(+), 227 deletions(-) rename xlib.c => guile-xlib.c (91%) create mode 100644 guile-xlib.h diff --git a/Makefile.am b/Makefile.am index 12b466e..4720a63 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,8 +9,8 @@ AUTOMAKE_OPTIONS = gnu lib_LTLIBRARIES = libguilexlib.la -BUILT_SOURCES = xlib.x -libguilexlib_la_SOURCES = xlib.c $(BUILT_SOURCES) +BUILT_SOURCES = guile-xlib.x +libguilexlib_la_SOURCES = guile-xlib.c $(BUILT_SOURCES) libguilexlib_la_LDFLAGS = -version-info 0:0 -export-dynamic libguilexlib_la_CFLAGS = $(GUILE_CFLAGS) libguilexlib_la_LIBADD = $(X_LIBS) $(X_PRE_LIBS) -lX11 $(X_EXTRA_LIBS) $(GUILE_LIBS) diff --git a/configure.ac b/configure.ac index 1120f0d..1bfe878 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,6 @@ -AC_INIT(xlib.c) -AM_INIT_AUTOMAKE(guile2-xlib, 0.1) +AC_INIT(guile2-xlib, 0.1) +AC_CONFIG_SRCDIR(guile-xlib.c) +AM_INIT_AUTOMAKE AC_CONFIG_MACRO_DIR([m4]) AM_MAINTAINER_MODE diff --git a/xlib.c b/guile-xlib.c similarity index 91% rename from xlib.c rename to guile-xlib.c index 54d7be8..d829b22 100644 --- a/xlib.c +++ b/guile-xlib.c @@ -1,3 +1,5 @@ +#include "guile-xlib.h" + #include #include #include @@ -10,152 +12,6 @@ # define SCM_STRING_CHARS(x) (SCM_ROCHARS(x)) #endif -/* Note on differences between this interface and raw Xlib in C. - - Some differences are inevitable. When the power of Xlib is made - available in an general purpose interpreted environment like Guile, - we need to make sure that the interface cannot be called in a way - that would cause the environment as a whole to crash or hang. For - example, in C you can call XCloseDisplay and then, say, - XDestroyWindow for the display that you have just closed; and your - program will probably hang or crash as a result. An interface like - the one implemented here must protect the environment against such - problems by detecting and rejecting invalid usage. - - In practice, this means that the interface needs to track the - current state of X resources like displays and windows. So the - Guile Xlib interface differs from C Xlib at least in that it stores - certain additional state information and uses this information to - detect and disallow invalid usage. - - Given that some difference is inevitable, one piece of Schemely - behaviour is sufficiently useful - and sufficiently easier to - implement in this interface than in a Scheme layer above it - that - it merits a further small departure from C Xlib. This is the - automatic freeing of X resources when the interface-level objects - associated with them are garbage collected. It applies to displays - (using XCloseDisplay), windows (XDestroyWindow) and non-default gcs - (XFreeGC). Note that it is still possible to free these resources - explicitly, using the x-close-display!, x-destroy-window! and - x-free-gc! primitives respectively. - - Many further differences (between this interface and C Xlib) are - possible, but none are compelling. The X people presumably thought - quite carefully about the structure and completeness of the Xlib - interface, and that's worth benefitting from. Layers presenting a - graphical X interface with a different structure, or from a - different angle, can easily be implemented in Scheme on top of - this one. */ - - -/* Note on garbage collection and freeing of X resources. - - The one wrinkle in implementing automatic freeing of X resources is - that almost all X resources depend on a valid display, so we have - to be careful that the display resource is always freed (using - XCloseDisplay) last of all. - - In most cases this is handled by having resource smobs include a - reference to the display smob. But there is still a problem when - all remaining X resource references are dropped between one GC - cycle and the next: when this happens, the next GC sweep could free - the display smob before it gets to some of the other resource - smobs. - - Fortunately, resource smobs can check, in their free functions, - whether this has happened, by looking at the SCM_TYP16 of their - reference to the display smob. If the display smob is still valid, - this will be scm_tc16_xdisplay, and the relevant X resource should - be freed as normal. If the display smob has been freed earlier in - this sweep, GC will have set its SCM_TYP16 to scm_tc_free_cell; - this indicates that XCloseDisplay has already been called, and so - the relevant X resource no longer needs to be freed. */ - - -/* SMOB TYPES */ - -typedef struct xdisplay_t -{ - /* The underlying Xlib display pointer. */ - Display *dsp; - - /* State - open/closed. */ - int state; - -#define XDISPLAY_STATE_OPEN 1 -#define XDISPLAY_STATE_CLOSED 2 -#define XDISPLAY_STATE_ANY ( XDISPLAY_STATE_OPEN | XDISPLAY_STATE_CLOSED ) - - /* Cached default gc smob for this display. */ - SCM gc; - -} xdisplay_t; - -typedef struct xscreen_t -{ - /* The display that this screen is on. */ - SCM dsp; - - /* The underlying Xlib screen structure. */ - Screen *scr; - -} xscreen_t; - -typedef struct xwindow_t -{ - /* The display that this window is on. */ - SCM dsp; - - /* The underlying Xlib window ID. */ - Window win; - - /* State - mapped/unmapped/destroyed. */ - int state; - -#define XWINDOW_STATE_UNMAPPED 1 -#define XWINDOW_STATE_MAPPED 2 -#define XWINDOW_STATE_DESTROYED 4 -#define XWINDOW_STATE_THIRD_PARTY 8 -#define XWINDOW_STATE_PIXMAP 16 - -} xwindow_t; - -typedef struct xgc_t -{ - /* The display that this GC belongs to. */ - SCM dsp; - - /* The underlying Xlib GC ID. */ - GC gc; - - /* State - default/created/freed. */ - int state; - -#define XGC_STATE_DEFAULT 1 -#define XGC_STATE_CREATED 2 -#define XGC_STATE_FREED 4 - -} xgc_t; - - -/* DECLARATIONS */ - -int scm_tc16_xdisplay = 0; -int scm_tc16_xscreen = 0; -int scm_tc16_xwindow = 0; -int scm_tc16_xgc = 0; - -SCM resource_id_hash; - -#define XDISPLAY(display) ((xdisplay_t *) SCM_SMOB_DATA (display)) -#define XSCREEN(screen) ((xscreen_t *) SCM_SMOB_DATA (screen)) - -#define XDATA_ARCS 0 -#define XDATA_LINES 1 -#define XDATA_POINTS 2 -#define XDATA_SEGMENTS 3 -#define XDATA_RECTANGLES 4 - static int xdisplay_print (SCM display, SCM port, scm_print_state *pstate); static size_t xdisplay_free (SCM display); static SCM xdisplay_mark (SCM display); @@ -164,95 +20,21 @@ static SCM valid_dsp (SCM arg, int pos, int expected, const char *func); static SCM xscreen_mark (SCM screen); static int valid_scr (SCM display, SCM screen, int pos, xdisplay_t *dsp, const char *func); -SCM scm_x_open_display_x (SCM host); -SCM scm_x_close_display_x (SCM display); -SCM scm_x_no_op_x (SCM display); -SCM scm_x_flush_x (SCM display); -SCM scm_x_connection_number (SCM display); -SCM scm_x_screen_count (SCM display); -SCM scm_x_default_screen (SCM display); -SCM scm_x_q_length (SCM display); -SCM scm_x_server_vendor (SCM display); -SCM scm_x_protocol_version (SCM display); -SCM scm_x_protocol_revision (SCM display); -SCM scm_x_vendor_release (SCM display); -SCM scm_x_display_string (SCM display); -SCM scm_x_bitmap_unit (SCM display); -SCM scm_x_bitmap_bit_order (SCM display); -SCM scm_x_bitmap_pad (SCM display); -SCM scm_x_image_byte_order (SCM display); -SCM scm_x_next_request (SCM display); -SCM scm_x_last_known_request_processed (SCM display); -SCM scm_x_display_of (SCM whatever); -SCM scm_x_all_planes (void); -SCM scm_x_root_window (SCM display, SCM screen); -SCM scm_x_black_pixel (SCM display, SCM screen); -SCM scm_x_white_pixel (SCM display, SCM screen); -SCM scm_x_display_width (SCM display, SCM screen); -SCM scm_x_display_height (SCM display, SCM screen); -SCM scm_x_display_width_mm (SCM display, SCM screen); -SCM scm_x_display_height_mm (SCM display, SCM screen); -SCM scm_x_display_planes (SCM display, SCM screen); -SCM scm_x_display_cells (SCM display, SCM screen); -SCM scm_x_screen_of_display (SCM display, SCM screen); -SCM scm_x_screen_number_of_screen (SCM screen); -SCM scm_x_min_colormaps (SCM display, SCM screen); -SCM scm_x_max_colormaps (SCM display, SCM screen); - static int xwindow_print (SCM window, SCM port, scm_print_state *pstate); static size_t xwindow_free (SCM window); static SCM xwindow_mark (SCM window); -static xwindow_t * valid_win (SCM arg, int pos, int expected, const char *func); - -SCM scm_x_create_window_x (SCM display); /* @@@ simplified */ -SCM scm_x_map_window_x (SCM window); -SCM scm_x_unmap_window_x (SCM window); -SCM scm_x_destroy_window_x (SCM window); -SCM scm_x_clear_window_x (SCM window); -SCM scm_x_clear_area_x (SCM window, SCM x, SCM y, SCM width, SCM height, SCM exposures); - -SCM scm_x_create_pixmap_x (SCM display, SCM screen, SCM width, SCM height, SCM depth); -SCM scm_x_copy_area_x (SCM source, SCM destination, SCM gc, SCM src_x, SCM src_y, SCM width, SCM height, SCM dst_x, SCM dst_y); static int xgc_print (SCM window, SCM port, scm_print_state *pstate); static size_t xgc_free (SCM gc); static SCM xgc_mark (SCM gc); static xgc_t * valid_gc (SCM arg, int pos, int expected, const char *func); -SCM scm_x_default_gc (SCM display, SCM screen); -SCM scm_x_free_gc_x (SCM gc); -SCM scm_x_create_gc_x (SCM gc, SCM changes); -SCM scm_x_change_gc_x (SCM gc, SCM changes); -SCM scm_x_set_dashes_x (SCM gc, SCM offset, SCM dashes); -SCM scm_x_set_clip_rectangles_x (SCM gc, SCM x, SCM y, SCM rectangles, SCM ordering); -SCM scm_x_copy_gc_x (SCM src, SCM dst, SCM fields); - static void * valid_data (SCM arg, int pos, int type, int *allocatedp, int *count, const char *func); static SCM draw (SCM window, SCM gc, SCM data, int type, const char *func); -SCM scm_x_draw_arcs_x (SCM window, SCM gc, SCM arcs); -SCM scm_x_draw_lines_x (SCM window, SCM gc, SCM points); -SCM scm_x_draw_points_x (SCM window, SCM gc, SCM points); -SCM scm_x_draw_segments_x (SCM window, SCM gc, SCM segments); -SCM scm_x_draw_rectangles_x (SCM window, SCM gc, SCM rectangles); - static SCM copy_event_fields (SCM display, XEvent *e, SCM event, const char *func); static SCM lookup_window (SCM display, XID id, const char *func); -SCM scm_x_check_mask_event_x (SCM display, SCM mask, SCM event); -SCM scm_x_check_typed_event_x (SCM display, SCM type, SCM event); -SCM scm_x_check_typed_window_event_x (SCM window, SCM type, SCM event); -SCM scm_x_check_window_event_x (SCM window, SCM mask, SCM event); -SCM scm_x_events_queued_x (SCM display, SCM mode); -SCM scm_x_pending_x (SCM display); -SCM scm_x_mask_event_x (SCM display, SCM mask, SCM event); -SCM scm_x_next_event_x (SCM display, SCM event); -SCM scm_x_peek_event_x (SCM display, SCM event); -SCM scm_x_select_input_x (SCM window, SCM mask); -SCM scm_x_window_event_x (SCM window, SCM mask, SCM event); - -void init_xlib_core (void); - /* DISPLAYS */ @@ -972,7 +754,7 @@ SCM xwindow_mark (SCM window) return win->dsp; } -static xwindow_t * valid_win (SCM arg, int pos, int expected, const char *func) +xwindow_t * valid_win (SCM arg, int pos, int expected, const char *func) { SCM arg1 = arg; xwindow_t *win = NULL; @@ -2838,7 +2620,6 @@ SCM_DEFINE (scm_x_window_event_x, "x-window-event!", 2, 1, 0, } #undef FUNC_NAME - /* INITIALIZATION */ void @@ -2874,7 +2655,9 @@ init_xlib_core () resource_id_hash = scm_gc_protect_object (scm_make_weak_value_hash_table (scm_from_int (19))); -#include "xlib.x" +#ifndef SCM_MAGIC_SNARFER +#include "guile-xlib.x" +#endif } /* diff --git a/guile-xlib.h b/guile-xlib.h new file mode 100644 index 0000000..0052b30 --- /dev/null +++ b/guile-xlib.h @@ -0,0 +1,228 @@ +#ifndef GUILE2_XLIB_XLIB_H +#define GUILE2_XLIB_XLIB_H + +#include +#include + +/* Note on differences between this interface and raw Xlib in C. + + Some differences are inevitable. When the power of Xlib is made + available in an general purpose interpreted environment like Guile, + we need to make sure that the interface cannot be called in a way + that would cause the environment as a whole to crash or hang. For + example, in C you can call XCloseDisplay and then, say, + XDestroyWindow for the display that you have just closed; and your + program will probably hang or crash as a result. An interface like + the one implemented here must protect the environment against such + problems by detecting and rejecting invalid usage. + + In practice, this means that the interface needs to track the + current state of X resources like displays and windows. So the + Guile Xlib interface differs from C Xlib at least in that it stores + certain additional state information and uses this information to + detect and disallow invalid usage. + + Given that some difference is inevitable, one piece of Schemely + behaviour is sufficiently useful - and sufficiently easier to + implement in this interface than in a Scheme layer above it - that + it merits a further small departure from C Xlib. This is the + automatic freeing of X resources when the interface-level objects + associated with them are garbage collected. It applies to displays + (using XCloseDisplay), windows (XDestroyWindow) and non-default gcs + (XFreeGC). Note that it is still possible to free these resources + explicitly, using the x-close-display!, x-destroy-window! and + x-free-gc! primitives respectively. + + Many further differences (between this interface and C Xlib) are + possible, but none are compelling. The X people presumably thought + quite carefully about the structure and completeness of the Xlib + interface, and that's worth benefitting from. Layers presenting a + graphical X interface with a different structure, or from a + different angle, can easily be implemented in Scheme on top of + this one. */ + + +/* Note on garbage collection and freeing of X resources. + + The one wrinkle in implementing automatic freeing of X resources is + that almost all X resources depend on a valid display, so we have + to be careful that the display resource is always freed (using + XCloseDisplay) last of all. + + In most cases this is handled by having resource smobs include a + reference to the display smob. But there is still a problem when + all remaining X resource references are dropped between one GC + cycle and the next: when this happens, the next GC sweep could free + the display smob before it gets to some of the other resource + smobs. + + Fortunately, resource smobs can check, in their free functions, + whether this has happened, by looking at the SCM_TYP16 of their + reference to the display smob. If the display smob is still valid, + this will be scm_tc16_xdisplay, and the relevant X resource should + be freed as normal. If the display smob has been freed earlier in + this sweep, GC will have set its SCM_TYP16 to scm_tc_free_cell; + this indicates that XCloseDisplay has already been called, and so + the relevant X resource no longer needs to be freed. */ + + +/* SMOB TYPES */ + +typedef struct xdisplay_t +{ + /* The underlying Xlib display pointer. */ + Display *dsp; + + /* State - open/closed. */ + int state; + +#define XDISPLAY_STATE_OPEN 1 +#define XDISPLAY_STATE_CLOSED 2 +#define XDISPLAY_STATE_ANY ( XDISPLAY_STATE_OPEN | XDISPLAY_STATE_CLOSED ) + + /* Cached default gc smob for this display. */ + SCM gc; + +} xdisplay_t; + +typedef struct xscreen_t +{ + /* The display that this screen is on. */ + SCM dsp; + + /* The underlying Xlib screen structure. */ + Screen *scr; + +} xscreen_t; + +typedef struct xwindow_t +{ + /* The display that this window is on. */ + SCM dsp; + + /* The underlying Xlib window ID. */ + Window win; + + /* State - mapped/unmapped/destroyed. */ + int state; + +#define XWINDOW_STATE_UNMAPPED 1 +#define XWINDOW_STATE_MAPPED 2 +#define XWINDOW_STATE_DESTROYED 4 +#define XWINDOW_STATE_THIRD_PARTY 8 +#define XWINDOW_STATE_PIXMAP 16 + +} xwindow_t; + +typedef struct xgc_t +{ + /* The display that this GC belongs to. */ + SCM dsp; + + /* The underlying Xlib GC ID. */ + GC gc; + + /* State - default/created/freed. */ + int state; + +#define XGC_STATE_DEFAULT 1 +#define XGC_STATE_CREATED 2 +#define XGC_STATE_FREED 4 + +} xgc_t; + + +/* DECLARATIONS */ + +int scm_tc16_xdisplay = 0; +int scm_tc16_xscreen = 0; +int scm_tc16_xwindow = 0; +int scm_tc16_xgc = 0; + +SCM resource_id_hash; + +#define XDISPLAY(display) ((xdisplay_t *) SCM_SMOB_DATA (display)) +#define XSCREEN(screen) ((xscreen_t *) SCM_SMOB_DATA (screen)) + +#define XDATA_ARCS 0 +#define XDATA_LINES 1 +#define XDATA_POINTS 2 +#define XDATA_SEGMENTS 3 +#define XDATA_RECTANGLES 4 + +SCM scm_x_open_display_x (SCM host); +SCM scm_x_close_display_x (SCM display); +SCM scm_x_no_op_x (SCM display); +SCM scm_x_flush_x (SCM display); +SCM scm_x_connection_number (SCM display); +SCM scm_x_screen_count (SCM display); +SCM scm_x_default_screen (SCM display); +SCM scm_x_q_length (SCM display); +SCM scm_x_server_vendor (SCM display); +SCM scm_x_protocol_version (SCM display); +SCM scm_x_protocol_revision (SCM display); +SCM scm_x_vendor_release (SCM display); +SCM scm_x_display_string (SCM display); +SCM scm_x_bitmap_unit (SCM display); +SCM scm_x_bitmap_bit_order (SCM display); +SCM scm_x_bitmap_pad (SCM display); +SCM scm_x_image_byte_order (SCM display); +SCM scm_x_next_request (SCM display); +SCM scm_x_last_known_request_processed (SCM display); +SCM scm_x_display_of (SCM whatever); +SCM scm_x_all_planes (void); +SCM scm_x_root_window (SCM display, SCM screen); +SCM scm_x_black_pixel (SCM display, SCM screen); +SCM scm_x_white_pixel (SCM display, SCM screen); +SCM scm_x_display_width (SCM display, SCM screen); +SCM scm_x_display_height (SCM display, SCM screen); +SCM scm_x_display_width_mm (SCM display, SCM screen); +SCM scm_x_display_height_mm (SCM display, SCM screen); +SCM scm_x_display_planes (SCM display, SCM screen); +SCM scm_x_display_cells (SCM display, SCM screen); +SCM scm_x_screen_of_display (SCM display, SCM screen); +SCM scm_x_screen_number_of_screen (SCM screen); +SCM scm_x_min_colormaps (SCM display, SCM screen); +SCM scm_x_max_colormaps (SCM display, SCM screen); + +xwindow_t * valid_win (SCM arg, int pos, int expected, const char *func); + +SCM scm_x_create_window_x (SCM display); /* @@@ simplified */ +SCM scm_x_map_window_x (SCM window); +SCM scm_x_unmap_window_x (SCM window); +SCM scm_x_destroy_window_x (SCM window); +SCM scm_x_clear_window_x (SCM window); +SCM scm_x_clear_area_x (SCM window, SCM x, SCM y, SCM width, SCM height, SCM exposures); + +SCM scm_x_create_pixmap_x (SCM display, SCM screen, SCM width, SCM height, SCM depth); +SCM scm_x_copy_area_x (SCM source, SCM destination, SCM gc, SCM src_x, SCM src_y, SCM width, SCM height, SCM dst_x, SCM dst_y); + +SCM scm_x_default_gc (SCM display, SCM screen); +SCM scm_x_free_gc_x (SCM gc); +SCM scm_x_create_gc_x (SCM gc, SCM changes); +SCM scm_x_change_gc_x (SCM gc, SCM changes); +SCM scm_x_set_dashes_x (SCM gc, SCM offset, SCM dashes); +SCM scm_x_set_clip_rectangles_x (SCM gc, SCM x, SCM y, SCM rectangles, SCM ordering); +SCM scm_x_copy_gc_x (SCM src, SCM dst, SCM fields); + +SCM scm_x_draw_arcs_x (SCM window, SCM gc, SCM arcs); +SCM scm_x_draw_lines_x (SCM window, SCM gc, SCM points); +SCM scm_x_draw_points_x (SCM window, SCM gc, SCM points); +SCM scm_x_draw_segments_x (SCM window, SCM gc, SCM segments); +SCM scm_x_draw_rectangles_x (SCM window, SCM gc, SCM rectangles); + +SCM scm_x_check_mask_event_x (SCM display, SCM mask, SCM event); +SCM scm_x_check_typed_event_x (SCM display, SCM type, SCM event); +SCM scm_x_check_typed_window_event_x (SCM window, SCM type, SCM event); +SCM scm_x_check_window_event_x (SCM window, SCM mask, SCM event); +SCM scm_x_events_queued_x (SCM display, SCM mode); +SCM scm_x_pending_x (SCM display); +SCM scm_x_mask_event_x (SCM display, SCM mask, SCM event); +SCM scm_x_next_event_x (SCM display, SCM event); +SCM scm_x_peek_event_x (SCM display, SCM event); +SCM scm_x_select_input_x (SCM window, SCM mask); +SCM scm_x_window_event_x (SCM window, SCM mask, SCM event); + +void init_xlib_core (void); + +#endif /* GUILE2_XLIB_XLIB_H */ -- 2.21.0