Menu

#49 Improvements [r876]

Unstable_(example)
open
None
5
2017-05-13
2017-05-13
No

Hi Jim,

Below are some fixes and improvements.
I hope you find useful.


COMPILE WARNINGS

Below is Color Picker by UglyMike.
Do this: Run/Stop/Run/Stop/Run/Stop and look at the editor window.
For each COMPILE WARNING the editor window is scrolled to the warning line.

Implementation:
In Debug mode: It is useless to follow each warning in editor window because the editor window will go to line 1 after compiling.
In Run mode: Only the first COMPILE WARNING is followed by goToLine() to alow user to follow those in order of appearance.

print "Color Picker - Proof of concept for GUI program by M. Vilain"
clg
# Load graphical elements
spritedim 3
spritepoly 0, {0,0,10,0,10,20,0,20}
spritepoly 1, {0,0,10,0,10,20,0,20}
spritepoly 2, {0,0,10,0,10,20,0,20}
# Color background
color grey
rect 0,0,299,299
#color mixer
# upper-left identation
color darkgrey
poly {10,10,10,180,210,10}
poly {38,193,38,212,72,193}
poly {98,193,98,212,132,193}
poly {158,193,158,212,192,193}
# lower-right identation
color 200,200,200
poly {10,179,210,10,210,179}
poly {38,213,72,193,72,213}
poly {98,213,132,193,132,213}
poly {158,213,192,193,192,213}
# RGB canvas elements
color black
rect 13,13,195,164
rect 40,195, 30,15
rect 100,195, 30,15
rect 160,195, 30,15
#slider headers
color red
rect 218,5,20, 10
color green
rect 244,5,20, 10
color blue
rect 270,5,20, 10
# Place & show sliders
color darkgrey
rect 225,20, 4,270
rect 250,20, 4,270
rect 275,20, 4,270
color 200,200,200
rect 229,20, 4,270
rect 254,20, 4,270
rect 279,20, 4,270
color black
line 229,20,229,287
line 228,20,228,287
line 254,20,254,287
line 253,20,253,287
line 279,20,279,287
line 278,20,278,287
spriteplace 0,230,27
spriteplace 1,255,27
spriteplace 2,280,27
spriteshow 0
spriteshow 1
spriteshow 2
#define counters for saving 10 colors
nextcolor=0
nextrow=0
mclick=0
#draw color slots (2 rows of 5 elements)
for i = 0 to 1
    for j = 0 to 4
        # upper-left identation
        color darkgrey
        poly {10+j*24,240+i*24,10+j*24, 264+i*24,34+j*24, 240+i*24}
        # lower-right identation
        color 190,190,190
        poly {10+j*24,265+i*24,34+j*24, 240+i*24,34+j*24, 265+i*24}
        # RGB canvas elements
        color black
        rect 12+j*24,242+i*24,20,20
    next j
next i
# Show Copy button
color 200,200,200
poly {143,248, 143, 282,207 ,248}
color darkgrey
poly {143, 282,207 ,282,207,248}
color grey
rect 147, 251, 57,28
color black
font "Tahoma",10,100
text 158,255,"Copy"
# initialize color values
rood=0
blauw=0
groen=0
#here the real work starts....
loop:
# is the mouse on the red slider?
if mousex > 220 and mousex < 240 then
    while mouseb=1
        if mousey < 27 then
            place=27
        else
            if mousey > 282 then
                place=282
            else
                place=mousey
                rood=mousey-27
            end if
        end if
        spriteplace 0,230,place
        pause 0.01
        gosub drwcolor
    end while
else
    # is the mouse on the blue slider?
    if mousex > 245 and mousex < 265 then
        while mouseb=1
            if mousey < 27 then
                place=27
            else
                if mousey > 282 then
                    place=282
                else
                    place=mousey
                    blauw=mousey-27
                end if
            end if
            spriteplace 1,255,place
            pause 0.01
            gosub drwcolor
        end while
    else
        # is the mouse on the green slider?
        if mousex > 270 and mousex < 290 then
            while mouseb=1
                if mousey < 27 then
                    place=27
                else
                    if mousey > 282 then
                        place=282
                    else
                        place=mousey
                        groen=mousey-27
                    end if
                end if
                spriteplace 2,280,place
                pause 0.01
                gosub drwcolor
            end while
        endif
    endif
