GNU Cobol and GTK programming

GnuCOBOL
2014-07-13
2014-08-17
  • Brian Tiffin

    Brian Tiffin - 2014-07-13

    GTK, or any GUI event driven foreign beasty.

    Having just spent a few hours playing with buttons, and the desire to write a graphical application using COBOL sources unless forced by circumstance to require C support code, there is a new plan.

    voidcall.c

    /** wrapping void C returns in callbacks for use with COBOL
     */
    
    void
    voidcall(void *gtk, int (*cobfunc)(void *))
    {
        if ((cobfunc) && (cobfunc(gtk))) return; else return;
    }    
    ~~~~~
    
    is a trick that allows
    

    ::cobol

      *> Connect a signal.  GNU Cobol doesn't generate void returns
      *>  so this calls a C function two-liner that calls the
      *>  COBOL entry, but returns void to the runtime stack frame
           set cob-button-callback to entry "buttonclick"
           set gtk-void-callback to entry "voidcall"
           call "g_signal_connect_data" using
               by value gtk-button
               by reference z"clicked"             *> with inline Z string
               by value gtk-void-callback          *> function call back pointer
               by value cob-button-callback        *> pointer to COBOL proc
               by value 0                          *> closure notify to manage data
               by value 0                          *> connect before or after flag
               returning gtk-quit-handler-id       *> not used in this sample
           end-call
    
    The GTK clicked event allowing for userdata, which is used to pass the COBOL callback handler, voidcall calls it, eats the return code and void returns back to GTK.
    
    *If there was no worry about compiler warnings and unused variables, voidcall is really:*
    

    ::c
    void
    voidcall(void gtk, int (cobfunc)(void *))
    {
    if (cobfunc) cobfunc(gtk);
    return;
    }

    but this means that individual widgets don't get a chance to hold luggage.  (A button is just a button, and doesn't have any internal information that would help an atomic chart.  EXTERNAL data is used to share information between main and the supporting event handler.  This is not really a smart way of coupling programs.  Tightly.  So, hmm, how to pass some actual userdata along with the COBOL function pointer through the GTK callback sequence.  *there is just enough state in the button, the label, to search the shared elements table; inefficient and tight coupling*
    
    Instead of the function pointer, a group with the function pointer and a slot (or two or ninety) for widget luggage.
    
    untested as of yet
    if the callback handler is the first field in the COBOL group then it's still an efficient call thru, one extra dereference.  Not the address of the function, but an address that holds the address of the function.
    

    ::c
    void
    voidcall_data(void gtk, int (cobfunc)(void ))
    {
    if (cobfunc && cobfunc) cobfunc(gtk);
    }

    Now the registration sequence can pass in
    

    ::cobolfree
    01 gtk-callback-data.
    05 cobol-callback-handler usage program-pointer.
    05 cobol-widget-information pic xxx. *> or pointer, etc.

    and buttons can then keep some state, say a pointer to element data for an atomic chart. *Pic x(3) is a poor choice probably, asking for alignment issues to bite.*
    
    This indirection should alleviate need for the data and code coupling with EXTERNAL.
    
    The event handler code just needs to skip past the COBOL program address when accessing widget data.  voidcall_data can stay generic as long as the program-pointer is the first field in the GTK userdata record.
    
    More soon, as I think this might be a smart path while building up GTK COBOL.
    
    Oh, and another don't.
    
    I was cheating with the atomic chart and had
    

    ::cobolfree
    SET ADDRESS OF based-widget-stuff TO gtk-widget-label-text

    Cool, as long as the 0 byte terminator is handled...
    
    Well, the label is zzzz9 a newline then the element name then a 0 byte.  I did a 
    

    ::cobolfree

    MOVE based-widget-stuff(7:3) to based-widget-stuff
    

    ~~~~~~

    before searching through the elements table, which wanted the three character element symbol key, and I was cheating.

    Double uncool. ;-) It's a don't. That trashes internal gtk-widget data space. Bad things. In this case, second and subsequent clicks on elements failed the search, the label space being garbage. Could have just as easily been 'splosions. I think a general rule has to be

    unowned BASED working storage is read only. That can't really be enforced, only watched for.

    Cheers,
    Brian

     
    Last edit: Brian Tiffin 2014-07-13
  • Paulo Reis

    Paulo Reis - 2014-07-13

    It's not easy or practical use GTK with GNU Cobol.
    It's important nowadays any application running in Graphical Environment (GUI). Using the JavaFX Scene Builder would be great, but of course this is enter in Java world. Another possibility would be use Python to interface with other GUI Generator... or something like that.
    Fujitsu PowerCOBOL is in my opinion one of the best implementations of this paradigm.
    The next step for the GNU COBOL should be "ease of use".

    Best Regards,
    PR

     
    Last edit: Paulo Reis 2014-07-13
    • Brian Tiffin

      Brian Tiffin - 2014-07-13

      Paulo;

      I'll disagree a little. I'm finding that the coding is very similar to the level of burden a C programmer would face. It feels 'practical', but yes, not that easy. (Mainly due to the size of the API and learning what's what).

      Federico is working on a project, guicobol. It's a preprocessor aimed at easing graphical application writing, modeled on INVOKE.

      For ease of use, going forward, keep an eye on the guicobol project.

      http://sourceforge.net/projects/guicobol

      There are still lots of other options to explore as well.

      Cheers,
      Brian

       
    • federico

      federico - 2014-08-03

      The experimental GuiCobol has the same Powercobol gui idea.
      I wrote it just using when possible the same properties and methods.
      It allows you also to design using GLADE and managing the xml files..

      It's only a test..as soon as possible I would like to recompile it with GNUCobol 2.0 and GTK 3.0.. and add new object..

      Some are already cool..

      Federico

       
  • Bruce Martin

    Bruce Martin - 2014-07-14

    Quick question Brian, is GTK based on 4 byte integer or 8 byte long's ??

    One thing about java (and C# as well) is it is very 4-byte Integer centric, all the core libraries use integers. Java's text-document model is built around integers ===>> Can only display 2gb of Text in JTextArea etc; Tables in Java can only display 2 billion rows. With the new JavaFX it would of been sensible to use longs, but they used integers in the bits I have looked at.

    While 2 billion is a lot, it is no longer infinity. I have 8gb on my PC, I saw someone asking question why they could not load a 11 gb csv in python (they had 32 gb).
    There is a lot of software that assumes 2gb will not be reached.
    See http://comments.gmane.org/gmane.comp.db.foxpro.profox/124928


    With the RecordEditor, I have just updated my Text-Document models to use 8-byte longs internally and check for max-integer when interfacing with standard Java libraries.
    I am going to have to do the same for the Table displays.

     
    Last edit: Bruce Martin 2014-07-14
    • Brian Tiffin

      Brian Tiffin - 2014-07-14

      Bruce; this answer comes with wishywashy ("I'm not legally allowed to give legal advice" type warnings).

      GLib is advertised as 64 bit clean, but a lot of the GTK 3 API signatures use gint (sized at 4 bytes on my 64 bit machine).

      For instance, gtk_text_buffer_get_char_count returns a gint.

      My "I refuse to stand by my word" answer is that GTK is based on 4 byte integer.

      Cheers,
      Brian

       
  • steve williams

    steve williams - 2014-07-14

    In a previous century, I developed a data warehouse in Python using FTP with a callback to copy legacy data. FTP would fail at 2 gb because the record count was an int.

    So I modified the Python FTP code (written in Python!) to make the count a long.

    And I thought "...in what other language...".

     
    • Brian Tiffin

      Brian Tiffin - 2014-07-14

      Hmm, Steve;

      Prodded by Paulo's post, the next time I get to sit down and try a few things, I was going to play with GtkBuilder and reading in Glade XML definition files. (Also an excuse to start an experimental kick at a COBOL package repository.) Perhaps I'll be pestering you for hints, do's and dont's. ;-)

      Cheers,
      Brian

       
      • Paulo Reis

        Paulo Reis - 2014-07-14

        I want to follow that development.
        Many thanks

        Regards,
        Paul

         
  • Brian Tiffin

    Brian Tiffin - 2014-08-02

    I think, the first kick at bindings a few years back can be reduced, at a high level, and with function-id, to something like:

          *> Tectonics: cobc -x cobweb-goodbye.cob
          *> ***************************************************************
           identification division.
           program-id. cobweb-goodbye.
    
           environment division.
           configuration section.
           repository.
               function
                   new-window new-box new-label new-entry new-button
                   add-to-box
               function all intrinsic.
    
           data division.
           working-storage section.
           01 gtk-window uage pointer.
           01 gtk-box usage pointer.
           01 gtk-label usage pointer.
           01 gtk-button usage pointer.
           01 gtk-entry usage pointer.
           01 entry-clicked-handler usage program-pointer.
           01 entry-button-handler usage program-pointer.
           01 extraneous usage binary-long.
           01 anonymous usage pointer.
    
           01 HORIZONTAL constant as 1.
    
          *> ***************************************************************
           procedure division.
    
           move new-window() to gtk-window
           move new-box(HORIZONTAL) to gtk-box
    
           move new-label("Goodbye, ") to gtk-label
           move add-to-box(gtk-box, gtk-label) to extraneous
    
           set entry-clicked-handler to entry "cobweb-text-entry-clicked"
           move new-entry(entry-clicked-handler) to gtk-entry
           move add-to-box(gtk-box, gtk-entry) to extraneous
    
           move new-button(" you'll be leaving me today") to gtk-button
           set button-clicked-handler to entry "cobweb-button-clicked"
           move add-to-box(gtk-box, gtk-button) to extraneous
    
           call "gtk-main" returning omitted
               on exception
                   display "Sorry, no gtk for you" upon syserr end-display
           end-call
    
           goback.
    
          *> ***************************************************************
           identification division.
           program-id. cobweb-text-entry-clicked.
           display "it worked?" upon syserr end-display
           goback.
           end program cobweb-text-entry-clicked.
    
          *> ***************************************************************
           identification division.
           program-id. cobweb-button-clicked.
           procedure division using event-frame.
           move get-text(event-frame) to process-to-kill
           call "SYSTEM" using concatenate("kill ", process-to-kill) end-call
           display
               "Sent kill signal to process " process-to-kill
               upon syserr
           end-display
           goback.
           end-program cobweb-button-clicked.
    
           end-program cobweb-goodbye.
    

    This is pondering code, won't compile, as it skips over the linkage details and lacks the support functions. Next step.

    The 15 lines of procedure division code, above, should put up a window, with a Goodbye label, a text entry field (for a process id) and the you'll be leaving me today button that will trigger a system call to kill a process by number. You have to be humming Pink Floyd when pressing the button, even though the lyrics are completely wrong

    Joking aside, I'm thinking that application layer GNU Cobol gui code can be made to be pretty easy on the brain.

    Next step is the function wrappers to the CALL sequences. Guessing, half a thousand lines or so.

    Application developers might need only write a few source lines, akin to:

           COPY cobweb-gtk-preamble.
    
           procedure division.
    
           move new-window() to gtk-window
           move new-box(gtk-window, HORIZONTAL) to gtk-box
    
           move new-label(gtk-box, "Goodbye, ") to gtk-label
           move new-entry(gtk-box, "cobweb-text-entry-clicked") to gtk-entry
           move new-button(gtk-box, "cobweb-button-clicked",
               " you'll be leaving me today")
             to gtk-button
    
           COPY cobweb-gtk-go.
    
           goback.
    

    to experiment with guis after that, I think. (And no, the default action of a button won't be to try and kill off processes, but it's the goal of a goodbye program; a small window for getting rid of pesky other programs that are spinning); and maybe and think, goodbye process, hello eas(ier). While humming Pink Floyd.

    I'm getting the feeling that the above can be factored out even more perhaps, the non container widgets can be effectively anonymous, once connected to an event handler, hmmm.

            COPY cobweb-gtk-preamble.
    
            move new-window() ...
            move new-box(gtk-window, ...
            move new-button(gtk-box, ... new-entry(... new-label(... )))
              to anonymous
    
            COPY cobweb-gtk-go.
    
            ... handlers ...
    

    or

            COPY cobweb-gtk-preamble.
            move new-builder("glade-filename.xml") to anonymous
            COPY cobweb-gtk-go.
    
            ... handlers ...
    

    More soonish.

    Cheers,
    Brian

     
    Last edit: Brian Tiffin 2014-08-17
    • Brian Tiffin

      Brian Tiffin - 2014-08-09

      Road block,

      Current 2.0's don't allow for FUNCTION-ID RETURNING a pointer, there is a datatype tripup in the parser...

      It'll be fixed.

      But, modifying arguments works, for the now

      GNU    >>SOURCE FORMAT IS FIXED
      Cobol *> *******************************************************
      cob   *> Author:    Brian Tiffin
        web *> Date:      20130308, 20140712
            *> Purpose:   A cobweb extension, periodic table
      GTK+  *> License:   GPL 3.0 or greater
            *> Tectonics:
            *>  cobc -m -g -debug cobweb-gtk.cob voidcall.c
            *>    `pkg-config --libs gtk+-3.0`
            *> ********************************************************
      id     identification division.
             program-id. cobweb-gtk.
             environment division.
             configuration section.
             repository.
                 function new-window
                 function all intrinsic.
      
      data   data division.
             working-storage section.
             01 newline pic x value x"0a".
             01 result  pic x(8).
      
             01 gtk-window usage pointer.
      
      code   procedure division.
             display
                 "*> cobweb-gtk is for linking; UDF repository:" upon syserr
             end-display
             display
                 "environment division." newline
                 "configuration section." newline
                 "repository." newline
                 "    function new-window new-box new-label new-entry" newline
                 "        new-button" newline
                 "    function all intrinsic."
             end-display
      
             display gtk-window end-display
             move new-window(gtk-window) to result
             display gtk-window end-display
      
      done   goback.
      
             end program cobweb-gtk.
      

      Passing the pointer in, it will be far better when this is the returning value. Function parameters are ALWAYS by reference so the argument in is modifiable.

      (The test head FUNCTION-ID new-window triggers a gui, long listing, skipped here, but it gets factored out into the dozen or so high level starter functions next)

      $ make
      cobc -m -g -debug cobweb-gtk.cob voidcall.c `pkg-config --libs gtk+-3.0`
      $ cobcrun cobweb-gtk
      *> cobweb-gtk is for linking; UDF repository:
      environment division.
      configuration section.
      repository.
          function new-window new-box new-label new-entry
              new-button
          function all intrinsic.
      0x0000000000000000
      GNU Cobol: GTK main eventloop terminated normally
      0x0000000001af2070
      

      It will make for some fairly concise GUI screens if it pans out further, I think.

      Cheers,
      Brian

       
  • Brian Tiffin

    Brian Tiffin - 2014-08-14

    Ok, this is a taunt post, as it won't work anywhere but here yet.

    GNU    >>SOURCE FORMAT IS FIXED
    Cobol *> ***********************************************
    cob   *> Author:    Brian Tiffin
      web *> Date:      20130308, 20140712
          *> Purpose:   A cobweb extension, periodic table
    GTK+  *> License:   GPL 3.0 or greater
          *> Tectonics:
          *>  cobc -x -g -debug cobweb-gui.cob cobweb-gtk.so
          *> ************************************************
           identification division.
           program-id. cobweb-gui.
    
           environment division.
           configuration section.
           repository.
               function new-window 
               function new-box
               function new-label
               function new-entry
               function new-button
               function gtk-go
               function all intrinsic.
    
           data division.
           working-storage section.
           01 GTK-ORIENTATION-HORIZONTAL constant as 0.
           01 GTK-ORIENTATION-VERTICAL   constant as 1.
    
           01 result               pic x(8).
    
           01 gtk-window           usage pointer.
           01 gtk-box              usage pointer.
           01 orientation          usage binary-long.
           01 gtk-label            usage pointer.
           01 gtk-entry            usage pointer.
           01 gtk-button           usage pointer.
    
          *> ***************************************************
           procedure division.
    
           move new-window() to gtk-window
           move GTK-ORIENTATION-HORIZONTAL to orientation
           move new-box(gtk-window, orientation) to gtk-box
           move new-label(gtk-box, z"Goodbye") to gtk-label
           move new-entry(gtk-box, "cobweb-entry-activated")
             to gtk-entry
           move new-button(gtk-box, z"you're leaving me today",
                           "cobweb-button-clicked")
             to gtk-button
           move gtk-go(gtk-window) to result
    
           goback.
           end program cobweb-gui.
    

    and a

    $ ./cobweb-gui 
    Somebody entered 0x0000000001d0a000
    Somebody clicked 0x0000000001ed1060
    

    A GTK program with label, entry and button in some 8 lines of procedure, 8ish lines of data and 8ish lines of repository paperwork (for the application layer; some 400 lines of support, but once the other 42 thousand support lines are written, will require only one or two entries in the tectonics, from then on).

    With this testhead gui looking like

    GNU Cobol functional GTK

    This required a patch to the compiler to allow for RETURNING a-pointer in FUNCTION-ID, a patch I'm not quite satisfied with yet, so more postings to follow.

    Cheers,
    Brian

    p.s. Just to repeat, over and over, all these GUI applications can be directed to a HTML5/CSS3 and Websocket transform (for free) for use in a browser, with the GDK Broadway backend support for web browsers as a "graphic device". All that is needed is a few environment variables set before application startup. No source code considerations, nor recompiles. Just to repeat, over and over. :-)

     
    Last edit: Brian Tiffin 2014-08-14
  • Brian Tiffin

    Brian Tiffin - 2014-08-16

    More teasing.

    Ok, I can't release the FUNCTION-ID RETURNING pointer patch yet, it generates warnings, ala

    ... lots of the following pattern...
    cobweb-gui.c:152:32: warning: assignment makes pointer from integer without a cast [enabled by default]
       (*(unsigned char **) (b_17)) = cob_get_int (func_NEW__ENTRY.funcfld (&cob_dyn_8, 2, &f_13, (cob_field *)&c_2));
                                    ^
    [btiffin@localhost gtk]$ ./cobweb-gui 
    Somebody entered 0x0000000000d0b000 in 0x0000000000402664
    with 112233445566                                                                    
    Somebody entered 0x0000000000d0b1c0 in 0x0000000000402664
    with -9                                                                              
    

    But, it does work. This code

    GNU    >>SOURCE FORMAT IS FIXED
    Cobol *> *******************************************************
    cob   *> Author:    Brian Tiffin
      web *> Date:      20130308, 20140715
          *> Purpose:   A cobweb extension, functional GTK+
    GTK+  *> License:   GPL 3.0 or greater
          *> Tectonics:
          *>  cobc -m -g -debug cobweb-gtk.cob voidcall.c
          *>    `pkg-config --libs gtk+-3.0`
          *>  cobc -x -g -debug cobweb-gui.cob cobweb-gtk.so
          *> ********************************************************
           identification division.
           program-id. cobweb-gui.
    
           environment division.
           configuration section.
           repository.
               function new-window 
               function new-box
               function new-label
               function new-entry
               function new-button
               function gtk-go
    
               function all intrinsic.
    
           data division.
           working-storage section.
           01 GTK-ORIENTATION-HORIZONTAL constant as 0.
           01 GTK-ORIENTATION-VERTICAL   constant as 1.
    
           01 newline              pic x value x"0a".
           01 result               pic x(8).
    
           01 gtk-window           usage pointer.
           01 gtk-container        usage pointer.
    
           01 orientation          usage binary-long.
           01 gtk-box              usage pointer.
           01 gtk-verticalbox      usage pointer.
    
           01 gtk-label            usage pointer.
           01 gtk-entry            usage pointer.
           01 gtk-button           usage pointer.
           01 gtk-signal-entry     usage pointer.
    
          *> ***************************************************************
           procedure division.
    
          *> Down (two boxes)
           move GTK-ORIENTATION-VERTICAL to orientation
    
           move new-window() to gtk-window
           move new-box(gtk-window, orientation) to gtk-container
    
          *> First box Across
           move GTK-ORIENTATION-HORIZONTAL to orientation
           move new-box(gtk-container, orientation) to gtk-box
           move new-label(gtk-box, z"Goodbye") to gtk-label
           move new-entry(gtk-box, "cobweb-entry-activated") to gtk-entry
           move new-button(gtk-box, z"you're leaving me today",
                           "cobweb-button-clicked") to gtk-button
    
          *> Second box Down
           move GTK-ORIENTATION-VERTICAL to orientation
           move new-box(gtk-container, orientation) to gtk-verticalbox
           move new-label(gtk-verticalbox, z"with signal") to gtk-label
           move new-entry(gtk-verticalbox, "cobweb-entry-activated")
             to gtk-signal-entry
    
           move gtk-go(gtk-window) to result
    
           goback.
           end program cobweb-gui.
    
          *> ********************************************************
          *> local function to kick GTK given a widget to show-all with 
          *> ********************************************************
    id     identification division.
           function-id. gtk-go. 
           environment division.
           configuration section.
           repository.
               function all intrinsic.
    
    data   data division.
    link   linkage section.
           01 gtk-window           usage pointer.
           01 extraneous           pic x(8).
    
    code   procedure division using gtk-window returning extraneous.
          *> ready to display
           call "gtk_widget_show_all" using
               by value gtk-window
               returning omitted
           end-call
    
          *> Enter the GTK event loop
           call "gtk_main" returning omitted end-call
    
          *> when control returns here, the GTK event loop has terminated
    done   goback.
           end function gtk-go.
    
          *> ********************************************************
          *> Callback event handlers 
          *> ********************************************************
    id     identification division.
           program-id. cobweb-button-clicked.
           data division.
           linkage section.
           01 gtk-widget           usage pointer.
           01 gtk-window           usage pointer.
    
           procedure division using by value gtk-widget gtk-window.
    
           display
               "Somebody clicked " gtk-widget upon syserr
           end-display
    
    done   goback.
           end program cobweb-button-clicked.
    
          *> ********************************************************
           REPLACE ==FIELDSIZE== BY ==80==.
    
    id     identification division.
           program-id. cobweb-entry-activated.
           data division.
           working-storage section.
           01 gtk-text-pointer     usage pointer.
           01 gtk-text-access      pic x(FIELDSIZE) based.
           01 the-text-entry       pic x(FIELDSIZE).
    
           linkage section.
           01 gtk-widget           usage pointer.
           01 gtk-window           usage pointer.
    
           procedure division using by value gtk-widget gtk-window.
    
           display
               "Somebody entered " gtk-widget " in " gtk-window
               upon syserr
           end-display
    
           call "gtk_entry_get_text" using
                   by value gtk-widget
               returning gtk-text-pointer
           end-call
           if gtk-text-pointer not equal null then
               initialize the-text-entry
               set address of gtk-text-access to gtk-text-pointer
               string gtk-text-access
                   delimited by x"00" into the-text-entry
               end-string
           end-if
    
           display
               "with " the-text-entry
           end-display
    
    done   goback.
           end program cobweb-entry-activated.
    

    which logged the run above, that looked like (yes, very poorly designed and styled widget block; I just needed to test up and down and across) this gui

    GNU Cobol functional GTK

    again, from a run of

    [btiffin@localhost gtk]$ ./cobweb-gui 
    Somebody entered 0x0000000000d0b000 in 0x0000000000402664
    with 112233445566                                                                    
    Somebody entered 0x0000000000d0b1c0 in 0x0000000000402664
    with -9
    

    Most of the code in the entry callback handler will be a function, entry-get-text, umm, soon. Still not bad for 100 lines of code, 15 of which laydown the gui, in my biased opinion.

    And I'll get the patch in split-lickety.

    Cheers,
    Brian

     
    Last edit: Brian Tiffin 2014-08-16
    • Brian Tiffin

      Brian Tiffin - 2014-08-16

      Oh, and by the by.

      enums map well to CONSTANT, but referencing CONSTANT is a no-no. User defined functions are always BY REFERENCE, so CONSTANT can't be used, (as you'd expose an address that could be used to modify the constant). So, no.

      That caused the extra 3 lines of code in cobweb-gui to stuff the box layout constant in a variable, so it can be passed by address to function LINKAGE. That can be avoided if HORIZONTAL and VERTICAL become USAGE BINARY-INTEGER VALUE 0 (or 1) etc...

      So, I think the cobweb-gtk.cob sources will define all the enum values with PIC and USAGE, avoiding the tantalizing CONSTANT. The goal is less application code to get simple things done.

      Thinking out loud, sorry.

            *> Main container, Down (two boxes)
             move new-window() to gtk-window
             move new-box(gtk-window, VERTICAL) to gtk-container
      
            *> First box Across
             move new-box(gtk-container, HORIZONTAL) to gtk-box
             move new-label(gtk-box, z"Goodbye") to gtk-label
             move new-entry(gtk-box, "cobweb-entry-activated") to gtk-entry
             move new-button(gtk-box, z"you're leaving me today",
                             "cobweb-button-clicked") to gtk-button
      
            *> Second box Down
             move new-box(gtk-container, VERTICAL) to gtk-verticalbox
             move new-label(gtk-verticalbox, z"with signal") to gtk-label
             move new-entry(gtk-verticalbox, "cobweb-entry-activated")
               to gtk-signal-entry
      
             move gtk-go(gtk-window) to result
      
             goback.
      

      As this gets refined, it's starting to feel very tight, and way fun to explore. Plopping in 10 to 30 line of procedure division for a gui. Some few more for each event handler. Fun.

      A nice function will be new-builder, which will read most any GTK friendly IDE visual design tool XML output.

      If, I'm not mistaken, procedure division will be

          move gtk-go(new-builder("xmlfilename")) to return-code
          goback.
      

      Starting to feel very easy, as well as practical Paulo.
      Umm, unless you take into account that you only need to, update a compiler, jury rig the build tree, ummm, take careful care over what library is where, ... and ignore very critical warnings. Yeah, there we still have ease of use issues. ;-)

      Cheers,
      Brian

       
      Last edit: Brian Tiffin 2014-08-16
  • Brian Tiffin

    Brian Tiffin - 2014-08-16

    Way too much fun.

    GNU Cobol functional GTK

    $ ./cobweb-gui 
    Somebody set 0x00000000011401c0 with this is a quick test of 80 character sequential reads from a file to a GTK+ GUI.
    Somebody clicked 0x00000000011ef060
    

    Read some data from a sequential file, and preset it in an entry, a little bit more actual COBOL program, like for realz.

    GNU    >>SOURCE FORMAT IS FIXED
    Cobol *> *******************************************************
    cob   *> Author:    Brian Tiffin
      web *> Date:      20130308, 20140715
          *> Purpose:   A cobweb extension, functional GTK+
    GTK+  *> License:   GPL 3.0 or greater
          *> Tectonics:
          *>  cobc -m -g -debug cobweb-gtk.cob voidcall.c
          *>    `pkg-config --libs gtk+-3.0`
          *>  cobc -x -g -debug cobweb-gui.cob cobweb-gtk.so
          *> ********************************************************
           identification division.
           program-id. cobweb-gui.
    
           environment division.
           configuration section.
           repository.
               function new-window 
               function new-box
               function new-label
               function new-entry
               function new-button
               function entry-set-text
               function gtk-go
               function all intrinsic.
    
           input-output section.
           file-control.
               select bondjamesbond
               assign to "007"
               organization is sequential
               status is dead-or-alive
               .
    
           data division.
           file section.
           fd bondjamesbond.
              01 some-80-characters    pic x(80).
    
           working-storage section.
           01 dead-or-alive        pic 99.
    
           01 GTK-ORIENTATION-HORIZONTAL constant as 0.
           01 GTK-ORIENTATION-VERTICAL   constant as 1.
    
           01 newline              pic x value x"0a".
           01 result               pic x(8).
    
           01 gtk-window           usage pointer.
           01 gtk-container        usage pointer.
    
           01 orientation          usage binary-long.
           01 gtk-box              usage pointer.
           01 gtk-verticalbox      usage pointer.
    
           01 gtk-label            usage pointer.
           01 gtk-entry            usage pointer.
           01 gtk-button           usage pointer.
           01 gtk-signal-entry     usage pointer.
    
          *> ***************************************************************
           procedure division.
           open input bondjamesbond
           if dead-or-alive less than 10 then
               read bondjamesbond end-read
           end-if
           close bondjamesbond
    
          *> Down
           move GTK-ORIENTATION-VERTICAL to orientation
    
           move new-window() to gtk-window
           move new-box(gtk-window, orientation) to gtk-container
    
          *> Across
           move GTK-ORIENTATION-HORIZONTAL to orientation
           move new-box(gtk-container, orientation) to gtk-box
           move new-label(gtk-box, z"And?") to gtk-label
           move new-entry(gtk-box, "cobweb-entry-activated") to gtk-entry
           move new-button(gtk-box, z"expedite",
                           "cobweb-button-clicked") to gtk-button
    
          *> Down
           move GTK-ORIENTATION-VERTICAL to orientation
           move new-box(gtk-container, orientation) to gtk-verticalbox
           move new-label(gtk-verticalbox, z"secret notes, ummm, until now")
             to gtk-label
           move new-entry(gtk-verticalbox, "cobweb-entry-activated")
             to gtk-signal-entry
    
           move entry-set-text(gtk-signal-entry, some-80-characters)
             to result
    
           move gtk-go(gtk-window) to result
    
           goback.
           end program cobweb-gui.
    
          *> ********************************************************
          *> local function to kick GTK given a widget to show-all with 
          *> ********************************************************
    id     identification division.
           function-id. gtk-go. 
           environment division.
           configuration section.
           repository.
               function all intrinsic.
    
    data   data division.
    link   linkage section.
           01 gtk-window           usage pointer.
           01 extraneous           pic x(8).
    
    code   procedure division using gtk-window returning extraneous.
          *> ready to display
           call "gtk_widget_show_all" using
               by value gtk-window
               returning omitted
           end-call
    
          *> Enter the GTK event loop
           call "gtk_main" returning omitted end-call
    
          *> when control returns here, the GTK event loop has terminated
    done   goback.
           end function gtk-go.
    
          *> ********************************************************
          *> Callback event handlers 
          *> ********************************************************
    id     identification division.
           program-id. cobweb-button-clicked.
           data division.
           linkage section.
           01 gtk-widget           usage pointer.
           01 gtk-window           usage pointer.
    
           procedure division using by value gtk-widget gtk-window.
    
           display
               "Somebody clicked " gtk-widget upon syserr
           end-display
    
    done   goback.
           end program cobweb-button-clicked.
    
          *> ********************************************************
           REPLACE ==FIELDSIZE== BY ==80==.
    
    id     identification division.
           program-id. cobweb-entry-activated.
           data division.
           working-storage section.
           01 gtk-text-pointer     usage pointer.
           01 gtk-text-access      pic x(FIELDSIZE) based.
           01 the-text-entry       pic x(FIELDSIZE).
    
           linkage section.
           01 gtk-widget           usage pointer.
           01 gtk-window           usage pointer.
    
           procedure division using by value gtk-widget gtk-window.
    
           display
               "Somebody entered " gtk-widget " in " gtk-window
               upon syserr
           end-display
    
           call "gtk_entry_get_text" using
                   by value gtk-widget
               returning gtk-text-pointer
           end-call
           if gtk-text-pointer not equal null then
               initialize the-text-entry
               set address of gtk-text-access to gtk-text-pointer
               string gtk-text-access
                   delimited by x"00" into the-text-entry
               end-string
           end-if
    
           display
               "with " the-text-entry
           end-display
    
    done   goback.
           end program cobweb-entry-activated.
    
          *> ********************************************************
    id     identification division.
           function-id. entry-set-text. 
           environment division.
           configuration section.
           repository.
               function all intrinsic.
    
    data   data division.
    link   linkage section.
           01 gtk-entry            usage pointer.
           01 the-text-entry       pic x any length.
           01 extraneous           usage binary-long.
    
          *> ********************************************************
    
          *> ********************************************************
    code   procedure division using gtk-entry the-text-entry
               returning extraneous.
    
           display
               "Somebody set " gtk-entry " with " the-text-entry
               upon syserr
           end-display
    
           call "gtk_entry_set_text" using
                   by value gtk-entry
                   by content function concatenate(
                       function trim(the-text-entry), x"00")
               returning omitted
           end-call
    
    done   goback.
           end function entry-set-text.
    

    Way fun.

    Cheers,
    Brian

     
    Last edit: Brian Tiffin 2014-08-16
  • Brian Tiffin

    Brian Tiffin - 2014-08-16

    DOH! Anyone reading along, there was some wrong thinking early on that carried through.

    Don't MOVE to pointers, SET pointers.

          *> Main window and top level container
           set gtk-window to new-window()
           set gtk-container to new-box(gtk-window, VERTICAL)
    
          *> First box, across
           set gtk-box to new-box(gtk-container, HORIZONTAL)
           set gtk-label to new-label(gtk-box, z"And?")
           set gtk-entry to new-entry(gtk-box, "cobweb-entry-activated")
           set gtk-button to new-button(gtk-box, z"expedite",
                           "cobweb-button-clicked")
    

    Still doesn't compile though with current 2.0, tripping the same little parser validation bug, but still

    Apologies to anyone that has gotten through this TL;DR thread. Most of which is riddled with mistakes. ;-)

    Brian

     
  • Michael Anderson

    Brian,

    move new-window() to gtk-window *> that is just so "COBOL" simple.

    And maybe one-day, open the door to working within the screen section, and therefore, with the GDK Broadway back-end, may give old (and NEW) COBOL Applications a place in the WebApp world, without modifying one single line of COBOL.....

    And having the ability for a FUNCTION-ID to return a pointer, will also open the door to other nice libs, like event libs (libev), and database callbacks, and so on.

    Functions returning pointers is a no-brainer, a must have....

    Your Work/Play :-) is Very much appreciated!

    Mike.

     
    • Brian Tiffin

      Brian Tiffin - 2014-08-16

      Yes on FUNCTION-ID and POINTER (and PROGRAM-POINTER) Mike, but, through SET.

      The way I hacked through the compiler to allow the MOVE instruction hid another validation step. If the patch was released as is, it'd allow function move of any kind of COBOL record structures to pointers. That would be :-( bad (sad bad).

      Yeah, it won't be that way. :-) The patch will take a reset and try again.

      But, on the other hand...returning a COBOL record will always work...this is dawning now Michael, might not need to get a safe patch of the compiler if the pointer is passed in and out as part of a COBOL record reference. And MOVE will be fine and fit then too.

      But but, if the destination is a pointer, it should only ever be set with SET. In my humble, otherwise safety is diminished, considerably.

          01 gtk-window.
             05 gtk-window-ref usage pointer.
      

      Hmm,...

      Cheers,
      Brian

       
      Last edit: Brian Tiffin 2014-08-17
      • Brian Tiffin

        Brian Tiffin - 2014-08-17

        The brain tickle Michael caused worked out. MOVE and data records was the way to go. Current GNU Cobol 2.0 builds will work, no need for a patch (it will still be patched to allow for SET, but for now, this works just grand).

        Started a new thread at [ab28685d] and attached the initial tarball here as well, just in case someone makes it to the bottom of this learner thread. ;-)

        Cheers,
        Brian

         

        Related

        Discussion: ab28685d


        Last edit: Simon Sobisch 2014-08-18
  • Brian Tiffin

    Brian Tiffin - 2014-08-17

    One final post; code that compiles with 2.0, too early to call alpha (signatures will definitely change) but there to play with.

    GNU    >>SOURCE FORMAT IS FIXED
    Cobol *> *******************************************************
    cob   *> Author:    Brian Tiffin
      web *> Date:      20130308, 20140717
          *> Purpose:   A cobweb extension, functional GTK+
    GTK+  *> License:   GPL 3.0 or greater
          *> Tectonics:
          *>  cobc -m -g -debug cobweb-gtk.cob voidcall.c
          *>    `pkg-config --libs gtk+-3.0`
          *> ********************************************************
    id     identification division.
           program-id. cobweb-gtk.
           environment division.
           configuration section.
           repository.
               function new-window 
               function new-box
               function new-label
               function new-entry
               function new-button
               function gtk-go
               function all intrinsic.
    
    data   data division.
           working-storage section.
           01 HORIZONTAL           usage binary-long value 0.
           01 VERTICAL             usage binary-long value 1.
    
           01 newline              pic x value x"0a".
           01 result               pic x(8).
    
           01 gtk-window-data.
              05 gtk-window        usage pointer.
           01 width-hint           usage binary-long value 270.
           01 height-hint          usage binary-long value 18.
    
           01 gtk-box-data.
              05 gtk-box           usage pointer.
           01 orientation          usage binary-long.
    
           01 gtk-label-data.
              05 gtk-label         usage pointer.
           01 gtk-entry-data.
              05 gtk-entry         usage pointer.
           01 gtk-button-data.
              05 gtk-button        usage pointer.
    
           01 venue                pic x(8).
              88 broadway              values "broadway", "BROADWAY".
    
    code   procedure division.
           display
               "      *> cobweb-gtk is for linking; UDF repository follows"
               upon syserr
           end-display
           display
               "       environment division."                      newline
               "       configuration section."                     newline
               upon syserr
           end-display
           display
               "       repository."                                newline
               "           function new-window"                    newline
               "           function new-box"                       newline
               "           function new-label"                     newline
               "           function new-entry"                     newline
               "           function new-button"                    newline
               "           function new-textview"                  newline
               "           function entry-get-text"                newline
               "           function entry-set-text"                newline
               "           function gtk-go"                        newline
               "           function all intrinsic."
           end-display
    
          *> test
           move new-window(z"cobweb-gtk", width-hint, height-hint)
             to gtk-window-data
           move new-box(gtk-window, HORIZONTAL) to gtk-box-data
           move new-label(gtk-box, z"And? ") to gtk-label-data
           move new-entry(gtk-box, "cobweb-entry-clicked") to gtk-entry-data
           move new-button(gtk-box, z"Expedite", "cobweb-button-clicked")
             to gtk-button-data
    
           move gtk-go(gtk-window) to result
    
          *> Control can pass back and forth to COBOL subprograms,
          *>  by event, but control flow stops above, until the
          *>  window is torn down and the event loop exits
           display
               "GNU Cobol: GTK main eventloop terminated normally"
               upon syserr
           end-display
    
           accept venue from environment "GDK_BACKEND" end-accept
           if broadway then
               display "Ken sends his regards" upon syserr end-display
           end-if
    
    done   goback.
           end program cobweb-gtk.
    
          *> ********************************************************
          *> Callback event handlers 
          *> ********************************************************
    id     identification division.
           program-id. cobweb-button-clicked.
           data division.
           linkage section.
           01 gtk-widget           usage pointer.
           01 gtk-window           usage pointer.
    
           procedure division using by value gtk-widget gtk-window.
    
           display
               "Somebody clicked " gtk-widget upon syserr
           end-display
    
    done   goback.
           end program cobweb-button-clicked.
    
          *> ********************************************************
    id     identification division.
           program-id. cobweb-entry-activated.
           data division.
           linkage section.
           01 gtk-widget           usage pointer.
           01 gtk-window           usage pointer.
    
           procedure division using by value gtk-widget gtk-window.
    
           display
               "Somebody entered " gtk-widget upon syserr
           end-display
    
    done   goback.
           end program cobweb-entry-activated.
    
          *> ********************************************************
          *> widget functions
          *> ********************************************************
    id     identification division.
           function-id. new-window. 
           environment division.
           configuration section.
           repository.
               function all intrinsic.
    
           data division.
    data   working-storage section.
           01 banner-msg   pic x(22) value z"GNU Cobol cobweb GTK+".
    
           01 gtk-quit-callback          usage program-pointer.
           01 gtk-quit-handler-id        usage pointer.
           01 gtk-void-callback          usage program-pointer.
    
           01 GTK-WINDOW-TOPLEVEL        constant as 0.
           01 gtk-data                   usage pointer.
    
          *> destined to be a callable, not a main, linkage in the future
           linkage section.
    link   01 window-title               usage pointer.
           01 width-hint                 usage binary-long.
           01 height-hint                usage binary-long.
           01 gtk-window-data.
              05 gtk-window              usage pointer.
    
    code   procedure division using window-title width-hint height-hint
               returning gtk-window-data.
    
          *> Start up the GIMP/Gnome Tool Kit
           call "gtk_init" using
               by value 0                          *> argc int
               by value 0                          *> argv pointer to pointer
               returning omitted                   *> void return, requires cobc 2010+
               on exception
                   display
                       "gtk_init link error, see pkg-config --libs gtk+-3.0"
                       upon syserr
                   end-display
    bail           stop run returning 1
           end-call
    
          *> Create a new window, returning handle as pointer
           call "gtk_window_new" using 
               by value GTK-WINDOW-TOPLEVEL        *> it's a zero or a 1 popup
               returning gtk-window                *> and remember the handle
           end-call
    
          *> More fencing, skimped on after this first test
           if gtk-window equal null then
               display
                   "GTK service error; gtk_window_new NULL"
                   upon syserr
               end-display
    bail       stop run returning 1
           end-if
    
          *> Hint to not let the sample window be too small
           call "gtk_window_set_default_size" using
               by value gtk-window                 *> by value is used to get the C address
               by value width-hint
               by value height-hint
               returning omitted                   *> another void
           end-call
    
          *> Put in the title, it'll be truncated in a size request window
           call "gtk_window_set_title" using
               by value gtk-window                 *> pass the C handle
               by reference window-title
               returning omitted
           end-call
    
          *> Connect death signals.
           set gtk-quit-callback to entry "gtk_main_quit"
           call "g_signal_connect_data" using
               by value gtk-window
               by reference z"destroy"             *> with inline Z string
               by value gtk-quit-callback          *> function call back pointer
               by value 0                          *> pointer to data
               by value 0                          *> closure notify to manage data
               by value 0                          *> connect before or after flag
               returning gtk-quit-handler-id       *> not used in this sample
           end-call
           call "g_signal_connect_data" using
               by value gtk-window
               by reference z"delete_event"        *> with inline Z string
               by value gtk-quit-callback          *> function call back pointer
               by value 0                          *> pointer to data
               by value 0                          *> closure notify to manage data
               by value 0                          *> connect before or after flag
               returning gtk-quit-handler-id       *> not used in this sample
           end-call
    
    done   goback.
           end function new-window.
    
          *> ********************************************************
    id     identification division.
           function-id. new-box. 
           environment division.
           configuration section.
           repository.
               function all intrinsic.
    
    data   data division.
    link   linkage section.
           01 gtk-window                 usage pointer.
           01 gtk-box-data.
              05 gtk-box                 usage pointer.
           01 orientation                usage binary-long.
    
    code   procedure division using gtk-window orientation
               returning gtk-box-data.
    
          *> Define a container. Boxey, but nice.
           call "gtk_box_new" using
               by value orientation
               by value 8                          *> pixels between widgets
               returning gtk-box
           end-call
    
          *> Add the box to the window
           call "gtk_container_add" using
               by value gtk-window
               by value gtk-box
               returning omitted
           end-call
    done   goback.
    COOL   end function new-box.
    
          *> ********************************************************
    id     identification division.
           function-id. new-label.
           environment division.
           configuration section.
           repository.
               function all intrinsic.
    
    data   data division.
    link   linkage section.
           01 gtk-container              usage pointer.
           01 gtk-label-data.
              05 gtk-label               usage pointer.
           01 label-text                 pic x any length.
    
    code   procedure division using gtk-container label-text
               returning gtk-label-data.
    
          *> Add a label
           call "gtk_label_new" using
               by reference label-text
               returning gtk-label
           end-call
    
          *> Add the label to the container
           call "gtk_container_add" using
               by value gtk-container
               by value gtk-label
               returning omitted
           end-call
    
    done   goback.
           end function new-label.
    
          *> ********************************************************
    id     identification division.
           function-id. new-entry.
           environment division.
           configuration section.
           repository.
               function all intrinsic.
    
    data   data division.
           working-storage section.
           01 cobweb-entry-callback      usage program-pointer.
           01 gtk-void-callback          usage program-pointer.
           01 gtk-quit-handler-id        usage pointer.
    
    link   linkage section.
           01 gtk-container              usage pointer.
           01 gtk-entry-data.
              05 gtk-entry               usage pointer.
           01 entry-callback             pic x any length.
    
    code   procedure division using gtk-container entry-callback
             returning gtk-entry-data.
    
          *> Add a single line text entry
           call "gtk_entry_new" returning gtk-entry
           end-call
    
          *> Add the entry to the container
           call "gtk_container_add" using
               by value gtk-container
               by value gtk-entry
               returning omitted
           end-call
    
          *> Connect a signal.  GNU Cobol doesn't generate void returns
          *>  so this calls a C function two-liner that calls the
          *>  COBOL entry, but returns void to the runtime stack frame
           set cobweb-entry-callback to entry entry-callback
           set gtk-void-callback to entry "voidcall"
           call "g_signal_connect_data" using
               by value gtk-entry
               by reference z"activate"            *> with inline Z string
               by value gtk-void-callback          *> function callback pointer
               by value cobweb-entry-callback      *> pointer to COBOL proc
               by value 0                          *> closure notify to manage data
               by value 0                          *> connect before or after flag
               returning gtk-quit-handler-id       *> not used in this sample
           end-call
    
    done   goback.
           end function new-entry.
    
          *> ********************************************************
    id     identification division.
           function-id. new-textview.
           environment division.
           configuration section.
           repository.
               function all intrinsic.
    
    data   data division.
           working-storage section.
           01 cobweb-entry-callback      usage program-pointer.
           01 gtk-void-callback          usage program-pointer.
           01 gtk-quit-handler-id        usage pointer.
    
    link   linkage section.
           01 gtk-container              usage pointer.
           01 gtk-textview-data.
              05 gtk-textview            usage pointer.
           01 entry-callback             pic x any length.
    
    code   procedure division using gtk-container entry-callback
             returning gtk-textview-data.
    
          *> Add a multi line text entry
           call "gtk_textview_new" returning gtk-textview
           end-call
    
          *> Add the entry to the container
           call "gtk_container_add" using
               by value gtk-container
               by value gtk-textview
               returning omitted
           end-call
    
          *> Connect signal wrapped in voidcall
           set cobweb-entry-callback to entry entry-callback
           set gtk-void-callback to entry "voidcall"
           call "g_signal_connect_data" using
               by value gtk-textview
               by reference z"activate"            *> with inline Z string
               by value gtk-void-callback          *> function call back pointer
               by value cobweb-entry-callback      *> pointer to COBOL proc
               by value 0                          *> closure notify to manage data
               by value 0                          *> connect before or after flag
               returning gtk-quit-handler-id       *> not used in this sample
           end-call
    
    done   goback.
           end function new-textview.
    
          *> ********************************************************
    id     identification division.
           function-id. new-button.
           environment division.
           configuration section.
           repository.
               function all intrinsic.
    
    data   data division.
           working-storage section.
           01 cobweb-button-callback     usage program-pointer.
           01 gtk-void-callback          usage program-pointer.
           01 gtk-quit-handler-id        usage pointer.
    
    link   linkage section.
           01 gtk-container              usage pointer.
           01 gtk-button-data.
              05 gtk-button              usage pointer.
           01 button-label               pic x any length.
           01 button-callback            pic x any length.
    
    code   procedure division using
               gtk-container button-label button-callback
               returning gtk-button-data.
    
          *> Add a labelled button
           call "gtk_button_new_with_label" using
               by reference button-label
               returning gtk-button
           end-call
    
          *> Add the button to the container
           call "gtk_container_add" using
               by value gtk-container
               by value gtk-button
               returning omitted
           end-call
    
          *> Connect signal wrapped in voidcall
           set cobweb-button-callback to entry button-callback
           set gtk-void-callback to entry "voidcall"
           call "g_signal_connect_data" using
               by value gtk-button
               by reference z"clicked"             *> with inline Z string
               by value gtk-void-callback          *> function call back pointer
               by value cobweb-button-callback     *> pointer to COBOL proc
               by value 0                          *> closure notify to manage data
               by value 0                          *> connect before or after flag
               returning gtk-quit-handler-id       *> not used in this sample
           end-call
    
    done   goback.
           end function new-button.
    
          *> ********************************************************
          *> helper functions
          *> ********************************************************
    
    id     identification division.
           function-id. gtk-go. 
           environment division.
           configuration section.
           repository.
               function all intrinsic.
    
    data   data division.
    link   linkage section.
           01 gtk-window           usage pointer.
           01 extraneous           pic x(8).
    
    code   procedure division using gtk-window returning extraneous.
          *> ready to display
           call "gtk_widget_show_all" using
               by value gtk-window
               returning omitted
           end-call
    
          *> Enter the GTK event loop
           call "gtk_main" returning omitted end-call
    
    done   goback.
           end function gtk-go.
    
          *> ********************************************************
           REPLACE ==FIELDSIZE== BY ==80==.
    
    id     identification division.
           function-id. entry-get-text. 
           environment division.
           configuration section.
           repository.
               function all intrinsic.
    
    data   data division.
           working-storage section.
           01 gtk-text-entry       usage pointer.
           01 gtk-text-buffer      pic x(FIELDSIZE) based.
    
    link   linkage section.
           01 gtk-entry            usage pointer.
           01 the-text-entry       pic x(FIELDSIZE).
    
    code   procedure division using gtk-entry
               returning the-text-entry.
    
           call "gtk_entry_get_text" using
                   by value gtk-entry
               returning gtk-text-entry
           end-call
           if gtk-text-entry not equal null then
               set address of gtk-text-buffer to gtk-text-entry
               initialize the-text-entry
               string
                   gtk-text-buffer delimited by x"00" into the-text-entry
               end-string
           end-if
    
    done   goback.
           end function entry-get-text.
    
          *> ********************************************************
    id     identification division.
           function-id. entry-set-text. 
           environment division.
           configuration section.
           repository.
               function all intrinsic.
    
    data   data division.
    link   linkage section.
           01 gtk-entry            usage pointer.
           01 the-text-entry       pic x any length.
           01 extraneous           usage binary-long.
    
    code   procedure division using gtk-entry the-text-entry
               returning extraneous.
    
           call "gtk_entry_set_text" using
                   by value gtk-entry
                   by content function concatenate(
                       function trim(the-text-entry), x"00")
               returning omitted
           end-call
    
    done   goback.
           end function entry-set-text.
    

    and a caller cobweb-gui.cob

    GNU    >>SOURCE FORMAT IS FIXED
    Cobol *> *******************************************************
    cob   *> Author:    Brian Tiffin
      web *> Date:      20130308, 20140717
          *> Purpose:   A cobweb extension, functional GTK+ sample
    GTK+  *> License:   GPL 3.0 or greater
          *> Tectonics:
          *>  cobc -m -g -debug cobweb-gtk.cob voidcall.c
          *>    `pkg-config --libs gtk+-3.0`
          *>  cobc -x -g -debug cobweb-gui.cob cobweb-gtk.so
          *> ********************************************************
           identification division.
           program-id. cobweb-gui.
    
           environment division.
           configuration section.
           repository.
               function new-window 
               function new-box
               function new-label
               function new-entry
               function new-button
               function entry-get-text
               function entry-set-text
               function gtk-go
               function all intrinsic.
    
           input-output section.
           file-control.
               select sample-data
               assign to "cobweb-gui-sample-data.txt"
               organization is sequential
               status is sample-data-status
               .
    
           data division.
           file section.
           fd sample-data.
              01 some-80-characters    pic x(80).
    
           working-storage section.
           01 sample-data-status       pic 99.
    
           01 HORIZONTAL           usage binary-long value 0.
           01 VERTICAL             usage binary-long value 1.
    
           01 newline              pic x value x"0a".
           01 result               pic x(8).
    
           01 gtk-window-data.
              05 gtk-window        usage pointer.
           01 width-hint           usage binary-long value 270.
           01 height-hint          usage binary-long value 20.
    
           01 gtk-container-data.
              05 gtk-container     usage pointer.
           01 orientation          usage binary-long.
    
           01 gtk-box-data.
              05 gtk-box           usage pointer.
           01 gtk-label-data.
              05 gtk-label         usage pointer.
           01 gtk-entry-data                                     external.
              05 gtk-entry         usage pointer.
           01 gtk-button-data.
              05 gtk-button        usage pointer.
    
           01 gtk-verticalbox-data.
              05 gtk-verticalbox   usage pointer.
           01 gtk-signal-entry-data.
              05 gtk-signal-entry  usage pointer.
    
          *> ***************************************************************
           procedure division.
           open input sample-data
           if sample-data-status less than 10 then
               read sample-data end-read
           end-if
           close sample-data
    
          *> Main window and top level container
           move new-window(z"cobweb-gui", width-hint, height-hint)
             to gtk-window-data
           move new-box(gtk-window, VERTICAL) to gtk-container-data
    
          *> First box, across
           move new-box(gtk-container, HORIZONTAL) to gtk-box-data
           move new-label(gtk-box, z"And?") to gtk-label-data
           move new-entry(gtk-box, "cobweb-entry-activated")
             to gtk-entry-data
           move new-button(gtk-box, z"expedite", "cobweb-button-clicked")
             to gtk-button-data
    
          *> Other box, down
           move new-box(gtk-container, VERTICAL) to gtk-verticalbox-data
           move new-label(gtk-verticalbox, z"sample data") to gtk-label-data
           move new-entry(gtk-verticalbox, "cobweb-entry-activated")
             to gtk-signal-entry-data 
    
          *> prefill the entry with the data read from the sample file
           move entry-set-text(gtk-signal-entry, some-80-characters)
             to result
    
           move gtk-go(gtk-window) to result
    
           goback.
           end program cobweb-gui.
    
          *> ********************************************************
          *> Callback event handlers 
          *> ********************************************************
    
           REPLACE ==FIELDSIZE== BY ==80==.
    
    id     identification division.
           program-id. cobweb-button-clicked.
    
           environment division.
           configuration section.
           repository.
               function entry-get-text
               function all intrinsic.
    
           data division.
           working-storage section.
           01 gtk-entry-data                                     external.
              05 gtk-entry         usage pointer. 
           01 the-text-entry       pic x(FIELDSIZE).
    
           linkage section.
           01 gtk-widget           usage pointer.
           01 gtk-window           usage pointer.
    
           procedure division using by value gtk-widget gtk-window.
    
          *> access the external, sample data text entry.
           move entry-get-text(gtk-entry) to the-text-entry        
           display trim(the-text-entry) " (via button)" end-display
    
    done   goback.
           end program cobweb-button-clicked.
    
          *> ********************************************************
    id     identification division.
           program-id. cobweb-entry-activated.
    
           environment division.
           configuration section.
           repository.
               function entry-get-text
               function all intrinsic.
    
           data division.
           working-storage section.
           01 the-text-entry       pic x(FIELDSIZE).
    
           linkage section.
           01 gtk-widget           usage pointer.
           01 gtk-window           usage pointer.
    
           procedure division using by value gtk-widget gtk-window.
    
          *> get the text entry widget data
           move entry-get-text(gtk-widget) to the-text-entry        
           display the-text-entry end-display
    
    done   goback.
           end program cobweb-entry-activated.
    

    Please note, if you download the tarball, the Makefile sets LD_RUN_PATH to include current working dir, dot, before compiling the gui sample, which makes it easier to find cobweb-gtk.so at runtime during testing.

    Please also note; the end-game. Application developers should only need to focus on two or three lines of event handler (or thousands, if it hits a sweet spot) and the 50 or so lines in the main procedure division to start putting up applications.

    A few more refactoring passes toward that front end end-game for cobweb-gtk, as it expands in features, and we'll see.

    To be honest, this listing may well be overwhelming and crufty, already. The goal is less, for more.

    Cheers,
    Brian

     
    Last edit: Brian Tiffin 2014-08-18

Log in to post a comment.