984 lines
35 KiB
Rexx
Executable File
984 lines
35 KiB
Rexx
Executable File
/*----------------------------------------------------------------------------*/
|
|
/* */
|
|
/* Copyright (c) 2007-2019 Rexx Language Association. All rights reserved. */
|
|
/* */
|
|
/* This program and the accompanying materials are made available under */
|
|
/* the terms of the Common Public License v1.0 which accompanies this */
|
|
/* distribution. A copy is also available at the following address: */
|
|
/* https://www.oorexx.org/license.html */
|
|
/* */
|
|
/* Redistribution and use in source and binary forms, with or */
|
|
/* without modification, are permitted provided that the following */
|
|
/* conditions are met: */
|
|
/* */
|
|
/* Redistributions of source code must retain the above copyright */
|
|
/* notice, this list of conditions and the following disclaimer. */
|
|
/* Redistributions in binary form must reproduce the above copyright */
|
|
/* notice, this list of conditions and the following disclaimer in */
|
|
/* the documentation and/or other materials provided with the distribution. */
|
|
/* */
|
|
/* Neither the name of Rexx Language Association nor the names */
|
|
/* of its contributors may be used to endorse or promote products */
|
|
/* derived from this software without specific prior written permission. */
|
|
/* */
|
|
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
|
|
/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
|
|
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
|
|
/* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
|
|
/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
|
|
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
|
|
/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
|
|
/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
|
|
/* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
|
|
/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
|
|
/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
|
/* */
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
/* oorexxtry.rex */
|
|
/*
|
|
What: 21st Century version of Rexxtry
|
|
Who: Lee Peedin
|
|
See documentation for version control
|
|
|
|
10/04/07 Extended fileNameDialog mask for open (*.*)
|
|
10/05/07 Added charout method to sayCatcher class
|
|
Added lineout method to sayCatcher class
|
|
|
|
10/15/07 Directives now work - return values aren't captured
|
|
10/16/07 Added header to copy all
|
|
|
|
11/29/07 Modified ~getText for occasions when lines should not be stripped.
|
|
Place in the incubator
|
|
|
|
04/19/09 Removed deprecated createFont() and replaced it with createFontEx().
|
|
04/19/09 Enhanced the menu to use check marks for font name, size, and silent.
|
|
*/
|
|
|
|
-- Capture the location of our source code program
|
|
discard = locate()
|
|
|
|
parse arg isDefault
|
|
.local~useDefault = .false
|
|
if isDefault~translate = 'DEFAULT' then
|
|
.local~useDefault = .true
|
|
|
|
call LoadEnvironment -- Set up the environment to work with
|
|
code = .oort_dialog~new() -- Create the dialog
|
|
if code~initCode \= 0 then
|
|
do
|
|
call errorDialog 'Error creating code dialog. initCode:' code~initCode
|
|
exit
|
|
end
|
|
say
|
|
say "This console will receive the output of your system commands."
|
|
say "Try 'dir' for example."
|
|
say
|
|
code~execute('ShowTop') -- Execute the dialog
|
|
exit
|
|
|
|
::requires "ooDialog.cls" -- Needed for the dialog
|
|
::requires 'winsystm.cls' -- Needed for the Windows clipboard
|
|
|
|
::class oort_dialog subclass userdialog
|
|
::method init
|
|
self~init:super
|
|
rc = self~create(.dx,.dy,.dwidth,.dheight,.title,'ThickFrame MinimizeBox MaximizeBox')
|
|
self~initCode = (rc=0)
|
|
self~fontMenuHelper
|
|
|
|
::method defineDialog
|
|
expose u menuBar
|
|
u = .dlgAreaU~new(self)
|
|
if .nil \= u~lastError then
|
|
call errorDialog u~lastError
|
|
|
|
---------- Arguments title & dialog area
|
|
at = .dlgArea~new(0,0,u~w,10)
|
|
self~createStaticText(17,at~x,at~y,at~w,at~h,'CENTER','Arguments')
|
|
ad = .dlgArea~new(0,at~y + 10,u~w,u~h('15%'))
|
|
self~createEdit(12,ad~x,ad~y,ad~w,ad~h,'multiline hscroll vscroll','args_data')
|
|
|
|
---------- Code title & dialog area
|
|
ct = .dlgArea~new(0,ad~y + ad~h,u~w,10)
|
|
self~addText(ct~x,ct~y,ct~w,ct~h,'Code','CENTER',18)
|
|
cd = .dlgArea~new(0,ct~y + ct~h,u~w,u~h('40%'))
|
|
self~addEntryLine(13,'code_data',cd~x,cd~y,cd~w,cd~h,'multiline hscroll vscroll')
|
|
|
|
---------- Says title & dialog area
|
|
st = .dlgArea~new(0,cd~y + cd~h,u~w('50%'),10)
|
|
self~createStaticText(19,st~x,st~y,st~w,st~h,'CENTER','Says')
|
|
sd = .dlgArea~new(0,st~y + st~h,u~w('50%'),u~h('43%'))
|
|
self~createEdit(14,sd~x,sd~y,sd~w,sd~h,'notab readonly multiline hscroll vscroll','say_data')
|
|
|
|
---------- Returns title & dialog area
|
|
rt = .dlgArea~new(sd~x + sd~w,cd~y + cd~h,u~w('50%'),10)
|
|
self~createStaticText(20,rt~x,rt~y,rt~w,rt~h,'CENTER','Returns')
|
|
rd = .dlgArea~new(rt~x,st~y + st~h,u~w('50%'),u~h('15%'))
|
|
self~createEdit(15,rd~x,rd~y,rd~w,rd~h,'notab readonly multiline hscroll vscroll','results_data')
|
|
|
|
---------- Errors/Information title & dialog area
|
|
et = .dlgArea~new(rt~x,rd~y + rd~h,u~w('50%'),10)
|
|
self~createStaticText(21,et~x,et~y,et~w,et~h,'CENTER','Errors / Information')
|
|
ed = .dlgArea~new(rt~x,et~y + et~h,u~w('50%'),u~h('17%'))
|
|
self~createEdit(16,ed~x,ed~y,ed~w,ed~h,'notab readonly multiline hscroll vscroll','error_data')
|
|
|
|
---------- Run & Exit buttons for easier execution
|
|
self~createPushButton(80,ed~x ,ed~y + ed~h + 2,35,10,,'&Run','RunIt')
|
|
self~createPushButton(IDCANCEL,ed~x + 40,ed~y + ed~h + 2,35,10,,'E&xit')
|
|
|
|
----------
|
|
menuBar = .UserMenuBar~new(500,0,65)
|
|
|
|
menuBar~addPopup(510, '&File')
|
|
menuBar~addItem(22,'&Run' , ,'RunIt')
|
|
menuBar~addItem(23,'&SaveAs', ,'FileDialog')
|
|
menuBar~addItem(25,'&Open' , ,'FileDialog')
|
|
menuBar~addItem(24,'E&xit' ,'END','Cancel')
|
|
|
|
menuBar~addPopup(520,'&Edit')
|
|
menuBar~addPopup(530,'Font&Name')
|
|
menuBar~addItem(30,'&Lucida Console', ,'onFontMenuClick')
|
|
menuBar~addItem(31,'&Courier New' ,'END','onFontMenuClick')
|
|
menuBar~addSeparator(535)
|
|
menuBar~addPopup(540,'Font&Size','END')
|
|
menuBar~addItem(40,'&8' , ,'onFontMenuClick')
|
|
menuBar~addItem(41,'1&0', ,'onFontMenuClick')
|
|
menuBar~addItem(42,'1&2', ,'onFontMenuClick')
|
|
menuBar~addItem(43,'1&4', ,'onFontMenuClick')
|
|
menuBar~addItem(44,'1&6', ,'onFontMenuClick')
|
|
menuBar~addItem(45,'1&8','END','onFontMenuClick')
|
|
menuBar~addPopup(550,'&Tools')
|
|
menuBar~addPopup(560,'&Copy')
|
|
menuBar~addItem(50,'&Args' , ,'Clipboard')
|
|
menuBar~addItem(51,'&Code' , ,'Clipboard')
|
|
menuBar~addItem(52,'&Says' , ,'ClipBoard')
|
|
menuBar~addItem(53,'&Returns', ,'ClipBoard')
|
|
menuBar~addItem(54,'&Errors' , ,'ClipBoard')
|
|
menuBar~addItem(55,'A&ll' ,'END','ClipBoard')
|
|
menuBar~addSeparator(565)
|
|
menuBar~addPopup(570,'C&lear')
|
|
menuBar~addItem(60,'&Args' , ,'ClearAll')
|
|
menuBar~addItem(61,'&Code' , ,'ClearAll')
|
|
menuBar~addItem(62,'&Says' , ,'ClearAll')
|
|
menuBar~addItem(63,'&Returns', ,'ClearAll')
|
|
menuBar~addItem(64,'&Errors' , ,'ClearAll')
|
|
menuBar~addItem(65,'A&ll' ,'END','ClearAll')
|
|
menuBar~addSeparator(575)
|
|
menuBar~addPopup(580,'&Silent')
|
|
menuBar~addItem(66,'&No' , ,'Silent')
|
|
menuBar~addItem(67,'&Yes' ,'END','Silent')
|
|
menuBar~addSeparator(585)
|
|
menuBar~addPopup(590,'Sa&ve Settings','END')
|
|
menuBar~addItem(72,'Sa&ve' ,'END','SaveSettings')
|
|
menuBar~addPopup(600,'&Help','END')
|
|
menuBar~addItem(71,'Current &Settings', ,'Settings')
|
|
menuBar~addItem(70,'&About' ,'END','Help')
|
|
|
|
if \ menuBar~complete then
|
|
statusText = 'User menu bar completion error:' .SystemErrorCode SysGetErrortext(.SystemErrorCode)
|
|
|
|
::method initDialog unguarded
|
|
expose args_input code_input result_input say_input errors_input menuBar
|
|
-- Use font data from .ini file or defaults if .ini not present yet
|
|
|
|
-- FW_EXTRALIGHT == 200
|
|
d = .Directory~new
|
|
d~weight = 200
|
|
hfont = self~createFontEx(.fontname,.fontsize,d)
|
|
|
|
if menuBar \== .nil then menuBar~attachTo(self)
|
|
|
|
-- Set the font and silent menu item check marks.
|
|
self~setFontMenuChecks
|
|
if .silent then menuBar~check(67)
|
|
else menuBar~check(66)
|
|
|
|
-- Get the controls for all dialog elements that will need to be adjusted
|
|
args_input = self~newEdit(12)
|
|
code_input = self~newEdit(13)
|
|
say_input = self~newEdit(14)
|
|
result_input = self~newEdit(15)
|
|
errors_input = self~newEdit(16)
|
|
args_title = self~newStatic(17)
|
|
code_title = self~newStatic(18)
|
|
say_title = self~newStatic(19)
|
|
result_title = self~newStatic(20)
|
|
errors_title = self~newStatic(21)
|
|
|
|
-- Set the color of the titles
|
|
args_title ~setColor(5,10)
|
|
code_title ~setColor(16,10)
|
|
say_title ~setColor(15,0)
|
|
result_title~setColor(14,0)
|
|
errors_title~setColor(13,10)
|
|
|
|
-- Set the font name/size to the default values
|
|
self~reDraw
|
|
|
|
if \.useDefault then
|
|
do
|
|
-- Read oorexxtry.ini position & size the dialog based on its values
|
|
sd = .application~srcDir
|
|
k1 = SysIni(sd'oorexxtry.ini','oorexxtry','k1')
|
|
k2 = SysIni(sd'oorexxtry.ini','oorexxtry','k2')
|
|
k3 = SysIni(sd'oorexxtry.ini','oorexxtry','k3')
|
|
k4 = SysIni(sd'oorexxtry.ini','oorexxtry','k4')
|
|
if k1 = 'ERROR:' | k2 = 'ERROR:' | k3 = 'ERROR:' | k4 = 'ERROR:' then
|
|
nop -- First exection will not find the ini file
|
|
else
|
|
do
|
|
r = .Rect~new(k1,k2,k3-k1,k4-k2)
|
|
self~setWindowPos(TOP,r)
|
|
self~ensureVisible
|
|
end
|
|
end
|
|
|
|
self~connectResize('onResize', 'sync')
|
|
|
|
-- Run menu option
|
|
::method RunIt
|
|
expose args_input code_input result_input say_input errors_input
|
|
|
|
-- Calculate the center point of the code_input edit control, in screen
|
|
-- co-ordinates.
|
|
r = code_input~clientRect
|
|
centerPoint = .Point~new((r~right - r~left) % 2, (r~bottom - r~top) % 2)
|
|
code_input~client2screen(centerPoint)
|
|
|
|
-- Get and save the current mouse position.
|
|
mouse = .Mouse~new(code_input)
|
|
oldCursorPos = mouse~getCursorPos
|
|
|
|
-- Set the cursor to the busy symbol / move the cursor to our center point
|
|
oldCursor = mouse~wait
|
|
mouse~setCursorPos(centerPoint)
|
|
|
|
arg_array = self~getText(args_input,.true)
|
|
.local~si = say_input
|
|
w1 = code_input~selected~word(1)
|
|
w2 = code_input~selected~word(2)
|
|
code_array = self~getText(code_input,.true)
|
|
if (w1 = .max_length & w2 = .max_length) | (w1 = w2) then
|
|
nop -- we've already loaded our code_array
|
|
else
|
|
do
|
|
code_string = code_array~makeString
|
|
code_array = code_string~substr(w1,w2-w1)~makearray
|
|
end
|
|
|
|
-- Clear any previous error data
|
|
self~error_data = ''
|
|
errors_input~title = self~error_data
|
|
|
|
-- Clear any previous say data
|
|
self~say_data = ''
|
|
say_input~title = self~say_data
|
|
|
|
-- Clear any previous returns data
|
|
self~results_data = ''
|
|
result_input~title = self~results_data
|
|
|
|
.local~emsg = ''
|
|
.local~imsg = ''
|
|
|
|
self~error_data = 'Code Is Executing'
|
|
errors_input~title = self~error_data
|
|
|
|
.local~Error? = .false
|
|
.local~badarg = ''
|
|
-- Interpret each argument so that expressions can be used
|
|
signal on syntax name ArgSyntax
|
|
do i = 1 to arg_array~items
|
|
.local~badarg = i arg_array[i]
|
|
interpret 'arg_array['i'] =' arg_array[i]
|
|
end
|
|
signal off syntax
|
|
|
|
exec = .executor~new('oorexxtry.code',code_array)
|
|
exec~run(arg_array)
|
|
|
|
if .emsg \= '' then
|
|
do
|
|
if \.silent then
|
|
call beep 600,100
|
|
self~error_data = .emsg
|
|
errors_input~title = self~error_data
|
|
self~results_data = ''
|
|
result_input~title = self~results_data
|
|
end
|
|
else
|
|
do
|
|
self~error_data = 'Code Execution Complete'
|
|
errors_input~title = self~error_data
|
|
end
|
|
|
|
if .nil \= .run_results['returns'] then
|
|
do
|
|
self~results_data = .run_results['returns']
|
|
result_input~title = self~results_data
|
|
end
|
|
if \.silent then -- Let the user know when code execution is complete
|
|
call beep 150,150
|
|
|
|
mouse~restoreCursor(oldCursor)
|
|
mouse~setCursorPos(oldCursorPos)
|
|
|
|
self~returnFocus
|
|
return
|
|
|
|
ArgSyntax:
|
|
msg = 'Trapped In'~right(11)'..: ArgSyntax'
|
|
obj = condition('o')
|
|
msg = msg||.endOfLine||'Message'~right(11)'..:' obj['MESSAGE']
|
|
msg = msg||.endOfLine||'ErrorText'~right(11)'..:' obj['ERRORTEXT']
|
|
msg = msg||.endOfLine||'Code'~right(11)'..:' obj['CODE']
|
|
msg = msg||.endOfLine||('Argument' .badarg~word(1))~right(11)'..:' .badarg~subword(2)
|
|
.local~emsg = msg
|
|
if \.silent then
|
|
call beep 600,100
|
|
self~error_data = .emsg
|
|
errors_input~title = self~error_data
|
|
self~results_data = ''
|
|
result_input~title = self~results_data
|
|
.local~emsg = ''
|
|
self~focusItem(12)
|
|
args_input~select(1,1)
|
|
|
|
mouse~restoreCursor(oldCursor)
|
|
mouse~setCursorPos(oldCursorPos)
|
|
return
|
|
|
|
::method cancel
|
|
|
|
r = self~windowRect
|
|
-- Write out the size,position,fontname,fontsize, & silent to the .ini file
|
|
sd = .application~srcDir
|
|
if \self~isMinimized & \self~isMaximized then
|
|
do
|
|
rv = SysIni(sd'oorexxtry.ini','oorexxtry','k1',r~left)
|
|
rv = SysIni(sd'oorexxtry.ini','oorexxtry','k2',r~top)
|
|
rv = SysIni(sd'oorexxtry.ini','oorexxtry','k3',r~right)
|
|
rv = SysIni(sd'oorexxtry.ini','oorexxtry','k4',r~bottom)
|
|
end
|
|
rv = SysIni(sd'oorexxtry.ini','oorexxtry','fn',.fontname)
|
|
rv = SysIni(sd'oorexxtry.ini','oorexxtry','fs',.fontsize)
|
|
rv = SysIni(sd'oorexxtry.ini','oorexxtry','sl',.silent)
|
|
return self~ok:super
|
|
|
|
-- Clipboard menu option
|
|
::method ClipBoard
|
|
expose args_input errors_input code_input say_input result_input
|
|
use arg msg, args
|
|
cp = .WindowsClipBoard~new
|
|
select
|
|
when msg = 50 then
|
|
do
|
|
cp_array = self~getText(args_input,.false)
|
|
cp_string = cp_array~makestring
|
|
cp~copy(cp_string)
|
|
.local~imsg = 'Arguments Are On ClipBoard'
|
|
end
|
|
when msg = 51 then
|
|
do
|
|
cp_array = self~getText(code_input,.false)
|
|
cp_string = cp_array~makestring
|
|
cp~Copy(cp_string)
|
|
.local~imsg = 'Code Is On ClipBoard'
|
|
end
|
|
when msg = 52 then
|
|
do
|
|
cp_array = self~getText(say_input,.false)
|
|
cp_string = cp_array~makestring
|
|
cp~copy(cp_string)
|
|
.local~imsg = 'Says Are On The ClipBoard'
|
|
end
|
|
when msg = 53 then
|
|
do
|
|
cp_array = self~getText(result_input,.false)
|
|
cp_string = cp_array~makestring
|
|
cp~Copy(cp_string)
|
|
.local~imsg = 'Returns Are On ClipBoard'
|
|
end
|
|
when msg = 54 then
|
|
do
|
|
cp_array = self~getText(errors_input,.false)
|
|
cp_string = cp_array~makestring
|
|
cp~copy(cp_string)
|
|
.local~imsg = 'Errors Are On ClipBoard'
|
|
end
|
|
when msg = 55 then
|
|
do
|
|
allData = 'The Following Output Was Generated With ooRexxTry'.endOfLine||.endOfLine
|
|
cp_array = self~getText(args_input,.false)
|
|
cp_string = cp_array~makestring
|
|
allData = alldata||'Arguments'||.endOfLine||cp_string||.endOfLine||'-'~copies(20)||.endOfLine
|
|
|
|
cp_array = self~getText(code_input,.false)
|
|
cp_string = cp_array~makestring
|
|
allData = allData||'Code'||.endOfLine||cp_string||.endOfLine||'-'~copies(20)||.endOfLine
|
|
|
|
cp_array = self~getText(say_input,.false)
|
|
cp_string = cp_array~makestring
|
|
allData = allData||'Says'||.endOfLine||cp_string||.endOfLine||'-'~copies(20)||.endOfLine
|
|
|
|
cp_array = self~getText(result_input,.false)
|
|
cp_string = cp_array~makestring
|
|
allData = allData||'Results'||.endOfLine||cp_string||.endOfLine||'-'~copies(20)||.endOfLine
|
|
|
|
cp_array = self~getText(errors_input,.false)
|
|
cp_string = cp_array~makestring
|
|
allData = allData||'Errors/Information'||.endOfLine||cp_string||.endOfLine||'-'~copies(20)||.endOfLine
|
|
|
|
cp~copy(allData)
|
|
.local~imsg = 'All Data Is On ClipBoard'
|
|
end
|
|
otherwise
|
|
nop
|
|
end
|
|
self~error_data = .imsg
|
|
errors_input~title = self~error_data
|
|
self~returnFocus
|
|
|
|
-- Code2File menu option
|
|
::method FileDialog
|
|
expose code_input errors_input
|
|
use arg msg, args
|
|
if msg = 23 then
|
|
do
|
|
c_array = self~getText(code_input,.false)
|
|
c_string = c_array~makestring
|
|
action = 'S'
|
|
dtitle = 'ooRexxTry File Save'
|
|
end
|
|
else
|
|
do
|
|
action = 'L'
|
|
dtitle = 'ooRexxTry File Open'
|
|
end
|
|
|
|
delimiter = '0'x
|
|
filemask = 'ooRexx Files (*.rex)'delimiter'*.rex'delimiter||-
|
|
'All Files (*.*)'delimiter'*.*'delimiter
|
|
handle = self~getSelf
|
|
a_file = FileNameDialog(.preferred_path,handle,filemask,action,dtitle,'.rex')
|
|
if a_file \= 0 then
|
|
do
|
|
ostream = .stream~new(a_file)
|
|
if msg = 23 then
|
|
do
|
|
ostream~open('Write Replace')
|
|
ostream~lineout(c_string)
|
|
ostream~close
|
|
.local~imsg = 'Code Saved As' a_file
|
|
self~error_data = .imsg
|
|
errors_input~title = self~error_data
|
|
end
|
|
else
|
|
do
|
|
oarray = ostream~charin(,ostream~chars)~makearray
|
|
ostream~close
|
|
mycode = ''
|
|
do i = 1 to oarray~items
|
|
mycode = mycode||oarray[i]
|
|
if i < oarray~items then
|
|
mycode = mycode||.endOfLine
|
|
end
|
|
self~code_data = mycode
|
|
code_input~title = self~code_data
|
|
|
|
.local~imsg = 'Code From' a_file 'In Code Dialog'
|
|
self~error_data = .imsg
|
|
errors_input~title = self~error_data
|
|
end
|
|
end
|
|
self~returnFocus
|
|
|
|
-- ClearAll menu option
|
|
::method ClearAll
|
|
expose args_input code_input result_input say_input errors_input
|
|
use arg msg, args
|
|
select
|
|
when msg = 60 then
|
|
do
|
|
self~args_data = ''
|
|
args_input~title = self~args_data
|
|
end
|
|
when msg = 61 then
|
|
do
|
|
self~code_data = ''
|
|
code_input~title = self~code_data
|
|
end
|
|
when msg = 62 then
|
|
do
|
|
self~say_data = ''
|
|
say_input~title = self~say_data
|
|
end
|
|
when msg = 63 then
|
|
do
|
|
self~results_data = ''
|
|
result_input~title = self~results_data
|
|
end
|
|
when msg = 64 then
|
|
do
|
|
self~error_data = ''
|
|
errors_input~title = self~error_data
|
|
end
|
|
when msg = 65 then
|
|
do
|
|
self~args_data = ''
|
|
args_input~title = self~args_data
|
|
|
|
self~code_data = ''
|
|
code_input~title = self~code_data
|
|
|
|
self~results_data = ''
|
|
result_input~title = self~results_data
|
|
|
|
self~say_data = ''
|
|
say_input~title = self~say_data
|
|
|
|
self~error_data = ''
|
|
errors_input~title = self~error_data
|
|
end
|
|
otherwise
|
|
nop
|
|
end
|
|
self~returnFocus
|
|
|
|
::method Silent
|
|
expose menuBar
|
|
use arg msg, args
|
|
select
|
|
when msg = 66 then do
|
|
.local~silent = .false
|
|
menuBar~check(66)
|
|
menuBar~unCheck(67)
|
|
end
|
|
when msg = 67 then do
|
|
.local~silent = .true
|
|
menuBar~check(67)
|
|
menuBar~unCheck(66)
|
|
end
|
|
otherwise
|
|
nop
|
|
end
|
|
self~returnFocus
|
|
|
|
::method SaveSettings
|
|
use arg msg, args
|
|
|
|
r = self~windowRect
|
|
select
|
|
when msg = 72 then
|
|
do
|
|
sd = .application~srcDir
|
|
if \self~isMinimized & \self~isMaximized then
|
|
do
|
|
rv = SysIni(sd'oorexxtry.ini','oorexxtry','k1',r~left)
|
|
rv = SysIni(sd'oorexxtry.ini','oorexxtry','k2',r~top)
|
|
rv = SysIni(sd'oorexxtry.ini','oorexxtry','k3',r~right)
|
|
rv = SysIni(sd'oorexxtry.ini','oorexxtry','k4',r~bottom)
|
|
end
|
|
rv = SysIni(sd'oorexxtry.ini','oorexxtry','fn',.fontname)
|
|
rv = SysIni(sd'oorexxtry.ini','oorexxtry','fs',.fontsize)
|
|
rv = SysIni(sd'oorexxtry.ini','oorexxtry','sl',.silent)
|
|
end
|
|
otherwise
|
|
nop
|
|
end
|
|
self~returnFocus
|
|
|
|
::method ReturnFocus
|
|
expose code_input
|
|
w1 = code_input~selected~word(1)
|
|
w2 = code_input~selected~word(2)
|
|
code_array = self~getText(code_input,.true)
|
|
if w1 = .max_length & w2 = .max_length then
|
|
do
|
|
sel_start = .max_length
|
|
sel_end = .max_length
|
|
end
|
|
else
|
|
do
|
|
sel_start = w1
|
|
sel_end = w2
|
|
end
|
|
self~focusItem(13)
|
|
code_input~select(sel_start,sel_end)
|
|
|
|
-- Method to handle all the resizing
|
|
::method onResize
|
|
expose u
|
|
use arg dummy,sizeinfo
|
|
u~resize(self,sizeinfo)
|
|
|
|
::method Help
|
|
expose code_input u
|
|
handle = self~getSelf
|
|
parse value self~GetWindowRect(handle) with var1 var2 var3 var4
|
|
.local~dw = (var3 - var1) / self~factorX
|
|
.local~dh = (var4 - var2) / self~factorY
|
|
|
|
parse value self~GetPos with dx dy
|
|
.local~dx = dx
|
|
.local~dy = dy
|
|
|
|
help = .help_dialog~new()
|
|
if help~initCode \= 0 then
|
|
do
|
|
call errorDialog 'Error creating help dialog. initCode:' help~initCode
|
|
exit
|
|
end
|
|
help~execute('ShowTop')
|
|
|
|
::method Settings
|
|
expose code_input u
|
|
handle = self~getSelf
|
|
parse value self~getWindowRect(handle) with var1 var2 var3 var4
|
|
.local~dw = (var3 - var1) / self~factorX
|
|
.local~dh = (var4 - var2) / self~factorY
|
|
|
|
parse value self~getPos with dx dy
|
|
.local~dx = dx
|
|
.local~dy = dy
|
|
|
|
settings = .settings_dialog~new()
|
|
if settings~initCode \= 0 then
|
|
do
|
|
call errorDialog 'Error creating help dialog. initCode:' settings~initCode
|
|
exit
|
|
end
|
|
settings~execute('ShowTop')
|
|
|
|
-- Redraw applicable areas of the dialog based on the font menu choice
|
|
::method ReDraw
|
|
expose args_input code_input say_input result_input errors_input
|
|
|
|
-- FW_EXTRALIGHT == 200
|
|
d = .Directory~new
|
|
d~weight = 200
|
|
hfont = self~createFontEx(.fontname,.fontsize,d)
|
|
args_input ~setFont(hfont)
|
|
code_input ~setFont(hfont)
|
|
say_input ~setFont(hfont)
|
|
result_input~setFont(hfont)
|
|
errors_input~setFont(hfont)
|
|
|
|
::method getText
|
|
use arg the_input,stripIt
|
|
iarray = .array~new()
|
|
max_length = 0
|
|
do i = 1 to the_input~lines
|
|
if stripIt then
|
|
do
|
|
if the_input~getLine(i)~strip() \= '' then
|
|
do
|
|
iarray~append(the_input~getLine(i))
|
|
max_length += iarray[iarray~last]~length
|
|
end
|
|
end
|
|
else
|
|
do
|
|
iarray~append(the_input~getLine(i))
|
|
max_length += iarray[iarray~last]~length
|
|
end
|
|
end
|
|
.local~max_length = max_length + 1
|
|
return iarray
|
|
|
|
-- This method is invoked whenever the user clicks on one of the font menu items.
|
|
-- The first arg to the method is the resource id of the menu id that was clicked.
|
|
::method onFontMenuClick
|
|
expose fontMenuIDs
|
|
use arg id
|
|
|
|
-- Map the menu item id to a font setting. Could be size of name.
|
|
item = fontMenuIDs~index(id)
|
|
|
|
-- If item is a number, then it is a font size menu item, otherwis a font name.
|
|
if item~datatype('W') then .local~fontSize = item
|
|
else .local~fontname = item
|
|
|
|
-- Reset the menu item check marks and redraw in the new font.
|
|
self~setFontMenuChecks
|
|
self~reDraw
|
|
|
|
-- This method sets the appropriate font menu item check state. Checked for selected
|
|
-- and unchecked for unselected.
|
|
::method setFontMenuChecks private
|
|
expose fontMenuIDs menuBar
|
|
|
|
-- Iterate over all items in the table unchecking each menu item. Brute force,
|
|
-- but easy, and there are not many items. The alternative is to keep track of
|
|
-- which items are checked and uncheck / check the correct ones.
|
|
do id over fontMenuIDs~allItems
|
|
menuBar~unCheck(id)
|
|
end
|
|
|
|
-- Now check the menu item that matches what font name and size is currently
|
|
-- in use.
|
|
menuBar~check(fontMenuIDs[.fontname])
|
|
menuBar~check(fontMenuIDs[.fontsize])
|
|
|
|
-- A private help method that sets up things to make working with the font menu easier
|
|
::method fontMenuHelper private
|
|
expose fontMenuIDs
|
|
|
|
-- Create a table that maps menu item IDs to the matching font setting. Since
|
|
-- the Table class has the index() method, the mapping works both ways.
|
|
fontMenuIDs = .Table~new
|
|
fontMenuIDs["Lucida Console"] = 30
|
|
fontMenuIDs["Courier New"] = 31
|
|
|
|
fontMenuIDs[ 8] = 40
|
|
fontMenuIDs[10] = 41
|
|
fontMenuIDs[12] = 42
|
|
fontMenuIDs[14] = 43
|
|
fontMenuIDs[16] = 44
|
|
fontMenuIDs[18] = 45
|
|
|
|
-- Class that dynamically creates a method to take the arguments and execute the code
|
|
::class executor public
|
|
::method init
|
|
expose rt_routine
|
|
use arg routine_name,code
|
|
.local~Error? = .false
|
|
signal on syntax name ExecSyntax
|
|
rt_routine = .routine~new(routine_name, code)
|
|
return
|
|
|
|
-- Syntax trap similiar to rexxc.exe
|
|
ExecSynTax:
|
|
msg = 'Trapped In'~right(11)'..: ExecSyntax'
|
|
obj = condition('o')
|
|
msg = msg||.endOfLine||'Message'~right(11)'..:' obj['MESSAGE']
|
|
msg = msg||.endOfLine||'ErrorText'~right(11)'..:' obj['ERRORTEXT']
|
|
msg = msg||.endOfLine||'Code'~right(11)'..:' obj['CODE']
|
|
msg = msg||.endOfLine||'Line #'~right(11)'..:' obj['POSITION']
|
|
.local~emsg = msg
|
|
.local~Error? = .true
|
|
return
|
|
|
|
-- Method that actually runs our code
|
|
::method run
|
|
expose rt_routine say_string
|
|
signal on syntax name RunSyntax
|
|
.local~run_results = .directory~new
|
|
.local~say_stg = ''
|
|
my_result = ''
|
|
if \.Error? then
|
|
do
|
|
-- Redirect STDOUT for say statements
|
|
scrnOut = .SayCatcher~New('STDOUT')~~Command('open write nobuffer')
|
|
theSayMonitor = .monitor~New(scrnOut)
|
|
.output~destination(theSayMonitor)
|
|
-- Run the Code
|
|
args = arg(1)
|
|
rt_routine~callWith(args)
|
|
-- Test if there was anything returned by the code
|
|
if symbol('result') = 'VAR' then
|
|
my_result = result
|
|
-- Load the says and returns into environment variables for updating the dialog areas
|
|
.local~run_results['returns'] = my_result
|
|
-- Redirect STDOUT back to what it was (probably the screen)
|
|
.output~Destination()
|
|
end
|
|
return .run_results
|
|
|
|
-- Syntax trap for errors in the code
|
|
RunSyntax:
|
|
msg = 'Trapped In'~right(11)'..: RunSyntax'
|
|
obj = condition('o')
|
|
msg = msg||.endOfLine||'Message'~right(11)'..:' obj['MESSAGE']
|
|
msg = msg||.endOfLine||'ErrorText'~right(11)'..:' obj['ERRORTEXT']
|
|
msg = msg||.endOfLine||'Code'~right(11)'..:' obj['CODE']
|
|
msg = msg||.endOfLine||'Line #'~right(11)'..:' obj['POSITION']
|
|
.local~emsg = msg
|
|
return
|
|
|
|
-- Class to "catch" all say,charout,lineout statements in the code
|
|
-- Will not catch charout & lineout if the first argument is supplied
|
|
::class SayCatcher subclass stream
|
|
::method say
|
|
use arg input
|
|
.local~say_stg = .say_stg||input||.endOfLine
|
|
.si~title = .say_stg
|
|
return
|
|
|
|
::method charout
|
|
use arg input
|
|
.local~say_stg = .say_stg||input
|
|
.si~title = .say_stg
|
|
return 0
|
|
|
|
::method lineout
|
|
use arg input
|
|
.local~say_stg = .say_stg||input||.endOfLine
|
|
.si~title = .say_stg
|
|
return 0
|
|
|
|
|
|
::class help_dialog subclass userdialog
|
|
::method init
|
|
self~init:super
|
|
lp = (.dx + (.dw / 2) - 50)~format( , 0)
|
|
tp = (.dy + (.dh / 2) - 30)~format( , 0)
|
|
rc = self~create(lp,tp,100,60,.title,"THICKFRAME")
|
|
self~initCode = (rc=0)
|
|
|
|
::method defineDialog
|
|
expose h sizing
|
|
h = .dlgAreaU~new(self)
|
|
if .nil \= h~lastError then
|
|
call errorDialog h~lastError
|
|
h~updateOnResize = .false
|
|
sizing = .false
|
|
|
|
vt = .dlgArea~new(h~x,0,h~w,10)
|
|
self~createStaticText(20,vt~x,vt~y,vt~w,vt~h,'CENTER','Version')
|
|
vd = .dlgArea~new(h~x,vt~y + vt~h,h~w,10)
|
|
self~createStaticText(21,vd~x,vd~y,vd~w,vd~h,'CENTER',.version)
|
|
|
|
at = .dlgArea~new(h~x,vd~y + vd~h,h~w,10)
|
|
self~createStaticText(22,at~x,at~y,at~w,at~h,'CENTER','Author')
|
|
ad = .dlgArea~new(h~x,at~y + at~h,h~w,10)
|
|
self~createStaticText(23,ad~x,ad~y,ad~w,ad~h,'CENTER','Lee Peedin')
|
|
|
|
dt = .dlgArea~new(h~x,ad~y + ad~h,h~w,10)
|
|
self~createStaticText(24,dt~x,dt~y,dt~w,dt~h,'CENTER','Documentation')
|
|
dd = .dlgArea~new(h~x,dt~y + dt~h,h~w,10)
|
|
self~createPushButton(25,dd~x,dd~y,dd~w,10,,'&PDF','Help')
|
|
|
|
::method initDialog unguarded
|
|
v_title = self~newStatic(20)
|
|
a_title = self~newStatic(22)
|
|
d_title = self~newStatic(24)
|
|
|
|
v_title~setColor(5,10)
|
|
a_title~setColor(5,10)
|
|
d_title~setColor(5,10)
|
|
|
|
self~connectResize('onResize', 'sync')
|
|
self~connectSizeMoveEnded('onSizeMoveEnded')
|
|
|
|
::method help
|
|
-- The help doc is supposed to be in the 'doc' subdirectory, but we will also check the
|
|
-- current directory, then the Rexx home directory.
|
|
if SysFileExists('doc\ooRexxTry.pdf') then do
|
|
helpDoc = 'doc\ooRexxTry.pdf'
|
|
end
|
|
else if SysFileExists('ooRexxTry.pdf') then do
|
|
helpDoc = 'ooRexxTry.pdf'
|
|
end
|
|
else if SysfileExists(value("REXX_HOME",,"ENVIRONMENT")||"\doc\ooRexxTry.pdf") then do
|
|
helpDoc = value("REXX_HOME",,"ENVIRONMENT")||"\doc\ooRexxTry.pdf"
|
|
end
|
|
else do
|
|
msg = "The ooRexxTry.pdf help documentation could not be located." || .endOfLine -
|
|
|| .endOfLine || -
|
|
"Tried:" || .endOfLine -
|
|
" doc subdirectory: "||directory()||"\doc\ooRexxTry.pdf" || .endOfLine -
|
|
" current directory: "||directory()||"\ooRexxTry.pdf" || .endOfLine -
|
|
" Rexx home: "||value("REXX_HOME",,"ENVIRONMENT")||"\doc\ooRexxTry.pdf" || .endOfLine -
|
|
|| .endOfLine || -
|
|
"Sorry, no help is available"
|
|
title = 'ooRexx Try for the 21st Century - Error'
|
|
j = MessageDialog(msg, self~hwnd, title, 'Ok', 'WARNING')
|
|
return
|
|
end
|
|
'start "ooRexxTry Online Documentation"' '"'||helpDoc||'"'
|
|
|
|
::method onResize unguarded
|
|
expose h sizing
|
|
use arg sizingType, sizeinfo
|
|
|
|
sizing = .true
|
|
h~resize(self, sizeinfo)
|
|
|
|
::method onSizeMoveEnded unguarded
|
|
expose sizing
|
|
|
|
-- If we were resizing, force the dialog controls to redraw themselves.
|
|
if sizing then self~update
|
|
|
|
-- We are not resizing anymore.
|
|
sizing = .false
|
|
return 0
|
|
|
|
|
|
::class settings_dialog subclass userdialog
|
|
::method Init
|
|
self~init:super
|
|
lp = (.dx + (.dw / 2) - 50)~format( , 0)
|
|
tp = (.dy + (.dh / 2) - 30)~format( , 0)
|
|
rc = self~Create(lp,tp,100,60,.title)
|
|
self~InitCode = (rc=0)
|
|
|
|
::method DefineDialog
|
|
expose h
|
|
h = .dlgAreaU~new(self)
|
|
if .nil \= h~lastError then
|
|
call errorDialog h~lastError
|
|
vt = .dlgArea~new(h~x,0,h~w,10)
|
|
self~addText(vt~x,vt~y,vt~w,vt~h,'Font Name','CENTER',20)
|
|
vd = .dlgArea~new(h~x,vt~y + vt~h,h~w,10)
|
|
self~addText(vd~x,vd~y,vd~w,vd~h,.fontname,'CENTER',21)
|
|
|
|
at = .dlgArea~new(h~x,vd~y + vd~h,h~w,10)
|
|
self~addText(at~x,at~y,at~w,at~h,'Font Size','CENTER',22)
|
|
ad = .dlgArea~new(h~x,at~y + at~h,h~w,10)
|
|
self~addText(ad~x,ad~y,ad~w,ad~h,.fontsize,'CENTER',23)
|
|
|
|
dt = .dlgArea~new(h~x,ad~y + ad~h,h~w,10)
|
|
self~addText(dt~x,dt~y,dt~w,dt~h,'Silent','CENTER',24)
|
|
dd = .dlgArea~new(h~x,dt~y + dt~h,h~w,10)
|
|
self~addText(dd~x,dd~y,dd~w,dd~h,.silent,'CENTER',23)
|
|
|
|
::method InitDialog
|
|
v_title = self~newStatic(20)
|
|
a_title = self~newStatic(22)
|
|
d_title = self~newStatic(24)
|
|
|
|
v_title~setColor(14,0)
|
|
a_title~setColor(14,0)
|
|
d_title~setColor(14,0)
|
|
|
|
::routine LoadEnvironment
|
|
.local~px = ScreenSize()[3]
|
|
.local~py = ScreenSize()[4]
|
|
|
|
-- Establish dialog area sizes based of the user's screen resolution - will only be used for the first
|
|
-- execution - from then on data is retrieved from the .ini file, unless user specifies default as an
|
|
-- execution argument from the command line
|
|
.local~dwidth = ((.px / 2.5) * .65)~format(,0)
|
|
.local~dheight = ((.py / 2.5) * .65)~format(,0)
|
|
.local~dx = 0
|
|
.local~dy = 0
|
|
|
|
|
|
-- Need a few generic variables
|
|
.local~version = '1.0' -- Internal version control
|
|
.local~preferred_path = '' -- Default starting path for Save As dialog - will be either
|
|
-- the folder ooRexxTry is executed from or the last folder that
|
|
-- was accessed using the Windows File Dialog
|
|
.local~title = 'ooRexxTry' -- Title to use for the dialogs
|
|
|
|
-- If the .ini file is present, use it for font/silent variables
|
|
sd = .application~srcDir
|
|
.local~fontname = SysIni(sd'oorexxtry.ini','oorexxtry','fn')
|
|
.local~fontsize = SysIni(sd'oorexxtry.ini','oorexxtry','fs')
|
|
.local~silent = SysIni(sd'oorexxtry.ini','oorexxtry','sl')
|
|
|
|
-- Else use some defaults
|
|
if .fontname = 'ERROR:' | .useDefault then
|
|
.local~fontname = 'Lucida Console'
|
|
if .fontsize = 'ERROR:' | .useDefault then
|
|
.local~fontsize = 12
|
|
if .silent = 'ERROR:' | .useDefault then
|
|
.local~silent = .false
|
|
return
|
|
|
|
|
|
|