Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Support

Pages: 1 ... 40 41 [42] 43 44 ... 59
616
General Discussions / Re: MTSB
« on: January 02, 2011, 09:45:37 PM »
Here is an example of embedding a web browser in a ScriptBasic application.

Code: [Select]
DECLARE SUB DLL ALIAS "_idll" LIB "iDLL-Server"
DECLARE SUB REQUIRE ALIAS "_idll_require" LIB "iDLL-Server"
DECLARE SUB DEFINE ALIAS "_idll_define" LIB "iDLL-Server"

REQUIRE "libgtkembedmoz.so"

DEFINE "gtk_init NONE NONE 2 NULL NULL"
DEFINE "gtk_window_new delete-event WIDGET 1 INT"
DEFINE "gtk_window_set_title NONE NONE 2 WIDGET STRING"
DEFINE "gtk_window_set_position NONE NONE 2 WIDGET INT"
DEFINE "gtk_widget_set_size_request NONE NONE 3 WIDGET INT INT"
DEFINE "gtk_window_set_icon_name NONE NONE 2 WIDGET STRING"
DEFINE "gtk_widget_show_all NONE NONE 1 WIDGET"
DEFINE "gtk_moz_embed_set_comp_path NONE NONE 1 STRING"
DEFINE "gtk_moz_embed_set_profile_path NONE NONE 2 STRING STRING"
DEFINE "gtk_moz_embed_new NONE WIDGET 0"
DEFINE "gtk_moz_embed_load_url NONE NONE 2 WIDGET STRING"
DEFINE "gtk_moz_embed_open_stream NONE NONE 3 WIDGET STRING STRING"
DEFINE "gtk_moz_embed_append_data NONE NONE 3 WIDGET STRING INT"
DEFINE "gtk_server_callback NONE STRING 1 STRING"
DEFINE "gtk_server_exit NONE NONE 0"

DLL("gtk_init NULL NULL")
window = DLL("gtk_window_new 0")
DLL("gtk_window_set_title " & window & " \"ScriptBasic Open Source Project\"")
DLL("gtk_window_set_position " & window & " 1")
DLL("gtk_widget_set_size_request " & window & " 700 500")
DLL("gtk_window_set_icon_name " & window & " mozilla")
DLL("gtk_moz_embed_set_comp_path \"/usr/lib/kompozer/\"")
DLL("gtk_moz_embed_set_profile_path \"/tmp\" \"mozilla\"")
moz = DLL("gtk_moz_embed_new")
DLL("gtk_container_add " & window & " " & moz)
DLL("gtk_moz_embed_load_url " & moz & " \"http://www.scriptbasic.org/forum\"")
DLL("gtk_widget_show_all " & window)

REPEAT
  event = DLL("gtk_server_callback WAIT")
UNTIL event = window

DLL("gtk_server_exit")

Quote
GtkMozEmbed is an easy-to-use widget that will allow you to embed a Mozilla browser window into your Gtk application.

617
General Discussions / Re: MTSB
« on: January 02, 2011, 09:42:56 PM »
Here is a Gtk example instantiated multiple times as threads.

Code: Text
  1. INCLUDE curl.bas
  2.  
  3. ch = curl::init()
  4.  
  5. curl::option(ch,"NOBODY")
  6. curl::option(ch,"URL","http://127.0.0.1:8080/mtsb/mtgtk.sb")
  7. curl::perform(ch)
  8.  
  9. curl::option(ch,"NOBODY")
  10. curl::option(ch,"URL","http://127.0.0.1:8080/mtsb/mtgtk.sb")
  11. curl::perform(ch)
  12.  
  13. curl::finish(ch)
  14.  

Code: Text
  1. PRINT "Status: 200\nContent-Type: text/html\n\n"
  2.  
  3. DECLARE SUB DLL ALIAS "_idll" LIB "gtk-server"
  4. DECLARE SUB DEFINE ALIAS "_idll_define" LIB "gtk-server"
  5.  
  6. DEFINE "gtk_init NONE NONE 2 NULL NULL"
  7. DEFINE "gtk_window_new delete-event WIDGET 1 INT"
  8. DEFINE "gtk_window_set_title NONE NONE 2 WIDGET STRING"
  9. DEFINE "gtk_table_new NONE WIDGET 3 INT INT BOOL"
  10. DEFINE "gtk_container_add NONE NONE 2 WIDGET WIDGET"
  11. DEFINE "gtk_button_new_with_label clicked WIDGET 1 STRING"
  12. DEFINE "gtk_table_attach_defaults NONE NONE 6 WIDGET WIDGET INT INT INT INT"
  13. DEFINE "gtk_widget_show_all NONE NONE 1 WIDGET"
  14. DEFINE "gtk_server_callback NONE STRING 1 STRING"
  15. DEFINE "gtk_widget_destroy NONE NONE 1 WIDGET"
  16. DEFINE "g_thread_init NONE NONE 1 NULL"
  17. DEFINE "gdk_threads_init NONE NONE 0"
  18. DEFINE "gdk_threads_enter NONE NONE 0"
  19. DEFINE "gdk_threads_leave NONE NONE 0"
  20.  
  21. DLL("g_thread_init NULL")
  22. DLL("gdk_threads_init")
  23. DLL("gdk_threads_enter")
  24. DLL("gtk_init NULL NULL")
  25. win = DLL("gtk_window_new 0")
  26. DLL("gtk_window_set_title " & win & " \"SB Gtk\"")
  27. tbl = DLL("gtk_table_new 10 10 1")
  28. DLL("gtk_container_add " & win & " " & tbl)
  29. but = DLL("gtk_button_new_with_label \"Quit\"")
  30. DLL("gtk_table_attach_defaults " & tbl & " " & but & " 5 9 5 9")
  31. DLL("gtk_widget_show_all " & win)
  32.  
  33. REPEAT
  34.   event = DLL("gtk_server_callback WAIT")
  35. UNTIL event = win OR event = but
  36.  
  37. DLL("gtk_widget_destroy " & win)
  38. DLL("gtk_server_callback 1")
  39. DLL("gdk_threads_leave")
  40.  
  41. END
  42.  

Both Gtk windows are independent of each other but can share common variables (read/write lockable) provided by the MT module.

Note: The threading support will be incorporated into a new forked version of GTK-Server that is ScriptBasic extension module specific and static linked in the upcoming mtsb.so extension module. (API scripting and SB embedding in a common module)

618
General Discussions / Re: email through sb?
« on: January 02, 2011, 10:05:06 AM »
Welcome nime to the ScriptBasic forum / open source project.

I use Linux mutt as a e-mail client to send e-mail as a SYSTEM command from SB. Automation of e-mail delivery under Windows is something I have no experience with. I have a client that uses a 3rd party standalone mass mailing package. (which there are many) Have you considered using a web based service which would allow you to use ScriptBasic on any platform to interface with it?

The cURL extension module is great for HTTP and FTP protocols. I spent an hour or so researching how to use cURL for e-mail and gave up after multiple dead ends.

619
General Discussions / Re: MTSB
« on: January 01, 2011, 02:56:59 AM »
Here is an example of ScriptBasic embeding itself in a thread of itself.

Code: Text
  1. INCLUDE curl.bas
  2.  
  3. ch = curl::init()
  4.  
  5. curl::option(ch,"URL","http://127.0.0.1:8080/mtsb/threadembed.sb")
  6. txt = curl::perform(ch)
  7. PRINT txt
  8.  
  9. curl::finish(ch)
  10.  

