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 jacobite1@fastmail.fm, 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_incomeEuphoria 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 ifThe "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 ifUsing 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 ifYou 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 ifProgram 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 whileIf 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 forBoth 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 ifThe 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 forYou 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 forAnother 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 forThe 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 whileIf 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 whileLeft 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 whileTo 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 ifWhenever 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 whileIf 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 ifWhenever 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 whileIf 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 forThe 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 whilePerhaps 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 forTo 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 ifRather 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 ifYou 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 ifRemember 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 ifDrawing 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 ifThe 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 ifAnother 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 ifNow 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 ifIf 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 ifIt 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 ifYour 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 ifIf 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 ifWith 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 while0.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 ifHere'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 ifHere'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 forYou 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)
include machine.e ra = atom_to_float64(a)
include machine.e ra = float64_to_atom(s)
include machine.e integer demo_file atom returned_float sequence values,IEEE_bytes clear_screen() values = {1023.11,-33.25} for elements = 1 to length(values) do printf(1,"Saving To File: %.2f\n",values[elements]) if elements = 1 then IEEE_bytes = atom_to_float64(values[elements]) demo_file = open("demo.fle","wb") for bytes = 1 to length(IEEE_bytes) do puts(demo_file,IEEE_bytes[bytes]) end for close(demo_file) IEEE_bytes = {} demo_file = open("demo.fle","rb") for bytes = 1 to 8 do IEEE_bytes = IEEE_bytes & getc(demo_file) end for close(demo_file) returned_float = float64_to_atom(IEEE_bytes) end if if elements = 2 then IEEE_bytes = atom_to_float32(values[elements]) demo_file = open("demo.fle","wb") for bytes = 1 to length(IEEE_bytes) do puts(demo_file,IEEE_bytes[bytes]) end for close(demo_file) IEEE_bytes = {} demo_file = open("demo.fle","rb") for bytes = 1 to 4 do IEEE_bytes = IEEE_bytes & getc(demo_file) end for close(demo_file) returned_float = float32_to_atom(IEEE_bytes) end if printf(1,"Read From File: %.2f\n\n",returned_float) end for
1) Whether the library routine is a procedure or a function. 2) The name of the library routine. 3) The number and type of parameters the library routine accepts. This is optional. 4) The programming statements that will process the parameters accepted by the library routine. 5) The value returned if the library routine is a function.To declare a library routine that is a procedure, here is the syntax required:
procedure name(parameter declaration, parameter declaration, ...) one or more Euphoria statements to execute end procedure
function name(parameter declaration, parameter declaration, ...) one or more Euphoria statements to execute return value end function
procedure print_some_lines() puts(1, "lines\n") puts(1, "lines\n") puts(1, "lines\n") end procedure print_some_lines()
procedure print_some_lines(integer repeat, sequence line_to_print) for count = 1 to repeat do puts(1, line_to_print & "\n") end for end procedure print_some_lines(10, "Hi There!")
integer status_of_print function print_some_lines(integer repeat, sequenc line_to_print) if repeat > 50 then return 2 else for count = 1 to repeat do puts(1, line_to_print & "\n") end for return 1 end if end function status_of_print = print_some_lines(10, "Hi There")
sequence returned_string function draw_text_rectangle(sequence top_left, sequence bottom_right) integer tl_corner,tr_corner,bl_corner,br_corner,across,down tl_corner = 'Ú' tr_corner = '¿' bl_corner = 'À' br_corner = 'Ù' across = 'Ä' down = '³' if length(top_left) != 2 then return "Invalid Top Left Location" elsif length(bottom_right) != 2 then return "Invalid Bottom Right Location" elsif bottom_right[1]-top_left[1] < 2 then return "Rectangle Not High Enough" elsif bottom_right[2]-top_left[2] < 2 then return "Rectangle Not Wide Enough" else position(top_left[1],top_left[2]) puts(1,tl_corner) position(top_left[1],bottom_right[2]) puts(1,tr_corner) position(bottom_right[1],top_left[1]) puts(1,bl_corner) position(bottom_right[1],bottom_right[2]) puts(1,br_corner) for lines = top_left[1]+1 to bottom_right[1]-1 do position(lines,top_left[2]) puts(1,down) position(lines,bottom_right[2]) puts(1,down) end for for columns = top_left[2]+1 to bottom_right[2]-1 do position(top_left[1],columns) puts(1,across) position(bottom_right[1],columns) puts(1,across) end for end if return "Text Rectangle Drawn" end function clear_screen() returned_string = draw_text_rectangle({1,1},{18,80}) position(20,1) puts(1,returned_string & '\n')You can also design custom variable types in the same manner you design custom library routines. As a matter of fact, declaring a variable type is like designing a one parameter function.
type name(parameter declaration) one or more Euphoria statements to execute return true or false value end type
housepet cat
1) Euphoria starts the "type-end type" group declaring the custom variable type, using the assigned variable as the parameter. 2) The Euphoria statements executed within the "type-end type" group tests the parameter value, and a value of 1 or 0 is returned. 3) If the value returned is 1, the assignment statement that triggered the "type-end type" sets the variable to the assigned value, otherwise the program will end with a type check error message.
type fruit(sequence unknown_fruit) sequence valid_fruit valid_fruit = {"bananas", "apples", "oranges", "pears"} return find(unknown_fruit, valid_fruit) end type fruit fruit_check fruit_check = "pears" puts(1, "Program Run Completed\n")
fruit_check = "yams"
type_check failure, fruit_check is {121'y',97'a',109'm',115's'}
include machine.e type binary(integer values) sequence bad_digit integer valid_value bad_digit = "**********************************************\n" & "* This type of variable only accepts values *\n" & "* between 0 and 1! Check EX.ERR for details! *\n" & "**********************************************\n" crash_message(bad_digit) valid_value = values >= 0 and values <=1 return valid_value end type binary binary_digit binary_digit = 2But your learning of custom library routines does not end at this point. There are other questions that need to be answered. For example, are any variables used in one library routine accessible by other library routines, or even the entire program? Do we have to keep everything that makes up a program in a single source file, or can certain parts be stored in several source files? The next chapter will address this when we learn about scope and using include files.
marbles = marbles + 1 atom marbles
atom count_3s for counter = 1 to 500 do count_3s = count_3s + 3 end for printf(1,"%d %d\n",{count_3s, counter})
procedure alpha() clear_screen() end procedure procedure beta() alpha() end procedure
global object grab_bag global function add_two(atom first, atom second) atom sum sum = first + second return sum end function
include d2808a.e print(1,find('J',valid_capitals)) puts(1,"\n\n") show_trademark()
global sequence valid_capitals valid_capitals = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" global procedure show_trademark() puts(1,"**********************************************\n") puts(1,"* Copyright 1997 Mom, The Cat Smells Funny! *\n") puts(1,"* Productions *\n") puts(1,"* *\n") puts(1,"* |\\\\\"\"\"//| *\n") puts(1,"* {_ O O _} *\n") puts(1,"* {/~\\} *\n") puts(1,"* \"\"\" *\n") puts(1,"**********************************************\n") end procedure
include mouse.e ro = get_mouse()
{event, pixel column, pixel row}
1 - Mouse moved 2 - Left button pressed 4 - Left button released 8 - Right button pressed 16 - Right button released 32 - Middle button pressed 64 - Middle button released
include mouse.e mouse_events(i)
include mouse.e mouse_pointer(i)
include graphics.e sound(i)
include graphics.e include image.e include mouse.e integer current_colour sequence pattern, bright_magenta_map, bright_blue_map, bright_green_map, bright_red_map, bright_white_map, sound_on object mouse_data bright_magenta_map = palette(13, {63,63,63}) bright_red_map = palette(12, {63,63,63}) bright_blue_map = palette(9, {63,63,63}) bright_green_map = palette(10, {63,63,63}) bright_white_map = palette(12, bright_red_map) bright_white_map = palette(9, bright_blue_map) bright_white_map = palette(10, bright_green_map) bright_white_map = palette(13, bright_magenta_map) if graphics_mode(18) then puts(1, "Mode Failure") else position(3,10) puts(1, "Place the mouse pointer on any of the coloured areas") position(4,10) puts(1, "of the shape, and click with the left button. A sound") position(5,10) puts(1, "from your PC speaker will be generated. Click the right") position(6,10) puts(1, "button to turn off the sound, or press 'q' to quit.") pattern = {{290,280},{190,280},{290,180}} polygon(9,1,pattern) pattern = {{290,180},{290,280},{390,280}} polygon(10,1,pattern) pattern = {{190,280},{290,280},{290,380}} polygon(12,1,pattern) pattern = {{290,380},{390,280},{290,280}} polygon(13,1,pattern) sound_on = " " mouse_events(2+8) while get_key() != 'q' do mouse_data = get_mouse() if sequence(mouse_data) then mouse_pointer(0) if mouse_data[1] = 2 then current_colour = get_pixel({mouse_data[2], mouse_data[3]}) if current_colour = 13 and compare(sound_on," ") = 0 then sound(2100) bright_magenta_map = palette(13, bright_white_map) sound_on = "bm" end if if current_colour = 12 and compare(sound_on," ") = 0 then sound(2000) bright_red_map = palette(12, bright_white_map) sound_on = "br" end if if current_colour = 9 and compare(sound_on," ") = 0 then sound(1900) bright_blue_map = palette(9, bright_white_map) sound_on = "bb" end if if current_colour = 10 and compare(sound_on," ") = 0 then sound(1800) bright_green_map = palette(10, bright_white_map) sound_on = "bg" end if end if if mouse_data[1] = 8 then sound(0) if compare(sound_on,"bm") = 0 then bright_white_map = palette(13, bright_magenta_map) sound_on = " " end if if compare(sound_on,"br") = 0 then bright_white_map = palette(12, bright_red_map) sound_on = " " end if if compare(sound_on,"bb") = 0 then bright_white_map = palette(9, bright_blue_map) sound_on = " " end if if compare(sound_on,"bg") = 0 then bright_white_map = palette(10, bright_green_map) sound_on = " " end if end if mouse_pointer(1) end if end while if graphics_mode(-1) then puts(1, "Mode Failure") end if end if sound(0)
constant variable name = expression
integer constants_file, current_record, input_key, update sequence database, input_record constant number_of_records = 49, field_1_start = 1, field_1_end = 24, field_2_start = 25, field_2_end = 35, field_3_start = 36, field_3_end = 37, field_4_start = 38, field_4_end = 110, field_5_start = 111 procedure display_data(sequence record) sequence dline1, dline2, dline3, dline4, constant_name, include_file, constant_value,library_routines_where_used, constant_description dline1 = "Constant Name: %s\n" dline2 = "Constant Description: %s\n" dline3 = "Constant Value: %s\n" dline4 = "Declared In Include File: %s\n" constant_name = record[field_1_start..field_1_end] include_file = record[field_2_start..field_2_end] constant_value = record[field_3_start..field_3_end] library_routines_where_used = record[field_4_start..field_4_end] constant_description = record[field_5_start..length(record)] position(4,1) for line = 1 to 7 do puts(1,repeat(' ',75) & "\n") end for position(4,1) printf(1,dline1,{constant_name}) printf(1,dline2,{constant_description}) printf(1,dline3,{constant_value}) printf(1,dline4,{include_file}) puts(1,"\nExamples Of Library Routines Where Used:\n") puts(1,library_routines_where_used & "\n") end procedure clear_screen() current_record = 1 database = {} input_key = 0 update = 'y' constants_file = open("constants.txt","r") for ix = 1 to number_of_records do input_record = gets(constants_file) input_record = input_record[1..length(input_record)-1] database = append(database,input_record) end for position(1,1) puts(1,"Euphoria Constants Dictionary") position(2,1) puts(1,"=============================") position(13,1) puts(1,"Press < and > to move about") position(14,1) puts(1,"Press Q to quit") while input_key != 'q' do if input_key = '.' or input_key = '>' then if current_record < number_of_records then current_record = current_record + 1 update = 'y' end if end if if input_key = ',' or input_key = '<' then if current_record > 1 then current_record = current_record - 1 update = 'y' end if end if if update = 'y' then update = 'n' display_data(database[current_record]) end if input_key = get_key() end while clear_screen()ToC
program.ex:nnnn error message
Global & Local Variables (a list of variables and the values they contain follow)
program.ex:nnnn in procedure procedure_name()
type_check failure, variable is n
sequence found inside character string
subscript value n1 is out of bounds, reading from a length-n2 sequence
slice ends past end of sequence (n1 > n2)
can't open include file path
sequence lengths are not the same (n1 != n2)
syntax error - expected to see ..., not ...
true/false condition must be an ATOM
unknown escape character
may not change the value of a constant
a loop variable name is expected here
no value returned from function
attempt to subscript an atom
slice length is less than 0 (-n1)
symbol has not been declared