endif
#did we click on the Copy button?
if clickb=1 then
    if mousex > 143 and mousex < 208 then
        if mousey > 248 and mousey < 280 then
            mclick=1
            # Show Copy button pressed
            color darkgrey
            poly {143,248, 143, 282,207 ,248}
            color 200,200,200
            poly {143, 282,207 ,282,207,248}
            color grey
            rect 147, 251, 57,28
            color black
            font "Tahoma",10,100
            text 159,256,"Copy"
            color rood,blauw,groen
            rect 12+nextcolor*24,242+nextrow*24,20,20
            nextcolor=nextcolor+1
            if nextcolor=5 then
                if nextrow = 1 then
                    nextcolor=0
                    nextrow=0
                else
                    nextcolor=0
                    nextrow=1
                endif
            endif
            pause 0.2
        end if
    endif
endif
clickclear
if mclick=1 then
    # Show Copy button
    color 200,200,200
    poly {143,248, 143, 282,207 ,248}
    color darkgrey
    poly {143, 282,207 ,282,207,248}
    color grey
    rect 147, 251, 57,28
    color black
    font "Tahoma",10,100
    text 158,255,"Copy"
    mclick=0
endif
goto loop
drwcolor:
if rood > 255 then rood = 255
if groen > 255 then groen = 255
if blauw > 255 then blauw = 255
if rood < 0 then rood = 0
if groen < 0 then groen = 0
if blauw < 0 then blauw = 0
# individual color elements
color rood,blauw,groen
rect 13,13,195,164
color rood,0,0
rect 40,195, 30,15
color 0,blauw,0
rect 100,195, 30,15
color 0,0,groen
rect 160,195, 30,15
#numeric representation
color grey
rect 39,213, 160,20
color black
font "Tahoma",10,100
text 49,213,rood
font "Tahoma",10,100
text 106,213,blauw
font "Tahoma",10,100
text 166,213,groen
return

Fix debug crash

Go to "Preferences" panel and set debugging speed to Fast (1 ms).
Run program above in debug mode. Now press Run to button.
Let it run for a while and try to stop it.
It will crash.
Implementation: fixed


Preferences panel - lack of memory

Open and close preferences window and watch memory allocation. There is a lack of memory.
Implementation: fixed


Preferences panel - multiple instances

Open preferences window but do not close it. Open another preferences window. You can open any number of preferences panels.
Implementation: fixed


Preferences panel remains open

Open preferences panel and do not close it.
Run a program.
Preferences window is still open...
Implementation: fixed


Preferences-Advanced-SETTINGS

First: SETSETTING and GETSETTING are some of my favorites statements. Those simple statements allow for example to save the top scores for a game! :)
There was an option in Preferences panel: Allow GETSETTING/SETSETTING statements. If it was not checked the program stops in case of SETSETTING / GETSETTING statemets. So if you did not trust a program you could not even see what it was doing.
Ironically, to see what such a program does, the user had to give it access to these commands.

So I change this option to: Allow programs to use persistent settings (SETSETTING statement)
If it is unchecked then programs will set/get settings from a virtual/fake settings system. This is transparent for programs so no error message will be displayed. This allows programs to run normally, even if user do not want to let tracks or do not trust programs. All volatile settings will be accessible for entire session, so if user runs programs in the same session, then settings will remain accessible for other programs till the end of the BASIC256 session.

Add security levels for SETTINGS in Preference panel GETSETTING/SETSETTING access level
1) Full access (get/set) to settings. Program can set or get settings using different program names.
2) Get any settings / set only owned settings. Program can read any settings from any program but can set only for a single program name (first program name used by SETSETTING).
3) Get / set only owned settings. This is default option. Program can read/write settings for a single program (first program name used by SETSETTING/GETSETTING))

Two error messages have been added:
"The program does not have permission to read settings from other program. Check access level from 'Preferences' panel"
"The program does not have permission to write settings for other program. Check access level from 'Preferences' panel"

Add option Max number of settings for each program so user can limit the number of keys that a program can save (to avoid abuse). The default limit is 100 keys (which is quite enough).