Code: Text
  1. PRINT "Status: 200\nContent-Type: text/html\n\n"
  2.  
  3. DECLARE SUB DLL ALIAS "_idll" LIB "iDLL-Server"
  4. DECLARE SUB DEFINE ALIAS "_idll_define" LIB "iDLL-Server"
  5. DECLARE SUB REQUIRE ALIAS "_idll_require" LIB "iDLL-Server"
  6.  
  7. REQUIRE "libiDLL.so"
  8. DEFINE "sb_new NONE POINTER 0"
  9. DEFINE "scriba_LoadConfiguration NONE INT 2 POINTER STRING"
  10. DEFINE "scriba_SetFileName NONE INT 2 POINTER STRING"
  11. DEFINE "scriba_Run NONE INT 2 POINTER STRING"
  12. DEFINE "scriba_LoadSourceProgram NONE INT 1 POINTER"
  13. DEFINE "scriba_destroy NONE NONE 1 POINTER"
  14.  
  15. pProgram = DLL("sb_new")
  16. DLL("scriba_LoadConfiguration " & pProgram & " \"/etc/scriba/basic.conf\"")
  17. DLL("scriba_SetFileName " & pProgram & " \"/home/jrs/SB/mtsb/E01.bas\"")
  18. DLL("scriba_LoadSourceProgram " & pProgram)
  19. DLL("scriba_Run " & pProgram & " \"JRS\"")
  20. DLL("scriba_destroy " & pProgram)
  21.  

Code: Text
  1. cmd = COMMAND()
  2.  
  3. PRINT "ARG = ",cmd,"\n"
  4.  
  5. FOR x = 1 TO 10
  6.   PRINT x,"\n"
  7. NEXT
  8.  

root@Laptop:~# ARG = JRS
1
2
3
4
5
6
7
8
9
10

root@Laptop:~#

The only strange thing is that the output of the embedded scriba went to the root console I started sbhttpd in and didn't get returned in the cURL response as I would have expected. It's still cool to see ScriptBasic create an instance of itself in a thread of itself. I think this proves the embedding ScriptBasic in your application is painless and non-intrusive.

Update

Actually the program did exactly what it was suppose to do. When you embed ScriptBasic (in sbhttpd in this case) it uses the stdin/out of the host as a default unless you redefine it with a SB API call.


620
What's New / Re: ScriptBasic 3.0 Open Items
« on: December 31, 2010, 12:06:49 PM »
Quote from: Tom
My vote is to create the new RAD() function.

+1


621
General Discussions / Re: MTSB
« on: December 29, 2010, 06:12:23 PM »
Here is an example of running the Bible word count code challenge on the sbhttpd server as side by side threads and returning immediately to my main testfaith.sb program to continue on with local processing.

I have been trying to solve an issue of the server releasing control back to the client and continue running on the server in it's own thread. Peter Verhas suggested I try closing channel zero on the server in my script but SB complained saying 1-512 are the only valid channels numbers. Not willing to give up easy, something I read in the SB docs on CGI methods gave me a clue that I might be able to do a HEAD request and return back to the client leaving the script to continue running till it sees an END.

Success!

testfaith.sb
Code: [Select]
INCLUDE curl.bas

ch = curl::init()

'Start 1st thread
curl::option(ch,"NOBODY")
curl::option(ch,"URL","http://127.0.0.1:8080/mtsb/faith.cgi")
txt = curl::perform(ch)

'Start 2nd thread
curl::option(ch,"NOBODY")
curl::option(ch,"URL","http://127.0.0.1:8080/mtsb/faith2.cgi")
txt = curl::perform(ch)

curl::finish(ch)


faith.cgi
Code: [Select]
INCLUDE cgi.bas

option cgi$Method cgi::Get or cgi::Upload or cgi::Head

cgi::Header(200, "text/html")
cgi::FinishHeader()

fname = "/home/jrs/SB/test/Bible.txt"

