#!/usr/bin/scriba -n
REM
REM Demoprogram for Scriptbasic with the GTK-server
REM Encode to and decode from Base64
REM Runs on both Linux and Windows
REM
REM (C) October 22, 2003 by Peter van Eerten
REM
REM 14/6/2004: improvements on the code
REM Changed for GTK-server 1.2 at October 10, 2004
REM Changed for GTK-server 1.3 at December 6, 2004
REM
REM ****************************************

FUNCTION GTK(st)

LOCAL tmp

PRINT #1, st & nl
LINE INPUT #1, tmp

GTK = tmp

END FUNCTION

REM ****************************************

GLOBAL CONST NL = "\n"
GLOBAL CONST BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
GLOBAL CONST EXPLAIN = "This is a demonstration on how to use Scriptbasic with the GTK-server in Windows."
REM Start a GTK-SERVER
pid = SYSTEM("gtk-server tcp localhost:50000")
REM Wait for initialization
SLEEP(1)
REM Connect to GTK-SERVER
OPEN "localhost:50000" FOR SOCKET AS 1
REM Setup User Interface
CALL Build_Gui

REPEAT
        event = GTK("gtk_server_callback wait")
        IF event = encode THEN CALL Encode_Input
        IF event = entry1 THEN CALL Encode_Input
        IF event = clear1 THEN
                REM Empty entry field
                GTK("gtk_editable_delete_text " & entry1 & " 0 -1")
                REM Empty result field
                GTK("gtk_text_set_point " & encresult & " 0")
                tmp = GTK("gtk_text_get_length " & encresult)
                GTK("gtk_text_forward_delete " & encresult & " " & tmp)
                REM Get focus to text entry
                GTK("gtk_widget_grab_focus " & entry1)
        END IF
        IF event = decode THEN CALL Decode_Input
        IF event = entry2 THEN CALL Decode_Input
        IF event = clear2 THEN
                REM Empty entry field
                GTK("gtk_editable_delete_text " & entry2 & " 0 -1")
                REM Empty result field
                GTK("gtk_text_set_point " & decresult & " 0")
                tmp = GTK("gtk_text_get_length " & decresult)
                GTK("gtk_text_forward_delete " & decresult & " " & tmp)
                REM Get focus to text entry
                GTK("gtk_widget_grab_focus " & entry2)
        END IF
UNTIL event = myexit

REM Exit GTK
PRINT #1, "gtk_exit 0"
REM Kill server
result = KILL (pid)

END

REM ************************************************************Setup GUI with GTK-SERVER

SUB Build_Gui

