Attached is a beta ScriptBasic 2.2 release for Windows. (IUP included) The only installation step is to adjust your PATH variable to point to the
bin directory of this beta. I have included a test directory with examples and their output. (.out) Some of the extension module like MySQL and cURL require their runtime libraries/clients installed before using the ScriptBasic extension modules for them. I have uploaded a zip of
extension module support DLLs that should go in your system32 on XP and SysWOW64 on 64 bit Windows 7.
Note: There are two version of the ScriptBasic interpreter. For console applications and redirection (stdin/out) use
scriba.exe. If you wish to run GUI based applications, use the Windows
sbiup.exe version of the interpreter that has no console support. If you like you could associate the
.sbx attribute for example to sbiup.exe which would allow you to run the script directly by clicking on them in explorer or as a shortcut.
Feedback welcome.
ScriptBasic DocumentationScriptBasic ForumSBx_buttons' SBx_buttons Example
INCLUDE "SBx"
SUB Btn1_clicked
PRINT "BUTTON 1 Event\n"
END SUB
SUB Btn2_clicked
PRINT "BUTTON 2 Event\n"
END SUB
SUB Btn3_clicked
PRINT "BUTTON 3 Event\n"
END SUB
SUB Win_exit
Iup::ExitLoop = TRUE
END SUB
win = WINDOW()
SETPROPERTY(win, "TITLE=\"SBx Buttons\", SIZE=300x")
horzbox = HBOX()
SETPROPERTY(horzbox, "GAP=5")
btn1 = BUTTON()
SETPROPERTY(btn1, "TITLE=Button1, EXPAND=HORIZONTAL")
btn2 = BUTTON()
SETPROPERTY(btn2, "TITLE=Button2, EXPAND=HORIZONTAL")
btn3 = BUTTON()
SETPROPERTY(btn3, "TITLE=Button3, EXPAND=HORIZONTAL")
APPEND(horzbox, btn1)
APPEND(horzbox, btn2)
APPEND(horzbox, btn3)
APPEND(win, horzbox)
EVENT(win,"CLOSE_CB",ADDRESS(Win_exit()))
EVENT(btn1,"ACTION",ADDRESS(Btn1_clicked()))
EVENT(btn2,"ACTION",ADDRESS(Btn2_clicked()))
EVENT(btn3,"ACTION",ADDRESS(Btn3_clicked()))
SHOW(win)
sbiupdict.sbIMPORT iup.bas
servers[0]="dict.org"
servers[1]="dict1.us.dict.org"
servers[2]="all.dict.org"
about="""This is a Demo
of the IUP GUI Binding
for Scriptbasic"""
' Initialize IUP
Iup::Open()
' Create main window
win = Iup::Create("dialog")
Iup::SetAttributes(win, "TITLE=\"ScriptBasic IUP Online Dictionary\", SIZE=500x300")
Iup::SetCallback(win,"CLOSE_CB",ADDRESS(Win_exit()))
' Create container to house ALL GUI objects
vbox = Iup::Create("vbox")
Iup::SetAttributes(vbox, "MARGIN=10x10")
' Create server panel
topBox = Iup::Create("hbox")
Iup::SetAttributes(topBox, "GAP=10")
Iup::Append(vbox, topBox)
serverFrame = Iup::Create("frame")
Iup::SetAttributes(serverFrame, "TITLE=Servers, EXPAND=YES")
Iup::Append(topBox, serverFrame)
serverBox = Iup::Create("hbox")
Iup::SetAttributes(serverBox, "GAP=5")
Iup::Append(serverFrame, serverBox)
serverCombo = Iup::Create("list")
Iup::SetAttributes(serverCombo, "DROPDOWN=YES, SIZE=120x, EXPAND=HORIZONTAL, VALUE=1")
Iup::Append(serverBox, serverCombo)
Iup::SetCallback(serverCombo, "ACTION", ADDRESS(serverCombo_selected()))
btnFetch = Iup::Create("button")
Iup::SetAttributes(btnFetch, "TITLE=Fetch, SIZE = 50x")
Iup::Append(serverBox, btnFetch)
Iup::SetCallback(btnFetch, "ACTION", ADDRESS(btnFetch_clicked()))
' Create control panel
controlFrame = Iup::Create("frame")
Iup::SetAttributes(controlFrame, "TITLE=Controls")
Iup::Append(topBox, controlFrame)
controlBox = Iup::Create("hbox")
Iup::SetAttributes(controlBox, "GAP=5")
Iup::Append(controlFrame, controlBox)
btnAbout = Iup::Create("button")
Iup::SetAttributes(btnAbout, "TITLE=About, SIZE = 50x")
Iup::Append(controlBox, btnAbout)
Iup::SetCallback(btnAbout, "ACTION", ADDRESS(btnAbout_clicked()))
btnClear = Iup::Create("button")
Iup::SetAttributes(btnClear, "TITLE=Clear, SIZE = 50x")
Iup::Append(controlBox, btnClear)
Iup::SetCallback(btnClear, "ACTION", ADDRESS(btnClear_clicked()))
btnExit = Iup::Create("button")
Iup::SetAttributes(btnExit, "TITLE=Exit, SIZE = 50x")
Iup::Append(controlBox, btnExit)
Iup::SetCallback(btnExit,"ACTION",ADDRESS(Win_exit()))
' Create dictionary panel
dictFrame = Iup::Create("frame")
Iup::SetAttributes(dictFrame, "TITLE=Dictionaries")
Iup::Append(vbox, dictFrame)
serverList = Iup::Create("list")
Iup::SetAttributes(serverList, "EXPAND=YES, VISIBLELINES=1")
Iup::Append(dictFrame, serverList)
Iup::SetCallback(serverList, "ACTION", ADDRESS(serverList_selected()))
' Create text part
transFrame = IUP::Create("frame")
Iup::SetAttributes(transFrame, "TITLE=Translation")
Iup::Append(vbox, transFrame)
text = Iup::Create("text")
Iup::SetAttributes(text, "MULTILINE=YES, EXPAND=YES")
Iup::Append(transFrame, text)
' Create entry and search button
bottomBox = Iup::Create("hbox")
Iup::SetAttributes(bottomBox, "GAP=10")
Iup::Append(vbox, bottomBox)
label = Iup::Create("label")
Iup::SetAttributes(label, "TITLE=\"Enter Word to Search For:\", SIZE=x12")
Iup::Append(bottomBox, label)
entry = Iup::Create("text")
Iup::SetAttributes(entry, "EXPAND=HORIZONTAL")
Iup::Append(bottomBox, entry)
btnSearch = Iup::Create("button")
Iup::SetAttributes(btnSearch,"TITLE=Search, SIZE=50x")
Iup::Append(bottomBox, btnSearch)
Iup::SetCallback(btnSearch, "ACTION", ADDRESS(btnSearch_clicked()))
chkAll = Iup::Create("toggle")
Iup::SetAttributes(chkAll, "TITLE=ALL, SIZE=x12")
Iup::Append(bottomBox, chkAll)
chkUTF = Iup::Create("toggle")
Iup::SetAttributes(chkUTF, "TITLE=UTF-8, SIZE=x12")
Iup::Append(bottomBox, chkUTF)
' Add the main GUI container to the Window
Iup::Append(win, vbox)
' Setup dialog defaults
Iup::Show(win)
Iup::SetFocus(btnFetch)
FOR i = 0 TO UBOUND(servers)
Iup::SetAttribute(serverCombo, "APPENDITEM", servers[i])
NEXT
Iup::SetAttribute(serverCombo, "VALUE", "1")
Iup::Update(serverCombo)
server_selection = servers[0]
' Main processing loop
Iup::MainLoop()
Iup::Close()
END
' Callback routines
SUB Win_exit
Iup::ExitLoop = TRUE
END SUB
SUB btnAbout_clicked
Iup::Message("ABOUT", about)
END SUB
SUB serverCombo_selected
server_selection = Iup::GetListText()
END SUB
SUB serverList_selected
whichDictionary = Iup::GetListText()
END SUB
SUB btnFetch_clicked
LOCAL dat, total, count
ON ERROR GOTO G_NetError
OPEN server_selection & ":2628" FOR SOCKET AS #1
PRINT#1,"SHOW DB\n"
LINE INPUT#1, dat
LINE INPUT#1, dat
count = 0
WHILE LEFT(dat, 1) <> "."
LINE INPUT#1, dat
IF LEFT(dat, 1) <> "." THEN total[count] = TRIM(dat)
count+=1
WEND
PRINT#1,"QUIT\n"
CLOSE(#1)
FOR cnt = 0 TO count - 2
Iup::SetAttribute(serverList, "APPENDITEM", total[cnt])
NEXT
Iup::SetAttribute(serverList, "VALUE", "1")
Iup::Update(serverCombo)
whichDictionary = total[0]
EXIT SUB
G_NetError:
PRINT "Server ",server_selection," not available. (",ERROR,")\n"
END SUB
SUB btnClear_clicked
Iup::ClearList(serverList)
Iup::SetAttribute(text, "VALUE", "")
Iup::SetAttribute(entry, "VALUE", "")
END SUB
SUB btnSearch_clicked
LOCAL dict, dat, total, info
IUP::SetAttribute(text, "VALUE","Fetching....")
ON ERROR GOTO L_NetError
dict = LEFT(whichDictionary, INSTR(whichDictionary, " "))
OPEN server_selection & ":2628" FOR SOCKET AS 1
IF Iup::GetAttribute(chkAll, "VALUE") THEN
PRINT#1,"DEFINE * " & Iup::GetAttribute(entry,"VALUE") & "\n"
ELSE
PRINT#1,"DEFINE " & dict & " " & Iup::GetAttribute(entry,"VALUE") & "\n"
END IF
REPEAT
LINE INPUT#1, dat
IF LEFT(dat, 3) = "151" THEN
total$ &= "------------------------------\r\n"
total$ &= RIGHT(dat, LEN(dat) - LEN(Iup::GetAttribute(entry, "VALUE")) - LEN(dict))
total$ &= "------------------------------\r\n"
REPEAT
LINE INPUT#1, info
info = REPLACE(info, CHR(34), CHR(92) & CHR(34))
IF LEFT(info, 1) <> "." THEN total &= TRIM(info) & "\n"
UNTIL LEFT(info, 1) = "."
total &= "\n"
END IF
UNTIL LEFT(dat, 3) = "250" OR VAL(LEFT(dat, 3)) > 499
PRINT#1,"QUIT\n"
CLOSE(#1)
IF LEFT(dat, 3) = "552" THEN
total = "No match found."
ELSE IF LEFT(dat, 3) = "501" THEN
total = "Select a dictionary first!"
ELSE IF LEFT(dat, 3) = "550" THEN
total = "Invalid database!"
END IF
Iup::SetAttribute(text, "VALUE", total)
EXIT SUB
L_NetError:
dat[0] = "Could not lookup word! (" & ERROR & ")"
Iup::SetAttribute(text, "VALUE", dat)
END SUB
testsqlite3.sbimport sqlite.bas
db = sqlite::open("sqlite3.db")
sqlite::execute(db,"create table demo (someval integer, sometxt text);")
sqlite::execute(db,"insert into demo values (123,'hello');")
sqlite::execute(db, "INSERT INTO demo VALUES (234, 'cruel');")
sqlite::execute(db, "INSERT INTO demo VALUES (345, 'world');")
stmt = sqlite::query(db,"SELECT * FROM demo")
while (sqlite::row(stmt) = sqlite::SQLITE3_ROW)
if sqlite::fetchhash(stmt,column) then
print column{"someval"},"\t-\t",column{"sometxt"},"\n"
end if
wend
sqlite::close(db)
123 - hello
234 - cruel
345 - world
testmysql.sb' MySQL Test Program
INCLUDE mysql.bas
dbh = mysql::RealConnect("localhost","root","your_password","test")
mysql::query(dbh,"SELECT * FROM city LIMIT 0,10")
WHILE mysql::FetchHash(dbh,column)
PRINT "| "
PRINT column{"ID"}," | "
PRINT column{"Name"}," | "
PRINT column{"CountryCode"}," | "
PRINT column{"District"}," | "
PRINT column{"Population"}," |"
PRINTNL
WEND
PRINTNL
PRINT "The database handle is: ",dbh,"\n"
PRINT "Affected rows by SELECT: ",mysql::AffectedRows(dbh),"\n"
PRINT "Character set name is: ",mysql::CharacterSetName(dbh),"\n"
PRINT "Last error is: ",mysql::ErrorMessage(dbh),"\n"
PRINT "Client info is: ",mysql::GetClientInfo(),"\n"
PRINT "Host info is: ",mysql::GetHostInfo(dbh),"\n"
PRINT "Proto info is: ",mysql::GetProtoInfo(dbh),"\n"
PRINT "Server info is: ",mysql::GetServerInfo(dbh),"\n"
PRINT "PING result: ",mysql::Ping(dbh),"\n"
PRINT "Thread ID: ",mysql::ThreadId(dbh),"\n"
PRINT "Status is: ",mysql::Stat(dbh),"\n"
mysql::Close(dbh)
| 1 | Kabul | AFG | Kabol | 1780000 |
| 2 | Qandahar | AFG | Qandahar | 237500 |
| 3 | Herat | AFG | Herat | 186800 |
| 4 | Mazar-e-Sharif | AFG | Balkh | 127800 |
| 5 | Amsterdam | NLD | Noord-Holland | 731200 |
| 6 | Rotterdam | NLD | Zuid-Holland | 593321 |
| 7 | Haag | NLD | Zuid-Holland | 440900 |
| 8 | Utrecht | NLD | Utrecht | 234323 |
| 9 | Eindhoven | NLD | Noord-Brabant | 201843 |
| 10 | Tilburg | NLD | Noord-Brabant | 193238 |
The database handle is: 1
Affected rows by SELECT: 10
Character set name is: latin1
Last error is:
Client info is: 6.0.0
Host info is: localhost via TCP/IP
Proto info is: 10
Server info is: 5.5.28
PING result: -1
Thread ID: 0
Status is: Uptime: 23820 Threads: 1 Questions: 4 Slow queries: 0 Opens: 35 Flush tables: 1 Open tables: 1 Queries per second avg: 0.000
testodbc.sbIMPORT odbc.bas
dbh = odbc::RealConnect("SBSQL3","","")
odbc::query(dbh,"SELECT * FROM demo")
WHILE odbc::FetchHash(dbh,dbcol)
PRINT dbcol{"someval"},"\t-\t",dbcol{"sometxt"},"\n"
WEND
odbc::Close(dbh)
123 - hello
234 - cruel
345 - world
testmxml.sbimport mxml.bas
filename = "stuff.xml"
doc = mxml::LoadDoc(filename)
node = mxml::GetNode(doc,"/stufflist/stuff_test")
if node then print "Test1: ", mxml::GetNodeValue(node),"\n"
node = mxml::GetNode(doc,"/stufflist/stuff_test2")
if (node) then print "Test2: ", mxml::GetNodeValue(node),"\n\n"
node = mxml::GetNode(doc,"/stufflist/stuff_test3/painting/img")
if node then
print "Image: ", mxml::GetProperty(node,"src"), "\n"
print "Alt Image: ", mxml::GetProperty(node,"alt"), "\n\n"
endif
node = mxml::GetNode(doc,"/stufflist/books")
child = mxml::GetChild(node)
while child
node = mxml::GetNode(child,"id")
if node then print "ID = ", mxml::GetNodeValue(node),"\n"
node = mxml::GetNode(child,"name")
if node then print "Name = ", mxml::GetNodeValue(node),"\n"
child = mxml::GetNext(child)
wend
if doc then mxml::FreeDoc(doc)
stuff.xml<?xml version="1.0" encoding="UTF-8" ?>
<stufflist>
<stuff_test>This is a test!</stuff_test>
<stuff_test2>And this is another test!</stuff_test2>
<stuff_test3>
<painting>
<img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
<caption>This is Raphael's "Foligno" Madonna, painted in
<date>1511</date>.
</caption>
</painting>
</stuff_test3>
<books>
<book>
<id>1</id>
<name>Hello, world!</name>
</book>
<book>
<id>2</id>
<name>Hello, China!</name>
</book>
</books>
</stufflist>
Test1: This is a test!
Test2: And this is another test!
Image: madonna.jpg
Alt Image: Foligno Madonna, by Raphael
ID = 1
Name = Hello, world!
ID = 2
Name = Hello, China!
testcurl.sbINCLUDE curl.bas
ch = curl::init()
curl::option(ch,"URL","http://localhost/index.html")
' curl::option(ch,"FILE","test.html")
wp = curl::perform(ch)
' curl::perform(ch)
curl::finish(ch)
PRINT wp
<html><body><h1>It works!</h1></body></html>
ScriptBasic CGI response to a thinBasic
QOD (Question of the Day) on operator precedence.
Which of the expressions will provide a different answer?
qod1.cgi#! /usr/bin/scriba -c
INCLUDE cgi.bas
cgi::Header(200, "text/html")
cgi::FinishHeader()
PRINT """
<html>
<header>
<title>thinBasic QOD #1</title>
</header>
<body>
<h1>Answer:</h1>
<table border="0" cellpadding="5">
<tr><td>(1)</td><td>""" & ( 45 * ( 9 - 5 + 8 ) - 36 / 4 ) & """</td></tr>
<tr><td>(2)</td><td>""" & ( 45 * ( 9 - ( 5 + 8 ) ) - 36 / 4 ) & """</td></tr>
<tr><td>(3)</td><td>""" & ( 45 * ( 9 - 5 + 8 ) - ( 36 / 4 ) ) & """</td></tr>
<tr><td>(4)</td><td>""" & ( 45 * ( ( 9 - 5 ) + 8 ) - 36 / 4 ) & """</td></tr>
</table>
</body>
</html>
"""
testnt.sbIMPORT nt.bas
PRINT nt::RegRead("HKCU\\SOFTWARE\\SCRIPTBASIC\\DEBUGGER\\"),"\n"
C:\scriptbasic\test>scriba testnt.sb
sdbg
C:\scriptbasic\test>
ScriptBasic 2.2 (Windows 32) Attached