problems adapting GTK to Forth



Hello,

I am not sure that this is the right list for this question, so here it is.  If the gtk-app-devel-list would be better, let me know.  I hope that if the reader is not able to give me any guidance directly, my question could be passed to someone who can.

In brief, I am trying to use GTK+ to develop a windowing system for a CLI version of the Forth language, Swiftforth. I hope to develop a toolkit which would allow users of this system to make use of the powerful facilities of GTK to construct a GUI.  I am in trouble already because most Forth programmers know little about GTK, and since the documentation for it is written in C and most C folks care little about Forth, I am wandering barefoot through no-mans'-land.  And, of course, there are no bindings for Forth.

The core of the my problem appears to be with the signal/callback mechanism.  Swiftforth allows me to run GTK library calls successfully, and I can open the custom window I will use, etc.  I set up the signals and they compile without any error.  I use the SwiftForth word CB: to set up the callbacks, and I have annotated the pertinent parts to make it clear what is happening:  The whole of the code follows:

\ --------------------------------------- CODE -----------------------------------------------------

LIBRARY  /usr/lib/i386-linux-gnu/libgtk-3.so.0.1000.8

FUNCTION: gtk_window_new ( code -- addr )
FUNCTION: gtk_widget_destroy ( wptr -- )
FUNCTION: gtk_window_close ( wptr -- )
FUNCTION: gtk_widget_show  ( wptr -- )
FUNCTION: gtk_init  ( -- )
FUNCTION: gtk_window_set_decorated ( wptr flag -- ) ( prob. 0 )
FUNCTION: gtk_window_set_title ( wptr TitlePtr -- )
FUNCTION: gtk_window_resize ( wptr width height -- )
FUNCTION: gtk_widget_modify_bg ( wptr state cptr -- )
FUNCTION: g_signal_connect_data ( wptr name callback data 0 0 -- )
FUNCTION: gtk_main ( -- )
FUNCTION: gtk_main_quit ( -- )
FUNCTION: gtk_widget_set_events ( wptr flag -- )

LIBRARY  /usr/lib/i386-linux-gnu/libgdk-3.so.0.1000.8
FUNCTION: gdk_event_get_keyval ( eptr kptr -- )
FUNCTION: gdk_event_get_state ( eptr sptr -- )
FUNCTION: gdk_event_get_event_type ( eptr -- type )

VARIABLE Window-Ptr

Z" Forth"         VALUE Title                                \ Z" creates 0 terminated string, address into VALUE
Z" key_press_event"    VALUE Keypress-Name
Z" delete_event"       VALUE Delete-Event-Name
Z" destroy"            VALUE Destroy-Name

CREATE Background 0 , 0 H, 0 H, $2000 H,

20000 TASK CF                   \  using a task here only for diagnostic purposes, not to be in final version

: SHUTDOWN
    Window-Ptr @   DUP  gtk_window_close
    gtk_widget_destroy
    CF KILL
;
                                                                         \ possible problem area #1
:NONAME    ( wptr data -- res )
    FALSE                              \ return of flag to GTK
;

( xt on stack )   2   CB: CB.DELETE.EVENT

:NONAME    ( wptr data -- res )
    FALSE
    gtk_main_quit
;       

( xt on stack )   2   CB: CB.DESTROY

:NONAME     ( wptr eptr data -- res )
    FALSE
;         

( xt on stack )   3  CB: CB.KEYPRESS

: (STARTUP)   ( -- )
    Window-Ptr OFF
    gtk_init
    0 gtk_window_new ?DUP                            \ 0 = GTK_WINDOW_TOPLEVEL  Can't use .h files
      IF DUP Window-Ptr !
         DUP 1024 gtk_widget_set_events          \  1024 for keypress events
         DUP Title gtk_window_set_title
         DUP 1280 850 gtk_window_resize
         DUP 0 gtk_window_set_decorated
         DUP 0 Background gtk_widget_modify_bg
                                                                        \ possible problem area #2
         DUP Delete-Event-Name  CB.DELETE.EVENT  0
           0 0  g_signal_connect_data
         DUP Destroy-Name  CB.DESTROY 0
           0 0  g_signal_connect_data
         DUP Keypress-Name  CB.KEYPRESS 0
           0 0  g_signal_connect_data
         gtk_widget_show
      THEN
      gtk_main
;

: STARTUP
    4th ACTIVATE (STARTUP)
;

\ --------------------------------------------------------------------------

Basically, I have tried to translate the C functions into Forth.  Often I have not been able to find out exactly what those functions  do because the details are hidden, so I will document exactly what the pertinent Forth functions step by step hopefully to reveal how I may be doing it wrong.  I have already consulted the SwiftForth expert, but he knew little about GTK or C in general, so he could not help.

\----------------------------------------- Signal Code -----------------------------------------

 DUP                                \  puts address of window structure on stack
 Keypress-Name              \  puts address of event name on stack
 CB.KEYPRESS                 \  puts address of callback handler on stack
 0 0 0                              \ 3 nulls
 g_signal_connect_data   \  pulls the trigger

\ -------------------------------------------------------------------------------------------------

The Forth system installs a wrapper to put the input parameters into the correct form for the library call, and I know this basic procedure works because the window opens and assumes the correct size and color.  Part of my problem here is that C users are sometimes ambiguous about the word "pointer", using it occasionally for "the address pointing to something" and usually "a variable containing the address pointing to something".   The inputs could be wrong for this reason.

\----------------------------------- Callback Code -------------------------------------------

:NONAME       \  noname: compiles code and leaves the execution token (xt) for the next step
                      \  later here will be a large SWITCH mechanism determine what to do with the keypress
    FALSE         \  the return
;         

( xt on stack )   3  CB: CB.KEYPRESS     \ creates a wrapper to interface with GTK, incorporating the xt

\--------------------------------------------------------------------------------------------

The wrapper installed by Swiftforth gets the address of the first input parameter on the Rstack and puts it into a user variable, 'WF. Then it runs the actual callback, and finally puts the return into EAX.  'WF will give me access to the event structure, I am home free.  But. . .

What actually happens:

STARTUP opens the window, but pressing a key does nothing.  It should put an address into 'WF, but nothing is there.  I imagine that I am either setting up the signal wrong, but in a manner which does not crash the system, or there is something wrong with the callback setup.  All I know is that the callback is not being run because there is nothing in 'WF.  I have the sneaking suspicion that there is some simple thing which I am neglecting.

I have read that callbacks cannot be written in forth, only in C.  However, since the C code compiles into machine language which can be disassembled, analyzed, and duplicated in another language, I am still trying.

My intention is to open up GTK usage to a new batch of potential users who would be able to use Linux-forth plus GTK to develop serious GUI applications, something now rather difficult. I can imagine that this may seem a very small problem, especially since so few people are familiar with Forth.  However, if I can get past this hurdle, I intend to develop my toolkit as an enhancement to several varieties of Forth currently lacking such tools.

I am hoping there is someone in your camp who will see this as an interesting problem to solve.  I am willing to put my two bits into it if you can.

Terence C. Gibian


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]