LOCAL tmp
REM Initialize GTK
GTK("gtk_init NULL, NULL")
REM Create Window
win = GTK("gtk_window_new 0")
GTK("gtk_window_set_title " & win & " \"Scriptbasic BASE64 converter using the GTK-server\"")
GTK("gtk_widget_set_usize " & win & " 450 300")
GTK("gtk_window_set_position " & win & " 1")
table = GTK("gtk_table_new 50 100 1")
GTK("gtk_container_add " & win & " " & table)
REM Create notebook
notebook = GTK("gtk_notebook_new")
GTK("gtk_notebook_set_tab_pos " & notebook & " 2")
GTK("gtk_table_attach_defaults " & table & " " & notebook & " 1 99 1 42")
REM Define notebook pages
notetable1 = GTK("gtk_table_new 50 50 1")
notetable2 = GTK("gtk_table_new 50 50 1")
notetable3 = GTK("gtk_table_new 50 50 1")
notelabel1 = GTK("gtk_label_new Encoder")
notelabel2 = GTK("gtk_label_new Decoder")
notelabel3 = GTK("gtk_label_new About")
REM Add the pages to the notebook
GTK("gtk_notebook_insert_page " & notebook & " " & notetable1 & " " & notelabel1 & " 1")
GTK("gtk_notebook_insert_page " & notebook & " " & notetable2 & " " & notelabel2 & " 2")
GTK("gtk_notebook_insert_page " & notebook & " " & notetable3 & " " & notelabel3 & " 3")
REM *************************** Create encoding part
frame1 = GTK("gtk_frame_new NULL")
GTK("gtk_table_attach_defaults " & notetable1 & " " & frame1 & " 1 49 1 49")
REM Create regular input entry
entry1 = GTK("gtk_entry_new")
GTK("gtk_table_attach_defaults " & notetable1 & " " & entry1 & " 3 48 3 10")
REM Create ENCODE button
encode = GTK("gtk_button_new_with_label Encode")
GTK("gtk_table_attach_defaults " & notetable1 & " " & encode & " 3 10 13 22")
REM Create CLEAR button
clear1 = GTK("gtk_button_new_with_label Clear")
GTK("gtk_table_attach_defaults " & notetable1 & " " & clear1 & " 11 18 13 22")
REM Create result area
encresult = GTK("gtk_text_new NULL NULL")
GTK("gtk_text_set_editable " & encresult & " 1")
GTK("gtk_table_attach_defaults " & notetable1 & " " & encresult & " 3 46 25 47")
adj1 = GTK("gtk_adjustment_new 0 0 100 1 1 5")
GTK("gtk_text_set_adjustments " & encresult & " NULL " & adj1)
scroll1 = GTK("gtk_vscrollbar_new " & adj1)
GTK("gtk_table_attach_defaults " & notetable1 & " " & scroll1 & " 46 48 25 47")
REM *************************** Create decoding part
frame2 = GTK("gtk_frame_new NULL")
GTK("gtk_table_attach_defaults " & notetable2 & " " & frame2 & " 1 49 1 49")
REM Create regular input entry
entry2 = GTK("gtk_entry_new")
GTK("gtk_table_attach_defaults " & notetable2 & " " & entry2 & " 3 48 3 10")
REM Create DECODE button
decode = GTK("gtk_button_new_with_label Decode")
GTK("gtk_table_attach_defaults " & notetable2 & " " & decode & " 3 10 13 22")
REM Create CLEAR button
clear2 = GTK("gtk_button_new_with_label Clear")
GTK("gtk_table_attach_defaults " & notetable2 & " " & clear2 & " 11 18 13 22")
REM Create result area
decresult = GTK("gtk_text_new NULL NULL")
GTK("gtk_text_set_editable " & decresult & " 1")
GTK("gtk_table_attach_defaults " & notetable2 & " " & decresult & " 3 46 25 47")
adj2 = GTK("gtk_adjustment_new 0 0 100 1 1 5")
GTK("gtk_text_set_adjustments " & decresult & " NULL " & adj2)
scroll2 = GTK("gtk_vscrollbar_new " & adj2)
GTK("gtk_table_attach_defaults " & notetable2 & " " & scroll2 & " 46 48 25 47")
REM *************************** Create ABOUT part
frame3 = GTK("gtk_frame_new NULL")
GTK("gtk_table_attach_defaults " & notetable3 & " " & frame3 & " 1 49 1 49")
label = GTK("gtk_label_new \"" & EXPLAIN & "\"")
GTK("gtk_label_set_line_wrap " & label & " 1")
GTK("gtk_table_attach_defaults " & notetable3 & " " & label & " 3 47 3 20")
REM Create EXIT button
myexit = GTK("gtk_button_new_with_label Exit")
GTK("gtk_table_attach_defaults " & table & " " & myexit & " 85 99 43 49")
REM Show all widgets
GTK("gtk_widget_show_all " & win)
REM Get focus to text entry
GTK("gtk_widget_grab_focus " & entry1)

END SUB

REM ************************************************************ Encode

SUB Encode_Input

LOCAL tmp

tmp = GTK("gtk_entry_get_text " & entry1)
tmp = B64_Enc(MID(tmp, 1, LEN(tmp) - 1))
REM Put on screen
GTK("gtk_text_insert " & encresult & " NULL NULL NULL \"" & tmp & "\n\" -1")
REM Get focus to text entry
GTK("gtk_widget_grab_focus " & entry1)

END SUB

REM ************************************************************ Decode

SUB Decode_Input

LOCAL tmp