Add a new button Clear all persistent settings to clear all saved pesistent settings.

Add Browse persistent settings button which launches a nice browser to browse/delete persistent settings


Using SETSETTING/GETSETTING is now secured. Check below the behaviour!

1) Program name and key name cannot be empty anymore.

2) The Windows system registry has the following limitations: A subkey may not exceed 255 characters, an entry's value may not exceed 16,383 characters. So, program name and key name for settings may not exceed 255 characters. Also saved value may not exceed 16,383 characters to fit Windows limitations.

3) Slashes ('/' and '\') are forbidden in program name or key names to avoid creating subgroups (On windows '\' are converted by QSettings to '/', which makes them identical).
The only place that slash is allowed is when user read a BASIC256 setting:

print getsetting("SYSTEM", "Main/Font")

4) Program name "SYSTEM" is reserved for getting BASIC256 settings and it is forbidden to be used with SETSETTING.
Because BASIC256 settings are read-only, user cannot use SETSETTING to change those settings. So SETSETTING "SYSTEM", "key", "value" will not work anymore because settings saved in this way could not be read anyway.

If you run program below in previous version you will get empty value every time because SETSETTING is actually save key value for a program named "SYSTEM" and GETSETTING read BASIC256 system key instead of saved key.

setsetting "SYSTEM", "key", "value"
print getsetting("SYSTEM", "key")

5) Now it's possible for the user to delete a key by setting value to an empty one.

setsetting "myprog", "mykey", "blabla"
print getsetting("myprog", "mykey")
setsetting "myprog", "mykey", "" #delete key
print getsetting("myprog", "mykey")

6) Safe password
If you run this program you can get the MD5 password

print getsetting("SYSTEM", "Pref/Password/")

But this is wrong because MD5 can be broken. For example, if I set a password even a beginner user can get the hash (202cb962ac59075b964b07152d234b70) and he can find easy the password on web. Try it: https://crackstation.net/

Implementation: User receive a fake password "****" when try to read it and an empty one if there is no password set.


SetSetting (Statement)

Format

setsetting program_name, setting_key_name, string_expression
setsetting ( program_name, setting_key_name, string_expression )

Description

Save a string_expression to the system registry (or other persistent storage). The program_name and setting_key_name are used to categorize and to make sure that settings accessed when needed and not accidentally changed by another program.

If "Allow programs to use persistent settings (SETSETTING statement)" option from 'Preferences' panel is checked, then the saved value will be available to other BASIC-256 programs and should remain available for an extended period. Otherwise saved values will be avaiable only for current BASIC256 session (till BASIC256 is closed). After this those settings will be lost.

Rules for names:
Program name and key name cannot be empty.
Program name and key name may not exceed 255 characters.
Do not use slashes ('/' and '\') in program name or key names.
Program name "SYSTEM" is reserved for getting BASIC256 settings. BASIC256 settings are read-only so user cannot use SETSETTING to change those settings. This is possible only from 'Preferences' panel.
Failure to comply with any of the above rules will generate an error message: "Invalid program name" or "Invalid key name".

Also string_expression may not exceed 16,383 characters.
If string_expression is empty, the setting_key_name will be removed.

Example

setsetting "thisprogram", "testsetting", "value of setting"
print getsetting("thisprogram", "testsetting")

will print

value of setting

GetSetting (Function)

Format

getsetting ( program_name, setting_key_name )

returns string_expression

Description

Retrieve a setting from the system registry (or other persistent storage). The program_name and setting_key_name are required by this function to access a previously saved setting. The empty string “” will be returned if the requested setting has not been previously set.

The saved value will be available to other BASIC-256 programs and should remain available for an extended period.

Program name "SYSTEM" is reserved for getting BASIC256 settings. BASIC256 settings are read-only so

Example

setsetting "thisprogram", "testsetting", "value of setting"
print getsetting("thisprogram", "testsetting")

will print

value of setting

To retreive a BASIC256 setting "SYSTEM" should be used as a program name. In this case slashes are allowed in key name to acces the desired setting.

Example

print getsetting("SYSTEM", "Main/Font")

SYSTEM (GUI is not responding)

Run this program above. It will launch the calculator program.

system "calc"

Now try to stop the program. GUI is not responding.

Implementation: fixed


SYSTEM (30 seconds runtime)

Run this program above. It will launch the calculator program.

system "calc"

Now wait 30 seconds. Any external program lounched will be closed after 30 seconds.

Implementation: fixed


Preferences-Advanced-Allow SYSTEM statement

There are 3 options in Preferences panel for running system commands:
1) Do not allow - program stops and throw error: "You do not have permission to use this statement/function."
2) Ask confirmation from user - program waits for user confirmation
3) Allow - program will run any system commands

