For Edwin: gtk-widget-font, scm-layout-scroll-step, etc.
authorMatt Birkholz <matt@birkholz.chandler.az.us>
Thu, 24 Jun 2010 18:26:26 +0000 (11:26 -0700)
committerMatt Birkholz <matt@birkholz.chandler.az.us>
Sun, 12 Dec 2010 05:59:08 +0000 (22:59 -0700)
* doc/gtk/gtk.texinfo: Followed the example of ffi.texinfo.  Added
VERSION.  Changed name from "Users'" to "Reference" Manual.  Clarified
how to run the examples.

* src/Makefile.in: Use @FFIS@ to init FFIS, allowing gtk to be built
conditionally.  Install lib/conses.png only when the Gtk interface is
built.

* src/Setup.sh: The lib/lib/prgtkio.so symlink is no longer needed.

* src/configure.ac: Added support for a --with-gtk option, to
conditionally include Gtk.  Added --enable-debugging, needed in
microcode/achost.ac.

* src/gtk/.gitignore: Make git ignore the gtk-shim build byproducts.

* src/gtk/Includes/, src/gtk/gtk.cdecl: Added and deleted various
declarations.

* src/gtk/demo.scm: Renamed the event handler "demo-event-handler".
Added a call to gtk-widget-grab-focus.

* src/gtk/ed-ffi.scm: Added pango.scm.

* src/gtk/gobject.scm: Added punt-gc-cleanup, for alien objects that
can be explicitly destroyed as well as GCed.  Allow for C-enum values
that do not fit in a fixnum.  Treat them as integers.

* src/gtk/gtk-object.scm: Defined and used gtk-object-flags, despite
their being deprecated.  Added peek-gtk-adjustment, for debugging.
Added gtk-widget-queue-draw, -get-pango-context, -create-pango-layout,
-set-size-request.

Added gtk-widget-font, -bg-color, -fg-color, -base-color, and
-text-color, and their setters, mostly from scm-layout.scm.

Added gtk-scrolled-window-set-policy and -set-placement.

Replace guarantee-gtk-window with check-gtk-window.  Use
error:wrong-type-argument in the check-TYPE procedures.

Fixed the C types peeked by gtk-window-get-default-size.

* src/gtk/gtk.pkg: Added several new exports, and a new (gtk pango)
package.  Moved color and font support from (gtk layout) to (gtk
gtk-object).

* src/gtk/gtk.scm: Added rect-union!.  Use integer operators on pixel
coordinates and sizes.  Moved most of the Pango code to the new
pango.scm file.

* src/gtk/gtk.sf: Suppress option loading noise.  Syntax each file in
its respective package, as its dependencies require.

* src/gtk/hello.scm: Quiet warnings.  Punt call to error; keeping it
simple.  This code appears in the manual.

* src/gtk/main.scm: Punt private copy of ucode-primitive syntax
transformer.

* src/gtk/pango.scm: New, implementing <pango-layout> as a <gobject>.

* src/gtk/scm-layout.scm: Created a second, "detailed" trace level.
Allow logical device coordinates and sizes to be integers, not just
fixnums.  Added set-scm-layout-scroll-step! and scm-layout-realized?.
Init on-screen-area to an un(der)defined rect.  Adjust scrollbars only
when realized and necessary.

Moved the color support to gtk-object.scm.  None of it depends on
scm-layout anymore -- just gtk-widget.  Re-worked the
_get_modifier_style,modify,_modify_style abstraction to accommodate
set-rcstyle-font!.

Combined common scrolling code from set-scm-layout-scroll-pos!,
scm-layout-adjustment-value-changed.

Allow drawing-add-item! to splice in an item just under/before
another, given item.

Keep drawn-item changes (damage old area, move, damage new area)
thread-atomic, else another thread can interfere.

* src/gtk/thread.scm (kill-gtk-thread): Send ONE thread event, and
clear gtk-thread first.

* src/microcode/configure.ac: Put prgtkio.so on MODULE_TARGETS, not
_BASES.  The latter does too much.

24 files changed:
doc/gtk/gtk.texinfo
src/Makefile.in
src/Setup.sh
src/configure.ac
src/gtk/.gitignore [new file with mode: 0644]
src/gtk/Includes/gdkevents.cdecl
src/gtk/Includes/gtkwidget.cdecl
src/gtk/Includes/pango-context.cdecl
src/gtk/Includes/pango-font.cdecl
src/gtk/Includes/pango-layout.cdecl
src/gtk/demo.scm
src/gtk/ed-ffi.scm
src/gtk/gobject.scm
src/gtk/gtk-object.scm
src/gtk/gtk.cdecl
src/gtk/gtk.pkg
src/gtk/gtk.scm
src/gtk/gtk.sf
src/gtk/hello.scm
src/gtk/main.scm
src/gtk/pango.scm [new file with mode: 0644]
src/gtk/scm-layout.scm
src/gtk/thread.scm
src/microcode/configure.ac

index 241be68a2d1cdbb6fd3b6bcda76d023c4b37dbe1..2fd3a63069bc84191c6b364e76d692b0c94d1709 100644 (file)
@@ -1,11 +1,12 @@
 \input texinfo @c -*-Texinfo-*-
 @comment %**start of header
 @setfilename mit-scheme-gtk
-@settitle Gtk Users' Manual
+@set VERSION 0.1
+@settitle Gtk @value{VERSION}
 @comment %**end of header
 
 @copying
-The users' manual for a Gtk interface for MIT/GNU Scheme.
+This manual documents @acronym{Gtk} @value{VERSION}.
 
 Copyright @copyright{} 2008, 2009, 2010 Matthew Birkholz
 
@@ -26,13 +27,13 @@ Software Foundation raise funds for GNU development.''
 
 @dircategory Programming Languages
 @direntry
-* Gtk Users': (mit-scheme-gtk).                MIT/GNU Scheme GNOME toolkit
+* Gtk Interface: (mit-scheme-gtk).     MIT/GNU Scheme GNOME Interface
 @end direntry
 
 @titlepage
-@title The Gtk Users' Manual
-@subtitle for Schemely access to the GNOME toolkit
-@subtitle for MIT/GNU Scheme version 7.7.90+
+@title The Gtk Reference Manual
+@subtitle Schemely access (@value{VERSION}) to the GNOME toolkits
+@subtitle for MIT/GNU Scheme version 9.0.1+
 @author by Matt Birkholz (@email{birkholz@@alum.mit.edu})
 @page
 @vskip 0pt plus 1filll
@@ -41,7 +42,7 @@ Software Foundation raise funds for GNU development.''
 
 @ifnottex
 @node Top, Introduction, (dir), (dir)
-@top Gtk Users' Manual
+@top Gtk Interface
 
 @insertcopying
 @end ifnottex
@@ -51,7 +52,7 @@ Software Foundation raise funds for GNU development.''
 * Hello World:: Not your primitive ``Hello, world!'' example.
 * Gtk-Event-Viewer:: A simple Scheme widget.  GtkEv translated into Scheme/FFI.
 * Scm-Layout:: A Scheme canvas widget.
-* GNU Free Documentation License::  
+* GNU Free Documentation License::
 @end menu
 
 
@@ -87,10 +88,10 @@ wrappings.  The existing wrappers are the best examples of
 what needs to be done.  They are written in Scheme/FFI --- Scheme
 extended with the accompanying FFI.
 @ifnothtml