tmp = GTK("gtk_entry_get_text " & entry2)
tmp = B64_Dec(MID(tmp, 1, LEN(tmp) - 1))
REM Remove '0' karakters from string, gtk_text does not like these
WHILE ASC(RIGHT(tmp, 1)) = 0
        tmp = MID(tmp, 1, LEN(tmp) - 1)
WEND
REM Put on screen
GTK("gtk_text_insert " & decresult & " NULL NULL NULL \"" & tmp & "\n\" -1")
REM Get focus to text entry
GTK("gtk_widget_grab_focus " & entry2)

END SUB

REM ************************************************************Convert to BASE64

FUNCTION B64_Enc(dat$)

LOCAL byte1, byte2, byte3, base1, base2, base3, base4, enc$

enc$ = ""

WHILE LEN(dat$) > 0
        REM Find ASCII values
        IF LEN(dat$) = 1 THEN
                byte1 = ASC(MID(dat$, 1, 1))
        byte2 = 0
        byte3 = 0
        ELIF LEN(dat$) = 2 THEN
        byte1 = ASC(MID(dat$, 1, 1))
        byte2 = ASC(MID(dat$, 2, 1))
        byte3 = 0
        ELSE
        byte1 = ASC(MID(dat$, 1, 1))
        byte2 = ASC(MID(dat$, 2, 1))
        byte3 = ASC(MID(dat$, 3, 1))
        ENDIF
        REM Create Base64 values
        base1 = byte1 \ 4
        base2 = (byte1 AND 3) * 16 + (byte2 AND 240) \ 16
        base3 = (byte2 AND 15) * 4 + (byte3 AND 192) \ 64
        base4 = byte3 AND 63
        REM Find Base64 characters
        IF LEN(dat$) = 1 THEN
                enc$ = enc$ & MID(BASE64, base1 + 1, 1)
                enc$ = enc$ & MID(BASE64, base2 + 1, 1)
                enc$ = enc$ & "=="
                dat$ = ""
        ELIF LEN(dat$) = 2 THEN
                enc$ = enc$ & MID(BASE64, base1 + 1, 1)
                enc$ = enc$ & MID(BASE64, base2 + 1, 1)
                enc$ = enc$ & MID(BASE64, base3 + 1, 1)
                enc$ = enc$ & "="
                dat$ = ""
        ELSE
                enc$ = enc$ & MID(BASE64, base1 + 1, 1)
                enc$ = enc$ & MID(BASE64, base2 + 1, 1)
                enc$ = enc$ & MID(BASE64, base3 + 1, 1)
                enc$ = enc$ & MID(BASE64, base4 + 1, 1)
                dat$ = RIGHT(dat$, LEN(dat$) - 3)
    ENDIF
WEND
REM Define return value
B64_Enc = enc$

END FUNCTION

REM ************************************************************Decode from BASE64

FUNCTION B64_Dec(dat$)

LOCAL dec$, base1$, base2$, base3$, base4$, byte1, byte2, byte3, byte4

dec$ = ""

WHILE LEN(dat$) > 0
        REM Specify byte values of incoming string
        base1$ = MID(dat$, 1, 1)
        base2$ = MID(dat$, 2, 1)
        base3$ = MID(dat$, 3, 1)
        base4$ = MID(dat$, 4, 1)
        REM Now find the indexnumber
        byte1 = INSTR(BASE64, base1$) - 1
        byte2 = INSTR(BASE64, base2$) - 1
        byte3 = INSTR(BASE64, base3$) - 1
        byte4 = INSTR(BASE64, base4$) - 1
        REM Recalculate to ASCII values
        dec$ = dec$ & CHR( (byte1 AND 63) * 4 + (byte2 AND 48) \ 16 )
        dec$ = dec$ & CHR( (byte2 AND 15) * 16 + (byte3 AND 60) \ 4 )
        dec$ = dec$ & CHR( (byte3 AND 3) * 64 + byte4 )
        REM Decrease incoming string with 4
        dat$ = RIGHT(dat$, LEN(dat$) - 4)
WEND
REM Return the result
B64_Dec = dec$

END FUNCTION