with trace trace(1)This will enable you to step through each line of code and see the variables change as the program runs. Note that the content of the tutorial has been faithfully preserved from David's executable, so occasional references to "the console", etc (which may give rise to some puzzlement) are a reflection of the original format. There have been many additions and enhancements to the language during the years since 1997 when this tutorial was originally written. Chapters 21 and 22 should really be re-named 'Euphoria And OS', to reflect the fact that Euphoria is now multi-platform. The download now includes a database system (EDS), and more recently, multi-tasking was built-in to the interpreter. In spite of this, the tutorial still stands as the most comprehensive introduction to the basics. The later chapters were copied directly from a screen, so a few errors may have crept in. Also, although the demo programs should work ok, I haven't tested them all. If you find any errors/bugs, drop me a line at suninyoureye@linuxmail.org, and I'll fix them.
EX filename.EX
BIND filename.EX
filename
A sequence made up of atoms: {2,4,6,8,10}
A sequence that is made up of three smaller sequences: {{31,32,33,34,35},{41,42,43},{51,52,53,54,55,56}}
namely {31,32,33,34,35}, {41,42,43} and {51,52,53,54,55,56}.
A sequence that is made up of both an atom and two sequences: {{100,101,102},200,{301,302,{-401,-402},303}}
namely {100,101,102},200 and {301,302,{-401,-402},303}.
"David Alan Gay"
{68,97,118,105,100,32,65,108,97,110,32,71,97,121}
variable type variable name
sequence address
atom age
object grab_bag
integer whole_numbers
sequence name, address, city, country
atom hours_worked,
hourly_rate,
deductions,
net_income
Euphoria offers the ability to split variable declarations (and
other types of statements) into several lines as opposed to one
line. Just remember the commas, and only split the line where
there is a space. Having a variable type as part of a variable
declaration is a kind of safety system. It prevents a programmer
from entering the wrong type of value into a variable. It also
ensures that certain features of the Euphoria programming language
that are meant to work on one data
type do not get slipped with a variable value that is of a different
data object type. Which brings us next to the topic of
variable values. Is there an initial value placed inside a
variable after it is declared? The answer is no. Don't get the
impression, however, that there is nothing inside a variable. Most
likely it is left-over data from a previous program run, and probably
so garbled that it is unusable. For this reason, Euphoria
rules dictate that a programmer must place a value
inside a variable for the first time before it can be used. The
next few chapters will discuss the process of
initializing variables with values, and even changing those
values. This is an important part of Euphoria that must be clearly
understood, because it involves the primary purpose of all
programs, which is to process data.
variable = expression
atom year, copy_of_year
year = 1997
copy_of_year = year
atom letter_of_the_alphabet
letter_of_the_alphabet = 'C'
atom double_quotation_mark
double_quotation_mark = '\"'
atom jeans, tax, tax_paid, total_cost jeans = 22.00 tax = .07 tax_paid = jeans * tax total_cost = jeans + tax_paid
atom counter counter = 0 counter = counter + 1 counter = counter + 1 counter = counter + 1
atom counter counter = 0 -- "counter" is initialized to 0 counter = counter + 1 -- "counter"'s value is now 1, by adding 1 to 0 counter = counter + 1 -- "counter"'s value is now 2, by adding 1 to 1 counter = counter + 1 -- "counter"'s value is now 3, by adding 1 to 2
atom t1, t2, t3, t4 t1 = 5 > 4 --1 (TRUE) in "t1": 5 is GREATER than 4 t2 = 7 != 7 --0 (FALSE) in "t2": 7 is EQUAL to 7, not UNEQUAL t3 = 13 <= 13 --1 (TRUE) in "t3": 13 is LESS THAN OR EQUAL to 13 t4 = 12 = 2 * 6 --1 (TRUE) in "t4": 12 is EQUAL to 2 * 6, which is 12
| Condition 1 | Condition 2 | Result | |
| 1 (true) | and | 1 (true) | 1 (true) |
| 0 (false) | and | 1 (true) | 0 (false) |
| 1 (true) | and | 0 (false) | 0 (false) |
| 0 (false) | and | 0 (false) | 0 (false) |
| 1 (true) | or | 1 (true) | 1 (true) |
| 0 (false) | or | 1 (true) | 1 (true) |
| 1 (true) | or | 0 (false) | 1 (true) |
| 0 (false) | or | 0 (false) | 0 (false) |
atom value1,value2,test1,test2,test3,test4 value1 = 50 value2 = 25 test1 = value1 < 10 and value2 = 25 test2 = value1 > 5 and value2 = 12.5 * 2 test3 = value1 != 100 or value2 < 90 test4 = value1 = 5 or value2 > 27
value1 = 50 value2 = 25 test1 = value1 < 10 and value2 = 25
test2 = value1 > 5 and value2 = 12.5 * 2
test3 = value1 != 100 or value2 > 2000
test4 = value1 = 5 or value2 < 49
atom opposite, result result = 15 < 20 opposite = not result
complex_result = value1 * 5 and value2 - 8
atom rent1, rent2, rent3, average_rent rent1 = 500 rent2 = 600 rent3 = 400 average_rent = rent1 + rent2 + rent3 / 3This example is supposed to work out the average of three rents. But precedence dictates that division is done first before addition. This means this program will work out the average of the rents incorrectly! We can fix this by using parentheses to force different parts of the expression to be worked out in a manner different from precedence of operators:
average_rent = (rent1 + rent2 + rent3) / 3
sequence list_of_values
list_of_values = {1,2,3,4,5,6,7,8,9,0}
sequence Mister_No_Elements
Mister_No_Elements = {}
sequence my_name my_name = "David Alan Gay"
{68,97,118,105,100,32,65,108,97,110,32,71,97,121}
sequence seq1, seq2
seq1 = {{1,2,3}, {4,5,6}, {7,8,9}}
seq2 = {{5,5,5,5,5,5,5}, -98, {100,-50,20.3}}
sequence seq1, seq2
seq1 = {{1,2,3},
{4,5,6},
{7,8,9}}
seq2 = {{5,5,5,5,5,5,5},
-98,
{100,-50,20.3}}
sequence mixed_bunch
atom some_atom_element
some_atom_element = 502
mixed_bunch = {"Euphoria", some_atom_element, some_atom_element/2}
sequence old_rents, new_rents
atom rent_increase
old_rents = {413,500,435,619,372}
rent_increase = 1.05
new_rents = old_rents * rent_increase
new_rents = old_rents * rent_increase
element 1 of "old_rents" (413) × element 1 of temporary sequence (1.05) element 2 of "old_rents" (500) × element 2 of temporary sequence (1.05) element 3 of "old_rents" (435) × element 3 of temporary sequence (1.05) element 4 of "old_rents" (619) × element 4 of temporary sequence (1.05) element 5 of "old_rents" (372) × element 5 of temporary sequence (1.05)
{433.65, 525, 456.75, 649.95, 390}
sequence test1,test2
test1 = {1,0,0} and 0
test2 = {20,30,40} <= 30
element 1 of {1,0,0} (1) and element 1 of {0,0,0} (0) = 0
element 2 of {1,0,0} (0) and element 2 of {0,0,0} (0) = 0
element 3 of {1,0,0} (0) and element 3 of {0,0,0} (0) = 0
Thus, variable "test1" is assigned a value of {0,0,0}
element 1 of {20,30,40} (20) ≤ element 1 of {30,30,30} (30), giving a value of 1.
element 2 of {20,30,40} (30) ≤ element 2 of {30,30,30} (30), giving a value of 1.
element 3 of {20,30,40} (40) ≥ element 3 of {30,30,30} (30), giving a value of 0.
Thus, variable "test2" is assigned a value of {1,1,0}
sequence seq1, seq2
seq1 = {1,0,1,0,1} or {0,1,0,1,0}
seq2 = {2,{2,2},2} + {{2,2},2,{2,2}}
variable = sequence variable[element number(s)]
sequence list_of_days, list_of_months, month_name
atom days_in_month
list_of_months = {"January","February","March","April","May","June",
"July","August","September","October","November","December"}
list_of_days = {31,28,31,30,31,30,31,31,30,31,30,31}
days_in_month = list_of_days[3]
month_name = list_of_months[3]
variable = sequence variable [element number(s)][element number(s)]
sequence days_of_months
atom no_leap_february, leap_february
days_of_months = {31,{28,29},31,30,31,30,31,31,30,31,30,31}
no_leap_february = days_of_months[2][1]
leap_february = days_of_months[2][2]
seq. variable = seq. variable[starting element..ending element]
sequence nine_numbers, first_four, last_five
nine_numbers = {1,2,3,4,5,6,7,8,9}
first_four = nine_numbers[1..4]
last_five = nine_numbers[5..9]
sequence bigseq, seq1, seq2
bigseq = {{1,1,1},{2,2,2},{3,3,3}}
seq1 = bigseq[1][1..2]
seq2 = bigseq[1..2][1]
sequence variable [element number(s)] = expressionHere is a program example that demonstrates how to change both a single element and a range of elements:
sequence bunch
bunch = {"cat",5,{1,9,8,4},{0,0,0}}
bunch[1][1] = 'b'
bunch[2] = {7,7,7} + 1
bunch[3][3..4] = {9,7}
bunch[4][1..3] = -20
bunch = {"cat",5,{1,9,8,4},{0,0,0}} - assign variable "bunch" with the value of {{99,97,116},5,{1,9,8,4},{0,0,0}}
bunch[1][1] = 'b' - access first element in element 1 of "bunch" and change it from 99 ('c') to (98) ('b'), "bunch[1]" is now {98,97,116}
bunch[2] = {7,7,7} + 1 - access second element of "bunch" and change it to the value of expression {7,7,7} + 1, "bunch[2]" is now {8,8,8}
bunch[3][3..4] = {9,7} - access third and fourth elements in element 3 of "bunch", and replace with {9,7}, "bunch[3]" is now {1,9,9,7}
bunch[4][1..3] = -20 - access all three elements in element 4 of "bunch" and replace with {-20,-20,-20}, "bunch[4]" is now {-20,-20,-20}
{{98,97,116},{8,8,8},{1,9,9,7},{-20,-20,-20}}
sequence variable = expression & expression
sequence s1, s2, s3
s1 = 5 & 4 -- s1 is assigned {5,4}
s2 = 90 & {30,60} -- s2 is assigned {90,30,60}
s3 = {{1,1},{2,2,2}} & {3,3,3} + 1 -- s3 is assigned {{1,1},{2,2,2},4,4,4}
include (file name).e
GRAPHICS.E - Graphics And Sound SORT.E - Sorting Routine GET.E - Input And Conversion Routines MOUSE.E - Mouse Routines FILE.E - Random Access File Operations And Directory Functions MACHINE.E - Machine Level Programming For 386's And Higher WILDCARD.E - Wildcard String Matching And Conversion IMAGE.E - Graphical Image Routines
procedure name (parameters)
print(1,"Hey, now!")
clear_screen()
pixel({BRIGHT_BLUE,BRIGHT_RED,BRIGHT_GREEN},{100,150})
receiving variable = function name (parameters)
index_bitmap = read_bitmap("index.bmp")
pressed_key = get_key()
computed_result = sqrt(25) * (30 + units)
While a function can modify the original value of a receiving
variable, both procedures and functions do not modify the
parameter values that are passed to them. Also, procedure and
function names follow the same rules that variable names must
adhere to. The following abbreviations will be used every time a new
library routine is introduced to you. Take a moment to look them
over:
a - either an atom data object or a variable of type atom i - either an integer data object or a variable of type integer o - either an object data object or a variable of type object s - either a sequence data object or a variable of type sequence ra,ri,ro,rs - receiving variable, the second letter means variable type.
print(1,o)
atom some_atom_value some_atom_value = 134.45Demo program 2
print(1,some_atom_value)
sequence some_sequence_value
some_sequence_value = {1,2,3,4,3,2,1}
print(1,some_sequence_value)
Demo program 3
print(1,36/2)Demo program 4
sequence my_name my_name = "David Gay" print(1,my_name)One minor drawback with print() is that it displays the actual values of atom and sequence data objects. As a result, any data object values meant to be shown on the screen as ASCII characters cannot be displayed using print(). However, Euphoria has another library routine that can display screen output in human-readable form:
puts(1,o)
atom a_character a_character = 'A' puts(1,a_character)Demo program 6
sequence a_string a_string = "Utter Nonsense" puts(1,a_string)
puts(1,"Column 1\tColumn 2\tColumn 3\n\n") puts(1,"********\t********\t********\n") puts(1,"********\t********\t********\n") puts(1,"********\t********\t********\n") puts(1,"********\t********\t********\n") puts(1,"********\t********\t********\n") puts(1,"********\t********\t********\n") puts(1,"********\t********\t********\n") puts(1,"********\t********\t********\n") puts(1,"********\t********\t********\n") puts(1,"********\t********\t********\n")
printf(1,s,o)
printf(1,"%s\n","Euphoria") - Only "E" is printed
printf(1,"%s\n",{"Euphoria"}) - "Euphoria" is printed
atom atom_value integer integer_value atom_value = 1233.14 integer_value = 255 print(1,atom_value) printf(1,"\n is shown as %d when using %%d", atom_value) printf(1,"\n is shown as %e when using %%e", atom_value) printf(1,"\n is shown as %f when using %%f\n\n", atom_value) print(1,integer_value) printf(1,"\n is shown as %x when using %%x", integer_value) printf(1,"\n is shown as %o when using %%o\n\n", integer_value) atom_value = 'A' print(1,atom_value) printf(1,"\n is shown as %s when using %%s\n", atom_value)Demo program 9
puts(1,"Field Width Using %9s\n")
puts(1,".........\n")
printf(1,"%9s", {"CAT"})
puts(1,"\n\n")
puts(1,"Field Width Using %-9s\n")
puts(1,".........\n")
printf(1,"%-9s", {"CAT"})
puts(1,"\n\n")
puts(1,"Field Width Using %4d\n")
puts(1,"....\n")
printf(1,"%4d", 123)
puts(1,"\n\n")
puts(1,"Field Width Using %04d\n")
puts(1,"....\n")
printf(1,"%04d", 123)
puts(1,"\n\n")
puts(1,"Field Width Using %+4d\n")
puts(1,"....\n")
printf(1,"%+4d", 123)
puts(1,"\n\n")
Demo program 10
puts(1, "How Decimal Precision Affects Floating Point Values\n\n") printf(1,"%f <- Using Straight %%f\n", 123.7651) puts(1,".......\n") printf(1,"%7.3f <- %%7.3f\n", 123.7651) printf(1,"%7.2f <- %%7.2f\n", 123.7651) printf(1,"%7.1f <- %%7.1f\n", 123.7651) printf(1,"%7.0f <- %%7.0f\n", 123.7651)We would normally explore the other side of screen output by introducing library routines that accept data from the keyboard. However, because some keyboard library routines require a program to execute a block of statements based on a condition or for a set number of times in order to work properly, a detour is needed. The next chapter will show you how to change the way your program executes.
if expression then
one or more Euphoria statements
end if
atom first, second, sum
first = 36
second = 1.5
sum = first * second
if second >= 1.4 and second <= 1.6 then
puts(1,"Condition 1 is true\n")
end if
if sum = 54 then
puts(1,"Condition 2 is true\n")
first = 63
end if
if first = 36 then
puts(1,"Condition 3 is true\n")
end if
The "if" statement can be used to execute a group of statements for
both false and true outcomes of a condition. One way to do this is
to write a second "if" statement that checks for the opposite of
the first "if" statement.
if speed > 65 then
puts(1,"You are driving too fast!\n")
end if
if speed <= 65 then
puts(1,"Thank you for driving within the speed limit!\n")
end if
if expression then
one or more statements that will only run if expression is true
else
one or more statements that will only run if expression is false
end if
atom character
character = 'a'
if character = 'a' then
puts(1,"********************************\n")
puts(1,"* This line should be printed! *\n")
puts(1,"********************************\n")
else
puts(1,"This line should not be printed!\n")
end if
character = 'b'
if character = 'a' then
puts(1,"This line should not be printed!\n")
else
puts(1,"********************************\n")
puts(1,"* This line should be printed! *\n")
puts(1,"********************************\n")
end if
Using an "if-else" combination can handle situations that result in
only one of two outcomes. For situations that can result in more
than two outcomes, we replace "else" with "elsif".
if expression 1 then
one or more statements that execute if expression 1 is true
elsif expression 2 then
one or more statements that execute if expression 2 is true
elsif expression 3 then
one or more statements that execute if expression 3 is true
elsif expression 4 then
one or more statements that execute if expression 4 is true
end if
atom character
character = 'M'
if character >= 'A' and character <= 'J' then
puts(1, "This line should not be printed\n")
elsif character >= 'K' and character <= 'T' then
puts(1, "********************************\n")
puts(1, "* This line should be printed! *\n")
puts(1, "********************************\n")
elsif character >= 'U' and character <= 'Z' then
puts(1, "This line should not be printed\n")
end if
You can have what is called nested "if" statements, where one
"if" statement leads to a second "if" statement when its
expression is true:
if expression 1 then
if expression 2 then
one or more statements that run only if expression 2 is true
end if
end if
if expression 1 and expression 2 then
one or more expressions to be run only if both expressions are true
end if
ri = compare(o1,o2)
sequence my_name
my_name = "David Gay"
if compare(my_name, "David Gay") = 0 then
puts(1,"Hi, David!\n")
else
puts(1,"Who the heck are you?\n")
end if
sequence animal1, animal2
animal1 = "cat"
animal2 = animal1
if compare(animal1,animal2) = 0 then
puts(1, "These strings are the same\n")
else
puts(1, "These strings are unequal\n")
end if
animal2 = "CAT"
if compare(animal1,animal2) = 0 then
puts(1, "These strings are the same\n")
else
puts(1, "These strings are unequal\n")
end if
Program branching is only one part of changing the way your program
runs. You can also make a group of statements repeat for as long
as an expression remains true. This is done by using the "while"
statement:
while expression do
one or more statements that are executed while condition is true
end while
atom count
puts(1,"Hello, I'm Sparky I, The Counting Euphoria Program\n")
puts(1,"Watch me count to 10!\n\n")
count = 1
while count < 11 do
printf(1,"%d\n",count)
count = count + 1
end while
If you want to repeat a group of statements for a specific number of times, Euphoria offers the "for" statement:
for ra = start value to end value by increment do
one or more statements to repeat until ra > end value
end for
puts(1,"Hello, I'm Sparky II, The Counting Euphoria Program\n")
puts(1,"Watch me count to 5, then back again to 1!\n\n")
for count = 1 to 5 do
printf(1,"%d\n",count)
end for
puts(1,"\n")
for count = 5 to 1 by -1 do
printf(1,"%d\n",count)
end for
Both the "for" and "while"
statements can be nested, meaning that you can have smaller loops
within larger ones. However, the nested "while" and "for"
statement levels should have correctly matching "end while" and
"end for" statements. You can force both a "while" and a "for"
statement to end early using the "exit" statement. The loop ends
at the moment the "exit" statement is executed. The program will
then resume at the next statement following "end for" or "end
while". The "exit" statement is best used as either an "emergancy
brake" when something unexpected comes up, or for creating a loop
that needs to end for a set of reasons uniquely separate from each
other. A program demo shows the "exit" statement in action. You
have now learned everything you need to know to control the course
of program execution. These tools will be valuable in the next
chapter, when you learn how to accept data from the keyboard.
atom pet_index
sequence pets
puts(1,"Examples Of Animals You Can Keep As Pets\n")
puts(1,"========================================\n\n")
pets = {"Cat",
"Dog",
"Hamster",
"Rat",
"Snake",
"Parrot",
"Budgie",
"Unelected Politician",
"*END*"}
pet_index = 1
while 1 do
if compare(pets[pet_index],"*END*") = 0 then
exit
else
puts(1,pets[pet_index])
puts(1,"\n")
end if
pet_index = pet_index + 1
end while
puts(1,"\nList Completed!\n")
Displaying data on the screen is only one side
of program-human interaction. While it is great that we can
now write programs that present text on the
include get.e ri = wait_key()
include get.e integer keystroke puts(1,"Please press a key on the keyboard\n") keystroke = wait_key() puts(1,"\nThank you!\n") printf(1,"You pressed the %s key!\n",keystroke)It is sometimes necessary to read in an entire character string instead of a single character. Euphoria has a library routine that performs this:
ro = gets(0)
object name, city
puts(1, "Hello, what is your name?\n")
name = gets(0)
printf(1, "\nHello, %sWhat city are you from?\n",{name})
city = gets(0)
printf(1, "\nI've always wanted to go to %s", {city})
All the library routines introduced so far have one thing in common,
and that is the accepted keyboard data is treated like a character
string to be redisplayed as text later. This means if we entered a
value of 16.13 using gets(), it will not be stored as an atom
value of 16.13, but a 5 element long character string "16.13".
This makes the library routines we have mentioned unsuitable for
handling numeric data. However, Euphoria does have a more
sophisticated routine that can accept both numeric and character
data:
include get.e
rs = get(0)
include get.e
object input
atom value1, value2, value3, average, error_code
sequence name
error_code = 999
puts(1,"Hello! Enter your first name in quotes below, like \"John\":\n")
while error_code != 0 do
input = get(0)
error_code = input[1]
end while
name = input[2]
puts(1, "\nThank you! Now please enter any three numeric values below,\n")
puts(1, "and you will see both your name and the average of the three\n")
puts(1, "numbers you entered. Separate the numbers with the space bar:\n")
error_code = 999
while error_code != 0 do
input = get(0)
error_code = input[1]
end while
puts(1, "\nGot first number!\n")
value1 = input[2]
error_code = 999
while error_code != 0 do
input = get(0)
error_code = input[1]
end while
puts(1, "\nGot second number!\n")
value2 = input[2]
error_code = 999
while error_code != 0 do
input = get(0)
error_code = input[1]
end while
puts(1, "\nGot third number!\n")
value3 = input[2]
average = (value1+value2+value3)/3
printf(1,"\nHello, %s, your computed average is %4.2f\n",{name, average})
You may have played some games that are able to accept data from
the keyboard without pausing. Actually, they do pause, but only
for a tiny fraction of time to check the keyboard buffer for a
pressed keystroke. Because computers can operate at such high
speeds, this delay goes unnoticed. The next library routine would
be of interest to game designers:
ri = get_key()
integer keystroke, counter
keystroke = -1
counter = 10000
while keystroke = -1 and counter > 0 do
keystroke = get_key()
printf(1,"%5d\n",counter)
counter = counter - 1
end while
if counter = 0 then
puts(1, "\nHey, why didn't you press any of the keys?\n")
end if
The one keystroke that cannot be accepted by a Euphoria program
is Ctrl-C, generated by either pressing the c or break key while
holding down the Ctrl key at the same time. If you press these
combination of keys, the operating system will abruptly stop the
program. In the case of larger, more complex programs, this can
result in an unexpected loss of data. It would be preferable for
the program to know that Ctrl-C has been pressed and perform an
orderly shutdown.
First of all, we need to disable Ctrl-C so it cannot kill the program outright. This is done by using the allow_break() library routine:
include file.e allow_break(i)
include file.e ri = check_break()
include file.e
integer control_break_counter, pressed_key
allow_break(0)
puts(1, "***********************************\n")
puts(1, "* The Program That Would Not Die! *\n")
puts(1, "***********************************\n")
puts(1,"\n")
control_break_counter = 0
while control_break_counter < 3 do
pressed_key = get_key()
if check_break() then
control_break_counter = control_break_counter + 1
if control_break_counter <= 2 then
puts(1,"Neener-neener, can't kill meeeeeeee!\n")
end if
end if
end while
puts(1, "\n")
puts(1, "***********************************\n")
puts(1, "* Okay, I'll be nice and stop.... *\n")
puts(1, "***********************************\n")
Now that you have learned how to display data on the screen, and how
to accept data from the keyboard, let's learn some powerful
library routines that show you what you can really do with this
data.ri = atom(o)
ri = integer(o)
ri = sequence(o)
include get.e
atom atom_received, integer_received, sequence_received
sequence inputted_string
atom_received = 'n'
integer_received = 'n'
sequence_received = 'n'
puts(1,"Enter any numeric value (such as 5.004 or -7)\n")
while atom_received = 'n' and integer_received = 'n' do
inputted_string = get(0)
if inputted_string[1] = 0 then
if integer(inputted_string[2]) then
integer_received = 'y'
puts(1,"\nThank you! This value is an integer!\n\n")
else
if atom(inputted_string[2]) then
atom_received = 'y'
puts(1,"\nThank you! This value is an atom!\n\n")
end if
end if
end if
end while
puts(1,"Enter a sequence value (such as {54,-8,2.3} or \"Hi There!\")\n")
while sequence_received = 'n' do
inputted_string = get(0)
if inputted_string[1] = 0 then
if sequence(inputted_string[2]) then
sequence_received = 'y'
end if
end if
end while
puts(1,"\nThank you! Program Finished!\n")
To convert a character string to either an atom or a sequence value, you use the value() library routine: include get.e rs = value(s)
include get.e
sequence character_strings, value_string
object actual_value
character_strings = {"45.99","{1,2,3,{4,4},5}","\"Euphoria\""}
for ix = 1 to 3 do
printf(1,"Character String: %s\n",{character_strings[ix]})
value_string = value(character_strings[ix])
actual_value = value_string[2]
puts(1,"Euphoria Data Object After value(): ")
print(1,actual_value)
puts(1,"\n\n")
end for
You can also convert a Euphoria data object into a character string, or as part of a formatted character string by using sprintf():
rs = sprintf(s,o)
sequence print_line
for line = 1 to 5 do
print_line = sprintf("This is line %03d\n", line)
puts(1,print_line)
end for
Another way of changing the state of a data object is by
altering the case of alphabetic characters. Euphoria has two
library routines that can do this for you.
include wildcard.e ro = lower(o)
include wildcard.e ro = upper(o)
include wildcard.e
sequence test_string, uppered, lowered
test_string = "This is a fun way to learn Euphoria!"
uppered = upper(test_string)
lowered = lower(test_string)
printf(1,"Original String : %s\n",{test_string})
printf(1," After lower() : %s\n",{lowered})
printf(1," After upper() : %s\n",{uppered})
Earlier in the tutorial, we
introduced the & operator, which allows you to join atom or
sequence data objects together to create new sequences. Euphoria
offers other ways of linking data objects together, the
first being append():
rs = append(s,o)
atom atom1, atom2
sequence seq1, seq2, union
atom1 = 83
atom2 = 4
seq1 = {1,1,1,1}
seq2 = {2,2}
puts(1,"& And append()\n")
puts(1,"==============\n\n")
printf(1,"Atom Values: %d, %d\n",{atom1,atom2})
puts(1," Using &: ")
union = atom1 & atom2
print(1,union)
puts(1,"\n")
puts(1," Using append(): ")
union = {}
union = append(union,atom1)
union = append(union,atom2)
print(1,union)
puts(1,"\n\n")
puts(1,"Sequence Values: ")
print(1,seq1)
puts(1," ")
print(1,seq2)
puts(1,"\n")
puts(1," Using &: ")
union = seq1 & seq2
print(1,union)
puts(1,"\n")
puts(1," Using append(): ")
union = {}
union = append(seq1,seq2)
print(1,union)
puts(1,"\n\n")
A related library routine to append() is prepend():
rs = prepend(s,o)
atom atom1, atom2
sequence seq1, seq2, union
atom1 = 83
atom2 = 4
seq1 = {1,1,1,1}
seq2 = {2,2}
puts(1,"& And prepend()\n")
puts(1,"==============\n\n")
printf(1,"Atom Values: %d, %d\n",{atom1,atom2})
puts(1," Using &: ")
union = atom1 & atom2
print(1,union)
puts(1,"\n")
puts(1," Using prepend(): ")
union = {}
union = prepend(union,atom1)
union = prepend(union,atom2)
print(1,union)
puts(1,"\n\n")
puts(1,"Sequence Values: ")
print(1,seq1)
puts(1," ")
print(1,seq2)
puts(1,"\n")
puts(1," Using &: ")
union = seq1 & seq2
print(1,union)
puts(1,"\n")
puts(1," Using prepend(): ")
union = {}
union = prepend(seq1,seq2)
print(1,union)
puts(1,"\n\n")
Both append() and prepend() are handy when you want to stack atoms and sequences in a queue, like candies in a "PEZ" dispenser. When append() or prepend()
is used to attach a data object to a larger sequence, that data
object retains its separate identity. Sequences can also be
created "on the fly" by repeating a value so many times. The repeat() library routine was created to perform just that:
rs = repeat(o,a)
puts(1,"Some Sequences Created By repeat()\n\n")
puts(1,"repeat(20,10):\n ")
print(1,repeat(20,10))
puts(1,"\n\n")
puts(1,"repeat({1,1,1,1,1},5):\n ")
print(1,repeat({1,1,1,1,1},5))
puts(1,"\n\n")
puts(1,"repeat(\"Tim\",4):\n ")
print(1,repeat("Tim",4))
puts(1,"\n")
Once you've created your
sequences, it's a good idea to know how large they are if you plan
to examine one or many of the elements that make the sequence up.
The length() library routine returns the length of a sequence in number of elements:
ri = length(s)
sequence seq
seq = {{0,0,0},{65,{7,7,7},23.1},"Timmy"}
for element1 = 1 to 3 do
puts(1,"Elements For Sequence ")
print(1,seq[element1])
puts(1,":\n")
for element2 = 1 to length(seq[element1]) do
printf(1," Element %d: ",element2)
print(1,seq[element1][element2])
puts(1,"\n")
end for
puts(1,"\n")
end for
The next chapter will introduce library routines that search sequences!ri = find(o,s)
atom found, more_finds, offset
sequence search_string
search_string = {34,5,106,72,65,5,90,17,5,13}
puts(1,"Searching Sequence ")
print(1,search_string)
puts(1," For 5\n\n")
offset = 0
more_finds = 'y'
while more_finds = 'y' do
found = find(5,search_string)
if found then
offset = offset + found
printf(1,"5 Found As Element %d\n",offset)
search_string = search_string[found+1..length(search_string)]
else
more_finds = 'n'
end if
end while
puts(1,"\nProgram completed\n")
While find() finds a single element in a sequence, match() allows you to search a sequence for a specfic group of elements:
ri = match(s1,s2)
atom element_id1, element_id2, element_id3
element_id1 = match("Al", "David Alan Gay")
element_id2 = match({3,4,5}, {1,2,3,4,5,6,7,8,9,0})
element_id3 = match({{50,23,4},{-1,-2}}, {{15,89},{50,23,4},{-1,-2}})
"David Alan Gay" - element_id1 is assigned the value of 7
{1,2,3,4,5,6,7,8,9,0} - element_id2 is assigned the value of 3
{{15,89}, {50,23,4},{-1,-2}} - element_id3 is assigned the value of 2
sequence nursery_rhyme
atom found
nursery_rhyme = "Jack and Jill went up the hill to fetch a pail of water"
puts(1,nursery_rhyme & "\n\n")
printf(1,"Searching String For \"%s\"\n",{"hill"})
found = match("hill",nursery_rhyme)
printf(1," Found \"%s\" beginning at element %d\n\n",{"hill",found})
printf(1,"Searching String For \"%s\"\n",{"l of water"})
found = match("l of water",nursery_rhyme)
printf(1," Found \"%s\" beginning at element %d\n\n",{"l of water",
found})
puts(1, "Searching String For ")
print(1, {97,110,100})
puts(1,"\n")
found = match({97,110,100},nursery_rhyme)
puts(1," Found ")
print(1, {97,110,100})
printf(1," beginning at element %d\n\n",found)
The previous library routines we introduced in this chapter used
an actual value to match one or a specific group of elements in a
sequence. The next library routine uses "wildcards" to search for
elements in sequences. Before we introduce this library routine,
we need to discuss what wildcards are. Wildcards are single
substitution characters used in conjunction with other characters
to make a generic search string. You may have seen wildcards at
work when you use the DIR command in DOS as follows:
include wildcard.e
ri = wildcard_match(s1,s2)
atom match_1, match_2, match_3
match_1 = wildcard_match("a*","ABCDEFGHIJKLMNOPQRSTUVWXYZ")
match_2 = wildcard_match("?Z","ABCDEFGHIJKLMNOPQRSTUVWXYZ")
match_3 = wildcard_match("PQR*","ABCDEFGHIJKLMNOPQRSTUVWXYZ")
All three variables above will be assigned a value of 0. The first wildcard_match()
line won't match because the pattern has a lowercase letter while
the searched string is all in uppercase. The second wildcard_match()
will not match because ? was used instead of *, even though "Z" is
indeed the last letter of the searched string. "?Z" means any two
character string, the second character being "Z". The last wildcard_match()
line will not match because even though "PQR" does exist in the
searched string, the pattern "PQR*" implies a match only if the
searched string begins with "PQR". If you want to search for a
substring of characters anywhere in the target sequence, place a *
wildcard on both sides of the substring. This will produce a match
pattern of "*PQR*" for example. You can also mix wildcards in a
match pattern, such as "A?c*1". This means wildcard_match()
will only get a match on this pattern if the searched string's
first character is "A", its third character is "c", and its last
character is "1". A demo program is available that allows you to
experiment with pattern strings, to help you get a better
understanding of wildcard_match().
include wildcard.e
sequence pattern_string, search_string
atom halt_program, matched
halt_program = 'n'
search_string = "wildcard_match() is a powerful feature of Euphoria."
while halt_program = 'n' do
puts(1,search_string & "\n")
puts(1,"Enter a wildcard pattern string or \"STOP\": ")
pattern_string = gets(0)
pattern_string = pattern_string[1..(length(pattern_string)-1)]
if compare(pattern_string,"STOP") = 0 then
halt_program = 'y'
else
matched = wildcard_match(pattern_string, search_string)
puts(1,"\n")
if matched then
puts(1,pattern_string & " matches above string.\n\n")
else
puts(1,pattern_string & " does not match above string.\n\n")
end if
end if
end while
If you want to write your own sequence search programs, one
important factor is the speed on finding the element you are
searching for. To optimize your search, it is best to sort the
sequence and then look up each element until you either get a
match, or compare a value that is larger than the element you are
looking for (which means not found). To sort a sequence to be searched,
you use the sort() library routine.include sort.e rs = sort(s)
include sort.e
sequence sorted, unsorted
unsorted = {"world","the","Euphoria","rules"}
sorted = sort(unsorted)
puts(1,"Unsorted: ")
for words = 1 to length(unsorted) do
puts(1,unsorted[words] & " ")
end for
puts(1,"\n")
puts(1,"Sorted: ")
for words = 1 to length(sorted) do
puts(1,sorted[words] & " ")
end for
puts(1,"\n\n")
unsorted = {{1,1,8,2},5,{1,2,3},{1,1,9},-45,{1,2,1}}
sorted = sort(unsorted)
puts(1,"Unsorted: ")
print(1,unsorted)
puts(1,"\n")
puts(1,"Sorted: ")
print(1,sorted)
puts(1,"\n")
This concludes your introduction to advanced data object
handling library routines. The next chapter will introduce library
routines that can enhance any arithmetic computations you may have
in your programs.
ro = sqrt(o)
atom value1
sequence value2
value1 = 25
value2 = {81,{9,4},100}
puts(1, "The square root of ")
print(1,value1)
puts(1, " is ")
print(1,sqrt(value1))
puts(1,"\n")
puts(1, "The square root of ")
print(1,value2)
puts(1, " is ")
print(1,sqrt(value2))
puts(1,"\n")
The opposite of square-rooting a number is to raise a number by the
power of 2. Euphoria has a library routine that can raise a number
to the power 2, or any power for that matter. Here is the library
routine used to raise a data object value by a given power:
ro = power(o1,o2)
atom base, result
sequence base2, result2
base = 2
for exponent = 1 to 4 do
result = power(base,exponent)
printf(1, "%d to the power of %d is %d\n",{base,exponent,result})
end for
puts(1,"\n")
for exponent = 1 to 4 do
base2 = repeat(10,5)
result2 = power(base2,exponent)
print(1, base2)
puts(1, " to the power of ")
print(1,exponent)
puts(1, " is ")
print(1,result2)
puts(1,"\n")
end for
puts(1, "\n")
base = 3
result2 = power(base,{2,3,4})
print(1, base)
puts(1, " to the power of ")
print(1,{2,3,4})
puts(1, " is ")
print(1,result2)
puts(1,"\n")
Another library routine related to sqrt() is log():
ro = log(o)
atom log1, base, result1
sequence log2, result2
base = 2.71828
log1 = log(63)
log2 = log({100,50,25})
result1= power(base,log1)
result2= power(base,log2)
printf(1,"The natural logarithm of 63 is %f\n",log1)
printf(1,"%.5f to the power of %f is %.0f (rounded up)\n\n",
{base,log1,result1})
puts(1,"The natural logarithm of ")
print(1,{100,50,25})
puts(1," is ")
print(1,log2)
puts(1,"\n")
printf(1,"%.5f to the power of ",base)
print(1,log2)
puts(1," is ")
printf(1,"{%.0f,%.0f,%.0f} (rounded up)\n\n",result2)
When
one number does not evenly divide by another, have you
wondered what the decimal part of the result means? Well, the
numbers to the right of the decimal is what is left over, shown as
a decimal fraction. For example, 3.5 returned from dividing 7 by 2
means "3 with 1 left over". How did we get 1? Multiply .5 by the
divisor 2 and you get 1. Sometimes this remainder of a division is
just as important as the result, and usually it is preferable to
have that remainder shown as a whole number. You could use the
technique shown above to determine the remainder, or you can use
this next Euphoria library routine instead.
ro = remainder(o1,o2)
sequence format_string
atom leftovers, result
format_string = "10 divided by %d goes %d time(s) with %d left over.\n"
for divisor = 2 to 9 do
leftovers = remainder(10,divisor)
result = 10/divisor
printf(1,format_string,{divisor,result,leftovers})
end for
If you are working with floating point numbers and want to convert that value to an integer, one way
to do it is to use the floor() library routine:
ro = floor(o)
object value1, value2
value1 = 5.3
value2 = -5.3
printf(1,"%.1f floor()'d gives %d\n",{value1,floor(value1)})
printf(1,"%.1f floor()'d gives %d\n",{value2,floor(value2)})
puts(1,"\n")
value1 = {35.3,-46.1,22.9,-.7345}
print(1, value1)
puts(1," floor()'d gives ")
print(1, floor(value1))
puts(1,"\n")
Euphoria has a library routine that may be of interest to those who want to write their own games. It involves the creation of random numbers, a key element in any game, whether it involves randomly generating a number to guess, or creating an unexpected malfunction aboard a spaceship during
a critical moment in battle. Here is the syntax of the rand() library routine:
ro = rand(o)
include get.e
atom random_number,guessed_number, end_program
sequence input_data
puts(1,"Guess any number between 1 and 10\n")
end_program = 'n'
random_number = rand(10)
while end_program = 'n' do
input_data = get(0)
if input_data[1] = 0 then
if integer(input_data[2]) then
guessed_number = input_data[2]
if guessed_number = random_number then
end_program = 'y'
puts(1,"\nBingo!\n")
elsif guessed_number < random_number then
puts(1,"\nYou're too low! Try again!\n")
elsif guessed_number > random_number then
puts(1,"\nYou're too high! Try again!\n")
end if
end if
end if
end while
Left on its own, rand() will generate a unpredictable random value every
time it is called. However, some programs may need to repeat the same
random values more than once. This is done by setting the random number
generator's "seed" (a source value where all rand()-generated values are
drawn from) to a certain value. You can do this by using the library
routine set_rand():
include machine.e set_rand(a)
include get.e
include machine.e
atom seed, end_program
sequence input_data, prompt, line1, line2, line3
line1 = "\nYou entered "
line2 = " as the value to set the random number generator seed to.\n"
line3 = "The next 10 numbers generated by rand(100) will always be:\n"
prompt = "\nEnter any value or 0 to end this program program\n"
end_program = 'n'
while end_program = 'n' do
puts(1,prompt)
input_data = get(0)
if input_data[1] = 0 then
if integer(input_data[2]) then
seed = input_data[2]
if seed != 0 then
puts(1,line1)
print(1,seed)
puts(1,line2)
set_rand(seed)
puts(1,line3)
for i = 1 to 10 do
print(1,rand(100))
puts(1, " ")
end for
puts(1,"\n")
else
end_program = 'y'
end if
end if
end if
end while
To close this chapter, we will briefly introduce a series of library
routines devoted to trigonometry:
ro = sin(o) - Returns the sine of an angle
ro = cos(o) - Returns the cosine of an angle
ro = tan(o) - Returns the tangent of an angle
ro = arctan(o) - Returns the angle of a tangent (opposite of tan())
ri = open(s1,s2)
Read Write Append Update
Data Data Data Data
==== ===== ====== ======
Treat data as text r w a u
Treat data as binary rb wb ab ub
integer file_id
file_id = open("text.doc","r")
integer file_id
file_id = open("c:\\binary\\database.bin","ab")
integer file_id
file_id = open("f:\\output\\write.dta","w")
integer file_id
file_id = open("c:\\EuphoriaFiles\\tutorialfile.textfile","u")
CON - Console (screen) AUX - Auxiliary serial port COM1 - Serial port 1 COM2 - Serial port 2 PRN - Parallel port printer NUL - Non-existent device that discards accepted output
integer file_id
file_id = open("PRN","w")
print(i,o) - sends a Euphoria value to a file or device
puts(i,o) - sends an atom or a sequence as a character string to a file or device
printf(i,s,o) - sends an atom or a sequence as part of an edited string to a file or device
include get.e rs = get(i) - retrieve a Euphoria data object from a file or device, and store as a two element sequence
ro = gets(o) - retrieve a character string from a file or device up to and including the '\n' code, or -1 if no data is availablewait_key() and get_key() only works with the keyboard. However, Euphoria has a counterpart for get_key(), called getc():
ri = getc(i)
close(i)
include get.e
sequence input_data
integer file_id, byte
puts(1,"File And Device I/O Demo Program\n")
puts(1,"================================\n\n")
puts(1,"Creating a new file called demo.fle on your system......\n\n")
file_id = open("demo.fle","w")
if file_id != -1 then
puts(1,"Successfully created file demo.fle on your system!\n\n")
puts(1,"Writing a character string of \"Euphoria\" in demo.fle\n")
puts(1,"using puts().....\n\n")
puts(file_id,"Euphoria")
puts(1,"Done....closing file demo.fle\n\n")
close(file_id)
end if
puts(1,"Press any key to continue......\n\n")
while get_key() = -1 do
end while
puts(1,"-----------------------------------------------------------------\n")
puts(1,"Opening demo.fle on your system for reading......\n\n")
file_id = open("demo.fle","r")
if file_id != -1 then
puts(1,"Successfully opened file demo.fle on your system!\n\n")
puts(1,"Read character string from demo.fle\n")
puts(1,"in one shot using gets().....\n\n")
input_data = gets(file_id)
if sequence(input_data) then
printf(1,"The string read in is: %s\n\n", {input_data})
else
puts(1,"Error reading data from file!\n")
end if
puts(1,"Done....closing file demo.fle\n\n")
close(file_id)
end if
puts(1,"Press any key to continue......\n\n")
while get_key() = -1 do
end while
puts(1,"-----------------------------------------------------------------\n")
puts(1,"Opening demo.fle on your system for reading......\n\n")
file_id = open("demo.fle","rb")
if file_id != -1 then
puts(1,"Successfully opened file demo.fle on your system!\n\n")
puts(1,"Read character string from demo.fle\n")
puts(1,"one character at a time using getc().....\n\n")
byte = getc(file_id)
puts(1, "The character string read in is: ")
while byte != -1 do
puts(1,byte)
byte = getc(file_id)
end while
puts(1,"\n\nDone....closing file demo.fle\n\n")
close(file_id)
end if
puts(1,"Press any key to continue......\n\n")
while get_key() = -1 do
end while
puts(1,"-----------------------------------------------------------------\n")
puts(1,"Opening demo.fle on your system to clear data......\n\n")
file_id = open("demo.fle","w")
if file_id != -1 then
puts(1,"Successfully cleared file demo.fle!\n\n")
puts(1,"Writing a Euphoria data object of ")
print(1,-36.5)
puts(1," using print().....\n\n")
print(file_id,-36.5)
puts(1,"Done....closing file demo.fle\n\n")
close(file_id)
end if
puts(1,"Press any key to continue......\n\n")
while get_key() = -1 do
end while
puts(1,"-----------------------------------------------------------------\n")
puts(1,"Opening demo.fle on your system for reading......\n\n")
file_id = open("demo.fle","r")
if file_id != -1 then
puts(1,"Successfully opened file demo.fle on your system!\n\n")
puts(1,"Read a Euphoria data object from demo.fle\n")
puts(1,"using get().....\n\n")
input_data = get(file_id)
if input_data[1] = 0 then
printf(1,"The value read in is: %.1f\n\n", {input_data[2]})
else
puts(1,"Error reading data from file!\n")
end if
puts(1,"Done....closing file demo.fle\n\n")
close(file_id)
end if
puts(1,"Press any key to continue......\n\n")
while get_key() = -1 do
end while
puts(1,"-----------------------------------------------------------------\n")
puts(1,"Opening printer PRN......\n\n")
file_id = open("LPT1","w")
if file_id != -1 then
puts(1,"Successfully opened printer for use!\n\n")
puts(1,"Printing a line on your printer using puts()\n")
puts(1,"Press 'y' to print or 'n' to skip\n\n")
byte = get_key()
while byte != 'n' do
if byte = 'y' then
puts(file_id,"*************************\n")
puts(file_id,"* Euphoria in hardcopy! *\n")
puts(file_id,"*************************\n")
end if
byte = get_key()
end while
puts(1,"Done....closing PRN\n\n")
close(file_id)
end if
Whenever you open a file for use, there is a bookmark that determines where at the byte position
the next read or write will occur in the file. When a file is opened for read, write and update
(whether in text or binary handling), the byte position is 0, meaning the start of the file.
For files open for append, the byte position is the last byte of the file. Any data output will
change the byte position value.
include file.e
ri = seek(i1,i2)
seek() sets the next read or write in file i1 (returned by open()) to byte position i2. i2 is the
number of bytes from the first byte in the file. For example, seek(0) would have the next read or
write occur at the first byte. seek(2999) would have the next read or write occur at the 30,000th
byte. A value of 0 is returned to receiving variable ri if seek() successfully changes the current
byte position. If unsuccessful, seek() returns a non-zero value.
include file.e
sequence string, seek_positions, vowels
object input_line
atom file_id, status
vowels = "aeiou"
string =
"The beauty of the seek() library routine is that you can control\n" &
"where the next write or read will occur. This will allow you to\n" &
"update any old information in your file with new data. This eliminates\n" &
"the need to maintain different versions of the same data in the\n" &
"file.\n\n"
seek_positions = {}
for element = 1 to length(string) do
if find(string[element],vowels) then
seek_positions = append(seek_positions,{element, string[element]})
string[element] = ' '
end if
end for
file_id = open("demo.fle","wb")
puts(file_id,string)
close(file_id)
puts(1,"The paragraph below has been written to a file named demo.fle,\n")
puts(1,"after the vowels were removed and stored in a sequence. This\n")
puts(1,"demo will use seek() to return the vowels back to the paragraph\n")
puts(1,"in the file\n\n")
puts(1,string)
file_id = open("demo.fle","ub")
for element = 1 to length(seek_positions) do
status = seek(file_id,seek_positions[element][1]-1)
if status = 0 then
puts(file_id,seek_positions[element][2])
end if
end for
close(file_id)
file_id = open("demo.fle","rb")
input_line = gets(file_id)
puts(1,"Adding vowels now.....\n\n")
while compare(input_line,-1) != 0 do
puts(1,input_line)
input_line = gets(file_id)
end while
If you want to know the current byte position in the file, you can find out using the where()
library routine:include file.e ri = where(i)
include file.e
sequence list_of_words, input_string
integer file_id, current_location
list_of_words = {"Euphoria ","rocks"}
puts(1,"This demo program will show how the current byte position is\n")
puts(1,"updated with every I/O made to a file, courtesy of the where()\n")
puts(1,"library routine. Remember that the current byte position is\n")
puts(1,"the number of bytes from the first byte in the file!\n\n")
file_id = open("demo.fle","wb")
current_location = where(file_id)
printf(1,"Opening file in write mode, the current byte position is %d\n\n",
current_location)
for word = 1 to length(list_of_words) do
printf(1,"Writing \"%s\" to file....\n",{list_of_words[word]})
puts(file_id,list_of_words[word])
current_location = where(file_id)
if word < 2 then
printf(1,"The next write or read will occur at %d\n\n",
current_location)
else
puts(1,"Closing file\n\n")
end if
end for
close(file_id)
file_id = open("demo.fle","ab")
current_location = where(file_id)
printf(1,"Opening file in append mode, the current byte position is %d\n\n",
current_location)
printf(1,"Writing \"%s\" to file....\n",'!')
puts(file_id,"!")
puts(1,"Closing file\n\n")
close(file_id)
puts(1,"Opening file in read mode now...\n\n")
file_id = open("demo.fle","rb")
input_string = gets(file_id)
printf(1,"The file contains the following string: %s\n",{input_string})
close(file_id)
The next few chapters will make learning Euphoria more fun, by writing programs that generate
and manipulate colourful text and graphics.include graphics.e ri = graphics_mode(i)
0 = 40×25 text, 16 grey 1 = 40×25 text, 16/8 color 2 = 80×25 text, 16 grey 3 = 80×25 text, 16/8 color 4 = 320×200 pixels, 4 color 5 = 320×200 pixels, 4 grey 6 = 640×200 pixels, BW 7 = 80×25 text, BW 11 = 720×350 pixels, BW 13 = 320×200 pixels, 16 color 14 = 640×200 pixels, 16 color 15 = 640×350 pixels, BW 16 = 640×350 pixels, 4 or 16 color 17 = 640×480 pixels, BW 18 = 640×480 pixels, 16 color 19 = 320×200 pixels, 256 color 256 = 640×400 pixels, 256 color 257 = 640×480 pixels, 256 color 258 = 800×600 pixels, 16 color 259 = 800×600 pixels, 256 color 260 = 1024×768 pixels, 16 color 261 = 1024×768 pixels, 256 colorNot all video cards will support all of these modes. The older the video card, the least number of the listed modes that will be available to you.
include graphics.e
sequence screen_modes, good_modes, bad_modes
atom counter
integer screen_set_status
screen_modes = {0,1,2,3,4,5,6,7,11,13,14,15,16,17,18,19,256,257,258,259,260,
261,262,263,-999}
counter = 1
good_modes = {}
bad_modes = {}
while screen_modes[counter] != -999 do
screen_set_status = graphics_mode(screen_modes[counter])
if screen_set_status = 0 then
good_modes = append(good_modes,screen_modes[counter])
else
bad_modes = append(bad_modes, screen_modes[counter])
end if
counter = counter + 1
end while
screen_set_status = graphics_mode(-1)
puts(1, "The modes that can be used for your video card are:\n")
print(1, good_modes)
puts(1, "\n\nThe modes that cannot be used for your video card are:\n")
print(1, bad_modes)
Whatever graphics mode you are in, it's important to know what you can and cannot do while in this
graphics mode, because going over the limits defined in the graphics mode could lead to a program
error. This library routine will give you information about the graphics mode you are in:include graphics.e rs = video_config()
{colour monitor (1 means yes, 0 means no), graphics mode number,
number of text rows, number of text columns, number of pixels across,
number of pixels down, number of colours supported, number of pages}
include graphics.e
sequence screen_modes, video_settings
atom counter
integer screen_set_status
screen_modes = {0,1,2,3,4,5,6,7,11,13,14,15,16,17,18,19,256,257,258,259,260,
261,262,263,-999}
counter = 1
while screen_modes[counter] != -999 do
screen_set_status = graphics_mode(screen_modes[counter])
if screen_set_status = 0 then
video_settings = video_config()
printf(1, "Mode %d supports the following attributes:\n\n",
{screen_modes[counter]})
if video_settings[1] = 1 then
puts(1, " Has Colour\n")
else
puts(1, " Has No Colour\n")
end if
printf(1, " Has %d text rows and %d text columns\n",
{video_settings[3], video_settings[4]})
if video_settings[5] + video_settings[6] > 0 then
printf(1, " Has %d pixels across and %d pixels down\n",
{video_settings[5], video_settings[6]})
end if
printf(1, " Has %d colours available\n", {video_settings[7]})
printf(1, " Has %d display pages accessible\n\n",
{video_settings[8]})
puts(1, "Press Any Key To Continue\n")
while get_key() = -1 do
end while
end if
counter = counter + 1
end while
if graphics_mode(-1) then
end if
Whenever you switch to any new graphics mode, the screen automatically clears any data off the screen. However, you may want to clear the screen without having to reset the graphics mode:clear_screen()
position(i1,i2)
clear_screen()
position(3,15)
puts(1, "A Program Example To Demonstrate Text Positioning")
position(4,30)
puts(1, "Written By David Gay")
position(5,20)
puts(1, "Author, \"A Beginner's Guide To Euphoria II\"")
position(8,1)
puts(1, "Top Ten Reasons why you should purchase Euphoria:")
position(9,1)
puts(1, "==============================================")
position(11, 5)
puts(1, "Number 10: It's (thankfully) not a Microsoft product.")
position(12, 5)
puts(1, "Number 9: Because C is like tax laws: too complex to figure out.")
position(13, 5)
puts(1, "Number 8: Euphoria is more fun than this year's prime time TV season.")
position(14, 5)
puts(1, "Number 7: The money spent will go to BASIC's retirement home.")
position(15, 5)
puts(1, "Number 6: Because \"Ernest Learns Euphoria\" hits the theatres soon.")
position(16, 5)
puts(1, "Number 5: You sound very smart when you say you work with atoms.")
position(17, 5)
puts(1, "Number 4: You can write word games you already know the answers to.")
position(18, 5)
puts(1, "Number 3: You can declare things without cross border shopping.")
position(19, 5)
puts(1, "Number 2: At last! A reason to use the { and } keys on the keyboard!")
position(20, 5)
puts(1, "Number 1: It's a great product!!!!! :)\n\n")
If you need to know where the cursor is on the screen, you can receive the cursor location by using the
library routine get_position():include graphics.e rs = get_position()
{current row position, current column position}
The current cursor position is always updated whenever a puts(), print(), or printf() library routine
sends any text output to the screen. A demo program is available to show how the current cursor
position changes whenever text print is sent to the screen and even when position() is used.
include graphics.e
integer element, keystroke, update
sequence some_text, current_position
clear_screen()
element = 1
update = 'y'
some_text = "As the screen is continually updated, the cursor position\n" &
"is updated automatically. get_position() will report the\n" &
"current position of the cursor.\n\n"
position(1,1)
puts(1,"An example of get_position()")
position(2,1)
puts(1,"============================")
position(25,1)
puts(1,"Press Q to quit, or any other key to display a character")
position(5,1)
while element <= length(some_text) do
if update = 'y' then
update = 'n'
puts(1,some_text[element])
current_position = get_position()
position(23,1)
printf(1,"Cursor at row %2d, column %2d",current_position)
position(current_position[1],current_position[2])
end if
keystroke = get_key()
if keystroke = 'q' then
element = length(some_text) + 1
elsif keystroke != -1 then
element = element + 1
update = 'y'
end if
end while
If text sent to the screen is longer than the number of columns per row, it is wrapped at the right
margin of the screen to continue on the next row below. There may be times where you want any text
that goes over the right margin to be simply truncated and therefore not seen. Euphoria has a library
routine that allows you to choose whether to wrap long text strings that go past the right margin or
to truncate:include graphics.e wrap(i)
include graphics.e
sequence some_string
some_string = "This is a text string that is longer than " &
"the width of your screen. See how wrap() handles the " &
"output of the text string when printed. "
for modes = 1 to 0 by -1 do
wrap(modes)
printf(1,"When wrap(%d) is used:\n\n", modes)
puts(1,some_string & "\n\n")
end for
The standard 25 rows in most graphics modes is more than enough for displaying full-screen text. But
if you need to show a lot of text data on the screen, having more rows per screen would help. For text modes only, Euphoria has a library routine that can change the number of rows that can be
displayed on the screen:include graphics.e ri = text_rows(i)
include graphics.e
integer current_rows
sequence text_length
puts(1, "The following will demonstrate how to use text_rows() to\n")
puts(1, "increase the number of rows available in this program. Note\n")
puts(1, "how the spacing between the lines narrows. For those\n")
puts(1, "text rows that are not supported, this program will simply skip\n")
puts(1, "them. You will be required to press any key in order for this\n")
puts(1, "program to continue. Press any key to start the demonstration\n")
while get_key() = -1 do
end while
text_length = {25,28,43,50}
for ix = 1 to 4 do
current_rows = text_rows(text_length[ix])
if current_rows = text_length[ix] then
for iy = 1 to text_length[ix] do
print(1, iy)
if iy < text_length[ix] then
puts(1, "\n")
end if
end for
while get_key() = -1 do
end while
end if
end for
current_rows = text_rows(25)
Another way to handle large amounts of text on the screen is by scrolling. Scrolling involves treating the screen as a movable window to view any part of the text. It's like riding in a glass
elevator: as you go up or down, the view from your position will appear to vertically roll.
Wordprocessors use this approach to handle documents larger than the size of the screen. While you
could write some program code to perform text scrolling, Euphoria has a powerful library routine that can do
this for you:include graphics.e scroll(i1,i2,i3)
include graphics.e
integer keystroke, current_position
clear_screen()
position(5,1)
puts(1, repeat('Í',80))
position(20,1)
puts(1, repeat('Í',80))
position(11,25)
puts(1, "ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»")
position(12,25)
puts(1, "º Welcome To The SCROLL ZONE º")
position(13,25)
puts(1, "ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ")
position(22,1)
puts(1, "Press 8 for up, 2 for down, or q to quit this program")
keystroke = get_key()
current_position = 11
while keystroke != 'q' do
if keystroke = '8' and current_position > 6 then
scroll(1,6,19)
current_position = current_position - 1
end if
if keystroke = '2' and current_position < 17 then
scroll(-1,6,19)
current_position = current_position + 1
end if
keystroke = get_key()
end while
Perhaps the best way to present text is in colour. This tutorial, for example, uses colour to separate Euphoria statements and specific points apart from the regular text. There is a library routine you can use to present text in a certain colour.include graphics.e text_color(i)
1 = blue 2 = green 3 = cyan 4 = red 5 = magenta 6 = brown 7 = white 8 = gray 9 = bright blue 10 = bright green 11 = bright cyan 12 = bright red 13 = bright magenta 14 = yellow 15 = bright white (note: 0 = black)When your program terminates, any screen text after will appear in the colour set by the last text_color() issued. As a result your program should issue a text_color(7) (white) followed by a puts("\n") before it completes. text_color() works in any text or pixel-graphics modes. A demo program is available to show one use of text_color().
include graphics.e
integer foreground_colour
sequence list_of_colours, already_used
clear_screen()
list_of_colours = {"blue","green","cyan","red","magenta","brown",
"white","gray","bright blue","bright green",
"bright cyan","bright red","bright magenta",
"yellow","bright white"}
already_used = {}
for ix = 1 to 10 do
foreground_colour = rand(15)
while find(foreground_colour,already_used) do
foreground_colour = rand(15)
end while
already_used = already_used & foreground_colour
text_color(foreground_colour)
printf(1, "Text in %s\n",{list_of_colours[foreground_colour]})
end for
To set the background colour of any text printed in a text mode, or the entire background of a screen
in pixel graphics mode, you use the following library routine:include graphics.e bk_color(i)
include graphics.e
clear_screen()
text_color(15)
bk_color(2)
position(13,9)
puts(1,"When using bk_color() in text mode, only the background colour")
position(14,10)
puts(1,"of the text itself is affected. Press any key to continue...")
while get_key() = -1 do
end while
if graphics_mode(18) = 0 then
text_color(15)
bk_color(2)
position(14,10)
puts(1,"When using bk_color() in pixel-graphics mode, the background")
position(15,10)
puts(1,"colour of the entire screen is changed. Press any key to end.")
while get_key() = -1 do
end while
if graphics_mode(-1) then
puts(1,"Resetting to the previous screen does not work for you!")
end if
end if
Rather than have text sit motionless on the screen, you can make it more interesting to look at
through animation, as in moving groups of text horizontally and vertically around the screen. To
perform this trick of movement, you must be able to grab text right off the screen, then re-display it
at a new location. Euphoria has two library routines that can do this for you.include image.e rs = save_text_image(s1,s2)
{top left row, top left column}
s2 is also a sequence made up of two atoms, the first being the bottom right row, the
second being the bottom right column:
{bottom right row, bottom right column}
The saved data in rs is a sequence made up of sequence elements. Each sequence element
represents a row of text in the rectangular area of the screen that was saved. The sequence elements
themselves are made up of atom values. The odd-numbered elements are the actual text characters, and
the even-numbered elements are values representing the combined foreground and background colours of
each text character. So saving a rectangular area containing the following text:Welcome to Euphora!would retrieve the value:
{{87,13,101,13,108,13,99,13,111,13,109,13,101,13,32,13,84,13,111,13},
{69,13,117,13,112,13,104,13,111,13,114,13,105,13,97,13,33,13,32,13}}
The foreground/background colour value always FOLLOWS the text character it is associated with. This
value, called the attribute byte, is created by multiplying the background number by 16, then adding
the foreground colour number to the result. In the example above, the text foreground was 13 or bright magenta with a background of 0 or black, so the attribute byte was 0 times 16, giving 0, then
we added 13 to the result, giving 13.include image.e display_text_image(s1,s2)
{top left row, top left column}
s2 would very likely be the saved data obtained by the save_text_image() library routine. You could, however, create your own sequences to be displayed by display_text_image() using the structure shown to you earlier. Both save_text_image()
and display_text_image() only work in text_modes. A demo program is available to show how
save_text_image() and display_text_image() moves a block of text around the screen.
include image.e
sequence stored_image
integer input_key, line, column
line = 1
column = 1
bk_color(2)
clear_screen()
text_color(14)
position(2,2)
puts(1, "******************************")
position(3,2)
puts(1, "* Use the left, right, up, *")
position(4,2)
puts(1, "* and down arrow keys to *")
position(5,2)
puts(1, "* move box, press Q to quit! *")
position(6,2)
puts(1, "******************************")
stored_image = save_text_image({1,1},{7,32})
input_key = get_key()
while input_key != 'q'do
display_text_image({line, column},stored_image)
if input_key = 328 and line > 1 then
line = line - 1
end if
if input_key = 336 then
line = line + 1
end if
if input_key = 331 and column > 1 then
column = column - 1
end if
if input_key = 333 then
column = column + 1
end if
input_key = get_key()
end while
bk_color(0)
text_color(7)
The next chapter promises to be more entertaining, as it shows you how to work with pixels and even
graphic shapes in a pixel graphics mode.include graphics.e pixel(o,s)
{pixel column location, pixel row location}
pixel(6,{200,100})
pixel({9,2,14},{63,120})
include graphics.e
integer x_or_y_work_variable
if graphics_mode(18) then
puts(1, "640 X 480 mode, 16 colours, not supported!\n")
else
text_color(15)
position(1,1)
puts(1,"Drawing A Shape Using pixel()")
position(25,1)
puts(1, "Press q to end this program")
for ix = 100 to 300 do
pixel(9, {ix , ix})
end for
pixel(repeat(12,400),{100,100})
x_or_y_work_variable = 300
for ix = 300 to 500 do
pixel(10, (ix & x_or_y_work_variable))
x_or_y_work_variable = x_or_y_work_variable - 1
end for
for ix = 100 to 300 do
pixel(11, {100, ix})
pixel(13, {500, ix})
end for
for ix = 100 to 500 do
pixel(14, {ix, 300})
end for
while get_key() != 'q' do
end while
if graphics_mode(-1) then
puts(1, "Unable To Reset\n")
end if
end if
You can find out what colour one or a series of pixels on the screen is set to by using the get_pixel() library routine:
include graphics.e ro = get_pixel(s)
{pixel column location, pixel row location} then the colour of the pixel at that location is returned, and is stored in receiving variable ro. If s is in the format: {pixel column location, pixel row location, number of pixels} then a series of colours is returned as a sequence, and stored in receiving variable ro. This sequence is all the colours of the pixels starting at that pixel column and pixel row location, and continuing right for the specified number of pixels.
one_colour = get_pixel({167,231})
series_of_colours = get_pixel({1500,10,15})
include graphics.e
sequence copy_buffer
if graphics_mode(18) then
puts(1, "Mode 18 not supported\n")
else
pixel({10,10,10,10,10,10,10,10,10,10,10,10,15,15,15,15,15,15,15,15,
15,15,15,15,12,12,12,12,12,12,12,12,12,12,12,12},{300,100})
position(20,1)
puts(1, "Press 1 to continue")
while get_key() != '1' do
end while
copy_buffer = get_pixel({300,100,36})
for ix = 205 to 220 do
pixel(copy_buffer,{300,ix})
end for
position(20,1)
puts(1, "Press 2 to end program")
while get_key() != '2' do
end while
if graphics_mode(-1) then
puts(1, "Reset failed!\n")
end if
end if
Remember the demo program that created a shape using pixel()? While this worked well, it was awkward using pixel() to create even this simple shape. Euphoria has a library routine that can draw a line of pixels on the screen using a series of pixel screen locations:
include graphics.e draw_line(i,s)
{{pixel column location, pixel row location},
{pixel column location, pixel row location},
{pixel column location, pixel row location},...}
draw_line(14,{{50,50},{150,50},{150,150},{50,150},{50,50}})
include graphics.e
if graphics_mode(18) then
puts(1, "640 X 480 mode, 16 colours, not supported!\n")
else
text_color(15)
position(1,1)
puts(1, "Drawing A Shape Using draw_line()")
position(25,1)
puts(1, "Press q to end this program")
draw_line(9,{{100,100},{300,300}})
draw_line(12,{{100,100},{500,100}})
draw_line(10,{{300,300},{500,100}})
draw_line(11,{{100,100},{100,300}})
draw_line(13,{{500,100},{500,300}})
draw_line(14,{{100,300},{500,300}})
while get_key() != 'q' do
end while
if graphics_mode(-1) then
puts(1, "Unable To Reset\n")
end if
end if
include graphics.e polygon(i1,i2,s)
include graphics.e
include image.e
if graphics_mode(18) = 0 then
text_color(15)
position(1,34)
puts(1,"Polygon Fun!")
position(30,30)
puts(1,"Press any key to end")
position(6,16)
puts(1,"polygon(6,1,{{10,50},{100,50},{100,140},{10,140}})")
polygon(6,1,{{10,50},{100,50},{100,140},{10,140}})
position(13,16)
puts(1,"polygon(13,0,{{55,160},{10,240},{100,240}})")
polygon(13,0,{{55,160},{10,240},{100,240}})
position(19,16)
puts(1,"polygon(2,1,{{30,260},{100,260},{80,340},{10,340}})")
polygon(2,1,{{30,260},{100,260},{80,340},{10,340}})
position(25,16)
puts(1,"polygon(12,0,{{10,360},{55,360},{55,400},{100,400},")
position(26,16)
puts(1," {100,440},{10,440}})")
polygon(12,0,{{10,360},{55,360},{55,400},{100,400},
{100,440},{10,440}})
while get_key() = -1 do
end while
if graphics_mode(-1) then
puts(1,"Reset Failure")
end if
end if
Drawing shapes with multiple sides is not too difficult, even without library routines like polygon()
. Drawing oval shapes is a different matter entirely. A background in trigonometry was the only way
you could draw any kind of circle or ellipse shape. Fortunately, Euphoria comes to the rescue with
a library routine that makes drawing circles and ellipses easy:
include graphics.e ellipse(i1,i2,s1,s2)
{pixel column location, pixel row location}
include graphics.e
integer input_key, tl1, tl2, br1, br2, update
tl1 = 200
tl2 = 100
br1 = 400
br2 = 300
update = 'y'
if graphics_mode(18) then
puts(1, "Mode not available")
else
position (28,1)
puts(1, "Press 1 to widen horizontally, 2 to narrow horizontally")
position (29,1)
puts(1, " 3 to widen vertically, 4 to narrow vertically")
position (30,1)
puts(1, " q to quit")
input_key = get_key()
while input_key != 'q' do
input_key = get_key()
if update = 'y' then
update = 'n'
ellipse(15, 0, {tl1,tl2},{br1,br2})
polygon(3,0, {{tl1,tl2},{br1,tl2},{br1,br2},{tl1,br2}})
end if
if input_key = '1' then
ellipse(0, 0, {tl1,tl2},{br1,br2})
polygon(0,0, {{tl1,tl2},{br1,tl2},{br1,br2},{tl1,br2}})
tl1 = tl1 - 3
br1 = br1 + 3
update = 'y'
end if
if input_key = '2' then
ellipse(0, 0, {tl1,tl2},{br1,br2})
polygon(0,0, {{tl1,tl2},{br1,tl2},{br1,br2},{tl1,br2}})
tl1 = tl1 + 3
br1 = br1 - 3
update = 'y'
end if
if input_key = '3' then
ellipse(0, 0, {tl1,tl2},{br1,br2})
polygon(0,0, {{tl1,tl2},{br1,tl2},{br1,br2},{tl1,br2}})
tl2 = tl2 - 3
br2 = br2 + 3
update = 'y'
end if
if input_key = '4' then
ellipse(0, 0, {tl1,tl2},{br1,br2})
polygon(0,0, {{tl1,tl2},{br1,tl2},{br1,br2},{tl1,br2}})
tl2 = tl2 + 3
br2 = br2 - 3
update = 'y'
end if
end while
if graphics_mode(-1) then
puts(1, "Mode not available")
end if
end if
The next chapter will show you how to make graphic images more animated instead of sitting motionless
on the screen.include image.e rs = save_image(s1,s2)
{{pixel colour, pixel colour, pixel colour, pixel colour,...}
{pixel colour, pixel colour, pixel colour, pixel colour,...}
{pixel colour, pixel colour, pixel colour, pixel colour,...},...}
{pixel column location, pixel row location}
include image.e display_image(s1,s2)
{pixel column location, pixel row location}
include image.e
include graphics.e
sequence ball, bounce
bounce =
{200,200.125,200.375,200.75,201.25,201.875,202.625,203.5,204.5,205.625,
206.875,208.25,209.75,211.375,213.125,215,217,219.125,221.375,223.75,226.25,
228.875,231.625,234.5,237.5,240.625,243.875,247.25,250.75,254.375,258.125,
262,266,270.125,274.375,278.75,283.25,287.875,292.625,297.5,302.5,307.625,
312.875,318.25,323.75,329.375,335.125,341,347,353.125}
if graphics_mode(18) then
puts(1, "Mode Set Failure")
else
clear_screen()
ellipse(5, 1, {200,200}, {300,300})
for iy = 234 to 266 do
for ix = 200 to 300 do
if get_pixel({ix, iy}) = 5 then
pixel(15,{ix, iy})
end if
end for
end for
for iy = 267 to 300 do
for ix = 200 to 300 do
if get_pixel({ix, iy}) = 5 then
pixel(9,{ix, iy})
end if
end for
end for
ball = save_image({193,193},{308,308})
clear_screen()
position(1,1)
puts(1, "Press q to end this bouncing ball demo!")
while 1 = 1 do
if get_key() = 'q' then
exit
end if
for ix = 1 to length(bounce) do
display_image({270,bounce[ix]},ball)
end for
for ix = length(bounce) to 1 by -1 do
display_image({270,bounce[ix]},ball)
end for
end while
if graphics_mode(-1) then
puts(1, "Mode Set Failure")
end if
end if
Another kind of animation is colour-shifting, where one or more colours that the text or graphic image is in is changed. One way of doing it is to perform a save_image() or save_text_image(), search through the retrieved sequence value for the colour to be changed, and change where a match is made. Once done, you redisplay using either display_image() or display_text_image(). However, that is a lot of work just to change the colour of something displayed on the screen. Can we change the image colour without having the image itself redisplayed?
include image.e rs = get_all_palette()
{{red level, green level, blue level}, <-----colour 0
{red level, green level, blue level}, <-----colour 1
{red level, green level, blue level}, <-----colour 2
{red level, green level, blue level},...} <-----colour 3
include graphics.e
include image.e
sequence colour_list,rgb_levels
colour_list = {{"BLACK",0},{"BLUE",0},{"GREEN",0},{"CYAN",0},{"RED",0},
{"MAGENTA",0},{"BROWN",0},{"WHITE",0},{"GRAY",0},
{"BRIGHT BLUE",0},{"BRIGHT GREEN",0},{"BRIGHT CYAN",0},
{"BRIGHT RED",0},{"BRIGHT MAGENTA",0},{"YELLOW",0},
{"BRIGHT WHITE",0}}
if graphics_mode(3) = 0 then
rgb_levels = get_all_palette()
if graphics_mode(-1) then
puts(1,"Reset Failure!")
end if
end if
if graphics_mode(3) = 0 then
for rgb = 1 to length(colour_list) do
colour_list[rgb][2] = rgb_levels[rgb]
end for
position(1,10)
puts(1," RGB Intensity Makeup")
position(2,10)
puts(1," --------------------")
position(3,10)
puts(1,"Colour Red Green Blue")
position(4,10)
puts(1,"============== === ===== ====")
for colours = 1 to length(colour_list) do
position(5+colours,10)
printf(1,"%-14s %2d %2d %2d",
{colour_list[colours][1],colour_list[colours][2][1],
colour_list[colours][2][2],
colour_list[colours][2][3]})
end for
position(25,10)
puts(1,"Press any key to end")
while get_key() = -1 do
end while
if graphics_mode(-1) then
puts(1,"Reset Failure!")
end if
end if
Now that you have a copy of the palette, you can start changing colour numbers to mean a different colour. This is done by changing either one or more of the RGB intensity levels assigned to that colour. Here is the library routine that can change a colour's RGB intensity:
include graphics.e ro = palette(i,s)
{red intensity level, green intensity level, blue intensity level}
include graphics.e
object changed_palette
integer Red_, Green_, Blue_, input
if graphics_mode(18) then
puts(1, "Mode Set Failure")
else
for ix = 0 to 60 do
ellipse(14, 1, {250-ix, 180-ix}, {350+ix, 280+ix})
ellipse(15, 0, {249-ix, 179-ix}, {351+ix, 281+ix})
end for
Red_ = 0
Green_ = 0
Blue_ = 0
changed_palette = palette(14, {Red_, Green_, Blue_})
Red_ = changed_palette[1]
Green_ = changed_palette[2]
Blue_ = changed_palette[3]
input = get_key()
position(1,9)
puts(1,"This program will demonstrate how to modify the palette")
position(2,9)
puts(1,"colour code for yellow into another colour by manipulating")
position(3,9)
puts(1,"the RGB colour code. Use 1 and 2 to change the red tint,")
position(4,9)
puts(1,"3 and 4 to change the green tint, and 5 and 6 to change the")
position(5,9)
puts(1,"blue tint. Press q when you are finished using this program.")
while input != 'q' do
if input = '1' and Red_ > 0 then
Red_ = Red_ - 1
end if
if input = '2' and Red_ < 63 then
Red_ = Red_ + 1
end if
if input = '3' and Green_ > 0 then
Green_ = Green_ - 1
end if
if input = '4' and Green_ < 63 then
Green_ = Green_ + 1
end if
if input = '5' and Blue_ > 0 then
Blue_ = Blue_ - 1
end if
if input = '6' and Blue_ < 63 then
Blue_ = Blue_ + 1
end if
changed_palette = palette(14, {Red_, Green_, Blue_})
position(28,19)
printf(1, "Red: %.2d Green: %.2d Blue: %.2d",
{Red_,Green_,Blue_})
input = get_key()
end while
if graphics_mode(-1) then
puts(1, "Mode Set Failure")
end if
end if
If you want to change all the colours in the palette, you can either issue palette() once for every colour, or use a Euphoria library routine created to change all colours at once.
include graphics.e all_palette(s)
{{red level, green level, blue level}, <---- new colour for 0
{red level, green level, blue level}, <---- new colour for 1
{red level, green level, blue level}, <---- new colour for 2
{red level, green level, blue level},...} <---- new colour for 3
include graphics.e
include image.e
sequence colours_one_to_five, original
if graphics_mode(18) = 0 then
original = get_all_palette()
clear_screen()
text_color(7)
puts(1,"This program will attempt to demonstrate all_palette() by\n")
puts(1,"changing 5 colour numbers without having to redisplay\n")
puts(1,"the text again.\n\n")
colours_one_to_five = original
colours_one_to_five[2..6] = {{0,63,0},{0,63,0},{0,63,0},{0,63,0},
{0,63,0}}
for ix = 0 to 15 do
text_color(ix)
print(1,ix)
puts(1," ")
end for
for retry = 1 to 2 do
text_color(7)
position(20,1)
if retry = 1 then
puts(1,
"These are the colours present in the default palette.\n")
puts(1,
"Press any key to change the first 5 colours to green.\n")
end if
if retry = 2 then
all_palette(colours_one_to_five)
puts(1,
"Colour numbers from 1 to 5 now have an RGB setting \n")
puts(1,
"of {0,63,0}, or pure green. Press any key to end. \n")
end if
while get_key() = -1 do
end while
end for
all_palette(original)
end if
if graphics_mode(-1) then
puts(1,"reset failure\n")
end if
It is important to understand how to change palettes in graphics modes, as you will need to do so when dealing with .BMP files, or Windows bitmaps. The next chapter will introduce you to bitmaps, as well as how to direct screen output (text or pixel graphics images) to multiple screen pages.
include image.e ro = read_bitmap(s)
{{{red level, green level, blue level},...},
{{pixel colour, pixel colour, pixel colour,...},
{pixel colour, pixel colour, pixel colour,...},
{pixel colour, pixel colour, pixel colour,...},...}}
1 = open failed (probably spelt the name of the file wrong) 2 = unexpected end of file (the end of the file was reached before all the required data was read in 3 = unsupported format (Euphoria may not recognize that format even though other paint programs can load it with no problems)
include graphics.e
include image.e
sequence demo_bitmap
if graphics_mode(18) then
puts(1, "Mode Failure")
else
demo_bitmap = read_bitmap("d2105a.bmp")
position(3,10)
puts(1, "This image was made using Windows Paintbrush program.")
position(4,10)
puts(1, "It uses a different palette numbering scheme than what")
position(5,10)
puts(1, "Euphoria has, so the colours come out wrong. But if you")
position(6,10)
puts(1, "press 'n'..........")
display_image({200,200}, demo_bitmap[2])
while get_key() != 'n' do
end while
position(3,10)
puts(1, "......we apply the palette read in with the bitmap after ")
position(4,10)
puts(1, "dividing it by four to scale it for use with Euphoria. ")
position(5,10)
puts(1, "The all_palette() statement is handy for displaying bitmaps")
position(6,10)
puts(1, "with a different colour palette. Press 'q' to quit now. ")
all_palette((demo_bitmap[1]/4))
while get_key() != 'q' do
end while
if graphics_mode(-1) then
puts(1, "Mode Failure")
end if
end if
Your Euphoria programs can take screen images and save them into a .BMP file to be viewed and edited by a paint program, or loaded and displayed by another Euphoria program using read_bitmap().
include image.e ri = save_bitmap(s1,s2)
0 = .BMP file created successfully (it works!) 1 = .BMP file open failed (probably mis-spelled the name) 4 = .BMP file invalid mode (invalid graphic mode or parameters received)
include graphics.e
include image.e
atom blue, increment, status
sequence palette_mode,new_blue, previous_blue, bitmap_data, bitmap_file
blue = 30
increment = 1
if graphics_mode(18) then
puts(1,"Unable to go into mode 18!")
else
palette_mode = get_all_palette()
position(1,3)
text_color(11)
puts(1,"How to build a bitmap using Euphoria, Part I")
position(24,5)
puts(1,"Press any key to continue demo")
for ix = 0 to 50 by 4 do
ellipse(2,0,{100+ix,100-ix},{199-ix,199+ix})
ellipse(2,0,{100-ix,100+ix},{199+ix,199-ix})
polygon(1,0,{{50,50},{50,249},{249,249},{249,50}})
end for
position(20,1)
puts(1,"1) Define an area on the screen you want to save")
while get_key() = -1 do
if blue = 63 then
increment = -3
elsif blue = 30 then
increment = 3
end if
blue = blue + increment
new_blue = {0,0,0}
new_blue[3] = blue
previous_blue = palette(1,new_blue)
end while
polygon(0,0,{{50,50},{50,249},{249,249},{249,50}})
bitmap_data = save_image({50,50},{249,249})
polygon(0,1,{{50,50},{50,249},{249,249},{249,50}})
for ix = 3 to 18 do
position(ix,10)
print(1,palette_mode[-2+ix])
end for
position(20,1)
puts(1,"2) Get the current mode screen palette..........")
while get_key() = -1 do
end while
palette_mode = palette_mode * 4
for ix = 3 to 18 do
position(ix,10)
print(1,palette_mode[-2+ix])
end for
position(20,1)
puts(1,"3) ....and scale it for use as a bitmap palette. ")
while get_key() = -1 do
end while
clear_screen()
puts(1,"You then use both the palette and the bitmap data to\n")
puts(1,"construct the bitmap using save_image..\n")
bitmap_file = {}
bitmap_file = append(bitmap_file,palette_mode)
bitmap_file = append(bitmap_file,bitmap_data)
while get_key() = -1 do
end while
if graphics_mode(-1) then
puts(1,"Unable to reset mode!")
end if
status = save_bitmap(bitmap_file,"d2107a.BMP")
if status != 0 then
puts(1,"Bitmap creation failure!")
end if
end if
If you find the steps taken to assemble a sequence used by save_bitmap() to create a .BMP file a little daunting, Euphoria has another approach that is somewhat simpler:
include image.e ri = save_image(o,s)
{{top left pixel colmn, top left pixel row},
{bottom right pixel column, bottom right pixel row}}
include graphics.e
include image.e
atom blue, increment, status
sequence palette_mode,new_blue, previous_blue
blue = 30
increment = 1
if graphics_mode(18) then
puts(1,"Unable to go into mode 18!")
else
palette_mode = get_all_palette()
position(1,3)
text_color(11)
puts(1,"How to build a bitmap using Euphoria, Part II")
position(24,5)
puts(1,"Press any key to continue demo")
for ix = 0 to 50 by 4 do
ellipse(2,0,{100+ix,100-ix},{199-ix,199+ix})
ellipse(2,0,{100-ix,100+ix},{199+ix,199-ix})
polygon(1,0,{{50,50},{50,249},{249,249},{249,50}})
end for
position(20,1)
puts(1,"Define an area on the screen you want to save")
while get_key() = -1 do
if blue = 63 then
increment = -3
elsif blue = 30 then
increment = 3
end if
blue = blue + increment
new_blue = {0,0,0}
new_blue[3] = blue
previous_blue = palette(1,new_blue)
end while
all_palette(palette_mode)
polygon(0,0,{{50,50},{50,249},{249,249},{249,50}})
status = save_screen({{50,50},{249,249}},"d2109a.bmp")
polygon(0,1,{{50,50},{50,249},{249,249},{249,50}})
clear_screen()
puts(1,"save_screen() produces the same result as save_bitmap()\n")
puts(1,"but without the steps shown in the save_bitmap() demo.\n")
while get_key() = -1 do
end while
if graphics_mode(-1) then
puts(1,"Unable to reset mode!")
end if
end if
With handling .BMP files now explored, let's move on to handling screen pages. Each screen page is assigned a number, beginning with screen page 0. The default active page (where screen output is sent) and the default display page (the page that you want displayed on the screen) are both screen page 0. To change the screen page where all screen output is sent to, you use the following library routine below:
include image.e set_active_page(i)
include image.e set_display_page(i)
include graphics.e
include image.e
include get.e
integer file_id
sequence capture_buffer, video_data
video_data = video_config()
clear_screen()
printf(1, "%d pages available, 5 pages required\n", {video_data[8]})
if video_data[8] < 5 then
puts(1, "Sorry, you have insufficient pages on your video card\n")
else
puts(1, "Stand By, Loading Each Virtual Page\n")
set_active_page(1)
file_id = open("now.bin","rb")
capture_buffer = get(file_id)
close(file_id)
display_text_image({1,1}, capture_buffer[2])
set_active_page(2)
file_id = open("this.bin","rb")
capture_buffer = get(file_id)
close(file_id)
display_text_image({1,1}, capture_buffer[2])
set_active_page(3)
file_id = open("is.bin","rb")
capture_buffer = get(file_id)
close(file_id)
display_text_image({1,1}, capture_buffer[2])
set_active_page(4)
file_id = open("ppower.bin","rb")
capture_buffer = get(file_id)
close(file_id)
display_text_image({1,1}, capture_buffer[2])
set_active_page(0)
clear_screen()
puts(1, "Done....to cycle through all the four pages, press 'n'.\n")
puts(1, "Press any key to start cycling now.\n")
while get_key() = -1 do
end while
for ix = 1 to 4 do
set_display_page(ix)
while get_key() != 'n' do
end while
end for
clear_screen()
end if
set_active_page(0)
set_display_page(0)
If you want to know what screen page you have made either an active page or a display page, there are two library routines that can help you find out. To determine which screen page is the current active page, you use:
include image.e ri = get_active_page()
include image.e ri = get_display_page()
include machine.e use_vesa(i)
rs = date()
{number of years since 1900, month number (where January is 1),
day of month (starting at one), hour (between 0 and 23),
minute (between 0 and 59), second (between 0 and 59),
day of the week (where Sunday is 1),
number of days since the start of the year}
integer curr_year, curr_day, curr_day_of_year,As a programmer, you may be interested in time of a differenct kind, as in elapsed time taken to complete a process. This is particularly the case if you are interested in learning how long a section of code in your program takes to complete, or even to delay program execution for an interval of time. Here's the library routine that can help you do this:
curr_hour, curr_minute, curr_second
sequence system_date, word_week, word_month, notation,
curr_day_of_week, curr_month
word_week = {"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"}
word_month = {"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"}
system_date = date()
curr_year = system_date[1]
curr_month = word_month[system_date[2]]
curr_day = system_date[3]
curr_hour = system_date[4]
curr_minute = system_date[5]
curr_second = system_date[6]
curr_day_of_week = word_week[system_date[7]]
curr_day_of_year = system_date[8]
if curr_hour >= 12 then
notation = "p.m."
else
notation = "a.m."
end if
if curr_hour > 12 then
curr_hour = curr_hour - 12
end if
if curr_hour = 0 then
curr_hour = 12
end if
puts(1, "\nHello!\n\n")
printf(1, "Today is %s, %s %d, 19%d.\n", {curr_day_of_week,
curr_month,
curr_day, curr_year})
printf(1, "The time is %.2d:%.2d:%.2d %s\n", {curr_hour, curr_minute,
curr_second, notation})
printf(1, "It is %3d days into the current year.\n", {curr_day_of_year})
ra = time()
include graphics.e
atom minutes, seconds, elapsed_seconds, halt_program
clear_screen()
position(25,1)
text_color(9)
puts(1,"Press Q To Quit Demo Or Let Run For 5 Minutes")
text_color(2)
halt_program = ' '
while halt_program != 'q' do
halt_program = get_key()
elapsed_seconds = time()
minutes = elapsed_seconds / 60
seconds = remainder(elapsed_seconds, 60)
position(10, 30)
printf(1, "Program run time: %.2d:%.2d", {minutes, seconds})
if minutes >= 4 then
if seconds >= 50 then
if seconds >= 55 then
text_color(12 + 16)
else
text_color(14)
end if
end if
end if
if minutes >= 5 then
clear_screen()
halt_program = 'q'
end if
end while
0.055 seconds resolution is a very small fraction of time, too small to perceive, and is fine enough to serve your programming purposes. However, for programming that requires a very fine resolution of time, 0.055 seconds may be too large. If you want to measure time in even smaller steps, you have to force the operating system to fetch the time more often per second. By default, the time is checked 18.2 times per second, here is a library routine that forces more checking per second and thus giving you a finer resolution of time:include machine.e tick_rate(i) [Note: DOS32 only]
include machine.e
atom precision_rate, ticker, seconds
precision_rate = .01
ticker = 1/precision_rate
tick_rate(ticker)
clear_screen()
position(22,1)
puts(1,"Press Any Key To End This Program")
seconds = 0
while get_key() = -1 do
position(12,24)
seconds = time()
printf(1,"Program Running For %03.2f Seconds",seconds)
end while
clear_screen()
The system time isn't the only thing you can get from the operating system. You can also get directory information from the hard drive and floppy drives. Here is the library routine that can do this for you:
include file.e ro = dir(s)
{{s1, s2, i3, i4, i5, i6, i7, i8, i9},
{s1, s2, i3, i4, i5, i6, i7, i8, i9},...}
s1 - File or directory name s2 - Attribute(s) i3 - Size in bytes i4 - Year modified i5 - Month modified i6 - Day modified i7 - Hour modified i8 - Minute modified i9 - Second modified
d - directory r - read only file h - hidden file s - system file v - volume id a - archive file
include file.e
include graphics.e
sequence entry_type, format_string
integer keystroke, update, display_from, length_window, current_entry
object cur_dir_info
clear_screen()
position(21,1)
text_color(7)
puts(1,"Page Up And Page Down Keys : Scroll Data ")
position(22,1)
text_color(7)
puts(1,"Up And Down Arrow Keys: Move Highlight Line ")
position(23,1)
text_color(7)
puts(1,"ENTER Key: Get File Or Directory Attributes ")
position(24,1)
text_color(7)
puts(1,"Press Q Key To Quit Program")
position(2,1)
puts(1,
" Object Object Object Date Time \n")
puts(1,
" Name Type Size Modified Modified\n")
puts(1,
"____________ ___________ _______ __________ ________\n")
format_string = "%-12s %11s %7d %04d\\%02d\\%02d %02d:%02d:%02d\n"
display_from = 1
length_window = 10
cur_dir_info = dir(".")
current_entry = 1
update = 'y'
keystroke = 0
while keystroke != 'q' do
keystroke = get_key()
if keystroke = 13 then
position(18,1)
puts(1,repeat(' ',78))
if length(cur_dir_info[current_entry][2]) > 0 then
position(18,1)
text_color(7)
puts(1,"Entry Attributes: ")
for attribz = 1 to length(cur_dir_info[current_entry][2]) do
puts(1,cur_dir_info[current_entry][2][attribz])
puts(1, " ")
end for
text_color(8)
end if
end if
if keystroke = 337 then
if (display_from + length_window - 1) <
length(cur_dir_info) then
display_from = display_from + 1
current_entry = display_from
update = 'y'
end if
end if
if keystroke = 329 then
if display_from > 1 then
display_from = display_from - 1
current_entry = display_from
update = 'y'
end if
end if
if keystroke = 336 then
if current_entry < length(cur_dir_info) and
current_entry < (display_from + length_window - 1) then
update = 'y'
current_entry = current_entry + 1
end if
end if
if keystroke = 328 then
if current_entry > 1 and current_entry > display_from then
update = 'y'
current_entry = current_entry - 1
end if
end if
if update = 'y' then
update = 'n'
position(6,1)
for line = display_from to (display_from + (length_window-1)) do
if line <= length(cur_dir_info) then
if find('d',cur_dir_info[line][2]) then
entry_type = "<DIRECTORY>"
else
entry_type = " -FILE- "
end if
if current_entry = line then
text_color(15)
else
text_color(8)
end if
printf(1,format_string,{cur_dir_info[line][1],
entry_type,
cur_dir_info[line][3],
cur_dir_info[line][4],
cur_dir_info[line][5],
cur_dir_info[line][6],
cur_dir_info[line][7],
cur_dir_info[line][8],
cur_dir_info[line][9]})
else
puts(1,repeat(' ',78) & "\n")
end if
end for
end if
end while
clear_screen()
If you want to know what directory you are currently in, you can use the following library routine:include file.e rs = current_dir()
include file.e
sequence where_am_i
where_am_i = current_dir()
puts(1,"Hello!\n")
printf(1,"This demo runs from directory %s\n",{where_am_i})
system(s,i)
0 - clear the screen by restoring graphics mode of Euphoria program 1 - beep, wait for key press, and then restore graphics mode 2 - do not restore graphics mode
system("type C:\\autoexec.bat | more ",2)
We will conclude our discussion of Euphoria and DOS in the next chapter by showing how to use DOS to control the execution of a Euphoria program, and also how to end the program in more ways than one.
rs = command_line()
{the EX.EXE file name (including the directory where it is stored),
the name of your Euphoria program being run,
the first parameter the program accepts,...}
{the Euphoria program name (including the directory where it is stored),
the Euphoria program name (including the directory where it is stored),
the first parameter the program accepts,...}
sequence command_line_data
atom number_of_parameters
clear_screen()
command_line_data = command_line()
number_of_parameters = length(command_line_data) - 2
if number_of_parameters = 0 then
puts(1, "\nPlease run the demo BATCH file to execute this program\n")
else
printf(1, "\n%d parameter(s) were passed to this program\n\n",
{number_of_parameters})
for ix = 3 to length(command_line_data) do
printf(1, "%s is parameter %d\n", {command_line_data[ix],
ix-2})
end for
end if
Here's the associated batch file:
ex d2305a.ex cats dogs budgies mice
ro = getenv(s) [Note: DOS32 only]
object path_settings
clear_screen()
path_settings = getenv("PATH")
if sequence(path_settings) then
puts(1,
"\nThe following directories are in your DOS PATH variable:\n\n")
for ix = 1 to length(path_settings) do
if path_settings[ix] = ';' then
puts(1, "\n")
else
puts(1, path_settings[ix])
end if
end for
puts(1, "\n\nScan completed. Have a nice day!\n")
else
puts(1, "\nNo variable PATH found. You really should set the path\n")
puts(1, "variable in DOS. It will allow you to run programs in\n")
puts(1, "different directories without typing the full path name!\n")
end if
abort(i)
sequence parms, workarea
integer no_of_parms, bad_first, bad_second
parms = command_line()
no_of_parms = length(parms) - 2
if no_of_parms < 2 then
abort(1)
else
workarea = parms[3]
bad_first = 0
bad_second = 0
for ix = 1 to length(workarea) do
if workarea[ix] < '0' or workarea[ix] > '9' then
bad_first = 1
exit
end if
end for
workarea = parms[4]
for ix = 1 to length(workarea) do
if workarea[ix] < '0' or workarea[ix] > '9' then
bad_second = 1
exit
end if
end for
if bad_first then
abort(2)
end if
if bad_second then
abort(3)
end if
puts(1, parms[3] & parms[4] & "\n\n")
abort(0)
end if
Here's the associated batch file:
@echo off ex d2307a.ex %1 %2 if errorlevel 3 goto err3 if errorlevel 2 goto err2 if errorlevel 1 goto err1 if errorlevel 0 goto err0 :err3 echo Second parameter is non-numeric goto finished :err2 echo First parameter is non-numeric goto finished :err1 echo Two numbers required to join goto finished :err0 echo Program completed normally :finished
include machine.e crash_message(s)
include machine.e
atom result
crash_message("**************************************\n"&
"* An error has been encountered that *\n"&
"* is so serious the software must *\n"&
"* stop running now. *\n"&
"* *\n"&
"* Please Email the file ex.err to *\n"&
"* moggie@interlog.com. Thank you! *\n"&
"**************************************\n")
for ix = 100 to 0 by -1 do
result = 100 / ix
printf(1,"%d divided by %d gives %f\n",{100,ix,result})
end for
euphoria program < input file or device euphoria program > output file or device
5 4 1 3
5 groups of 1000 (103)-----^
4 groups of 100 (102)---------^
1 group of 10 (101)-------------^
3 groups of 1 (100)-----------------^
1 0 1 1 0
1 group of 16 (or 24)------^
0 groups of 8 (or 23)---------^
1 group of 4 (or 22)------------^
1 group of 2 (or 21)---------------^
0 groups of 1 (or 20)------------------^
1) Divide number n by 2.
2) If the result of the division ends in .5, write down the value 1 on the sheet of paper, and then
change the result to an integer (for example, 12.5 to 12). Otherwise, just write down the value
0.
3) Take the results and make it the next number n to divide by 2, and go to step 1. Repeat these
steps until you produce a value less than 1. When you are done, reverse the digits written on
the paper.
| Binary | Decimal | Binary | Decimal | Binary | Decimal |
| 00000000 | 0 |
00000101 | 5 |
00001010 | 10 |
| 00000001 | 1 |
00000110 | 6 |
: |
: |
| 00000010 | 2 |
00000111 | 7 |
11111101 | 253 |
| 00000011 | 3 |
00001000 | 8 |
11111110 | 254 |
| 00000100 | 4 |
00001001 | 9 |
11111110 | 255 |
1) First 00100010 is reversed to 11011101 (called one's complement) 2) You then add binary 1 to the reversed value: 11011101 +00000001 -------- 11011110 (-34 in decimal)
include machine.e rs = int_to_bits(a,i)
include machine.e
sequence actual_binary_number, binary_bits, series_of_values
clear_screen()
puts(1,"A Simple Example Of Using int_to_bits()\n")
puts(1,"======================================\n\n")
puts(1,"Decimal Binary\n")
puts(1,"======= ================================\n\n")
series_of_values = {1,-1,500,-500}
for element = 1 to length(series_of_values) do
binary_bits = int_to_bits(series_of_values[element],32)
actual_binary_number = {}
for bits = length(binary_bits) to 1 by -1 do
actual_binary_number = actual_binary_number &
(binary_bits[bits] + 48)
end for
printf(1,"%5d %32s\n",
{series_of_values[element],actual_binary_number})
end for
puts(1,"\n\n")
puts(1,"(Note: int_to_bits() returns the bits in reversed sequence.\n")
puts(1," The output displayed has been adjusted to show the bits as they\n")
puts(1," are meant to appear in a binary number)\n")
The opposite of this is to take a binary number and convert it into an integer value. The is approach might be taken when you are using bits to represent a list of conditions, and for efficient storage want to bundle them all into a single integer value. To convert a binary number into an integer value, you use the following library routine below:
include machine.e ra = bits_to_int(s)
include machine.e
sequence bit_patterns
atom integer_value
clear_screen()
puts(1,"How bits_to_int() is used to convert a sequence of 8 bits into\n")
puts(1,"a single byte value.\n")
puts(1,"==============================================================\n\n")
bit_patterns = {{1,1,1,1,0,0,0,0},
{1,0,1,0,1,0,1,0},
{1,1,1,0,0,1,1,1},
{1,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1}}
for bit_groups = 1 to length(bit_patterns) do
integer_value = bits_to_int(bit_patterns[bit_groups])
print(1,bit_patterns[bit_groups])
printf(1," can be stored in a value of %3d\n",integer_value)
end for
You can also reference one or more bits by a process called "masking". Masking involves comparing a value (let's call it "A") against a second value (let's call it "B") in such a way that B's bit pattern either obtains or filters out specific bits in A. B is called the mask value. Boolean logic at the bit level is used in masking. There are three types of masks, with the first two being shown below:11110000 - value 11010010 - value 00001111 - OR mask 01111110 - AND mask -------- -------- 11111111 - OR result 01010010 - AND result
11011100 - value 00011100 - XOR mask -------- 11000000 - XOR result
ro = and_bits(o1,o2)
include machine.e
atom single_value, ANDed_atom, work_value, ANDer_atom
sequence bunch_of_values, ANDed_sequence, returned_bits
clear_screen()
ANDer_atom = 484848
bunch_of_values = {222222,333333,444444}
single_value = 123456
printf(1,"ANDing %6d and %6d\n\n",{single_value,ANDer_atom})
ANDed_atom = and_bits(single_value,ANDer_atom)
work_value = single_value
returned_bits = int_to_bits(work_value,32)
printf(1,"%6d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n")
work_value = ANDer_atom
returned_bits = int_to_bits(work_value,32)
printf(1,"%6d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n")
puts(1,repeat('-',50) & "\n")
work_value = ANDed_atom
returned_bits = int_to_bits(work_value,32)
printf(1,"%6d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n\n")
puts(1,"\nPress Any Key To Continue.......\n\n")
while get_key() = -1 do
end while
clear_screen()
ANDed_sequence = and_bits(bunch_of_values,ANDer_atom)
puts(1,"ANDing ")
print(1,bunch_of_values)
printf(1," and %6d\n\n",ANDer_atom)
for element = 1 to length(bunch_of_values) do
work_value = bunch_of_values[element]
returned_bits = int_to_bits(work_value,32)
printf(1,"%6d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n")
work_value = ANDer_atom
returned_bits = int_to_bits(work_value,32)
printf(1,"%6d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n")
puts(1,repeat('-',50) & "\n")
work_value = ANDed_sequence[element]
returned_bits = int_to_bits(work_value,32)
printf(1,"%6d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n\nPress Any Key To Continue.......\n\n")
while get_key() = -1 do
end while
end for
puts(1,"Result is ")
print(1,ANDed_sequence)
puts(1,"\n")
ro = or_bits(o1,o2)
include machine.e
atom single_value, ORed_atom, work_value, ORer_atom
sequence bunch_of_values, ORed_sequence, returned_bits
clear_screen()
ORer_atom = 545454
bunch_of_values = {414141,707070,312312}
single_value = 321321
printf(1,"ORing %6d and %6d\n\n",{single_value,ORer_atom})
ORed_atom = or_bits(single_value,ORer_atom)
work_value = single_value
returned_bits = int_to_bits(work_value,32)
printf(1,"%6d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n")
work_value = ORer_atom
returned_bits = int_to_bits(work_value,32)
printf(1,"%6d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n")
puts(1,repeat('-',50) & "\n")
work_value = ORed_atom
returned_bits = int_to_bits(work_value,32)
printf(1,"%6d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n\n")
puts(1,"\nPress Any Key To Continue.......\n\n")
while get_key() = -1 do
end while
clear_screen()
ORed_sequence = or_bits(bunch_of_values,ORer_atom)
puts(1,"ORing ")
print(1,bunch_of_values)
printf(1," and %6d\n\n",ORer_atom)
for element = 1 to length(bunch_of_values) do
work_value = bunch_of_values[element]
returned_bits = int_to_bits(work_value,32)
printf(1,"%6d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n")
work_value = ORer_atom
returned_bits = int_to_bits(work_value,32)
printf(1,"%6d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n")
puts(1,repeat('-',50) & "\n")
work_value = ORed_sequence[element]
returned_bits = int_to_bits(work_value,32)
printf(1,"%6d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n\nPress Any Key To Continue.......\n\n")
while get_key() = -1 do
end while
end for
puts(1,"Result is ")
print(1,ORed_sequence)
puts(1,"\n")
ro = xor_bits(o1,o2)
include machine.e
atom single_value, XORed_atom, work_value, XORer_atom
sequence bunch_of_values, XORed_sequence, returned_bits
clear_screen()
XORer_atom = 545454
bunch_of_values = {414141,707070,312312}
single_value = 321321
printf(1,"XORing %6d and %6d\n\n",{single_value,XORer_atom})
XORed_atom = xor_bits(single_value,XORer_atom)
work_value = single_value
returned_bits = int_to_bits(work_value,32)
printf(1,"%6d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n")
work_value = XORer_atom
returned_bits = int_to_bits(work_value,32)
printf(1,"%6d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n")
puts(1,repeat('-',50) & "\n")
work_value = XORed_atom
returned_bits = int_to_bits(work_value,32)
printf(1,"%6d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n\n")
puts(1,"\nPress Any Key To Continue.......\n\n")
while get_key() = -1 do
end while
clear_screen()
XORed_sequence = xor_bits(bunch_of_values,XORer_atom)
puts(1,"XORing ")
print(1,bunch_of_values)
printf(1," and %6d\n\n",XORer_atom)
for element = 1 to length(bunch_of_values) do
work_value = bunch_of_values[element]
returned_bits = int_to_bits(work_value,32)
printf(1,"%6d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n")
work_value = XORer_atom
returned_bits = int_to_bits(work_value,32)
printf(1,"%6d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n")
puts(1,repeat('-',50) & "\n")
work_value = XORed_sequence[element]
returned_bits = int_to_bits(work_value,32)
printf(1,"%6d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n\nPress Any Key To Continue.......\n\n")
while get_key() = -1 do
end while
end for
puts(1,"Result is ")
print(1,XORed_sequence)
puts(1,"\n")
The last bit-handling library routine for this chapter is listed below:
ro = not_bits(o)
include machine.e
atom single_value, NOTed_atom, work_value
sequence bunch_of_values, NOTed_sequence, returned_bits
clear_screen()
bunch_of_values = {823123,-907121,621325}
single_value = -1
printf(1,"NOTing %2d\n\n",single_value)
NOTed_atom = not_bits(single_value)
work_value = single_value
returned_bits = int_to_bits(work_value,32)
printf(1,"%7d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n")
puts(1, repeat('-',51) & "\n")
work_value = NOTed_atom
returned_bits = int_to_bits(work_value,32)
printf(1,"%7d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n\n")
puts(1,"\nPress Any Key To Continue.......\n\n")
while get_key() = -1 do
end while
clear_screen()
NOTed_sequence = not_bits(bunch_of_values)
puts(1,"NOTing ")
print(1,bunch_of_values)
puts(1,"\n\n")
for element = 1 to length(bunch_of_values) do
work_value = bunch_of_values[element]
returned_bits = int_to_bits(work_value,32)
printf(1,"%7d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n")
puts(1, repeat('-',51) & "\n")
work_value = NOTed_sequence[element]
returned_bits = int_to_bits(work_value,32)
printf(1,"%7d ---------> ",work_value)
for bits = 32 to 1 by -1 do
print(1,returned_bits[bits])
end for
puts(1,"\n\nPress Any Key To Continue.......\n\n")
while get_key() = -1 do
end while
end for
puts(1,"Result is ")
print(1,NOTed_sequence)
puts(1,"\n")
The next chapter will show you how you can save numbers larger than 255 outside your program, whether it is an integer
or a floating point number.
include machine.e rs = int_to_bytes(a)
{byte, byte, byte, byte}
bits 20 to 27 ----^
bits 28 to 215----------^
bits 216 to 223----------------^
bits 224 to 231----------------------^
include machine.e ra = bytes_to_int(s)
1) Use int_to_bits() to convert the 4th element of the sequence created by int_to_bytes() into a 32 element sequence, and look at the 32nd element. If it is 1, you have a negative number. 2) Use not_bits() to reverse the bits in the int_to_bytes() sequence. 3) Use the result of not_bits() as the sequence you pass to bytes_to_int(). 4) Add 1 to the integer created by bytes_to_int(), then multiply the integer by -1. The integer should be the correct value.
include machine.e
sequence four_bytes, values_to_be_saved, returned_bits
integer demo_file
atom value_to_be_restored
puts(1,"This program will demonstrate how to save negative and positive\n")
puts(1,"integers to file after converting them into 4 bytes, and then \n")
puts(1,"read them back and re-assemble them into their original values.\n")
puts(1,"Because puts() strips off the upper 24 bits (bit 2 to the power\n")
puts(1,"of 8 to bit to the power of 31), the procedure used to convert\n")
puts(1,"negative numbers back from the four bytes made by int_to_bytes()\n")
puts(1,"needs to be modified. First of all, the eighth element, not the\n")
puts(1,"thirty-second element, is treated as the sign bit. Second, you\n")
puts(1,"subtract {255,255,255,255} from the four_elements instead of\n")
puts(1,"using not_bits(). Third, you add -1 after converting the\n")
puts(1,"adjusted four bytes to an integer using bytes_to_int().\n\n")
values_to_be_saved = {31619125,-31619125}
for values = 1 to 2 do
four_bytes = int_to_bytes(values_to_be_saved[values])
demo_file = open("demo.fle","wb")
printf(1,"Saving To File: %9d\n",values_to_be_saved[values])
for bytes = 1 to 4 do
puts(demo_file,four_bytes[bytes])
end for
close(demo_file)
four_bytes = {}
demo_file = open("demo.fle","rb")
for bytes = 1 to 4 do
four_bytes = four_bytes & getc(demo_file)
end for
close(demo_file)
returned_bits = int_to_bits(four_bytes[4],8)
if returned_bits[8] = 1 then
four_bytes = four_bytes - 255
value_to_be_restored = bytes_to_int(four_bytes)
value_to_be_restored = value_to_be_restored - 1
else
value_to_be_restored = bytes_to_int(four_bytes)
end if
printf(1,"Retrieved From File: %9d\n\n",value_to_be_restored)
end for
6.13451e+009 (meaning 6.13451 × 1000000000, or 6134510000) 4.52e-005 (meaning 4.52 × .00001, or.0000452)
1 bit + 8 bits + 23 bits = 32 bits (sign bit) (exponent) (mantissa) 1 bit + 11 bits + 52 bits = 64 bits (sign bit) (exponent) (mantissa)
include machine.e rs = atom_to_float32(a)
include machine.e ra = float32_to_atom(s)