-@xref{Top,, Introduction, mit-scheme-ffi, FFI Users' Manual}.
+@xref{Top,, Introduction, mit-scheme-ffi, The FFI Reference Manual}.
 @end ifnothtml
 @ifhtml
-See the @uref{../FFI/mit-scheme-ffi.html,, FFI Users' Manual}.
+See the @uref{../FFI/mit-scheme-ffi.html,, The FFI Reference Manual}.
 @end ifhtml
 
 @unnumberedsec Procedures
@@ -118,7 +119,7 @@ The @code{gtk-label-get-text} wrapper procedure hides these details.
 Using such wrappings, the primitive ``Hello, world!'' example in the
 FFI system
 @ifnothtml
-(@pxref{Top,, Hello World, mit-scheme-ffi, FFI Users' Manual})
+(@pxref{Top,, Hello World, mit-scheme-ffi, The FFI Reference Manual})
 @end ifnothtml
 @ifhtml
 (@uref{mit-scheme-ffi.html#Hello%20World,, here})
@@ -234,9 +235,8 @@ the first or second expression below.
 @node Hello World, Gtk-Event-Viewer, Introduction, Top
 @chapter Hello World
 
-To run the example ``Hello, World!'' program, enter the following
-command lines in the @file{src/gtk} directory of the source
-distribution.
+To run the example ``Hello, World!'' program, execute the following
+command lines in the @file{src/gtk} directory of your build tree.
 
 @smallexample
   ../microcode/scheme --library ../lib
@@ -262,7 +262,8 @@ running within callouts.  For example, while calling out to
 @code{gdk_window_show_all}, the toolkit calls the Scheme widget's
 realize method, which calls out again to @code{gdk_window_new}.
 
-Enter these 3 lines to create this widget.
+To see this widget, execute the following command lines in the
+@file{src/gtk} directory of your build tree.
 
 @smallexample
   ../microcode/scheme --library ../lib
@@ -304,7 +305,8 @@ There are just a few specializations of @code{<drawn-item>} so far:
 A demo of two @code{<scm-layout>} widgets displaying one canvas is
 provided.  The canvas contains text, horizontal and vertical lines,
 and an image.  It also contains animated boxes that blink and follow
-the mouse.  Enter these 3 lines to create this widget.
+the mouse.  To see these widgets in action, execute the following
+command lines in the @file{src/gtk} directory of your build tree.
 
 @smallexample
   ../microcode/scheme --library ../lib
index 7ff6700c512aa87dc362fe0aad1abcfa5627fa24..ce3aba870523e36d9b5fc7f85578b21baa5669c9 100644 (file)
@@ -62,7 +62,7 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/microcode/mkinstalldirs
 
 LIARC_BOOT_BUNDLES = compiler cref sf star-parser
 LIARC_BUNDLES = $(LIARC_BOOT_BUNDLES) edwin ffi imail sos ssp xml $(FFIS)
-FFIS = gtk
+FFIS = @FFIS@
 
 SUBDIRS = $(INSTALLED_SUBDIRS) 6001 compiler rcs win32 xdoc
 INSTALLED_SUBDIRS = microcode runtime $(LIARC_BUNDLES)
@@ -204,7 +204,8 @@ install-auxdir-top:
        $(mkinstalldirs) $(DESTDIR)$(AUXDIR)
        $(INSTALL_DATA) $(top_srcdir)/etc/optiondb.scm $(DESTDIR)$(AUXDIR)/.
        $(INSTALL_DATA) lib/*.com $(DESTDIR)$(AUXDIR)/.
-       $(INSTALL_DATA) lib/*.png $(DESTDIR)$(AUXDIR)/.
+       if [ -e lib/conses.png ]; then \
+           $(INSTALL_DATA) lib/conses.png $(DESTDIR)$(AUXDIR)/.; fi
 
 .PHONY: all all-native all-liarc all-svm macosx-app
 .PHONY: compile-microcode build-bands
index 97ce736153a59cea19ab56b8d70b68beb5889c8b..16143a8c9e3d5377ec10ceeacf2ebb866a6c47b7 100755 (executable)
@@ -86,7 +86,6 @@ maybe_link lib/optiondb.scm ../etc/optiondb.scm
 maybe_link lib/runtime ../runtime
 maybe_link lib/mit-scheme.h ../microcode/pruxffi.h
 maybe_link lib/ffi ../ffi
-maybe_link lib/lib/prgtkio.so ../../microcode/prgtkio.so
 maybe_link lib/gtk ../gtk
 maybe_link config.sub microcode/config.sub
 maybe_link config.guess microcode/config.guess
index 340922a7f4e21c32cd29440312153a310cf8d13e..77b168cfd2548697fee4e9f3cf9c79468bacfa8c 100644 (file)
@@ -38,6 +38,16 @@ AC_ARG_ENABLE([host-scheme-test],
        [Test for working scheme on build host [[no]]]))
 : ${enable_host_scheme_test=no}
 
+AC_ARG_ENABLE([debugging],
+    AS_HELP_STRING([--enable-debugging],
+       [Compile with debugging support [[no]]]))
+: ${enable_debugging='no'}
+
+AC_ARG_WITH([gtk],
+    AS_HELP_STRING([--with-gtk],
+       [Support the GNOME Toolkits if available [[yes]]]))
+: ${with_gtk='yes'}
+
 AC_CANONICAL_HOST
 
 MIT_SCHEME_NATIVE_CODE([${enable_native_code}],[${host_cpu}])
@@ -92,7 +102,28 @@ directory, which is usually \`/usr/local/lib/mit-scheme-${mit_scheme_native_code
     AC_MSG_RESULT([yes])
 fi
 
+AC_CHECK_PROG([PKG_CONFIG], [pkg-config], [yes])
+if test "${with_gtk}" = yes; then
+    AC_MSG_CHECKING([for gtk])
+    if test "${PKG_CONFIG}" != yes; then
+       AC_MSG_RESULT([no, no pkg-config])
+       with_gtk=no
+    elif ! "${MIT_SCHEME_EXE}" --eval "(load-option'FFI)" \
+               --batch-mode </dev/null >/dev/null 2>&1; then
+       AC_MSG_RESULT([no, no FFI])
+       with_gtk=no
+    else
+       if pkg-config --exists gtk+-2.0; then
+           AC_MSG_RESULT([yes])
+           FFIS=gtk
+       else
+           AC_MSG_RESULT([no, ! pkg-config --exists gtk+2.0])
+       fi
+    fi
+fi
+
 AC_SUBST([ALL_TARGET])
+AC_SUBST([FFIS])
 AC_SUBST([INSTALL_COM])
 AC_SUBST([INSTALL_LIARC_BUNDLES])
 AC_SUBST([MIT_SCHEME_EXE])
@@ -129,7 +160,6 @@ compiler/Makefile
 cref/Makefile
 edwin/Makefile
 ffi/Makefile
-gtk/Makefile
 imail/Makefile
 runtime/Makefile
 sf/Makefile
@@ -140,6 +170,9 @@ win32/Makefile
 xdoc/Makefile
 xml/Makefile
 ])
+if test "${with_gtk}" = yes; then
+    AC_CONFIG_FILES([gtk/Makefile])
+fi
 AC_OUTPUT
 
 if test x"${mit_scheme_native_code}" = xc; then
@@ -150,8 +183,9 @@ if test x"${mit_scheme_native_code}" = xc; then
     for BN in star-parser; do
         (cd lib; rm -f ${BN}; ${LN_S} ../${BN} .)
     done
-    for BUNDLE in 6001 compiler cref edwin ffi gtk imail sf sos ssp \
-           star-parser xdoc xml; do
+    BUNDLES="6001 compiler cref edwin ffi imail sf sos ssp star-parser xdoc xml"
+    if test x"${with_gtk}" = xyes; then BUNDLES="$BUNDLES gtk"; fi
+    for BUNDLE in $BUNDLES; do
        SO=${BUNDLE}.so
        (cd lib/lib; rm -f ${SO}; ${LN_S} ../../${BUNDLE}/${SO} .)
     done
diff --git a/src/gtk/.gitignore b/src/gtk/.gitignore
new file mode 100644 (file)
index 0000000..88d0758
--- /dev/null
@@ -0,0 +1,6 @@
+gtk-const
+gtk-const.c
+gtk-const.scm
+gtk-shim.c
+gtk-shim.so
+scmwidget.c
index 6a2c627f9f7a9c2e8fa6b6d20fe961f0a873a592..db532eb60514a2af7f2aa59d0611a0a83f1e45d3 100644 (file)
@@ -88,7 +88,9 @@ gtk-2.0/gdk/gdkevents.h |#
     (GDK_SCROLL)
     (GDK_WINDOW_STATE)
     (GDK_SETTING)
-    (GDK_OWNER_CHANGE)))
+    (GDK_OWNER_CHANGE)
+    (GDK_GRAB_BROKEN)
+    (GDK_DAMAGE)))
 
 (typedef GdkEventMask
   (enum
index 70439ab76ed47324ab6c67fc8a7bd954cdde9a35..d3ea4f3b818c281f6916f9b980d57d56960b7e46 100644 (file)
@@ -292,6 +292,9 @@ gtk-2.0/gtk/gtkwidget.h |#
 (extern void gtk_widget_show_all
        (widget (* GtkWidget)))
 
+(extern void gtk_widget_queue_draw
+       (widget (* GtkWidget)))
+
 (extern void gtk_widget_queue_draw_area
        (widget (* GtkWidget))
        (x gint)
@@ -308,6 +311,11 @@ gtk-2.0/gtk/gtkwidget.h |#
 (extern void gtk_widget_error_bell
        (widget (* GtkWidget)))
 
+(extern void gtk_widget_set_size_request
+       (widget (* GtkWidget))
+       (width gint)
+       (height gint))
+
 (extern (* GdkColormap) gtk_widget_get_colormap
        (widget (* GtkWidget)))
 (extern (* GdkVisual) gtk_widget_get_visual
@@ -349,10 +357,6 @@ gtk-2.0/gtk/gtkwidget.h |#
        (state GtkStateType)
        (color (* (const GdkColor))))
 
-(extern void gtk_widget_modify_font
-       (widget (* GtkWidget))
-       (font_desc (* PangoFontDescription)))
-
 (extern (* PangoContext)
        gtk_widget_get_pango_context (widget (* GtkWidget)))
 
index d9614cc9bc13af22fadcfb90ab196a83c2c14c52..c7697aecfa4c9270b88b89c34f84a53b9cf77699 100644 (file)
@@ -33,10 +33,14 @@ pango-1.0/pango/pango-context.h |#
        (desc (const (* PangoFontDescription)))
        (language (* PangoLanguage)))
 
-;(extern void
-;      pango_context_set_font_description
-;      (context (* PangoContext))
-;      (desc (const (* PangoFontDescription))))
+(extern (* PangoFontDescription)
+       pango_context_get_font_description
+       (context (* PangoContext)))
+
+(extern void
+       pango_context_set_font_description
+       (context (* PangoContext))
+       (desc (const (* PangoFontDescription))))
 
 (extern (* PangoLanguage)
        pango_context_get_language
index 0bf1bf4dc7d2d022f286e6a68743659cd12be137..9406818eca4ba60f1b5eb76823551868ef3d6ba1 100644 (file)
@@ -67,13 +67,17 @@ pango-1.0/pango/pango-font.h |#
        pango_font_description_from_string
        (str (* (const char))))
 
+(extern (* char)
+       pango_font_description_to_string
+       (desc (* (const PangoFontDescription))))
+
 (extern void pango_font_metrics_unref (metrics (* PangoFontMetrics)))
 (extern int pango_font_metrics_get_ascent (metrics (* PangoFontMetrics)))
 (extern int pango_font_metrics_get_descent (metrics (* PangoFontMetrics)))
-;(extern int pango_font_metrics_get_approximate_char_width (metrics (* PangoFontMetrics)))
-(extern int pango_font_metrics_get_approximate_digit_width (metrics (* PangoFontMetrics)))
+(extern int pango_font_metrics_get_approximate_char_width (metrics (* PangoFontMetrics)))
+;(extern int pango_font_metrics_get_approximate_digit_width (metrics (* PangoFontMetrics)))
 ;(extern int pango_font_metrics_get_underline_position (metrics (* PangoFontMetrics)))
-;(extern int pango_font_metrics_get_unerline_thickness (metrics (* PangoFontMetrics)))
+;(extern int pango_font_metrics_get_underline_thickness (metrics (* PangoFontMetrics)))
 ;(extern int pango_font_metrics_get_strikethrough_position (metrics (* PangoFontMetrics)))
 ;(extern int pango_font_metrics_get_strikethrough_thickness (metrics (* PangoFontMetrics)))
 
index cb622cd9480f09e380936af5cad958394a042042..c98d2c026a7745b79e92983f13abc263e9173cec 100644 (file)
@@ -7,36 +7,55 @@ pango-1.0/pango/pango-layout.h |#
 ;(include "pango-glyph-item")
 ;(include "pango-tabs")
 
+(extern (* PangoLayout) pango_layout_new
+       (context (* PangoContext)))
+
+(extern (* PangoContext) pango_layout_get_context
+       (layout (* PangoLayout)))
+
+(extern void pango_layout_set_text
+       (layout (* PangoLayout))
+       (text (const (* char)))
+       (length int))
+
+(extern void pango_layout_set_font_description
+       (layout (* PangoLayout))
+       (desc (const (* PangoFontDescription))))
+
+(extern (const (* PangoFontDescription))
+       pango_layout_get_font_description
+       (layout (* PangoLayout)))
+
 (extern int pango_layout_get_spacing
        (layout (* PangoLayout)))
+
 (extern void pango_layout_get_extents
        (layout (* PangoLayout))
        (ink_rect (* PangoRectangle))
        (logical_rect (* PangoRectangle)))
+
 (extern void pango_layout_get_pixel_extents
        (layout (* PangoLayout))
        (ink_rect (* PangoRectangle))
        (logical_rect (* PangoRectangle)))
-(extern void pango_layout_set_text
-       (layout (* PangoLayout))
-       (text (const (* char)))
-       (length int))
-(extern void pango_layout_set_font_description
-       (layout (* PangoLayout))
-       (desc (const (* PangoFontDescription))))
+
 (extern void pango_layout_index_to_pos
        (layout (* PangoLayout))
        (index int)
        (pos (* PangoRectangle)))
+
 (extern void pango_layout_xy_to_index
        (layout (* PangoLayout))
        (x int) (y int)
        (index (* int))
        (trailing (* int)))
+
 (extern (* PangoLayoutIter)
        pango_layout_get_iter
        (layout (* PangoLayout)))
+
 (extern void pango_layout_iter_free
        (iter (* PangoLayoutIter)))
+
 (extern int pango_layout_iter_get_baseline
-        (iter (* PangoLayoutIter)))
+        (iter (* PangoLayoutIter)))
\ No newline at end of file
index 63f208e0228f0feb1d44de3b3e9a0d56dd6ef60b..21227d4125a4f19e62e87d6b9d22e19b61f2a387 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-Copyright (C) 2007, 2008, 2009  Matthew Birkholz
+Copyright (C) 2007, 2008, 2009, 2010  Matthew Birkholz
 
 This file is part of MIT/GNU Scheme.
 
@@ -49,20 +49,24 @@ USA.
        (outf-console "; Closed "window".\n")
        0))
     (let ((drawing (demo-drawing layout1)))
+
       (set-scm-layout-drawing! layout1 drawing)
       (set-scm-layout-scroll-pos! layout1 175 150)
       (set-scm-widget-event!
-       layout1 (demo-event layout1 (scm-layout-event layout1)))
+       layout1 (demo-event-handler layout1 (scm-layout-event-handler layout1)))
+
       (set-scm-layout-drawing! layout2 drawing)
       (set-scm-layout-scroll-pos! layout2 175 150)
       (set-scm-widget-event!
-       layout2 (demo-event layout2 (scm-layout-event layout2)))
+       layout2 (demo-event-handler layout2 (scm-layout-event-handler layout2)))
+
       (let ((cursor1 (add-box-item drawing 'BOTTOM))
            (cursor2 (add-box-item drawing 'BOTTOM)))
        (set-demo-drawing-cursor-items!
         drawing (list (list cursor1 layout1) (list cursor2 layout2)))
        (let ((thread (start-blinking drawing)))
          (outf-console "; Cursor blinking courtesy of "thread".\n"))))
+    (gtk-widget-grab-focus layout1)
     (outf-console "; Created "layout1" and "layout2"\n"))
   unspecific)
 
@@ -96,8 +100,8 @@ USA.
   ;; and mouse motion handler.
   (cursor-items define standard initial-value '()))
 
-(define (demo-event widget old-handler)
-  (named-lambda (scm-layout-demo::event GtkWidget GdkEvent)
+(define (demo-event-handler widget old-handler)
+  (named-lambda (scm-layout-demo::handle-event GtkWidget GdkEvent)
 
     (trace2 ";(scm-layout-demo::event "GtkWidget" "GdkEvent")\n")
     (let ((type (C-> GdkEvent "GdkEvent any type")))
index 9d72bec5db553eb4613fd5496f74d7096bfa7b9b..6fe4af646153b60a4f4cfa1f647678ccb0567379 100644 (file)
@@ -11,5 +11,6 @@ GTK buffer packaging info |#
     ("scm-layout" (gtk layout))
     ("thread"  (gtk thread))
     ("main"    (gtk main))
+    ("pango"   (gtk pango))
     ("gtk-ev"  (gtk event-viewer))
     ("demo"    (gtk demo))))
\ No newline at end of file
index 4dfd91b1b6a676e017cb5d693e83532973974fd8..f1b27f5cbfbd8213953d01eccc8ea1c85f5aa2a6 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-Copyright (C) 2007, 2008, 2009  Matthew Birkholz
+Copyright (C) 2007, 2008, 2009, 2010  Matthew Birkholz
 
 This file is part of MIT/GNU Scheme.
 
@@ -197,6 +197,24 @@ USA.
    (lambda ()
      (set! gc-cleanups
           (cons (weak-cons object cleanup-thunk) gc-cleanups)))))
+
+(define (punt-gc-cleanup object)
+  (without-interrupts
+   (lambda ()
+     (let ((entry (weak-assq object gc-cleanups)))
+       (if entry
+          (begin
+            (set! gc-cleanups (delq! entry gc-cleanups))
+            (weak-cdr entry))
+          #f)))))
+
+(define (weak-assq obj alist)
+  (let loop ((alist alist))
+    (if (null? alist) #f
+       (let* ((entry (car alist))
+              (key (weak-car entry)))
+         (if (eq? obj key) entry
+             (loop (cdr alist)))))))
 \f
 
 ;;; Properties
@@ -213,58 +231,59 @@ USA.
     (C-call "g_object_get_property" (gobject-alien object) name gvalue)
     (let* ((type (C-> gvalue "GValue g_type"))
           (value
-           (case type
-             (((C-enum "G_TYPE_INVALID"))
-              (ferror "Property "name" (for "object") is invalid."))
-             (((C-enum "G_TYPE_NONE"))
-              (ferror "Property "name" (for "object") is void."))
-             (((C-enum "G_TYPE_INTERFACE")) (unimplemented "an interface"))
-             (((C-enum "G_TYPE_CHAR"))
-              (C-call "g_value_get_char" gvalue))
-             (((C-enum "G_TYPE_UCHAR"))
-              (C-call "g_value_get_uchar" gvalue))
-             (((C-enum "G_TYPE_BOOLEAN"))
-              (C-call "g_value_get_boolean" gvalue))
-             (((C-enum "G_TYPE_INT"))
-              (C-call "g_value_get_int" gvalue))
-             (((C-enum "G_TYPE_UINT"))
-              (C-call "g_value_get_uint" gvalue))
-             (((C-enum "G_TYPE_LONG"))
-              (C-call "g_value_get_long" gvalue))
-             (((C-enum "G_TYPE_ULONG"))
-              (C-call "g_value_get_ulong" gvalue))
-;            (((C-enum "G_TYPE_INT64"))
-;             (C-call "g_value_get_int64" gvalue))
-;            (((C-enum "G_TYPE_UINT64"))
-;             (C-call "g_value_get_uint64" gvalue))
-             (((C-enum "G_TYPE_ENUM"))
-              (C-call "g_value_get_enum" gvalue))
-             (((C-enum "G_TYPE_FLAGS"))
-              (C-call "g_value_get_flags" gvalue))
-             (((C-enum "G_TYPE_FLOAT"))
-              (C-call "g_value_get_float" gvalue))
-             (((C-enum "G_TYPE_DOUBLE"))
-              (C-call "g_value_get_double" gvalue))
-             (((C-enum "G_TYPE_STRING"))
-              (let ((alien (make-alien '(const (* |gchar|)))))
-                (C-call "g_value_get_string" alien gvalue)
-                (let ((str (c-peek-cstring alien)))
-                  (free alien)
-                  str)))
-             (((C-enum "G_TYPE_POINTER"))
-              (let ((alien (make-alien '|gpointer|)))
-                (C-call "g_value_get_pointer" alien gvalue)
-                alien))
-             (((C-enum "G_TYPE_BOXED")) (unimplemented "a boxed"))
-             (((C-enum "G_TYPE_PARAM")) (unimplemented "a param"))
-             (((C-enum "G_TYPE_OBJECT"))
-              (let ((alien (make-alien '|GObject|)))
-                (C-call "g_value_get_object" alien gvalue)
-                alien))
-             (else
-              (ferror "Unexpected GFundamentalType "
-                      (C-enum "enum GFundamentalType" type)
-                      " ("type").")))))
+           (cond
+            ((int:= type (C-enum "G_TYPE_INVALID"))
+             (ferror "Property "name" (for "object") is invalid."))
+            ((int:= type (C-enum "G_TYPE_NONE"))
+             (ferror "Property "name" (for "object") is void."))
+            ((int:= type (C-enum "G_TYPE_INTERFACE"))
+             (unimplemented "an interface"))
+            ((int:= type (C-enum "G_TYPE_CHAR"))
+             (C-call "g_value_get_char" gvalue))
+            ((int:= type (C-enum "G_TYPE_UCHAR"))
+             (C-call "g_value_get_uchar" gvalue))
+            ((int:= type (C-enum "G_TYPE_BOOLEAN"))
+             (C-call "g_value_get_boolean" gvalue))
+            ((int:= type (C-enum "G_TYPE_INT"))
+             (C-call "g_value_get_int" gvalue))
+            ((int:= type (C-enum "G_TYPE_UINT"))
+             (C-call "g_value_get_uint" gvalue))
+            ((int:= type (C-enum "G_TYPE_LONG"))
+             (C-call "g_value_get_long" gvalue))
+            ((int:= type (C-enum "G_TYPE_ULONG"))
+             (C-call "g_value_get_ulong" gvalue))
+;           ((int:= type (C-enum "G_TYPE_INT64"))
+;            (C-call "g_value_get_int64" gvalue))
+;           ((int:= type (C-enum "G_TYPE_UINT64"))
+;            (C-call "g_value_get_uint64" gvalue))
+            ((int:= type (C-enum "G_TYPE_ENUM"))
+             (C-call "g_value_get_enum" gvalue))
+            ((int:= type (C-enum "G_TYPE_FLAGS"))
+             (C-call "g_value_get_flags" gvalue))
+            ((int:= type (C-enum "G_TYPE_FLOAT"))
+             (C-call "g_value_get_float" gvalue))
+            ((int:= type (C-enum "G_TYPE_DOUBLE"))
+             (C-call "g_value_get_double" gvalue))
+            ((int:= type (C-enum "G_TYPE_STRING"))
+             (let ((alien (make-alien '(const (* |gchar|)))))
+               (C-call "g_value_get_string" alien gvalue)
+               (let ((str (c-peek-cstring alien)))
+                 (free alien)
+                 str)))
+            ((int:= type (C-enum "G_TYPE_POINTER"))
+             (let ((alien (make-alien '|gpointer|)))
+               (C-call "g_value_get_pointer" alien gvalue)
+               alien))
+            ((int:= type (C-enum "G_TYPE_BOXED")) (unimplemented "a boxed"))
+            ((int:= type (C-enum "G_TYPE_PARAM")) (unimplemented "a param"))
+            ((int:= type (C-enum "G_TYPE_OBJECT"))
+             (let ((alien (make-alien '|GObject|)))
+               (C-call "g_value_get_object" alien gvalue)
+               alien))
+            (else
+             (ferror "Unexpected GFundamentalType "
+                     (C-enum "enum GFundamentalType" type)
+                     " ("type").")))))
       (free gvalue)
       value)))
 
@@ -300,68 +319,68 @@ USA.
                 (C-call "g_value_init" gvalue gtype)
                 ;;       g_value_set_* gvalue *
                 (let ((fundamental (C-call "G_TYPE_FUNDAMENTAL" gtype)))
-                  (case fundamental
-                    (((C-enum "G_TYPE_CHAR"))
-                     (C-call "g_value_set_char"
-                             gvalue (check-prop-char value name)))
-                    (((C-enum "G_TYPE_UCHAR"))
-                     (C-call "g_value_set_uchar"
-                             gvalue (check-prop-uchar value name)))
-                    (((C-enum "G_TYPE_INT"))
-                     (C-call "g_value_set_int"
-                             gvalue (check-prop-int value name)))
-                    (((C-enum "G_TYPE_UINT"))
-                     (C-call "g_value_set_uint"
-                             gvalue (check-prop-uint value name)))
+                  (cond
+                   ((int:= fundamental (C-enum "G_TYPE_CHAR"))
+                    (C-call "g_value_set_char"
+                            gvalue (check-prop-char value name)))
+                   ((int:= fundamental (C-enum "G_TYPE_UCHAR"))
+                    (C-call "g_value_set_uchar"
+                            gvalue (check-prop-uchar value name)))
+                   ((int:= fundamental (C-enum "G_TYPE_INT"))
+                    (C-call "g_value_set_int"
+                            gvalue (check-prop-int value name)))
+                   ((int:= fundamental (C-enum "G_TYPE_UINT"))
+                    (C-call "g_value_set_uint"
+                            gvalue (check-prop-uint value name)))
 ;                   (((C-enum "G_TYPE_LONG"))
 ;                    (C-call "g_value_set_long"
 ;                            gvalue (check-prop-long value name)))
 ;                   (((C-enum "G_TYPE_ULONG"))
 ;                    (C-call "g_value_set_ulong"
 ;                            gvalue (check-prop-ulong value name)))
-                    (((C-enum "G_TYPE_FLOAT"))
-                     (C-call "g_value_set_float"
-                             gvalue (check-prop-flonum value name)))
-                    (((C-enum "G_TYPE_DOUBLE"))
-                     (C-call "g_value_set_double"
-                             gvalue (check-prop-flonum value name)))
-                    (((C-enum "G_TYPE_STRING"))
-                     (C-call "g_value_set_string"
-                             gvalue (check-prop-string value name)))
-                    (((C-enum "G_TYPE_BOOLEAN"))
-                     (C-call "g_value_set_boolean"
-                             gvalue (check-prop-boolean value name)))
-                    (((C-enum "G_TYPE_ENUM"))
-                     (C-call "g_value_set_enum"
-                             gvalue (check-prop-enum value name)))
-                    (((C-enum "G_TYPE_FLAGS"))
-                     (C-call "g_value_set_flags"
-                             gvalue (check-prop-flags value name)))
-                    (((C-enum "G_TYPE_OBJECT"))
-                     (let* ((value-alien
-                             (cond ((gobject? value) (gobject-alien value))
-                                   ((alien? value) value)
-                                   (else
-                                    (ferror
-                                     "The value "value" for property "
-                                     name" of "gclass-name" is not a"
-                                     " <gobject> nor alien."))))
-                            (value-gtype
-                             (gobject-get-gtype value-alien)))
-                       (if (fix:zero? (C-call "g_value_type_compatible"
-                                              value-gtype gtype))
-                           (ferror "The value "value" for property "
-                                   name" of "gclass-name
-                                   " has incompatible type "
-                                   (gclass-get-name
-                                    (gobject-get-gclass value-alien))
-                                   "."))
-                       (C-call "g_value_set_object" gvalue value-alien)))
-                    (else
-                     (ferror "Fundamental GType "
-                             (C-enum "enum GFundamentalType" fundamental)
-                             " (the type of the "name" property of a "
-                             gclass-name") is not supported."))))
+                   ((int:= fundamental (C-enum "G_TYPE_FLOAT"))
+                    (C-call "g_value_set_float"
+                            gvalue (check-prop-flonum value name)))
+                   ((int:= fundamental (C-enum "G_TYPE_DOUBLE"))
+                    (C-call "g_value_set_double"
+                            gvalue (check-prop-flonum value name)))
+                   ((int:= fundamental (C-enum "G_TYPE_STRING"))
+                    (C-call "g_value_set_string"
+                            gvalue (check-prop-string value name)))
+                   ((int:= fundamental (C-enum "G_TYPE_BOOLEAN"))
+                    (C-call "g_value_set_boolean"
+                            gvalue (check-prop-boolean value name)))
+                   ((int:= fundamental (C-enum "G_TYPE_ENUM"))
+                    (C-call "g_value_set_enum"
+                            gvalue (check-prop-enum value name)))
+                   ((int:= fundamental (C-enum "G_TYPE_FLAGS"))
+                    (C-call "g_value_set_flags"
+                            gvalue (check-prop-flags value name)))
+                   ((int:= fundamental (C-enum "G_TYPE_OBJECT"))
+                    (let* ((value-alien
+                            (cond ((gobject? value) (gobject-alien value))
+                                  ((alien? value) value)
+                                  (else
+                                   (ferror
+                                    "The value "value" for property "
+                                    name" of "gclass-name" is not a"
+                                    " <gobject> nor alien."))))
+                           (value-gtype
+                            (gobject-get-gtype value-alien)))
+                      (if (fix:zero? (C-call "g_value_type_compatible"
+                                             value-gtype gtype))
+                          (ferror "The value "value" for property "
+                                  name" of "gclass-name
+                                  " has incompatible type "
+                                  (gclass-get-name
+                                   (gobject-get-gclass value-alien))
+                                  "."))
+                      (C-call "g_value_set_object" gvalue value-alien)))
+                   (else
+                    (ferror "Fundamental GType "
+                            (C-enum "enum GFundamentalType" fundamental)
+                            " (the type of the "name" property of a "
+                            gclass-name") is not supported."))))
                 (C-call "g_object_set_property" object-alien name gvalue)
                 (C-call "g_value_reset" gvalue)))
             (loop (cddr plist)))))
@@ -421,23 +440,26 @@ USA.
 (define (check-prop-int value name)
   (check-prop-value value name "fit in an int"
                    (lambda (x) (and (exact-integer? x)
-                                    (<= (expt -2 31) x (- (expt 2 32) 1))))))
+                                    (int:<= (expt -2 31) x)
+                                    (int:< x (expt 2 31))))))
 
 (define (uint? x)
-  (and (exact-integer? x) (<= 0 x (- (expt 2 32) 1))))
+  (and (exact-integer? x) (int:<= 0 x) (int:< x (expt 2 32))))
 
 (define (check-prop-uint value name)
   (check-prop-value value name "fit in an unsigned int" uint?))
 
-;(define (check-prop-long value name)
-;  (check-prop-value value name "fit in a long"
-;                  (lambda (x) (and (exact-integer? x)
-;                                   (<= (expt -2 63) x (- (expt 2 64) 1))))))
+#;(define (check-prop-long value name)
+  (check-prop-value value name "fit in a long"
+                   (lambda (x) (and (exact-integer? x)
+                                    (int:<= (expt -2 63) x)
+                                    (int:< x (expt 2 63))))))
 
-;(define (check-prop-ulong value name)
-;  (check-prop-value value name "fit in an unsigned long"
-;                  (lambda (x) (and (exact-integer? x)
-;                                   (<= 0 x (- (expt 2 64) 1))))))
+#;(define (check-prop-ulong value name)
+  (check-prop-value value name "fit in an unsigned long"
+                   (lambda (x) (and (exact-integer? x)
+                                    (int:<= 0 x)
+                                    (int:< x (expt 2 64))))))
 
 (define (check-prop-flonum value name)
   (check-prop-value value name "be a flonum" flo:flonum?))
index 626a91b83ec46cd10b9d8e1af07377ddb5cb3c79..2ce5da7208997aae5d1808e379dfcea4eb49e090 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-Copyright (C) 2007, 2008, 2009  Matthew Birkholz
+Copyright (C) 2007, 2008, 2009, 2010  Matthew Birkholz
 
 This file is part of MIT/GNU Scheme.
 
@@ -69,6 +69,15 @@ USA.
           (set-gtk-object-destroyed?! object #t)
           (gtk-object-cleanup
            (gobject-alien object) (gobject-signals object)))))))
+
+(define-integrable (gtk-object-flags gtkobject)
+  ;; Returns GTK_OBJECT(obj)->flags.
+  (let ((alien (gobject-alien (check-gtk-object gtkobject))))
+    (C-> alien "GtkObject flags")))
+
+(define-integrable (check-gtk-object object)
+  (if (gtk-object? object) object
+      (error:wrong-type-argument object "<gtk-object>" 'check-gtk-object)))
 \f
 
 ;;;; GtkAdjustments
@@ -134,9 +143,20 @@ USA.
       (if (not (int:= new-value old-value))
          (C-call "gtk_adjustment_value_changed" alien)))))
 
-(define (check-real object)
+(define (peek-gtk-adjustment adjustment)
+  ;; For debugging...
+  (let ((alien (live-alien-adjustment adjustment)))
+    (list
+     (C-> alien "GtkAdjustment lower")
+     (C-> alien "GtkAdjustment upper")
+     (C-> alien "GtkAdjustment value")
+     (C-> alien "GtkAdjustment page_size")
+     (C-> alien "GtkAdjustment step_increment")
+     (C-> alien "GtkAdjustment page_increment"))))
+
+(define-integrable (check-real object)
   (if (real? object) object
-      (ferror "The object "object" is not a real number.")))
+      (error:wrong-type-argument object "real number" 'check-real)))
 \f
 
 ;;;; GtkWidgets, GtkContainers
@@ -147,24 +167,209 @@ USA.
   (parent define standard initial-value #f))
 
 (define (gtk-widget-has-focus? widget)
-  (let* ((alien (gobject-alien (check-gtk-widget widget)))
-        (flags (C-> alien "GtkWidget object flags")))
+  (let ((flags (gtk-object-flags widget)))
     (not (int:zero? (bit-and flags (C-enum "GTK_HAS_FOCUS"))))))
 
 (define (gtk-widget-drawable? widget)
-  (let* ((alien (gobject-alien (check-gtk-widget widget)))
-        (flags (C-> alien "GtkWidget object flags")))
+  (let ((flags (gtk-object-flags widget)))
     (and (not (int:zero? (bit-and flags (C-enum "GTK_VISIBLE"))))
         (not (int:zero? (bit-and flags (C-enum "GTK_MAPPED")))))))
 
-(define (gtk-widget-show-all widget)
-  (C-call "gtk_widget_show_all" (gobject-alien (check-gtk-widget widget))))
-
 (define (gtk-widget-grab-focus widget)
-  (C-call "gtk_widget_grab_focus" (gobject-alien (check-gtk-widget widget))))
+  (C-call "gtk_widget_grab_focus" (check-gtk-widget-alien widget)))
+
+(define (gtk-widget-show-all widget)
+  (C-call "gtk_widget_show_all" (check-gtk-widget-alien widget)))
 
 (define (gtk-widget-error-bell widget)
-  (C-call "gtk_widget_error_bell" (gobject-alien (check-gtk-widget widget))))
+  (C-call "gtk_widget_error_bell" (check-gtk-widget-alien widget)))
+
+(define (gtk-widget-queue-draw widget)
+  (C-call "gtk_widget_queue_draw" (check-gtk-widget-alien widget)))
+
+(define (gtk-widget-get-pango-context widget)
+  (C-call "gtk_widget_get_pango_context"
+         (make-alien '|PangoContext|) (gobject-alien widget)))
+
+(define (gtk-widget-create-pango-layout widget #!optional text)
+  (let ((t (if (default-object? text) 0 (check-string text)))
+       (w (check-gtk-widget widget)))
+    (let ((l (make-pango-layout)))
+      (C-call "gtk_widget_create_pango_layout"
+             (gobject-alien l) (gobject-alien w) t)
+      l)))
+
+(define (check-string object)
+  (if (string? object) object
+      (error:wrong-type-argument object "a string" 'check-string)))
+
+(define (gtk-widget-set-size-request widget width height)
+  (C-call "gtk_widget_set_size_request" (gobject-alien widget) width height))
+\f
+
+;;;; GtkWidget Font
+
+(define (gtk-widget-font widget)
+  (let ((alien (check-gtk-widget-alien widget))
+       (desc (make-alien '|PangoFontDescription|)))
+    (C-> alien "GtkWidget style" desc)
+    (C-> desc "GtkStyle font_desc" desc)
+    (pango-font-description-to-string desc)))
+
+(define (set-gtk-widget-font! widget desc)
+  (let ((font (->PangoFontDescription desc)))
+    (modify-rcstyle widget (lambda (rcstyle)
+                            (set-rcstyle-font! rcstyle font)))))
+
+(define (modify-rcstyle widget modify)
+  ;; The _get_modifier_style(), modify, _modify_style() process.  And
+  ;; _queue_draw all.
+  (let ((gtkwidget (gobject-alien widget))
+       (rcstyle (make-alien '|GtkRcStyle|)))
+    (C-call "gtk_widget_get_modifier_style" rcstyle gtkwidget)
+    (modify rcstyle)
+    (C-call "gtk_widget_modify_style" gtkwidget rcstyle) ; rcstyle destroyed
+    (C-call "gtk_widget_queue_draw" gtkwidget)))
+
+(define (set-rcstyle-font! rcstyle pangofontdescription)
+  (C->= rcstyle "struct _GtkRcStyle font_desc" pangofontdescription))
+
+(define (->PangoFontDescription desc)
+  (cond ((and (alien? desc) (eq? '|PangoFontDescription| (alien/ctype desc)))
+        desc)
+       ((string? desc)
+        (let ((alien (pango-font-description-from-string desc)))
+          (if (alien-null? alien)
+              (error:wrong-type-argument desc "PangoFontDescription string"
+                                         '->PangoFontDescription)
+              alien)))
+       (else (error:wrong-type-argument desc "PangoFontDescription"
+                                        '->PangoFontDescription))))
+\f
+
+;;;; GtkWidget Colors
+
+(define (gtk-widget-fg-color widget)
+  ;; Returns WIDGET's foreground color as a new vector: #(red green blue).
+  (let ((gtkstyle (C-> (check-gtk-widget-alien widget) "GtkWidget style")))
+    (peek-rgb (C-> gtkstyle "GtkStyle fg"))))
+
+(define (peek-rgb colors)
+  (let ((color (C-array-loc colors "GdkColor" (C-enum "GTK_STATE_NORMAL"))))
+    (vector (/ (C-> color "GdkColor red") 65535)
+           (/ (C-> color "GdkColor green") 65535)
+           (/ (C-> color "GdkColor blue") 65535))))
+
+(define (gtk-widget-bg-color widget)
+  ;; Returns WIDGET's background color as a new vector: #(red green blue).
+  (let ((gtkstyle (C-> (check-gtk-widget-alien widget) "GtkWidget style")))
+    (peek-rgb (C-> gtkstyle "GtkStyle bg"))))
+
+(define (gtk-widget-text-color widget)
+  ;; Returns WIDGET's text color as a new vector: #(red green blue).
+  (let ((gtkstyle (C-> (check-gtk-widget-alien widget) "GtkWidget style")))
+    (peek-rgb (C-> gtkstyle "GtkStyle text"))))
+
+(define (gtk-widget-base-color widget)
+  ;; Returns WIDGET's base color as a new vector: #(red green blue).
+  (let ((gtkstyle (C-> (check-gtk-widget-alien widget) "GtkWidget style")))
+    (peek-rgb (C-> gtkstyle "GtkStyle base"))))
+
+(define (set-gtk-widget-fg-color! widget color)
+  ;; Sets WIDGET's foreground color.  Queues a complete redraw.
+  (let ((gdkcolor (->gdkcolor color widget 'set-gtk-widget-fg-color!)))
+    (modify-rcstyle widget (lambda (rcstyle)
+                            (set-rcstyle-fg-color! rcstyle gdkcolor)))
+    (free gdkcolor)))
+
+(define (set-rcstyle-fg-color! rcstyle gdkcolor)
+  (set-rcstyle-gdkcolor! gdkcolor (C-enum "GTK_STATE_NORMAL")
+                        (C-> rcstyle "struct _GtkRcStyle fg")
+                        (C-> rcstyle "struct _GtkRcStyle color_flags")
+                        (C-enum "GTK_RC_FG")))
+
+(define (set-rcstyle-gdkcolor! newcolor index colors flagss newflag)
+  ;; Hack modifier style GdkColor array and corresponding flags.
+  (let ((color (C-array-loc! colors "GdkColor" index))
+       (flags (C-array-loc! flagss "uint" index)))
+    (C->= color "GdkColor red" (C-> newcolor "GdkColor red"))
+    (C->= color "GdkColor green" (C-> newcolor "GdkColor green"))
+    (C->= color "GdkColor blue" (C-> newcolor "GdkColor blue"))
+    (C->= flags "GtkRcFlags" (fix:or newflag (C-> flags "GtkRcFlags")))))
+
+(define (set-gtk-widget-bg-color! widget color)
+  ;; Sets WIDGET's background color.  Queues a complete redraw.
+  (let ((gdkcolor (->gdkcolor color widget 'set-gtk-widget-bg-color!)))
+    (modify-rcstyle widget (lambda (rcstyle)
+                            (set-rcstyle-bg-color! rcstyle gdkcolor)))
+    (free gdkcolor)))
+
+(define (set-rcstyle-bg-color! rcstyle gdkcolor)
+  (set-rcstyle-gdkcolor! gdkcolor (C-enum "GTK_STATE_NORMAL")
+                        (C-> rcstyle "struct _GtkRcStyle bg")
+                        (C-> rcstyle "struct _GtkRcStyle color_flags")
+                        (C-enum "GTK_RC_BG")))
+
+(define (set-gtk-widget-text-color! widget color)
+  ;; Queues a complete redraw.
+  (let ((gdkcolor (->gdkcolor color widget 'set-gtk-widget-text-color!)))
+    (modify-rcstyle widget (lambda (rcstyle)
+                            (set-rcstyle-text-color! rcstyle gdkcolor)))
+    (free gdkcolor)))
+
+(define (set-rcstyle-text-color! rcstyle gdkcolor)
+  (set-rcstyle-gdkcolor! gdkcolor (C-enum "GTK_STATE_NORMAL")
+                        (C-> rcstyle "struct _GtkRcStyle text")
+                        (C-> rcstyle "struct _GtkRcStyle color_flags")
+                        (C-enum "GTK_RC_TEXT")))
+
+(define (set-gtk-widget-base-color! widget color)
+  ;; Queues a complete redraw.
+  (let ((gdkcolor (->gdkcolor color widget 'set-gtk-widget-base-color!)))
+    (modify-rcstyle widget (lambda (rcstyle)
+                            (set-rcstyle-base-color! rcstyle gdkcolor)))
+    (free gdkcolor)))
+
+(define (set-rcstyle-base-color! rcstyle gdkcolor)
+  (set-rcstyle-gdkcolor! gdkcolor (C-enum "GTK_STATE_NORMAL")
+                        (C-> rcstyle "struct _GtkRcStyle base")
+                        (C-> rcstyle "struct _GtkRcStyle color_flags")
+                        (C-enum "GTK_RC_BASE")))
+
+(define (->gdkcolor object widget operator)
+  (let ((rgb (->rgb object widget operator))
+       (gdkcolor (malloc (C-sizeof "GdkColor") '|GdkColor|)))
+    (C->= gdkcolor "GdkColor red" (round->exact (* (vector-ref rgb 0) 65535)))
+    (C->= gdkcolor "GdkColor green" (round->exact(* (vector-ref rgb 1) 65535)))
+    (C->= gdkcolor "GdkColor blue" (round->exact (* (vector-ref rgb 2) 65535)))
+    gdkcolor))
+
+(define (->rgb object widget operator)
+  (or (and (string? object)
+          (gtk-widget-parse-color widget object))
+      (and (vector? object) (= 3 (vector-length object))
+          object)
+      (error:wrong-type-argument object "a color name or #(rgb)" operator)))
+
+(define (gtk-widget-parse-color widget string)
+  ;; Returns the color named by STRING, or #F.  STRING can be a color
+  ;; name, hex number, or symbolic color name for the WIDGET.
+  (guarantee-string string 'gtk-widget-parse-color)
+  (let ((style (C-> (check-gtk-widget-alien widget) "GtkWidget style"))
+       (gdkcolor (malloc (C-sizeof "GdkColor") '|GdkColor|)))
+    (if (and (zero? (C-call "gtk_style_lookup_color" style string gdkcolor))
+            (zero? (C-call "gdk_color_parse" string gdkcolor)))
+       (begin
+         (free gdkcolor)
+         #f)
+       (let ((rgb (vector (/ (C-> gdkcolor "GdkColor red") 65535)
+                          (/ (C-> gdkcolor "GdkColor green") 65535)
+                          (/ (C-> gdkcolor "GdkColor blue") 65535))))
+         (free gdkcolor)
+         rgb))))
+\f
+
+;;;; GtkContainers
 
 (define-class <gtk-container> (<gtk-widget>)
 
@@ -204,13 +409,17 @@ USA.
          (gobject-alien (check-gtk-container container))
          width))
 
-(define (check-gtk-widget object)
+(define-integrable (check-gtk-widget-alien object)
+  (gobject-alien (check-gtk-widget object)))
+
+(define-integrable (check-gtk-widget object)
   (if (gtk-widget? object) object
-      (ferror object" is not a <gtk-widget> instance.")))
+      (error:wrong-type-argument object "<gtk-widget>" 'check-gtk-widget)))
 
-(define (check-gtk-container object)
+(define-integrable (check-gtk-container object)
   (if (gtk-container? object) object
-      (ferror object" is not a <gtk-container> instance.")))
+      (error:wrong-type-argument object "<gtk-container>"
+                                'check-gtk-container)))
 \f
 
 ;;; GtkLabels
@@ -296,6 +505,40 @@ USA.
     (C-call "gtk_scrolled_window_new" alien null-alien null-alien)
     (if (alien-null? alien) (ferror "Could not create GtkScrolledWindow."))
     window))
+
+(define (gtk-scrolled-window-set-policy window horizontal vertical)
+  (let ((w (check-scrolled-window window))
+       (h (check-scrollbar-policy horizontal))
+       (v (check-scrollbar-policy vertical)))
+    (C-call "gtk_scrolled_window_set_policy" (gobject-alien w) h v)))
+
+(define (gtk-scrolled-window-set-placement window placement)
+  (let ((w (check-scrolled-window window))
+       (p (check-scrolled-window-placement placement)))
+    (C-call "gtk_scrolled_window_set_placement" (gobject-alien w) p)))
+
+(define-integrable (check-scrolled-window object)
+  (if (gtk-scrolled-window? object) object
+      (error:wrong-type-argument object "<gtk-scrolled-window>"
+                                'check-scrolled-window)))
+
+(define-integrable (check-scrollbar-policy object)
+  (case object
+    ((ALWAYS)  (C-enum "GTK_POLICY_ALWAYS"))
+    ((AUTO)    (C-enum "GTK_POLICY_AUTOMATIC"))
+    ((NEVER)   (C-enum "GTK_POLICY_NEVER"))
+    (else (error:wrong-type-argument object "symbol: ALWAYS, AUTO or NEVER"
+                                    'check-scrollbar-policy))))
+
+(define-integrable (check-scrolled-window-placement object)
+  (case object
+    ((TOP-LEFT) (C-enum "GTK_CORNER_TOP_LEFT"))
+    ((BOTTOM-LEFT) (C-enum "GTK_CORNER_BOTTOM_LEFT"))
+    ((TOP-RIGHT) (C-enum "GTK_CORNER_TOP_RIGHT"))
+    ((BOTTOM-RIGHT) (C-enum "GTK_CORNER_BOTTOM_RIGHT"))
+    (else (error:wrong-type-argument
+          object "symbol: TOP-LEFT, BOTTOM-LEFT, TOP-RIGHT or BOTTOM-RIGHT"
+          'check-scrolled-window-placement))))
 \f
 
 ;;;; GtkWindows
@@ -321,55 +564,54 @@ USA.
     (C-call "gtk_window_set_default_size" alien -1 -1)
     window))
 
-(define (check-window-type type)
+(define-integrable (check-window-type type)
   (case type
     ((TOPLEVEL POPUP) type)
     (else
-     (check-window-type
-      (ferror "The argument to gtk-window-new must be one of"
-             " the symbols TOPLEVEL or POPUP (not "type").")))))
+     (error:wrong-type-argument type "symbol: TOPLEVEL or POPUP"
+                               'check-window-type))))
 
-(define (guarantee-gtk-window object operator)
-  (if (not (gtk-window? object))
-      (error:wrong-type-argument object "<gtk-window>" operator)))
+(define-integrable (check-gtk-window object)
+  (if (gtk-window? object) object
+      (error:wrong-type-argument object "<gtk-window>" 'check-gtk-window)))
 
 (define (gtk-window-set-title window title)
-  (guarantee-gtk-window window 'gtk-window-set-title)
   (guarantee-string title 'gtk-window-set-title)
-  (C-call "gtk_window_set_title" (gobject-alien window) title))
+  (let ((alien (gobject-alien (check-gtk-window window))))
+    (C-call "gtk_window_set_title" alien title)))
 
 (define (gtk-window-get-default-size window receiver)
   ;; Calls RECEIVER with WINDOW's default width and height.
   (let* ((*width (malloc (fix:* 2 (C-sizeof "gint")) 'gint))
         (*height (alien-byte-increment *width (C-sizeof "gint") 'gint)))
-    (C-call "gtk_window_get_default_size" window *width *height)
-    (let ((width (C-> *width "* gint"))
-         (height (C-> *height "* gint")))
+    (C-call "gtk_window_get_default_size"
+           (gobject-alien window) *width *height)
+    (let ((width (C-> *width "gint"))
+         (height (C-> *height "gint")))
       (free *width)
       (receiver width height))))
 
 (define (gtk-window-set-default-size window width height)
-  (guarantee-gtk-window window 'gtk-window-set-default-size)
   (guarantee-integer width 'gtk-window-set-default-size)
   (guarantee-integer height 'gtk-window-set-default-size)
-  (C-call "gtk_window_set_default_size" (gobject-alien window) width height))
+  (let ((alien (gobject-alien (check-gtk-window window))))
+    (C-call "gtk_window_set_default_size" alien width height)))
 
 (define (gtk-window-parse-geometry window geometry)
-  (guarantee-gtk-window window 'gtk-window-parse-geometry)
   (guarantee-string geometry 'gtk-window-parse-geometry)
-  (if (fix:zero? (C-call "gtk_window_parse_geometry"
-                        (gobject-alien window) geometry))
-      (ferror "Could not parse geometry string: "geometry)))
+  (let ((alien (gobject-alien (check-gtk-window window))))
+    (if (fix:zero? (C-call "gtk_window_parse_geometry" alien geometry))
+       (ferror "Could not parse geometry string: "geometry))))
 
 (define (gtk-window-resize window width height)
-  (guarantee-gtk-window window 'gtk-window-resize)
   (guarantee-integer width 'gtk-window-resize)
   (guarantee-integer height 'gtk-window-resize)
-  (C-call "gtk_window_resize" (gobject-alien window) width height))
+  (let ((alien (gobject-alien (check-gtk-window window))))
+    (C-call "gtk_window_resize" alien width height)))
 
 (define (gtk-window-present window)
-  (guarantee-gtk-window window 'gtk-window-present)
-  (C-call "gtk_window_present" (gobject-alien window)))
+  (let ((alien (gobject-alien (check-gtk-window window))))
+    (C-call "gtk_window_present" alien)))
 
 
 (define trace? #f)
index 377c6eef6150c32a3a6bb86f05d4a6a872be7728..2c2cef703e84f47ecd6db4ed2c983765870ce48e 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-Copyright (C) 2007, 2008, 2009  Matthew Birkholz
+Copyright (C) 2007, 2008, 2009, 2010  Matthew Birkholz
 
 This file is part of MIT/GNU Scheme.
 
@@ -150,4 +150,15 @@ USA.
 (extern (* GtkWidget)                  ;gtk+-2.8.20/gtk/gtkscrolledwindow.h
        gtk_scrolled_window_new
        (hadjustment (* GtkAdjustment))
-       (vadjustment (* GtkAdjustment)))
\ No newline at end of file
+       (vadjustment (* GtkAdjustment)))
+
+(extern void
+       gtk_scrolled_window_set_policy
+        (scrolled_window (* GtkScrolledWindow))
+       (hscrollbar_policy GtkPolicyType)
+       (vscrollbar_policy GtkPolicyType))
+
+(extern void
+       gtk_scrolled_window_set_placement
+       (scrolled_window (* GtkScrolledWindow))
+       (window_placement GtkCornerType))
\ No newline at end of file
index 3dd3caf13544a58491a5c7b71be5970d20a47117..333a604c6d7aff6f68458f49263ed42b13e2235e 100644 (file)
@@ -1,6 +1,27 @@
 #| -*-Scheme-*-
 
-Gtk System Packaging |#
+Copyright (C) 2007, 2008, 2009, 2010  Matthew Birkholz
+
+This file is part of MIT/GNU Scheme.
+
+MIT/GNU Scheme is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+MIT/GNU Scheme is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with MIT/GNU Scheme; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
+USA.
+
+|#
+
+;;;; Gtk System Packaging
 
 (global-definitions "../runtime/runtime")
 (global-definitions "../ffi/ffi")
@@ -16,7 +37,8 @@ Gtk System Packaging |#
   (export (gtk)
          <gobject> gobject-alien
          gobject-unref gobject-finalized?
-         g-signal-connect g-signal-disconnect add-gc-cleanup
+         g-signal-connect g-signal-disconnect
+         add-gc-cleanup punt-gc-cleanup
          gobject-get-property gobject-set-properties
          gquark-from-string gquark-to-string
          <pixbuf-loader> make-pixbuf-loader load-pixbuf-from-file
@@ -34,9 +56,22 @@ Gtk System Packaging |#
          <gtk-object> gtk-object-destroyed? gtk-object-destroy
          <gtk-adjustment> make-gtk-adjustment set-gtk-adjustment!
          <gtk-widget> gtk-widget? gtk-widget-parent
-         gtk-widget-has-focus? gtk-widget-drawable? gtk-widget-show-all
+         gtk-widget-drawable? gtk-widget-has-focus? 
          gtk-widget-grab-focus
+         gtk-widget-show-all
          gtk-widget-error-bell
+         gtk-widget-queue-draw
+         gtk-widget-get-pango-context
+         gtk-widget-create-pango-layout
+         gtk-widget-set-size-request
+
+         gtk-widget-font set-gtk-widget-font!
+         gtk-widget-fg-color gtk-widget-bg-color
+         gtk-widget-text-color gtk-widget-base-color
+         set-gtk-widget-fg-color! set-gtk-widget-bg-color!
+         set-gtk-widget-text-color! set-gtk-widget-base-color!
+         gtk-widget-parse-color
+
          <gtk-container> gtk-container?
          gtk-container-children gtk-container-add
          gtk-container-set-border-width
@@ -51,11 +86,9 @@ Gtk System Packaging |#
          gtk-label-get-text gtk-label-set-text
          <gtk-vbox> gtk-vbox-new gtk-box-pack-start gtk-box-pack-end
          <gtk-scrolled-window> gtk-scrolled-window-new
-         pango-rectangle pangos->pixels pixels->pangos
-         pango-font-families pango-context-list-families
-         pango-font-family-get-name pango-font-family-is-monospace?
-         pango-font-family-faces pango-font-face-get-name)
-  (import (gtk gobject) gobject-cleanup gobject-signals))
+         gtk-scrolled-window-set-policy gtk-scrolled-window-set-placement)
+  (import (gtk gobject) gobject-cleanup gobject-signals)
+  (import (gtk pango) make-pango-layout check-PangoFontDescription))
 
 (define-package (gtk widget)
   (parent (gtk))
@@ -65,7 +98,8 @@ Gtk System Packaging |#
          set-scm-widget-destroy!
          set-scm-widget-realize! set-scm-widget-unrealize!
          set-scm-widget-size-request! set-scm-widget-size-allocate!
-         set-scm-widget-event! set-scm-widget-set-scroll-adjustments!))
+         set-scm-widget-event!
+         set-scm-widget-set-scroll-adjustments!))
 
 (define-package (gtk layout)
   (parent (gtk))
@@ -76,17 +110,15 @@ Gtk System Packaging |#
          scm-layout-geometry set-scm-layout-size!
          scm-layout-drawing set-scm-layout-drawing!
          scm-layout-on-screen-area set-scm-layout-scroll-pos!
+         scm-layout-scroll-step set-scm-layout-scroll-step!
 
-         scm-layout-fg-color scm-layout-bg-color
-         scm-layout-text-color scm-layout-base-color
-         set-scm-layout-fg-color! set-scm-layout-bg-color!
-         set-scm-layout-text-color! set-scm-layout-base-color!
-         scm-layout-parse-color
-
-         <drawing> make-drawing set-drawing-size! drawing-pick-list
+         <drawing> make-drawing drawing-widgets
+         set-drawing-size! drawing-pick-list
 
-         <drawn-item> drawn-item-area set-drawn-item-position!
+         <drawn-item>
+         drawn-item-drawing drawn-item-area set-drawn-item-position!
          drawn-item-widgets set-drawn-item-widgets!
+         drawn-item-remove!
 
          <box-item> add-box-item set-box-item-size!
          set-box-item-pos-size! set-box-item-shadow!
@@ -100,6 +132,31 @@ Gtk System Packaging |#
 
          <image-item> add-image-item-from-file))
 
+(define-package (gtk pango)
+  (parent (gtk))
+  (files "pango")
+  (export (gtk)
+         <pango-layout>
+         pango-layout-get-context
+         pango-layout-get-font-description
+         pango-layout-set-text
+         pango-layout-get-pixel-extents
+         pango-layout-index-to-pos
+         pango-font-description-from-string
+         pango-font-description-to-string
+         pango-font-description-free
+         pango-context-get-font-description
+         pango-context-set-font-description
+         pango-context-get-metrics
+         pango-context-spacing
+         pango-font-metrics-get-ascent
+         pango-font-metrics-get-descent
+         pango-font-metrics-get-approximate-char-width
+         pango-font-metrics-unref
+         pango-rectangle
+         pangos->pixels
+         pixels->pangos))
+
 (define-package (gtk thread)
   (parent (runtime thread))
   (files "thread")
@@ -118,6 +175,8 @@ Gtk System Packaging |#
          *unused-command-line*
          hook/process-command-line
          default/process-command-line)
+  (import (runtime)
+         ucode-primitive)
   (export (gtk)
          gtk-time-slice-window?
          gtk-time-slice-window!
@@ -135,6 +194,6 @@ Gtk System Packaging |#
   (parent (gtk))
   (files "demo")
   (import (gtk layout)
-         scm-layout-event)
+         scm-layout-event-handler)
   (export ()
          scm-layout-demo))
\ No newline at end of file
index e79745e7bb131fc4b63f07150bba84951405acf9..fb8a8a68848078b9c0c6a5725d61ac103d5cde00 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-Copyright (C) 2007, 2008, 2009  Matthew Birkholz
+Copyright (C) 2007, 2008, 2009, 2010  Matthew Birkholz
 
 This file is part of MIT/GNU Scheme.
 
@@ -152,10 +152,10 @@ USA.
    (lambda (window-x-start window-x-end window-y-start window-y-end)
      (call-with-rect-bounds item
       (lambda (item-x-start item-x-end item-y-start item-y-end)
-       (cond ((< window-x-end item-x-start) #f)
-             ((< window-y-end item-y-start) #f)
-             ((< item-x-end window-x-start) #f)
-             ((< item-y-end window-y-start) #f)
+       (cond ((int:< window-x-end item-x-start) #f)
+             ((int:< window-y-end item-y-start) #f)
+             ((int:< item-x-end window-x-start) #f)
+             ((int:< item-y-end window-y-start) #f)
              (else
               (let ((x (int:max window-x-start item-x-start))
                     (y (int:max window-y-start item-y-start))
@@ -166,6 +166,18 @@ USA.
                            (int:- x-end x)
                            (int:- y-end y))))))))))
 
+(define (rect-union! rect1 rect2)
+  (call-with-rect-bounds rect1
+   (lambda (min-x1 max-x1 min-y1 max-y1)
+     (call-with-rect-bounds rect2
+      (lambda (min-x2 max-x2 min-y2 max-y2)
+       (let ((x (int:min min-x1 min-x2))
+             (y (int:min min-y1 min-y2)))
+         (set-rect! rect1
+                    x y
+                    (int:- x (int:max max-x1 max-x2))
+                    (int:- y (int:max max-y1 max-y2)))))))))
+
 (define (gdk-rectangle #!optional x y width height)
   (let ((alien (malloc (C-sizeof "GdkRectangle") '|GdkRectangle|)))
     (if (default-object? x) alien
@@ -245,30 +257,12 @@ USA.
       (with-simple-restart 'MUFFLE-WARNING "Ignore warning."
        (lambda () (signal args))))))
 \f
-
-;;;; Pango
-
-(define (pango-rectangle #!optional x y width height)
-  (if (default-object? x)
-      (malloc (C-sizeof "PangoRectangle") '|PangoRectangle|)
-      (let ((rect (malloc (C-sizeof "PangoRectangle") '|PangoRectangle|)))
-       (C->= rect "PangoRectangle x" x)
-       (C->= rect "PangoRectangle y" y)
-       (C->= rect "PangoRectangle width" width)
-       (C->= rect "PangoRectangle height" height)
-       rect)))
-
-(define-integrable (pangos->pixels pango-units)
-  (quotient (int:+ pango-units 512) 1024))
-
-(define-integrable (pixels->pangos pixel-units)
-  (* pixel-units 1024))
+;;; Pango
+;;;
+;;; Debugging hacks.  No gc-cleanups!
 
 (define (pango-font-families widget)
-  (let ((PangoContext (make-alien '|PangoContext|)))
-    (C-call "gtk_widget_get_pango_context" PangoContext
-           (gobject-alien widget))
-    (pango-context-list-families PangoContext)))
+  (pango-context-list-families (gtk-widget-get-pango-context widget)))
 
 (define (pango-context-list-families PangoContext)
   (let ((data-arg (malloc (C-sizeof "*") '(* (* |PangoFontFamily|))))
index 12402441634e149f3ba5730f82010dd3bbc9eb3b..e38a2ddeea46c3ee84675033d8b4a0edb901f8c5 100644 (file)
@@ -1,22 +1,71 @@
 #| -*-Scheme-*-
 
-Syntax the GTK system. |#
+Copyright (C) 2007, 2008, 2009, 2010  Matthew Birkholz
 
-(load-option 'CREF)
-(load-option 'SOS)
-(load-option 'FFI)
+This file is part of MIT/GNU Scheme.
+
+MIT/GNU Scheme is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+MIT/GNU Scheme is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with MIT/GNU Scheme; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
+USA.
+
+|#
+
+;;;; Syntax the GTK system
+
+(fluid-let ((load/suppress-loading-message? #t))
+  (load-option 'CREF)
+  (load-option 'SOS)
+  (load-option 'FFI))
 
 (with-working-directory-pathname (directory-pathname (current-load-pathname))
   (lambda ()
-    (let ((gtk-files '("gtk" "main" "gobject" "gtk-object"
-                      "scm-widget" "scm-layout"
-                      "gtk-ev" "demo"))
-         (sf+
-          (lambda (files env deps)
-            (fluid-let ((sf/default-declarations
-                         (cons '(usual-integrations)
-                               sf/default-declarations)))
-              (sf-with-dependencies files deps (->environment env))))))
+    (let* ((files.packages
+           '(("gtk"        . (gtk))
+             ("main"       . (gtk main))
+             ("gobject"    . (gtk gobject))
+             ("gtk-object" . (gtk gtk-object))
+             ("pango"      . (gtk pango))
+             ("scm-widget" . (gtk widget))
+             ("scm-layout" . (gtk layout))
+             ("thread"     . (gtk thread))
+             ("gtk-ev"     . (gtk event-viewer))
+             ("demo"       . (gtk demo))))
+          (sf+
+           (lambda (files deps)
+             (let loop ((files (if (pair? files) files (list files))))
+               (if (pair? files)
+                   (let* ((file (car files))
+                          (file.package (assoc file files.packages))
+                          (package (if (pair? file.package)
+                                       (cdr file.package)
+                                       (error "No package: " file)))
+                          (env (->environment package)))
+                     (fluid-let ((sf/default-declarations
+                                  (cons '(usual-integrations)
+                                        sf/default-declarations)))
+                       (sf-with-dependencies file deps env))
+                     (loop (cdr files)))))))
+          (sfx+
+           (lambda (files deps)
+             (fluid-let ((sf/default-declarations
+                          (append!
+                           (map (lambda (file)
+                                  `(integrate-external
+                                    ,(pathname-new-type file #f)))
+                                deps)
+                           sf/default-declarations)))
+               (sf+ files deps)))))
 
       ;; Build an empty package for use at syntax-time.
       ;; The C-include syntax will bind C-INCLUDES here.
@@ -29,8 +78,18 @@ Syntax the GTK system. |#
       ;; Load the gtkio primitives too.
       (load-library-object-file "prgtkio" #t)
 
-      (sf+ gtk-files '(gtk) '("gtk-const"))
-      (sf+ "thread" '(gtk thread) '())
+      ;; These core files depend only on the constants behind the C-
+      ;; syntax.
+      (sf+ '("gtk" "main" "gobject" "gtk-object" "pango" "scm-widget")
+          '("gtk-const"))
+
+      ;; These files will want the latest rect(angle) and
+      ;; pango/pixel procedures for inlining.
+      (sfx+ '("scm-layout" "thread" "gtk-ev" "demo")
+           '("gtk" "pango"))
+
+      ;; Depends only on (runtime thread).
+      (sf+ '("thread") '())
 
       ;; Cross-check.
       (cref/generate-constructors "gtk" 'ALL))))
\ No newline at end of file
index 88c96cb9e7d21713221892ce7da950ea10e1bd01..e888dc7b7dde6f09248809e78b6bad6514c32b77 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-This is Havoc Pennington's Hello World example from GGAD, nicely wrapped. |#
+This is Havoc Pennington's Hello World example from GGAD, wrapped in Scheme. |#
 
 (declare (usual-integrations))
 
@@ -17,16 +17,14 @@ This is Havoc Pennington's Hello World example from GGAD, nicely wrapped. |#
     (let ((counter 0))
       (g-signal-connect window (C-callback "delete_event")
        (lambda (w e)
-         (outf-console ";Delete me "(- 2 counter)" times.\n")
+         w e ;ignore
+         (outf-console ";Bite me "(- 2 counter)" times.\n")
          (set! counter (1+ counter))
          ;; Three or more is the charm.
          (if (> counter 2) 0 1)))
       (g-signal-connect button (C-callback "clicked")
        (lambda (w)
-         (if (= counter 1)
-             (begin
-               (outf-console "\n;Erroring in "(current-thread)"...\n")
-               (error "Testing error handling.")))
+         w ;ignore
          (let ((text (gtk-label-get-text label)))
            (gtk-label-set-text
             label (list->string (reverse! (string->list text)))))
index 4d28c66e7fd8da11c7189a70a9df537f2a78086e..59d58981503193603c74570cbcabd04b6d2acede 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-Copyright (C) 2008, 2009  Matthew Birkholz
+Copyright (C) 2008, 2009, 2010  Matthew Birkholz
 
 This file is part of MIT/GNU Scheme.
 
@@ -27,12 +27,6 @@ USA.
 
 (c-include "gtk")
 
-(define-syntax ucode-primitive
-  (sc-macro-transformer
-   (lambda (form environment)
-     environment
-     (apply make-primitive-procedure (cdr form)))))
-
 (define (initialize-package!)
   (let ((program-name ((ucode-primitive scheme-program-name 0))))
     (let ((processor hook/process-command-line))
diff --git a/src/gtk/pango.scm b/src/gtk/pango.scm
new file mode 100644 (file)
index 0000000..9537b04
--- /dev/null
@@ -0,0 +1,226 @@
+#| -*-Scheme-*-
+
+Copyright (C) 2009, 2010  Matthew Birkholz
+
+This file is part of MIT/GNU Scheme.
+
+MIT/GNU Scheme is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+MIT/GNU Scheme is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with MIT/GNU Scheme; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
+USA.
+
+|#
+
+;;;; Pango interface.
+;;; package: (gtk pango)
+
+
+(c-include "gtk")
+\f
+;;; PangoLayout
+
+(define-class (<pango-layout> (constructor ()))
+    (<gobject>))
+
+(define-method initialize-instance ((pango-layout <pango-layout>))
+  (call-next-method pango-layout)
+  (set-alien/ctype! (gobject-alien pango-layout) '|PangoLayout|))
+
+(define (pango-layout-get-context layout)
+  (C-call "pango_layout_get_context"
+         (make-alien '|PangoContext|)
+         (gobject-alien layout)))
+
+(define (pango-layout-get-font-description layout)
+  (C-call "pango_layout_get_font_description"
+         (make-alien '|PangoFontDescription|)
+         (gobject-alien layout)))
+
+(define (pango-layout-set-text layout text)
+  (let ((l (check-pango-layout layout))
+       (s (check-string text)))
+    (C-call "pango_layout_set_text" (gobject-alien l) s (string-length s))))
+
+(define (pango-layout-get-pixel-extents layout receiver)
+  ;; Calls RECEIVER with the logical(?) dimensions (width and height)
+  ;; of the laid-out text.
+
+  (let ((log-extent (pango-rectangle))
+       (ink-extent null-alien))
+    (C-call "pango_layout_get_pixel_extents"
+           (gobject-alien layout) ink-extent log-extent)
+    (let ((width (C-> log-extent "GdkRectangle width"))
+         (height (C-> log-extent "GdkRectangle height")))
+      (free log-extent)
+      (receiver width height))))
+
+(define (pango-layout-index-to-pos layout index receiver)
+  ;; Calls RECEIVER with the x, y, width and height of the grapheme at
+  ;; INDEX in LAYOUT.
+  (let ((rect (pango-rectangle)))
+    (C-call "pango_layout_index_to_pos" (gobject-alien layout) index rect)
+    (let ((x (pangos->pixels (C-> rect "PangoRectangle x")))
+         (y (pangos->pixels (C-> rect "PangoRectangle y")))
+         (width (pangos->pixels (C-> rect "PangoRectangle width")))
+         (height (pangos->pixels (C-> rect "PangoRectangle height"))))
+      (free rect)
+      (receiver x y width height))))
+
+(define-integrable (check-pango-layout object)
+  (if (pango-layout? object)
+      object
+      (error:wrong-type-argument object "<pango-layout>" 'check-pango-layout)))
+\f
+;;; PangoFontDescription
+
+(define (pango-font-description-from-string string)
+  (let ((str (check-string string)))
+    (let ((font (make-alien '|PangoFontDescription|))
+         (copy (make-alien '|PangoFontDescription|)))
+      (add-gc-cleanup font (pango-font-description-cleanup copy))
+      (C-call "pango_font_description_from_string" copy str)
+      (copy-alien-address! font copy)
+      font)))
+
+(define (pango-font-description-cleanup alien)
+  (lambda ()
+    ;;without-interrupts
+    (if (not (alien-null? alien))
+       (begin
+         (C-call "pango_font_description_free" alien)
+         (alien-null! alien)))))
+
+(define (pango-font-description-free font)
+  (let ((alien (check-PangoFontDescription font)))
+    (without-interrupts
+     (lambda ()
+       (if (not (alien-null? alien))
+          (let ((cleanup (punt-gc-cleanup alien)))
+            (if cleanup (cleanup))
+            (alien-null! alien)))))))
+
+(define (pango-font-description-to-string PangoFontDescription)
+  (let ((font (check-PangoFontDescription PangoFontDescription)))
+    (if (alien-null? font)
+       "<null>"
+       (let ((cstr (make-alien '|char|)))
+         (C-call "pango_font_description_to_string" cstr font)
+         (let ((str (c-peek-cstring cstr)))
+           (C-call "g_free" cstr)
+           str)))))
+
+(define (check-PangoFontDescription object)
+  (if (and (alien? object) (eq? '|PangoFontDescription| (alien/ctype object)))
+      object
+      (check-PangoFontDescription
+       (error:wrong-type-argument
+       object "PangoFontDescription's (alien) address"
+       'check-PangoFontDescription))))
+
+(define (check-string object)
+  (if (string? object) object
+      (error:wrong-type-argument object "a string" 'check-string)))
+\f
+;;; PangoContext
+
+(define (pango-context-get-font-description context)
+  ;; Owned by the PangoContext, not Scheme.
+  (C-call "pango_context_get_font_description"
+         (make-alien '|PangoFontDescription|)
+         (check-PangoContext context)))
+
+(define (pango-context-set-font-description context font)
+  (C-call "pango_context_set_font_description"
+         (check-PangoContext context)
+         (check-PangoFontDescription font)))
+
+(define (pango-context-get-metrics context font)
+  ;; Owned by Scheme.
+  (let ((context (check-PangoContext context))
+       (font (check-PangoFontDescription font)))
+    (let ((alien (make-alien '|PangoFontMetrics|))
+         (copy (make-alien '|PangoFontMetrics|)))
+      (add-gc-cleanup alien (pango-font-metrics-cleanup copy))
+      (C-call "pango_context_get_metrics" copy context font 0)
+      (copy-alien-address! alien copy)
+      alien)))
+
+(define (pango-context-spacing context)
+  (let ((layout (make-alien '|PangoLayout|)))
+    (C-call "pango_layout_new" layout (check-PangoContext context))
+    (let ((spacing (C-call "pango_layout_get_spacing" layout)))
+      (C-call "g_object_unref" layout)
+      spacing)))
+
+(define (check-PangoContext object)
+  (if (and (alien? object) (eq? '|PangoContext| (alien/ctype object)))
+      object
+      (check-PangoContext
+       (error:wrong-type-argument
+       object "the (alien) address of a PangoContext"
+       'check-PangoContext))))
+\f
+;;; PangoFontMetrics
+
+(define (pango-font-metrics-cleanup alien)
+  (lambda ()
+    ;;without-interrupts
+    (if (not (alien-null? alien))
+       (begin
+         (C-call "pango_font_metrics_unref" alien)
+         (alien-null! alien)))))
+
+(define (pango-font-metrics-unref metrics)
+  (let ((alien (check-PangoFontMetrics metrics)))
+    (without-interrupts
+     (lambda ()
+       (if (not (alien-null? alien))
+          (let ((cleanup (punt-gc-cleanup alien)))
+            (if cleanup (cleanup))
+            (alien-null! alien)))))))
+
+(define (pango-font-metrics-get-ascent metrics)
+  (C-call "pango_font_metrics_get_ascent" (check-PangoFontMetrics metrics)))
+
+(define (pango-font-metrics-get-descent metrics)
+  (C-call "pango_font_metrics_get_descent" (check-PangoFontMetrics metrics)))
+
+(define (pango-font-metrics-get-approximate-char-width metrics)
+  (C-call "pango_font_metrics_get_approximate_char_width"
+         (check-PangoFontMetrics metrics)))
+
+(define (check-PangoFontMetrics object)
+  (if (and (alien? object) (eq? '|PangoFontMetrics| (alien/ctype object)))
+      object
+      (check-PangoFontMetrics
+       (error:wrong-type-argument
+       object "the (alien) address of PangoFontMetrics"
+       'check-PangoFontMetrics))))
+\f
+;;; PangoRectangle
+
+(define (pango-rectangle #!optional x y width height)
+  (if (default-object? x)
+      (malloc (C-sizeof "PangoRectangle") '|PangoRectangle|)
+      (let ((rect (malloc (C-sizeof "PangoRectangle") '|PangoRectangle|)))
+       (C->= rect "PangoRectangle x" x)
+       (C->= rect "PangoRectangle y" y)
+       (C->= rect "PangoRectangle width" width)
+       (C->= rect "PangoRectangle height" height)
+       rect)))
+
+(define-integrable (pangos->pixels pango-units)
+  (quotient (int:+ pango-units 512) 1024))
+
+(define-integrable (pixels->pangos pixel-units)
+  (* pixel-units 1024))
\ No newline at end of file
index ed92158d02fcdd268316a7a7770185dbfac22672..175492d31f555f1c841dabcdef06b8fc4fa755cd 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-Copyright (C) 2007, 2008, 2009  Matthew Birkholz
+Copyright (C) 2007, 2008, 2009, 2010  Matthew Birkholz
 
 This file is part of MIT/GNU Scheme.
 
@@ -30,30 +30,28 @@ USA.
 (define-class (<scm-layout> (constructor make-scm-layout ()))
     (<scm-widget>)
 
-  ;; Our window, a GdkWindow alien, and its geometry (allocation).
-  ;; Until realized, these are a NULL alien and #f.  If realized, they
-  ;; are a non-NULL alien and a rectangular area in device coordinates
-  ;; (e.g. size in pixels, offset within parent window [ancestor
-  ;; widget]).
-
+  ;; Our window, a GdkWindow alien.  Until realized, this will be NULL.
   (window define accessor
          initializer (lambda () (make-alien '|GdkWindow|)))
+  
+  ;; Our window geometry (allocation) -- a rectangular area in device
+  ;; coordinates (e.g. size in pixels, offset within parent window
+  ;; [ancestor widget]).
   (geometry define accessor initializer make-rect)
 
   ;; Scrollbar widgets.
   (vadjustment define standard initial-value #f)
   (hadjustment define standard initial-value #f)
+  (scroll-step define accessor initializer (lambda () (cons 10 20)))
 
   ;; Scrollable area (drawing size), in logical device coords.
-  ;; The rectangle contains integers (or #f if uninitialized).
   (scrollable-area define accessor
                   initializer (lambda () (make-rect 0 0 100 100)))
 
   ;; Scroll offset and window size (on-screen area).
-  ;; The rectangle contains integers (or #f if uninitialized).
   ;; The width and height should match the window geometry.
   (on-screen-area define accessor
-                 initializer (lambda () (make-rect 0 0 100 100)))
+                 initializer (lambda () (make-rect 0 0)))
 
   ;; The drawing.
   (drawing define standard
@@ -61,8 +59,8 @@ USA.
           initial-value #f))
 
 (define (scm-layout-new width height)
-  (let ((w (check-non-negative-fixnum width))
-       (h (check-non-negative-fixnum height))
+  (let ((w (check-non-negative-integer width))
+       (h (check-non-negative-integer height))
        (layout (make-scm-layout)))
     (let ((alien (gobject-alien layout)))
       (C->= alien "GtkWidget requisition width" w)
@@ -70,15 +68,18 @@ USA.
     (set-scm-widget-size-request! layout (scm-layout-size-request layout))
     (set-scm-widget-size-allocate! layout (scm-layout-size-allocate  layout))
     (set-scm-widget-realize! layout (scm-layout-realize  layout))
-    (set-scm-widget-event! layout (scm-layout-event layout))
+    (set-scm-widget-event! layout (scm-layout-event-handler layout))
     (set-scm-widget-set-scroll-adjustments!
      layout (scm-layout-set-scroll-adjustments layout))
     layout))
 
+(define-integrable (scm-layout-realized? layout)
+  (not (alien-null? (scm-layout-window layout))))
+
 (define (set-scm-layout-size! widget width height)
   ;; Tells WIDGET to (re)request the given WIDTH and HEIGHT in pixels.
-  (let ((w (check-non-negative-fixnum width))
-       (h (check-non-negative-fixnum height))
+  (let ((w (check-non-negative-integer width))
+       (h (check-non-negative-integer height))
        (alien (check-scm-layout-alien widget)))
     (let ((rw (C-> alien "GtkWidget requisition width"))
          (rh (C-> alien "GtkWidget requisition height")))
@@ -88,38 +89,66 @@ USA.
                (C->= alien "GtkWidget requisition width" w))
            (if (not (fix:= h rh))
                (C->= alien "GtkWidget requisition height" h))
-           (if (not (alien-null? (scm-layout-window widget))) ;;realized
+           (if (scm-layout-realized? widget)
                (C-call "gtk_widget_queue_resize" alien)))))))
 
 (define (set-scm-layout-scroll-size! widget width height)
   ;; Tells WIDGET to adjust its scrollable area.  Notifies any
   ;; scrollbars.
-  (set-rect-size! (scm-layout-scrollable-area widget) width height)
-  (adjust-adjustments widget))
+  (let ((w (check-positive-integer width))
+       (h (check-positive-integer height))
+       (area (scm-layout-scrollable-area widget)))
+    (if (not (and (int:= w (rect-width area))
+                 (int:= h (rect-height area))))
+       (begin
+         (set-rect-size! area w h)
+         (if (scm-layout-realized? widget)
+             (adjust-adjustments widget))))))
 
 (define (set-scm-layout-scroll-pos! widget x y)
-  (let ((xI (check-non-negative-integer x))
-       (yI (check-non-negative-integer y))
-       (window-area (scm-layout-on-screen-area widget))
-       (alien-window (scm-layout-window widget)))
-    (let ((xW (rect-x window-area)) (yW (rect-y window-area)))
-      (set-rect-pos! window-area xI yI)
-      (adjust-adjustments widget)
-
-      (if (not (alien-null? alien-window))
-         (let ((dx (int:- xI xW)) (dy (int:- yI yW)))
-           (if (not (or (int:zero? dx) (int:zero? dy)))
-               ;; If more than 25% will remain onscreen, scroll; else jump.
-               (let ((width (rect-width window-area))
-                     (height (rect-height window-area)))
-                 (if (< 0.25 (/ (* dx dy) (* width height)))
-                     ;; Scroll.
-                     (C-call "gdk_window_scroll" alien-window
-                             (int:* -1 dx) (int:* -1 dy))
-                     ;; Jump.
-                     (C-call "gtk_widget_queue_draw_area"
-                             (gobject-alien widget) 0 0 width height))
-                 (C-call "gdk_window_process_updates" alien-window 0))))))))
+  (let ((x1 (check-integer x))
+       (y1 (check-integer y)))
+    (scroll widget x1 y1)))
+
+(define (scroll widget new-x new-y)
+  ;; Scroll if more than 25% will remain in the window, else jump.
+  (if (scm-layout-realized? widget)
+      (let ((scroll (scm-layout-on-screen-area widget)))
+       (let ((old-x (rect-x scroll))
+             (old-y (rect-y scroll)))
+         (let ((dx (int:- new-x old-x))
+               (dy (int:- new-y old-y)))
+           (if (not (and (int:zero? dx) (int:zero? dy)))
+               (let ((width (rect-width scroll))
+                     (height (rect-height scroll))
+                     (gdkwindow (scm-layout-window widget)))
+                 (let ((remaining-width (int:- width (int:abs dy)))
+                       (remaining-height (int:- height (int:abs dx))))
+                   (if (or (int:negative? remaining-width)
+                           (int:negative? remaining-height)
+                           (< 0.25 (/ (int:* remaining-width remaining-height)
+                                      (int:* width           height))))
+                       (C-call "gdk_window_scroll"
+                               gdkwindow (int:negate dx) (int:negate dy))
+                       (C-call "gtk_widget_queue_draw"
+                               (gobject-alien widget)))
+                   (set-rect-pos! scroll new-x new-y)
+                   (adjust-adjustments widget))
+                 (C-call "gdk_window_process_updates" gdkwindow 0))))))))
+
+(define-integrable (int:abs i)
+  (if (int:negative? i) (int:negate i) i))
+
+(define (set-scm-layout-scroll-step! widget width height)
+  ;; Tells WIDGET to use WIDTH/HEIGHT as its "step-increment" when
+  ;; setting up h/vscrollbars.
+  (let ((w (check-positive-integer width))
+       (h (check-positive-integer height)))
+    (let ((width.height (scm-layout-scroll-step widget)))
+      (set-car! width.height w)
+      (set-cdr! width.height h)))
+  (if (scm-layout-realized? widget)
+      (adjust-adjustments widget)))
 
 (define (set-scm-layout-drawing! widget drawing)
   (let ((old (scm-layout-drawing widget))
@@ -129,171 +158,37 @@ USA.
     (%set-scm-layout-drawing! widget new)
     (drawing-add-widget! new widget)
     (let ((a (drawing-area new)))
-      (set-scm-layout-scroll-size! widget (rect-width a) (rect-height a)))
-    (if (not (alien-null? (scm-layout-window widget))) ;;realized
-       (let ((geo (scm-layout-geometry widget)))
-         (C-call "gtk_widget_queue_draw_area" alien
-                 0 0 (rect-width geo) (rect-height geo))))))
+      (set-rect! (scm-layout-scrollable-area widget)
+                (rect-x a) (rect-y a) (rect-width a) (rect-height a))
+      (if (scm-layout-realized? widget)
+         (begin
+           (adjust-adjustments widget)
+           (C-call "gtk_widget_queue_draw" alien))))))
 
 (define-integrable (check-scm-layout-alien obj)
   (if (scm-layout? obj) (gobject-alien obj)
-      (ferror "Not a <scm-layout> instance: "obj)))
-\f
-
-;;;; Colors
-
-(define (scm-layout-fg-color layout)
-  ;; Returns LAYOUT's foreground color as a new vector: #(red green blue).
-  (let ((gtkstyle (C-> (gobject-alien layout) "GtkWidget style")))
-    (peek-rgb (C-> gtkstyle "GtkStyle fg"))))
-
-(define (peek-rgb colors)
-  (let ((color (C-array-loc colors "GdkColor" (C-enum "GTK_STATE_NORMAL"))))
-    (vector (/ (C-> color "GdkColor red") 65535)
-           (/ (C-> color "GdkColor green") 65535)
-           (/ (C-> color "GdkColor blue") 65535))))
-
-(define (scm-layout-bg-color layout)
-  ;; Returns LAYOUT's background color as a new vector: #(red green blue).
-  (let ((gtkstyle (C-> (gobject-alien layout) "GtkWidget style")))
-    (peek-rgb (C-> gtkstyle "GtkStyle bg"))))
-
-(define (scm-layout-text-color layout)
-  ;; Returns LAYOUT's text color as a new vector: #(red green blue).
-  (let ((gtkstyle (C-> (gobject-alien layout) "GtkWidget style")))
-    (peek-rgb (C-> gtkstyle "GtkStyle text"))))
-
-(define (scm-layout-base-color layout)
-  ;; Returns LAYOUT's base color as a new vector: #(red green blue).
-  (let ((gtkstyle (C-> (gobject-alien layout) "GtkWidget style")))
-    (peek-rgb (C-> gtkstyle "GtkStyle base"))))
-
-(define (set-scm-layout-fg-color! layout color)
-  ;; Queues a complete redraw.
-  (let ((gdkcolor (->gdkcolor color layout 'set-scm-layout-fg-color!)))
-    (set-gdkcolor! layout gdkcolor set-rcstyle-fg-color!)
-    (free gdkcolor)))
-
-(define (set-gdkcolor! layout gdkcolor applicator)
-  (let ((scmwidget (gobject-alien layout))
-       (rcstyle (make-alien '|GtkRcStyle|)))
-    (C-call "gtk_widget_get_modifier_style" rcstyle scmwidget)
-    (applicator rcstyle gdkcolor)
-    (C-call "gtk_widget_modify_style" scmwidget rcstyle) ; rcstyle destroyed
-    (if (not (alien-null? (scm-layout-window layout))) ;realized
-       (let ((geo (scm-layout-geometry layout)))
-         (C-call "gtk_widget_queue_draw_area" scmwidget
-                 0 0 (rect-width geo) (rect-height geo))))))
-
-(define (set-rcstyle-fg-color! rcstyle gdkcolor)
-  (set-rcstyle-gdkcolor! gdkcolor (C-enum "GTK_STATE_NORMAL")
-                        (C-> rcstyle "struct _GtkRcStyle fg")
-                        (C-> rcstyle "struct _GtkRcStyle color_flags")
-                        (C-enum "GTK_RC_FG")))
-
-(define (set-rcstyle-gdkcolor! newcolor index colors flagss newflag)
-  (let ((color (C-array-loc! colors "GdkColor" index))
-       (flags (C-array-loc! flagss "uint" index)))
-    (C->= color "GdkColor red" (C-> newcolor "GdkColor red"))
-    (C->= color "GdkColor green" (C-> newcolor "GdkColor green"))
-    (C->= color "GdkColor blue" (C-> newcolor "GdkColor blue"))
-    (C->= flags "GtkRcFlags" (fix:or newflag (C-> flags "GtkRcFlags")))))
-
-(define (set-scm-layout-bg-color! layout color)
-  ;; Queues a complete redraw.
-  (let ((gdkcolor (->gdkcolor color layout 'set-scm-layout-bg-color!)))
-    (set-gdkcolor! layout gdkcolor set-rcstyle-bg-color!)
-    (free gdkcolor))
-  (let ((gdkwindow (scm-layout-window layout)))
-    (if (not (alien-null? gdkwindow))  ;realized
-       (let* ((scmwidget (gobject-alien layout))
-              (style (C-> scmwidget "GtkWidget style")))
-         (C-call "gtk_style_set_background" style gdkwindow
-                 (C-enum "GTK_STATE_NORMAL"))))))
-
-(define (set-rcstyle-bg-color! rcstyle gdkcolor)
-  (set-rcstyle-gdkcolor! gdkcolor (C-enum "GTK_STATE_NORMAL")
-                        (C-> rcstyle "struct _GtkRcStyle bg")
-                        (C-> rcstyle "struct _GtkRcStyle color_flags")
-                        (C-enum "GTK_RC_BG")))
-
-(define (set-scm-layout-text-color! layout color)
-  ;; Queues a complete redraw.
-  (let ((gdkcolor (->gdkcolor color layout 'set-scm-layout-text-color!)))
-    (set-gdkcolor! layout gdkcolor set-rcstyle-text-color!)
-    (free gdkcolor)))
-
-(define (set-rcstyle-text-color! rcstyle gdkcolor)
-  (set-rcstyle-gdkcolor! gdkcolor (C-enum "GTK_STATE_NORMAL")
-                        (C-> rcstyle "struct _GtkRcStyle text")
-                        (C-> rcstyle "struct _GtkRcStyle color_flags")
-                        (C-enum "GTK_RC_TEXT")))
-
-(define (set-scm-layout-base-color! layout color)
-  ;; Queues a complete redraw.
-  (let ((gdkcolor (->gdkcolor color layout 'set-scm-layout-base-color!)))
-    (set-gdkcolor! layout gdkcolor set-rcstyle-base-color!)
-    (free gdkcolor)))
-
-(define (set-rcstyle-base-color! rcstyle gdkcolor)
-  (set-rcstyle-gdkcolor! gdkcolor (C-enum "GTK_STATE_NORMAL")
-                        (C-> rcstyle "struct _GtkRcStyle base")
-                        (C-> rcstyle "struct _GtkRcStyle color_flags")
-                        (C-enum "GTK_RC_BASE")))
-
-(define (->gdkcolor object layout operator)
-  (let ((rgb (->rgb object layout operator))
-       (gdkcolor (malloc (C-sizeof "GdkColor") '|GdkColor|)))
-    (C->= gdkcolor "GdkColor red" (round (* (vector-ref rgb 0) 65535)))
-    (C->= gdkcolor "GdkColor green" (round (* (vector-ref rgb 1) 65535)))
-    (C->= gdkcolor "GdkColor blue" (round (* (vector-ref rgb 2) 65535)))
-    gdkcolor))
-
-(define (->rgb object layout operator)
-  (or (and (string? object)
-          (scm-layout-parse-color layout object))
-      (and (vector? object) (= 3 (vector-length object))
-          object)
-      (error:wrong-type-argument object "a color name or #(rgb)" operator)))
-
-(define (scm-layout-parse-color layout string)
-  ;; Returns the color named by STRING, or #F.  STRING can be a color
-  ;; name, hex number, or symbolic color name for the LAYOUT widget.
-  (guarantee-string string 'scm-layout-parse-color)
-  (let ((scmwidget (gobject-alien layout)))
-    (let ((style (C-> scmwidget "GtkWidget style"))
-         (gdkcolor (malloc (C-sizeof "GdkColor") '|GdkColor|)))
-      (if (and (zero? (C-call "gtk_style_lookup_color" style string gdkcolor))
-              (zero? (C-call "gdk_color_parse" string gdkcolor)))
-         (begin
-           (free gdkcolor)
-           #f)
-         (let ((rgb (vector (/ (C-> gdkcolor "GdkColor red") 65535)
-                            (/ (C-> gdkcolor "GdkColor green") 65535)
-                            (/ (C-> gdkcolor "GdkColor blue") 65535))))
-           (free gdkcolor)
-           rgb)))))
+      (error:wrong-type-argument obj "<scm-layout>" 'check-scm-layout-alien)))
 \f
 
 ;;;; Callback handlers.
 
 (define (scm-layout-size-request widget)
   (named-lambda (scm-layout::size-request GtkWidget GtkRequisition)
-    (trace ";((scm-layout-size-request "widget") "GtkWidget
-          " "GtkRequisition")\n")
+    (trace2 ";((scm-layout-size-request "widget") "GtkWidget
+           " "GtkRequisition")\n")
 
     (let ((alien (gobject-alien widget)))
       (let ((width (C-> alien "GtkWidget requisition width"))
            (height(C-> alien "GtkWidget requisition height")))
        (C->= GtkRequisition "GtkRequisition width" width)
        (C->= GtkRequisition "GtkRequisition height" height)
-       (trace "; Requisition: "widget"x"height" from "widget"\n")
+       (trace "; Requisition: "width"x"height" from "widget"\n")
        ))))
 
 (define (scm-layout-size-allocate widget)
   (named-lambda (scm-layout::size-allocate GtkWidget GtkAllocation)
-    (trace ";((scm-layout-size-allocate "widget") "GtkWidget
-          " "GtkAllocation")\n")
+    (trace2 ";((scm-layout-size-allocate "widget") "GtkWidget
+           " "GtkAllocation")\n")
 
     (let ((x (C-> GtkAllocation "GtkAllocation x"))
          (y (C-> GtkAllocation "GtkAllocation y"))
@@ -308,21 +203,20 @@ USA.
       (C->= GtkWidget "GtkWidget allocation y" y)
       (C->= GtkWidget "GtkWidget allocation width" width)
       (C->= GtkWidget "GtkWidget allocation height" height)
-      (let ((window (scm-layout-window widget)))
-       (if (not (alien-null? window)) ;;realized
-           (begin
-             (C-call "gdk_window_move_resize" window x y width height)
-             (adjust-adjustments widget)))))))
+      (if (scm-layout-realized? widget)
+         (begin
+           (C-call "gdk_window_move_resize" (scm-layout-window widget)
+                   x y width height)
+           (adjust-adjustments widget))))))
 
 (define (scm-layout-realize widget)
   (named-lambda (scm-layout::realize GtkWidget)
-    (trace ";((scm-layout-realize "widget") "GtkWidget")\n")
+    (trace2 ";((scm-layout-realize "widget") "GtkWidget")\n")
 
     ;; ScmWidget automatically sets GTK_REALIZED.
 
     (let ((attr (malloc (C-sizeof "GdkWindowAttr") '|GdkWindowAttr|))
          (main-GdkWindow (scm-layout-window widget))
-         (GtkStyle (C-> GtkWidget "GtkWidget style"))
          (parent-GdkWindow (make-alien '|GdkWindow|))
 ;        (GdkVisual (make-alien '|GdkVisual|))
 ;        (GdkColormap (make-alien '|GdkColormap|))
@@ -340,7 +234,6 @@ USA.
 
       (C->= attr "GdkWindowAttr window_type" (C-enum "GDK_WINDOW_CHILD"))
       (let ((r (scm-layout-geometry widget)))
-       ;; Just assume geometry has been allocated?!
        (C->= attr "GdkWindowAttr x" (rect-x r))
        (C->= attr "GdkWindowAttr y" (rect-y r))
        (C->= attr "GdkWindowAttr width" (rect-width r))
@@ -364,20 +257,24 @@ USA.
 
       ;; Style
 
-      (C-call "gtk_style_attach" GtkStyle
-             (C-> GtkWidget "GtkWidget style" GtkStyle) main-GdkWindow)
-      (C->= GtkWidget "GtkWidget style" GtkStyle)
-      (C-call "gtk_style_set_background"
-             GtkStyle main-GdkWindow (C-enum "GTK_STATE_NORMAL"))
+      (let ((GtkStyle (C-> GtkWidget "GtkWidget style")))
+       (C-call "gtk_style_attach" GtkStyle GtkStyle main-GdkWindow)
+       (C->= GtkWidget "GtkWidget style" GtkStyle)
+       (C-call "gdk_window_set_background"
+               main-GdkWindow
+               (C-array-loc (C-> GtkStyle "GtkStyle base" )
+                            "GdkColor" (C-enum "GTK_STATE_NORMAL"))))
+
+      (adjust-adjustments widget)
       unspecific)))
 
-(define (scm-layout-event widget)
-  (named-lambda (scm-layout::event GtkWidget GdkEvent)
-    (trace ";((scm-layout-event "widget") "GtkWidget" "GdkEvent")\n")
+(define (scm-layout-event-handler widget)
+  (named-lambda (scm-layout-handle-event GtkWidget GdkEvent)
+    (trace2 ";((scm-layout-handle-event "widget") "GtkWidget" "GdkEvent")\n")
 
     (let ((type (C-> GdkEvent "GdkEvent any type")))
 
-      (cond ((fix:= type (C-enum "GDK_EXPOSE"))
+      (cond ((int:= type (C-enum "GDK_EXPOSE"))
             (let ((window (C-> GdkEvent "GdkEvent any window"))
                   (x (C-> GdkEvent "GdkEventExpose area x"))
                   (y (C-> GdkEvent "GdkEventExpose area y"))
@@ -400,18 +297,15 @@ USA.
                                                   width height)))))))
 
            (else
-            (let ((name (C-enum "GdkEventType" type))
-                  (addr (alien/address-string
-                         (C-> GdkEvent "GdkEvent any window"))))
-              (trace "; "name" on "GtkWidget" (window 0x"addr").\n")))))
+            (trace "; "(C-enum "GdkEventType" type)" on "widget"\n"))))
     1 ;;TRUE -- "handled" -- done.
     ))
 
 (define (scm-layout-set-scroll-adjustments widget)
   (named-lambda (scm-layout::set-scroll-adjustments
                 GtkWidget hGtkAdjustment vGtkAdjustment)
-    (trace ";((scm-layout-set-scroll-adjustments "widget")"
-          " "GtkWidget" "hGtkAdjustment" "vGtkAdjustment")\n")
+    (trace2 ";((scm-layout-set-scroll-adjustments "widget")"
+           " "GtkWidget" "hGtkAdjustment" "vGtkAdjustment")\n")
 
     (let ((haddr (alien/address-string hGtkAdjustment))
          (vaddr (alien/address-string vGtkAdjustment)))
@@ -420,7 +314,8 @@ USA.
                        widget set-scm-layout-hadjustment!)
     (connect-adjustment (scm-layout-vadjustment widget) vGtkAdjustment
                        widget set-scm-layout-vadjustment!)
-    (adjust-adjustments widget)
+    (if (scm-layout-realized? widget)
+       (adjust-adjustments widget))
     0 ;; What does this mean?
     ))
 
@@ -448,78 +343,56 @@ USA.
 
 (define (scm-layout-adjustment-value-changed widget adjustment)
   (named-lambda (scm-layout::adjustment-value-changed GtkAdjustment)
-    (trace ";((scm-layout-adjustment-value-changed "widget" "adjustment")"
-          " "GtkAdjustment")\n")
+    (trace2 ";((scm-layout-adjustment-value-changed "widget" "adjustment")"
+           " "GtkAdjustment")\n")
 
-    (let ((alien-widget (gobject-alien widget))
-         (alien-window (scm-layout-window widget))
-         (window-area (scm-layout-on-screen-area widget))
+    (let ((window-area (scm-layout-on-screen-area widget))
          (vadjustment (scm-layout-vadjustment widget))
          (hadjustment (scm-layout-hadjustment widget))
-         (alien-adjustment (gobject-alien adjustment)))
-      (let ((value
-            (floor->exact (C-> alien-adjustment "GtkAdjustment value"))))
-       (cond ((eq? adjustment vadjustment)
-              (let* ((y (rect-y window-area))
-                     (dy (int:- value y)))
-                (trace "; Vadjustment to "value" (dy:"dy")\n")
-                (if (not (int:zero? dy))
-                    (let ((width (rect-width window-area)))
-                      (set-rect-y! window-area value)
-                      (if (> (abs dy) (* 0.90 width))
-                          (let ((height (rect-height window-area)))
-                            (if (not (alien-null? alien-window)) ;;realized
-                                (C-call "gtk_widget_queue_draw_area"
-                                        alien-widget 0 0 width height)))
-                          (C-call "gdk_window_scroll"
-                                  alien-window 0 (int:* -1 dy)))
-                      (C-call "gdk_window_process_updates" alien-window 0)))))
-             ((eq? adjustment hadjustment)
-              (let* ((x (rect-x window-area))
-                     (height (rect-height window-area))
-                     (dx (int:- value x)))
-                (trace "; Hadjustment to "value" (dx:"dx")\n")
-                (if (not (int:zero? dx))
-                    (begin
-                      (set-rect-x! window-area value)
-                      (if (> (abs dx) (* 0.90 height))
-                          (let ((width (rect-width window-area)))
-                            (if (not (alien-null? alien-window)) ;;realized
-                                (C-call "gtk_widget_queue_draw_area"
-                                        alien-widget 0 0 width height)))
-                          (C-call "gdk_window_scroll"
-                                  alien-window (int:* -1 dx) 0))
-                      (C-call "gdk_window_process_updates" alien-window 0)))))
-             (else (fwarn "Unexpected adjustment "adjustment
-                          " (not "vadjustment" nor "hadjustment").")))))))
+         (value (floor->exact
+                 (C-> (gobject-alien adjustment) "GtkAdjustment value"))))
+      (cond ((eq? adjustment vadjustment)
+            (trace "; Vadjustment to "value"\n")
+            (scroll widget (rect-x window-area) value))
+           ((eq? adjustment hadjustment)
+            (trace "; Hadjustment to "value"\n")
+            (scroll widget value (rect-y window-area)))
+           (else (fwarn "Unexpected adjustment "adjustment
+                        " (not "vadjustment" nor "hadjustment")."))))))
 
 (define (adjust-adjustments widget)
   ;; Called after the widget gets new adjustment(s) or its size or
   ;; scrollable area changes.
 
-  (let ((hadj (scm-layout-hadjustment widget))
-       (vadj (scm-layout-vadjustment widget)))
+  (let ((vadj (scm-layout-vadjustment widget)))
     (if (and vadj (not (gobject-finalized? vadj)))
-       (let* ((total-height (rect-height (scm-layout-scrollable-area widget)))
-              (scroll (scm-layout-on-screen-area widget))
-              (window-height (rect-height scroll))
-              (value (rect-y scroll)))
-         (set-gtk-adjustment!
-          vadj value                   ;value
-          0 total-height               ;lower (top), upper (bottom)
-          window-height 10             ;page-size, step-increment
-          (- window-height             ;page-increment
-             (* 0.05 window-height)))))
+       (let* ((window (scm-layout-on-screen-area widget))
+              (window-height (rect-height window))
+              (area (scm-layout-scrollable-area widget))
+              (top (rect-y area))      ;most neg.
+              (bottom (int:+ top       ;most pos.
+                             (max (rect-height area) window-height)))
+              (value (rect-y window))
+              (page-size window-height)
+              (step-incr (cdr (scm-layout-scroll-step widget)))
+              (page-incr (min page-size (- page-size step-incr))))
+         (set-gtk-adjustment! vadj value top bottom
+                              page-size step-incr page-incr))))
+
+  (let ((hadj (scm-layout-hadjustment widget)))
     (if (and hadj (not (gobject-finalized? hadj)))
-       (let* ((total-width (rect-width (scm-layout-scrollable-area widget)))
-              (scroll (scm-layout-on-screen-area widget))
-              (window-width (rect-width scroll))
-              (value (rect-x scroll)))
-         (set-gtk-adjustment!
-          hadj value
-          0 total-width
-          window-width 10
-          (- window-width (* 0.05 window-width)))))))
+       (let* ((window (scm-layout-on-screen-area widget))
+              (window-width (rect-width window))
+              (area (scm-layout-scrollable-area widget))
+              (left (rect-x area))     ;most neg.
+              (right (int:+ left       ;most pos.
+                            (max (rect-width area) window-width)))
+              (value (rect-x window))
+              (page-size window-width)
+              (step-incr (car (scm-layout-scroll-step widget)))
+              (page-incr (min page-size (- page-size step-incr))))
+         (set-gtk-adjustment! hadj value left right
+                              page-size step-incr page-incr)))))
 \f
 
 ;;;; Drawings
@@ -540,7 +413,7 @@ USA.
 (define (drawing-damage item #!optional rect)
   ;; Invalidates any widget areas affected by RECT in ITEM.  By
   ;; default, RECT is ITEM's entire area.
-  (trace ";(drawing-damage "item")\n")
+  (trace2 ";(drawing-damage "item")\n")
 
   (let ((area (if (default-object? rect)
                  (drawn-item-area item)
@@ -594,7 +467,7 @@ USA.
 
 (define-generic drawn-item-expose (item widget window expose-area)
   ;; Due to the checks in drawing-expose, methods of this generic can
-  ;; assume expose-area and the draw item's area are well-defined (all
+  ;; assume expose-area and the drawn item's area are well-defined (all
   ;; four members are integers), intersecting, and ITEM is visible in
   ;; WIDGET.  Methods may also assume the widget is realized and its
   ;; window's (gc's) clipping is already set.  The widget's scroll
@@ -617,6 +490,9 @@ USA.
     (set-drawing-widgets! drawing (delq! widget widgets))))
 
 (define (drawing-add-item! drawing item where)
+  ;; WHERE can be 'TOP (or #f) or 'BOTTOM or a drawn item already in
+  ;; the display list.  If a drawn-item, WHERE means ITEM should be
+  ;; spliced in just under (before) it.
   (cond ((or (eq? #f where)
             (eq? 'TOP where))
         (set-drawing-display-list!
@@ -624,7 +500,18 @@ USA.
        ((eq? 'BOTTOM where)
         (set-drawing-display-list!
          drawing (cons item (drawing-display-list drawing))))
-       (else (ferror "Bad where: "where)))
+       ((drawn-item? where)
+        (let loop ((items (drawing-display-list drawing))
+                   (prev #f))
+          (if (null? items)
+              (error "Item not found in drawing:" item drawing)
+              (let ((i (car items)))
+                (if (eq? where i)
+                    (if (pair? prev)
+                        (set-cdr! prev (cons item items))
+                        (set-drawing-display-list! drawing (cons item items)))
+                    (loop (cdr items) items))))))
+       (else (error:wrong-type-argument where "display list location, one of #F, TOP, BOTTOM, or a <drawn-item> already in the drawing's display list" 'drawing-add-item!)))
   (drawing-damage item))
 
 (define (set-drawing-size! drawing width height)
@@ -634,6 +521,14 @@ USA.
     (for-each
      (lambda (widget) (set-scm-layout-scroll-size! widget w h))
      (drawing-widgets drawing))))
+
+(define (set-drawing-area! drawing rectangle)
+  (let ((area (drawing-area drawing)))
+    (set-rect! area
+              (rect-x rectangle)
+              (rect-y rectangle)
+              (rect-width rectangle)
+              (rect-height rectangle))))
 \f
 
 ;;;; Drawn items.
@@ -650,41 +545,41 @@ USA.
   (drawing-add-item! (drawn-item-drawing item) item where))
 
 (define (set-drawn-item-position! item x y)
-  (let ((area (drawn-item-area item))
-       (ix (check-non-negative-integer x))
-       (iy (check-non-negative-integer y)))
-    (let ((curr-x (rect-x area))
-         (curr-y (rect-y area))
-         (width (rect-width area))
-         (height (rect-height area)))
-
-      ;; Two trivial cases, and a general one.
-      (cond ((and (integer? curr-x) (int:= x curr-x)
-                 (integer? curr-y) (int:= y curr-y))
-            unspecific)
-           ((or (not (integer? width)) (int:zero? width)
-                (not (integer? height)) (int:zero? height))
-            (set-rect-pos! area ix iy))
-           (else
-            (drawing-damage item)
-            (set-rect-pos! area ix iy)
-            (drawing-damage item))))))
-
-(define (%set-drawn-item-size! item width height)
+  (let ((x (check-non-negative-integer x))
+       (y (check-non-negative-integer y)))
+    (without-interrupts
+     (lambda ()
+       (let ((area (drawn-item-area item)))
+        (let ((x* (rect-x area))
+              (y* (rect-y area)))
+          (if (and (int:= x x*) (int:= y y*))
+              unspecific
+              (begin
+                (drawing-damage item)
+                (set-rect-pos! area x y)
+                (drawing-damage item)))))))))
+
+(define (set-drawn-item-size! item width height)
   (let ((area (drawn-item-area item)))
-    (drawing-damage item)
-    (set-rect-size! area width height)
-    (drawing-damage item)))
+    (let ((width* (rect-width area))
+         (height* (rect-height area)))
+      (if (and (int:= width width*) (int:= height height*))
+         unspecific
+         (begin
+           (drawing-damage item)
+           (set-rect-size! area width height)
+           (drawing-damage item))))))
 
 (define (set-drawn-item-widgets! item new)
   ;; Draw ITEM only on the NEW widgets.  If NEW is #f, ITEM will
   ;; appear in all views.
   (let ((old (drawn-item-widgets item)))
     (if (not (equal? old new))
-       (begin
-         (drawing-damage item)
-         (%set-drawn-item-widgets! item new)
-         (drawing-damage item)))))
+       (without-interrupts
+        (lambda ()
+          (drawing-damage item)
+          (%set-drawn-item-widgets! item new)
+          (drawing-damage item))))))
 
 (define (drawn-item-widget item)
   ;; Return a widget that will display the item.
@@ -693,6 +588,15 @@ USA.
     (if (null? widgets)
        (ferror "No widgets display drawing "drawing".")
        (car widgets))))
+
+(define (drawn-item-remove! item)
+  (let ((drawing (drawn-item-drawing item)))
+    (if (not (memq item (drawing-display-list drawing)))
+       (warn "Removing orphan drawn-item" item drawing)
+       (set-drawing-display-list!
+        drawing (delq! item (drawing-display-list drawing))))
+    (drawing-damage item)
+    (set-drawn-item-drawing! item #f)))
 \f
 
 ;;;; Simple Items (e.g. the toolkit's gtk_paint_* operators).
@@ -727,9 +631,9 @@ USA.
                    (rect-height area)))))))
 
 (define (set-box-item-size! item width height)
-  (let ((w (check-non-negative-fixnum width))
-       (h (check-non-negative-fixnum height)))
-    (%set-drawn-item-size! item w h)))
+  (let ((w (check-non-negative-integer width))
+       (h (check-non-negative-integer height)))
+    (set-drawn-item-size! item w h)))
 
 (define (set-box-item-pos-size! item x y width height)
   (let ((area (drawn-item-area item))
@@ -737,17 +641,20 @@ USA.
        (yI (if (and (integer? y) (not (int:negative? y))) y 0))
        (wI (if (and (fixnum? width) (not (fix:negative? width))) width 0))
        (hI (if (and (fixnum? height) (not (fix:negative? height))) height 0)))
-    (drawing-damage item)
-    (set-rect! area xI yI wI hI)
-    (drawing-damage item)))
+    (without-interrupts
+     (lambda ()
+       (drawing-damage item)
+       (set-rect! area xI yI wI hI)
+       (drawing-damage item)))))
 
 (define (box-item-shadow item)
-  (case (%box-item-shadow item)
-    (((C-enum "GTK_SHADOW_NONE")) 'NONE)
-    (((C-enum "GTK_SHADOW_IN")) 'IN)
-    (((C-enum "GTK_SHADOW_OUT")) 'OUT)
-    (((C-enum "GTK_SHADOW_ETCHED_IN")) 'ETCHED-IN)
-    (((C-enum "GTK_SHADOW_ETCHED_OUT")) 'ETCHED-OUT)))
+  (let ((shadow (%box-item-shadow item)))
+    (cond
+     ((int:= shadow (C-enum "GTK_SHADOW_NONE")) 'NONE)
+     ((int:= shadow (C-enum "GTK_SHADOW_IN")) 'IN)
+     ((int:= shadow (C-enum "GTK_SHADOW_OUT")) 'OUT)
+     ((int:= shadow (C-enum "GTK_SHADOW_ETCHED_IN")) 'ETCHED-IN)
+     ((int:= shadow (C-enum "GTK_SHADOW_ETCHED_OUT")) 'ETCHED-OUT))))
 
 (define (set-box-item-shadow! item type)
   (let ((new
@@ -788,9 +695,9 @@ USA.
                    (int:- (rect-y area) scroll-y)))))))
 
 (define (set-hline-item-size! item width)
-  (let ((w (check-non-negative-fixnum width))
+  (let ((w (check-non-negative-integer width))
        (hline (check-hline-item item)))
-    (%set-drawn-item-size! hline w (rect-height (drawn-item-area hline)))))
+    (set-drawn-item-size! hline w (rect-height (drawn-item-area hline)))))
 
 (define (check-hline-item obj)
   (if (hline-item? obj) obj
@@ -821,9 +728,9 @@ USA.
                    (int:- (rect-x area) scroll-x)))))))
 
 (define (set-vline-item-size! item height)
-  (let ((h (check-non-negative-fixnum height))
+  (let ((h (check-non-negative-integer height))
        (vline (check-vline-item item)))
-    (%set-drawn-item-size! vline (rect-width (drawn-item-area vline)) h)))
+    (set-drawn-item-size! vline (rect-width (drawn-item-area vline)) h)))
 
 (define (check-vline-item obj)
   (if (vline-item? obj) obj
@@ -882,8 +789,6 @@ USA.
 (define (set-text-item-text! text-item text)
   (let ((layout (text-item-pango-layout text-item)))
 
-    (drawing-damage text-item)
-
     (if (alien-null? layout)
        (begin
          (C-call "gtk_widget_create_pango_layout" layout
@@ -893,48 +798,51 @@ USA.
     (let ((log-extent (pango-rectangle))
          (ink-extent null-alien))
       (C-call "pango_layout_get_pixel_extents" layout ink-extent log-extent)
-      (set-rect-size! (drawn-item-area text-item)
-                     (C-> log-extent "GdkRectangle width")
-                     (C-> log-extent "GdkRectangle height"))
-      (%set-text-item-text! text-item text)
-      (free log-extent))
 
-    (drawing-damage text-item)
+      (without-interrupts
+       (lambda ()
+        (drawing-damage text-item)
+        (set-rect-size! (drawn-item-area text-item)
+                        (C-> log-extent "GdkRectangle width")
+                        (C-> log-extent "GdkRectangle height"))
+        (%set-text-item-text! text-item text)
+        (drawing-damage text-item)))
 
-    unspecific))
+      (free log-extent))))
 
 (define (text-item-xy-to-index item x y)
   ;; Assumes (X,Y) is in ITEM's area (all logical dev. coords.).
-  (let ((layout (text-item-pango-layout item))
-       (area (drawn-item-area item)))
+  (let ((layout (text-item-pango-layout item)))
     (if (not (alien-null? layout))
-       (let ((index-alien (malloc (C-sizeof "int") '(* int)))
-             ;;-> layout coords.
-             (xL (int:- x (rect-x area)))
-             (yL (int:- y (rect-y area))))
-         (if (fix:= 0 (C-call "pango_layout_xy_to_index" layout
-                              (pixels->pangos xL) (pixels->pangos yL)
-                              index-alien null-alien))
-             (begin
-               (free index-alien)
-               #f)
-             (let ((index (C-> index-alien "int")))
-               (free index-alien)
-               index)))
+       (let ((area (drawn-item-area item))
+             (index-alien (malloc (C-sizeof "int") 'int)))
+         (let ((xL (int:- x (rect-x area))) ; layout coords.
+               (yL (int:- y (rect-y area))))
+           (if (fix:= 0 (C-call "pango_layout_xy_to_index" layout
+                                (pixels->pangos xL) (pixels->pangos yL)
+                                index-alien null-alien))
+               (begin
+                 (free index-alien)
+                 #f)
+               (let ((index (C-> index-alien "int")))
+                 (free index-alien)
+                 index))))
        #f)))
 
 (define (call-with-text-item-grapheme-rect item index receiver)
   ;; Calls RECEIVER with the x, y, width and height of the grapheme at
   ;; INDEX in ITEM.
-  (let ((layout (text-item-pango-layout item))
-       (rect (pango-rectangle)))
-    (C-call "pango_layout_index_to_pos" layout index rect)
-    (let ((x (pangos->pixels (C-> rect "PangoRectangle x")))
-         (y (pangos->pixels (C-> rect "PangoRectangle y")))
-         (width (pangos->pixels (C-> rect "PangoRectangle width")))
-         (height (pangos->pixels (C-> rect "PangoRectangle height"))))
-      (free rect)
-      (receiver x y width height))))
+  (let ((layout (text-item-pango-layout item)))
+    (if (not (alien-null? layout))
+       (let ((rect (pango-rectangle)))
+         (C-call "pango_layout_index_to_pos" layout index rect)
+         (let ((x (pangos->pixels (C-> rect "PangoRectangle x")))
+               (y (pangos->pixels (C-> rect "PangoRectangle y")))
+               (width (pangos->pixels (C-> rect "PangoRectangle width")))
+               (height (pangos->pixels (C-> rect "PangoRectangle height"))))
+           (free rect)
+           (receiver x y width height)))
+       #f)))
 \f
 
 ;;;; Images (aka GdkPixbufLoaders)
@@ -957,7 +865,7 @@ USA.
 (define (image-item-size-prepared item)
   (named-lambda (image-item::size-prepared width height)
     (trace "; image-item::size-prepared "item" "width" "height"\n")
-    (%set-drawn-item-size! item width height)))
+    (set-drawn-item-size! item width height)))
 
 (define (image-item-pixbuf-prepared item)
   (named-lambda (image-item::pixbuf-prepared pixbuf)
@@ -1020,24 +928,15 @@ USA.
                          ))))))))
 
 (define (add-image-item-from-file drawing where filename)
-  ;; WHERE can be 'TOP (or #f) or 'BOTTOM.
-  (let ((item (add-image-item drawing (check-where where))))
+  (let ((item (add-image-item drawing where)))
     (load-pixbuf-from-file (image-item-loader item) filename)
     item))
 
-(define (check-where where)
-  (cond ((eq? where #f) 'TOP)
-       ((eq? where 'TOP) 'TOP)
-       ((eq? where 'BOTTOM) 'BOTTOM)
-       (else (ferror "The WHERE argument ("where") must be TOP (or #f)"
-                     " or BOTTOM if it is not optional."))))
-
-(define-integrable (check-non-negative-fixnum obj)
-  (if (fixnum? obj)
-      (if (fix:negative? obj)
-         (ferror "Not a NON-NEGATIVE fixnum: "obj)
-         obj)
-      (ferror "Not a non-negative fixnum: "obj)))
+(define-integrable (check-positive-integer obj)
+  (if (and (integer? obj) (int:> obj 0))
+      obj
+      (error:wrong-type-argument obj "positive, non-zero integer"
+                                'check-positive-integer)))
 
 (define-integrable (check-non-negative-integer obj)
   (if (integer? obj)
@@ -1050,4 +949,9 @@ USA.
 
 (define-syntax trace
   (syntax-rules ()
-    ((_ . ARGS) (if trace? ((lambda () (outf-console . ARGS)))))))
\ No newline at end of file
+    ((_ . ARGS) (if trace? ((lambda () (outf-console . ARGS)))))))
+
+(define trace2? #f)
+(define-syntax trace2
+  (syntax-rules ()
+    ((_ . ARGS) (if trace2? ((lambda () (outf-console . ARGS)))))))
\ No newline at end of file
index 55eb4159891a738cef69b3d1350e35de16f496bd..3b35fc1ce84e5af8880bf8c57669de1ed7df29c3 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-Copyright (C) 2007, 2008, 2009  Matthew Birkholz
+Copyright (C) 2007, 2008, 2009, 2010  Matthew Birkholz
 
 This file is part of MIT/GNU Scheme.
 
@@ -69,9 +69,12 @@ USA.
            (+ (real-time-clock) 1000)))))
 
 (define (kill-gtk-thread)
-  (if (not gtk-thread) (error "A GTk thread is not running."))
-  (signal-thread-event
-   gtk-thread (lambda () (exit-current-thread #t))))
+  (let ((thread gtk-thread))
+    (set! gtk-thread #f)
+    (if (not thread) (error "A GTk thread was not running."))
+    (signal-thread-event
+     thread (lambda ()
+             (exit-current-thread #t)))))
 
 (define trace? #f)
 
index 4a2bb7275c8debee472884dfe1ff983b78234eeb..ff59d0b0619133a4c3804caa1ef2d4398ec90001 100644 (file)
@@ -795,7 +795,6 @@ if test ${enable_valgrind_mode} != no; then
     M4_FLAGS="${M4_FLAGS} -P VALGRIND_MODE,1"
 fi
 
-dnl Add support for Gtk if present.
 AC_CHECK_PROG([PKG_CONFIG], [pkg-config], [yes])
 if test ${with_gtk} = yes; then
     AC_MSG_CHECKING([for gtk])
@@ -804,7 +803,7 @@ if test ${with_gtk} = yes; then
     else
        if pkg-config --exists gtk+-2.0; then
            AC_MSG_RESULT([yes])
-           MODULE_BASES="${MODULE_BASES} prgtkio"
+           MODULE_TARGETS="${MODULE_TARGETS} prgtkio.so"
        else
            AC_MSG_RESULT([no, ! pkg-config --exists gtk+-2.0])
        fi