start_time = NOW
fsize = FILELEN(fname)
OPEN fname FOR INPUT AS #1
text = INPUT(fsize, #1)
CLOSE #1

strip = "()[]{}|<>/@0123456789*.,;:!#?%$&+=_~\"\\" & CHR(9) & CHR(10) & CHR(13)
FOR i = 1 TO LEN(strip)
  text = REPLACE(text, MID(strip, i, 1), " ")
NEXT i

SPLITA text BY " " TO word_list

OPEN "/home/jrs/SB/test/wc.raw" FOR OUTPUT AS #1
FOR x = 0 TO UBOUND(word_list)
  text_out = TRIM(word_list[x])
  IF LEN(text_out) THEN PRINT #1,LCASE(text_out),"\n"
NEXT x

CLOSE #1

ok = EXECUTE("sort /home/jrs/SB/test/wc.raw -o /home/jrs/SB/test/wc.srt", -1, PID)
OPEN "/home/jrs/SB/test/wc.srt" FOR INPUT AS #2
OPEN "/home/jrs/SB/test/wc.lst" FOR OUTPUT AS #3


last_word = ""
word_count = 0
word_total = 0

Next_Word:

IF EOF(2) THEN GOTO Done
LINE INPUT #2, this_word
this_word = CHOMP(this_word)
word_total += 1
IF last_word = "" THEN last_word = this_word
IF this_word = last_word THEN
  word_count += 1
  GOTO Next_Word
END IF

PRINT #3, last_word & " (" & word_count & ")\n"
last_word = this_word
word_count = 1
GOTO Next_Word  

Done:
PRINTNL #3
PRINT #3, word_total - 1, " words in ", NOW - start_time, " seconds.\n"
CLOSE #2
CLOSE #3

END

Note: faith2.cgi is the same as faith.cgi except I added a 2 to the end of each wc*.xxx work file name. I could have passed a thread count ID but this was only a two thread test so I was lazy.

Results:

Bible - Bible in text format. (4.2 MB)

Word List - All words in the Bible, sorted and the number of times they are used. (what this program does - should work with any text file)

wc.sb - original word count SB program I started from the command line with scriba.  
804895 words in 56 seconds.

faith.cgi - running as a single thread task
804895 words in 56 seconds.

faith.cgi - running along side faith2.cgi
804895 words in 121 seconds.

faith2.cgi - running along side faith.cgi
804895 words in 122 seconds.

As this was going on my testfaith.sb program returned back immediately after starting the program. (could have continued on doing something else or initiating new scripts)

622
General Discussions / Re: MTSB
« on: December 29, 2010, 12:12:52 PM »
I webified one of the old All Basic code challenge projects that is based on Gtk and MySQL as the DB. The real benefit as I see it comes to light when you start running detached updates and reports on the server in a multi-threaded task.


csgtkcustomer.sb
Code: [Select]
' All Basic address book challenge - 9/15/2008
'
' Basic Language: ScriptBasic 2.1 (Windows / Linux)
'
' Authors: Peter van Eerten - www.gtk-server.org
'          John Spikowski - www.scriptbasic.org

' GTK-server extension module
INCLUDE gtk.bas

' cURL extension module
INCLUDE curl.bas

GLOBAL CONST TAB = "\t"
GLOBAL CONST NL = "\n"

ch = curl::init()

SUB Fill_Data

' clear the list
gtk_list_store_clear(List_Store)

curl::option(ch,"URL","http://127.0.0.1:8080/mtsb/gtkdbweb.sb")
curl::option(ch,"COOKIEJAR","/home/jrs/SB/test/cookie.txt")
db_response = curl::perform(ch)

WHILE LEN(db_response)
  eor = INSTR(db_response,NL)
  this_row = LEFT(db_response, eor - 1)
  SPLIT this_row BY TAB TO dbrow{"cust_id"},dbrow{"cust_name"},dbrow{"cust_addr"},dbrow{"cust_city"},dbrow{"cust_state"},dbrow{"cust_zip"},dbrow{"cust_phone"}
  gtk_list_store_append(List_Store, List_Iter)
  gtk_list_store_set(List_Store, List_Iter, 0, dbrow{"cust_id"}, -1)
  gtk_list_store_set(List_Store, List_Iter, 1, dbrow{"cust_name"}, -1)
  gtk_list_store_set(List_Store, List_Iter, 2, dbrow{"cust_addr"}, -1)
  gtk_list_store_set(List_Store, List_Iter, 3, dbrow{"cust_city"}, -1)
  gtk_list_store_set(List_Store, List_Iter, 4, dbrow{"cust_state"}, -1)
  gtk_list_store_set(List_Store, List_Iter, 5, dbrow{"cust_zip"}, -1)
  gtk_list_store_set(List_Store, List_Iter, 6, dbrow{"cust_phone"}, -1)
  db_response = MID(db_response, eor + 1)
WEND

END SUB

SUB Add_Edit_Data

' determine which mode we are
IF Add_Edit_Mode = 1 THEN
    gtk_list_store_append(List_Store, List_Iter)
END IF

' Get the etries, currently no checking
info[0] = gtk_entry_get_text(EntryID)
info[1] = gtk_entry_get_text(EntryName)
info[2] = gtk_entry_get_text(EntryAddress)
info[3] = gtk_entry_get_text(EntryCity)
info[4] = gtk_entry_get_text(EntryState)
info[5] = gtk_entry_get_text(EntryZip)
info[6] = gtk_entry_get_text(EntryPhone)

' Add mode, store the info into the list widget
FOR i = 0 TO 6
    gtk_list_store_set(List_Store, List_Iter, i, info[i], -1)
NEXT i

' Delete the entries
gtk_editable_delete_text(EntryID, 0, -1)
gtk_editable_delete_text(EntryName, 0, -1)
gtk_editable_delete_text(EntryAddress, 0, -1)
gtk_editable_delete_text(EntryCity, 0, -1)
gtk_editable_delete_text(EntryState, 0, -1)
gtk_editable_delete_text(EntryZip, 0, -1)
gtk_editable_delete_text(EntryPhone, 0, -1)

post_str = "cust_id=" & curl::escape(info[0]) & "&cust_name=" & curl::escape(info[1]) & "&cust_addr=" & curl::escape(info[2]) & "&cust_city=" & curl::escape(info[3]) & "&cust_state=" & curl::escape(info[4]) & "&cust_zip=" & curl::escape(info[5]) & "&cust_phone=" & curl::escape(info[6]) & "&maint_flag=" & curl::escape(Add_Edit_Mode)

curl::option(ch,"URL","http://127.0.0.1:8080/mtsb/gtkdbweb.sb")
curl::option(ch,"COOKIE","webcust")
curl::option(ch,"POST")
curl::option(ch,"POSTFIELDS",post_str)
txt = curl::perform(ch)

END SUB

SUB Del_Data

' Check if a row is selected
IF gtk_tree_selection_get_selected(Tree_Sel, "NULL", List_Iter) = "1" THEN
   gtk_list_store_remove(List_Store, List_Iter)
   post_str = "cust_id=" & curl::escape(info[0]) & "&maint_flag=" & "3"
   curl::option(ch,"URL","http://127.0.0.1:8080/mtsb/gtkdbweb.sb")
   curl::option(ch,"COOKIE","webcust")
   curl::option(ch,"POST")
   curl::option(ch,"POSTFIELDS",post_str)
   txt = curl::perform(ch)
ELSE
    gtk_widget_show_all(Error_Msg)
END IF

END SUB

' MAIN program

' Optionally enable GTK logging
gtk_server_cfg("-log=log.txt")

' Get GLADE definition
xml = glade_xml_new("form.glade")
glade_xml_signal_autoconnect(xml)

' Get main window ID and connect signal
Main_Window = glade_xml_get_widget(xml, "Main_Window")
gtk_server_connect(Main_Window, "delete-event", "Main_Window")

' Get button IDs and connect signals
Add_Button = glade_xml_get_widget(xml, "Add_Button")
gtk_server_connect(Add_Button, "clicked", "Add_Button")
Del_Button = glade_xml_get_widget(xml, "Del_Button")
gtk_server_connect(Del_Button, "clicked", "Del_Button")
Edit_Button = glade_xml_get_widget(xml, "Edit_Button")
gtk_server_connect(Edit_Button, "clicked", "Edit_Button")
Exit_Button = glade_xml_get_widget(xml, "Exit_Button")
gtk_server_connect(Exit_Button, "clicked", "Exit_Button")

' Get scrolled window
Scrolled_Window =  glade_xml_get_widget(xml, "Scrolled_Window")

' Define the list
List_Iter = gtk_server_opaque()
GTK::gtk("gtk_server_redefine gtk_list_store_new NONE WIDGET 8 INT INT INT INT INT INT INT INT")
List_Store = GTK::gtk("gtk_list_store_new 7 64 64 64 64 64 64 64")
List_Choice = gtk_tree_view_new_with_model(List_Store)
GTK::gtk("gtk_server_connect " & List_Choice & " button-press-event " & List_Choice & " 1")
gtk_tree_view_set_headers_visible(List_Choice, 1)
gtk_tree_view_set_headers_clickable(List_Choice, 1)
gtk_tree_view_set_grid_lines(List_Choice, 3)
gtk_tree_sortable_set_sort_column_id(List_Store, 0, 0)
Tree_Sel = gtk_tree_view_get_selection(List_Choice)
gtk_tree_selection_set_mode(Tree_Sel, 2)
Txt_Cell = gtk_cell_renderer_text_new()
List_Column0 = gtk_tree_view_column_new_with_attributes("ID", Txt_Cell, "text", 0, "NULL")
gtk_tree_view_append_column(List_Choice, List_Column0)
gtk_tree_view_column_set_resizable(List_Column0, 1)
gtk_tree_view_column_set_clickable(List_Column0, 1)
List_Column1 = gtk_tree_view_column_new_with_attributes("Name", Txt_Cell, "text", 1, "NULL")
gtk_tree_view_append_column(List_Choice, List_Column1)
gtk_tree_view_column_set_resizable(List_Column1, 1)
List_Column2 = gtk_tree_view_column_new_with_attributes("Address", Txt_Cell, "text", 2, "NULL")
gtk_tree_view_append_column(List_Choice, List_Column2)
gtk_tree_view_column_set_resizable(List_Column2, 1)
List_Column3 = gtk_tree_view_column_new_with_attributes("City", Txt_Cell, "text", 3, "NULL")
gtk_tree_view_append_column(List_Choice, List_Column3)
gtk_tree_view_column_set_resizable(List_Column3, 1)
List_Column4 = gtk_tree_view_column_new_with_attributes("State", Txt_Cell, "text", 4, "NULL")
gtk_tree_view_append_column(List_Choice, List_Column4)
gtk_tree_view_column_set_resizable(List_Column4, 1)
List_Column5 = gtk_tree_view_column_new_with_attributes("ZIP", Txt_Cell, "text", 5, "NULL")
gtk_tree_view_append_column(List_Choice, List_Column5)
gtk_tree_view_column_set_resizable(List_Column5, 1)
List_Column6 = gtk_tree_view_column_new_with_attributes("Phone", Txt_Cell, "text", 6, "NULL")
gtk_tree_view_append_column(List_Choice, List_Column6)
gtk_tree_view_column_set_resizable(List_Column6, 1)
gtk_container_add(Scrolled_Window, List_Choice)
gtk_widget_show_all(Scrolled_Window)

' Add entry window
Entry_Field = glade_xml_get_widget(xml, "Entry_Field")
gtk_server_connect(Entry_Field, "delete-event", "Entry_Field")

' Get button ID and connect signal
Entry_Ok_Button = glade_xml_get_widget(xml, "Entry_Ok_Button")
gtk_server_connect(Entry_Ok_Button, "clicked", "Entry_Ok_Button")
Entry_Can_Button = glade_xml_get_widget(xml, "Entry_Can_Button")
gtk_server_connect(Entry_Can_Button, "clicked", "Entry_Can_Button")

' Get ID's for the textentries
EntryID = glade_xml_get_widget(xml, "EntryID")
EntryName = glade_xml_get_widget(xml, "EntryName")
EntryAddress = glade_xml_get_widget(xml, "EntryAddress")
EntryCity = glade_xml_get_widget(xml, "EntryCity")
EntryState = glade_xml_get_widget(xml, "EntryState")
EntryZip = glade_xml_get_widget(xml, "EntryZip")
EntryPhone = glade_xml_get_widget(xml, "EntryPhone")

' Warning dialog, define here because of a bug in Glade
Warning_Msg = gtk_message_dialog_new(Main_Window, 1, 1, 4, "\nAre you sure to delete this entry?", "''")
gtk_window_set_title(Warning_Msg, "Warning")
gtk_server_connect(Warning_Msg, "delete-event", "Warning_Msg")
gtk_server_connect(Warning_Msg, "response", "Warning_Msg_Response")

' Warning dialog, define here because of a bug in Glade
Error_Msg = gtk_message_dialog_new(Main_Window, 1, 3, 2, "\nSelect an entry first!", "''")
gtk_window_set_title(Error_Msg, "Error!")
gtk_server_connect(Error_Msg, "delete-event", "Error_Msg")

' Fill grid with data
CALL Fill_Data()

' Set sort flag
Sort_Flag = 0

' Set edit or add mode - 1=ADD, 2=EDIT
Add_Edit_Mode = 1

' Mainloop starts here
REPEAT

    ' Get event
    event = gtk_server_callback("wait")

    ' Add entry form
    IF event = "Add_Button" THEN
Add_Edit_Mode = 1
gtk_window_set_title(Entry_Field, "Add entry")
gtk_widget_show_all(Entry_Field)
gtk_widget_grab_focus(EntryID)
    END IF

    ' Edit entry form
    IF event = "Edit_Button" THEN
Add_Edit_Mode = 2
IF gtk_tree_selection_get_selected(Tree_Sel, "NULL", List_Iter) = "0" THEN
   gtk_widget_show_all(Error_Msg)
ELSE
   FOR i = 0 TO 6
info[i] = gtk_tree_model_get(List_Store, List_Iter, i, "''", -1)
   NEXT i

   ' Get the etries, currently no checking
   gtk_entry_set_text(EntryID, MID(info[0], 4))
   gtk_entry_set_text(EntryName, MID(info[1], 4))
   gtk_entry_set_text(EntryAddress, MID(info[2], 4))
   gtk_entry_set_text(EntryCity, MID(info[3], 4))
   gtk_entry_set_text(EntryState, MID(info[4], 4))
   gtk_entry_set_text(EntryZip, MID(info[5], 4))
   gtk_entry_set_text(EntryPhone, MID(info[6], 4))

   gtk_window_set_title(Entry_Field, "Edit entry")
   gtk_widget_show_all(Entry_Field)
   gtk_widget_grab_focus(EntryID)

END IF
    END IF

    ' These are the buttons on the entry form
    IF event = "Entry_Can_Button" OR event = "Entry_Field" THEN
gtk_widget_hide(Entry_Field)

' Delete the entries
gtk_editable_delete_text(EntryID, 0, -1)
gtk_editable_delete_text(EntryName, 0, -1)
gtk_editable_delete_text(EntryAddress, 0, -1)
gtk_editable_delete_text(EntryCity, 0, -1)
gtk_editable_delete_text(EntryState, 0, -1)
gtk_editable_delete_text(EntryZip, 0, -1)
gtk_editable_delete_text(EntryPhone, 0, -1)
    END IF
    IF event = "Entry_Ok_Button" THEN
CALL Add_Edit_Data()
    END IF

    ' Warning dialog
    IF event = "Del_Button" THEN
IF gtk_tree_selection_get_selected(Tree_Sel, "NULL", List_Iter) = "0" THEN
   gtk_widget_show_all(Error_Msg)
ELSE
   gtk_widget_show_all(Warning_Msg)
END IF
    END IF
    IF event = "Warning_Msg" THEN gtk_widget_hide(Warning_Msg)
    IF event = "Warning_Msg_Response" THEN
response = gtk_server_callback_value(1, "INT")
IF response = -8 THEN CALL Del_Data()
gtk_widget_hide(Warning_Msg)
    END IF

    ' Error dialog
    IF event = "Error_Msg" OR event = Error_Msg THEN gtk_widget_hide(Error_Msg)

    ' Sortable on key
    IF event = List_Column0 THEN
Sort_Flag = 1 - Sort_Flag
gtk_tree_sortable_set_sort_column_id(List_Store, 0, Sort_Flag)
    END IF

UNTIL event = "Main_Window" OR event = "Exit_Button"

' Cleanup resources
gtk_server_exit()
curl::finish(ch)

gtkdbweb.sb
Code: [Select]
' Program: gtkdbweb.sb
' Version: 1.0
'    Date: 2010-12-27
'      By: JRS

INCLUDE cgi.bas
INCLUDE mt.bas
INCLUDE mysql.bas

CONST TAB = "\t"
CONST NL = "\n"

dbh = mysql::RealConnect("localhost","root","xxxx","sbtest")

OPTION cgi$Method cgi::GET or cgi::POST

session_id = cgi::Cookie("webcust")

New_Session:

IF session_id = undef THEN
  session_id = mt::NewSessionId()
  mt::SetSessionId(session_id)
ELSE
  IF mt::CheckSessionId(session_id) = False THEN
    session_id = undef
    GOTO New_Session
  END IF
  mt::SetSessionId(session_id)
END IF

IF cgi::RequestMethod() = "POST" THEN GOTO Maintenance

mysql::query(dbh,"SELECT * FROM customer")

cgi::Header(200, "text/html")
cgi::SetCookie("webcust", session_id)
cgi::FinishHeader()

WHILE mysql::FetchHash(dbh, dbrow)
  PRINT dbrow{"cust_id"} & TAB & dbrow{"cust_name"} & TAB & dbrow{"cust_addr"} & TAB & dbrow{"cust_city"} & TAB & dbrow{"cust_state"} & TAB & dbrow{"cust_zip"} & TAB & dbrow{"cust_phone"} & NL
WEND

mysql::Close(dbh)
END

Maintenance:

cust_id = cgi::PostParam("cust_id")
cust_name = cgi::PostParam("cust_name")
cust_addr = cgi::PostParam("cust_addr")
cust_city = cgi::PostParam("cust_city")
cust_state = cgi::PostParam("cust_state")
cust_zip = cgi::PostParam("cust_zip")
cust_phone = cgi::PostParam("cust_phone")
maint_flag = cgi::PostParam("maint_flag")

IF maint_flag = "1" THEN SQL = "INSERT INTO customer (cust_id, cust_name, cust_addr, cust_city, cust_state, cust_zip, cust_phone) VALUES ('" & cust_id & "', '" & cust_name & "', '" & cust_addr & "', '" & cust_city & "', '" & cust_state & "', '" & cust_zip & "', '" & cust_phone & "')"
IF maint_flag = "2" THEN SQL = "UPDATE customer SET cust_id = '" & cust_id & "', cust_name = '" & cust_name & "', cust_addr = '" & cust_addr & "', cust_city = '" & cust_city & "', cust_state = '" & cust_state & "', cust_zip = '" & cust_zip & "', cust_phone = '" & cust_phone & "'"
IF maint_flag = "3" THEN SQL = "DELETE FROM customer WHERE cust_id = " & cust_id
    
mysql::query(dbh, SQL)

cgi::Header(200, "text/html")
cgi::SetCookie("webcust", session_id)
cgi::FinishHeader()

mysql::Close(dbh)
END

623
General Discussions / Re: MTSB
« on: December 29, 2010, 12:04:28 PM »
I thought I would start off with the browser (HTML) version first to show how the flow of a CGI client/server application might look. Keep in mind there is no formating (CSS) or validation to keep this simple and easy to read.

webcustomer.sb
Code: [Select]
' Program: webcustomer.sb
' Version: 1.0
'    Date: 2010-12-27
'      By: JRS

INCLUDE cgi.bas
INCLUDE mt.bas
INCLUDE mysql.bas

dbh = mysql::RealConnect("localhost","root","xxx","sbtest")

OPTION cgi$Method cgi::GET or cgi::POST

session_id = cgi::Cookie("webcust")

New_Session:

IF session_id = undef THEN
  session_id = mt::NewSessionId()
  mt::SetSessionId(session_id)
ELSE
  IF mt::CheckSessionId(session_id) = False THEN
    session_id = undef
    GOTO New_Session
  END IF
  mt::SetSessionId(session_id)
END IF

IF cgi::RequestMethod() = "GET" THEN GOTO Enter_Customer
cust_id = cgi::PostParam("cust_id")
cust_name = cgi::PostParam("cust_name")
cust_addr = cgi::PostParam("cust_addr")
cust_city = cgi::PostParam("cust_city")
cust_state = cgi::PostParam("cust_state")
cust_zip = cgi::PostParam("cust_zip")
cust_phone = cgi::PostParam("cust_phone")

SQL = "INSERT INTO customer (cust_id, cust_name, cust_addr, cust_city, cust_state, cust_zip, cust_phone) VALUES ('" & cust_id & "', '" & cust_name & "', '" & cust_addr & "', '" & cust_city & "', '" & cust_state & "', '" & cust_zip & "', '" & cust_phone & "')"  
mysql::query(dbh, SQL)

SQL = "SELECT * FROM customer"
mysql::query(dbh, SQL)

cgi::Header(200, "text/html")
cgi::SetCookie("webcust", session_id)
cgi::FinishHeader()
PRINT """
<html>
<head>
<title>Customer Master File list</title>
</head>
<body>
<table border="1">
  <tr>
    <th>ID</th>
    <th>Name</th>
    <th>Address</th>
    <th>City</th>
    <th>State</th>
    <th>Zip</th>
    <th>Phone</th>
  </tr>
"""
WHILE mysql::FetchHash(dbh, dbcol)
  PRINT """
  <tr>
    <td>""" & dbcol{"cust_id"} & """</td>
    <td>""" & dbcol{"cust_name"} & """</td>
    <td>""" & dbcol{"cust_addr"} & """</td>
    <td>""" & dbcol{"cust_city"} & """</td>
    <td>""" & dbcol{"cust_state"} & """</td>
    <td>""" & dbcol{"cust_zip"} & """</td>
    <td>""" & dbcol{"cust_phone"} & """</td>
  </tr>
"""
WEND
PRINT """
  <tr>
    <td colspan=7 align="left"><br><input type="button" value="Add New Customer" onClick="parent.location='/mtsb/webcustomer.sb'"></td>
  </tr>
</table>
</body>
</html>
"""
END

Enter_Customer:

cgi::Header(200, "text/html")
cgi::SetCookie("webcust", session_id)
cgi::FinishHeader()

PRINT """
<html>
<head>
<title>Customer Master File Maintenance</title>
</head>
<body>
<form name="custform" method="POST" action="/mtsb/webcustomer.sb">
<table border="0">
  <tr>
    <td align="right">ID</td>
    <td><input type="text" name="cust_id" size="5"></td>
  </tr>
  <tr>
    <td align="right">Name</td>
    <td><input type="text" name="cust_name" size="30"></td>
  </tr>
  <tr>
    <td align="right">Address</td>
    <td><input type="text" name="cust_addr" size="30"></td>
   </tr>
  <tr>
    <td align="right">City</td>
    <td><input type="text" name="cust_city" size="20"></td>
  </tr>
  <tr>
    <td align="right">State</td>
    <td><input type="text" name="cust_state" size="5"></td>
  </tr>
  <tr>
    <td align="right">Zip</td>
    <td><input type="text" name="cust_zip" size="5"></td>
  </tr>
  <tr>
    <td align="right">Phone</td>
    <td><input type="text" name="cust_phone" size="20"></td>
  </tr>
  <tr>
    <td colspan=2 align="center"><br><input type="submit" value="Add Customer"></td>
  </tr>
</table>
</form>
</body>
</html>
"""

MySQL - customer table
Code: [Select]
CREATE TABLE `sbtest`.`customer` (
`cust_id` VARCHAR( 5 ) NOT NULL ,
`cust_name` VARCHAR( 30 ) NULL ,
`cust_addr` VARCHAR( 30 ) NULL ,
`cust_city` VARCHAR( 20 ) NULL ,
`cust_state` VARCHAR( 5 ) NULL ,
`cust_zip` VARCHAR( 5 ) NULL ,
`cust_phone` VARCHAR( 20 ) NULL ,
PRIMARY KEY ( `cust_id` )
) ENGINE = MYISAM ;

624
General Discussions / MTSB
« on: December 29, 2010, 12:02:57 PM »
ScriptBasic provides in it's distribution a variation of the language called sbhttpd. This example use of ScriptBasic shows how to assemble a multi-threaded webserver with in-memory session support and running as a service/daemon. I have used the sbhttpd server as a proxy behind Apache for years for my web based applications. I thought I would expand on the concept and include desktop applications to the CGI client/server realm. This concept can be used with any server side scripting language and a client with cURL like functionality.

The following posts were from the All Basic site I'm migrating here.

625
Download / Re: ScriptBasic 2.1 Linux
« on: December 26, 2010, 12:28:14 PM »
Tom,

ScriptBasic 2.1 is the current distribution on all platforms. The 3.0 goal (started on Windows) was a 32/64 bit MinGW-gcc project that died shortly after getting started. (Armando migrated back to his BCX MBC translator project as his pet project.)  My time is being spent on the Linux environment and I could use your help putting together a distribution we all can be proud of.

John

626
GTK-Server / Re: IDLL
« on: December 19, 2010, 04:04:01 PM »
You can embed a script without having to run it using the scriba_NoRun call. You're able to call functions/subs and access/set global variables. (embeddable function library)

iembed
Code: [Select]
' ScriptBasic self embedding demo

INCLUDE "iembed.sbh"

pProgram = DLL("sb_new")
_DLL "scriba_LoadConfiguration", pProgram, "/etc/scriba/basic.conf"
_DLL "scriba_SetFileName", pProgram, "E02.sb"
_DLL "scriba_LoadSourceProgram", pProgram
_DLL "scriba_NoRun", pProgram
   v = _DLL("scriba_LookupVariableByName", pProgram, "main::a")
_DLL "scriba_SetVariable", pProgram, v, SBT_LONG, 500
   f = _DLL("scriba_LookupFunctionByName", pProgram, "main::vprint")
_DLL "scriba_Call", pProgram, f
_DLL "scriba_destroy", pProgram

E02.sb
Code: [Select]
SUB vprint
  PRINT "Variable 'a' = ",a,"\n"
END SUB

a = 0

jrs@Laptop:~/SB/test$ scriba iembed
Variable 'a' = 500
jrs@Laptop:~/SB/test$

iembed.sbh
Code: [Select]
DECLARE SUB DLL ALIAS "_idll" LIB "iDLL-Server"
DECLARE SUB REQUIRE ALIAS "_idll_require" LIB "iDLL-Server"
DECLARE SUB DEFINE ALIAS "_idll_define" LIB "iDLL-Server"

REQUIRE "libiDLL.so"

DEFINE "sb_new NONE POINTER 0"
DEFINE "scriba_LoadConfiguration NONE INT 2 POINTER STRING"
DEFINE "scriba_SetFileName NONE INT 2 POINTER STRING"
DEFINE "scriba_LoadSourceProgram NONE INT 1 POINTER"
DEFINE "scriba_Run NONE INT 2 POINTER STRING"
DEFINE "scriba_NoRun NONE INT 1 POINTER"
DEFINE "scriba_LookupVariableByName NONE LONG 2 POINTER STRING"
DEFINE "scriba_SetVariable NONE INT 4 POINTER LONG INT LONG"
DEFINE "scriba_LookupFunctionByName NONE LONG 2 POINTER STRING"
DEFINE "scriba_Call NONE INT 2 POINTER LONG"
DEFINE "scriba_destroy NONE NONE 1 POINTER"

CONST SBT_LONG = 2

FUNCTION _DLL(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)
LOCAL arg_str
  arg_str = STR(a0) & " " & STR(a1) & " " & STR(a2) & " " & STR(a3) & " " & STR(a4) & " " & STR(a5) & " " & STR(a6) & " " & STR(a7) & " " & STR(a8) & " " & STR(a9)
  _DLL = DLL(arg_str)
END FUNCTION

627
GTK-Server / Re: IDLL
« on: December 18, 2010, 11:22:27 PM »
Here is an example of ScriptBasic being embedded in itself.

Code: [Select]
DECLARE SUB DLL ALIAS "_gtk" LIB "gtk-server"

DLL("gtk_server_require libiDLL.so")

DLL("gtk_server_define sb_new NONE POINTER 0")
DLL("gtk_server_define scriba_LoadConfiguration NONE INT 2 POINTER STRING")
DLL("gtk_server_define scriba_SetFileName NONE INT 2 POINTER STRING")
DLL("gtk_server_define scriba_Run NONE INT 2 POINTER STRING")
DLL("gtk_server_define scriba_LoadSourceProgram NONE INT 1 POINTER")
DLL("gtk_server_define scriba_destroy NONE NONE 1 POINTER")

pProgram = DLL("sb_new")
DLL("scriba_LoadConfiguration " & pProgram & " \"/etc/scriba/basic.conf\"")
DLL("scriba_SetFileName " & pProgram & " \"E01.bas\"")
DLL("scriba_LoadSourceProgram " & pProgram)
DLL("scriba_Run " & pProgram & " \"JRS\"")
DLL("scriba_destroy " & pProgram)

Code: Text
  1. cmd = COMMAND()
  2.  
  3. PRINT "ARG = ",cmd,"\n"
  4.  
  5. FOR x = 1 TO 10
  6.   PRINT x,"\n"
  7. NEXT
  8.  


rs@Laptop:~/SB/test$ scriba embed.sb
ARG = JRS
1
2
3
4
5
6
7
8
9
10
jrs@Laptop:~/SB/test$

628
GTK-Server / API Scripting Helper Library
« on: December 16, 2010, 06:49:41 PM »
This is an ongoing project as GTK-Server definitions are created and tested under ScriptBasic.

Code: [Select]
' ScriptBasic API helper functions and declarations

' INTERFACE
DECLARE SUB DLL ALIAS "_gtk" LIB "gtk-server"
DECLARE SUB VARPTR ALIAS "varptr" LIB "gtk-server"

' Convert standard function calls to a space delimited command string
FUNCTION _DLL(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)
LOCAL arg_str
  arg_str = STR(a0) & " " & STR(a1) & " " & STR(a2) & " " & STR(a3) & " " & STR(a4) & " " & STR(a5) & " " & STR(a6) & " " & STR(a7) & " " & STR(a8) & " " & STR(a9)
  _DLL = DLL(arg_str)
END FUNCTION

' Returns a data pointer address of a variable or element in a structure as a text based numeric value that GTK-Server understands.
FUNCTION STRPTR(mem_addr)
LOCAL tmp_ptr
  tmp_ptr = 0
  DLL("strncpy " & VARPTR(tmp_ptr) & " " & mem_addr & " 4")
  STRPTR = tmp_ptr
END FUNCTION

' Returns a ScriptBasic string variable given the memory address in numeric text format of a null terminated string variable or element of a structure.
FUNCTION GETSTR(mem_addr)
LOCAL tmp_ptr
  tmp_ptr = 0
  DLL("strncpy " & VARPTR(tmp_ptr) & " " & mem_addr & " 4")
  tmp_ptr = DLL("strdup " & tmp_ptr)
  GETSTR = tmp_ptr
END FUNCTION

' Returns a string of data given the memory address of a data pointer and the length in bytes requested.
FUNCTION GETMEM(mem_addr, bytes)
LOCAL tmp_ptr, tmp_data
  tmp_ptr = 0
  DLL("strncpy " & VARPTR(tmp_ptr) & " " & mem_addr & " 4")
  tmp_data = 0
  tmp_data = DLL("strncpy " & VARPTR(tmp_data) & " " & tmp_ptr & " " & bytes)
  GETMEM = tmp_data
END FUNCTION

' Convert a string to a hex representation of it.
FUNCTION Str2Hex(str_arg)
  LOCAL str_len, pos, hex_str
  str_len = LEN(str_arg)
  IF str_len THEN
    FOR pos = 1 TO str_len
      hex_str &= RIGHT("0" & HEX(ASC(MID(str_arg, pos, 1))),2)
    NEXT
  ELSE
    hex_str = ""
  END IF
  Str2Hex = hex_str
END FUNCTION

629
GTK-Server / Re: IDLL
« on: December 15, 2010, 07:44:23 PM »
For those of you interested in the GNOME-DB solution and would like to use the interface in a console mode setting, gda-sql-4.0 is an easy to use tool to access multiple database providers (multiple connections in one session supported) from a common interface.

Code: [Select]
jrs@Laptop:~/gtk-server$ gda-sql-4.0 -L
          Installed providers list
Provider   │ Description                     
───────────┼──────────────────────────────────
SQLite     │ Provider for SQLite databases   
PostgreSQL │ Provider for PostgreSQL databases
SQLCipher  │ Provider for SQLCipher           
MySQL      │ Provider for MySQL databases     
(4 rows)
jrs@Laptop:~/gtk-server$


jrs@Laptop:~/gtk-server$ gda-sql-4.0 -l
                                                    List of defined data sources
DSN       │ Provider   │ Description                          │ Connection string                                          │ Username │ Global
──────────┼────────────┼──────────────────────────────────────┼────────────────────────────────────────────────────────────┼──────────┼───────
Planner   │ PostgreSQL │ GNOME Planner DB                     │ DB_NAME=plannerdb                                          │ jrs      │ FALSE
SalesTest │ SQLite     │ Test database for a sales department │ DB_DIR=/home/jrs/.local/share/libgda;DB_NAME=sales_test.db │          │ FALSE
SBMySQL   │ MySQL      │ SB testing DB                        │ DB_NAME=sbtest                                             │ root     │ FALSE
(3 rows)
jrs@Laptop:~/gtk-server$ gda-sql-4.0 --help
Usage:
  gda-sql-4.0 [OPTION...] [DSN|connection string]...

Help Options:
  -h, --help                        Show help options

Application Options:
  -v, --version                     Show version information and exit
  -o, --output-file=output file     Output file
  -C, --command=command             Run only single command (SQL or internal) and exit
  -f, --commands-file=filename      Execute commands from file, then exit (except if -i specified)
  -i, --interactive                 Keep the console opened after executing a file (-f option)
  -l, --list-dsn                    List configured data sources and exit
  -L, --list-providers              List installed database providers and exit

jrs@Laptop:~/gtk-server$ gda-sql-4.0 SalesTest
Welcome to the GDA SQL console, version 4.2.0

Type: .copyright to show usage and distribution terms
      .? for help with internal commands
      .q (or CTRL-D) to quit
      (the '.' can be replaced by a '\')
      or any query terminated by a semicolon

Opening connection 'SalesTest' for: SalesTest
All the meta data associated to the 'SalesTest' connection will be stored in the '/home/jrs/.local/share/libgda/gda-sql-SalesTest.db' file
SalesTest> select * from customers;
id │ name            │ default_served_by │ country │ city
───┼─────────────────┼───────────────────┼─────────┼─────
 2 │ Ed Lamton       │                 4 │ SP      │ MDR
 3 │ Lew Bonito      │                 1 │ FR      │ TLS
 4 │ Mark Lawrencep  │                   │ SP      │ MDR
 9 │ Greg Popoff     │                 2 │ SP      │ MDR
10 │ Vladimir Zirkov │                 4 │         │     
(5 rows)
SalesTest>

Here is a standalone, non-GUI (console mode) example using GDA.

Code: [Select]
' GNOME-DB console mode example

DECLARE SUB DLL ALIAS "_gtk" LIB "gtk-server"

DLL("gtk_server_require libgda-4.0.so")
DLL("gtk_server_define gda_init NONE NONE 0")
DLL("gtk_server_define gda_connection_open_from_string NONE WIDGET 4 STRING STRING NULL INT")
DLL("gtk_server_define gda_execute_select_command NONE WIDGET 2 WIDGET STRING")
DLL("gtk_server_define gda_data_model_dump NONE NONE 2 WIDGET NULL")
DLL("gtk_server_define g_object_unref NONE NONE 1 WIDGET")

DLL("gda_init")
cnc = DLL("gda_connection_open_from_string \"SQLite\" \"DB_DIR=/home/jrs/.local/share/libgda;DB_NAME=sales_test.db\" NULL 0")
data_model = DLL("gda_execute_select_command " & cnc & " \"SELECT * FROM customers\"")
DLL("gda_data_model_dump " & data_model & " NULL")
DLL("g_object_unref " & data_model)
DLL("g_object_unref " & cnc)

Results
Code: [Select]
jrs@Laptop:~/SB/test$ scriba db-con.sb
id │ name            │ default_served_by │ country │ city
───┼─────────────────┼───────────────────┼─────────┼─────
 2 │ Ed Lamton       │                 4 │ SP      │ MDR
 3 │ Lew Bonito      │                 1 │ FR      │ TLS
 4 │ Mark Lawrencep  │              NULL │ SP      │ MDR
 9 │ Greg Popoff     │                 2 │ SP      │ MDR
10 │ Vladimir Zirkov │                 4 │ NULL    │ NULL
(5 rows)
jrs@Laptop:~/SB/test$

GDA supports dumping to a XML file as an option as well as a comma delimited file. You can always access the table by row/column if you need that granularity.

Code: [Select]
' GNOME-DB console mode example

DECLARE SUB DLL ALIAS "_gtk" LIB "gtk-server"

DLL("gtk_server_require libgda-4.0.so")
DLL("gtk_server_define gda_init NONE NONE 0")
DLL("gtk_server_define gda_connection_open_from_string NONE WIDGET 4 STRING STRING NULL INT")
DLL("gtk_server_define gda_execute_select_command NONE WIDGET 2 WIDGET STRING")
DLL("gtk_server_define gda_data_model_export_to_file NONE BOOL 9 WIDGET INT STRING NULL INT NULL INT NULL NULL")
DLL("gtk_server_define g_object_unref NONE NONE 1 WIDGET")

DLL("gda_init")
cnc = DLL("gda_connection_open_from_string \"SQLite\" \"DB_DIR=/home/jrs/.local/share/libgda;DB_NAME=sales_test.db\" NULL 0")
data_model = DLL("gda_execute_select_command " & cnc & " \"SELECT * FROM customers\"")
DLL("gda_data_model_export_to_file " & data_model & " 0 \"SalesTest.xml\" NULL 0 NULL 0 NULL NULL")
DLL("g_object_unref " & data_model)
DLL("g_object_unref " & cnc)

Results

Code: [Select]
jrs@Laptop:~/SB/test$ ls -l SalesTest.xml
-rw-r--r-- 1 jrs jrs 1712 2010-12-15 19:06 SalesTest.xml
jrs@Laptop:~/SB/test$ cat SalesTest.xml
<?xml version="1.0"?>
<gda_array id="EXPORT" name="Exported Data">
  <gda_array_field id="FI0" name="id" title="id" dbms_type="integer" gdatype="int" nullok="TRUE"/>
  <gda_array_field id="FI1" name="name" title="name" dbms_type="string" gdatype="string" nullok="TRUE"/>
  <gda_array_field id="FI2" name="default_served_by" title="default_served_by" dbms_type="integer" gdatype="int" nullok="TRUE"/>
  <gda_array_field id="FI3" name="country" title="country" dbms_type="string" gdatype="string" nullok="TRUE"/>
  <gda_array_field id="FI4" name="city" title="city" dbms_type="string" gdatype="string" nullok="TRUE"/>
  <gda_array_data>
    <gda_array_row>
      <gda_value>2</gda_value>
      <gda_value>Ed Lamton</gda_value>
      <gda_value>4</gda_value>
      <gda_value>SP</gda_value>
      <gda_value>MDR</gda_value>
    </gda_array_row>
    <gda_array_row>
      <gda_value>3</gda_value>
      <gda_value>Lew Bonito</gda_value>
      <gda_value>1</gda_value>
      <gda_value>FR</gda_value>
      <gda_value>TLS</gda_value>
    </gda_array_row>
    <gda_array_row>
      <gda_value>4</gda_value>
      <gda_value>Mark Lawrencep</gda_value>
      <gda_value isnull="t"/>
      <gda_value>SP</gda_value>
      <gda_value>MDR</gda_value>
    </gda_array_row>
    <gda_array_row>
      <gda_value>9</gda_value>
      <gda_value>Greg Popoff</gda_value>
      <gda_value>2</gda_value>
      <gda_value>SP</gda_value>
      <gda_value>MDR</gda_value>
    </gda_array_row>
    <gda_array_row>
      <gda_value>10</gda_value>
      <gda_value>Vladimir Zirkov</gda_value>
      <gda_value>4</gda_value>
      <gda_value isnull="t"/>
      <gda_value isnull="t"/>
    </gda_array_row>
  </gda_array_data>
</gda_array>
jrs@Laptop:~/SB/test$

630
GTK-Server / IDLL
« on: December 12, 2010, 02:53:47 AM »
Here is a more challenging use of API scripting. This example shows the new VARPTR (language level addition) and STRPTR. (implemented at the script level with IDLL calls to low level API functions)  For those that like the more traditional function argument format, I added a _DLL function wrapper in the included .sbh file to allow this. (see second gda.sb example)

Here is the C code example that this code challenge was based on. (GNOME-DB project site)

Code: Text
  1. ' GNOME-DB GRID
  2.  
  3. ' INTERFACE
  4. DECLARE SUB DLL ALIAS "_gtk" LIB "gtk-server"
  5. DECLARE SUB VARPTR ALIAS "varptr" LIB "gtk-server"
  6.  
  7. ' GDA4
  8. DLL("gtk_server_require libgda-4.0.so")
  9. DLL("gtk_server_require libgda-ui-4.0.so")
  10.  
  11. ' DECLARE
  12. DLL("gtk_server_define gtk_init NONE NONE 2 NULL NULL")
  13. DLL("gtk_server_define gtk_dialog_new_with_buttons NONE WIDGET 8 STRING WIDGET INT STRING INT STRING INT NULL")
  14. DLL("gtk_server_define gdaui_login_new NONE WIDGET 1 STRING")
  15. DLL("gtk_server_define gtk_box_pack_start NONE NONE 5 WIDGET WIDGET BOOL BOOL INT")
  16. DLL("gtk_server_define gtk_dialog_get_content_area NONE WIDGET 1 WIDGET")
  17. DLL("gtk_server_define gtk_widget_show NONE NONE 1 WIDGET")
  18. DLL("gtk_server_define gtk_dialog_run delete-event INT 1 WIDGET")
  19. DLL("gtk_server_define gdaui_login_get_connection_information NONE WIDGET 1 WIDGET")
  20. ' Use the following format definition if you are passing actual strings not pointers to them.
  21. ' DLL("gtk_server_define gda_connection_open_from_string NONE WIDGET 5 STRING STRING POINTER INT NULL")
  22. DLL("gtk_server_define gda_connection_open_from_string NONE WIDGET 5 POINTER POINTER POINTER INT NULL")
  23. DLL("gtk_server_define gtk_widget_destroy NONE NONE 1 WIDGET")
  24. DLL("gtk_server_define gda_execute_select_command NONE WIDGET 3 WIDGET STRING NULL")
  25. DLL("gtk_server_define g_object_unref NONE NONE 1 WIDGET")
  26. DLL("gtk_server_define gtk_window_new delete-event WIDGET 1 INT")
  27. DLL("gtk_server_define gdaui_grid_new NONE WIDGET 1 WIDGET")
  28. DLL("gtk_server_define gtk_container_add NONE NONE 2 WIDGET WIDGET")
  29. DLL("gtk_server_define gtk_widget_show_all NONE NONE 1 WIDGET")
  30. DLL("gtk_server_define gtk_server_callback NONE STRING 1 STRING")
  31. DLL("gtk_server_define gtk_window_set_default_size NONE NONE 3 WIDGET INT INT")
  32. DLL("gtk_server_define gtk_window_set_title NONE NONE 2 WIDGET STRING")
  33. DLL("gtk_server_define strncpy NONE STRING 3 POINTER POINTER INT")
  34. DLL("gtk_server_define strdup NONE STRING 1 POINTER")
  35.  
  36.  
  37.  
  38. CONST GTK_STOCK_CANCEL = "gtk-cancel"
  39. CONST GTK_STOCK_OK = "gtk-ok"
  40. CONST GTK_RESPONSE_NONE = -1
  41. CONST GTK_RESPONSE_OK = -5
  42. CONST GDA_CONNECTION_OPTIONS_NONE = 0
  43. CONST GTK_WINDOW_TOPLEVEL = 0
  44. CONST GTK_DIALOG_MODAL = 1
  45. CONST provider = 4
  46. CONST cnc_string = 12
  47.  
  48.  
  49. FUNCTION _DLL(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  50. LOCAL arg_str
  51.   arg_str = STR(a0) & " " & STR(a1) & " " & STR(a2) & " " & STR(a3) & " " & STR(a4) & " " & STR(a5) & " " & STR(a6) & " " & STR(a7) & " " & STR(a8) & " " & STR(a9)
  52.   _DLL = DLL(arg_str)
  53. END FUNCTION
  54.  
  55.  
  56. FUNCTION STRPTR(pointer)
  57. LOCAL info_str
  58.  
  59. info_str = 0
  60. DLL("strncpy " & VARPTR(info_str) & " " & pointer & " 4")
  61. ' Enabling the next line of code will return the actual string in info_str and not just the pointer to it.
  62. ' info_str = DLL("strdup " & info_str)
  63. STRPTR = info_str
  64.  
  65. END FUNCTION
  66.  
  67.  
  68. SUB gtk_main
  69. LOCAL event
  70.  
  71. REPEAT
  72.   event = DLL("gtk_server_callback wait")
  73. UNTIL event = window
  74.  
  75. END SUB
  76.  


Code: Text
  1. ' GNOME-DB GRID
  2.  
  3. INCLUDE "db-grid.sbh"
  4.  
  5. DLL("gtk_init 0 0")
  6. DLL("gdaui_init")
  7.  
  8. ' DB Control Window
  9. window = DLL("gtk_dialog_new_with_buttons \"Select the Data Source to connect to\" 0 " & GTK_DIALOG_MODAL & " " & GTK_STOCK_CANCEL & " " & GTK_RESPONSE_NONE & " " & GTK_STOCK_OK & " " & GTK_RESPONSE_OK & " 0")
  10. login = DLL("gdaui_login_new NULL")
  11. DLL("gtk_box_pack_start " & DLL("gtk_dialog_get_content_area " & window) & " " &  login & " TRUE TRUE 0")
  12. DLL("gtk_widget_show " & login)
  13. IF DLL("gtk_dialog_run " & window) <> GTK_RESPONSE_OK THEN
  14.   PRINT "Cancelled!\n"
  15.   END
  16. END IF
  17. dsninfo = DLL("gdaui_login_get_connection_information " & login)
  18. cnc = DLL("gda_connection_open_from_string " & STRPTR(dsninfo + provider) & " " & STRPTR(dsninfo + cnc_string) & " " & " 0 0 0")
  19. data_model = DLL("gda_execute_select_command " & cnc & " \"SELECT * FROM customers\" 0")
  20. DLL("gtk_widget_destroy " & window)
  21.  
  22. ' DB Data Grid
  23. window = DLL("gtk_window_new 0")
  24. DLL("gtk_window_set_title " & window & " \"GNOME-DB Grid Control Example\"")
  25. DLL("gtk_window_set_default_size " & window & " 400 200")
  26. grid = DLL("gdaui_grid_new " & data_model)
  27. DLL("g_object_unref " & data_model)
  28. DLL("gtk_container_add " & window & " " & grid)
  29. DLL("gtk_widget_show_all " & window)
  30.  
  31. gtk_main()
  32.  
  33. DLL("g_object_unref " & cnc)
  34.  

Code: Text
  1. ' GNOME-DB GRID
  2.  
  3. INCLUDE "db-grid.sbh"
  4.  
  5. _DLL("gtk_init", 0, 0)
  6. _DLL("gdaui_init")
  7.  
  8. ' DB Control Window
  9. window = _DLL("gtk_dialog_new_with_buttons","\"Select the Data Source to connect to\"", 0, GTK_DIALOG_MODAL, GTK_STOCK_CANCEL, GTK_RESPONSE_NONE, GTK_STOCK_OK, GTK_RESPONSE_OK, 0)
  10. login = _DLL("gdaui_login_new", "NULL")
  11. _DLL("gtk_box_pack_start", _DLL("gtk_dialog_get_content_area", window), login, TRUE, TRUE, 0)
  12. _DLL("gtk_widget_show", login)
  13. IF _DLL("gtk_dialog_run", window) <> GTK_RESPONSE_OK THEN
  14.   PRINT "Cancelled!\n"
  15.   END
  16. END IF
  17. dsninfo = _DLL("gdaui_login_get_connection_information", login)
  18. cnc = _DLL("gda_connection_open_from_string", STRPTR(dsninfo + provider), STRPTR(dsninfo + cnc_string), 0, 0, 0)
  19. data_model = _DLL("gda_execute_select_command", cnc, "\"SELECT * FROM customers\"", 0)
  20. _DLL("gtk_widget_destroy", window)
  21.  
  22. ' DB Data Grid
  23. window = _DLL("gtk_window_new", 0)
  24. _DLL("gtk_window_set_title", window, "\"GNOME-DB Grid Control Example\"")
  25. _DLL("gtk_window_set_default_size", window, 400, 200)
  26. grid = _DLL("gdaui_grid_new", data_model)
  27. _DLL("g_object_unref", data_model)
  28. _DLL("gtk_container_add", window, grid)
  29. _DLL("gtk_widget_show_all", window)
  30.  
  31. gtk_main()
  32.  
  33. _DLL("g_object_unref", cnc)
  34.  

jrs@Laptop:~/SB/test$ scriba gda.sb
Trying to load plugins in /usr/local/lib/libgda-4.0/plugins...
Loading file /usr/local/lib/libgda-4.0/plugins/libgda-ui-plugins.so...
  - loaded filesel (File selection entry): Entry
  - loaded cird (Entry to hold an IPv4 network specification): Entry
  - loaded text (Multiline text entry): Entry
  - loaded picture (Picture entry): Entry Cell
  - loaded picture_as_string (Picture entry for data stored as a string): Entry Cell
jrs@Laptop:~/SB/test$

The GDA-Browser is a common admin/SQL browser for multiple providers. (SQLite3, PostgreSQL and MySQL)

The GdaBrowser program is a graphical tool to get a quick access to a database's structure and contents. This is a work in progress and more features will be added with time.
This tool aims at being simple to use, visually appealing, and full of features usefull to the database administrator or to discover a new database.

The main features are:

  • it is possible to open any number of connections withing a running instance
  • can access any database Libgda supports
  • is fully multi-threaded to the UI never locks on an operation
  • is organized around the notion of perspective which correspond to activities, and is easy to extend adding new perspectives
  • fullsreen support
  • integrated help


Pages: 1 ... 40 41 [42] 43 44 ... 59