Since I hadn't seen any examples using Glade, I decided to roll my own and share.
***UPDATE***
Removed the calls to the GLib-provided Base64 routines, and implemented
native routines, to avoid potential GLib version issues.
Screenshots:
(http://www.recursivemedia.net/screenshots/eba_b64_encode.jpg)
(http://www.recursivemedia.net/screenshots/eba_b64_decode.jpg)
Source:
'~ base64_demo
'~ copyright 2008, Armando I. Rivera / Recursive Media Group
'~ Demonstrates how to use libGlade with Emergence Basic
'~ ************************************************************************
'~ * NOTE: ALL EVENT ROUTINE SUBS NEED TO BE DECLARED GLOBAL *
'~ * IN ORDER FOR GLADE TO FIND THEM *
'~ ************************************************************************
'~ Compile with Target=GTK 2.0
'~ FORCE DECLARATION OF ALL VARIABLES
autodefine "off"
'~ PROGRAM ENTRY POINT
$main
'~ INCLUDE BASE64.INC FILE
$include "base64.inc"
'~ LINKER FLAGS
'~ -s STRIPS THE EXECUTABLE, REDUCING SIZE. OPTIONAL. DISABLE IF DEBUGGING
'~ "-E", OR "--EXPORT DYNAMIC" IS REQUIRED FOR LIBGLADE'S SIGNAL AUTOCONNECT FEATURE
'~ "-lglade-2.0" LINKS THE LIBGLADE LIBRARY
$use "-s -E -lglade-2.0"
'~ API DECLARATIONS. SEE THE GTK DOCS FOR DETAILS
declare cdecl extern glade_xml_new (string XML_FILE,string ROOT_NODE),pointer
declare cdecl extern glade_xml_get_widget (pointer XML_INSTANCE, string XML_OBJECT),pointer
declare cdecl extern glade_xml_signal_autoconnect(pointer WIDGET)
declare cdecl extern g_object_get(pointer object,string propname,...)
declare cdecl extern g_object_set(pointer object,string propname,...)
declare cdecl extern g_base64_encode(string text_to_encode,uint text_len),string
declare cdecl extern g_base64_decode(string text_to_decode,pointer text_len),string
declare cdecl extern g_free(pointer gmem)
declare cdecl extern g_object_unref(pointer gobject)
'~ MAKE SURE THE GLADE FILE IS AVAILABLE, ELSE BAIL
bfile chkFile
int run
if openfile(chkFile,GETSTARTPATH+"B64.glade","R")=0
closefile(chkFile)
'~ VARIABLES THAT WILL POINT TO WINDOW OBJECT HANDLES
pointer GladeFile,window1,txtEncode,txtEncodeOutput,txtDecode,txtDecodeOutput
'~ LOAD UP THE GLADE DEFINITION FILE
GladeFile=glade_xml_new(GETSTARTPATH+"B64.glade","window1")
'~ Interesting bit: You only need handles to objects you need to manipulate directly when using Glade and AutoConnect.
'~ All other objects, like the main Window, for example, don't need to have a handle created
'~ if we're not doing anything with it like changing the Title or setting it's destroy method in code.
'~ window1=glade_xml_get_widget(GladeFile,"window1")
txtEncode=glade_xml_get_widget(GladeFile,"txtEncode")
txtEncodeOutput=glade_xml_get_widget(GladeFile,"textEncodeOutput")
txtDecode=glade_xml_get_widget(GladeFile,"txtDecode")
txtDecodeOutput=glade_xml_get_widget(GladeFile,"textDecodeOutput")
'~ AUTOCONNECT THE EVENT SIGNALS TO THE HANDLERS SPECIFIED IN THE GLADE FILE
glade_xml_signal_autoconnect(GladeFile)
'~ testing property set
'~ g_object_set(window1,"title","Changing the FORM Title in Code",0)
'~ START THE PROGRAM MAIN LOOP
run=true
waituntil run=false
else
'~ GLADE DEF FILE NOT FOUND
print ("GLADE FILE \"B64.glade\" IS NOT IN PROGRAM DIRECTORY")
closefile(chkFile)
end if
end
'~ ROUTINE CALLED WHEN FORM IS CLOSED TO EXIT APPLICATION
global sub on_window1_destroy()
run=false
end sub
'~ ENCODE BUTTON CLICK EVENT HANDLER
global sub on_btnEncode_clicked
start_process(txtEncode,txtEncodeOutput,"Encode")
end sub
'~ ENCODE CLEAR BUTTON CLICK EVENT HANDLER
global sub on_btnEncodeClear_clicked
clear_views(txtEncode,txtEncodeOutput)
end sub
'~ DECODE BUTTON CLICK EVENT HANDLER
global sub on_btnDecode_clicked
start_process(txtDecode,txtDecodeOutput,"Decode")
end sub
'~ DECODE CLEAR BUTTON CLICK EVENT HANDLER
global sub on_btnDecodeClear_clicked
clear_views(txtDecode,txtDecodeOutput)
end sub
'~ ROUTINE TO CLEAR CONTENTS OF GTKENTRY/GTKTEXTVIEW
'~ POINTERS TO GTKENTRY AND GTKTEXTVIEW ARE PASSED
'~ IN ORDER TO SERVICE OBJECTS ON MULTIPLE TABS
sub clear_views(entryHnd as pointer, textviewHnd as pointer)
pointer textbuffer
'~ GET THE HANDLE TO THE GTKTEXVIEW'S GTKTEXTBUFFER
'~ HANDLE IS PASSED TO textbuffer POINTER VARIABLE
g_object_get(textviewHnd,"buffer",&textbuffer,0)
'~ CLEAR THE GTKTEXTBUFFER
g_object_set(textbuffer,"text","",0)
'~ CLEAR THE GTKENTRY
g_object_set(entryHnd,"text","",0)
'~ FREE UP MEMORY ALLOCATED TO THE textbuffer OBJECT
g_object_unref(textbuffer)
end sub
'~ ROUTINE TO BEGIN THE ACTUAL ENCODING/DECODING
'~ POINTERS TO GTKENTRY/GTKTEXTVIEW ARE PASSED
'~ ALONG WITH THE TYPE OF OPERATION DESIRED (ENCODE OR DECODE)
sub start_process(entryHnd as pointer, textviewHnd as pointer, operation as string)
pointer textbuffer,p1,source_string_len
string source_string,encoded_string,lc_string
lc_string=lcase$(operation)
'~ GET THE TEXT CONTENTS OF GTKENTRY AND ASSIGN TO STRING VAR
g_object_get(entryHnd,"text",&p1,0)
source_string=*<string>p1
'~ FREE THE MEMORY USED BY POINTER p1
'~ g_object_get MAKES A COPY OF THE DATA RETRIEVED,
'~ LEAVING IT TO THE CALLER TO FREE THE MEMORY ALLOCATED
'~ ONCE THE DATA HAS BEEN RETRIEVED/USED
'~ g_object_unref would be used for objects
g_free(p1)
'~ CHECK IF THERE'S ANY ACTUAL TEXT
if len(source_string) then
'~ ENCODE, OR DECODE, OR ABORT
select lc_string '(lcase$(operation))
case "encode"
'~ ENCODE IT USING GLIB FUNCTION
encoded_string=ENCODE64(source_string)
case "decode"
'~ DECODE IT USING GLIB FUNCTION
encoded_string=DECODE64(source_string)
end select
'~ GET THE HANDLE TO THE GTKTEXVIEW'S GTKTEXTBUFFER
g_object_get(textviewHnd,"buffer",&textbuffer,0)
'~ GET THE ASC VALUE OF THE FIRST CHARACTER IN THE
'~ RETURNED STRING
int first_char:first_char= asc(encoded_string)
'~ FILTER TO CHECK IF WITHIN SAFE ASCII RANGE
if ((first_char > 31) and (first_char<128)) then
'~SET THE GTKTEXTBUFFER'S CONTENTS TO THE ENCODED STRING
g_object_set(textbuffer,"text",encoded_string,0)
else
'~ NOT IN SAFE RANGE. NOTIFY USER
g_object_set(textbuffer,"text","** Invalid Entry **",0)
end if
'~ FREE UP MEMORY ALLOCATED TO THE textbuffer OBJECT
g_object_unref(textbuffer)
end if
end sub
base64.inc:
'base64.inc Copyright 2007-2008 Armando I. Rivera, Recursive Media Group
'Updated: Sept 7, 2008
'Usage:
' ENCODE64(<string>) returns encoded string
' DECODE64(<string>) returns decoded string
sub ENCODE64(szUnEncoded AS STRING),string
' Create variables
int icLowFill,iChar,iLowMask,iPtr,iCounter,icBitShift,icChopMask,iHighMask,iShift,iRollOver
string szTemp
'~ ' Initialize lookup dictionary and constants
string szAlphabet:szAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
icBitShift = 4
icChopMask = 255
icLowFill = 3
' Initialize Masks
szTemp = ""
iHighMask = 252
iLowMask = 3
iShift = 16
iRollOver = 0
' Begin Encoding process
FOR iCounter = 1 TO LEN(szUnEncoded)
' Fetch ascii character in passed string
iChar = ASC(MID$(szUnEncoded, iCounter, 1))
' Calculate Alphabet lookup pointer
iPtr = ((iChar & iHighMask) / (iLowMask + 1)) | iRollOver
' Roll bit patterns
iRollOver = (iChar & iLowMask) * iShift
' Concatenate encoded character to working encoded string
szTemp += MID$(szAlphabet, iPtr + 1, 1)
' Adjust masks
iHighMask = (iHighMask * icBitShift) & icChopMask
iLowMask = iLowMask * icBitShift + icLowFill
iShift = iShift / icBitShift
' If last character in block, concat last RollOver and
' reset masks
IF iHighMask = 0 THEN
szTemp += MID$(szAlphabet, iRollOver + 1, 1)
iRollOver = 0
iHighMask = 252
iLowMask = 3
iShift = 16
END IF
NEXT iCounter
' If RollOver remains, concat it to the working string
IF iShift < 16 THEN
szTemp += MID$(szAlphabet, iRollOver + 1, 1)
END IF
' Pad encoded string with required '=' pad characters
iPtr = (LEN(szTemp) % 4)
IF iPtr THEN szTemp += STRING$(4 - iPtr, "=")
' Return encoded string
return szTemp
END sub
sub DECODE64 (string szEncoded),string
' Create variables
int icLowFill,iChar,iLowMask,iPtr,iCounter,icBitShift,icChopMask,iHighMask,iShift,iRollOver,iLowShift,icStartMask
string szTemp,szAlphabet
' Initialize lookup dictionary
szAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
' Initialize Constants
icChopMask = 255
icBitShift = 4
icStartMask = 16
' Initialize Masks
iShift = icBitShift
iLowShift = 0
iRollOver = 0
iHighMask = -1
' Initialize working string
szTemp = ""
' Begin Decoding
FOR iCounter = 1 TO LEN(szEncoded)
' Get next alphabet
iChar = ASC(MID$(szEncoded, iCounter, 1))
' Get Decoded value
iPtr = INSTR(szAlphabet, CHR$(iChar)) - 1
' Check if character is valid
IF iPtr >= 0 THEN
' Char is valid, process it
IF iShift = icBitShift THEN
' 1st char in block of 4, keep high part of character
iRollOver = (iPtr * iShift) & icChopMask
' Reset masks for next character
iHighMask = 0x030
iLowShift = icStartMask
iShift = icStartMask
ELSE
' Start saving decoded character
szTemp += CHR$(iRollOver | ((iPtr & iHighMask) / iLowShift))
' Calculate next mask and shift values
iRollOver = (iPtr * iShift) & icChopMask
iShift = iShift * icBitShift
iHighMask = ((iHighMask / icBitShift) | 0x030)
iLowShift = iLowShift / icBitShift
IF iShift > 256 THEN
iShift = icBitShift
iLowShift = 0
END IF
END IF
END IF
NEXT iCounter
' return decoded string
return szTemp
END sub
B64.glade:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--Generated with glade3 3.4.5 on Sat Sep 6 01:39:55 2008 -->
<glade-interface>
<widget class="GtkWindow" id="window1">
<property name="visible">True</property>
<property name="border_width">6</property>
<property name="title" translatable="yes">Emergence Basic Base64 Glade Demo</property>
<property name="window_position">GTK_WIN_POS_CENTER</property>
<signal name="destroy" handler="on_window1_destroy"/>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<child>
<widget class="GtkNotebook" id="notebook1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<widget class="GtkFrame" id="frame1">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<child>
<widget class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
<widget class="GtkVBox" id="vbox2">
<property name="visible">True</property>
<property name="spacing">4</property>
<child>
<widget class="GtkEntry" id="txtEncode">
<property name="visible">True</property>
<property name="can_focus">True</property>
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox2">
<property name="height_request">36</property>
<property name="visible">True</property>
<child>
<widget class="GtkButton" id="btnEncode">
<property name="width_request">70</property>
<property name="height_request">22</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">Encode</property>
<property name="response_id">0</property>
<signal name="clicked" handler="on_btnEncode_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="padding">2</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="btnEncodeClear">
<property name="width_request">70</property>
<property name="height_request">22</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">Clear</property>
<property name="response_id">0</property>
<signal name="clicked" handler="on_btnEncodeClear_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
<child>
<widget class="GtkTextView" id="textEncodeOutput">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="wrap_mode">GTK_WRAP_WORD_CHAR</property>
<property name="left_margin">1</property>
<property name="right_margin">1</property>
</widget>
</child>
</widget>
<packing>
<property name="padding">4</property>
<property name="position">2</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">Encoder</property>
</widget>
<packing>
<property name="type">tab</property>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<widget class="GtkFrame" id="frame2">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<child>
<widget class="GtkAlignment" id="alignment2">
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
<widget class="GtkVBox" id="vbox3">
<property name="visible">True</property>
<property name="spacing">4</property>
<child>
<widget class="GtkEntry" id="txtDecode">
<property name="visible">True</property>
<property name="can_focus">True</property>
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox3">
<property name="height_request">36</property>
<property name="visible">True</property>
<child>
<widget class="GtkButton" id="btnDecode">
<property name="width_request">70</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">Decode</property>
<property name="response_id">0</property>
<signal name="clicked" handler="on_btnDecode_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="padding">2</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="btnDecodeClear">
<property name="width_request">70</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">Clear</property>
<property name="response_id">0</property>
<signal name="clicked" handler="on_btnDecodeClear_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
<child>
<widget class="GtkTextView" id="textDecodeOutput">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="wrap_mode">GTK_WRAP_WORD_CHAR</property>
<property name="left_margin">2</property>
<property name="right_margin">2</property>
</widget>
</child>
</widget>
<packing>
<property name="padding">4</property>
<property name="position">2</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="label" translatable="yes">Decoder</property>
</widget>
<packing>
<property name="type">tab</property>
<property name="position">1</property>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<widget class="GtkFrame" id="frame3">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<child>
<widget class="GtkAlignment" id="alignment3">
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
<widget class="GtkVBox" id="vbox4">
<property name="visible">True</property>
<property name="spacing">4</property>
<child>
<widget class="GtkLabel" id="label7">
<property name="visible">True</property>
<property name="label" translatable="yes"><big><b>This is a demo showing how
to use Emergence Basic with
the Glade Designer and
libGlade Under Linux.</b></big>
<b><i>Copyright 2008 Armando I. Rivera, Recursive Media Group</i></b></property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_CENTER</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="padding">56</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox4">
<property name="height_request">45</property>
<property name="visible">True</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="position">2</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="label" translatable="yes">About</property>
</widget>
<packing>
<property name="type">tab</property>
<property name="position">2</property>
<property name="tab_fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">6</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<child>
<placeholder/>
</child>
<child>
<widget class="GtkButton" id="btnExit">
<property name="width_request">70</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="border_width">2</property>
<property name="label" translatable="yes">Exit</property>
<property name="response_id">0</property>
<signal name="clicked" handler="on_window1_destroy"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="pack_type">GTK_PACK_END</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="pack_type">GTK_PACK_END</property>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>
Script for use when compiling from a terminal:
#!/bin/bash
#**MODIFY THE PATH TO THE libebasic.a FILE!**
#Place this script somewhere in path (/usr/bin,/usr/local/bin,etc), call it what you want (I call mine "eb")
#Then, just "eb <name of source file>" WITHOUT the .eba extension or quotes
if [ -f $1.uselibs ]; then
rm $1.uselibs
fi
if [ -f $1.eba ]; then
ebparse $1.eba $1.o
ld -e _gtkstart $1.o -o $1 ~/dev/ebasic/libebasic.a -ldl -lc -I /lib/ld-linux.so.2 $2 $3 $4 $5 `cat $1.uselibs`
strip -s -R.comment $1
else
echo "Unable to locate $1.eba. Make sure you typed the name correctly..."
fi
Enjoy.....
AIR.
Hi Armando,
Just a couple of points...
You don't need to call gtk_init as it is done for you by the entry point _gtkstart, otherwise you are actually calling it twice. Not sure what the side effects of that will be.
Similarly if you use the built in functionality of WaitUntil then you also don't need gtk_main and gtk_main_end, but it is fine either way.
Nice example in any case :D
Paul.
Thank you very much for the Glade example AIR.
Allan
Hi AIR
I have it up and running after having to get glade.dev installed.
When I run the program it comes up fine and the Encode works fine. But the Decode does not work out.
Just to make sure I am using it correctly.
1. Start prog and enter my Name in the Encode Edit box
2. Click Encode button
3. Copy the Encoded text from the Text View
4. Click Clear button
5. Click the Decode Tab.
6. Paste in the Encoded text to the Decode Edit box.
7. Click Decode button
Quotebpak@bpak-desktop:~/EBasic_Linux/AIR$ dir
B64.glade base64_demo.asm base64_demo.o
base64_demo base64_demo.eba base64_demo.uselibs
bpak@bpak-desktop:~/EBasic_Linux/AIR$ ./base64_demo
Segmentation fault (core dumped)
bpak@bpak-desktop:~/EBasic_Linux/AIR$
Segment fault (core dumped) suggests a problem with....?
Allan
Hmmmmm. Not sure, because I'm not getting that here.
Let me look into it some more, and I'll get back to you....
AIR.
It may have something to do with not checking if the encoded/decoded string is within the "safe" ascii range.
In the start_process sub, try replacing whats between the end of the select block and the "end if" at the end of the sub with:
'~ GET THE HANDLE TO THE GTKTEXVIEW'S GTKTEXTBUFFER
g_object_get(textviewHnd,"buffer",&textbuffer,0)
'~ GET THE ASC VALUE OF THE FIRST CHARACTER IN THE
'~ RETURNED STRING
int first_char:first_char= asc(encoded_string)
'~ FILTER TO CHECK IF WITHIN SAFE ASCII RANGE
if ((first_char > 31) and (first_char<128)) then
'~SET THE GTKTEXTBUFFER'S CONTENTS TO THE ENCODED STRING
g_object_set(textbuffer,"text",encoded_string,0)
else
'~ NOT IN SAFE RANGE. NOTIFY USER
g_object_set(textbuffer,"text","** Invalid Entry **",0)
end if
'~ FREE UP MEMORY ALLOCATED TO THE textbuffer OBJECT
g_object_unref(textbuffer)
Which distro are you using, and what version of GTK is installed?
AIR.
Ubuntu Fiesty 7.04 with latest updates.
GTK version is 2 something. Dont know how to find this out as they have numbers all over the place.
They have some things mentioned as version 2.10.11 and lots of different combinations for various GTK files. But I guess this is the version.
libgtk2.0-dev is 2.10.11
Could you indicate the file name I would look for in the Synaptic Package Manger please if that is not the one?
I thought this system automatically updated??
I will try that change in the prog.
Thanks....
Allan
EDIT
Still comes up with the same error message.
Quotebpak@bpak-desktop:~/EBasic_Linux/AIR$ eb base64_demo
bpak@bpak-desktop:~/EBasic_Linux/AIR$ ./base64_demo
Segmentation fault (core dumped)
bpak@bpak-desktop:~/EBasic_Linux/AIR$
Allan
I don't think the change is gonna help.
It looks like a GLib Version difference, not GTK. My mistake.
Base64 Encoding/Decoding support was added as of Glib 2.12. If you don't have that version, that's the likely cause of the segfault.
So, what can we do?
Create Native Base64 Encoding/Decoding routines.
I have an Encode routine that I ported from some ancient code I came across, but I haven't worked out a Decode routine yet:
*EDIT* Encode/Decode routines have been redone using Native code. See the first post for updated example.
AIR.
Looking through the packages under Libraries Development there is libglib2.0-dev 2.12.11.0 ubuntu1
That would be the correct one?
Allan
Yes, that should be the one.
You raise an interesting point, though: How to address end-users that DON'T have the latest libs installed.
I think trying to implement as much as possible in a native fashion is the answer.
I've worked out native routines to both encode and decode Base64 strings, and will be updating the original post shortly. ;D
**EDIT** Original post has been updated.
AIR.
Hi AIR
I found the problem.
After finding it was in libglib and not GTK I managed to install docs for it and in DevHelp could search for the g_base64_Decode
It showed that it returned the gsize (32 bit integer) in the variable u used txt_len
So I changed it from a pointer to an INT
INT txt_len
and change the call:
encoded_string=g_base64_decode(source_string,&txt_len)
Compiled it with eb
and it now works fine.
Thanks for the help and LOOK forward to more examples to work with.
Thanks again AIR
Allan
QuoteYou raise an interesting point, though: How to address end-users that DON'T have the latest libs installed.
I think trying to implement as much as possible in a native fashion is the answer.
I like the idea of native fashion indeed. Though I think I was reading somewhere about making dpkg (Installation Package) and that you can declare in it the libs needed and it will make/let the user get those files if needed.
Cant remember exactly but it was something like that.
Allan
Quote from: Allan on September 06, 2008, 11:05:14 PM
Hi AIR
I found the problem.
After finding it was in libglib and not GTK I managed to install docs for it and in DevHelp could search for the g_base64_Decode
It showed that it returned the gsize (32 bit integer) in the variable u used txt_len
So I changed it from a pointer to an INT
Good catch, Allan!.
This is why I try to share my code, because after staring at it for what seems like an eternity a fresh set of eyes sees things that I can't anymore. ;)
QuoteThanks for the help and LOOK forward to more examples to work with.
;D You know my track record.....I'm still getting up to speed with what the native gui capabilities are, so the next thing I'm working on will be using (mostly) Gtk Api calls.
Is there a comprehensive list of what's implemented in the current Linux version? For example, I tried ENUM and it didn't work. @GROUPBOX didn't display anything either, but didn't cause any errors compiling or executing...
AIR.
Air,
There is a 1 to 1 correspondence for most of the controls from the windows to linux versions. The point is to be able to compile your code on both compilers without much changes. Off the top of my head, without booting into linux, button, checkbox, scrollbars, edit, multi line edit, combobox, and list box are working. Radiobuttons were next, have to simulate automatic grouping like Windows does.
There are some linux specific functions like GetControlWidget which returns a pointer to the GtkWidget based on the Emergence control ID. Functions just like GetControlHandle does on the windows version. Which would propbably come in handy for you. GetControlWidget understands container hierarchy.
There are container controls as well built in. @HPANED and @VPANED for example. Which I use for things like tinyide.
The example programs are meant to give a general idea of what is working so far.
The Emergence Window simulates a window from the Microsoft OS's. It doesn't automatically scale or position controls that are placed in it. But you can achieve the same functionality as Gtk using a container control and sizing that container when your handler receives a @IDSIZE message.
The other linux specific function that you might find useful is CreateControl, which creates a control without adding it to a window, it returns a pointer to the base widget used to construct the control in question. You can also create any widget using gtk functions, and make it an Emergence control by setting a few object data properties.
"EBIDENT" is the numeric identifier
"EBTYPE" controls how functions like SetFont, SetControlColor, etc work.
"EBSTYLE" is the style bits used when creating the control.
If your control is a compound widget, such as gtk_scrollable with some other control being scrolled, then call it a @button so SetFont will use gtk_bin_get_child. If it isn't a compound widget then give it a non existant type like 99999 as there are default cases.
In any event here is some of the creation code for tinyide so you can see how I combine native control functionality with GTK api functions.
openwindow win,0,0,640,400,@SIZE|@MINBOX|@MAXBOX|@MAXIMIZED|@NOAUTODRAW,0,"Emergence BASIC Tiny IDE 0.5",&mainwindow
getclientsize win,left,top,width,height
control win,@VPANED,"",left,top,width,height,0,100
pointer pControl,pControl2,pNotebook,pDocument
pControl2 = GetControlWidget(win,100)
if pControl2
pNotebook = CreateControl(@NOTEBOOK,"",0,0,640,100,0,200)
gtk_paned_pack1(pControl2,pNotebook,true,false)
gtk_notebook_set_scrollable(pNotebook,TRUE)
pControl = CreateControl(@HPANED,"",0,0,0,0,0,300)
gtk_paned_pack2(pControl2,pControl,false,false)
pControl2 = CreateControl(@EDIT,"",0,0,320,100,@CTEDITMULTI|@HSCROLL|@VSCROLL,400)
gtk_text_view_set_editable(gtk_bin_get_child(pControl2),false)
gtk_scrolled_window_set_policy(pControl2,1,1)
gtk_paned_add1(pControl,pControl2)
NewDocument()
endif
sub NewDocument(),int
pointer pControl
'
pointer pScrollWindow:pScrollWindow = gtk_scrolled_window_new(NULL,NULL)
pControl = gtk_source_view_new()
gtk_container_add(pScrollWindow,pControl)
g_object_set_data(pScrollWindow,"EBIDENT",base_edit_id)
g_object_set_data(pScrollWindow,"EBTYPE",@EDIT)
g_object_set_data(pScrollWindow,"EBSTYLE",@CTEDITMULTI|@HSCROLL|@VSCROLL)
gtk_source_view_set_show_line_numbers(pControl,true)
gtk_source_view_set_show_line_markers(pControl,true)
gtk_source_view_set_indent_on_tab(pControl,true)
gtk_source_view_set_tabs_width(pControl,4)
gtk_widget_show_all(pScrollWindow)
pControl = pScrollWindow
pDocument = NEW(document,1)
#<document>pDocument.edit_id = base_edit_id
g_object_set_data(pControl,"document",pDocument+0)
gtk_widget_show(pControl)
page = gtk_notebook_append_page(pNotebook,pControl,NULL)
CreatePageTab(page,"Untitled" + ltrim$(str$(current_untitled)))
setfont win,"Sans",11,400,0,base_edit_id
current_untitled++
base_edit_id++
return page
endsub
SUB CreatePageTab(int page,string title)
pointer pBook,pPage,pTab,pClose,pLabel,pImage,hfont
pBook = GetControlWidget(win,200)
if pBook
pPage = gtk_notebook_get_nth_page(pBook,page)
pTab = CreateControl(@HBOX,"",0,0,0,0,0,3000)
pClose = CreateControl(@BUTTON,"",0,0,0,0,0,1000)
pImage = gtk_image_new()
gtk_image_set_from_stock(pImage,"gtk-close",1)
gtk_button_set_relief(pClose,2)
gtk_button_set_image(pClose,pImage)
g_signal_connect_data(pClose,"clicked",&CloseTabClicked,pPage,NULL,0)
gtk_box_pack_end(pTab,pClose,false,false,0)
pLabel = CreateControl(@STATIC,title,0,0,0,0,0,2000)
hfont = pango_font_description_from_string("Sans 10")
gtk_widget_modify_font(pLabel,hfont)
pango_font_description_free(hfont)
gtk_box_pack_start(pTab,pLabel,true,true,0)
gtk_notebook_set_tab_label(pBook,pPage,pTab)
endif
ENDSUB
Paul.
Thanks, Paul.
I actually have looked over the source to tinyide and did have some questions, which you've answered.
Thanks again for the info, it will definitely come in handy.
AIR.
Hi AIR
QuoteThis is why I try to share my code, because after staring at it for what seems like an eternity a fresh set of eyes sees things that I can't anymore
I am not too cluey about Linux and its API yet but hopefully my experience with programming in Emergence may help a bit.
Looks like a lot of pointer in the GTK API.
QuoteYou know my track record.....I'm still getting up to speed with what the native gui capabilities are, so the next thing I'm working on will be using (mostly) Gtk Api calls.
Look forward to it. I dont have the Source so leave it to the experts ::)