Ask confirmation from user

Yes - program run external command
No - program stops and throw error: "You do not have permission to use this statement/function."
Ignore - program do not run external command and continue to run without error
Checkbox [ ] Do not ask me again - remembers user choice till the end of program

If command line is too long, the confirmation dialog will show a new button: Show Details... to view the entire command.

system "mshta "+'"'+"javascript:var sh=new ActiveXObject( 'WScript.Shell' ); sh.Popup( 'Message!', 10, 'Title!', 64 );close()"+'"'


Preferences-Advanced-Allow PORTIN/PORTOUT statements

There are 3 options in Preferences panel for allowing PORTIN/PORTOUT statements:
1) Do not allow - program stops and throw error: "You do not have permission to use this statement/function." when encounters PORTIN/PORTOUT statements.
2) Ask confirmation from user - program waits for user confirmation
3) Allow - program will execute any PORTIN/PORTOUT statements

Ask confirmation from user

Yes - program run statement
No - program stops and throw error: "You do not have permission to use this statement/function."
Ignore - program will ignore PORTIN/PORTOUT statement and continue to run without error. For PORTIN the received value will be 0
Checkbox [ ] Do not ask me again - remembers user choice till the end of program


PORTIN/PORTOUT examples

# this program shows the content of your CMOS - Florin Oprea
# check http://www.bioscentral.com/misc/cmosmap.htm

loop:
s=""
for a=0 to 127
    portout(0x70, a|0x80)
    x=portin(0x71)
    h=tohex(x)
    if length(h)=1 then h="0";h
    s=s;h
next a
cls
print s
goto loop
end

or

# this program shows the time and date of your CMOS - Florin Oprea
# check http://www.bioscentral.com/misc/cmosmap.htm

loop:
cls
print "CMOS time (hh:mm:ss): ";getCMOS(4);":";getCMOS(2);":";getCMOS(0)
print "CMOS date (dd-mm-yy): ";getCMOS(7);"-";getCMOS(8);"-";getCMOS(9)
pause 1
goto loop

function getCMOS(reg)
    portout(0x70, reg|0x80)
    x=portin(0x71)
    h=tohex(x)
    if length(h)=1 then h="0";h
    return h
end function

Go to line on error

Run this program:

print 1
print a
print 2

Program do not go to line 2 on error.

Implementation: Fixed


Debug mode - allow back to step by step

Run a program in debug mode as:

loop:
goto loop

Press Run to button. Now user cannot return to step by step debug mode if there is no break point.
I find very usefull to let Step button enabled to return to step by step mode any time.


Show full path for history items in status bars


INTERPRETER - read important settings from start

Several settings are read at the beginning of the program run, avoiding reading every time.


IMAGEAUTOCROP - Reversing the changes to original behaviour

imageautocrop will autocrop the specified image to contend by cutting the transparent part around it. You can specify a desired color to be used in which case the image is cut to the content, ignoring the color around it. Remember that imageautocrop(img) is not the same as imageautocrop(img,clear). The first statement will reduce the size of image if full transparent colors are found around it. The second statement imageautocrop(img,clear) will cut ONLY if the pixels are 0. (SEE EXAMPLE BELOW)

This is a quote from https://sourceforge.net/p/kidbasic/patches/45/
So, imageautocrop(img) will cut ANY transparent pixels. Those transparent pixels can have any values but with alpha chanel full transparent (0x00000000, 0x00FFFFFF, 0x007A4E22, so on...)
imageautocrop(img,color) will cut pixels with value EQUAL to color. So, imageautocrop(img,CLEAR) will cut only 0x00000000 pixels and not all transparent pixels.

Respectfully,
Florin Oprea

Discussion


Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.