Syntax: | include image.e i = save_bitmap(s, st) |
Description: | Create a bitmap (.bmp) file from a 2-element sequence s.
st is the name of a .bmp "bitmap" file. s[1] is the palette: {{r,g,b}, {r,g,b}, ..., {r,g,b}} Each red, green, or blue value is in the range 0 to 255. s[2] is a 2-d sequence of sequences containing a pixel-graphics image. The sequences contained in s[2] must all have the same length. s is in the same format as the value returned by read_bitmap(). The result will be one of the following codes: |
global constant BMP_SUCCESS = 0, BMP_OPEN_FAILED = 1, BMP_INVALID_MODE = 4 -- invalid graphics mode -- or invalid argument | |
Comments: | If you use get_all_palette() to get the palette before calling
this function, you must multiply the returned intensity values
by 4 before calling save_bitmap().
You might use save_image() to get the 2-d image for s[2]. save_bitmap() produces bitmaps of 2, 4, 16, or 256 colors and these can all be read with read_bitmap(). Windows Paintbrush and some other tools do not support 4-color bitmaps. |
Example: | |
paletteData = get_all_palette() * 4 code = save_bitmap({paletteData, imageData}, "c:\\example\\a1.bmp") | |
See Also: | save_image, read_bitmap, save_screen, get_all_palette |
Platform: | DOS32 |
Syntax: | include image.e s3 = save_image(s1, s2) |
Description: | Save a rectangular image from a pixel-graphics screen. The result is a 2-d sequence of sequences containing all the pixels in the image. You can redisplay the image using display_image(). s1 is a 2-element sequence {x1,y1} specifying the top-left pixel in the image. s2 is a sequence {x2,y2} specifying the bottom-right pixel. |
Example: | |
s = save_image({0,0}, {50,50}) display_image({100,200}, s) display_image({300,400}, s) -- saves a 51x51 square image, then redisplays it at {100,200} -- and at {300,400} | |
See Also: | display_image, save_text_image |
Platform: | DOS32 |
Syntax: | include image.e i = save_screen(x1, st) |
Description: | Save the whole screen or a rectangular region of the screen as
a Windows bitmap (.bmp) file. To save the whole screen, pass the
integer 0 for x1. To save a rectangular region of the screen,
x1 should be a sequence of 2 sequences:
{{topLeftXPixel, topLeftYPixel},
{bottomRightXPixel, bottomRightYPixel}} st is the name of a .bmp "bitmap" file. The result will be one of the following codes: |
global constant BMP_SUCCESS = 0, BMP_OPEN_FAILED = 1, BMP_INVALID_MODE = 4 -- invalid graphics mode -- or invalid argument | |
Comments: | save_screen() produces bitmaps of 2, 4, 16, or 256 colors and
these can all be read with read_bitmap(). Windows Paintbrush
and some other tools do not support 4-color bitmaps.
save_screen() only works in pixel-graphics modes, not text modes. |
Example 1: | |
-- save whole screen: code = save_screen(0, "c:\\example\\a1.bmp") | |
Example 2: | |
-- save part of screen: err = save_screen({{0,0},{200, 15}}, "b1.bmp") | |
See Also: | save_image, read_bitmap, save_bitmap |
Syntax: | include image.e s3 = save_text_image(s1, s2) |
Description: | Save a rectangular region of text from a text-mode screen. The result is a sequence of sequences containing ASCII characters and attributes from the screen. You can redisplay this text using display_text_image(). s1 is a 2-element sequence {line1, column1} specifying the top-left character. s2 is a sequence {line2, column2} specifying the bottom right character. |
Comments: | Because the character attributes are also saved, you will get
the correct foreground color, background color and other properties
for each character when you redisplay the text.
On DOS32, an attribute byte is made up of two 4-bit fields that encode the foreground and background color of a character. The high-order 4 bits determine the background color, while the low-order 4 bits determine the foreground color. This routine only works in text modes. You might use this function in a text-mode graphical user interface to save a portion of the screen before displaying a drop-down menu, dialog box, alert box etc. On DOS32, if you are flipping video pages, note that this function reads from the current active page. |
Example: | If the top 2 lines of the screen have: |
Hello World | |
And you execute: | |
s = save_text_image({1,1}, {2,5}) | |
Then s is something like: | |
{"H-e-l-l-o-", "W-o-r-l-d-"} where '-' indicates the attribute bytes | |
See Also: | display_text_image, save_image, set_active_page, get_screen_char |
Syntax: | include graphics.e scroll(i1, i2, i3) |
Description: | Scroll a region of text on the screen either up (i1 positive) or down (i1 negative) by i1 lines. The region is the series of lines on the screen from i2 (top line) to i3 (bottom line), inclusive. New blank lines will appear at the top or bottom. |
Comments: | You could perform the scrolling operation using a series
of calls to puts(), but scroll() is much faster.
The position of the cursor after scrolling is not defined. |
Example Program: | bin\ed.ex |
See Also: | clear_screen, text_rows |
Syntax: | include file.e i1 = seek(fn, a1) |
Description: | Seek (move) to any byte position in the file fn or to the end of file if a1 is -1. For each open file there is a current byte position that is updated as a result of I/O operations on the file. The initial file position is 0 for files opened for read, write or update. The initial position is the end of file for files opened for append. The value returned by seek() is 0 if the seek was successful, and non-zero if it was unsuccessful. It is possible to seek past the end of a file. If you seek past the end of the file, and write some data, undefined bytes will be inserted into the gap between the original end of file and your new data. |
Comments: | After seeking and reading (writing) a series of bytes, you may need to
call seek() explicitly before you switch to writing (reading) bytes,
even though the file position should already be what you want.
This function is normally used with files opened in binary mode. In text mode, DOS converts CR LF to LF on input, and LF to CR LF on output, which can cause great confusion when you are trying to count bytes. |
Example: | |
include file.e integer fn fn = open("mydata", "rb") -- read and display first line of file 3 times: for i = 1 to 3 do puts(1, gets(fn)) if seek(fn, 0) then puts(1, "rewind failed!\n") end if end for | |
See Also: | where, open |
Syntax: | i = sequence(x) |
Description: | Return 1 if x is a sequence else return 0. |
Comments: | This serves to define the sequence type. You can also call it like an ordinary function to determine if an object is a sequence. |
Example 1: | |
sequence s s = {1,2,3} | |
Example 2: | |
if sequence(x) then sum = 0 for i = 1 to length(x) do sum = sum + x[i] end for else -- x must be an atom sum = x end if | |
See Also: | atom, object, integer, atoms and sequences |
Platform: | DOS32 |
Syntax: | include image.e set_active_page(i) |
Description: | Select video page i to send all screen output to. |
Comments: | With multiple pages you can instantaneously change the entire
screen without causing any visible "flicker". You can also
save the screen and bring it back quickly.
video_config() will tell you how many pages are available in the current graphics mode. By default, the active page and the display page are both 0. This works under DOS, or in a full-screen DOS window. In a partial-screen window you cannot change the active page. |
Example: | |
include image.e -- active & display pages are initially both 0 puts(1, "\nThis is page 0\n") set_active_page(1) -- screen output will now go to page 1 clear_screen() puts(1, "\nNow we've flipped to page 1\n") if getc(0) then -- wait for key-press end if set_display_page(1) -- "Now we've ..." becomes visible if getc(0) then -- wait for key-press end if set_display_page(0) -- "This is ..." becomes visible again set_active_page(0) | |
See Also: | get_active_page, set_display_page, video_config |
Platform: | DOS32 |
Syntax: | include image.e set_display_page(i) |
Description: | Set video page i to be mapped to the visible screen. |
Comments: | With multiple pages you can instantaneously change the entire
screen without causing any visible "flicker". You can also
save the screen and bring it back quickly.
video_config() will tell you how many pages are available in the current graphics mode. By default, the active page and the display page are both 0. This works under DOS, or in a full-screen DOS window. In a partial-screen window you cannot change the active page. |
Example: | See set_active_page() example. |
See Also: | get_display_page, set_active_page, video_config |
Syntax: | include machine.e set_rand(i1) |
Description: | Set the random number generator to a certain state, i1, so that you will get a known series of random numbers on subsequent calls to rand(). |
Comments: | Normally the numbers returned by the rand() function are totally unpredictable, and will be different each time you run your program. Sometimes however you may wish to repeat the same series of numbers, perhaps because you are trying to debug your program, or maybe you want the ability to generate the same output (e.g. a random picture) for your user upon request. |
Example: | |
sequence s, t s = repeat(0, 3) t = s set_rand(12345) s[1] = rand(10) s[2] = rand(100) s[3] = rand(1000) set_rand(12345) -- same value for set_rand() t[1] = rand(10) -- same arguments to rand() as before t[2] = rand(100) t[3] = rand(1000) -- at this point s and t will be identical | |
See Also: | rand |
Platform: | DOS32 |
Syntax: | include machine.e set_vector(i, s) |
Description: | Set s as the new address for handling interrupt number i. s must be a protected mode far address in the form: {16-bit segment, 32-bit offset}. |
Comments: | Before calling set_vector() you must store a machine-code
interrupt handling routine at location s in memory.
The 16-bit segment can be the code segment used by Euphoria. To get the value of this segment see demo\dos32\hardint.ex. The offset can be the 32-bit value returned by allocate(). Euphoria runs in protected mode with the code segment and data segment pointing to the same physical memory, but with different access modes. Interrupts occurring in either real mode or protected mode will be passed to your handler. Your interrupt handler should immediately load the correct data segment before it tries to reference memory. Your handler might return from the interrupt using the iretd instruction, or jump to the original interrupt handler. It should save and restore any registers that it modifies. You should lock the memory used by your handler to ensure that it will never be swapped out. See lock_memory(). It is highly recommended that you study demo\dos32\hardint.ex before trying to set up your own interrupt handler. You should have a good knowledge of machine-level programming before attempting to write your own handler. You can call set_vector() with the far address returned by get_vector(), when you want to restore the original handler. |
Example: | |
set_vector(#1C, {code_segment, my_handler_address}) | |
Example Program: | demo\dos32\hardint.ex |
See Also: | get_vector, lock_memory, allocate |
Syntax: | x2 = sin(x1) |
Description: | Return the sine of x1, where x1 is in radians. |
Comments: | This function may be applied to an atom or to all elements of a sequence. |
Example: | |
sin_x = sin({.5, .9, .11}) -- sin_x is {.479, .783, .110} | |
See Also: | cos, tan |
Syntax: | include misc.e sleep(i) |
Description: | Suspend execution for i seconds. |
Comments: | On WIN32 and Linux/FreeBSD, the operating
system will suspend your process and schedule other processes.
On DOS32, your program will go into a busy loop
for i seconds, during which time other processes may run, but
they will compete with your process for the CPU.
With multiple tasks, the whole program sleeps, not just the current task. To make just the current task sleep, you can call task_schedule(task_self(), {i, i}) and then execute task_yield(). |
Example: | |
puts(1, "Waiting 15 seconds...\n") sleep(15) puts(1, "Done.\n") | |
See Also: | lock_file, abort, time |
Syntax: | include sort.e s2 = sort(s1) |
Description: | Sort s1 into ascending order using a fast sorting algorithm. The elements of s1 can be any mix of atoms or sequences. Atoms come before sequences, and sequences are sorted "alphabetically" where the first elements are more significant than the later elements. |
Example 1: | |
x = 0 & sort({7,5,3,8}) & 0 -- x is set to {0, 3, 5, 7, 8, 0} | |
Example 2: | |
y = sort({"Smith", "Jones", "Doe", 5.5, 4, 6}) -- y is {4, 5.5, 6, "Doe", "Jones", "Smith"} | |
Example 3: | |
database = sort({{"Smith", 95.0, 29}, {"Jones", 77.2, 31}, {"Clinton", 88.7, 44}}) -- The 3 database "records" will be sorted by the first "field" -- i.e. by name. Where the first field (element) is equal it -- will be sorted by the second field etc. -- after sorting, database is: {{"Clinton", 88.7, 44}, {"Jones", 77.2, 31}, {"Smith", 95.0, 29}} | |
See Also: | custom_sort, compare, match, find |
Platform: | DOS32 |
Syntax: | include graphics.e sound(i) |
Description: | Turn on the PC speaker at frequency i. If i is 0 the speaker will be turned off. |
Comments: | On WIN32 and Linux/FreeBSD no sound will be made. |
Example: | |
sound(1000) -- starts a fairly high pitched sound |
Syntax: | include misc.e s = sprint(x) |
Description: | The representation of x as a string of characters is returned. This is exactly the same as print(fn, x), except that the output is returned as a sequence of characters, rather than being sent to a file or device. x can be any Euphoria object. |
Comments: | The atoms contained within x will be displayed to a maximum of 10 significant digits, just as with print(). |
Example 1: | |
s = sprint(12345) -- s is "12345" | |
Example 2: | |
s = sprint({10,20,30}+5) -- s is "{15,25,35}" | |
See Also: | print, sprintf, value, get |
Syntax: | s = sprintf(st, x) |
Description: | This is exactly the same as printf(), except that the output is returned as a sequence of characters, rather than being sent to a file or device. st is a format string, x is the value or sequence of values to be formatted. printf(fn, st, x) is equivalent to puts(fn, sprintf(st, x)). |
Comments: | Some typical uses of sprintf() are:
1. Converting numbers to strings. |
Example: | |
s = sprintf("%08d", 12345) -- s is "00012345" | |
See Also: | printf, value, sprint, get, system |
Syntax: | x2 = sqrt(x1) |
Description: | Calculate the square root of x1. |
Comments: | This function may be applied to an atom or to all elements
of a sequence.
Taking the square root of a negative number will abort your program with a run-time error message. |
Example: | |
r = sqrt(16) -- r is 4 | |
See Also: | log, power |
Syntax: | system(st, i) |
Description: | Pass a command string st to the operating system command interpreter.
The argument i indicates the manner in which to
return from the call to system(): When i is 0, the previous graphics mode is restored and the screen is cleared. When i is 1, a beep sound will be made and the program will wait for the user to press a key before the previous graphics mode is restored. When i is 2, the graphics mode is not restored and the screen is not cleared. |
Comments: | i = 2 should only be used when it is known that the command executed by
system() will not change the graphics mode.
You can use Euphoria as a sophisticated "batch" (.bat) language by making calls to system() and system_exec(). system() will start a new DOS or Linux/FreeBSD shell. system() allows you to use command-line redirection of standard input and output in the command string st. Under DOS32, a Euphoria program will start off using extended memory. If extended memory runs out the program will consume conventional memory. If conventional memory runs out it will use virtual memory, i.e. swap space on disk. The DOS command run by system() will fail if there is not enough conventional memory available. To avoid this situation you can reserve some conventional (low) memory by typing: |
SET CAUSEWAY=LOWMEM:xxx | |
where xxx is the number of K of conventional memory to reserve. Type this before running your program. You can also put this in autoexec.bat, or in a .bat file that runs your program. For example: | |
SET CAUSEWAY=LOWMEM:80 ex myprog.ex | |
This will reserve 80K of conventional memory, which should be enough to run simple DOS commands like COPY, MOVE, MKDIR etc. | |
Example 1: | |
system("copy temp.txt a:\\temp.bak", 2) -- note use of double backslash in literal string to get -- single backslash | |
Example 2: | |
system("ex \\test\\myprog.ex < indata > outdata", 2) -- executes myprog by redirecting standard input and -- standard output | |
See Also: | system_exec, dir, current_dir, getenv, command_line |
Syntax: | i1 = system_exec(st, i2) |
Description: | Try to run the command given by st. st must be a command to run an
executable program,
possibly with some command-line arguments.
If the program can be run, i1 will be the exit code from the
program. If it is not possible to run the program, system_exec()
will return -1. i2 is a code that indicates what to do about the
graphics mode when system_exec() is finished. These codes are
the same as for system(): When i2 is 0, the previous graphics mode is restored and the screen is cleared. When i2 is 1, a beep sound will be made and the program will wait for the user to press a key before the previous graphics mode is restored. When i2 is 2, the graphics mode is not restored and the screen is not cleared. |
Comments: | On DOS32 or WIN32, system_exec() will only run .exe and .com
programs. To run
.bat files, or built-in DOS commands, you need system().
Some commands, such as DEL, are not programs, they are
actually built-in to the command interpreter.
On DOS32 and WIN32, system_exec() does not allow the use of command-line redirection in the command string st, nor does it allow you to quote strings that contain blanks, such as file names. exit codes from DOS or Windows programs are normally in the range 0 to 255, with 0 indicating "success". You can run a Euphoria program using system_exec(). A Euphoria program can return an exit code using abort(). system_exec() does not start a new DOS shell. |
Example 1: | |
integer exit_code exit_code = system_exec("xcopy temp1.dat temp2.dat", 2) if exit_code = -1 then puts(2, "\n couldn't run xcopy.exe\n") elsif exit_code = 0 then puts(2, "\n xcopy succeeded\n") else printf(2, "\n xcopy failed with code %d\n", exit_code) end if | |
Example 2: | |
-- executes myprog with two file names as arguments if system_exec("ex \\test\\myprog.ex indata outdata", 2) then puts(2, "failure!\n") end if | |
See Also: | system, abort |
Syntax: | x2 = tan(x1) |
Description: | Return the tangent of x1, where x1 is in radians. |
Comments: | This function may be applied to an atom or to all elements of a sequence. |
Example: | |
t = tan(1.0) -- t is 1.55741 | |
See Also: | sin, cos, arctan |
Syntax: | task_clock_start() |
Description: | Restart the clock used for scheduling real-time tasks. Call this routine, some time after calling task_clock_stop(), when you want scheduling of real-time tasks to continue. |
Comments: | task_clock_stop() and task_clock_start() can be used to freeze
the scheduling of real-time tasks.
task_clock_start() causes the scheduled times of all real-time tasks to be incremented by the amount of time since task_clock_stop() was called. This allows a game, simulation, or other program to continue smoothly. Time-shared tasks are not affected. |
Example: | |
-- freeze the game while the player answers the phone task_clock_stop() while get_key() = -1 do end while task_clock_start() | |
See Also: | task_clock_stop, task_schedule, task_yield, task_suspend |
Syntax: | task_clock_stop() |
Description: | Stop the scheduling of real-time tasks. Scheduling will resume when task_clock_start() is called. Time-shared tasks can continue. The current task can also continue, unless it's a real-time task and it yields. |
Comments: | Call task_clock_stop() when you want to take time out
from scheduling real-time tasks. For instance, you want to temporarily
suspend a game or simulation for a period of time.
The time() function is not affected by this. |
See Also: | task_clock_start, task_schedule, task_yield, task_suspend |
Syntax: | a2 = task_create(i1, s) |
Description: | Create a new task. i1 is the routine id of a user-defined Euphoria procedure. s is the list of arguments that will be passed to this procedure when the task starts executing. The result, a2, is a task identifier, created by the system. It can be used to identify this task to the other Euphoria multitasking routines. |
Comments: | task_create() creates a new task,
but does not start it executing.
Each task has its own set of private variables and its own call stack. Global and local variables are shared between all tasks. If a run-time error is detected, the traceback will include information on all tasks, with the offending task listed first. Many tasks can be created that all run the same procedure, possibly with different parameters. A task cannot be based on a function, since there would be no way of using the function result. Each task id is unique. task_create() never returns the same task id as it did before. Task id's are integer-valued atoms and can be as large as the largest integer-valued atom (15 digits). |
Example: | |
mytask = task_create(routine_id("myproc"), {5, 9, "ABC"}) | |
See Also: | task_schedule, task_yield, task_suspend, task_self |
Syntax: | s = task_list() |
Description: | Get a sequence containing the task id's for all active or suspended tasks. |
Comments: | This function lets you find out which tasks currently exist. Tasks that have terminated naturally, or have been killed are not included. You can pass a task id to task_status() to find out more about a particular task. |
Example: | |
sequence tasks tasks = task_list() for i = 1 to length(tasks) do if task_status(tasks[i]) > 0 then printf(1, "task %d is active\n", tasks[i]) end if end for | |
See Also: | task_status, task_create, task_schedule, task_yield, task_suspend |
Syntax: | task_schedule(a, x) |
Description: | Schedule task a to run using scheduling parameter x. a must be a task identifier returned by task_create(). If x is a positive atom, then x tells the task scheduler how many times it should run time-shared task a in one burst before it considers running other tasks. If x is a sequence, it must be a 2-element sequence {min, max}, both values greater than or equal to 0, where min and max indicate the minimum and maximum times, in seconds, to wait before running real-time task a. min and max also set the time interval for subsequent runs of task a, unless overridden by another call to task_schedule() or task_suspend(). |
Comments: | The task scheduler, which is built-in to the Euphoria run-time system, will use the
scheduling parameter x as a guide when scheduling this task. It may not
always be possible to achieve the desired number of consecutive runs,
or the desired time frame. For instance, a task might take so long before
yielding control, that another task misses it's desired time window.
Real-time tasks have a higher priority. Time-shared tasks are run when no real-time task is ready to execute. A task can switch back and forth between real-time and time-shared. It all depends on the last call to task_schedule() for that task. The scheduler never runs a real-time task before the start of its time frame (min value), and it tries to avoid missing the task's deadline (max value). For precise timing, you can specify the same value for min and max. However, by specifying a range of times, you give the scheduler some flexibility. This allows it to schedule tasks more efficiently, and avoid non-productive delays. When the scheduler must delay, it calls sleep(), unless the required delay is very short. sleep() lets the operating system run other programs. The min and max values can be fractional. If the min value is smaller than the resolution of the scheduler's clock (currently 0.01 seconds on Windows and Linux/FreeBSD, and 0.55 seconds on DOS unless tick_rate() is called) then accurate time scheduling cannot be performed, but the scheduler will try to run the task several times in a row to approximate what is desired. For example, if you ask for a min time of 0.002 seconds, then the scheduler will try to run your task .01/.002 = 5 times in a row before waiting for the clock to "click" ahead by .01. During the next 0.01 seconds it will run your task (up to) another 5 times etc. provided your task can be completed 5 times in one clock period. At program start-up there is a single task running. Its task id is 0, and initially it's a time-shared task allowed 1 run per task_yield(). No other task can run until task 0 executes a task_yield(). If task 0 (top-level) runs off the end of the main file, the whole program terminates, regardless of what other tasks may still be active. If the scheduler finds that no task is active, i.e. no task will ever run again (not even task 0), it terminates the program with a 0 exit code code, similar to abort(0). |
Example: | |
-- Task t1 will be executed up to 10 times in a row before -- other time-shared tasks are given control. If a real-time -- task needs control, t1 will lose control to the real-time task. task_schedule(t1, 10) -- Task t2 will be scheduled to run some time between 4 and 5 seconds -- from now. Barring any rescheduling of t2, it will continue to -- execute every 4 to 5 seconds thereafter. task_schedule(t2, {4, 5}) | |
See Also: | task_create, task_yield, task_suspend, task_suspend |
Syntax: | a = task_self() |
Description: | Return the task id of the current task. |
Comments: | This value may be needed, if a task wants to schedule, kill or suspend itself. |
Example: | |
-- schedule self task_schedule(task_self(), {5.9, 6.0}) | |
See Also: | task_create, task_schedule, task_yield, task_suspend |
Syntax: | i2 = task_status(a) |
Description: | Return the status of a task. Status values are 1 (active), 0 (suspended), and -1 (task does not exist) |
Comments: | A task might want to know the status of one or more other tasks when
deciding whether to proceed with some processing.
A -1 value could indicate a task that never existed, or a task that terminated naturally or was killed. |
Example: | |
integer s s = task_status(tid) if s = 1 then puts(1, "ACTIVE\n") elsif s = 0 then puts(1, "SUSPENDED\n") else puts(1, "DOESN'T EXIST\n") end if | |
See Also: | task_list, task_create, task_schedule, task_suspend |
Syntax: | task_suspend(a) |
Description: | Suspend execution of task a. |
Comments: | This causes task a to be suspended. Task a will not be executed again unless
there is a call to task_schedule() for task a. a is a task id
returned from task_create(). Any task can suspend any other task. If a task suspends itself, the suspension will start as soon as the task calls task_yield(). |
Example: | |
-- suspend task 15 task_suspend(15) -- suspend current task task_suspend(task_self()) | |
See Also: | task_create, task_schedule, task_self, task_yield |
Syntax: | task_yield() |
Description: | Yield control to the scheduler. The scheduler can then choose another task to run, or perhaps let the current task continue running. |
Comments: | Tasks should call task_yield() periodically so other tasks will
have a chance to run. Only when task_yield() is called, is there
a way for the scheduler to take back control from a task.
This is what's known as cooperative multitasking. A task can have calls to task_yield() in many different places in it's code, and at any depth of subroutine call. The scheduler will use the current value of {min, max} or the current number of consecutive runs remaining, in determining when to return to the current task. When control returns, execution will continue with the statement that follows task_yield(). The call-stack and all private variables will remain as they were when task_yield() was called. Global and local variables may have changed, due to the execution of other tasks. Tasks should try to call task_yield() often enough to avoid causing real-time tasks to miss their time window, and to avoid blocking time-shared tasks for an excessive period of time. On the other hand, there is a bit of overhead in calling task_yield(), and this overhead is slightly larger when an actual switch to a different task takes place. A task should avoid calling task_yield() when it is in the middle of a delicate operation that requires exclusive access to some data. Otherwise a race-condition could occur, where one task might interfere with an operation being carried out by another task. In some cases a task might need to mark some data as "locked" or "unlocked" in order to prevent this possibility. With cooperative multitasking, these concurrency issues are much less of a problem than with the preemptive multitasking that other languages support. |
Example: | |
-- From Language war game. -- This small task deducts life support energy from either the -- large Euphoria ship or the small shuttle. -- It seems to run "forever" in an infinite loop, -- but it's actually a real-time task that is called -- every 1.7 to 1.8 seconds throughout the game. -- It deducts either 3 units or 13 units of life support energy each time. global procedure task_life() -- independent task: subtract life support energy while TRUE do if shuttle then p_energy(-3) else p_energy(-13) end if task_yield() end while end procedure | |
See Also: | task_create, task_schedule, task_suspend task_suspend |
Syntax: | include graphics.e text_color(i) |
Description: | Set the foreground text color. Add 16 to get blinking text in some modes. See graphics.e for a list of possible colors. |
Comments: | Text that you print after calling text_color() will have the
desired color.
When your program terminates, the last color that you selected and actually printed on the screen will remain in effect. Thus you may have to print something, maybe just '\n', in WHITE to restore white text, especially if you are at the bottom line of the screen, ready to scroll up. |
Example: | |
text_color(BRIGHT_BLUE) | |
See Also: | bk_color |
Platform: | DOS32, WIN32 |
Syntax: | include graphics.e i2 = text_rows(i1) |
Description: | Set the number of lines on a text-mode screen to i1 if possible. i2 will be set to the actual new number of lines. |
Comments: | Values of 25, 28, 43 and 50 lines are supported by most video cards. |
See Also: | graphics_mode |
Platform: | DOS32 |
Syntax: | include machine.e tick_rate(a) |
Description: | Specify the number of clock-tick interrupts per second. This determines the precision of the time() library routine. It also affects the sampling rate for time profiling. |
Comments: | tick_rate() is ignored on
WIN32 and
Linux/FreeBSD.
The time resolution on WIN32 is always 100 ticks/second.
On a PC the clock-tick interrupt normally occurs at 18.2 interrupts per second. tick_rate() lets you increase that rate, but not decrease it. tick_rate(0) will restore the rate to the normal 18.2 rate. Euphoria will also restore the rate automatically when it exits, even when it finds an error in your program. If a program runs in a DOS window with a tick rate other than 18.2, the time() function will not advance unless the window is the active window. With a tick rate other than 18.2, the time() function on DOS takes about 1/100 the usual time that it needs to execute. On Windows and FreeBSD, time() normally executes very quickly. While ex.exe is running, the system will maintain the correct time of day. However if ex.exe should crash (e.g. you see a "CauseWay..." error) while the tick rate is high, you (or your user) may need to reboot the machine to restore the proper rate. If you don't, the system time may advance too quickly. This problem does not occur on Windows 95/98/NT, only on DOS or Windows 3.1. You will always get back the correct time of day from the battery-operated clock in your system when you boot up again. |
Example: | |
tick_rate(100) -- time() will now advance in steps of .01 seconds -- instead of the usual .055 seconds | |
See Also: | time, time profiling |
Syntax: | a = time() |
Description: | Return the number of seconds since some fixed point in the past. |
Comments: | Take the difference between two readings of time(), to
measure, for example, how long a section of code takes to
execute.
The resolution with DOS32 is normally about 0.05 seconds. On WIN32 and Linux/FreeBSD it's about 0.01 seconds. Under DOS32 you can improve the resolution by calling tick_rate(). Under DOS32 the period of time that you can normally measure is limited to 24 hours. After that, the value returned by time() will reset and start over. If however, you have called tick_rate(), and clock ticks are happening at a rate that is higher than the usual 18.2/sec, time() will continue much longer, since in that case, Euphoria handles the clock-tick interrupt directly, and accumulates the ticks in a larger, 32-bit variable. DOS emulation under Windows XP is not perfect. When you do time profiling, (with profile_time) the time() function might be off by several percent. This problem does not occur on Windows ME/98/95. |
Example: | |
constant ITERATIONS = 1000000 integer p atom t0, loop_overhead t0 = time() for i = 1 to ITERATIONS do -- time an empty loop end for loop_overhead = time() - t0 t0 = time() for i = 1 to ITERATIONS do p = power(2, 20) end for ? (time() - t0 - loop_overhead)/ITERATIONS -- calculates time (in seconds) for one call to power | |
See Also: | date, tick_rate |
Syntax: | with trace trace(i) |
Description: | If i is 1 or 2, turn on full-screen interactive statement tracing/debugging.
If i is 3, turn on tracing of statements to a file called ctrace.out.
If i is 0, turn off tracing. When i is 1 a color display appears.
When i is 2 a monochrome trace display appears.
Tracing can only occur in routines that were
compiled "with trace", and trace() has no effect unless it is
executed in a "with trace" section of your program.
See Part I - 3.1 Debugging for a full discussion of tracing / debugging. |
Comments: | Use trace(2) if the color display is hard to view on your system.
All forms of trace() are supported by the Interpreter. Only trace(3) is supported by the Euphoria To C Translator. |
Example: | |
if x < 0 then -- ok, here's the case I want to debug... trace(1) -- etc. ... end if | |
See Also: | profile, debugging and profiling |